/* ============================================================
   GameDropz™ — Mockup match: dark cinematic + violet glow
   ============================================================ */
:root {
    /* Dark theme — default per mockup */
    --bg: #07050F;
    --bg-elevated: #0E0B1C;
    --bg-card: #110D22;
    --bg-card-hover: #1A1530;
    --bg-input: #15112A;
    --sidebar-bg: #07050F;
    --topbar-bg: rgba(7, 5, 15, 0.85);

    --text: #FFFFFF;
    --text-muted: #8E8AA8;
    --text-soft: #524F6E;
    --text-dim: #3A374F;

    --border: rgba(124, 96, 215, 0.12);
    --border-strong: rgba(124, 96, 215, 0.28);
    --divider: rgba(255, 255, 255, 0.04);

    --accent: #9A6CFF;        /* main violet */
    --accent-bright: #B891FF;  /* hover / highlight */
    --accent-soft: #6B49C7;    /* secondary */
    --accent-glow: rgba(154, 108, 255, 0.55);
    --accent-glow-strong: rgba(154, 108, 255, 0.85);

    --success: #2AE07A;
    --danger: #FF5C7A;

    --radius-sm: 6px;
    --radius: 10px;
    --radius-lg: 16px;
    --radius-xl: 22px;
    --radius-pill: 999px;

    --ease: cubic-bezier(0.32, 0.72, 0.32, 1);
    --ease-spring: cubic-bezier(0.34, 1.56, 0.64, 1);

    --sidebar-w: 240px;
}

[data-theme="light"] {
    --bg: #F4F2FA;
    --bg-elevated: #FFFFFF;
    --bg-card: #FFFFFF;
    --bg-card-hover: #F0EDF8;
    --bg-input: #FFFFFF;
    --sidebar-bg: #FFFFFF;
    --topbar-bg: rgba(244, 242, 250, 0.85);
    --text: #1A1330;
    --text-muted: #5C5878;
    --text-soft: #9290A8;
    --text-dim: #C8C5DC;
    --border: rgba(124, 96, 215, 0.16);
    --border-strong: rgba(124, 96, 215, 0.32);
    --divider: rgba(0, 0, 0, 0.05);
    --accent: #7D33FF;
    --accent-bright: #9A6CFF;
}

/* Hybrid mode — slightly muted light main content with dark-mode sidebar.
   :root variables are derived from the LIGHT palette but with each surface
   tone dialled DOWN ~13% in lightness so the canvas feels softer and a bit
   more cinematic than pure light mode (less "office app", more "showroom").
   Hue is preserved — colours stay in the same lavender family, just deeper.
   The .sidebar scope below still reassigns its OWN custom properties to the
   DARK palette so the sidebar reads as a dedicated "command bar". */
[data-theme="hybrid"] {
    --bg: #DDD7E8;                          /* was #F4F2FA — ~13% darker lavender */
    --bg-elevated: #EAE6F1;                 /* was #FFFFFF — slightly tinted off-white */
    --bg-card: #EAE6F1;                     /* was #FFFFFF */
    --bg-card-hover: #DBD6E4;               /* was #F0EDF8 */
    --bg-input: #EAE6F1;                    /* was #FFFFFF */
    --sidebar-bg: #07050F;                  /* dark — overrides light default */
    --topbar-bg: rgba(221, 215, 232, 0.85); /* matches new bg */
    --text: #1A1330;
    --text-muted: #5C5878;
    --text-soft: #9290A8;
    --text-dim: #B8B4CC;                    /* bumped slightly for the darker bg */
    --border: rgba(124, 96, 215, 0.18);     /* +0.02 alpha to stay visible */
    --border-strong: rgba(124, 96, 215, 0.35);
    --divider: rgba(0, 0, 0, 0.07);
    --accent: #7D33FF;
    --accent-bright: #9A6CFF;
}

/* Re-darken everything INSIDE the sidebar for hybrid mode. Scoping vars on
   .sidebar means every descendant (nav-items, brand, icons, count badges)
   reads the dark palette without per-component selectors. */
[data-theme="hybrid"] .sidebar {
    --bg: #07050F;
    --bg-elevated: #0E0B1C;
    --bg-card: #110D22;
    --bg-card-hover: #1A1530;
    --bg-input: #15112A;
    --sidebar-bg: #07050F;
    --text: #FFFFFF;
    --text-muted: #8E8AA8;
    --text-soft: #524F6E;
    --text-dim: #3A374F;
    --border: rgba(124, 96, 215, 0.12);
    --border-strong: rgba(124, 96, 215, 0.28);
    --divider: rgba(255, 255, 255, 0.04);
    --accent: #9A6CFF;
    --accent-bright: #B891FF;
}

/* Same scoping trick as the sidebar above — but for the calendar widgets and
   the modal countdown. In hybrid we want these to read as DARK panels sitting
   on the light canvas (a "calendarium" feel). Re-assigning the dark palette
   on the wrapper means every descendant (day-cells, release-cards, weekdays,
   countdown-value, etc.) inherits the dark colours without per-component
   selectors. .calendar-month covers month view, .mini-month each year-view
   tile, .modal-countdown the countdown widget in the game modal. */
[data-theme="hybrid"] .calendar-month,
[data-theme="hybrid"] .mini-month,
[data-theme="hybrid"] .modal-countdown {
    --bg: #07050F;
    --bg-elevated: #0E0B1C;
    --bg-card: #110D22;
    --bg-card-hover: #1A1530;
    --bg-input: #15112A;
    --text: #FFFFFF;
    --text-muted: #8E8AA8;
    --text-soft: #524F6E;
    --text-dim: #3A374F;
    --border: rgba(124, 96, 215, 0.12);
    --border-strong: rgba(124, 96, 215, 0.28);
    --divider: rgba(255, 255, 255, 0.04);
    --accent: #9A6CFF;
    --accent-bright: #B891FF;
}

/* Background glow + hex pattern inherit the LIGHT palette in hybrid (because
   they're outside the sidebar — they live on body). Re-apply light overrides
   so hybrid feels visually identical to light for the main canvas. */
[data-theme="hybrid"] body::before {
    background:
        radial-gradient(ellipse 70% 60% at 100% 100%, rgba(125, 51, 255, 0.16), transparent 70%);
}
[data-theme="hybrid"] body::after {
    opacity: 0.35;
}

/* Hybrid mode overscroll fix — body keeps its light --bg, but <html> bg
   gets the dark sidebar colour so iOS Safari rubber-band bounce reads as
   "dark frame" instead of flashing white above/below the page. data-theme
   attribute lives on <html>, so this selector targets <html> directly. */
[data-theme="hybrid"] {
    background-color: #07050F;
}

* { box-sizing: border-box; margin: 0; padding: 0; }

html { height: 100%; }
/* body intentionally does NOT have height: 100% — it would pin body at
   exactly 100vh and its bg would only paint the first viewport. .app
   has min-height: 100vh and grows with content (cards, calendar, etc.),
   so anything past 100vh would expose html's bg below body. In hybrid
   that's a hard light→dark stripe mid-scroll because html is dark (for
   iOS overscroll) and body is light. With body height auto + min-height:
   100vh (set in body block below), body grows with .app and its bg
   paints the full scroll area. */

/* Give <html> an explicit background — iOS Safari overscroll (rubber-band
   bounce when you pull the page past its top/bottom) shows the html element's
   bg, NOT the body bg. Without this, hybrid mode would flash the light --bg
   into the rubber-band zone, which looks disconnected from the dark sidebar. */
html {
    background-color: var(--bg);
}

body {
    font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', sans-serif;
    background-color: var(--bg);
    color: var(--text);
    min-height: 100vh;
    -webkit-font-smoothing: antialiased;
    -moz-osx-font-smoothing: grayscale;
    font-feature-settings: 'cv11', 'ss01';
    letter-spacing: -0.011em;
    overflow-x: hidden;
    position: relative;
}

/* Subtle violet glow drifting in from the bottom-right corner */
body::before {
    content: '';
    position: fixed;
    inset: 0;
    z-index: 0;
    pointer-events: none;
    background:
        radial-gradient(ellipse 70% 60% at 100% 100%, rgba(154, 108, 255, 0.22), transparent 70%),
        radial-gradient(ellipse 50% 50% at 100% 100%, rgba(184, 145, 255, 0.10), transparent 50%);
}

[data-theme="light"] body::before {
    background:
        radial-gradient(ellipse 70% 60% at 100% 100%, rgba(125, 51, 255, 0.16), transparent 70%);
}

/* Subtle high-tech hex mesh overlay — most visible in upper area, fades out.
   Dark mode opacity tuned to be only just-noticeable so it stays decorative
   without competing with the spotlight art / card grids underneath. */
body::after {
    content: '';
    position: fixed;
    inset: 0;
    z-index: 0;
    pointer-events: none;
    background-image: url('hex.svg');
    background-repeat: repeat;
    background-size: 60px 104px;
    opacity: 0.22;
    -webkit-mask-image: radial-gradient(ellipse 90% 70% at 30% 15%, rgba(0,0,0,0.9) 0%, rgba(0,0,0,0.4) 45%, transparent 85%);
            mask-image: radial-gradient(ellipse 90% 70% at 30% 15%, rgba(0,0,0,0.9) 0%, rgba(0,0,0,0.4) 45%, transparent 85%);
}

[data-theme="light"] body::after {
    opacity: 0.35;
}

.app { position: relative; z-index: 1; }

.hidden { display: none !important; }

/* ============================================================
   App layout — sidebar + main
   ============================================================ */
.app {
    display: grid;
    grid-template-columns: var(--sidebar-w) 1fr;
    min-height: 100vh;
    position: relative;
}

/* ============================================================
   Sidebar
   ============================================================ */
.sidebar {
    background: var(--sidebar-bg);
    border-right: 1px solid var(--divider);
    /* Top padding = base 28px + iOS standalone status-bar inset. When the app
       is launched from the iOS home screen, the web view stretches under the
       status bar; env(safe-area-inset-top) tells us how much to shift down
       so the brand mark isn't half-eaten by the iPad notch / clock. Falls
       back to 0 in regular browser tabs. */
    padding: calc(28px + env(safe-area-inset-top, 0px)) 18px max(20px, env(safe-area-inset-bottom, 0px));
    display: flex;
    flex-direction: column;
    gap: 28px;
    position: sticky;
    top: 0;
    height: 100vh;
    z-index: 10;
}

/* Brand */
.brand {
    display: flex;
    align-items: center;
    gap: 12px;
    text-decoration: none;
    color: inherit;
    padding: 0 4px;
}

.brand-mark {
    width: 36px;
    height: 36px;
    color: var(--accent);
    display: inline-flex;
}

.brand-mark svg { width: 100%; height: 100%; filter: drop-shadow(0 0 12px var(--accent-glow)); }

.brand-text {
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: 4px;
    line-height: 1;
}

.brand-title {
    font-size: 20px;
    font-weight: 800;
    letter-spacing: -0.03em;
    color: var(--text);
    position: relative;       /* anchor for the absolute-positioned sup */
}

.brand-title-accent { color: var(--accent); }

/* The "™" sits absolutely to the right of the title so it doesn't contribute
   to the title's layout width. Without this, .brand-sub ("RELEASE TRACKER")
   centers under the whole "GameDropz™" string and visually shifts right of
   where the eye expects it (centred under just "GameDropz"). */
.brand-title sup {
    position: absolute;
    left: 100%;
    top: 0;
    margin-left: 2px;
    font-size: 9px;
    font-weight: 600;
    vertical-align: super;
    color: var(--text-muted);
}

.brand-sub {
    font-family: 'JetBrains Mono', monospace;
    font-size: 8.5px;
    font-weight: 700;
    letter-spacing: 0.22em;
    color: var(--text-muted);
}

/* Nav */
.sidenav {
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.sidenav-item {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 8px 12px;
    border-radius: var(--radius);
    text-decoration: none;
    color: var(--text-muted);
    font-size: 14px;
    font-weight: 500;
    letter-spacing: -0.01em;
    /* Specific transitions instead of `all` — avoids animating layout
       properties that change in compact mode (width, padding) */
    transition: background-color 0.2s var(--ease), color 0.25s var(--ease);
    position: relative;
}

/* Whole-row highlight on hover/active — soft card bg behind the entire
   item. Composes with the icon-chip below: row gets a subtle wash, the
   icon-chip the strong violet pill, the label flips violet on active. */
.sidenav-item:hover {
    background: var(--bg-card);
    color: var(--text);
}

.sidenav-item.active {
    background: var(--bg-card);
    color: var(--accent);
}

/* Subtle divider between the primary nav and the "side-quest" external
   item (Happy Comet). Same hairline as the global page dividers, just
   inset a few px so it doesn't reach the item edges. */
.sidenav-divider {
    height: 1px;
    background: var(--divider);
    margin: 10px 14px;
}

/* External "play our game" link. The four hand-drawn comet icons carry
   their own visual identity (no need for the violet wash chip behind them),
   so the icon wrapper is transparent and just holds the swappable images. */
.sidenav-item-external .sidenav-icon {
    background: transparent;
    border: 0;
    overflow: visible;   /* let any slight shadow/blur extend past 22 px */
}

/* All four comet variants stack at the same spot; only one is visible at a
   time based on (theme × hover). Default state: dark-idle visible, rest off.
   Object-fit:contain keeps the circle pixel-perfect inside the chip. */
.comet-icon-wrap {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
}
.comet-icon {
    display: none;
    width: 100%;
    height: 100%;
    object-fit: contain;
    object-position: center;
}
/* === Dark theme (default) === */
.comet-dark-idle { display: block; }
.sidenav-item-external:hover .comet-dark-idle { display: none; }
.sidenav-item-external:hover .comet-dark-hover { display: block; }

/* === Light theme === */
[data-theme="light"] .comet-dark-idle,
[data-theme="light"] .comet-dark-hover { display: none !important; }
[data-theme="light"] .comet-light-idle { display: block; }
[data-theme="light"] .sidenav-item-external:hover .comet-light-idle { display: none; }
[data-theme="light"] .sidenav-item-external:hover .comet-light-hover { display: block; }

/* === Hybrid theme === sidebar is dark even though the page reads light,
   so the sidebar's comet uses the DARK icons. Scope to .sidebar to win
   over the light-theme rules above on specificity. */
[data-theme="hybrid"] .sidebar .comet-light-idle,
[data-theme="hybrid"] .sidebar .comet-light-hover { display: none !important; }
[data-theme="hybrid"] .sidebar .comet-dark-idle { display: block; }
[data-theme="hybrid"] .sidebar .sidenav-item-external:hover .comet-dark-idle { display: none; }
[data-theme="hybrid"] .sidebar .sidenav-item-external:hover .comet-dark-hover { display: block; }

.sidenav-item-external-badge {
    margin-left: auto;
    width: 14px;
    height: 14px;
    color: var(--text-soft);
    display: inline-flex;
    align-items: center;
    justify-content: center;
    transition: color 0.2s var(--ease), transform 0.2s var(--ease);
}
.sidenav-item-external-badge svg { width: 100%; height: 100%; }
.sidenav-item-external:hover .sidenav-item-external-badge {
    color: var(--accent-bright);
    transform: translate(1px, -1px);
}

/* Group wrapper holds the external link + its tagline together. Lets us hide
   both as a unit on mobile while keeping the divider rule untouched. */
.sidenav-external-group {
    display: flex;
    flex-direction: column;
}

/* Tagline under "Happy Comet". Left edge aligns with the icon (not the
   label) so the text block reads as a caption for the whole item, not as a
   continuation of the label. Gets the full sidebar width to flow naturally —
   no forced line break — which avoids awkward orphaned words. */
.sidenav-external-desc {
    margin: 6px 12px 0 12px;   /* 12 left = same as .sidenav-item padding-left */
    font-size: 11.5px;
    line-height: 1.5;
    color: var(--text-soft);
    letter-spacing: 0.005em;
    transition: color 0.25s var(--ease);
}
/* On hover of the link above, warm the tagline a notch so the whole group
   feels like one interactive object. */
.sidenav-external-group:hover .sidenav-external-desc {
    color: var(--text-muted);
}

/* Light mode override — in light mode --bg-card is pure white #FFFFFF,
   same as --sidebar-bg, so the active/hover row highlight is invisible
   (white on white). Swap to a soft violet wash so the row indicator stays
   visible and on-brand. Dark + hybrid sidebars don't need this — there
   --bg-card is one step elevated from --sidebar-bg, so contrast exists. */
[data-theme="light"] .sidenav-item:hover {
    background: rgba(125, 51, 255, 0.06);
}

[data-theme="light"] .sidenav-item.active {
    background: rgba(125, 51, 255, 0.10);
}

.sidenav-item.active::before {
    content: '';
    position: absolute;
    left: -18px;
    top: 50%;
    transform: translateY(-50%);
    width: 3px;
    height: 22px;
    background: var(--accent);
    border-radius: 0 3px 3px 0;
    box-shadow: 0 0 12px var(--accent-glow);
}

/* Icon container is a CHIP — transparent in rest, fills with accent on
   hover/active. SVG inside flips its stroke from currentColor (muted) to
   white, so the icon reads as the negative space inside a filled rounded
   square. Same pattern as email.cz inbox icon. */
.sidenav-icon {
    width: 22px;
    height: 22px;
    padding: 4px;
    box-sizing: content-box;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    flex-shrink: 0;
    border-radius: 8px;
    background: transparent;
    transition: background-color 0.3s var(--ease);
}

.sidenav-icon svg {
    width: 100%;
    height: 100%;
    transition: stroke 0.3s var(--ease);
}

.sidenav-item:hover .sidenav-icon,
.sidenav-item.active .sidenav-icon {
    background: var(--accent);
}

.sidenav-item:hover .sidenav-icon svg,
.sidenav-item.active .sidenav-icon svg {
    stroke: #fff;
}

/* ============================================================
   Per-icon hover animations — each sidebar item plays a tiny
   semantic gesture on hover (controller wobble, clock spin,
   text type-in, calendar pegs jump, bookmark drop). Pattern
   inspired by email.cz / Lordicon. Pure CSS — no JS, no Lottie.

   We trigger by [data-nav="…"] attribute on .sidenav-item so we
   don't have to add classes to each SVG. transform-box defaults
   to `view-box` for SVG children, which means transform-origin
   coords align with the 24×24 SVG viewBox — used for clock spin.
   For self-contained elements (news lines, calendar pegs, bookmark
   path) we switch to `fill-box` so the origin is the element's
   own bounding box.

   :focus-visible mirrors :hover for keyboard users. Respect
   prefers-reduced-motion — disable animations entirely when set.
   ============================================================ */
/* Per-icon hover animations — gated by (hover: hover) so they ONLY fire
   on devices with a real mouse pointer that can hover. Two reasons:
   1) On touch devices (iPad/phone) :hover is "sticky" after a tap, so the
      animation would play on every navigation tap and feel laggy (mid-range
      tablet GPUs can drop frames during the SVG transforms while the page
      transition runs at the same time).
   2) On desktop, dropping :focus-visible kills the side-effect where a mouse
      click fires the animation — clicking a link briefly focuses it; with
      :focus-visible in the selector list, the animation would re-trigger on
      click, which is what the user asked to remove. Keyboard tab navigation
      loses the animation, but that's a fair trade for the mouse fix. */
@media (hover: hover) and (prefers-reduced-motion: no-preference) {

    /* Releases — controller wobble (rotates the whole SVG). */
    .sidenav-item[data-nav="releases"]:hover .sidenav-icon svg {
        animation: nav-anim-controller 0.6s var(--ease);
        transform-origin: center;
    }

    /* Upcoming — clock hands spin around the clock center (12,12). */
    .sidenav-item[data-nav="upcoming"]:hover .sidenav-icon svg polyline {
        animation: nav-anim-clock 0.7s var(--ease);
        transform-origin: 12px 12px;
    }

    /* News — three text lines sweep in from left, staggered. The first
       child of the SVG is a <rect> (frame) — we only target <line>s. */
    .sidenav-item[data-nav="news"]:hover .sidenav-icon svg line {
        animation: nav-anim-news 0.5s var(--ease) both;
        transform-box: fill-box;
        transform-origin: left center;
    }
    .sidenav-item[data-nav="news"]:hover .sidenav-icon svg line:nth-of-type(2) {
        animation-delay: 0.08s;
    }
    .sidenav-item[data-nav="news"]:hover .sidenav-icon svg line:nth-of-type(3) {
        animation-delay: 0.16s;
    }

    /* Calendar — top date pegs jump (line 2 = x=8 left peg, line 3 =
       x=16 right peg; line 1 = horizontal divider, skipped). Right peg
       fires slightly later for a tiny ripple. */
    .sidenav-item[data-nav="calendar"]:hover .sidenav-icon svg line:nth-of-type(2),
    .sidenav-item[data-nav="calendar"]:hover .sidenav-icon svg line:nth-of-type(3) {
        animation: nav-anim-calendar 0.5s var(--ease);
        transform-box: fill-box;
        transform-origin: bottom center;
    }
    .sidenav-item[data-nav="calendar"]:hover .sidenav-icon svg line:nth-of-type(3) {
        animation-delay: 0.08s;
    }

    /* Wishlist — bookmark drops in from above with a tiny overshoot. */
    .sidenav-item[data-nav="wishlist"]:hover .sidenav-icon svg path {
        animation: nav-anim-bookmark 0.55s var(--ease);
        transform-box: fill-box;
        transform-origin: top center;
    }

    /* Events — megaphone shouts: the cone wobbles like someone yelling into
       it, and the sound-wave arc (second <path>) pulses outward so it reads
       as "broadcast". Two separate animations on the same hover so the wave
       times with the swing's outward phase. */
    .sidenav-item[data-nav="events"]:hover .sidenav-icon svg {
        animation: nav-anim-megaphone 0.6s var(--ease);
        transform-origin: center;
    }
    .sidenav-item[data-nav="events"]:hover .sidenav-icon svg path:nth-of-type(2) {
        animation: nav-anim-megaphone-wave 0.6s var(--ease) both;
        transform-box: fill-box;
        transform-origin: left center;
    }
}

@keyframes nav-anim-controller {
    0%, 100% { transform: rotate(0); }
    20%      { transform: rotate(-14deg); }
    50%      { transform: rotate(10deg); }
    80%      { transform: rotate(-4deg); }
}

@keyframes nav-anim-clock {
    0%   { transform: rotate(0); }
    100% { transform: rotate(360deg); }
}

@keyframes nav-anim-news {
    0%   { transform: scaleX(0.2); opacity: 0.3; }
    100% { transform: scaleX(1);   opacity: 1; }
}

@keyframes nav-anim-calendar {
    0%, 100% { transform: translateY(0); }
    50%      { transform: translateY(-3px); }
}

@keyframes nav-anim-bookmark {
    0%   { transform: translateY(-4px); opacity: 0.4; }
    60%  { transform: translateY(2px);  opacity: 1; }
    100% { transform: translateY(0); }
}

@keyframes nav-anim-megaphone {
    0%, 100% { transform: rotate(0); }
    20%      { transform: rotate(-10deg); }
    55%      { transform: rotate(8deg); }
    80%      { transform: rotate(-3deg); }
}

@keyframes nav-anim-megaphone-wave {
    0%   { transform: scaleX(0.4) translateX(-2px); opacity: 0.3; }
    50%  { transform: scaleX(1.2);                  opacity: 1; }
    100% { transform: scaleX(1)   translateX(0);    opacity: 1; }
}

.sidenav-count {
    margin-left: auto;
    background: var(--accent);
    color: white;
    font-family: 'JetBrains Mono', monospace;
    font-size: 10px;
    font-weight: 800;
    padding: 2px 7px;
    border-radius: var(--radius-pill);
    min-width: 22px;
    text-align: center;
}

/* Wishlist count badge — green to match the "saved" semantic of the cards.
   Dark text by default (high contrast on bright green in dark mode);
   overridden to white in light mode where it looks more natural. */
.sidenav-count-success {
    background: var(--success);
    box-shadow: 0 0 10px rgba(42, 224, 122, 0.35);
    color: #07050F;
}

[data-theme="light"] .sidenav-count-success { color: #FFFFFF; }

/* Today-count badge — pulsing accent so user notices imminent drops */
.today-count {
    background: linear-gradient(135deg, var(--accent-bright), var(--accent));
    box-shadow: 0 0 12px var(--accent-glow);
    animation: todayPulse 1.8s ease-in-out infinite;
}

/* When one of today's releases is on the user's wishlist, paint the badge
   green — visual cue that a tracked game is dropping today.
   Same color logic as sidenav-count-success (dark text on dark mode for
   higher contrast on bright green; white on light mode). */
.today-count.wishlisted-today {
    background: linear-gradient(135deg, #5BFFB0, var(--success));
    box-shadow: 0 0 14px rgba(42, 224, 122, 0.55);
    animation: wishlistedTodayPulse 1.8s ease-in-out infinite;
    color: #07050F;
}

[data-theme="light"] .today-count.wishlisted-today { color: #FFFFFF; }

@keyframes wishlistedTodayPulse {
    0%, 100% { box-shadow: 0 0 12px rgba(42, 224, 122, 0.45); transform: scale(1); }
    50%      { box-shadow: 0 0 22px rgba(42, 224, 122, 0.8);  transform: scale(1.08); }
}

@keyframes todayPulse {
    0%, 100% { box-shadow: 0 0 8px var(--accent-glow); transform: scale(1); }
    50%      { box-shadow: 0 0 20px var(--accent-glow-strong); transform: scale(1.08); }
}

/* About button moved to topbar as a small icon — now reuses .icon-btn styles.
   The old sidebar variant is gone; we keep the rule below only as a safeguard
   in case stale markup still references .about-btn anywhere in the sidebar. */
.sidebar .about-btn { display: none; }

/* ============================================================
   Main column
   ============================================================ */
.main {
    background: transparent;
    min-width: 0;
    /* Sticky-footer column. We want the global site-footer to land near the
       bottom of the viewport on short pages (e.g. Home) so there's no big
       black gap, AND to flow naturally below content on long pages (Releases
       grid). Flex column + footer:margin-top:auto + min-height: 100vh on the
       container gives both behaviours without per-page tweaks. */
    display: flex;
    flex-direction: column;
    min-height: 100vh;
    /* Padding-bottom kept tight so the global site-footer sits near (but not
       flush against) the bottom edge of the viewport. Footer has its own
       margin-top: auto to push itself there. */
    padding: 0 40px 22px;
}
.main > .site-footer { margin-top: auto; }

/* Topbar */
.topbar {
    position: sticky;
    top: 0;
    z-index: 8;
    display: flex;
    align-items: center;
    justify-content: space-between;
    /* Top padding accounts for the iOS standalone status-bar overlap, same
       as .sidebar above. Without this, the search input + theme toggle render
       under the system clock when the user has the app on the home screen. */
    padding: calc(22px + env(safe-area-inset-top, 0px)) 40px 18px;
    background: var(--topbar-bg);
    backdrop-filter: blur(20px);
    -webkit-backdrop-filter: blur(20px);
    gap: 16px;
    margin: 0 -40px;
}

/* (Breadcrumb styles removed — the topbar no longer renders one; task #54.) */

.topbar-actions {
    display: flex;
    align-items: center;
    gap: 6px;
    /* Now that the breadcrumb is gone, .topbar-actions is the only child of
       .topbar. Take the full width so the search-wrap can flex-grow to the left
       while the icons stay anchored at the right edge. */
    width: 100%;
}

/* Search bar takes all available space; icons sit at the end */
.topbar-actions .search-wrap {
    flex: 1;
    max-width: 360px;
}
.topbar-actions .search-input {
    width: 100%;
}
.topbar-actions .icon-btn {
    flex-shrink: 0;
    margin-left: auto;
}
/* Only the FIRST icon (About) gets margin-left:auto so it gets pushed away
   from search; the rest sit tight next to it */
.topbar-actions .icon-btn ~ .icon-btn {
    margin-left: 0;
}

.search-wrap {
    position: relative;
    display: flex;
    align-items: center;
}

.search-icon {
    position: absolute;
    left: 14px;
    width: 16px;
    height: 16px;
    color: var(--text-muted);
    pointer-events: none;
    transition: color 0.2s;
}

.search-wrap:focus-within .search-icon { color: var(--accent); }

.icon-btn {
    background: transparent;
    border: none;
    color: var(--text-muted);
    width: 38px;
    height: 38px;
    border-radius: var(--radius);
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: all 0.2s var(--ease);
}

.icon-btn svg { width: 20px; height: 20px; }

.icon-btn:hover {
    background: var(--bg-card);
    color: var(--accent);
}

.search-input {
    background: var(--bg-input);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 9px 14px 9px 38px;
    color: var(--text);
    font-family: inherit;
    font-size: 13px;
    width: 260px;
    outline: none;
    transition: border-color 0.2s, box-shadow 0.2s;
}

.search-input:focus {
    border-color: var(--accent);
    box-shadow: 0 0 0 3px rgba(154, 108, 255, 0.15);
}

.search-input::placeholder { color: var(--text-soft); }

/* ============================================================
   Pages
   ============================================================ */
.page {
    animation: pageIn 0.5s var(--ease);
    transform-origin: top center;
}

/* pageIn — opacity + translate only. The previous `filter: blur(3px)`
   keyframe was the visible flicker on Firefox: animating filter forces a
   full repaint of the page subtree every frame, and Firefox's compositor
   can drop one or two frames at the start of the animation, producing a
   one-frame "flash". Composited transform + opacity stay on the GPU. */
@keyframes pageIn {
    from {
        opacity: 0;
        transform: translateY(10px);
    }
    to {
        opacity: 1;
        transform: translateY(0);
    }
}

.page-header {
    padding: 36px 0 28px;
    display: flex;
    align-items: flex-end;
    justify-content: space-between;
    gap: 24px;
    flex-wrap: wrap;
}

.page-title {
    font-size: 52px;
    font-weight: 800;
    letter-spacing: -0.035em;
    line-height: 1;
    color: var(--text);
}

.page-desc {
    font-size: 15px;
    color: var(--text-muted);
    margin-top: 8px;
}

.page-actions {
    display: flex;
    gap: 8px;
}

/* Hero-style page header — same vertical rhythm as the Releases hero.
   align-items: flex-start anchors the title to the TOP (matching Releases
   where .hero is plain block layout). Without this the parent .page-header
   sets flex-end and pins the title to the bottom of the 520px hero.
   Padding/min-height tuned tighter than .hero: with align-items: flex-start
   the content stacks at the top and the bottom would otherwise be a big
   empty band before the toolbar starts. Shorter hero pulls the grid up. */
.page-header-hero {
    padding: 60px 0 32px;
    align-items: flex-start;
    /* Anchor for #upcoming-spotlight which is absolute-positioned on the right */
    position: relative;
    min-height: 440px;
}
/* Text container (tag + title + desc + CTA) — first div child of the hero.
   :not(.hero-spotlight) prevents this rule from clobbering the spotlight,
   which is ALSO a div child and needs its own position:absolute + full width.
   Without the exclusion the spotlight would get max-width:560px + position:
   relative and collapse to 0 width as a sibling flex item. */
.page-header-hero > div:not(.hero-spotlight) {
    max-width: 560px;              /* match .hero-content */
    position: relative;
    z-index: 2;
}

.page-header-hero .hero-tag {
    margin-bottom: 18px;           /* match .hero-tag */
}

.page-header-hero .page-title {
    font-size: clamp(54px, 7vw, 92px);
    line-height: 0.95;
    letter-spacing: -0.045em;
    margin-bottom: 26px;           /* match .hero-title */
}

.page-header-hero .page-desc {
    font-size: 17px;
    line-height: 1.55;
    color: var(--text-muted);
    margin-top: 0;
    max-width: 460px;
    margin-bottom: 36px;           /* leave room for the CTA below */
}

/* Mobile — keep CTA visible and stacked under the desc */
@media (max-width: 700px) {
    .page-header-hero { padding: 28px 0 22px; align-items: stretch; min-height: 0; }
    .page-header-hero .page-title { font-size: 38px; margin-bottom: 14px; }
    .page-header-hero .page-desc { font-size: 14px; margin-bottom: 22px; }
    .page-header-hero .hero-tag { margin-bottom: 10px; }
    .page-header-hero .hero-cta { width: 100%; justify-content: center; }
}

/* ============================================================
   Hero — Latest Releases
   ============================================================ */
.hero {
    position: relative;
    padding: 60px 0 80px;
    min-height: 520px;
    overflow: visible;
    z-index: 1;
}

/* The SVG glow is now redundant — the page background image carries the glow */
.hero-glow { display: none; }

.hero-glow svg { width: 100%; height: 100%; }

@keyframes heroFloat {
    from { transform: scale(1) translate(0, 0); }
    to   { transform: scale(1.04) translate(-24px, 10px); }
}

.hero-content {
    position: relative;
    z-index: 2;
    max-width: 560px;
}

.hero-tag {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    font-family: 'JetBrains Mono', monospace;
    font-size: 12px;
    font-weight: 700;
    letter-spacing: 0.18em;
    color: var(--accent);
    margin-bottom: 18px;
}

.hero-tag::before {
    content: '';
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--accent);
    box-shadow: 0 0 12px var(--accent-glow);
    animation: pulse 1.8s ease-in-out infinite;
}

@keyframes pulse {
    0%, 100% { opacity: 1; transform: scale(1); }
    50%      { opacity: 0.5; transform: scale(0.9); }
}

.hero-title {
    font-size: clamp(54px, 7vw, 92px);
    font-weight: 800;
    letter-spacing: -0.045em;
    line-height: 0.95;
    color: var(--text);
    margin-bottom: 26px;
}

.hero-desc {
    font-size: 17px;
    color: var(--text-muted);
    line-height: 1.55;
    margin-bottom: 36px;
    max-width: 420px;
}

.hero-cta {
    display: inline-flex;
    align-items: center;
    gap: 14px;
    padding: 14px 22px;
    background: var(--accent);
    border: none;
    border-radius: var(--radius);
    color: var(--bg);
    font-size: 14px;
    font-weight: 700;
    letter-spacing: -0.01em;
    cursor: pointer;
    transition: all 0.2s var(--ease);
    box-shadow: 0 8px 30px var(--accent-glow);
}

.hero-cta:hover {
    background: var(--accent-bright);
    transform: translateY(-2px);
    box-shadow: 0 12px 40px var(--accent-glow-strong);
}

.hero-cta svg { width: 18px; height: 18px; }
.hero-cta:hover svg { transform: translateX(4px); transition: transform 0.2s; }


/* ============================================================
   Section header + filter tabs
   ============================================================ */
.section { margin-bottom: 60px; }

/* Match the .section's bottom buffer for pages that don't wrap their grid
   in <section class="section"> (Upcoming, Wishlist, Calendar, Events, News).
   Without this, the last row of cards crowds the global footer divider —
   Releases had the buffer because of its .section wrapper, others didn't.
   Targets the last meaningful child of each page so the buffer always lands
   right above the footer divider regardless of which subgrid is visible. */
.page-upcoming > .card-grid:last-child,
.page-upcoming > .upcoming-list:last-child,
.page-upcoming > .upcoming-grid:not(.hidden) + .upcoming-list.hidden,
.page-wishlist > .wishlist-section:last-child,
.page-calendar > .calendar-month:last-child,
.page-calendar > .calendar-year:last-child,
.page-events > .events-section:last-child,
.page-events > .events-empty:last-child,
.page-news > .news-grid {
    margin-bottom: 60px;
}
/* Upcoming has BOTH grid and list as siblings; whichever is visible needs
   the buffer. Targeting both ensures the active one always provides it. */
#upcoming-grid:not(.hidden),
#upcoming-list:not(.hidden) {
    margin-bottom: 60px;
}

.section-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    margin-bottom: 28px;
    flex-wrap: wrap;
}

.section-title {
    font-size: 24px;
    font-weight: 700;
    color: var(--accent);
    letter-spacing: -0.02em;
}

.filter-tabs {
    display: flex;
    align-items: center;
    gap: 28px;
}

.filter-tab {
    background: transparent;
    border: none;
    color: var(--text-muted);
    font-family: inherit;
    font-size: 14px;
    font-weight: 500;
    cursor: pointer;
    padding: 6px 0;
    position: relative;
    letter-spacing: -0.01em;
    transition: color 0.2s;
}

.filter-tab:hover { color: var(--text); }

.filter-tab.active {
    color: var(--text);
}

.filter-tab.active::after {
    content: '';
    position: absolute;
    bottom: -4px;
    left: 0;
    right: 0;
    height: 2px;
    background: var(--accent);
    box-shadow: 0 0 8px var(--accent-glow);
}

/* ============================================================
   Toolbar (sort, filter pills)
   ============================================================ */
.toolbar {
    display: flex;
    gap: 18px;
    align-items: center;
    margin-bottom: 22px;
    flex-wrap: wrap;
}

.toolbar-group {
    display: inline-flex;
    align-items: center;
    gap: 10px;
}

.toolbar-label {
    font-family: 'JetBrains Mono', monospace;
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--text-muted);
}

