/* -------------------------------------------------- Bootstrap Overrides -------------------------------------------------- */ $grid-breakpoints: ( xs: 0, sm: 576px, md: 768px, lg: 992px, xl: 1200px, xxl: 1400px, xxxl: 1920px ) !default; $container-max-widths: ( sm: 540px, md: 720px, lg: 960px, xl: 1140px, xxl: 1320px, xxxl: 1840px ) !default; @import "_bootstrap"; // ── Holofoil ────────────────────────────────────────────────────────────── //@import "_holofoil-integration"; // also pulls in _card.scss /* -------------------------------------------------- Root Variables -------------------------------------------------- */ :root { --total: 11; --radius: 40px; } html { scroll-behavior: smooth; } /* -------------------------------------------------- View Transitions -------------------------------------------------- */ @view-transition { navigation: auto; } ::view-transition-group(card-image) { animation-duration: 300ms; animation-timing-function: cubic-bezier(0.4, 0, 0.2, 1); } ::view-transition-old(card-image), ::view-transition-new(card-image) { width: 100%; height: 100%; object-fit: cover; } /* Optional: fade everything else */ ::view-transition-old(root), ::view-transition-new(root) { animation-duration: 150ms; } /* -------------------------------------------------- Layout -------------------------------------------------- */ .wrapper { display: flex; flex-direction: column; min-height: 100dvh !important; } .main { flex: 1; } .footer { margin-top: auto; } /* -------------------------------------------------- Energy Wheel -------------------------------------------------- */ .energy-wheel { position: relative; width: calc(var(--radius) * 2); height: calc(var(--radius) * 2); margin: 5px 0 10px; } .energy-wheel-item { position: absolute; width: 25px; height: 25px; top: 50%; left: 50%; --angle: calc(360deg / var(--total) * var(--i)); transform: rotate(var(--angle)) translateX(var(--radius)) rotate(calc(-1 * var(--angle))); &:first-of-type { z-index: 100; } } /* -------------------------------------------------- Navbar & Icons -------------------------------------------------- */ .navbar { background-color: var(--bs-danger) !important; } .sticky-top { position: sticky; top: 0; z-index: 1000; } .nav-icon { width: 1.85rem; height: 1.85rem; > svg { fill: hsla(210, 11%, 15%, 0.5); stroke: hsla(210, 11%, 15%, 0.5); &:hover { fill: hsla(210, 11%, 15%, 1); } } } /* -------------------------------------------------- Typography -------------------------------------------------- */ .copy-small { font-size: 0.75rem; opacity: 0.87; @media (min-width: 768px) { font-size: 0.85rem; } @media (min-width: 1400px) { font-size: 1rem; } } /* -------------------------------------------------- Modal & Cards -------------------------------------------------- */ .modal-xl { @media (min-width: 768px) { max-width: 95vw; } @media (min-width: 1400px) { max-width: 85vw; } @media (min-width: 1921px) { max-width: 75vw; } } .image-grow { transition: box-shadow 350ms ease, transform 350ms ease; box-shadow: 0 2px 4px rgba(0, 0, 0, 0.24); &:hover, &:focus { box-shadow: 0 8px 10px rgba(0, 0, 0, 0.2); transform: translateY(-0.9rem) scale(1.02); } } .card-modal { background-color: rgba(1, 11, 18, 0.8); cursor: default; } .pokedex-page { position: relative; top: 50px; z-index: 99; @media (min-width: 768px) { top: 100px !important; } } .modal-nav-btn { position: fixed; top: 50%; transform: translateY(-50%); z-index: 1060; /* above modal backdrop (1050) */ background: rgba(255,255,255,0.1); border: 1px solid rgba(255,255,255,0.2); color: white; border-radius: 50%; width: 48px; height: 48px; display: flex; align-items: center; justify-content: center; cursor: pointer; transition: background 0.2s; backdrop-filter: blur(4px); } .modal-nav-btn:hover { background: rgba(255,255,255,0.25); } .modal-nav-btn.d-none { display: none !important; } .modal-nav-prev { left: 12px; } .modal-nav-next { right: 12px; } @media (max-width: 768px) { .modal-nav-btn { display: none !important; } /* use swipe on mobile */ } /* -------------------------------------------------- Navigation Tabs & Tier Colors -------------------------------------------------- */ .nav-link { font-weight: 600; color: rgba(255, 255, 255, 0.67); transition: margin-top 0.2s cubic-bezier(0.5, 0, 0.3, 1), padding-top 0.2s cubic-bezier(0.5, 0, 0.3, 1), padding-bottom 0.2s cubic-bezier(0.5, 0, 0.3, 1); &:hover, &:focus { color: rgba(0, 0, 0, 0.87); } } .nav-tabs { .nav-link.active, .nav-item.show .nav-link { color: rgba(0, 0, 0, 0.94); } .nav-link:hover, .nav-link:focus { border-color: transparent; } } $tiers: ( nm: rgba(156, 204, 102, 1), lp: rgba(211, 225, 86, 1), mp: rgba(255, 238, 87, 1), hp: rgba(255, 201, 41, 1), dmg: rgba(255, 167, 36, 1), vendor: hsl(262, 47%, 55%) ); @each $name, $color in $tiers { .nav-link.#{$name} { border-bottom: 3px solid $color; &:hover, &:focus { background-color: rgba($color, 0.67); } &.active { background-color: $color; border-bottom-color: $color; @if $name == vendor { color: rgba(255, 255, 255, 0.87); } } } /* price-row alert left borders */ .nav-#{$name} div.alert { border-left: 3px solid $color; } } /* -------------------------------------------------- Misc UI -------------------------------------------------- */ .dark-callout { @media (min-width: 768px) { background-color: rgba(44, 48, 59, 1); } } .price-area { max-height: 75px; } .card-image { aspect-ratio: 23 / 32; object-fit: cover; z-index: 1; cursor: pointer; } /* Icon Sizes */ .small-icon svg { max-height: 16px; width: 100%; margin-top: -0.25rem; } .medium-icon svg { max-height: 32px; width: 100%; margin-left: -0.25rem; } /* Masked Image */ .masked-image { z-index: 1000; opacity: 1; filter: brightness(0); } /* Decorative Background */ .starburst, .whos-that-pokemon { mix-blend-mode: lighten; opacity: 0.1; object-fit: cover; } .whos-that-pokemon { aspect-ratio: 1 / 1; } /* SVG Generic Sizes */ .energy-icon svg, .rarity-icon-large svg, .set-icon svg, .edition-icon svg { width: 2rem; z-index: 999; @media (min-width: 1024px) { width: 2.5rem; } } .rarity-icon-large svg, .set-icon svg { margin-bottom: -0.25rem; } .filter-icon svg, .search-button { width: 2rem; fill: rgba(255,255,255,0.87); stroke: rgba(255,255,255,0.87); } /* Form states */ .form-check-input:checked { background-color: var(--bs-success); border-color: var(--bs-success-border-subtle); } .form-check-input:focus { border-color: var(--bs-success); box-shadow: 0 0 0 0.25rem rgba(var(--bs-success-rgb), 0.25); } /* Back to Top */ #btn-back-to-top { position: fixed; bottom: 5vh; right: 5vw; display: none; z-index: 2; } .top-icon svg { width: 2rem; height: 2rem; fill: var(--bs-info-bg-subtle); stroke: var(--bs-info-bg-subtle); } #btn-back-to-top:hover .top-icon svg { fill: var(--bs-info-border-subtle); stroke: var(--bs-info-border-subtle); } .shadow-filter { filter: drop-shadow(0 5px 5px rgba(0, 0, 0, 0.3)) drop-shadow(0 4px 6px rgba(0, 0, 0, 0.2)); } .tooltip.volatility-popover .tooltip-inner { background: #1d1f21; color: #e9ecef; padding: 0.9rem 1rem; border-radius: 0.6rem; text-align: left; max-width: 260px; border: 1px solid rgba(255, 255, 255, 0.08); } .tooltip.volatility-popover .tooltip-arrow::before { border-top-color: #1d1f21 !important; } /* -------------------------------------------------- Pricing -------------------------------------------------- */ .price-row { position: relative; z-index: 2; margin-top: -1.25rem; border-radius: 0.33rem; background: linear-gradient( 90deg, map-get($tiers, nm) 21%, map-get($tiers, lp) 42%, map-get($tiers, mp) 63%, map-get($tiers, hp) 74%, map-get($tiers, dmg) 85% ); } .inventory-button { width: 40px; height: 40px; margin-bottom: -2rem; margin-right: -0.25rem; border-radius: 0.33rem; background-color: hsl(262, 47%, 55%); color: #fff; } .inventory-label { width: 100%; height: 100%; font-size: 1rem; font-weight: 700; } .fs-7 { font-size: 0.9rem !important; } /* Price Label */ .price-label { font-size: 0.69rem; font-weight: 600; color: rgba(0, 0, 0, 0.87); background-color: hsl(88, 50%, 60%); border-radius: 0.33rem 0 0 0.33rem; box-shadow: 0 5px 10px rgba(0, 0, 0, 0.35); @media (min-width: 768px) { font-size: 0.72rem; } @media (min-width: 996px) { font-size: 0.75rem; } @media (min-width: 1200px) { font-size: 0.8rem; } @media (min-width: 1600px) { font-size: 1rem; } &:nth-of-type(2) { background-color: hsl(66, 70%, 61%); } &:nth-of-type(3) { background-color: hsl(54, 100%, 67%); } &:nth-of-type(4) { background-color: hsl(45, 100%, 58%); } &:last-of-type { background-color: hsl(36, 100%, 57%); border-radius: 0.33rem; } } /* -------------------------------------------------- Search -------------------------------------------------- */ @media (max-width: 768px) { .search-box, .search-button { min-height: 48px; } } ::placeholder { color: rgba(255, 255, 255, 0.7) !important; opacity: 1 !important; font-size: 1rem; line-height: 2rem; } /* Sticky Search Bar */ .search-bar { position: fixed; bottom: 0; width: 100%; height: 48px; z-index: 1000; transform: rotate(180deg); @media (min-width: 768px) { position: sticky; top: 0; min-width: 45vw; max-width: 45vw; transform: rotate(0); } } .facet-list { max-height: 185px; overflow-y: auto; } /* -------------------------------------------------- Circles -------------------------------------------------- */ %circle-base { width: 1rem; height: 1rem; border-radius: 50%; position: absolute; margin: 0 auto; border: 1px solid hsl(210, 11%, 15%); mask: linear-gradient(135deg, #fffc 40%, #fff, #fffc 60%) 100% 100% / 240% 240%; transition: 0.4s; transform: perspective(400px) rotate3d(var(--i, 1, -1), 0, var(--a, 8deg)); } .redCircle { @extend %circle-base; background: radial-gradient(circle at top left, hsl(0, 100%, 56%), hsl(0, 79%, 45%)); } .yellowCircle { @extend %circle-base; background: radial-gradient(circle at top left, hsl(61, 100%, 50%), hsl(61, 100%, 40%)); } .greenCircle { @extend %circle-base; background: radial-gradient(circle at top left, hsl(149, 100%, 40%), hsl(149, 100%, 30%)); } .redCircle:hover, .yellowCircle:hover, .greenCircle:hover, .blueCircle:hover { --i: -1, 1; mask-position: 0 0; } /* -------------------------------------------------- Buttons -------------------------------------------------- */ .btn-warning > span, .btn-warning > svg.nav-icon { fill: var(--bs-warning-border-subtle); stroke: var(--bs-warning-border-subtle); color: var(--bs-warning-border-subtle); } .btn.btn-warning:hover > span, .btn.btn-warning:hover > svg.nav-icon { fill: var(--bs-warning-bg-subtle); stroke: var(--bs-warning-bg-subtle); } .btn-outline-success svg.nav-icon { fill: var(--bs-success); stroke: var(--bs-success); } .btn.btn-outline-success:hover, .btn.btn-outline-success:hover svg.nav-icon { fill: var(--bs-success-border-subtle); stroke: var(--bs-success-border-subtle); } /* -------------------------------------------------- Card Modal Navigation -------------------------------------------------- */ .card-nav-prev, .card-nav-next { transition: all 0.2s ease-in-out; display: inline-flex; align-items: center; justify-content: center; min-width: 36px; padding: 0.375rem 0.5rem; will-change: opacity; &:hover:not(:disabled) { background-color: var(--bs-secondary); border-color: var(--bs-secondary); color: white; transform: translateY(-1px); box-shadow: 0 2px 4px rgba(0,0,0,0.1); } &:active:not(:disabled) { transform: translateY(0); } &:disabled { cursor: not-allowed; } } @media (max-width: 768px) { .card-nav-prev, .card-nav-next { min-width: 40px; padding: 0.5rem; } } /* -------------------------------------------------- Swipe Animation -------------------------------------------------- */ /* Smooth the hero image morph */ ::view-transition-group(card-hero) { animation-duration: 350ms; animation-timing-function: cubic-bezier(0.4, 0, 0.2, 1); } /* Fade the old image out quickly so it doesn't ghost */ ::view-transition-old(card-hero) { display: none; } /* Fade the new image in after it's in position */ ::view-transition-new(card-hero) { animation-duration: 350ms; animation-timing-function: cubic-bezier(0.4, 0, 0.2, 1); } /* Suppress the default full-page crossfade so only the card morphs */ ::view-transition-old(root), ::view-transition-new(root) { animation: none; } /* Sliding out (old content) */ ::view-transition-old(.modal-content) { animation: slide-out 200ms ease-in forwards; } /* Sliding in (new content) */ ::view-transition-new(.modal-content) { animation: slide-in 200ms ease-out forwards; } /* Direction-aware — set via dataset.navDirection */ #cardModal[data-nav-direction="next"]::view-transition-old(.modal-content) { animation: slide-out-left 200ms ease-in forwards; } #cardModal[data-nav-direction="next"]::view-transition-new(.modal-content) { animation: slide-in-right 200ms ease-out forwards; } #cardModal[data-nav-direction="prev"]::view-transition-old(.modal-content) { animation: slide-out-right 200ms ease-in forwards; } #cardModal[data-nav-direction="prev"]::view-transition-new(.modal-content) { animation: slide-in-left 200ms ease-out forwards; } /* The silhouette fades out while the colour image blooms in */ ::view-transition-old(pokemon-reveal) { animation: 300ms ease-in both fade-to-white; } ::view-transition-new(pokemon-reveal) { animation: 500ms ease-out both bloom-in; } @keyframes fade-to-white { to { opacity: 0; filter: brightness(3); } } @keyframes bloom-in { from { opacity: 0; filter: brightness(2) saturate(0); transform: scale(0.95); } to { opacity: 1; filter: brightness(1) saturate(1); transform: scale(1); } } /* -------------------------------------------------- Input Fix (Safari) input[type="search"]::-webkit-search-cancel-button { -webkit-appearance: none; height: 1rem; width: 1rem; display: block; background-repeat: no-repeat; background-size: 1rem; background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAB4AAAAeCAYAAAA7MK6iAAAAn0lEQVR42u3UMQrDMBBEUZ9WfQqDmm22EaTyjRMHAlM5K+Y7lb0wnUZPIKHlnutOa+25Z4D++MRBX98MD1V/trSppLKHqj9TTBWKcoUqffbUcbBBEhTjBOV4ja4l4OIAZThEOV6jHO8ARXD+gPPvKMABinGOrnu6gTNUawrcQKNCAQ7QeTxORzle3+sDfjJpPCqhJh7GixZq4rHcc9l5A9qZ+WeBhgEuAAAAAElFTkSuQmCC); } -------------------------------------------------- */