.toolbar-select {
    background: var(--bg-card);
    border: 1px solid var(--border);
    color: var(--text);
    font-family: inherit;
    font-size: 13px;
    font-weight: 600;
    padding: 8px 32px 8px 12px;
    border-radius: var(--radius);
    cursor: pointer;
    transition: border-color 0.2s, background 0.2s;
    appearance: none;
    background-image:
        linear-gradient(45deg, transparent 50%, var(--accent) 50%),
        linear-gradient(135deg, var(--accent) 50%, transparent 50%);
    background-position:
        calc(100% - 14px) 50%,
        calc(100% - 10px) 50%;
    background-size: 4px 4px, 4px 4px;
    background-repeat: no-repeat;
}

.toolbar-select:hover { border-color: var(--accent); }
.toolbar-select:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px rgba(154, 108, 255, 0.15); }

/* Platform tabs inside the toolbar — push to the right, tighter gap */
.toolbar-tabs {
    margin-left: auto;
    gap: 22px;
}

@media (max-width: 900px) {
    .toolbar-tabs {
        margin-left: 0;
        width: 100%;
        overflow-x: auto;
        scrollbar-width: none;
        padding-bottom: 4px;
    }
    .toolbar-tabs::-webkit-scrollbar { display: none; }
}

/* ============================================================
   Card grid
   ============================================================ */
.card-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
    gap: 16px;
}

.game-card {
    background: var(--bg-card);
    border: 1px solid var(--divider);
    border-radius: var(--radius-lg);
    overflow: hidden;
    cursor: pointer;
    transition: all 0.3s var(--ease);
    display: flex;
    flex-direction: column;
    animation: cardIn 0.4s var(--ease) backwards;
    position: relative;
    /* Isolate the card's layout + paint domain so a hover/animation in one
       card doesn't trigger a repaint of the sibling cards. We deliberately
       avoid `contain: content` (= layout + paint + style) because the `style`
       contain bucket can break CSS-counter / inheritance edge cases and on
       Firefox occasionally causes vertical gaps in grid auto-fill rows. */
    contain: layout paint;
}

@keyframes cardIn {
    from { opacity: 0; transform: translateY(12px); }
    to   { opacity: 1; transform: translateY(0); }
}

.game-card:hover {
    border-color: var(--border-strong);
    transform: translateY(-4px);
    box-shadow: 0 18px 40px rgba(0, 0, 0, 0.4), 0 0 30px var(--accent-glow);
}

.game-card:hover .game-card-img { transform: scale(1.04); }
.game-card:hover .game-card-arrow {
    background: var(--accent);
    color: var(--bg);
    border-color: var(--accent);
    transform: translateX(3px);
}

.game-card-media {
    position: relative;
    aspect-ratio: 3 / 4;
    overflow: hidden;
    background: var(--bg-elevated);
}

.game-card-img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
    /* 0.4s feels snappier than the original 0.6s for the hover-zoom — still
       smooth, less laggy on rapid mouseovers */
    transition: transform 0.4s var(--ease);
}

.game-card-img-fallback {
    width: 100%;
    height: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    background: linear-gradient(135deg, var(--accent-soft), var(--accent));
    color: white;
    font-size: 38px;
    font-weight: 900;
    letter-spacing: -0.04em;
}

.game-card-date {
    position: absolute;
    top: 12px;
    left: 12px;
    /* Pinned to the deeper #7D33FF (hybrid / light theme's --accent) instead of
       reading var(--accent), which on dark mode is the lighter #9A6CFF and made
       this pill read as washed-out against bright card art. Hybrid + light keep
       their existing look since they already use #7D33FF as their accent. */
    background: #7D33FF;
    color: #FFFFFF;
    border-radius: var(--radius-sm);
    padding: 8px 10px;
    box-shadow:
        /* Inset dark "border" — always visible because it's drawn inside the pill,
           never clipped by .game-card-media overflow:hidden */
        inset 0 0 0 1.5px rgba(0, 0, 0, 0.55),
        /* Drop shadow visible where overflow allows (below + right) */
        0 8px 22px rgba(0, 0, 0, 0.95),
        0 3px 8px rgba(0, 0, 0, 0.7);
    display: flex;
    flex-direction: column;
    align-items: center;
    line-height: 1;
    box-shadow: 0 6px 20px var(--accent-glow);
    z-index: 2;
}

.game-card-date-day {
    font-size: 18px;
    font-weight: 800;
    letter-spacing: -0.02em;
}

.game-card-date-month {
    font-family: 'JetBrains Mono', monospace;
    font-size: 9px;
    font-weight: 700;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    margin-top: 2px;
    opacity: 0.85;
}

.game-card-star {
    position: absolute;
    top: 12px;
    right: 12px;
    width: 32px;
    height: 32px;
    background: rgba(7, 5, 15, 0.7);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    border: 1px solid rgba(255,255,255,0.15);
    border-radius: 50%;
    color: white;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 3;
    /* Always visible by default — covers tablets and any touch device */
    opacity: 1;
    transition: all 0.2s var(--ease);
}

/* Only hide-on-hover for true mouse + hover-capable devices (desktop) */
@media (hover: hover) and (pointer: fine) {
    .game-card-star { opacity: 0; }
    .game-card:hover .game-card-star { opacity: 1; }
}

.game-card-star svg { width: 15px; height: 15px; }
.game-card-star.active {
    background: var(--success);
    border-color: var(--success);
    color: white;
    opacity: 1;
    box-shadow: 0 0 16px rgba(42, 224, 122, 0.5);
}

.game-card-star.active:hover {
    background: var(--success);
    transform: scale(1.1);
    box-shadow: 0 0 22px rgba(42, 224, 122, 0.65);
}

/* First-visit hint tooltip attached to the first card's star */
.game-card.show-star-hint .game-card-star {
    opacity: 1;
    animation: starHintPulse 1.8s ease-in-out infinite;
}

@keyframes starHintPulse {
    0%, 100% { transform: scale(1); box-shadow: 0 0 0 0 rgba(154, 108, 255, 0.55); }
    50%      { transform: scale(1.1); box-shadow: 0 0 0 10px rgba(154, 108, 255, 0); }
}

/* Hint pill — positioned BELOW the star so it never overlaps the date pill.
   Green (success colour) matches the wishlist semantic. Auto-dismisses
   after ~5s via the second animation (no need to click). */
.game-card.show-star-hint::after {
    content: 'Click ★ to track';
    position: absolute;
    top: 52px;            /* just below the 32px-tall star at top:12 */
    right: 12px;
    background: var(--success);
    color: #07050F;
    font-family: 'JetBrains Mono', monospace;
    font-size: 9.5px;
    font-weight: 700;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    padding: 5px 9px;
    border-radius: var(--radius-sm);
    white-space: nowrap;
    z-index: 6;
    box-shadow: 0 6px 18px rgba(42, 224, 122, 0.45);
    animation:
        starHintIn 0.4s var(--ease-spring) 0.8s backwards,
        starHintOut 0.5s var(--ease) 5s forwards;
    pointer-events: none;
}

/* Arrow now points UP from the pill toward the star above it */
.game-card.show-star-hint::before {
    content: '';
    position: absolute;
    top: 46px;
    right: 22px;
    width: 0;
    height: 0;
    border-bottom: 6px solid var(--success);
    border-left: 4px solid transparent;
    border-right: 4px solid transparent;
    z-index: 6;
    animation:
        starHintIn 0.4s var(--ease-spring) 0.8s backwards,
        starHintOut 0.5s var(--ease) 5s forwards;
    pointer-events: none;
}

@keyframes starHintIn {
    from { opacity: 0; transform: translateY(-6px); }
    to   { opacity: 1; transform: translateY(0); }
}

/* Auto-dismiss after ~5s — fades out and stays hidden (forwards fill) */
@keyframes starHintOut {
    from { opacity: 1; transform: translateY(0); }
    to   { opacity: 0; transform: translateY(-4px); }
}

.game-card-star:hover { transform: scale(1.1); }

.game-card-cd {
    position: absolute;
    bottom: 12px;
    right: 12px;
    background: rgba(7, 5, 15, 0.78);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    color: white;
    font-family: 'JetBrains Mono', monospace;
    font-size: 10px;
    font-weight: 700;
    padding: 4px 9px;
    border-radius: var(--radius-sm);
    letter-spacing: 0.04em;
    border: 1px solid rgba(255,255,255,0.12);
    z-index: 2;
}

/* Released — cinematic bottom gradient instead of a small badge.
   Dark fade-up from the bottom of the cover with "RELEASED" sitting in it. */
.game-card-cd.released {
    top: auto;
    left: 0;
    right: 0;
    bottom: 0;
    width: 100%;
    height: 58px;
    background: linear-gradient(180deg,
        transparent 0%,
        rgba(0, 0, 0, 0.45) 35%,
        rgba(0, 0, 0, 0.88) 80%,
        rgba(0, 0, 0, 0.95) 100%);
    backdrop-filter: none;
    -webkit-backdrop-filter: none;
    border: none;
    border-radius: 0;
    padding: 0 0 11px 0;
    display: flex;
    align-items: flex-end;
    justify-content: center;
    color: rgba(255, 255, 255, 0.95);
    font-size: 12px;
    font-weight: 800;
    letter-spacing: 0.28em;
    text-transform: uppercase;
    text-shadow: 0 2px 8px rgba(0, 0, 0, 0.5);
    pointer-events: none;
}

.game-card-body {
    padding: 16px 18px 14px;
    display: flex;
    flex-direction: column;
    gap: 4px;
}

.game-card-title {
    font-size: 17px;
    font-weight: 700;
    color: var(--text);
    letter-spacing: -0.025em;
    line-height: 1.2;
    overflow: hidden;
    display: -webkit-box;
    -webkit-line-clamp: 1;
    -webkit-box-orient: vertical;
}

.game-card-genre {
    font-size: 12px;
    color: var(--text-muted);
    font-weight: 500;
    overflow: hidden;
    white-space: nowrap;
    text-overflow: ellipsis;
}

.game-card-footer {
    margin-top: auto;
    padding: 0 18px 16px;
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 12px;
}

.game-card-platforms {
    display: flex;
    gap: 8px;
    align-items: center;
    color: var(--text-muted);
    transition: color 0.2s;
    min-width: 0;
    flex: 1;
    flex-wrap: wrap;
}

.game-card:hover .game-card-platforms { color: var(--text); }

/* Real brand SVGs rendered as a CSS mask so they inherit currentColor */
.platform-icon {
    display: inline-block;
    height: 16px;
    background-color: currentColor;
    -webkit-mask-image: var(--icon-url);
            mask-image: var(--icon-url);
    -webkit-mask-size: contain;
            mask-size: contain;
    -webkit-mask-repeat: no-repeat;
            mask-repeat: no-repeat;
    -webkit-mask-position: center;
            mask-position: center;
}

/* Per-platform widths keep aspect ratios looking right */
.platform-icon.platform-ps5 { width: 22px; }
.platform-icon.platform-xbox { width: 18px; }
.platform-icon.platform-switch { width: 19px; }

/* PC = plain mono text instead of an icon */
.platform-text {
    font-family: 'JetBrains Mono', monospace;
    font-size: 11px;
    font-weight: 800;
    letter-spacing: 0.04em;
    line-height: 1;
    color: currentColor;
}

.game-card-arrow {
    width: 32px;
    height: 32px;
    background: transparent;
    border: 1px solid var(--border-strong);
    border-radius: 50%;
    color: var(--accent);
    display: flex;
    align-items: center;
    justify-content: center;
    transition: all 0.25s var(--ease);
    flex-shrink: 0;
    margin-left: auto;
}

.game-card-arrow svg { width: 14px; height: 14px; }

/* Marked: interested — green halo to clearly differentiate from regular violet cards.
   "On my wishlist" = green / yes / saved. */
.game-card.interested {
    border-color: var(--success);
    /* Soft green wash through the card body so the wishlist state reads from
       the inside out — same vibe the list-view / compact rows already had.
       Bg-card stays underneath as a fallback so we don't get fully translucent
       cards if --bg-card is ever themed transparent. */
    background:
        linear-gradient(rgba(42, 224, 122, 0.10), rgba(42, 224, 122, 0.10)),
        var(--bg-card);
    animation:
        cardIn 0.4s var(--ease) backwards,
        interestedPulse 3s ease-in-out infinite;
}

/* Two-layer shadow only (was three). 60px blur radius is the most expensive
   GPU operation here — dropped to a tighter 28px max. Visually almost identical
   but at ~50 wishlisted cards this saves significant compositing work. */
@keyframes interestedPulse {
    0%, 100% {
        box-shadow:
            0 0 0 1.5px var(--success),
            0 0 16px rgba(42, 224, 122, 0.32);
    }
    50% {
        box-shadow:
            0 0 0 1.5px var(--success),
            0 0 28px rgba(42, 224, 122, 0.55);
    }
}

/* Hint the browser to GPU-composite box-shadow changes off the main thread */
.game-card.interested { will-change: box-shadow; }

/* On touch devices the pulse is mostly distracting — drop frequency in half
   to halve compositing work without losing the cue entirely */
@media (hover: none), (pointer: coarse) {
    .game-card.interested {
        animation:
            cardIn 0.4s var(--ease) backwards,
            interestedPulse 6s ease-in-out infinite !important;
    }
}

/* Users with reduced motion: no pulsing at all, just the static green ring */
@media (prefers-reduced-motion: reduce) {
    .game-card.interested {
        animation: cardIn 0.4s var(--ease) backwards !important;
        box-shadow: 0 0 0 1.5px var(--success), 0 0 14px rgba(42, 224, 122, 0.3);
    }
}

.game-card.interested:hover {
    animation-play-state: paused;
    transform: translateY(-4px);
    border-color: var(--success);
    /* Slightly stronger tint on hover, matching the list-view's 0.10 → 0.16 step */
    background:
        linear-gradient(rgba(42, 224, 122, 0.16), rgba(42, 224, 122, 0.16)),
        var(--bg-card-hover);
    box-shadow:
        0 0 0 1.5px var(--success),
        0 18px 38px rgba(0, 0, 0, 0.45),
        0 0 32px rgba(42, 224, 122, 0.6),
        0 0 70px rgba(42, 224, 122, 0.4);
}

.game-card.not-interested {
    opacity: 0.45;
}

.game-card.not-interested .game-card-title {
    text-decoration: line-through;
}

/* ============================================================
   Home page — cinematic welcome
   ============================================================ */
.page-home {
    /* Content flows from the top, padding scales with viewport for natural
       breathing room from mobile through to 4K. justify-content stays on X
       only — vertical centering used to push the footer below the fold. */
    display: flex;
    align-items: stretch;
    justify-content: center;
    padding: clamp(28px, 5vw, 72px) 0 0;
    position: relative;
}

.home-stage {
    /* min() wins between 92vw (mobile-safe) and 980px (max desktop reach).
       Wider than the old 720px so the layout breathes on 1440p+ monitors
       without going full-width-billboard at 4K. */
    max-width: min(980px, 92vw);
    width: 100%;
    text-align: center;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: clamp(14px, 1.6vw, 22px);
    position: relative;
}

/* === LOGO GLYPH (animated) === */
.home-glyph {
    position: relative;
    /* Scales from 180 px on phones to 260 px on big monitors. */
    width: clamp(180px, 18vw, 260px);
    height: clamp(90px, 9vw, 130px);
    margin-bottom: 0;
}

.home-glyph svg {
    width: 100%;
    height: 100%;
    position: relative;
    z-index: 2;
    overflow: visible;
}

.home-glyph-aura {
    position: absolute;
    inset: -30px;
    border-radius: 50%;
    background: radial-gradient(circle, var(--accent-glow) 0%, rgba(154, 108, 255, 0.18) 35%, transparent 70%);
    opacity: 0;
    z-index: 1;
    animation: homeAura 1s 0.5s var(--ease) forwards, homeAuraPulse 4s 1.5s ease-in-out infinite;
    filter: blur(24px);
}

@keyframes homeAura {
    from { opacity: 0; transform: scale(0.6); }
    to   { opacity: 0.5; transform: scale(1); }
}

@keyframes homeAuraPulse {
    0%, 100% { opacity: 0.5; transform: scale(1); }
    50%      { opacity: 0.3; transform: scale(1.06); }
}

.home-block {
    transform-origin: left center;
    transform-box: fill-box;
    opacity: 0;
}

.home-block-top {
    animation: homeBlockTop 0.7s 0.1s cubic-bezier(0.34, 1.4, 0.64, 1) forwards;
}

.home-block-bottom {
    animation: homeBlockBottom 0.7s 0.3s cubic-bezier(0.34, 1.4, 0.64, 1) forwards;
}

@keyframes homeBlockTop {
    from { transform: translateX(-120px) skewX(20deg); opacity: 0; }
    to   { transform: translateX(0) skewX(0); opacity: 1; }
}

@keyframes homeBlockBottom {
    from { transform: translateX(120px) skewX(-20deg); opacity: 0; }
    to   { transform: translateX(0) skewX(0); opacity: 1; }
}

/* === Title + subtitle === */
.home-title {
    /* Wider clamp range so the title actually grows on 1440p+ instead of
       capping at 84 px. Lower bound stays mobile-safe. */
    font-size: clamp(54px, 9vw, 104px);
    font-weight: 800;
    letter-spacing: -0.045em;
    line-height: 1;
    color: var(--text);
    opacity: 0;
    animation: homeFadeUp 0.6s 0.8s var(--ease) forwards;
}

.home-title sup {
    position: relative;
    top: -2.4em;
    font-size: 0.22em;
    line-height: 1;
    color: var(--text-muted);
    margin-left: 4px;
    font-weight: 500;
    vertical-align: baseline;
    letter-spacing: 0;
}

.home-sub {
    font-family: 'JetBrains Mono', monospace;
    font-size: clamp(12px, 1vw, 14px);
    font-weight: 700;
    letter-spacing: 0.25em;
    color: var(--accent);
    opacity: 0;
    animation: homeFadeUp 0.5s 1s var(--ease) forwards;
}

.home-desc {
    font-size: clamp(15px, 1.4vw, 19px);
    color: var(--text-muted);
    line-height: 1.6;
    max-width: clamp(380px, 36vw, 480px);
    opacity: 0;
    animation: homeFadeUp 0.5s 1.15s var(--ease) forwards;
}

@keyframes homeFadeUp {
    from { transform: translateY(16px); opacity: 0; filter: blur(6px); }
    to   { transform: translateY(0); opacity: 1; filter: blur(0); }
}

/* === Stats === */
.home-stats {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: clamp(10px, 1.2vw, 18px);
    margin-top: clamp(20px, 2.5vw, 36px);
    width: 100%;
    max-width: clamp(560px, 60vw, 760px);
    opacity: 0;
    animation: homeFadeUp 0.5s 1.3s var(--ease) forwards;
}

.home-stat {
    background: var(--bg-card);
    border: 1px solid var(--divider);
    border-radius: var(--radius);
    padding: clamp(16px, 1.8vw, 24px) clamp(12px, 1.4vw, 18px);
    display: flex;
    flex-direction: column;
    gap: 6px;
    transition: all 0.25s var(--ease);
}

.home-stat:hover {
    border-color: var(--accent);
    transform: translateY(-3px);
    box-shadow: 0 10px 25px rgba(0,0,0,0.3), 0 0 20px var(--accent-glow);
}

.home-stat strong {
    font-family: 'JetBrains Mono', monospace;
    font-size: clamp(26px, 2.6vw, 38px);
    font-weight: 800;
    color: var(--accent);
    letter-spacing: -0.02em;
    font-variant-numeric: tabular-nums;
    line-height: 1;
}

.home-stat span {
    font-family: 'JetBrains Mono', monospace;
    font-size: clamp(9px, 0.8vw, 11px);
    font-weight: 700;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--text-muted);
}

/* === Quick actions === */
.home-actions {
    display: grid;
    grid-template-columns: repeat(3, 1fr);
    gap: clamp(10px, 1.2vw, 18px);
    margin-top: clamp(14px, 1.6vw, 22px);
    width: 100%;
    max-width: clamp(560px, 60vw, 760px);
    opacity: 0;
    animation: homeFadeUp 0.55s 1.5s var(--ease) forwards;
}

.home-action {
    background: var(--bg-card);
    border: 1px solid var(--divider);
    border-radius: var(--radius);
    padding: clamp(18px, 2vw, 28px) clamp(12px, 1.4vw, 18px);
    color: var(--text);
    cursor: pointer;
    font-family: inherit;
    display: flex;
    flex-direction: column;
    align-items: center;
    gap: clamp(6px, 0.8vw, 10px);
    transition: all 0.25s var(--ease);
    text-align: center;
}

.home-action:hover {
    border-color: var(--accent);
    transform: translateY(-4px);
    box-shadow: 0 14px 30px rgba(0,0,0,0.35), 0 0 26px var(--accent-glow);
}

.home-action:hover .home-action-icon {
    color: var(--accent);
    transform: scale(1.1);
}

.home-action-icon {
    width: clamp(26px, 2.2vw, 36px);
    height: clamp(26px, 2.2vw, 36px);
    display: inline-flex;
    color: var(--text-muted);
    transition: all 0.25s var(--ease);
}

.home-action-icon svg { width: 100%; height: 100%; }

.home-action.primary {
    background: var(--accent);
    border-color: var(--accent);
    color: var(--bg);
    box-shadow: 0 8px 26px var(--accent-glow);
}

.home-action.primary .home-action-icon { color: var(--bg); }
.home-action.primary .home-action-sub { color: rgba(15, 14, 31, 0.7); }

.home-action.primary:hover {
    background: var(--accent-bright);
    transform: translateY(-4px);
    box-shadow: 0 14px 36px var(--accent-glow-strong);
}

.home-action-label {
    font-size: clamp(13px, 1.1vw, 16px);
    font-weight: 700;
    letter-spacing: -0.01em;
}

.home-action-sub {
    font-family: 'JetBrains Mono', monospace;
    font-size: clamp(9px, 0.75vw, 11px);
    font-weight: 700;
    letter-spacing: 0.14em;
    text-transform: uppercase;
    color: var(--text-muted);
}

/* === Footer === */
.home-footer {
    margin-top: 32px;
    font-family: 'JetBrains Mono', monospace;
    font-size: 9.5px;
    font-weight: 700;
    letter-spacing: 0.2em;
    color: var(--text-soft);
    opacity: 0;
    animation: homeFadeUp 0.5s 1.8s var(--ease) forwards;
    text-align: center;
}
/* Global site footer — minimal one-line strip pinned near the bottom edge.
   Big margin-top to push itself away from the last grid row above; minimal
   padding so it hugs the bottom of the viewport. */
.site-footer {
    /* margin-top here is just the MINIMUM gap from the content above when the
       page is long enough to fill the viewport. On short pages, the `.main >
       .site-footer { margin-top: auto }` rule wins and pins the footer to the
       bottom edge of the viewport instead.

       Bumped 80 → 120 so the last row of grid cards has breathing room before
       the divider line above the footer — at 80 the bottom of the cards was
       crowding the rule. */
    margin-top: 120px;
    padding-top: 8px;
    border-top: 1px solid var(--divider);
}
.site-footer-inner {
    display: flex;
    align-items: center;
    justify-content: space-between;
    gap: 16px;
    padding: 0 2px;
}
.site-footer-brand {
    display: inline-flex;
    align-items: center;
    gap: 6px;
    text-decoration: none;
    color: var(--text-soft);
    font-weight: 700;
    font-size: 11px;
    letter-spacing: -0.01em;
    transition: color 0.18s var(--ease);
}
.site-footer-brand:hover { color: var(--text-muted); }
/* Brand text inside the footer stays uniformly muted — including the "Dropz"
   span, which globally uses the accent color via .brand-title-accent. Down
   here it would stick out as a tiny violet word against everything else
   gray. Force it back to inherit so the whole word reads as one tone. */
.site-footer-brand-text .brand-title-accent { color: inherit; }
.site-footer-brand-mark {
    width: 12px;
    height: 12px;
    color: var(--text-soft);
    transition: color 0.18s var(--ease);
}
.site-footer-brand:hover .site-footer-brand-mark { color: var(--accent); }
.site-footer-brand-mark svg { width: 100%; height: 100%; }
.site-footer-brand-text sup { font-size: 6px; opacity: 0.6; margin-left: 1px; }

.site-footer-links {
    display: flex;
    align-items: center;
    gap: 8px;
    font-family: 'JetBrains Mono', monospace;
    font-size: 9px;
    font-weight: 600;
    letter-spacing: 0.16em;
    text-transform: uppercase;
}
.site-footer-links a {
    color: var(--text-soft);
    text-decoration: none;
    transition: color 0.18s var(--ease);
}
.site-footer-links a:hover { color: var(--accent-bright); }
.site-footer-links span { color: var(--text-dim); }

.site-footer-meta {
    display: flex;
    align-items: center;
    gap: 8px;
    font-family: 'JetBrains Mono', monospace;
    font-size: 9px;
    font-weight: 700;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--text-soft);
    line-height: 1;
}
.site-footer-meta-copy { color: var(--text-dim); }

@media (max-width: 700px) {
    .site-footer { margin-top: 72px; padding-top: 6px; }
    .site-footer-inner {
        flex-wrap: wrap;
        justify-content: center;
        gap: 8px 14px;
    }
    .site-footer-meta-build { display: none; }
}

/* === Mobile home tweaks === */
@media (max-width: 700px) {
    .page-home { padding: 20px 0 40px; min-height: auto; }
    .home-stage { gap: 16px; }
    .home-glyph { width: 150px; height: 75px; }
    .home-title { font-size: 44px; }
    .home-title sup { font-size: 12px; }
    .home-sub { font-size: 11px; }
    .home-desc { font-size: 14px; }
    .home-stats { grid-template-columns: 1fr 1fr 1fr; gap: 8px; margin-top: 18px; }
    .home-stat { padding: 12px 8px; }
    .home-stat strong { font-size: 22px; }
    .home-stat span { font-size: 8.5px; letter-spacing: 0.1em; }
    .home-actions { grid-template-columns: 1fr; gap: 10px; }
    .home-action { padding: 16px; flex-direction: row; justify-content: flex-start; gap: 14px; text-align: left; }
    .home-action-label { font-size: 15px; }
}

/* ============================================================
   News page (IGN feed)
   ============================================================ */
.page-desc-link {
    color: var(--accent);
    text-decoration: none;
    transition: opacity 0.2s;
}
.page-desc-link:hover { opacity: 0.7; }

.news-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(380px, 1fr));
    gap: 18px;
}

/* ============================================================
   EVENTS — same visual family as news cards but with extra metadata
   (presenter badge, countdown, optional approximate flag).
   ============================================================ */
.events-section { margin-bottom: 32px; }
.events-section.hidden { display: none; }

/* LIVE NOW — visually distinct so a glance is enough to spot a running
   showcase. Red header dot pulses (matches the LIVE badge inside cards). */
.events-section-live .events-grid { gap: 18px; }
.events-section-live .wishlist-section-label { color: #e0455e; letter-spacing: 0.1em; }
.events-live-dot {
    width: 10px; height: 10px;
    border-radius: 50%;
    background: #e0455e;
    box-shadow: 0 0 0 0 rgba(224,69,94,0.6);
    animation: livePulse 1.4s ease-in-out infinite;
    display: inline-block;
}
.event-card.live {
    border-color: rgba(224,69,94,0.55);
    box-shadow: 0 0 0 1px rgba(224,69,94,0.25), 0 8px 24px rgba(224,69,94,0.12);
}
.event-card.live:hover {
    border-color: #e0455e;
    box-shadow: 0 0 0 1px rgba(224,69,94,0.45), 0 12px 32px rgba(224,69,94,0.18);
}

/* Sidebar "LIVE" badge — red pulsing pill replacing the green count.
   Only appears when something is actually streaming right now. */
.sidenav-count-live {
    background: #e0455e !important;
    color: #fff !important;
    font-weight: 800;
    letter-spacing: 0.08em;
    animation: livePulse 1.4s ease-in-out infinite;
}
.events-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(380px, 1fr));
    gap: 18px;
}
.events-empty {
    padding: 40px 24px;
    text-align: center;
    color: var(--text-dim);
    background: var(--bg-card);
    border-radius: 16px;
    border: 1px solid var(--border);
}
.events-empty.hidden { display: none; }

.event-card {
    display: grid;
    grid-template-columns: 160px 1fr;
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: 16px;
    overflow: hidden;
    text-decoration: none;
    color: inherit;
    transition: transform 0.18s ease, border-color 0.18s ease, box-shadow 0.18s ease;
    animation: cardIn 0.35s ease both;
    position: relative;
}
.event-card:hover {
    transform: translateY(-2px);
    border-color: var(--accent-soft);
    box-shadow: 0 8px 24px rgba(0,0,0,0.08);
}
.event-card.past {
    opacity: 0.78;
}
.event-card.past:hover { opacity: 1; }
.event-card.approximate::after {
    /* Soft hatch overlay so approximate (anchor) events read as
       provisional even when the rest of the card looks the same. */
    content: '';
    position: absolute; inset: 0;
    pointer-events: none;
    background: repeating-linear-gradient(135deg, transparent 0 14px, rgba(125,125,150,0.04) 14px 16px);
}

.event-card-thumb {
    aspect-ratio: 16 / 10;
    background: var(--bg-soft, rgba(125,125,150,0.06));
    overflow: hidden;
}
.event-card-thumb img {
    width: 100%; height: 100%;
    object-fit: cover;
    display: block;
}
.event-card-thumb-placeholder {
    background: linear-gradient(135deg, rgba(125,90,200,0.15), rgba(140,140,180,0.06));
}

.event-card-body {
    padding: 14px 16px 16px;
    display: flex; flex-direction: column; gap: 8px;
    min-width: 0;
}

.event-card-meta {
    display: flex; align-items: center; justify-content: space-between;
    gap: 10px;
    font-size: 11px;
    text-transform: uppercase;
    letter-spacing: 0.06em;
}
.event-presenter {
    display: inline-flex; align-items: center; gap: 6px;
    color: var(--text-dim);
    font-weight: 600;
}
.event-presenter-dot {
    width: 8px; height: 8px; border-radius: 50%;
    box-shadow: 0 0 6px currentColor;
}
.event-countdown {
    font-family: 'Space Mono', ui-monospace, monospace;
    color: var(--accent2);
    background: var(--accent-bg, rgba(125,90,200,0.08));
    padding: 2px 8px;
    border-radius: 999px;
    font-size: 10px;
    letter-spacing: 0.04em;
}
.event-live-badge {
    color: #fff;
    background: #e0455e;
    padding: 2px 8px;
    border-radius: 999px;
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.08em;
    animation: livePulse 1.4s ease-in-out infinite;
}
@keyframes livePulse {
    0%,100% { box-shadow: 0 0 0 0 rgba(224,69,94,0.55); }
    50%     { box-shadow: 0 0 0 6px rgba(224,69,94,0); }
}

.event-card-title {
    font-size: 17px;
    line-height: 1.25;
    font-weight: 700;
    color: var(--text);
    margin: 0;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}
.event-card-date {
    font-family: 'Space Mono', ui-monospace, monospace;
    font-size: 12px;
    color: var(--text-dim);
}
.event-card-desc {
    font-size: 13px;
    line-height: 1.45;
    color: var(--text-dim);
    margin: 0;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    overflow: hidden;
}
.event-card-cta {
    margin-top: auto;
    display: inline-flex; align-items: center; gap: 6px;
    font-size: 12px;
    font-weight: 600;
    color: var(--accent2);
    padding-top: 4px;
}
.event-card-cta svg { width: 14px; height: 14px; transition: transform 0.18s ease; }
.event-card:hover .event-card-cta svg { transform: translateX(3px); }

@media (max-width: 700px) {
    .events-grid { grid-template-columns: 1fr; }
    .event-card { grid-template-columns: 120px 1fr; }
    .event-card-title { font-size: 15px; }
}

.news-card {
    display: grid;
    grid-template-columns: 140px 1fr;
    background: var(--bg-card);
    border: 1px solid var(--divider);
    border-radius: var(--radius);
    overflow: hidden;
    text-decoration: none;
    color: inherit;
    cursor: pointer;
    transition: all 0.25s var(--ease);
    animation: cardIn 0.35s var(--ease) backwards;
    min-height: 140px;
}

.news-card:hover {
    border-color: var(--accent);
    transform: translateY(-3px);
    box-shadow: 0 14px 32px rgba(0, 0, 0, 0.4), 0 0 28px var(--accent-glow);
}

.news-card:hover .news-arrow {
    transform: translate(3px, -3px);
    color: var(--accent-bright);
}

.news-card:hover .news-card-img { transform: scale(1.05); }

.news-card-media {
    background: var(--bg-elevated);
    overflow: hidden;
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
}

.news-card-media.failed::after {
    content: '';
    position: absolute;
    inset: 0;
    background:
        linear-gradient(135deg, var(--accent-soft) 0%, var(--accent) 100%);
    opacity: 0.6;
}

.news-card-media img,
.news-card-img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
    transition: transform 0.6s var(--ease);
}

.news-card-media img { transition: transform 0.6s var(--ease); }

.news-card-body {
    padding: 14px 16px 12px;
    display: flex;
    flex-direction: column;
    gap: 6px;
    min-width: 0;
}

.news-card-meta {
    display: flex;
    align-items: center;
    gap: 10px;
    font-family: 'JetBrains Mono', monospace;
    font-size: 9px;
    font-weight: 700;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: var(--text-soft);
    margin-bottom: 2px;
}

.news-source {
    color: var(--accent);
    padding: 2px 6px;
    border: 1px solid var(--accent);
    border-radius: 3px;
    font-weight: 800;
}

.news-cat {
    color: var(--text-muted);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    max-width: 140px;
}

.news-time {
    margin-left: auto;
    color: var(--text-muted);
}

.news-card-title {
    font-size: 15px;
    font-weight: 700;
    line-height: 1.3;
    color: var(--text);
    overflow: hidden;
    display: -webkit-box;
    -webkit-line-clamp: 3;
    -webkit-box-orient: vertical;
    letter-spacing: -0.015em;
}

.news-card-desc {
    font-size: 12.5px;
    color: var(--text-muted);
    line-height: 1.5;
    overflow: hidden;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
    flex: 1;
}

.news-card-foot {
    margin-top: 6px;
    padding-top: 8px;
    border-top: 1px dashed var(--divider);
    display: flex;
    align-items: center;
    justify-content: space-between;
    font-size: 11px;
    color: var(--text-muted);
}

.news-author {
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    max-width: 200px;
    font-weight: 500;
}

.news-arrow {
    color: var(--accent);
    font-size: 16px;
    font-weight: 800;
    transition: all 0.25s var(--ease);
}

.news-loading-state {
    grid-column: 1 / -1;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 16px;
    padding: 80px 20px;
}

@media (max-width: 600px) {
    .news-grid { grid-template-columns: 1fr; }
    .news-card { grid-template-columns: 110px 1fr; min-height: 120px; }
}

/* Stub pages */
.page-stub { padding: 100px 0; }

.stub {
    text-align: center;
    color: var(--text-muted);
    max-width: 420px;
    margin: 0 auto;
}

.stub-icon {
    color: var(--accent);
    display: inline-flex;
    padding: 22px;
    border: 1px solid var(--border-strong);
    border-radius: var(--radius-lg);
    margin-bottom: 22px;
    box-shadow: 0 0 30px var(--accent-glow);
}

.stub-icon svg { width: 32px; height: 32px; display: block; }

.stub h2 {
    font-size: 28px;
    font-weight: 700;
    color: var(--text);
    margin-bottom: 8px;
    letter-spacing: -0.02em;
}

.stub p { font-size: 14px; color: var(--text-muted); }

/* Designed empty state for the wishlist page */
.wishlist-empty {
    padding: 60px 20px 80px;
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    gap: 12px;
}

.wishlist-empty-ill {
    width: 220px;
    height: 180px;
    margin-bottom: 4px;
    animation: wishEmptyFloat 4s ease-in-out infinite;
    filter: drop-shadow(0 0 20px var(--accent-glow));
}

@keyframes wishEmptyFloat {
    0%, 100% { transform: translateY(0); }
    50%      { transform: translateY(-6px); }
}

.wishlist-empty-title {
    font-size: 22px;
    font-weight: 800;
    letter-spacing: -0.025em;
    color: var(--text);
}

.wishlist-empty-sub {
    font-size: 14px;
    color: var(--text-muted);
    max-width: 360px;
    line-height: 1.5;
}

.wishlist-empty-cta {
    margin-top: 10px;
    padding: 11px 18px;
}

/* ============================================================
   Calendar page
   ============================================================ */
.calendar-header {
    align-items: flex-end;
}

.calendar-controls {
    display: flex;
    gap: 8px;
    align-items: center;
}

.view-switcher {
    position: relative;
    display: flex;
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 3px;
}

.view-pill {
    position: absolute;
    top: 3px;
    left: 3px;
    height: calc(100% - 6px);
    width: calc(50% - 3px);
    background: var(--accent);
    border-radius: var(--radius-sm);
    transition: transform 0.3s var(--ease);
    z-index: 0;
    box-shadow: 0 0 16px var(--accent-glow);
}

.view-switcher.year-active .view-pill { transform: translateX(100%); }

.view-btn {
    position: relative;
    z-index: 1;
    background: transparent;
    border: none;
    padding: 8px 18px;
    color: var(--text-muted);
    font-family: inherit;
    font-size: 13px;
    font-weight: 600;
    cursor: pointer;
    border-radius: var(--radius-sm);
    transition: color 0.2s;
}

.view-btn.active { color: var(--bg); }

.nav-controls {
    display: flex;
    gap: 2px;
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 3px;
}

.nav-btn {
    background: transparent;
    border: none;
    color: var(--text);
    padding: 7px 14px;
    border-radius: var(--radius-sm);
    cursor: pointer;
    font-family: inherit;
    font-size: 13px;
    font-weight: 600;
    transition: all 0.15s var(--ease);
    display: inline-flex;
    align-items: center;
    justify-content: center;
}

.nav-btn.icon-only { padding: 7px 10px; }
.nav-btn svg { width: 14px; height: 14px; }
.nav-btn:hover { background: var(--bg-card-hover); color: var(--accent); }

/* Calendar grids */
.calendar-month {
    background: var(--bg-card);
    border: 1px solid var(--border-strong);
    border-radius: var(--radius-lg);
    overflow: hidden;
    box-shadow:
        0 10px 30px rgba(0, 0, 0, 0.35),
        0 0 0 1px rgba(154, 108, 255, 0.08) inset;
}

.weekdays {
    display: grid;
    grid-template-columns: repeat(7, 1fr);
    border-bottom: 1px solid var(--border-strong);
    background: rgba(154, 108, 255, 0.06);
}

.weekday {
    padding: 14px 10px;
    text-align: center;
    font-family: 'JetBrains Mono', monospace;
    font-size: 10px;
    font-weight: 800;
    color: var(--accent-bright);
    letter-spacing: 0.2em;
    text-transform: uppercase;
    border-right: 1px solid var(--border);
}

.weekday:last-child { border-right: none; }
.weekday:nth-child(6),
.weekday:nth-child(7) { color: var(--accent); opacity: 0.85; }

.days-grid {
    display: grid;
    grid-template-columns: repeat(7, 1fr);
    grid-auto-rows: minmax(120px, auto);
}

.day-cell {
    border-right: 1px solid var(--border);
    border-bottom: 1px solid var(--border);
    padding: 10px;
    position: relative;
    display: flex;
    flex-direction: column;
    gap: 4px;
    overflow: hidden;
    transition: background 0.2s;
}

.day-cell:hover {
    background: var(--bg-card-hover);
    overflow: visible;
    z-index: 20;
}

.day-cell:nth-child(7n) { border-right: none; }
.day-cell.other-month { opacity: 0.35; }

/* Weekend cells get a very subtle violet tint to separate them visually */
.day-cell:nth-child(7n - 1),
.day-cell:nth-child(7n) {
    background: rgba(154, 108, 255, 0.025);
}

[data-theme="light"] .day-cell:nth-child(7n - 1),
[data-theme="light"] .day-cell:nth-child(7n) {
    background: rgba(125, 51, 255, 0.03);
}

.day-number {
    font-family: 'JetBrains Mono', monospace;
    font-size: 12px;
    font-weight: 700;
    color: var(--text-muted);
    align-self: flex-start;
    padding: 4px 7px;
    border-radius: var(--radius-sm);
    line-height: 1;
}

.day-cell.today {
    background: rgba(154, 108, 255, 0.12);
    box-shadow: inset 0 2px 0 var(--accent);
}

.day-cell.today .day-number {
    background: var(--accent);
    color: var(--bg);
    box-shadow: 0 0 14px var(--accent-glow);
    font-weight: 800;
}

.day-cell.has-interested {
    box-shadow: inset 0 0 0 1px var(--success);
    background: rgba(42, 224, 122, 0.05);
}

.release-card {
    background: var(--bg-elevated);
    border: 1px solid var(--divider);
    border-radius: var(--radius-sm);
    padding: 5px 7px;
    font-size: 11px;
    cursor: pointer;
    display: flex;
    align-items: center;
    gap: 6px;
    transition: all 0.2s var(--ease);
    position: relative;
    overflow: hidden;
}

.release-card.interested {
    border-color: var(--success);
    box-shadow: 0 0 0 1px var(--success), 0 0 10px rgba(42, 224, 122, 0.25);
}
.release-card.not-interested { opacity: 0.5; }
.release-card.not-interested .release-name { text-decoration: line-through; }

.day-cell:hover .release-card {
    transform: translateY(-2px) scale(1.05);
    background: var(--bg-card-hover);
    border-color: var(--accent);
    box-shadow: 0 8px 24px var(--accent-glow);
    z-index: 25;
}

.release-icon {
    width: 22px;
    height: 22px;
    border-radius: var(--radius-sm);
    flex-shrink: 0;
    background-size: cover !important;
    background-position: center !important;
    background-color: var(--accent);
    color: white;
    font-size: 9px;
    font-weight: 800;
    display: flex;
    align-items: center;
    justify-content: center;
}

.release-name {
    flex: 1;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
    font-weight: 600;
    color: var(--text);
}

.day-cell:hover .release-name {
    white-space: normal;
    display: -webkit-box;
    -webkit-line-clamp: 2;
    -webkit-box-orient: vertical;
}

.release-countdown {
    font-family: 'JetBrains Mono', monospace;
    font-size: 9px;
    color: var(--text-muted);
    font-weight: 700;
    flex-shrink: 0;
}

/* Year grid */
.calendar-year {
    display: grid;
    grid-template-columns: repeat(4, 1fr);
    gap: 16px;
}

@media (max-width: 1100px) { .calendar-year { grid-template-columns: repeat(3, 1fr); } }
@media (max-width: 800px)  { .calendar-year { grid-template-columns: repeat(2, 1fr); } }

.mini-month {
    background:
        linear-gradient(180deg, rgba(154, 108, 255, 0.04), transparent 50%),
        var(--bg-card);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 16px;
    cursor: pointer;
    transition: all 0.25s var(--ease);
    position: relative;
    box-shadow:
        0 6px 18px rgba(0, 0, 0, 0.28),
        0 1px 0 rgba(184, 145, 255, 0.05) inset,
        0 0 0 1px rgba(154, 108, 255, 0.04);
}

[data-theme="light"] .mini-month {
    box-shadow:
        0 4px 14px rgba(34, 33, 58, 0.08),
        0 1px 2px rgba(34, 33, 58, 0.04),
        0 0 0 1px rgba(125, 51, 255, 0.04);
}

.mini-month:hover {
    border-color: var(--accent);
    transform: translateY(-3px);
    box-shadow:
        0 16px 34px rgba(0, 0, 0, 0.4),
        0 0 30px var(--accent-glow),
        0 1px 0 rgba(184, 145, 255, 0.1) inset;
}

[data-theme="light"] .mini-month:hover {
    box-shadow:
        0 14px 30px rgba(34, 33, 58, 0.15),
        0 0 28px var(--accent-glow);
}

.mini-month-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    margin-bottom: 12px;
    padding-bottom: 10px;
    border-bottom: 1px solid var(--divider);
}

.mini-month-title {
    font-size: 13px;
    font-weight: 700;
    color: var(--text);
    letter-spacing: -0.01em;
}

.mini-month-count {
    background: var(--accent);
    color: var(--bg);
    font-family: 'JetBrains Mono', monospace;
    font-size: 10px;
    font-weight: 800;
    padding: 2px 8px;
    border-radius: var(--radius-pill);
}

.mini-weekdays {
    display: grid;
    grid-template-columns: repeat(7, 1fr);
    gap: 2px;
    margin-bottom: 4px;
}

.mini-weekday {
    font-family: 'JetBrains Mono', monospace;
    font-size: 9px;
    color: var(--text-soft);
    text-align: center;
    font-weight: 700;
}

.mini-days {
    display: grid;
    grid-template-columns: repeat(7, 1fr);
    gap: 2px;
}

.mini-day {
    aspect-ratio: 1;
    display: flex;
    align-items: center;
    justify-content: center;
    font-family: 'JetBrains Mono', monospace;
    font-size: 10px;
    color: var(--text-soft);
    font-weight: 600;
    border-radius: 4px;
}

.mini-day.current-month { color: var(--text); }
.mini-day.has-release {
    background: var(--accent);
    color: var(--bg);
    font-weight: 800;
}

.mini-day.has-release.interested {
    background: var(--success);
    box-shadow: 0 0 8px rgba(42, 224, 122, 0.45);
}

.mini-day.today { outline: 2px solid var(--accent); outline-offset: -2px; }

.mini-top-strip {
    display: flex;
    gap: 4px;
    margin-top: 12px;
    padding-top: 10px;
    border-top: 1px dashed var(--divider);
}

.mini-top-tile {
    flex: 1;
    aspect-ratio: 3/4;
    background-size: cover;
    background-position: center;
    background-color: var(--accent);
    border-radius: 4px;
    cursor: pointer;
    transition: transform 0.2s;
    overflow: hidden;
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    color: white;
    font-size: 10px;
    font-weight: 800;
}

.mini-top-tile:hover { transform: translateY(-3px); z-index: 2; }

.mini-top-tile.watched::before {
    content: '★';
    position: absolute;
    top: 2px;
    right: 3px;
    color: var(--success);
    filter: drop-shadow(0 0 4px rgba(42, 224, 122, 0.6));
    font-size: 12px;
    text-shadow: 0 0 6px rgba(0,0,0,0.6);
}

/* ============================================================
   Wishlist page
   ============================================================ */
.wishlist-header { align-items: flex-end; }

.ghost-btn {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    background: transparent;
    border: 1px solid var(--border-strong);
    color: var(--text);
    padding: 9px 14px;
    border-radius: var(--radius);
    font-family: inherit;
    font-size: 13px;
    font-weight: 600;
    cursor: pointer;
    transition: all 0.2s var(--ease);
}

.ghost-btn.refreshing svg { animation: spinSlow 0.8s linear infinite; }
.ghost-btn.refreshing { pointer-events: none; opacity: 0.7; }

@keyframes spinSlow { to { transform: rotate(360deg); } }

.news-updated {
    font-family: 'JetBrains Mono', monospace;
    font-size: 10px;
    font-weight: 600;
    letter-spacing: 0.1em;
    color: var(--text-soft);
    text-transform: uppercase;
    align-self: center;
}

.ghost-btn svg { width: 15px; height: 15px; color: var(--accent); }

.ghost-btn:hover {
    background: var(--bg-card);
    border-color: var(--accent);
}

.ghost-btn.danger:hover {
    border-color: var(--danger);
    color: var(--danger);
}

.ghost-btn.danger:hover svg { color: var(--danger); }

/* ============================================================
   Modal
   ============================================================ */
.modal-backdrop {
    position: fixed;
    inset: 0;
    background: rgba(7, 5, 15, 0.85);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 100;
    padding: 24px;
    animation: fadeIn 0.2s var(--ease);
}

@keyframes fadeIn { from { opacity: 0; } to { opacity: 1; } }

.modal {
    background:
        radial-gradient(ellipse 80% 50% at 50% 100%, rgba(154, 108, 255, 0.10), transparent 65%),
        radial-gradient(ellipse 60% 40% at 50% 0%, rgba(184, 145, 255, 0.06), transparent 60%),
        var(--bg-card);
    border: 1px solid var(--border-strong);
    border-radius: var(--radius-lg);
    max-width: 620px;
    width: 100%;
    max-height: 90vh;
    overflow-y: auto;
    position: relative;
    box-shadow:
        0 30px 80px rgba(0, 0, 0, 0.6),
        0 0 60px var(--accent-glow),
        inset 0 1px 0 rgba(184, 145, 255, 0.08);
    animation: modalIn 0.3s var(--ease);
    isolation: isolate;
}

/* Subtle hex texture overlay (very low opacity). Mask only fades the TOP
   (under the hero image area) so the hex doesn't compete with the cover
   art. The BOTTOM intentionally has no fade — in dark mode the bottom
   fade was invisible (bg-card was already dark), but in light/hybrid the
   bg-card is light lavender (#EAE6F1) and the bottom 20% with no hex
   read as a noticeably lighter strip above the action buttons. Going
   black-to-100% keeps tone consistent end-to-end on the light canvas. */
.modal::before {
    content: '';
    position: absolute;
    inset: 0;
    pointer-events: none;
    background-image: url('hex.svg');
    background-repeat: repeat;
    background-size: 60px 104px;
    opacity: 0.08;
    border-radius: inherit;
    -webkit-mask-image: linear-gradient(180deg, transparent 0%, black 30%, black 100%);
            mask-image: linear-gradient(180deg, transparent 0%, black 30%, black 100%);
    z-index: 0;
}

/* Accent gradient line under the hero — separates hero from body elegantly */
.modal-hero::before {
    content: '';
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    height: 2px;
    background: linear-gradient(90deg, transparent 0%, var(--accent) 30%, var(--accent-bright) 50%, var(--accent) 70%, transparent 100%);
    z-index: 3;
    box-shadow: 0 0 12px var(--accent-glow);
}

.modal-body {
    position: relative;
    z-index: 1;
}

@keyframes modalIn {
    from { transform: translateY(20px) scale(0.96); opacity: 0; }
    to   { transform: translateY(0) scale(1); opacity: 1; }
}

.modal-close {
    position: absolute;
    top: 14px;
    right: 14px;
    width: 36px;
    height: 36px;
    background: rgba(7, 5, 15, 0.7);
    backdrop-filter: blur(10px);
    border: 1px solid rgba(255,255,255,0.15);
    border-radius: 50%;
    color: white;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    z-index: 4;
    transition: all 0.2s;
}

.modal-close svg { width: 15px; height: 15px; }
.modal-close:hover {
    background: var(--danger);
    border-color: var(--danger);
    transform: rotate(90deg);
}

.modal-hero {
    height: 220px;
    background-color: var(--accent);
    position: relative;
    display: flex;
    align-items: center;
    justify-content: center;
    color: white;
    font-size: 60px;
    font-weight: 900;
    letter-spacing: -0.05em;
    border-radius: var(--radius-lg) var(--radius-lg) 0 0;
    overflow: hidden;
}
.modal-hero-img {
    position: absolute;
    inset: 0;
    width: 100%;
    height: 100%;
    object-fit: cover;
    object-position: center;
    display: block;
}

/* Crossfade rotation: every screenshot is stacked; only .active is opaque.
   The non-active slides stay in the DOM at opacity 0 so swapping the class
   produces a smooth dissolve handled entirely by CSS. */
.modal-hero-slide {
    opacity: 0;
    transition: opacity 0.9s var(--ease);
    z-index: 1;
}
.modal-hero-slide.active {
    opacity: 1;
    z-index: 2;
}

.modal-hero::after {
    content: '';
    position: absolute;
    inset: 0;
    background: linear-gradient(180deg, transparent 50%, rgba(17, 13, 34, 0.85) 100%);
    border-radius: var(--radius-lg) var(--radius-lg) 0 0;
    /* Above the rotating slides (z-index ≤ 2) so the bottom fade stays put
       while screenshots crossfade beneath it. */
    z-index: 3;
}

.modal-hero-text {
    position: relative;
    z-index: 1;
    text-shadow: 0 4px 24px rgba(0,0,0,0.5);
}

.modal-body { padding: 26px 28px 28px; }

.modal-title {
    font-size: 28px;
    font-weight: 800;
    letter-spacing: -0.03em;
    line-height: 1.1;
    margin-bottom: 6px;
    color: var(--text);
}

.modal-subtitle {
    color: var(--text-muted);
    font-size: 14px;
    font-weight: 500;
    margin-bottom: 20px;
}

.modal-countdown {
    background:
        radial-gradient(ellipse at 50% 130%, rgba(154, 108, 255, 0.2), transparent 65%),
        linear-gradient(180deg, rgba(154, 108, 255, 0.03), rgba(154, 108, 255, 0.01)),
        var(--bg-input);
    border: 1px solid rgba(154, 108, 255, 0.22);
    border-radius: var(--radius);
    padding: 16px;
    margin-bottom: 16px;
    text-align: center;
    position: relative;
    overflow: hidden;
    box-shadow: inset 0 1px 0 rgba(184, 145, 255, 0.1);
}

.modal-countdown::before {
    content: '';
    position: absolute;
    inset: 0;
    background: radial-gradient(circle at 50% 100%, rgba(154, 108, 255, 0.28), transparent 60%);
    opacity: 0.6;
    pointer-events: none;
}

.modal-countdown::after {
    content: '';
    position: absolute;
    top: 0;
    left: 20%;
    right: 20%;
    height: 1px;
    background: linear-gradient(90deg, transparent, var(--accent), transparent);
    opacity: 0.5;
}

.countdown-label {
    font-family: 'JetBrains Mono', monospace;
    font-size: 10px;
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: 0.18em;
    margin-bottom: 10px;
    font-weight: 700;
    position: relative;
}

.countdown-value {
    font-family: 'JetBrains Mono', monospace;
    font-size: 26px;
    font-weight: 800;
    color: #ffffff;
    letter-spacing: -0.02em;
    line-height: 1;
    position: relative;
    text-shadow:
        0 0 22px rgba(154, 108, 255, 0.55),
        0 2px 6px rgba(0, 0, 0, 0.35);
}

[data-theme="light"] .countdown-value {
    color: var(--accent);
    text-shadow:
        0 0 14px rgba(125, 51, 255, 0.2),
        0 1px 1px rgba(255, 255, 255, 0.6);
}

/* Released state — neutral white / muted treatment so it doesn't clash with the
   green wishlist semantics. "RELEASED" = status indicator, no action needed. */
.countdown-released {
    color: rgba(255, 255, 255, 0.95);
    text-shadow: 0 2px 8px rgba(0, 0, 0, 0.4);
    letter-spacing: 0.08em;
}

.modal-countdown:has(.countdown-released) {
    background:
        radial-gradient(ellipse at 50% 130%, rgba(255, 255, 255, 0.06), transparent 65%),
        linear-gradient(180deg, rgba(255, 255, 255, 0.02), transparent),
        var(--bg-input);
    border-color: rgba(255, 255, 255, 0.18);
    box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.06);
}

.modal-countdown:has(.countdown-released)::before {
    background: radial-gradient(circle at 50% 100%, rgba(255, 255, 255, 0.08), transparent 60%);
    opacity: 0.6;
}

.modal-countdown:has(.countdown-released)::after {
    background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.4), transparent);
    opacity: 0.5;
}

[data-theme="light"] .countdown-released {
    color: var(--text);
    text-shadow: 0 1px 0 rgba(255, 255, 255, 0.6);
}

[data-theme="light"] .modal-countdown:has(.countdown-released) {
    background:
        radial-gradient(ellipse at 50% 130%, rgba(34, 33, 58, 0.06), transparent 65%),
        var(--bg-input);
    border-color: rgba(34, 33, 58, 0.18);
}

[data-theme="light"] .modal-countdown:has(.countdown-released)::before {
    background: radial-gradient(circle at 50% 100%, rgba(34, 33, 58, 0.08), transparent 60%);
}

[data-theme="light"] .modal-countdown:has(.countdown-released)::after {
    background: linear-gradient(90deg, transparent, rgba(34, 33, 58, 0.35), transparent);
}

.modal-info {
    display: grid;
    grid-template-columns: 1fr 1fr;
    gap: 8px;
    margin-bottom: 16px;
}

.info-row {
    background:
        linear-gradient(135deg, rgba(154, 108, 255, 0.05) 0%, transparent 50%),
        var(--bg-input);
    border: 1px solid var(--border);
    border-left: 2px solid var(--accent);
    border-radius: var(--radius);
    padding: 11px 14px;
    transition: all 0.2s var(--ease);
}

.info-row:hover {
    border-color: var(--border);
    border-left-color: var(--accent-bright);
    background:
        linear-gradient(135deg, rgba(154, 108, 255, 0.10) 0%, transparent 60%),
        var(--bg-input);
}

.info-label {
    font-family: 'JetBrains Mono', monospace;
    font-size: 9px;
    color: var(--text-muted);
    text-transform: uppercase;
    letter-spacing: 0.18em;
    margin-bottom: 4px;
    font-weight: 700;
}

.info-value {
    font-size: 13px;
    font-weight: 600;
    color: var(--text);
}

.info-rating { color: var(--accent); font-family: 'JetBrains Mono', monospace; }
.info-rating-max { color: var(--text-soft); font-size: 11px; }

.modal-description {
    background:
        linear-gradient(135deg, rgba(154, 108, 255, 0.04) 0%, transparent 70%),
        var(--bg-input);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 14px 16px;
    font-size: 13.5px;
    line-height: 1.6;
    color: var(--text-muted);
    margin-bottom: 18px;
    position: relative;
    /* Clamp long descriptions to fit modal on 1080p without scrolling */
    display: -webkit-box;
    -webkit-line-clamp: 5;
    -webkit-box-orient: vertical;
    overflow: hidden;
}

.modal-description::before {
    content: '"';
    position: absolute;
    top: -2px;
    left: 6px;
    font-size: 36px;
    line-height: 1;
    font-family: serif;
    color: var(--accent);
    opacity: 0.25;
    pointer-events: none;
}

/* ============================================================
   Modal — "Where to buy" store links section
   ============================================================ */
.modal-stores {
    margin-bottom: 22px;
}

.modal-stores-title {
    font-family: 'JetBrains Mono', monospace;
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.22em;
    text-transform: uppercase;
    color: var(--text-muted);
    margin-bottom: 12px;
}

.modal-stores-grid {
    display: flex;
    flex-wrap: wrap;
    gap: 12px;
    align-items: center;
}

/* Each store button has two render modes:
   • ICON STYLE (default for Steam/Epic/PSN/Xbox/Switch) — IGDB-style rounded
     brand badge SVG, no text. Matches the Links section on IGDB's site.
   • CHIP STYLE (fallback for GOG/itch.io and any future stores without an
     icon asset) — brand-coloured pill with the store name. */
.store-btn {
    position: relative;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    text-decoration: none;
    transition: transform 0.2s var(--ease), box-shadow 0.2s var(--ease), filter 0.2s var(--ease);
}
.store-btn:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 3px;
    border-radius: var(--radius);
}

/* === ICON STYLE — IGDB-look rounded badge === */
.store-btn-icon-style {
    width: 40px;
    height: 40px;
    border-radius: var(--radius);
}
.store-btn-icon-style .store-btn-icon {
    width: 100%;
    height: 100%;
    display: block;
    border-radius: var(--radius);
    /* The SVGs ship with their own brand-coloured backgrounds + rounded
       corners. Subtle border keeps a clean edge against the modal bg. */
    box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.06) inset;
}
.store-btn-icon-style:hover {
    transform: translateY(-3px) scale(1.06);
    box-shadow: 0 10px 22px rgba(0, 0, 0, 0.45), 0 0 18px var(--accent-glow);
    filter: brightness(1.1);
}

/* Tiny magnifying-glass overlay in the bottom-right corner of search-URL
   buttons (PSN/Xbox/Switch when IGDB lacks a direct link, or Steam fallback
   for unreleased PC games). Subtle but communicates "this is a search,
   not a direct product page". */
.store-btn-search-badge {
    position: absolute;
    bottom: -4px;
    right: -4px;
    width: 18px;
    height: 18px;
    background: var(--bg-card);
    border: 1px solid var(--border-strong);
    border-radius: 50%;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    font-size: 10px;
    line-height: 1;
    box-shadow: 0 2px 6px rgba(0, 0, 0, 0.4);
    pointer-events: none;
}

/* === CHIP STYLE FALLBACK — for stores without an icon asset === */
.store-btn:not(.store-btn-icon-style) {
    gap: 8px;
    padding: 7px 10px 7px 7px;
    background: var(--bg-input);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    color: var(--text);
    font-size: 12px;
    font-weight: 600;
}
.store-btn:not(.store-btn-icon-style):hover {
    border-color: var(--accent);
    background: var(--bg-card-hover);
    transform: translateY(-2px);
    box-shadow: 0 8px 20px rgba(0, 0, 0, 0.3), 0 0 18px var(--accent-glow);
}

.store-btn-chip {
    padding: 4px 10px;
    border-radius: var(--radius-sm);
    color: #FFFFFF;
    font-family: 'JetBrains Mono', monospace;
    font-size: 11px;
    font-weight: 800;
    letter-spacing: 0.06em;
    line-height: 1.3;
    white-space: nowrap;
}

.store-btn[data-store="gog"]  .store-btn-chip { background: #86328A; }
.store-btn[data-store="itch"] .store-btn-chip { background: #FA5C5C; }

.modal-stores-hint {
    margin-top: 12px;
    font-size: 11px;
    color: var(--text-soft);
    line-height: 1.5;
}

/* Mobile: keep icon size identical (44px taps target), tighten spacing */
@media (max-width: 700px) {
    .modal-stores-grid { gap: 10px; }
    .store-btn-icon-style { width: 44px; height: 44px; }
    .store-btn:not(.store-btn-icon-style) { font-size: 11.5px; padding: 6px 9px 6px 6px; }
    .store-btn:not(.store-btn-icon-style) .store-btn-chip { font-size: 10.5px; padding: 3px 8px; }
}

/* ============================================================
   Modal — "Where to buy" + Trailer 2-col row
   ============================================================
   Wraps the stores grid and the trailer poster side-by-side on desktop so
   they share the previously-empty right column. Stacks vertically on narrow
   viewports so each block keeps a comfortable size. The .modal-stores
   margin-bottom (from its own rule) is neutralised here because the row
   itself owns the bottom spacing now. */
.modal-buy-row {
    display: flex;
    gap: 24px;
    align-items: flex-start;
    margin-bottom: 22px;
}
.modal-buy-row .modal-stores {
    flex: 1 1 auto;
    margin-bottom: 0;
    min-width: 0;
}
.modal-buy-row .modal-trailer {
    flex: 0 0 280px;        /* fixed-ish poster width on desktop */
    min-width: 0;
}

/* Trailer poster — click-to-play surface using the YouTube thumbnail. The
   actual <iframe> is only mounted after the user clicks (see openModal's
   trailerBtn handler). 16:9 aspect-ratio keeps it consistent regardless of
   container width. */
.modal-trailer-poster {
    appearance: none;
    position: relative;
    display: block;
    width: 100%;
    aspect-ratio: 16 / 9;
    border: 1px solid var(--border-strong);
    border-radius: var(--radius);
    overflow: hidden;
    padding: 0;
    background: var(--bg-card);
    cursor: pointer;
    transition: transform 0.22s var(--ease), box-shadow 0.22s var(--ease), border-color 0.22s var(--ease);
}
.modal-trailer-poster:hover {
    transform: translateY(-2px);
    border-color: var(--accent);
    box-shadow: 0 10px 26px var(--accent-glow);
}
.modal-trailer-poster:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 3px;
}

.modal-trailer-thumb {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}

/* Play icon — centered violet pill so it reads as the primary action on
   the poster, not just decorative. White ▶ glyph inside. */
.modal-trailer-play-icon {
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
    width: 54px;
    height: 54px;
    border-radius: 50%;
    background: rgba(154, 108, 255, 0.92);
    color: #fff;
    display: flex;
    align-items: center;
    justify-content: center;
    box-shadow: 0 6px 20px rgba(0, 0, 0, 0.45), 0 0 0 4px rgba(255, 255, 255, 0.08);
    transition: transform 0.22s var(--ease), background 0.22s var(--ease);
}
.modal-trailer-play-icon svg {
    width: 24px;
    height: 24px;
    margin-left: 3px;       /* visual nudge — ▶ shape skews slightly right */
}
.modal-trailer-poster:hover .modal-trailer-play-icon {
    transform: translate(-50%, -50%) scale(1.08);
    background: var(--accent);
}

/* Video name caption at the bottom of the poster — semi-transparent strip
   so the thumb is still readable. Hidden on very small posters. */
.modal-trailer-name {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    padding: 8px 12px;
    background: linear-gradient(180deg, transparent, rgba(0, 0, 0, 0.72));
    color: #fff;
    font-size: 11px;
    font-weight: 600;
    letter-spacing: 0.02em;
    text-align: left;
    text-shadow: 0 1px 2px rgba(0, 0, 0, 0.5);
    /* Truncate long names — "Official Reveal Trailer · 4K Director's Cut" */
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

/* Inline iframe that replaces the poster once playback starts. Same 16:9
   box so the modal doesn't jump. */
.modal-trailer-iframe {
    width: 100%;
    aspect-ratio: 16 / 9;
    border: 0;
    border-radius: var(--radius);
    display: block;
    background: #000;
}

/* Narrow viewports — stack stores on top, trailer below. The fixed 280px
   trailer width was a desktop-only allowance; on mobile let it take full
   width so the poster reads at a comfortable size. */
@media (max-width: 700px) {
    .modal-buy-row {
        flex-direction: column;
        gap: 18px;
    }
    .modal-buy-row .modal-trailer {
        flex: 1 1 auto;
        width: 100%;
    }
    .modal-trailer-play-icon {
        width: 48px;
        height: 48px;
    }
}

.modal-actions {
    display: flex;
    gap: 8px;
}

.action-btn {
    flex: 1;
    padding: 14px 16px;
    border: 1px solid var(--border-strong);
    background: var(--bg-input);
    color: var(--text);
    border-radius: var(--radius);
    cursor: pointer;
    font-family: inherit;
    font-size: 13px;
    font-weight: 700;
    transition: all 0.2s;
}

.action-btn:hover { border-color: var(--accent); color: var(--accent); }

.action-btn.active-interested {
    background: linear-gradient(135deg, #4DE89A, var(--success));
    color: white;
    border-color: var(--success);
    box-shadow: 0 4px 20px rgba(42, 224, 122, 0.45), inset 0 1px 0 rgba(255,255,255,0.25);
}

.action-btn.active-interested:hover {
    box-shadow: 0 6px 26px rgba(42, 224, 122, 0.6), inset 0 1px 0 rgba(255,255,255,0.3);
    transform: translateY(-1px);
}

.action-btn.active-not-interested {
    background: var(--danger);
    color: white;
    border-color: var(--danger);
}

.modal-link {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    margin-top: 16px;
    font-size: 13px;
    font-weight: 600;
    color: var(--accent);
    text-decoration: none;
    padding: 9px 14px;
    border: 1px solid var(--accent);
    border-radius: var(--radius);
    transition: all 0.2s;
}

.modal-link:hover {
    background: var(--accent);
    color: var(--bg);
}

/* About modal — custom layout */
.about-modal { padding: 36px 32px 32px; }

.about-mark {
    width: 56px;
    height: 56px;
    color: var(--accent);
    margin-bottom: 18px;
    filter: drop-shadow(0 0 24px var(--accent-glow));
}

.about-mark svg { width: 100%; height: 100%; }

.about-modal h2 {
    font-size: 32px;
    font-weight: 800;
    letter-spacing: -0.035em;
    line-height: 1;
    color: var(--text);
    margin-bottom: 4px;
}

.about-modal h2 sup {
    font-size: 12px;
    color: var(--text-muted);
    margin-left: 2px;
    vertical-align: super;
}

.about-modal h2 .brand-title-accent { color: var(--accent); }

.about-sub {
    font-family: 'JetBrains Mono', monospace;
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.2em;
    text-transform: uppercase;
    color: var(--text-muted);
    margin-bottom: 24px;
}

.about-desc {
    font-size: 14px;
    line-height: 1.6;
    color: var(--text-muted);
    margin-bottom: 26px;
}

.about-info {
    display: grid;
    grid-template-columns: 1fr;
    gap: 1px;
    background: var(--border);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    overflow: hidden;
    margin-bottom: 24px;
}

.about-row {
    display: grid;
    grid-template-columns: 110px 1fr;
    gap: 16px;
    padding: 12px 16px;
    background: var(--bg-card);
    align-items: center;
}

.about-row dt {
    font-family: 'JetBrains Mono', monospace;
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--text-muted);
}

.about-row dd {
    font-size: 13px;
    font-weight: 600;
    color: var(--text);
}

.about-row dd a {
    color: var(--accent);
    text-decoration: none;
    transition: opacity 0.2s;
}

.about-row dd a:hover { opacity: 0.7; }

.about-footer {
    font-family: 'JetBrains Mono', monospace;
    font-size: 9.5px;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: var(--text-soft);
    text-align: center;
    padding-top: 18px;
    border-top: 1px dashed var(--divider);
}

/* ============================================================
   Loading
   ============================================================ */
.loading-overlay {
    position: fixed;
    inset: 0;
    background: var(--bg);
    display: none;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 20px;
    z-index: 200;
    pointer-events: none;
}

.loading-overlay.visible { display: flex; }

.loading-spinner {
    width: 40px;
    height: 40px;
    border-radius: 50%;
    border: 3px solid var(--border);
    border-top-color: var(--accent);
    animation: spin 0.8s linear infinite;
}

@keyframes spin { to { transform: rotate(360deg); } }

.loading-text {
    font-family: 'JetBrains Mono', monospace;
    font-size: 11px;
    font-weight: 700;
    color: var(--text-muted);
    letter-spacing: 0.2em;
    text-transform: uppercase;
}

.loading-error {
    background: var(--bg-card);
    border: 1px solid var(--danger);
    color: var(--danger);
    padding: 18px 22px;
    border-radius: var(--radius);
    font-size: 14px;
    font-weight: 600;
    pointer-events: auto;
    max-width: 480px;
    text-align: center;
}

/* ============================================================
   Responsive
   ============================================================ */
/* ============================================================
   Tablet (≤1000px) — collapsed sidebar
   ============================================================ */
@media (max-width: 1000px) {
    :root { --sidebar-w: 72px; }

    /* Tighter side padding so 48px buttons fit comfortably; tighter gap between
       brand / nav / about for a tidier vertical rhythm. */
    .sidebar { padding: 22px 8px 16px; gap: 18px; }

    .brand-text { display: none; }
    .brand { justify-content: center; padding: 0; margin-bottom: 4px; }
    .brand-mark { width: 32px; height: 32px; }

    .sidenav { gap: 4px; }
    .sidenav-item span:not(.sidenav-icon):not(.sidenav-count) { display: none; }
    .sidenav-item {
        justify-content: center;
        padding: 12px;
        width: 48px;
        height: 48px;
        margin: 0 auto;
        border-radius: var(--radius);
        position: relative;
        transition: background-color 0.3s var(--ease);
    }

    /* In compact mode the 48×48 button is itself the chip — suppress the
       icon-level chip from the desktop rules so the highlight isn't doubled. */
    .sidenav-icon {
        padding: 0;
        background: transparent !important;
        border-radius: 0;
    }
    .sidenav-icon svg { transition: stroke 0.3s var(--ease); }

    .sidenav-item:hover {
        background: var(--accent);
    }
    .sidenav-item:hover .sidenav-icon svg {
        stroke: #fff;
    }

    /* Replace the left indicator bar with a full accent fill on the button —
       same chip pattern as hover, just locked-in for the active page. */
    .sidenav-item.active::before { display: none; }
    .sidenav-item.active {
        background: var(--accent);
        box-shadow: none;
    }
    .sidenav-item.active .sidenav-icon {
        color: #fff;
        filter: drop-shadow(0 0 10px var(--accent-glow));
    }
    .sidenav-item.active .sidenav-icon svg { stroke: #fff; }

    /* Position the badges as small dots in the top-right corner of the icon
       button instead of pushing them right with margin-left:auto */
    .sidenav-item .sidenav-count {
        position: absolute;
        top: -4px;
        right: -4px;
        margin: 0;
        min-width: 18px;
        height: 18px;
        padding: 0 5px;
        font-size: 9px;
        line-height: 18px;
        text-align: center;
        border-radius: 9px;
        border: 2px solid var(--sidebar-bg);
    }

    /* Visual end of nav — soft divider before the sign-in/user widget */
    #sidebar-auth::before {
        content: '';
        position: absolute;
        top: -14px;
        left: 8px;
        right: 8px;
        height: 1px;
        background: var(--divider);
    }

    .main { padding: 0 24px 60px; }
    .topbar { margin: 0 -24px; padding-left: 24px; padding-right: 24px; }
}

/* ============================================================
   Mobile (≤700px) — bottom tab bar + tighter layout
   ============================================================ */
@media (max-width: 700px) {
    :root {
        --sidebar-w: 0;
        --bottom-nav-h: 64px;
    }

    /* Hide the "Happy Comet" external link, its preceding divider, AND the
       descriptive tagline on mobile. The bottom tab bar is already at
       capacity with 6 primary nav items — adding a 7th + a paragraph would
       overflow / cramp the icons. The link stays reachable on desktop where
       there's room in the side rail. */
    .sidenav-external-group,
    .sidenav-divider { display: none !important; }

    /* Force full width — defensive against weird layout collapse */
    html, body { overflow-x: hidden; }
    .app { grid-template-columns: 1fr; }
    .main {
        padding-left: 16px;
        padding-right: 16px;
        max-width: 100%;
        width: 100%;
    }
    .hero, .hero-content, .page-header > div { width: 100%; max-width: 100%; }

    /* Don't force line breaks inside hero/home/page-desc — let text flow naturally */
    .hero-desc br,
    .home-desc br,
    .page-header-hero .page-desc br { display: none; }

    /* Keep "View upcoming releases" text together */
    .hero-cta { white-space: nowrap; min-width: 0; }
    .hero-cta span { white-space: nowrap; }

    /* Star hint tooltip is awkward on small screens — hide it on mobile */
    .game-card.show-star-hint::after,
    .game-card.show-star-hint::before { display: none; }
    .game-card.show-star-hint .game-card-star { animation: none; }

    /* Page header — always stack vertically on mobile */
    .page-header,
    .page-header-hero {
        flex-direction: column;
        align-items: stretch;
        gap: 14px;
    }

    /* Calendar — compact header, ensure grid shows */
    .calendar-header { gap: 12px; }
    .calendar-controls {
        flex-direction: row;
        flex-wrap: wrap;
        justify-content: space-between;
        gap: 8px;
    }
    .nav-controls { flex: 1; }
    .nav-controls .nav-btn { flex: 1; }
    .view-switcher { flex: 1; }
    .view-switcher .view-btn { flex: 1; min-width: 0; padding: 8px 10px; }
    .calendar-month { width: 100%; }

    /* News header — keep timestamp + refresh on one row */
    .page-actions { flex-direction: row; align-items: center; gap: 10px; }
    .news-updated { font-size: 9px; letter-spacing: 0.08em; }

    /* Toolbar on Upcoming — stack vertically for clarity on narrow screens */
    .toolbar {
        flex-direction: column;
        align-items: stretch;
        gap: 10px;
    }
    .toolbar-group {
        display: flex;
        flex-direction: row;
        align-items: center;
        gap: 10px;
        width: 100%;
    }
    .toolbar-label {
        flex-shrink: 0;
        min-width: 60px;
    }
    .toolbar-select {
        flex: 1;
        width: 100%;
    }
    .toolbar-tabs {
        margin-left: 0;
        width: 100%;
        overflow-x: auto;
        scrollbar-width: none;
        gap: 18px;
    }
    .toolbar-tabs::-webkit-scrollbar { display: none; }

    /* === Sidebar becomes bottom tab bar === */
    .sidebar {
        position: fixed;
        bottom: 0;
        left: 0;
        right: 0;
        top: auto;
        height: auto;
        flex-direction: row;
        align-items: stretch;
        padding: 8px 4px calc(8px + env(safe-area-inset-bottom));
        gap: 0;
        border-top: 1px solid var(--border-strong);
        border-right: none;
        background: rgba(7, 5, 15, 0.92);
        backdrop-filter: blur(20px) saturate(180%);
        -webkit-backdrop-filter: blur(20px) saturate(180%);
        z-index: 40;
        overflow: visible;
    }

    .brand { display: none; }

    .sidenav {
        flex-direction: row;
        gap: 2px;
        width: 100%;
        justify-content: space-around;
        align-items: stretch;
    }

    .sidenav-item {
        flex: 1;
        flex-direction: column;
        gap: 3px;
        padding: 6px 4px;
        text-align: center;
        background: transparent !important;
        border-radius: var(--radius-sm);
        max-width: 80px;
        position: relative;
        min-height: 48px;
        justify-content: center;
    }

    /* Re-show labels under icons (override 1000px hide) */
    .sidenav-item span:not(.sidenav-icon):not(.sidenav-count) {
        display: block !important;
        font-size: 9.5px;
        font-weight: 600;
        letter-spacing: 0.04em;
        line-height: 1;
    }

    /* Mobile bottom nav: column layout (icon above, label below). Restore
       the desktop chip pattern on .sidenav-icon — a full-item chip would
       wrap the label too, which reads wrong at this tiny size. */
    .sidenav-icon {
        width: 22px;
        height: 22px;
        padding: 4px;
        box-sizing: content-box;
        border-radius: 8px;
        background: transparent !important;  /* override compact-mode !important */
    }

    .sidenav-item:hover .sidenav-icon,
    .sidenav-item.active .sidenav-icon {
        background: var(--accent) !important;
        filter: none;  /* drop the old drop-shadow — chip is the highlight now */
    }

    .sidenav-item:hover .sidenav-icon svg,
    .sidenav-item.active .sidenav-icon svg { stroke: #fff; }

    .sidenav-item.active::before { display: none; }

    /* Active item: label color stays accent */
    .sidenav-item.active {
        color: var(--accent);
    }

    .sidenav-count {
        position: absolute;
        top: 0;
        right: 50%;
        margin-right: -18px;
        padding: 1px 5px;
        font-size: 8px;
        min-width: 16px;
        line-height: 1.3;
    }

    /* === Main + spacing for bottom nav === */
    .main {
        padding: 0 16px;
        padding-bottom: calc(var(--bottom-nav-h) + env(safe-area-inset-bottom) + 24px);
    }

    .topbar {
        margin: 0 -16px;
        /* iOS standalone PWA: env(safe-area-inset-top) returns the height of
           the notch / Dynamic Island so our content sits BELOW the system
           clock / camera cutout instead of underneath it. Same value works
           across all iPhones — old notch (iPhone X→13), Dynamic Island
           (14 Pro+), and flat status bar (SE). Fallback to 14 px on Android
           or any device where the inset is 0. The desktop topbar rule
           (line ~641) already does this; this mobile override was wiping
           the safe-area calc with a flat `padding: 14px 16px`. */
        padding: calc(14px + env(safe-area-inset-top, 0px)) 16px 14px;
        gap: 8px;
    }

    /* (Breadcrumb mobile rules removed — topbar no longer renders one.) */

    .search-wrap { flex: 1; }
    .search-input {
        width: 100%;
        /* 16px minimum — anything less makes iOS Safari auto-zoom on focus */
        font-size: 16px;
        padding: 10px 14px 10px 36px;
    }

    /* === Hero === */
    .hero {
        padding: 24px 0 32px;
        min-height: auto;
    }

    .hero-tag { font-size: 10px; margin-bottom: 12px; }
    .hero-title { font-size: 38px; margin-bottom: 16px; }
    .hero-desc { font-size: 14px; margin-bottom: 22px; }

    .hero-cta {
        width: 100%;
        justify-content: center;
        padding: 14px 18px;
    }

    /* === Page headers === */
    .page-header {
        padding: 24px 0 18px;
        gap: 12px;
    }

    .page-title { font-size: 32px; }
    .page-desc { font-size: 13px; }

    /* === Section header / filter tabs scrollable === */
    .section-header {
        flex-direction: column;
        align-items: flex-start;
        gap: 14px;
        margin-bottom: 18px;
    }

    .section-title { font-size: 18px; }

    .filter-tabs {
        gap: 18px;
        width: 100%;
        overflow-x: auto;
        padding-bottom: 4px;
        flex-wrap: nowrap;
        scrollbar-width: none;
        -ms-overflow-style: none;
    }
    .filter-tabs::-webkit-scrollbar { display: none; }

    .filter-tab {
        flex-shrink: 0;
        font-size: 13px;
    }

    /* === Cards grid: 2 per row on phones, compact === */
    .card-grid {
        grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
        gap: 12px;
    }

    .game-card-date {
        padding: 6px 8px;
        top: 8px;
        left: 8px;
    }
    .game-card-date-day { font-size: 14px; }
    .game-card-date-month { font-size: 8px; }

    .game-card-cd { font-size: 9px; padding: 3px 7px; bottom: 8px; right: 8px; }

    .game-card-star {
        opacity: 1;
        width: 28px;
        height: 28px;
        top: 8px;
        right: 8px;
    }

    .game-card-body {
        padding: 10px 12px 8px;
        gap: 2px;
    }

    .game-card-title { font-size: 13px; line-height: 1.2; }
    .game-card-genre { font-size: 10px; }

    .game-card-footer {
        padding: 0 12px 12px;
        gap: 6px;
    }

    .game-card-platforms { gap: 8px; }
    .platform-icon { height: 12px; }
    .platform-icon.platform-ps5 { width: 22px; }
    .platform-icon.platform-xbox { width: 18px; }
    .platform-icon.platform-switch { width: 18px; }
    .platform-text { font-size: 9px; }

    /* Hide the arrow — whole card is tappable on mobile, save space for platforms */
    .game-card-arrow { display: none; }
    .game-card-footer { justify-content: flex-start; }

    /* === Modal === */
    .modal-backdrop { padding: 0; align-items: flex-end; }

    .modal {
        max-width: 100%;
        max-height: 92vh;
        border-radius: var(--radius-lg) var(--radius-lg) 0 0;
        animation: modalSlideUp 0.3s var(--ease);
    }

    @keyframes modalSlideUp {
        from { transform: translateY(100%); opacity: 0; }
        to   { transform: translateY(0); opacity: 1; }
    }

    .modal-hero {
        height: 180px;
        border-radius: var(--radius-lg) var(--radius-lg) 0 0;
        font-size: 48px;
    }

    .modal-body { padding: 22px 20px 24px; }
    .modal-title { font-size: 24px; }
    .modal-subtitle { font-size: 13px; margin-bottom: 16px; }
    .countdown-value { font-size: 22px; }
    .modal-info { grid-template-columns: 1fr; gap: 6px; }

    .modal-actions {
        flex-direction: column;
    }
    .action-btn { padding: 14px; }

    /* === Calendar mobile === */
    .calendar-header { flex-direction: column; align-items: stretch; gap: 12px; }
    .calendar-controls { justify-content: space-between; }

    .days-grid { grid-auto-rows: minmax(64px, auto); }
    .day-cell { padding: 4px; gap: 2px; }
    .day-number { font-size: 10px; padding: 2px 5px; }
    .weekday { padding: 8px 4px; font-size: 9px; letter-spacing: 0.12em; }

    .release-card { padding: 3px 4px; font-size: 10px; gap: 3px; }
    .release-icon { width: 16px; height: 16px; }
    .release-name { display: none; }
    .release-countdown { font-size: 8px; }

    /* === Wishlist page === */
    .wishlist-header { flex-direction: column; align-items: stretch; }
    .page-actions { flex-wrap: wrap; gap: 6px; }
    .ghost-btn { flex: 1; justify-content: center; padding: 10px 12px; font-size: 12px; }

    /* === News mobile === */
    .news-card { grid-template-columns: 1fr; min-height: auto; }
    .news-card-media { aspect-ratio: 16 / 9; }

    /* === About modal === */
    .about-modal { padding: 30px 22px 24px; }
    .about-modal h2 { font-size: 26px; }
    .about-row { grid-template-columns: 90px 1fr; padding: 10px 14px; }
}

/* === Extra small phones (≤380px) === */
@media (max-width: 380px) {
    .card-grid { grid-template-columns: repeat(2, 1fr); gap: 10px; }
    .hero-title { font-size: 32px; }
    .page-title { font-size: 26px; }
    .sidenav-item span:not(.sidenav-icon):not(.sidenav-count) { font-size: 9px; }
    .crumb-current { font-size: 14px; }
}

/* Scrollbar */
::-webkit-scrollbar { width: 10px; height: 10px; }
::-webkit-scrollbar-track { background: transparent; }
::-webkit-scrollbar-thumb { background: var(--bg-card-hover); border-radius: 5px; }
::-webkit-scrollbar-thumb:hover { background: var(--accent-soft); }

/* ============================================================
   ============================================================
   v1.1 — UX polish pass
   ============================================================
   ============================================================ */

/* ============================================================
   Accessibility — :focus-visible + prefers-reduced-motion
   ============================================================ */
:focus { outline: none; }

button:focus-visible,
a:focus-visible,
input:focus-visible,
select:focus-visible,
[tabindex]:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 3px;
    border-radius: var(--radius-sm);
}

.game-card:focus-visible,
.news-card:focus-visible,
.release-card:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 4px;
    border-radius: var(--radius-lg);
    box-shadow: 0 0 0 6px rgba(154, 108, 255, 0.18);
}

.search-input:focus-visible {
    outline: none; /* already has its own focused styling */
}

@media (prefers-reduced-motion: reduce) {
    *,
    *::before,
    *::after {
        animation-duration: 0.001ms !important;
        animation-iteration-count: 1 !important;
        transition-duration: 0.001ms !important;
        scroll-behavior: auto !important;
    }
    body::before,
    body::after { animation: none !important; }
    .game-card:hover,
    .news-card:hover { transform: none !important; }
}

/* ============================================================
   Skeleton loaders
   ============================================================ */
.skeleton-grid {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
    gap: 18px;
    width: 100%;
    padding: 8px 0 32px;
}

.skeleton-card {
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: var(--radius-lg);
    overflow: hidden;
    display: flex;
    flex-direction: column;
    min-height: 320px;
    position: relative;
}

.skeleton-card::after {
    content: '';
    position: absolute;
    inset: 0;
    background: linear-gradient(
        90deg,
        transparent 0%,
        rgba(154, 108, 255, 0.08) 50%,
        transparent 100%
    );
    transform: translateX(-100%);
    animation: shimmer 1.6s ease-in-out infinite;
}

.skeleton-media {
    height: 200px;
    background: var(--bg-card-hover);
}

.skeleton-line {
    height: 12px;
    background: var(--bg-card-hover);
    border-radius: 4px;
    margin: 14px;
}
.skeleton-line.short { width: 50%; margin-top: 8px; }
.skeleton-line.medium { width: 75%; }

@keyframes shimmer {
    0%   { transform: translateX(-100%); }
    100% { transform: translateX(100%); }
}

/* ============================================================
   Search dropdown (typeahead)
   ============================================================ */
.search-wrap { position: relative; }

.search-dropdown {
    position: absolute;
    top: calc(100% + 8px);
    left: 0;
    right: 0;
    background: var(--bg-card);
    border: 1px solid var(--border-strong);
    border-radius: var(--radius-lg);
    box-shadow: 0 18px 50px rgba(0, 0, 0, 0.5), 0 0 30px rgba(154, 108, 255, 0.12);
    overflow: hidden;
    z-index: 100;
    animation: dropdownIn 0.2s var(--ease);
    max-height: 480px;
    overflow-y: auto;
    backdrop-filter: blur(20px);
    -webkit-backdrop-filter: blur(20px);
    min-width: 320px;
}

@media (max-width: 700px) {
    .search-dropdown {
        left: 12px;
        right: 12px;
        min-width: 0;
        position: fixed;
        top: 60px;
    }
}

@keyframes dropdownIn {
    from { opacity: 0; transform: translateY(-6px) scale(0.98); }
    to   { opacity: 1; transform: translateY(0) scale(1); }
}

.search-dropdown-section { padding: 6px 0; }
.search-dropdown-section + .search-dropdown-section { border-top: 1px solid var(--divider); }

.search-dropdown-label {
    font-family: 'JetBrains Mono', monospace;
    font-size: 9px;
    font-weight: 700;
    letter-spacing: 0.22em;
    text-transform: uppercase;
    color: var(--text-soft);
    padding: 10px 14px 6px;
    display: flex;
    align-items: center;
    justify-content: space-between;
}

.search-dropdown-label .clear-recent {
    background: none;
    border: none;
    color: var(--text-soft);
    font: inherit;
    cursor: pointer;
    padding: 2px 6px;
    border-radius: 4px;
}
.search-dropdown-label .clear-recent:hover { color: var(--accent); background: var(--bg-card-hover); }

.search-result {
    /* Reset button defaults so it reads as a flat list row, not a stacked card */
    appearance: none;
    -webkit-appearance: none;
    background: transparent;
    border: none;
    border-radius: 0;
    box-shadow: none;
    font: inherit;
    text-align: left;
    width: 100%;
    margin: 0;

    display: flex;
    align-items: center;
    gap: 14px;
    padding: 10px 16px;
    cursor: pointer;
    transition: background 0.18s var(--ease), padding-left 0.18s var(--ease);
    text-decoration: none;
    color: var(--text);
    position: relative;
}

/* Subtle accent stripe on hover/active — replaces the "card" look */
.search-result::before {
    content: '';
    position: absolute;
    left: 0;
    top: 6px;
    bottom: 6px;
    width: 2px;
    background: var(--accent);
    border-radius: 0 2px 2px 0;
    opacity: 0;
    transition: opacity 0.18s var(--ease);
}

.search-result:hover,
.search-result.active {
    background: linear-gradient(to right, rgba(154, 108, 255, 0.10), transparent 70%);
    padding-left: 20px;
}
.search-result:hover::before,
.search-result.active::before {
    opacity: 1;
}

.search-result-cover {
    width: 38px;
    height: 52px;
    border-radius: 4px;
    background-size: cover;
    background-position: center;
    background-color: var(--bg-input);
    flex-shrink: 0;
    border: 1px solid var(--divider);
    overflow: hidden;
    display: flex;
    align-items: center;
    justify-content: center;
    font-family: 'JetBrains Mono', monospace;
    font-size: 11px;
    font-weight: 700;
    color: white;
    letter-spacing: 0;
}

.search-result-body {
    flex: 1;
    min-width: 0;
}

.search-result-name {
    font-size: 14px;
    font-weight: 600;
    letter-spacing: -0.01em;
    margin-bottom: 3px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}
.search-result-name mark {
    background: rgba(154, 108, 255, 0.25);
    color: var(--accent-bright);
    padding: 0 2px;
    border-radius: 3px;
}

.search-result-meta {
    font-family: 'JetBrains Mono', monospace;
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.12em;
    text-transform: uppercase;
    color: var(--text-soft);
}

.search-result.released .search-result-name { color: var(--text-muted); }
.search-result.interested .search-result-name::before {
    content: '★ ';
    color: var(--success);
    font-size: 11px;
}

.search-see-all {
    padding: 10px 14px;
    text-align: center;
    font-family: 'JetBrains Mono', monospace;
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: var(--accent);
    background: var(--bg-input);
    cursor: pointer;
    border: none;
    width: 100%;
    transition: background 0.18s var(--ease);
}
.search-see-all:hover { background: var(--bg-card-hover); }

.recent-chips {
    display: flex;
    flex-wrap: wrap;
    gap: 6px;
    padding: 4px 14px 12px;
}

.recent-chip {
    background: var(--bg-input);
    border: 1px solid var(--border);
    color: var(--text-muted);
    padding: 5px 12px;
    border-radius: var(--radius-pill);
    font-size: 12px;
    font-weight: 500;
    cursor: pointer;
    transition: all 0.18s var(--ease);
}
.recent-chip:hover {
    border-color: var(--accent);
    color: var(--accent);
    background: var(--bg-card-hover);
}

.search-empty {
    padding: 28px 16px;
    text-align: center;
    color: var(--text-muted);
    font-size: 13px;
}
.search-empty strong { display: block; color: var(--text); margin-bottom: 6px; font-size: 14px; }

/* ============================================================
   Search empty state (on page)
   ============================================================ */
.search-empty-state {
    grid-column: 1 / -1;
    display: flex;
    flex-direction: column;
    align-items: center;
    text-align: center;
    padding: 60px 32px;
    color: var(--text-muted);
    animation: cardIn 0.4s var(--ease);
}
.search-empty-state-icon {
    width: 64px;
    height: 64px;
    margin-bottom: 16px;
    color: var(--accent);
    opacity: 0.6;
    filter: drop-shadow(0 0 16px var(--accent-glow));
}
.search-empty-state h3 {
    font-size: 20px;
    font-weight: 700;
    letter-spacing: -0.02em;
    color: var(--text);
    margin-bottom: 8px;
}
.search-empty-state .query {
    color: var(--accent);
    font-family: 'JetBrains Mono', monospace;
    font-size: 0.92em;
    padding: 2px 8px;
    background: var(--bg-input);
    border-radius: 4px;
}
.search-empty-state p { margin-bottom: 20px; max-width: 380px; line-height: 1.55; }
.search-empty-state-actions {
    display: flex;
    gap: 10px;
    flex-wrap: wrap;
    justify-content: center;
}
.search-empty-state-actions button {
    background: var(--bg-input);
    border: 1px solid var(--border-strong);
    color: var(--text);
    padding: 9px 18px;
    border-radius: var(--radius-pill);
    font-family: inherit;
    font-size: 13px;
    font-weight: 600;
    cursor: pointer;
    transition: all 0.2s var(--ease);
}
.search-empty-state-actions button:hover {
    background: var(--bg-card-hover);
    border-color: var(--accent);
    color: var(--accent);
}
.search-empty-state-actions button.primary {
    background: var(--accent);
    border-color: var(--accent);
    color: white;
}
.search-empty-state-actions button.primary:hover {
    background: var(--accent-bright);
    box-shadow: 0 0 18px var(--accent-glow);
}

/* ============================================================
   Body scroll lock (active while modal is open)
   ============================================================ */
body.scroll-locked {
    position: fixed;
    left: 0;
    right: 0;
    width: 100%;
    overflow: hidden;
}

/* ============================================================
   Scroll-to-top button
   ============================================================ */
.scroll-top-btn {
    position: fixed;
    bottom: 28px;
    right: 28px;
    width: 48px;
    height: 48px;
    border-radius: 50%;
    background: var(--accent);
    border: none;
    color: white;
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    box-shadow: 0 8px 28px rgba(0,0,0,0.4), 0 0 24px var(--accent-glow);
    z-index: 90;
    transition: all 0.28s var(--ease);
    opacity: 0;
    transform: translateY(20px) scale(0.85);
    pointer-events: none;
}
.scroll-top-btn.visible {
    opacity: 1;
    transform: translateY(0) scale(1);
    pointer-events: auto;
}
.scroll-top-btn:hover {
    background: var(--accent-bright);
    box-shadow: 0 12px 36px rgba(0,0,0,0.5), 0 0 36px var(--accent-glow-strong);
    transform: translateY(-3px) scale(1.05);
}
.scroll-top-btn svg { width: 22px; height: 22px; }

@media (max-width: 700px) {
    .scroll-top-btn {
        bottom: calc(76px + env(safe-area-inset-bottom));
        right: 16px;
        width: 44px;
        height: 44px;
    }
}

/* ============================================================
   Calendar hover preview popover
   ============================================================ */
.calendar-preview {
    position: fixed;
    z-index: 200;
    background: var(--bg-card);
    border: 1px solid var(--border-strong);
    border-radius: var(--radius-lg);
    padding: 12px;
    box-shadow: 0 18px 40px rgba(0,0,0,0.5), 0 0 30px rgba(154,108,255,0.18);
    backdrop-filter: blur(20px);
    -webkit-backdrop-filter: blur(20px);
    pointer-events: none;
    min-width: 200px;
    max-width: 280px;
    animation: dropdownIn 0.18s var(--ease);
}
.calendar-preview-date {
    font-family: 'JetBrains Mono', monospace;
    font-size: 9px;
    font-weight: 700;
    letter-spacing: 0.22em;
    text-transform: uppercase;
    color: var(--accent);
    margin-bottom: 10px;
}
.calendar-preview-game {
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 6px 0;
}
.calendar-preview-game + .calendar-preview-game {
    border-top: 1px solid var(--divider);
    padding-top: 8px;
    margin-top: 4px;
}
.calendar-preview-cover {
    width: 36px;
    height: 50px;
    border-radius: 4px;
    background-size: cover;
    background-position: center;
    background-color: var(--bg-input);
    flex-shrink: 0;
    border: 1px solid var(--divider);
    display: flex;
    align-items: center;
    justify-content: center;
    color: white;
    font-weight: 700;
    font-size: 11px;
}
.calendar-preview-name {
    font-size: 13px;
    font-weight: 600;
    line-height: 1.25;
    letter-spacing: -0.01em;
}
.calendar-preview-extra {
    font-family: 'JetBrains Mono', monospace;
    font-size: 9px;
    font-weight: 700;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--text-soft);
    margin-top: 6px;
}

/* ============================================================
   Sidebar tooltips (hover delayed bubble)
   ============================================================ */
.sidenav-item[data-tooltip] {
    position: relative;
}

/* Only on desktop layout (sidebar visible, not bottom nav) */
@media (min-width: 701px) {
    .sidenav-item[data-tooltip]::after {
        content: attr(data-tooltip);
        position: absolute;
        left: calc(100% + 12px);
        top: 50%;
        transform: translateY(-50%) translateX(-4px);
        background: var(--bg-card);
        border: 1px solid var(--border-strong);
        color: var(--text);
        padding: 6px 12px;
        border-radius: var(--radius-sm);
        font-family: 'JetBrains Mono', monospace;
        font-size: 10px;
        font-weight: 700;
        letter-spacing: 0.1em;
        text-transform: uppercase;
        white-space: nowrap;
        opacity: 0;
        pointer-events: none;
        transition: opacity 0.22s var(--ease) 0.4s, transform 0.22s var(--ease) 0.4s;
        z-index: 50;
        box-shadow: 0 6px 16px rgba(0,0,0,0.4);
    }
    .sidenav-item[data-tooltip]:hover::after {
        opacity: 1;
        transform: translateY(-50%) translateX(0);
    }
}

/* ============================================================
   Pull-to-refresh (mobile news)
   ============================================================ */
.pull-refresh-indicator {
    position: fixed;
    top: 0;
    left: 0;
    right: 0;
    height: 0;
    display: flex;
    align-items: center;
    justify-content: center;
    background: var(--bg-elevated);
    border-bottom: 1px solid var(--divider);
    transition: height 0.18s var(--ease);
    z-index: 90;
    overflow: hidden;
    pointer-events: none;
}
.pull-refresh-indicator.active { height: 56px; }
.pull-refresh-indicator.refreshing { height: 56px; }

.pull-refresh-spinner {
    width: 22px;
    height: 22px;
    border: 2px solid var(--divider);
    border-top-color: var(--accent);
    border-radius: 50%;
    transition: transform 0.1s linear;
}
.pull-refresh-indicator.refreshing .pull-refresh-spinner {
    animation: spin 0.7s linear infinite;
}
.pull-refresh-label {
    font-family: 'JetBrains Mono', monospace;
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.2em;
    text-transform: uppercase;
    color: var(--text-muted);
    margin-left: 10px;
}

/* ============================================================
   Touch device fixes — kill "sticky :hover" on mobile/tablet
   ============================================================
   On touch devices, :hover gets triggered when the user taps an element and
   stays "stuck" until they tap somewhere else. This causes cards to look
   selected while scrolling, calendar cells to jump around, etc.

   We target devices that DO NOT support real hover OR use coarse pointers
   (phones, tablets, touchscreens) and neutralize all hover-only visual
   transforms there.
   ============================================================ */
@media (hover: none), (pointer: coarse) {
    /* Cards — no lift, no glow, no image scale */
    .game-card:hover,
    .news-card:hover,
    .mini-top-tile:hover,
    .release-card:hover {
        transform: none !important;
        box-shadow: none !important;
        border-color: var(--border) !important;
    }
    .game-card:hover .game-card-img,
    .news-card:hover .news-card-img { transform: none !important; }
    .game-card:hover .game-card-arrow {
        background: transparent !important;
        color: var(--text-muted) !important;
        border-color: var(--border) !important;
        transform: none !important;
    }
    .game-card:hover .game-card-platforms { color: var(--text-muted) !important; }
    .news-card:hover .news-arrow {
        transform: none !important;
        color: var(--text-soft) !important;
    }

    /* Calendar — biggest culprit ("přeskakuje"). Touching a day was scaling
       release cards up and bumping z-index, causing visual jumps during scroll. */
    .day-cell:hover {
        background: transparent !important;
        z-index: auto !important;
        overflow: hidden !important;
    }
    .day-cell:hover .release-card {
        transform: none !important;
        background: var(--bg-card) !important;
        border-color: var(--border) !important;
        box-shadow: none !important;
    }
    .day-cell:hover .release-name {
        white-space: nowrap !important;
        display: block !important;
        -webkit-line-clamp: unset !important;
        -webkit-box-orient: unset !important;
    }

    /* Suppress iOS Safari's blue tap highlight rectangle on all interactive elements */
    a,
    button,
    [role="button"],
    .game-card,
    .news-card,
    .day-cell,
    .release-card,
    .mini-day,
    .mini-top-tile {
        -webkit-tap-highlight-color: transparent;
    }
}

/* ============================================================
   Welcome-back overlay — shown on return after multi-day absence
   when wishlisted games dropped while user was away.
   ============================================================ */
.welcome-back {
    position: fixed;
    inset: 0;
    z-index: 500;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 24px;
    pointer-events: auto;
}

.welcome-back.hidden { display: none; }

.welcome-back-backdrop {
    position: absolute;
    inset: 0;
    background: rgba(7, 5, 15, 0.78);
    backdrop-filter: blur(14px);
    -webkit-backdrop-filter: blur(14px);
    animation: wbBackdropIn 0.32s var(--ease);
}

.welcome-back.closing .welcome-back-backdrop {
    animation: wbBackdropOut 0.28s var(--ease) forwards;
}

@keyframes wbBackdropIn {
    from { opacity: 0; }
    to   { opacity: 1; }
}
@keyframes wbBackdropOut {
    from { opacity: 1; }
    to   { opacity: 0; }
}

.welcome-back-card {
    position: relative;
    z-index: 1;
    background:
        radial-gradient(ellipse 90% 60% at 50% 0%, rgba(154, 108, 255, 0.18), transparent 65%),
        radial-gradient(ellipse 80% 50% at 50% 100%, rgba(42, 224, 122, 0.12), transparent 65%),
        var(--bg-card);
    border: 1px solid var(--border-strong);
    border-radius: var(--radius-xl);
    padding: 40px 36px 32px;
    max-width: 720px;
    width: 100%;
    max-height: 90vh;
    overflow-y: auto;
    box-shadow:
        0 30px 80px rgba(0, 0, 0, 0.6),
        0 0 80px rgba(154, 108, 255, 0.25);
    animation: wbCardIn 0.5s var(--ease-spring);
}

.welcome-back.closing .welcome-back-card {
    animation: wbCardOut 0.28s var(--ease) forwards;
}

@keyframes wbCardIn {
    from { opacity: 0; transform: translateY(40px) scale(0.92); filter: blur(8px); }
    to   { opacity: 1; transform: translateY(0) scale(1); filter: blur(0); }
}
@keyframes wbCardOut {
    from { opacity: 1; transform: translateY(0) scale(1); }
    to   { opacity: 0; transform: translateY(20px) scale(0.96); }
}

.welcome-back-close {
    position: absolute;
    top: 16px;
    right: 16px;
    width: 36px;
    height: 36px;
    border-radius: 50%;
    background: var(--bg-input);
    color: var(--text-muted);
    border: 1px solid var(--border);
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: all 0.2s var(--ease);
}
.welcome-back-close:hover {
    background: var(--bg-card-hover);
    color: var(--text);
    border-color: var(--border-strong);
}
.welcome-back-close svg { width: 18px; height: 18px; }

.welcome-back-tag {
    font-family: 'JetBrains Mono', monospace;
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.24em;
    text-transform: uppercase;
    color: var(--success);
    margin-bottom: 18px;
    display: flex;
    align-items: center;
    gap: 8px;
    animation: wbContentIn 0.5s var(--ease) 0.12s backwards;
}

.welcome-back-tag::before {
    content: '';
    display: inline-block;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--success);
    box-shadow: 0 0 12px var(--success);
    animation: todayPulse 1.6s ease-in-out infinite;
}

.welcome-back-title {
    font-size: clamp(24px, 4vw, 36px);
    font-weight: 800;
    letter-spacing: -0.03em;
    line-height: 1.15;
    color: var(--text);
    margin-bottom: 8px;
    animation: wbContentIn 0.55s var(--ease) 0.18s backwards;
}
.welcome-back-title strong {
    color: var(--success);
    font-weight: 900;
}

.welcome-back-sub {
    color: var(--text-muted);
    font-size: 14px;
    margin-bottom: 28px;
    animation: wbContentIn 0.55s var(--ease) 0.24s backwards;
}

@keyframes wbContentIn {
    from { opacity: 0; transform: translateY(12px); }
    to   { opacity: 1; transform: translateY(0); }
}

.welcome-back-games {
    display: grid;
    grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
    gap: 14px;
    margin-bottom: 24px;
}

.welcome-game {
    /* Reset button defaults since this is interactive */
    appearance: none;
    background: var(--bg-elevated);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    overflow: hidden;
    cursor: pointer;
    display: flex;
    flex-direction: column;
    text-align: left;
    color: inherit;
    font: inherit;
    padding: 0;
    transition: all 0.25s var(--ease);
    /* Stagger entrance per index via CSS variable */
    animation: wbGameIn 0.55s var(--ease) calc(0.32s + var(--i, 0) * 0.07s) backwards;
}

@keyframes wbGameIn {
    from { opacity: 0; transform: translateY(20px) scale(0.94); }
    to   { opacity: 1; transform: translateY(0) scale(1); }
}

.welcome-game:hover {
    border-color: var(--success);
    transform: translateY(-3px);
    box-shadow: 0 12px 28px rgba(0, 0, 0, 0.45), 0 0 20px rgba(42, 224, 122, 0.3);
}

.welcome-game-cover {
    aspect-ratio: 3 / 4;
    background-size: cover;
    background-position: center;
    background-color: var(--bg-input);
    display: flex;
    align-items: center;
    justify-content: center;
    color: white;
    font-family: 'JetBrains Mono', monospace;
    font-weight: 800;
    font-size: 20px;
    letter-spacing: 0.08em;
}

.welcome-game-body {
    padding: 10px 12px 12px;
}

.welcome-game-name {
    font-size: 13px;
    font-weight: 700;
    line-height: 1.25;
    letter-spacing: -0.01em;
    color: var(--text);
    margin-bottom: 4px;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
}

.welcome-game-date {
    font-family: 'JetBrains Mono', monospace;
    font-size: 9px;
    font-weight: 700;
    letter-spacing: 0.16em;
    text-transform: uppercase;
    color: var(--success);
}

.welcome-back-extra {
    text-align: center;
    font-family: 'JetBrains Mono', monospace;
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.18em;
    text-transform: uppercase;
    color: var(--text-muted);
    margin-bottom: 24px;
    animation: wbContentIn 0.5s var(--ease) 0.6s backwards;
}

.welcome-back-actions {
    display: flex;
    gap: 12px;
    flex-wrap: wrap;
    justify-content: center;
    animation: wbContentIn 0.5s var(--ease) 0.7s backwards;
}

.welcome-back-cta {
    display: inline-flex;
    align-items: center;
    gap: 10px;
    padding: 12px 22px;
    border-radius: var(--radius-pill);
    background: var(--bg-input);
    border: 1px solid var(--border-strong);
    color: var(--text);
    font: inherit;
    font-size: 14px;
    font-weight: 600;
    letter-spacing: -0.01em;
    cursor: pointer;
    transition: all 0.22s var(--ease);
}
.welcome-back-cta:hover {
    background: var(--bg-card-hover);
    border-color: var(--accent);
    color: var(--accent);
}
.welcome-back-cta.primary {
    background: var(--accent);
    border-color: var(--accent);
    color: white;
    box-shadow: 0 4px 16px rgba(154, 108, 255, 0.3);
}
.welcome-back-cta.primary:hover {
    background: var(--accent-bright);
    border-color: var(--accent-bright);
    color: white;
    box-shadow: 0 8px 28px var(--accent-glow);
    transform: translateY(-1px);
}
.welcome-back-cta svg { width: 16px; height: 16px; }

@media (max-width: 700px) {
    .welcome-back { padding: 12px; }
    .welcome-back-card {
        padding: 28px 20px 22px;
        max-height: calc(100vh - 80px);
        margin-bottom: 60px;
    }
    .welcome-back-games {
        grid-template-columns: repeat(auto-fill, minmax(130px, 1fr));
        gap: 10px;
    }
    .welcome-back-title { font-size: 22px; }
    .welcome-back-sub { font-size: 13px; margin-bottom: 20px; }
}

@media (prefers-reduced-motion: reduce) {
    .welcome-back-backdrop,
    .welcome-back-card,
    .welcome-back-tag,
    .welcome-back-title,
    .welcome-back-sub,
    .welcome-game,
    .welcome-back-extra,
    .welcome-back-actions {
        animation: none !important;
    }
}

/* ============================================================
   Auth screen (sign in / sign up / magic link)
   ============================================================ */
.auth-screen {
    position: fixed;
    inset: 0;
    z-index: 600;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: 24px;
}
.auth-screen.hidden { display: none; }

.auth-backdrop {
    position: absolute;
    inset: 0;
    background: rgba(7, 5, 15, 0.82);
    backdrop-filter: blur(16px);
    -webkit-backdrop-filter: blur(16px);
    animation: authBackdropIn 0.32s var(--ease);
}
.auth-screen.closing .auth-backdrop {
    animation: authBackdropOut 0.22s var(--ease) forwards;
}
@keyframes authBackdropIn { from { opacity: 0; } to { opacity: 1; } }
@keyframes authBackdropOut { from { opacity: 1; } to { opacity: 0; } }

.auth-card {
    position: relative;
    z-index: 1;
    background:
        radial-gradient(ellipse 90% 60% at 50% 0%, rgba(154, 108, 255, 0.18), transparent 65%),
        var(--bg-card);
    border: 1px solid var(--border-strong);
    border-radius: var(--radius-xl);
    padding: 36px 36px 28px;
    max-width: 420px;
    width: 100%;
    max-height: 92vh;
    overflow-y: auto;
    box-shadow:
        0 30px 80px rgba(0, 0, 0, 0.6),
        0 0 60px var(--accent-glow);
    animation: authCardIn 0.45s var(--ease-spring);
}
.auth-screen.closing .auth-card {
    animation: authCardOut 0.22s var(--ease) forwards;
}
@keyframes authCardIn {
    from { opacity: 0; transform: translateY(28px) scale(0.94); filter: blur(6px); }
    to   { opacity: 1; transform: translateY(0) scale(1); filter: blur(0); }
}
@keyframes authCardOut {
    from { opacity: 1; transform: translateY(0) scale(1); }
    to   { opacity: 0; transform: translateY(16px) scale(0.96); }
}

.auth-brand {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 10px;
    margin-bottom: 28px;
}
.auth-brand-mark {
    width: 34px;
    height: 34px;
    color: var(--accent);
    display: inline-flex;
    filter: drop-shadow(0 0 12px var(--accent-glow));
}
.auth-brand-mark svg { width: 100%; height: 100%; }
.auth-brand-text {
    font-size: 22px;
    font-weight: 800;
    letter-spacing: -0.03em;
    color: var(--text);
}
.auth-brand-text sup {
    font-size: 10px;
    font-weight: 600;
    margin-left: 2px;
    vertical-align: super;
    color: var(--text-muted);
}

.auth-section-title {
    font-family: 'JetBrains Mono', monospace;
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.24em;
    text-transform: uppercase;
    color: var(--text);
    margin-bottom: 8px;
}
.auth-section-sub {
    color: var(--text-muted);
    font-size: 13px;
    line-height: 1.5;
    margin-bottom: 22px;
}

.auth-form {
    display: flex;
    flex-direction: column;
    gap: 6px;
}

.auth-label {
    font-family: 'JetBrains Mono', monospace;
    font-size: 9.5px;
    font-weight: 700;
    letter-spacing: 0.22em;
    text-transform: uppercase;
    color: var(--text-muted);
    margin-top: 8px;
}

.auth-input {
    background: var(--bg-input);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    color: var(--text);
    padding: 12px 14px;
    font-family: inherit;
    font-size: 14px;
    transition: border-color 0.2s var(--ease), box-shadow 0.2s var(--ease);
    /* 16px min on mobile to prevent iOS auto-zoom */
}
.auth-input::placeholder { color: var(--text-soft); }
.auth-input:focus {
    outline: none;
    border-color: var(--accent);
    box-shadow: 0 0 0 3px rgba(154, 108, 255, 0.15);
}
@media (max-width: 700px) {
    .auth-input { font-size: 16px; }
}

/* Password show/hide toggle. The wrapper sits in the normal form flow; the
   eye button is absolutely positioned over the right edge of the input, and
   the input itself gets extra right padding so the typed text never slides
   under the icon. */
.auth-password-wrap {
    position: relative;
    display: flex;
    flex-direction: column;
}
.auth-password-input {
    padding-right: 44px;
    width: 100%;
}
.auth-password-toggle {
    position: absolute;
    top: 50%;
    right: 6px;
    transform: translateY(-50%);
    width: 32px;
    height: 32px;
    display: flex;
    align-items: center;
    justify-content: center;
    background: transparent;
    border: 0;
    border-radius: 8px;
    color: var(--text-soft);
    cursor: pointer;
    transition: color 0.18s var(--ease), background 0.18s var(--ease);
}
.auth-password-toggle:hover {
    color: var(--text);
    background: rgba(154, 108, 255, 0.08);
}
.auth-password-toggle:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
}
.auth-password-eye { width: 18px; height: 18px; display: block; }
/* The SVG contains both an "open eye" group (visible by default) and an
   "off eye" group (hidden by default). Toggling `.showing` on the button
   swaps which group is visible — single source of truth, no DOM rebuild. */
.auth-password-eye .eye-off  { display: none; }
.auth-password-toggle.showing .auth-password-eye .eye-open { display: none; }
.auth-password-toggle.showing .auth-password-eye .eye-off  { display: inline; }

.auth-error {
    background: rgba(255, 92, 122, 0.12);
    border: 1px solid rgba(255, 92, 122, 0.4);
    color: #FF8FA1;
    border-radius: var(--radius-sm);
    padding: 8px 12px;
    font-size: 12px;
    font-weight: 600;
    margin-top: 12px;
    animation: cardIn 0.25s var(--ease);
}
/* Same box reused for a positive confirmation (e.g. after password reset) —
   flip the red palette to green so it doesn't read as an error. */
.auth-error.auth-success {
    background: rgba(42, 224, 122, 0.12);
    border-color: rgba(42, 224, 122, 0.4);
    color: #6EE7A8;
}

/* "Forgot password?" link under the login form. */
.auth-forgot {
    text-align: right;
    margin: 8px 0 0;
    font-size: 12px;
}
.auth-forgot a {
    color: var(--text-muted);
    text-decoration: none;
    font-weight: 600;
}
.auth-forgot a:hover { color: var(--accent-bright); }

.auth-cta {
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 10px;
    width: 100%;
    padding: 12px 18px;
    border-radius: var(--radius);
    background: var(--bg-input);
    border: 1px solid var(--border-strong);
    color: var(--text);
    font: inherit;
    font-size: 14px;
    font-weight: 700;
    cursor: pointer;
    transition: all 0.22s var(--ease);
    margin-top: 16px;
    position: relative;
}
.auth-cta:hover {
    background: var(--bg-card-hover);
    border-color: var(--accent);
    color: var(--accent);
}
.auth-cta.primary {
    background: var(--accent);
    border-color: var(--accent);
    color: white;
    box-shadow: 0 4px 18px rgba(154, 108, 255, 0.32);
}
.auth-cta.primary:hover {
    background: var(--accent-bright);
    border-color: var(--accent-bright);
    color: white;
    box-shadow: 0 8px 28px var(--accent-glow);
    transform: translateY(-1px);
}
.auth-cta.secondary {
    background: transparent;
    color: var(--text);
}
.auth-cta:disabled { cursor: not-allowed; opacity: 0.7; }
.auth-cta svg { width: 18px; height: 18px; }

.auth-cta-spinner {
    display: none;
    width: 16px;
    height: 16px;
    border: 2px solid rgba(255, 255, 255, 0.3);
    border-top-color: white;
    border-radius: 50%;
    animation: spin 0.7s linear infinite;
}
.auth-cta.loading .auth-cta-label { display: none; }
.auth-cta.loading .auth-cta-spinner { display: inline-block; }

.auth-or {
    text-align: center;
    color: var(--text-soft);
    font-size: 12px;
    margin: 18px 0 4px;
    position: relative;
    text-transform: lowercase;
}

.auth-toggle {
    text-align: center;
    font-size: 13px;
    color: var(--text-muted);
    margin-top: 16px;
}
.auth-toggle a {
    color: var(--accent);
    font-weight: 700;
    text-decoration: none;
}
.auth-toggle a:hover { color: var(--accent-bright); text-decoration: underline; }

.auth-divider-line {
    height: 1px;
    background: var(--divider);
    margin: 24px 0 16px;
}

.auth-guest {
    display: block;
    background: none;
    border: none;
    color: var(--text-muted);
    font: inherit;
    font-size: 13px;
    font-weight: 600;
    cursor: pointer;
    margin: 0 auto;
    padding: 6px 12px;
    text-decoration: underline;
    text-decoration-color: var(--text-soft);
    text-underline-offset: 3px;
    transition: color 0.2s var(--ease);
}
.auth-guest:hover { color: var(--text); }

.auth-guest-note {
    text-align: center;
    font-family: 'JetBrains Mono', monospace;
    font-size: 9.5px;
    font-weight: 600;
    letter-spacing: 0.16em;
    color: var(--text-soft);
    margin-top: 6px;
    text-transform: uppercase;
}

/* GDPR consent checkbox in the register form — sits between password and the
   CTA button. Native checkbox is hidden visually via opacity but stays in
   the layout so its `required` attribute still gates the form submit. */
.auth-consent {
    display: flex;
    align-items: flex-start;
    gap: 9px;
    margin: 14px 0 4px;
    font-size: 12.5px;
    line-height: 1.5;
    color: var(--text-muted);
    cursor: pointer;
    user-select: none;
}
.auth-consent input[type="checkbox"] {
    flex-shrink: 0;
    width: 16px;
    height: 16px;
    margin: 2px 0 0;
    accent-color: var(--accent);
    cursor: pointer;
}
.auth-consent a {
    color: var(--accent-bright);
    text-decoration: underline;
    text-underline-offset: 2px;
}
.auth-consent a:hover {
    color: var(--accent);
}

/* Legal links pinned to the bottom of every auth card — discoverable even
   for users who never open the register flow. */
.auth-legal-links {
    text-align: center;
    margin: 10px 0 0;
    font-size: 11px;
    color: var(--text-soft);
    display: flex;
    justify-content: center;
    gap: 8px;
}
.auth-legal-links a {
    color: var(--text-muted);
    text-decoration: none;
}
.auth-legal-links a:hover {
    color: var(--accent-bright);
}

/* Magic-link "check your email" state */
.auth-sent {
    text-align: center;
    padding: 8px 0 4px;
}
.auth-sent-icon {
    width: 56px;
    height: 56px;
    margin: 0 auto 14px;
    color: var(--accent);
    filter: drop-shadow(0 0 18px var(--accent-glow));
}
.auth-sent-icon svg { width: 100%; height: 100%; }
.auth-sent h2 {
    font-size: 22px;
    font-weight: 800;
    letter-spacing: -0.02em;
    margin-bottom: 8px;
}
.auth-sent p {
    color: var(--text-muted);
    font-size: 14px;
    line-height: 1.55;
    margin-bottom: 18px;
}

/* ============================================================
   Sidebar auth widget (sign-in button / user chip)
   ============================================================ */
.sidebar-auth {
    appearance: none;
    background: var(--bg-elevated);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    color: var(--text);
    cursor: pointer;
    display: flex;
    align-items: center;
    gap: 10px;
    padding: 10px 12px;
    /* margin-top: auto removed — the .sidebar-today widget above (also at
       the bottom via its own margin-top: auto) already consumes the auto
       space and sits directly above this widget. Two siblings both with
       margin-top: auto would split the auto space evenly, leaving today
       mid-sidebar instead of paired with auth. */
    margin-top: 0;
    font: inherit;
    font-size: 13px;
    font-weight: 600;
    width: 100%;
    text-align: left;
    transition: all 0.22s var(--ease);
}
.sidebar-auth:hover {
    background: var(--bg-card-hover);
    border-color: var(--accent);
    color: var(--accent);
}

.sidebar-auth-avatar {
    width: 28px;
    height: 28px;
    border-radius: 50%;
    background: linear-gradient(135deg, var(--accent-bright), var(--accent-soft));
    color: white;
    display: flex;
    align-items: center;
    justify-content: center;
    font-weight: 800;
    font-size: 13px;
    flex-shrink: 0;
    overflow: hidden;
    box-shadow: 0 0 12px var(--accent-glow);
}
.sidebar-auth-avatar img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}
.sidebar-auth-avatar.sidebar-auth-icon {
    background: var(--bg-input);
    box-shadow: none;
    color: var(--text-muted);
}
.sidebar-auth-avatar.sidebar-auth-icon svg { width: 14px; height: 14px; }

.sidebar-auth-label {
    flex: 1;
    min-width: 0;
    white-space: nowrap;
    overflow: hidden;
    text-overflow: ellipsis;
    letter-spacing: -0.005em;
}

.sidebar-auth-action {
    color: var(--text-soft);
    font-size: 14px;
    flex-shrink: 0;
}
.sidebar-auth:hover .sidebar-auth-action { color: var(--accent); }

/* Compact (tablet) sidebar — show only avatar */
@media (max-width: 1000px) {
    .sidebar-auth {
        width: 48px;
        height: 48px;
        padding: 0;
        margin: 0 auto;
        justify-content: center;
        position: relative;
    }
    .sidebar-auth-label,
    .sidebar-auth-action { display: none; }
    .sidebar-auth-avatar { box-shadow: none; }
}

/* Mobile (bottom-nav) — auth widget hidden in nav; surface via topbar later */
@media (max-width: 700px) {
    .sidebar-auth { display: none; }
}

/* ============================================================
   Sidebar today widget — current date for context
   ============================================================
   Sits between the nav and the auth widget. The thin top border acts as
   the "rozdělovací čára" separating navigation from the date anchor.
   Layout: small "TODAY" label, then a big day number next to MONTH YEAR · WEEKDAY
   in mono. Populated by renderTodayWidget() in app.js. */
.sidebar-today {
    /* Push to the bottom of the sidebar's flex column so the date widget
       pairs with the auth widget as a "bottom anchor cluster" mirroring the
       brand cluster at the top. Without this the date sits right under the
       nav with a huge blank gap below, which makes it feel orphaned mid-air.
       Auth widget's own margin-top: auto is overridden below — only this
       widget consumes the auto space; auth sits directly after it. */
    margin-top: auto;
    padding-top: 18px;
    padding-left: 4px;
    padding-right: 4px;
    border-top: 1px solid var(--border);
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.sidebar-today-label {
    font-family: 'JetBrains Mono', monospace;
    font-size: 9px;
    font-weight: 700;
    color: var(--text-muted);
    letter-spacing: 0.22em;
    text-transform: uppercase;
}

.sidebar-today-row {
    display: flex;
    align-items: baseline;
    gap: 10px;
}

.sidebar-today-day {
    font-family: 'Inter', sans-serif;
    font-size: 32px;
    font-weight: 800;
    color: var(--text);
    line-height: 0.9;
    letter-spacing: -0.04em;
    /* Subtle violet glow to match the brand language */
    text-shadow: 0 0 18px rgba(154, 108, 255, 0.25);
}

.sidebar-today-meta {
    font-family: 'JetBrains Mono', monospace;
    font-size: 10px;
    font-weight: 700;
    color: var(--text-muted);
    letter-spacing: 0.14em;
    text-transform: uppercase;
}

/* Tablet compact (72px sidebar) — collapse to just the day number, centered.
   Label + meta hidden; the day acts as a tiny "you are here in time" peg. */
@media (max-width: 1000px) {
    .sidebar-today {
        align-items: center;
        padding: 12px 0 0;
    }
    .sidebar-today-label,
    .sidebar-today-meta { display: none; }
    .sidebar-today-day {
        font-size: 22px;
        text-shadow: 0 0 12px rgba(154, 108, 255, 0.35);
    }
}

/* Mobile bottom-nav (≤700px) — no vertical room in the horizontal tab bar
   layout. Hide the widget; users on phones see dates inline on cards. */
@media (max-width: 700px) {
    .sidebar-today { display: none; }
}

/* ============================================================
   Topbar auth button (mobile only — mirrors sidebar widget)
   ============================================================ */
.topbar-auth-btn {
    display: none; /* Hidden on desktop/tablet — sidebar widget covers it */
    padding: 0;
    overflow: hidden;
    position: relative;
    /* Circular — reads as a profile slot, differentiates from About/Theme icons */
    border-radius: 50%;
}

.topbar-auth-btn.has-user {
    background: linear-gradient(135deg, var(--accent-bright), var(--accent-soft));
    color: white;
    border-color: transparent;
    box-shadow: 0 0 12px var(--accent-glow);
}
.topbar-auth-btn.has-user:hover {
    box-shadow: 0 0 18px var(--accent-glow-strong);
    transform: translateY(-1px);
}
.topbar-auth-btn img {
    width: 100%;
    height: 100%;
    object-fit: cover;
    display: block;
}
.topbar-auth-initial {
    font-family: inherit;
    font-weight: 800;
    font-size: 13px;
    letter-spacing: -0.01em;
}

@media (max-width: 700px) {
    .topbar-auth-btn { display: inline-flex; }
}

/* ============================================================
   Profile modal (opened from sidebar user chip)
   ============================================================ */
.profile-modal { padding: 28px 30px 26px; }

.profile-header {
    display: flex;
    align-items: center;
    gap: 18px;
    margin-bottom: 28px;
    padding-bottom: 22px;
    border-bottom: 1px solid var(--divider);
}

.profile-avatar {
    position: relative;
    width: 72px;
    height: 72px;
    border-radius: 50%;
    overflow: hidden;
    cursor: pointer;
    background: linear-gradient(135deg, var(--accent-bright), var(--accent-soft));
    color: white;
    display: flex;
    align-items: center;
    justify-content: center;
    box-shadow: 0 0 28px var(--accent-glow);
    flex-shrink: 0;
}
.profile-avatar img {
    width: 100%;
    height: 100%;
    object-fit: cover;
}
.profile-avatar-initial {
    font-weight: 800;
    font-size: 30px;
    letter-spacing: -0.02em;
}
.profile-avatar-overlay {
    position: absolute;
    inset: 0;
    background: rgba(7, 5, 15, 0.55);
    display: flex;
    align-items: center;
    justify-content: center;
    color: white;
    opacity: 0;
    transition: opacity 0.22s var(--ease);
}
.profile-avatar-overlay svg { width: 24px; height: 24px; }
.profile-avatar:hover .profile-avatar-overlay { opacity: 1; }
.profile-avatar.uploading .profile-avatar-overlay {
    opacity: 1;
    background: rgba(7, 5, 15, 0.7);
}
.profile-avatar.uploading .profile-avatar-overlay svg { display: none; }
.profile-avatar.uploading .profile-avatar-overlay::after {
    content: '';
    width: 22px;
    height: 22px;
    border: 2px solid rgba(255, 255, 255, 0.25);
    border-top-color: white;
    border-radius: 50%;
    animation: spin 0.7s linear infinite;
}

.profile-info { flex: 1; min-width: 0; }
.profile-name {
    font-size: 22px;
    font-weight: 800;
    letter-spacing: -0.025em;
    color: var(--text);
    margin-bottom: 4px;
    line-height: 1.1;
}
.profile-email {
    color: var(--text-muted);
    font-size: 13px;
    word-break: break-all;
}

.profile-section { margin-bottom: 22px; }

.profile-label {
    display: block;
    font-family: 'JetBrains Mono', monospace;
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.22em;
    text-transform: uppercase;
    color: var(--text-muted);
    margin-bottom: 8px;
}

.profile-input-row {
    display: flex;
    gap: 8px;
}
.profile-input {
    flex: 1;
    background: var(--bg-input);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    color: var(--text);
    padding: 11px 14px;
    font-family: inherit;
    font-size: 14px;
    transition: border-color 0.2s var(--ease), box-shadow 0.2s var(--ease);
    min-width: 0;
}
.profile-input:focus {
    outline: none;
    border-color: var(--accent);
    box-shadow: 0 0 0 3px rgba(154, 108, 255, 0.15);
}
@media (max-width: 700px) {
    .profile-input { font-size: 16px; }
}

.profile-save {
    background: var(--accent);
    border: 1px solid var(--accent);
    color: white;
    padding: 0 18px;
    border-radius: var(--radius);
    font: inherit;
    font-weight: 700;
    font-size: 13px;
    cursor: pointer;
    transition: all 0.2s var(--ease);
    white-space: nowrap;
    flex-shrink: 0;
}
.profile-save:hover:not(:disabled) {
    background: var(--accent-bright);
    box-shadow: 0 4px 18px var(--accent-glow);
    transform: translateY(-1px);
}
.profile-save:disabled {
    background: var(--bg-input);
    border-color: var(--border);
    color: var(--text-soft);
    cursor: not-allowed;
    transform: none;
    box-shadow: none;
}

.profile-hint {
    color: var(--text-soft);
    font-size: 11.5px;
    margin-top: 8px;
}

/* The auto-prune dropdown reuses .profile-input padding/border but is a
   <select>, so we strip native UI chrome and draw a small accent-colored
   chevron via two stacked linear-gradients (same pattern as .toolbar-select). */
.profile-select {
    appearance: none;
    -webkit-appearance: none;
    cursor: pointer;
    padding-right: 38px;
    background-image:
        linear-gradient(45deg, transparent 50%, var(--accent) 50%),
        linear-gradient(135deg, var(--accent) 50%, transparent 50%);
    background-position:
        calc(100% - 18px) 50%,
        calc(100% - 14px) 50%;
    background-size: 4px 4px, 4px 4px;
    background-repeat: no-repeat;
}
.profile-select:hover { border-color: var(--accent); }

/* Inline feedback ("Removed 2 games that released …") shown right under the
   dropdown after a prune pass. Soft success-tinted background so it reads as
   confirmation, not as an error. */
.profile-prune-result {
    margin-top: 10px;
    padding: 9px 12px;
    border-radius: var(--radius-sm);
    background: rgba(42, 224, 122, 0.08);
    border: 1px solid rgba(42, 224, 122, 0.22);
    color: var(--success);
    font-size: 12px;
    font-weight: 600;
    line-height: 1.4;
}

.profile-meta {
    background: var(--bg-input);
    border-radius: var(--radius);
    margin-bottom: 22px;
    padding: 0;
}
.profile-meta-row {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 12px 16px;
    gap: 16px;
}
.profile-meta-row + .profile-meta-row {
    border-top: 1px solid var(--divider);
}
.profile-meta-row dt {
    font-family: 'JetBrains Mono', monospace;
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.22em;
    text-transform: uppercase;
    color: var(--text-muted);
    flex-shrink: 0;
}
.profile-meta-row dd {
    font-size: 13px;
    color: var(--text);
    font-weight: 600;
    text-align: right;
    word-break: break-all;
    min-width: 0;
}

.profile-signout {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 10px;
    width: 100%;
    padding: 12px 18px;
    border-radius: var(--radius);
    background: rgba(255, 92, 122, 0.08);
    border: 1px solid rgba(255, 92, 122, 0.28);
    color: var(--danger);
    font: inherit;
    font-size: 14px;
    font-weight: 700;
    cursor: pointer;
    transition: all 0.22s var(--ease);
}
.profile-signout:hover {
    background: rgba(255, 92, 122, 0.16);
    border-color: var(--danger);
    color: var(--danger);
}
.profile-signout svg { width: 17px; height: 17px; }

/* Danger zone — collapsed by default to keep destructive ops behind a click.
   The toggle is a quieter, ghost-style button (no red fill) so it doesn't
   compete visually with Sign out; once expanded, the panel ramps up to a
   stronger red palette to signal the gravity of the action. */
/* Install app section — appears in the profile modal between auto-prune
   and meta. Empty wrapper when the user is already running standalone (the
   section is filled with a tiny "done" chip in that case). */
.profile-install:empty { display: none; }
.profile-install {
    margin-bottom: 22px;
}
.profile-install .profile-label {
    display: block;
    margin-bottom: 8px;
}
.profile-install-card {
    background: var(--bg-input);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 14px 16px;
}
.profile-install-lead {
    margin: 0 0 12px;
    font-size: 13px;
    line-height: 1.55;
    color: var(--text-muted);
}
.profile-install-steps {
    margin: 0;
    padding: 0;
    list-style: none;
    display: flex;
    flex-direction: column;
    gap: 10px;
}
.profile-install-steps li {
    display: flex;
    align-items: flex-start;
    gap: 12px;
    font-size: 13px;
    line-height: 1.5;
    color: var(--text);
}
.profile-install-steps li strong {
    color: var(--accent-bright);
    font-weight: 700;
}
.profile-install-step-icon {
    flex: 0 0 26px;
    width: 26px;
    height: 26px;
    border-radius: 50%;
    background: rgba(154, 108, 255, 0.16);
    color: var(--accent-bright);
    display: flex;
    align-items: center;
    justify-content: center;
}
.profile-install-step-icon svg { width: 14px; height: 14px; }
.profile-install-note {
    margin: 12px 0 0;
    font-size: 12px;
    color: var(--text-soft);
    line-height: 1.5;
}
.profile-install-btn {
    width: 100%;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 10px;
    padding: 12px 18px;
    border-radius: var(--radius);
    background: var(--accent);
    border: 1px solid var(--accent);
    color: #FFFFFF;
    font: inherit;
    font-size: 14px;
    font-weight: 700;
    cursor: pointer;
    transition: all 0.18s var(--ease);
    box-shadow: 0 6px 20px var(--accent-glow);
}
.profile-install-btn:hover {
    background: var(--accent-bright);
    border-color: var(--accent-bright);
    transform: translateY(-1px);
    box-shadow: 0 8px 26px var(--accent-glow-strong);
}
.profile-install-btn:disabled {
    opacity: 0.6;
    cursor: progress;
    transform: none;
}
.profile-install-btn svg { width: 16px; height: 16px; }
.profile-install-done {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    padding: 10px 14px;
    border-radius: var(--radius);
    background: rgba(42, 224, 122, 0.08);
    border: 1px solid rgba(42, 224, 122, 0.32);
    color: var(--success);
    font-size: 12.5px;
    font-weight: 700;
    letter-spacing: 0.05em;
    text-transform: uppercase;
}
.profile-install-done svg { width: 16px; height: 16px; }

/* Notifications opt-in panel. Same card chrome as Install, but the heart of
   it is the toggle row — a horizontal track with a sliding dot that flips
   to accent on enable. The toggle is a real <input type="checkbox"> so it
   stays keyboard- and screen-reader-friendly. */
.profile-notify:empty { display: none; }
.profile-notify { margin-bottom: 22px; }
.profile-notify .profile-label { display: block; margin-bottom: 8px; }
.profile-notify-card {
    background: var(--bg-input);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 14px 16px;
}
.profile-notify-row {
    display: flex;
    align-items: center;
    gap: 14px;
}
.profile-notify-text { flex: 1; min-width: 0; }
.profile-notify-title {
    font-size: 13.5px;
    font-weight: 700;
    color: var(--text);
    margin-bottom: 2px;
}
.profile-notify-sub {
    font-size: 12px;
    line-height: 1.5;
    color: var(--text-muted);
}
.profile-notify-switch {
    position: relative;
    display: inline-block;
    width: 42px;
    height: 24px;
    flex-shrink: 0;
    cursor: pointer;
}
.profile-notify-switch input {
    position: absolute;
    opacity: 0;
    inset: 0;
    margin: 0;
    cursor: pointer;
}
.profile-notify-track {
    position: absolute;
    inset: 0;
    background: var(--bg-card);
    border: 1px solid var(--border-strong);
    border-radius: 999px;
    transition: background 0.2s var(--ease), border-color 0.2s var(--ease);
}
.profile-notify-track::before {
    content: '';
    position: absolute;
    top: 2px;
    left: 2px;
    width: 18px;
    height: 18px;
    border-radius: 50%;
    background: var(--text-muted);
    transition: transform 0.2s var(--ease), background 0.2s var(--ease);
}
.profile-notify-switch input:checked ~ .profile-notify-track {
    background: var(--accent);
    border-color: var(--accent);
}
.profile-notify-switch input:checked ~ .profile-notify-track::before {
    transform: translateX(18px);
    background: #FFFFFF;
}
.profile-notify-switch input:disabled ~ .profile-notify-track {
    opacity: 0.6;
    cursor: progress;
}
.profile-notify-switch input:focus-visible ~ .profile-notify-track {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
}
.profile-notify-error {
    margin: 10px 0 0;
    font-size: 12px;
    color: var(--danger);
}

.profile-danger {
    margin-top: 14px;
    border-top: 1px dashed var(--border);
    padding-top: 14px;
}
.profile-danger-toggle {
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 10px;
    width: 100%;
    padding: 10px 18px;
    border-radius: var(--radius);
    background: transparent;
    border: 1px solid var(--border);
    color: var(--text-muted);
    font: inherit;
    font-size: 13px;
    font-weight: 600;
    cursor: pointer;
    transition: all 0.18s var(--ease);
}
.profile-danger-toggle:hover {
    border-color: rgba(255, 92, 122, 0.35);
    color: var(--danger);
}
.profile-danger-toggle svg { width: 15px; height: 15px; }
.profile-danger-panel {
    margin-top: 14px;
    padding: 16px 16px 14px;
    border-radius: var(--radius);
    background: rgba(255, 92, 122, 0.06);
    border: 1px solid rgba(255, 92, 122, 0.28);
    animation: dangerPanelIn 0.22s var(--ease);
}
@keyframes dangerPanelIn {
    from { opacity: 0; transform: translateY(-4px); }
    to   { opacity: 1; transform: translateY(0); }
}
.profile-danger-warning {
    margin: 0 0 14px;
    font-size: 13px;
    line-height: 1.55;
    color: var(--text);
}
.profile-danger-warning strong { color: var(--danger); }
.profile-danger-panel .profile-label { margin-top: 2px; }
.profile-danger-panel .profile-input { margin-top: 6px; }
.profile-danger-actions {
    display: flex;
    gap: 10px;
    margin-top: 14px;
}
.profile-danger-cancel,
.profile-danger-confirm {
    flex: 1;
    padding: 10px 14px;
    border-radius: var(--radius);
    font: inherit;
    font-size: 13px;
    font-weight: 700;
    cursor: pointer;
    transition: all 0.18s var(--ease);
}
.profile-danger-cancel {
    background: transparent;
    border: 1px solid var(--border);
    color: var(--text-muted);
}
.profile-danger-cancel:hover {
    border-color: var(--border-strong);
    color: var(--text);
}
.profile-danger-confirm {
    background: var(--danger);
    border: 1px solid var(--danger);
    color: #FFFFFF;
    position: relative;
}
.profile-danger-confirm:disabled {
    opacity: 0.4;
    cursor: not-allowed;
}
.profile-danger-confirm:not(:disabled):hover {
    background: #FF3D5E;
    box-shadow: 0 6px 22px rgba(255, 92, 122, 0.32);
}
.profile-danger-confirm-spinner {
    display: none;
    position: absolute;
    inset: 0;
    margin: auto;
    width: 14px; height: 14px;
    border: 2px solid rgba(255,255,255,0.4);
    border-top-color: #FFFFFF;
    border-radius: 50%;
    animation: dangerSpin 0.7s linear infinite;
}
.profile-danger-confirm.loading .profile-danger-confirm-label { visibility: hidden; }
.profile-danger-confirm.loading .profile-danger-confirm-spinner { display: block; }
@keyframes dangerSpin { to { transform: rotate(360deg); } }
.profile-danger-error {
    margin: 10px 0 0;
    font-size: 12.5px;
    color: var(--danger);
}

@media (max-width: 700px) {
    .profile-modal { padding: 22px 18px 20px; }
    .profile-header { gap: 14px; padding-bottom: 18px; margin-bottom: 22px; }
    .profile-avatar { width: 60px; height: 60px; }
    .profile-avatar-initial { font-size: 24px; }
    .profile-name { font-size: 19px; }
}

/* ============================================================
   Mobile/touch perf — backdrop-filter is GPU-heavy on phones.
   When `pointer: coarse` (touch device), swap blurs for solid
   backgrounds so scroll + page transitions stay 60fps.
   ============================================================ */
@media (pointer: coarse) {
    /* Topbar — blur(20px) at sticky position kills mid-range GPUs */
    .topbar {
        backdrop-filter: none;
        -webkit-backdrop-filter: none;
        background: rgba(7, 5, 15, 0.96);
    }
    /* In hybrid mode the SIDEBAR is dark but the main content is light —
       the topbar sits above the light canvas, so it should match the light
       palette here (same as in [data-theme="light"]). Without this override
       the topbar inherits the default dark touch fallback and looks like a
       dark stripe over a light page on iPad/iPhone in hybrid. */
    [data-theme="light"] .topbar,
    [data-theme="hybrid"] .topbar {
        background: rgba(244, 242, 250, 0.96);
    }

    /* Modal entrance perf — backdrop-filter: blur(8px) on a full-viewport
       backdrop AND a 60px accent-glow box-shadow on .modal are both very
       expensive to recompose every frame during the modalIn translate/scale
       animation. On iPad GPUs the combination drops 10-20 fps and reads as
       "choppy pop-up". Drop the blur (bump backdrop opacity so it still
       reads as a focused overlay) and trim the modal glow to a single
       cheap shadow during animation; on desktop the original effect stays. */
    .modal-backdrop {
        backdrop-filter: none;
        -webkit-backdrop-filter: none;
        background: rgba(7, 5, 15, 0.94);
    }
    .modal {
        box-shadow: 0 18px 44px rgba(0, 0, 0, 0.55);
        will-change: transform, opacity;
    }

    /* Modal-close — blur(10px) was previously only stripped at ≤700px (the
       max-width: 700px block below). On iPad it stayed active and added a
       tiny per-frame cost during the modal slide-up. Move it here so any
       touch device gets the cheap solid bg. */
    .modal-close {
        backdrop-filter: none;
        -webkit-backdrop-filter: none;
        background: rgba(7, 5, 15, 0.78);
    }

    /* Countdown badge on every card — blur(8px) × 80 cards in a grid is the
       single biggest GPU cost when scrolling the Upcoming / Releases pages
       on iPad. Star button already had this optimisation; doing the same
       here drops scroll cost dramatically with no visible change (the bg
       opacity goes from 0.78 → 0.92 to compensate for the missing blur). */
    .game-card-cd {
        backdrop-filter: none;
        -webkit-backdrop-filter: none;
        background: rgba(7, 5, 15, 0.92);
    }
}

/* Mobile-only hybrid override — at the phone breakpoint the sidebar
   collapses into a dark bottom tab bar. Pair it with a DARK topbar so the
   light content gets sandwiched between two dark frames (cleaner cockpit
   feel) instead of "light top + dark bottom" mismatch. iPad/tablet hybrid
   stays light (sidebar is vertical on the left, no sandwich available).
   Same var-scoping trick as [data-theme="hybrid"] .sidebar — re-assigning
   the dark palette here makes the search input, icon buttons, and avatar
   chip read with light text/borders, not the inherited light-mode colours. */
@media (max-width: 700px) {
    [data-theme="hybrid"] .topbar {
        background: rgba(7, 5, 15, 0.96);
        --bg: #07050F;
        --bg-elevated: #0E0B1C;
        --bg-card: #110D22;
        --bg-card-hover: #1A1530;
        --bg-input: #15112A;
        --text: #FFFFFF;
        --text-muted: #8E8AA8;
        --text-soft: #524F6E;
        --text-dim: #3A374F;
        --border: rgba(124, 96, 215, 0.12);
        --border-strong: rgba(124, 96, 215, 0.28);
        --divider: rgba(255, 255, 255, 0.04);
        --accent: #9A6CFF;
        --accent-bright: #B891FF;
    }

    /* Star button — repeated 80× in a grid was the worst offender */
    .game-card-star {
        backdrop-filter: none;
        -webkit-backdrop-filter: none;
        background: rgba(7, 5, 15, 0.85);
    }

    /* Modal-close button — also blur, also drops frames during slide-up */
    .modal-close {
        backdrop-filter: none;
        -webkit-backdrop-filter: none;
        background: rgba(7, 5, 15, 0.78);
    }

    /* Search dropdown & calendar preview — only show on touch when explicitly
       opened, but still worth lightening up */
    .search-dropdown,
    .calendar-preview {
        backdrop-filter: blur(8px);
        -webkit-backdrop-filter: blur(8px);
    }
}

/* ============================================================
   Home sign-in callout banner
   Shown to guests on the home page, dismissible per-device.
   ============================================================ */
/* Upcoming hero CTA slot — wraps the calendar deep-link button so the hero
   column has predictable spacing whether or not the JS has populated it yet
   (avoids a flash of layout shift on first paint). */
.upcoming-hero-cta-slot { margin-top: 24px; }

/* ============================================================
   Welcome modal — first-time visitor onboarding
   ============================================================
   Shown once per browser via localStorage gd_welcome_seen. Single
   conversion funnel: intro + 4 feature bullets + sign-in callout +
   skip/CTA buttons. Replaces the inline sign-in callout that used to
   live in the Upcoming hero (too visually heavy on mobile). */
.welcome-modal {
    position: fixed;
    inset: 0;
    z-index: 100;
    display: flex;
    align-items: center;
    justify-content: center;
    padding: clamp(12px, 3vw, 32px);
    /* Respect iOS safe areas so the close X isn't behind the notch
       and the bottom button row isn't behind the home indicator. */
    padding-top: max(clamp(12px, 3vw, 32px), env(safe-area-inset-top));
    padding-bottom: max(clamp(12px, 3vw, 32px), env(safe-area-inset-bottom));
}
.welcome-modal.hidden { display: none; }

.welcome-modal-backdrop {
    position: absolute;
    inset: 0;
    background: rgba(7, 5, 15, 0.78);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    animation: welcomeFadeIn 0.3s var(--ease);
}

.welcome-modal-card {
    position: relative;
    width: 100%;
    max-width: 480px;
    max-height: 100%;
    overflow-y: auto;
    background: var(--bg-elevated);
    border: 1px solid var(--border-strong);
    border-radius: clamp(14px, 2vw, 22px);
    box-shadow:
        0 30px 80px rgba(0, 0, 0, 0.6),
        0 0 60px rgba(154, 108, 255, 0.18);
    padding: clamp(22px, 4vw, 32px) clamp(20px, 4vw, 32px);
    animation: welcomeSlideUp 0.42s var(--ease-spring);
}

@keyframes welcomeFadeIn { from { opacity: 0; } to { opacity: 1; } }
@keyframes welcomeSlideUp {
    from { opacity: 0; transform: translateY(20px) scale(0.97); }
    to   { opacity: 1; transform: translateY(0) scale(1); }
}

.welcome-modal-close {
    position: absolute;
    top: 12px;
    right: 12px;
    width: 32px;
    height: 32px;
    border-radius: 50%;
    background: transparent;
    border: none;
    color: var(--text-soft);
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: all 0.18s var(--ease);
}
.welcome-modal-close:hover {
    background: var(--bg-card-hover);
    color: var(--text);
}
.welcome-modal-close svg { width: 16px; height: 16px; }

.welcome-modal-mark {
    width: 44px;
    height: 22px;
    color: var(--accent);
    margin: 0 auto 14px;
    filter: drop-shadow(0 0 18px var(--accent-glow));
}
.welcome-modal-mark svg { width: 100%; height: 100%; }

.welcome-modal-title {
    font-size: clamp(22px, 4vw, 28px);
    font-weight: 800;
    letter-spacing: -0.02em;
    text-align: center;
    margin-bottom: 8px;
    line-height: 1.15;
}
.welcome-modal-title > span { white-space: nowrap; }
.welcome-modal-lead {
    text-align: center;
    color: var(--text-muted);
    font-size: clamp(13.5px, 1.4vw, 15px);
    line-height: 1.55;
    margin-bottom: 22px;
}

.welcome-modal-features {
    list-style: none;
    padding: 0;
    margin: 0 0 22px;
    display: flex;
    flex-direction: column;
    gap: 12px;
}
.welcome-modal-features li {
    display: flex;
    align-items: flex-start;
    gap: 12px;
}
.welcome-modal-feature-icon {
    flex: 0 0 40px;
    /* Height locked from three sides so nothing in the flex row can stretch
       the box taller than 40px — that was what pushed the glyph "up": the box
       was growing to the 2-line text height while the svg stayed top-anchored. */
    width: 40px;
    height: 40px;
    min-height: 40px;
    max-height: 40px;
    align-self: flex-start;
    box-sizing: border-box;
    /* Centre the 22px glyph purely with symmetric padding — (40 − 22) / 2 = 9.
       With box-sizing: border-box the content box is exactly 22px and the svg
       fills it 100%, so it's dead-centre by construction. No flex/grid/margin
       centering to go wrong. */
    padding: 9px;
    border-radius: 11px;
    background: rgba(154, 108, 255, 0.18);
    color: var(--accent);
    display: block;
}
.welcome-modal-feature-icon svg {
    width: 100%;
    height: 100%;
    display: block;
}
.welcome-modal-features li > div { flex: 1; min-width: 0; }
.welcome-modal-features strong {
    display: block;
    font-size: 13.5px;
    font-weight: 700;
    color: var(--text);
    line-height: 1.25;
    margin-bottom: 2px;
}
.welcome-modal-features span {
    display: block;
    font-size: 12.5px;
    color: var(--text-muted);
    line-height: 1.45;
}

.welcome-modal-signin {
    display: flex;
    align-items: center;
    gap: 14px;
    background:
        radial-gradient(ellipse 60% 100% at 0% 50%, rgba(154, 108, 255, 0.16), transparent 70%),
        var(--bg-card);
    border: 1px solid var(--border-strong);
    border-radius: var(--radius);
    padding: 14px 16px;
    margin-bottom: 18px;
}
/* Cloud-with-down-arrow icon in a violet gradient circle — same visual
   anchor the original home-signin-banner used, ported here so the welcome
   modal's central conversion ask has a clear focal point instead of just
   stacked text. */
.welcome-modal-signin-icon {
    flex: 0 0 42px;
    width: 42px;
    height: 42px;
    border-radius: 50%;
    background: linear-gradient(135deg, var(--accent-bright), var(--accent-soft));
    color: white;
    display: flex;
    align-items: center;
    justify-content: center;
    box-shadow: 0 0 18px var(--accent-glow);
}
.welcome-modal-signin-icon svg { width: 22px; height: 22px; display: block; }
.welcome-modal-signin-body { flex: 1; min-width: 0; }
.welcome-modal-signin-body strong {
    display: block;
    font-size: 13.5px;
    font-weight: 700;
    color: var(--text);
    margin-bottom: 4px;
}
.welcome-modal-signin-body span {
    display: block;
    font-size: 12.5px;
    color: var(--text-muted);
    line-height: 1.5;
}

.welcome-modal-actions {
    display: flex;
    gap: 10px;
    align-items: center;
}
.welcome-modal-skip {
    flex: 0 0 auto;
    padding: 11px 16px;
    border-radius: var(--radius);
    background: transparent;
    border: 1px solid var(--border);
    color: var(--text-muted);
    font: inherit;
    font-size: 13px;
    font-weight: 600;
    cursor: pointer;
    transition: all 0.18s var(--ease);
}
.welcome-modal-skip:hover {
    border-color: var(--border-strong);
    color: var(--text);
}
.welcome-modal-cta {
    flex: 1;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    gap: 8px;
    padding: 12px 20px;
    border-radius: var(--radius);
    background: var(--accent);
    border: 1px solid var(--accent);
    color: white;
    font: inherit;
    font-weight: 700;
    font-size: 14px;
    cursor: pointer;
    transition: all 0.2s var(--ease);
    box-shadow: 0 6px 22px rgba(154, 108, 255, 0.32);
}
.welcome-modal-cta:hover {
    background: var(--accent-bright);
    border-color: var(--accent-bright);
    box-shadow: 0 10px 28px var(--accent-glow-strong);
    transform: translateY(-1px);
}
.welcome-modal-cta svg { width: 14px; height: 14px; }

@media (max-width: 480px) {
    .welcome-modal-actions {
        flex-direction: column-reverse;
        gap: 8px;
    }
    .welcome-modal-skip, .welcome-modal-cta {
        width: 100%;
        flex: initial;
    }
}

.home-signin-banner {
    display: flex;
    align-items: center;
    gap: 18px;
    max-width: 720px;
    width: 100%;
    margin: 32px auto 0;
    padding: 18px 22px;
    background:
        radial-gradient(ellipse 60% 100% at 0% 50%, rgba(154, 108, 255, 0.18), transparent 70%),
        var(--bg-card);
    border: 1px solid var(--border-strong);
    border-radius: var(--radius-lg);
    box-shadow: 0 8px 28px rgba(0, 0, 0, 0.35), 0 0 32px rgba(154, 108, 255, 0.12);
    animation: homeFadeUp 0.6s var(--ease) 0.7s backwards;
    position: relative;
}
.home-signin-banner.hidden { display: none; }

.home-signin-banner-icon {
    width: 40px;
    height: 40px;
    border-radius: 50%;
    flex-shrink: 0;
    background: linear-gradient(135deg, var(--accent-bright), var(--accent-soft));
    color: white;
    display: flex;
    align-items: center;
    justify-content: center;
    box-shadow: 0 0 16px var(--accent-glow);
}
.home-signin-banner-icon svg { width: 22px; height: 22px; }

.home-signin-banner-body {
    flex: 1;
    min-width: 0;
    text-align: left;
}

.home-signin-banner-title {
    font-size: 15px;
    font-weight: 700;
    letter-spacing: -0.015em;
    color: var(--text);
    margin-bottom: 3px;
    line-height: 1.3;
}

.home-signin-banner-desc {
    font-size: 13px;
    color: var(--text-muted);
    line-height: 1.45;
}

.home-signin-banner-cta {
    display: inline-flex;
    align-items: center;
    gap: 8px;
    padding: 10px 18px;
    border-radius: var(--radius-pill);
    background: var(--accent);
    border: 1px solid var(--accent);
    color: white;
    font: inherit;
    font-weight: 700;
    font-size: 13px;
    cursor: pointer;
    transition: all 0.22s var(--ease);
    flex-shrink: 0;
    box-shadow: 0 4px 16px rgba(154, 108, 255, 0.3);
}
.home-signin-banner-cta:hover {
    background: var(--accent-bright);
    border-color: var(--accent-bright);
    box-shadow: 0 8px 24px var(--accent-glow);
    transform: translateY(-1px);
}
.home-signin-banner-cta svg { width: 14px; height: 14px; }

.home-signin-banner-dismiss {
    position: absolute;
    top: 8px;
    right: 8px;
    width: 28px;
    height: 28px;
    border-radius: 50%;
    background: transparent;
    border: none;
    color: var(--text-soft);
    cursor: pointer;
    display: flex;
    align-items: center;
    justify-content: center;
    transition: all 0.18s var(--ease);
}
.home-signin-banner-dismiss:hover {
    background: var(--bg-input);
    color: var(--text);
}
.home-signin-banner-dismiss svg { width: 14px; height: 14px; }

@media (max-width: 700px) {
    .home-signin-banner {
        flex-direction: column;
        align-items: flex-start;
        gap: 14px;
        padding: 18px 18px 16px;
        margin-top: 24px;
    }
    .home-signin-banner-cta {
        width: 100%;
        justify-content: center;
    }
    .home-signin-banner-dismiss {
        top: 12px;
        right: 12px;
    }
    .home-signin-banner-body { padding-right: 32px; }
}

/* ============================================================
   Wishlist sectioned layout — Available now / Upcoming
   ============================================================ */
.wishlist-section {
    margin-bottom: 36px;
}
.wishlist-section.hidden { display: none; }
.wishlist-section:last-child { margin-bottom: 0; }

.wishlist-section-header {
    display: flex;
    align-items: center;
    gap: 12px;
    margin-bottom: 18px;
    padding-bottom: 14px;
    border-bottom: 1px solid var(--divider);
}

.wishlist-section-dot {
    width: 9px;
    height: 9px;
    border-radius: 50%;
    background: var(--accent);
    box-shadow: 0 0 12px var(--accent-glow);
    flex-shrink: 0;
}
.wishlist-section-dot-success {
    background: var(--success);
    box-shadow: 0 0 12px rgba(42, 224, 122, 0.55);
}

.wishlist-section-label {
    font-family: 'JetBrains Mono', monospace;
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.26em;
    text-transform: uppercase;
    color: var(--text);
}

.wishlist-section-count {
    font-family: 'JetBrains Mono', monospace;
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.14em;
    color: var(--text-soft);
    margin-left: auto;
    padding: 3px 10px;
    background: var(--bg-input);
    border: 1px solid var(--border);
    border-radius: var(--radius-pill);
    min-width: 32px;
    text-align: center;
}

.wishlist-empty { width: 100%; }
.wishlist-empty.hidden { display: none; }

@media (max-width: 700px) {
    .wishlist-section { margin-bottom: 28px; }
    .wishlist-section-header {
        margin-bottom: 14px;
        padding-bottom: 12px;
        gap: 10px;
    }
    .wishlist-section-label { font-size: 10px; letter-spacing: 0.22em; }
}

/* ============================================================
   Hero spotlight billboard — cinematic "top game" callout next to
   the page hero. Full-bleed art that fades into the page background
   on the left side, taking up the empty hero space.
   ============================================================ */
.hero-spotlight {
    position: absolute;
    top: 0;
    left: -40px;              /* bleed off both edges so the art reaches the */
    right: -40px;             /* viewport edges, not just the right one */
    bottom: 0;
    min-height: 420px;
    cursor: pointer;
    z-index: 1;
    animation: pageIn 0.6s var(--ease) 0.1s backwards;
    pointer-events: auto;
    /* Clip the scaled background so it can't visually bleed below the hero
       into the section underneath. Full-width layout now uses rounded corners
       on BOTH sides since the art touches both viewport edges. */
    overflow: hidden;
    border-radius: var(--radius-xl);
}
.hero-spotlight.hidden { display: none; }

/* Each rotation slide stacks at inset:0 of .hero-spotlight. Only the .active
   slide is opaque + clickable; others fade out. The 1.2 s crossfade matches
   the cinematic mood (slower than the Upcoming carousel by design). */
.hero-spotlight-slide {
    position: absolute;
    inset: 0;
    opacity: 0;
    pointer-events: none;
    transition: opacity 1.2s var(--ease);
}
.hero-spotlight-slide.active {
    opacity: 1;
    pointer-events: auto;
}

/* Background image — masked on THREE axes (full-width cinematic layout):
   • Horizontally (left):  art is invisible at the left edge, very faint
                           through the title text area (~0–45% width),
                           then ramps up to full visibility around 65%.
                           Title text reads cleanly on near-page-bg darkness.
   • Vertically (bottom):  art fades out at the bottom so it dissolves into
                           the section beneath the hero, no hard line.
   • Horizontally (right): subtle fade so the art doesn't hard-cut against
                           the viewport edge — the classic `do ztracena`.
   mask-composite: intersect combines all three masks so a pixel is visible
   only where ALL masks say "visible". */
.hero-spotlight-bg {
    position: absolute;
    inset: 0;
    background-size: cover;
    background-position: center right;
    background-color: transparent;
    -webkit-mask-image:
        linear-gradient(90deg,
            transparent 0%,
            transparent 32%,
            rgba(0, 0, 0, 0.18) 42%,
            rgba(0, 0, 0, 0.55) 55%,
            black 72%,
            black 100%),
        linear-gradient(180deg,
            black 0%,
            black 55%,
            rgba(0, 0, 0, 0.55) 82%,
            transparent 100%),
        linear-gradient(270deg,
            transparent 0%,
            rgba(0, 0, 0, 0.55) 3%,
            black 12%,
            black 100%);
    -webkit-mask-composite: source-in;
            mask-image:
        linear-gradient(90deg,
            transparent 0%,
            transparent 32%,
            rgba(0, 0, 0, 0.18) 42%,
            rgba(0, 0, 0, 0.55) 55%,
            black 72%,
            black 100%),
        linear-gradient(180deg,
            black 0%,
            black 55%,
            rgba(0, 0, 0, 0.55) 82%,
            transparent 100%),
        linear-gradient(270deg,
            transparent 0%,
            rgba(0, 0, 0, 0.55) 3%,
            black 12%,
            black 100%);
            mask-composite: intersect;
    transform: scale(1.04);
    transition: transform 0.6s var(--ease);
}
.hero-spotlight:hover .hero-spotlight-bg {
    transform: scale(1.07);
}

/* Darken behind text + subtle violet glow. The dark band peaks UNDER the text
   area then eases back to transparent at the very bottom so it blends with the
   page background instead of slamming into a hard line above the next section.
   The mask matches .hero-spotlight-bg so the dark overlay ONLY renders where
   the art is — critical for light mode, where an unmasked dark overlay would
   bleed onto the light page background and create a muddy cloud on the left
   side of the spotlight (the "přechod do ztracena" bug). */
.hero-spotlight-fade {
    position: absolute;
    inset: 0;
    pointer-events: none;
    background:
        linear-gradient(180deg,
            transparent 0%,
            transparent 38%,
            rgba(7, 5, 15, 0.45) 60%,
            rgba(7, 5, 15, 0.70) 78%,
            rgba(7, 5, 15, 0.35) 95%,
            transparent 100%),
        radial-gradient(ellipse 55% 35% at 70% 80%, rgba(154, 108, 255, 0.20), transparent 70%);
    -webkit-mask-image:
        linear-gradient(90deg,
            transparent 0%,
            transparent 32%,
            rgba(0, 0, 0, 0.18) 42%,
            rgba(0, 0, 0, 0.55) 55%,
            black 72%,
            black 100%),
        linear-gradient(180deg,
            black 0%,
            black 55%,
            rgba(0, 0, 0, 0.55) 82%,
            transparent 100%),
        linear-gradient(270deg,
            transparent 0%,
            rgba(0, 0, 0, 0.55) 3%,
            black 12%,
            black 100%);
    -webkit-mask-composite: source-in;
            mask-image:
        linear-gradient(90deg,
            transparent 0%,
            transparent 32%,
            rgba(0, 0, 0, 0.18) 42%,
            rgba(0, 0, 0, 0.55) 55%,
            black 72%,
            black 100%),
        linear-gradient(180deg,
            black 0%,
            black 55%,
            rgba(0, 0, 0, 0.55) 82%,
            transparent 100%),
        linear-gradient(270deg,
            transparent 0%,
            rgba(0, 0, 0, 0.55) 3%,
            black 12%,
            black 100%);
            mask-composite: intersect;
}

/* Text content (★ TAG + game title + countdown) anchors to the RIGHT portion
   of the now full-width spotlight. left: 65% keeps it solidly inside the
   visible-art zone (mask hits full opacity around 72% of container width). */
.hero-spotlight-content {
    position: absolute;
    left: 65%;
    right: 60px;
    bottom: 36px;
    z-index: 2;
    display: flex;
    flex-direction: column;
    gap: 8px;
}

.hero-spotlight-tag {
    font-family: 'JetBrains Mono', monospace;
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.28em;
    text-transform: uppercase;
    color: var(--accent-bright);
    /* Three-layer shadow so the tag stays legible even when the spotlight art
       is bright/yellow (e.g. desert covers): a tight near-black shadow gives a
       readable outline, a wider dark glow lifts it off the art, and the violet
       accent-glow keeps the brand pop. */
    text-shadow:
        0 1px 2px rgba(0, 0, 0, 0.85),
        0 2px 10px rgba(0, 0, 0, 0.7),
        0 0 16px var(--accent-glow);
    margin-bottom: 6px;
}

/* Spotlight text sits on top of a dark cinematic art image — NOT the page
   background. Hardcoded light colors so light-theme users still see legible
   white text on the art (var(--text) becomes dark navy in light mode, which
   reads as "invisible dark blob on dark art"). */
.hero-spotlight-title {
    font-size: clamp(28px, 3.4vw, 44px);
    font-weight: 900;
    letter-spacing: -0.035em;
    line-height: 1.05;
    color: #FFFFFF;
    text-shadow:
        0 2px 4px rgba(0, 0, 0, 0.85),
        0 2px 24px rgba(0, 0, 0, 0.75);
    margin: 0;
}

.hero-spotlight-meta {
    font-size: 14px;
    font-weight: 600;
    color: rgba(255, 255, 255, 0.78);
    text-shadow:
        0 1px 3px rgba(0, 0, 0, 0.85),
        0 1px 8px rgba(0, 0, 0, 0.7);
    margin-top: 4px;
    margin-bottom: 10px;
}

.hero-spotlight-countdown {
    display: inline-flex;
    align-items: baseline;
    gap: 12px;
    padding: 9px 16px;
    /* Bumped from 0.6 → 0.88 alpha so the panel stays uniformly dark even
       when bright key art renders behind it. The old 0.6 looked great on the
       dark page background while the image was still loading, then washed
       out the moment the spotlight image landed — same panel reading as two
       different shades. 0.88 keeps a faint glassmorphism feel through the
       blur but the dark dominates regardless of what's behind. */
    background: rgba(7, 5, 15, 0.88);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    border: 1px solid rgba(154, 108, 255, 0.4);
    border-radius: var(--radius);
    width: fit-content;
    margin-top: 4px;
    box-shadow: 0 8px 24px rgba(0, 0, 0, 0.35);
}
/* Countdown box sits on a dark rgba(7,5,15,0.6) backdrop, so the label/value
   need to stay light regardless of theme — using --text-muted in light mode
   would render as dark gray on the dark countdown bg (poor contrast). */
.hero-spotlight-cd-label {
    font-family: 'JetBrains Mono', monospace;
    font-size: 10px;
    font-weight: 700;
    letter-spacing: 0.22em;
    text-transform: uppercase;
    color: rgba(255, 255, 255, 0.65);
}
.hero-spotlight-cd-value {
    font-family: 'JetBrains Mono', monospace;
    font-size: 15px;
    font-weight: 700;
    letter-spacing: 0.04em;
    color: #B891FF;            /* accent-bright literal — stays violet in light mode */
    font-variant-numeric: tabular-nums;
    text-shadow: 0 0 12px rgba(154, 108, 255, 0.55);
}

/* Medium desktop — only adjust content anchor, the full-width art remains */
@media (max-width: 1400px) {
    .hero-spotlight-content {
        left: 62%;
        right: 48px;
        bottom: 28px;
    }
    .hero-spotlight-title { font-size: clamp(24px, 2.8vw, 36px); }
}

/* Smaller desktop — tighter content position, shorter hero */
@media (max-width: 1200px) {
    .hero-spotlight {
        min-height: 360px;
    }
    .page-header-hero { min-height: 380px; }
    .hero { min-height: 460px; }
    .hero-spotlight-content {
        left: 58%;
        right: 32px;
        bottom: 22px;
    }
    .hero-spotlight-title { font-size: clamp(20px, 2.4vw, 28px); }
    .hero-spotlight-meta { font-size: 12.5px; }
    .hero-spotlight-countdown { padding: 7px 12px; }
    .hero-spotlight-cd-value { font-size: 13px; }
}

/* Below 1000px hide the spotlight — there's no room for it without
   either squishing the art or overlapping the page title */
@media (max-width: 1000px) {
    .hero-spotlight { display: none !important; }
    .page-header-hero { min-height: 0; padding: 36px 0 28px; }
    .hero { min-height: 0; padding: 48px 0 60px; }
}

/* Reduced motion — kill the subtle bg zoom */
@media (prefers-reduced-motion: reduce) {
    .hero-spotlight-bg,
    .hero-spotlight:hover .hero-spotlight-bg { transform: none; }
}

/* (Upcoming page now reuses .hero-spotlight — same cinematic rotating
   component as Releases. The previous banner-carousel styles were
   removed; both pages share the spotlight CSS above.) */

/* ============================================================
   Upcoming page — view toggle (Grid / List). Desktop-only.
   ============================================================ */
.toolbar-view-toggle { gap: 10px; }

.view-toggle {
    display: inline-flex;
    background: var(--bg-card);
    border: 1px solid var(--border);
    border-radius: var(--radius);
    padding: 3px;
    gap: 2px;
}
.view-toggle-btn {
    background: transparent;
    border: none;
    color: var(--text-muted);
    width: 34px;
    height: 30px;
    border-radius: var(--radius-sm);
    cursor: pointer;
    display: inline-flex;
    align-items: center;
    justify-content: center;
    transition: background-color 0.18s var(--ease), color 0.18s var(--ease), box-shadow 0.18s var(--ease);
}
.view-toggle-btn svg { width: 16px; height: 16px; }
.view-toggle-btn:hover { color: var(--accent); }
.view-toggle-btn.active {
    background: var(--accent);
    color: #FFFFFF;
    box-shadow: 0 0 14px var(--accent-glow);
}
.view-toggle-btn.active:hover { color: #FFFFFF; }

/* List view is desktop-only by design — kill it on mobile so the toolbar
   doesn't wrap awkwardly and so the grid stays the canonical mobile UX. */
@media (max-width: 700px) {
    .toolbar-view-toggle { display: none; }
}

/* ============================================================
   Upcoming page — list view rows + month dividers.
   Hidden by default (.hidden); .renderUpcoming() flips visibility.
   ============================================================ */
.upcoming-list {
    display: flex;
    flex-direction: column;
    gap: 38px;
    animation: fadeIn 0.35s var(--ease);
}
.upcoming-list.hidden { display: none; }

.upcoming-list-month {
    display: flex;
    flex-direction: column;
}

/* Dot + label + count header — matches .wishlist-section-header rhythm so the
   page feels visually consistent with the Wishlist split sections. */
.upcoming-list-month-header {
    display: flex;
    align-items: center;
    gap: 12px;
    margin-bottom: 14px;
    padding-bottom: 12px;
    border-bottom: 1px solid var(--divider);
}
.upcoming-list-month-dot {
    width: 9px;
    height: 9px;
    border-radius: 50%;
    background: var(--accent);
    box-shadow: 0 0 12px var(--accent-glow);
    flex-shrink: 0;
}
.upcoming-list-month-label {
    font-family: 'JetBrains Mono', monospace;
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.26em;
    text-transform: uppercase;
    color: var(--text);
}
.upcoming-list-month-count {
    font-family: 'JetBrains Mono', monospace;
    font-size: 11px;
    font-weight: 700;
    letter-spacing: 0.14em;
    color: var(--text-soft);
    margin-left: auto;
    padding: 3px 10px;
    background: var(--bg-input);
    border: 1px solid var(--border);
    border-radius: var(--radius-pill);
    min-width: 32px;
    text-align: center;
}

.upcoming-list-rows {
    display: flex;
    flex-direction: column;
    gap: 8px;
}

/* Single row: date pill | title + genre | platforms. Hover lifts/glides right
   to echo the card-grid's vertical lift without redrawing the whole row. */
.upcoming-list-row {
    display: grid;
    grid-template-columns: 64px 1fr auto;
    align-items: center;
    gap: 20px;
    padding: 12px 18px;
    background: var(--bg-card);
    border: 1px solid var(--divider);
    border-radius: var(--radius);
    cursor: pointer;
    transition: border-color 0.18s var(--ease), transform 0.18s var(--ease), box-shadow 0.18s var(--ease), background 0.18s var(--ease);
    contain: layout paint;
}
.upcoming-list-row:hover {
    border-color: var(--border-strong);
    background: var(--bg-card-hover);
    transform: translateX(4px);
    box-shadow: 0 10px 26px rgba(0, 0, 0, 0.3), 0 0 18px rgba(154, 108, 255, 0.18);
}
.upcoming-list-row:focus-visible {
    outline: 2px solid var(--accent);
    outline-offset: 2px;
}

/* Saved/wishlisted rows get the same green ring as cards for visual parity.
   The whole row body picks up a soft green tint so the wishlist state reads
   at a glance — not just the border. Date pill flips violet → green too,
   otherwise it sticks out as the only non-green chunk in a green row. */
.upcoming-list-row.interested {
    border-color: var(--success);
    background: rgba(42, 224, 122, 0.10);
    box-shadow: 0 0 0 1px var(--success), 0 0 14px rgba(42, 224, 122, 0.22);
}
.upcoming-list-row.interested:hover {
    border-color: var(--success);
    background: rgba(42, 224, 122, 0.16);
    box-shadow:
        0 0 0 1px var(--success),
        0 10px 26px rgba(0, 0, 0, 0.3),
        0 0 22px rgba(42, 224, 122, 0.45);
}
.upcoming-list-row.interested .upcoming-list-date {
    background: var(--success);
    box-shadow: 0 4px 14px rgba(42, 224, 122, 0.45);
}

/* Date pill — same violet block as the grid cards' .game-card-date so users
   recognise the visual language even in a different layout. */
.upcoming-list-date {
    display: flex;
    flex-direction: column;
    align-items: center;
    padding: 7px 6px;
    background: var(--accent);
    color: #FFFFFF;
    border-radius: var(--radius-sm);
    box-shadow: 0 4px 14px var(--accent-glow);
    line-height: 1;
}
.upcoming-list-day {
    font-size: 18px;
    font-weight: 800;
    letter-spacing: -0.02em;
}
.upcoming-list-month-short {
    font-family: 'JetBrains Mono', monospace;
    font-size: 9px;
    font-weight: 700;
    letter-spacing: 0.1em;
    text-transform: uppercase;
    margin-top: 2px;
    opacity: 0.88;
}

.upcoming-list-info {
    display: flex;
    flex-direction: column;
    gap: 3px;
    min-width: 0;
}
.upcoming-list-title {
    font-size: 15px;
    font-weight: 700;
    color: var(--text);
    letter-spacing: -0.02em;
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}
.upcoming-list-genre {
    font-size: 12px;
    color: var(--text-muted);
    overflow: hidden;
    text-overflow: ellipsis;
    white-space: nowrap;
}

.upcoming-list-platforms {
    display: flex;
    align-items: center;
    gap: 12px;
    color: var(--text-muted);
    flex-shrink: 0;
}
.upcoming-list-platforms-none {
    font-family: 'JetBrains Mono', monospace;
    font-size: 11px;
    color: var(--text-soft);
}

/* Mobile: list view is hidden because the toggle button is also hidden.
   Belt-and-braces in case STATE.upcomingView is stale ('list' from desktop). */
@media (max-width: 700px) {
    .upcoming-list { display: none !important; }
    #upcoming-grid { display: grid !important; }
}

/* Light theme intentionally uses the default (dark) mask — same widely-fading
   transition that Hybrid mode uses. We tried tightening the mask in light
   mode to avoid the muddy gradient zone, but the user preferred the softer
   transition look from Hybrid mode applied to Light too. */

/* Light theme — soft outer glow on the hero title so it stays readable where
   the spotlight art bleeds into the text area. The glow uses the page-bg
   colour (#F4F2FA) at fading opacities, creating a halo that's invisible on
   the light page bg but adds contrast against any dark art pixel that drifts
   under the text. Dark mode doesn't need this (dark text on dark art is fine
   because the text is actually light in dark mode). */
[data-theme="light"] .hero-title,
[data-theme="light"] .page-header-hero .page-title {
    text-shadow:
        0 0 8px rgba(244, 242, 250, 0.95),
        0 0 22px rgba(244, 242, 250, 0.75),
        0 0 40px rgba(244, 242, 250, 0.45);
}

/* Same halo on the description text under the title — smaller font, so the
   blur radius is tighter (~6/14/24 instead of 8/22/40). The descriptions
   ("Catch up on the freshest game drops…" / "Games heading our way…") sit
   below the title and similarly graze the spotlight art's transition zone
   on wider viewports. Hero CTA / hero-tag aren't included — the CTA has its
   own violet button bg, the tag is a clear monospace label up top usually
   well above the art band. */
[data-theme="light"] .hero-desc,
[data-theme="light"] .page-header-hero .page-desc {
    text-shadow:
        0 0 6px rgba(244, 242, 250, 0.95),
        0 0 14px rgba(244, 242, 250, 0.75),
        0 0 24px rgba(244, 242, 250, 0.5);
}
