/* ============================================================
   AUDIOPIAN — "NEON STAGE" design system
   ============================================================
   One stylesheet for every page (landing, player, legal).
   Visual language: a concert stage. Twin spotlight beams (cyan
   stage-left, magenta stage-right) sweep a dark venue; the UI is
   the instrument panel. Dark theme = the venue at night; light
   theme = a daylight marquee (same beams, paper surfaces, ink text,
   deepened status inks for contrast).

   Sections:
     1. Design tokens (dark default + light overrides)
     2. Base reset & shared primitives
     3. Shared components (buttons, panels, pills, toggles, footer)
     4. Stage background (ambient beams, vignette, EQ motif)
     5. Landing page            (body.landing)
     6. Legal documents         (body.legal-page)
     7. Player shell            (body.player: header, controls, dock)
     8. Lyrics & word states    (the core feedback loop)
     9. Arcade HUD & ON FIRE
    10. Prep overlay (backstage) & mic check
    11. Count-in (the beat drop)
    12. Results ceremony & confetti
    13. Debug HUD
    14. Motion safety & responsive
   ============================================================ */

/* ============================================================
   1. DESIGN TOKENS
   ============================================================ */
:root {
    /* surfaces — the venue at night */
    --bg:           #06060e;
    --bg-deep:      #04040a;
    --surface:      #0d0f1b;
    --surface-2:    #131628;
    --surface-3:    #1b1f34;
    --line:         rgba(255,255,255,.08);
    --line-strong:  rgba(255,255,255,.16);
    /* legacy semantic aliases (spec-named; resolve via var()) */
    --bg-elev:       var(--surface-2);
    --border:        var(--line);
    --border-strong: var(--line-strong);

    /* text */
    --text:         #e8eaf4;
    --text-dim:     #9a9db2;
    --text-faint:   #64687e;
    --text-strong:  #f7f8fd;

    /* brand accents — cyan x magenta (kept from Neon Arcade) */
    --p:            #2dd4ee;
    --s:            #f0468f;
    --p-ink:        #7fe6f7;   /* accent used AS TEXT on the page bg */
    --s-ink:        #ff7ab3;
    --p-soft:       rgba(45,212,238,.14);
    --p-line:       rgba(45,212,238,.40);
    --s-soft:       rgba(240,70,143,.14);
    --glow-p:       rgba(45,212,238,.45);
    --glow-s:       rgba(240,70,143,.45);

    /* status (semantic, constant app-wide) */
    --matched:      #34e89e;
    /* Partial sits between clear-green and miss-red. ORANGE, not amber: the
       PERFECT gold ramp owns the yellow family now, and the two must be
       tellable apart at a glance mid-song. */
    --partial:      #ff9d4d;
    /* PERFECT-line gold ramp (dark: bright golds against the dark stage) */
    --perfect-1:    #d9a520;
    --perfect-2:    #ffd75e;
    --perfect-3:    #fff3c2;
    --missed:       #ff5d73;
    --key:          var(--p);

    /* fire (warm, fixed — reads as "hot") */
    --fire-a:       #ff5470;
    --fire-b:       #ff9f45;
    --fire-c:       #ffd24a;

    /* shape & type */
    --r:            10px;
    --r-sm:         7px;
    --r-lg:         18px;
    --r-pill:       999px;
    --font:         'Space Grotesk', 'Segoe UI', system-ui, sans-serif;
    --font-display: 'Space Grotesk', 'Segoe UI', system-ui, sans-serif;
    --font-text:    'Inter', 'Segoe UI', system-ui, sans-serif;
    --font-mono:    ui-monospace, 'SF Mono', 'Cascadia Mono', Menlo, Consolas, monospace;

    /* type scale */
    --text-xs:   .72rem;
    --text-sm:   .85rem;
    --text-base: .95rem;
    --text-md:   1.05rem;
    --text-lg:   1.3rem;
    --text-xl:   1.7rem;
    --text-2xl:  2.2rem;
    --text-3xl:  3rem;

    /* spacing scale (4px base) */
    --space-1: 4px;  --space-2: 8px;  --space-3: 12px; --space-4: 16px;
    --space-5: 24px; --space-6: 32px; --space-7: 40px; --space-8: 48px;

    /* neutral gray ramp (dark-oriented; light remaps below) */
    --gray-50:  #101012; --gray-100: #161618; --gray-200: #1d1d20;
    --gray-300: #26262a; --gray-400: #3a3a40; --gray-500: #52525a;
    --gray-600: #71717a; --gray-700: #a0a0a8; --gray-800: #cfcfd6;
    --gray-900: #ededed;

    /* gradients */
    --grad-accent:  linear-gradient(96deg, var(--p), var(--s));
    --grad-fire:    linear-gradient(95deg, var(--fire-a), var(--fire-b), var(--fire-c));
    --grad-grade:   linear-gradient(110deg, var(--p) 5%, var(--s) 55%, var(--matched) 100%);

    /* stage ambience — beam strength + page wash (light theme softens both) */
    --beam-op:      .16;   /* spotlight beam opacity */
    --beam-blur:    90px;  /* static falloff softness, painted once */
    --bg-wash:
        radial-gradient(120% 80% at 100% 0%, rgba(240,70,143,.12), transparent 56%),
        radial-gradient(120% 90% at 0% 100%, rgba(45,212,238,.11), transparent 56%),
        var(--bg);
    --active-glow:  rgba(45,212,238,.10);   /* spotlight behind the active lyric line */

    /* shadows & glows */
    --shadow-card:  0 1px 2px rgba(0,0,0,.4);
    --shadow-modal: 0 24px 60px rgba(0,0,0,.5), inset 0 0 0 1px rgba(255,255,255,.02);
    --shadow-pop:   0 18px 50px -12px rgba(0,0,0,.55);
    --glow-ring-p:  0 0 0 1px var(--p-line), 0 8px 34px -8px var(--glow-p);

    /* player chrome metrics (header/controls heights feed lyric-area sizing) */
    --header-h:     60px;
    --controls-h:   78px;

    /* motion */
    --dur-fast:   120ms;
    --dur-base:   200ms;
    --dur-slow:   360ms;
    --ease-out:   cubic-bezier(.2,.7,.2,1);
    --ease-spring: cubic-bezier(.2,1.3,.4,1);
    --ease-slam:   cubic-bezier(.16,1.45,.32,1);  /* overshoot for grade/count-in beats */
}

/* Light theme — the daylight marquee. Beams + accents stay (identity),
   surfaces flip to paper, status inks deepen so they stay unmistakable
   on white. */
:root[data-theme="light"] {
    --bg:           #f6f5f1;
    --bg-deep:      #efede7;
    --surface:      #ffffff;
    --surface-2:    #f1efe9;
    --surface-3:    #e8e5dc;
    --line:         #e6e3da;
    --line-strong:  #d3cfc2;

    --text:         #191824;
    --text-dim:     #4e4c5e;
    --text-faint:   #8b8899;
    --text-strong:  #0b0a14;

    --p-ink:        #0a8aa8;   /* cyan deepened for text-on-paper contrast */
    --s-ink:        #d61f72;
    --p-soft:       rgba(14,150,180,.12);
    --p-line:       rgba(14,150,180,.45);
    --s-soft:       rgba(214,31,114,.10);
    --glow-p:       rgba(14,150,180,.35);
    --glow-s:       rgba(214,31,114,.35);

    /* status inks deepened: matched green / partial amber / missed red
       must read instantly on white from across the room. */
    --matched:      #0a9e66;
    /* Orange, not amber — the gold ramp owns yellow (see dark-theme note). */
    --partial:      #c25e00;
    /* PERFECT-line gold ramp (light: deeper ambers so the gradient doesn't wash out) */
    --perfect-1:    #8a6400;
    --perfect-2:    #c99a12;
    --perfect-3:    #e8c968;
    --missed:       #e0334a;
    --key:          #0a8aa8;

    --gray-50:  #fafafa; --gray-100: #f5f5f5; --gray-200: #ededed;
    --gray-300: #e4e4e7; --gray-400: #d4d4d8; --gray-500: #a1a1aa;
    --gray-600: #71717a; --gray-700: #52525a; --gray-800: #27272a;
    --gray-900: #0a0a0a;

    --beam-op:      .10;
    --bg-wash:
        radial-gradient(120% 80% at 100% 0%, rgba(240,70,143,.06), transparent 56%),
        radial-gradient(120% 90% at 0% 100%, rgba(45,212,238,.06), transparent 56%),
        var(--bg);
    --active-glow:  rgba(14,150,180,.09);

    --shadow-card:  0 1px 2px rgba(20,16,40,.07);
    --shadow-modal: 0 24px 60px rgba(20,16,40,.16), inset 0 0 0 1px rgba(0,0,0,.02);
    --shadow-pop:   0 18px 50px -16px rgba(20,16,40,.22);
}

/* Animated angle for the rotating gradient border on the landing search
   shell. Registered so keyframes can interpolate it (static fallback in
   engines without @property). */
@property --sbA { syntax: '<angle>'; initial-value: 0deg; inherits: false; }

/* ============================================================
   2. BASE RESET & SHARED PRIMITIVES
   ============================================================ */
* { box-sizing: border-box; margin: 0; padding: 0; }

/* Bare body stays layout-neutral; each page opts into its layout via its
   body class (body.landing / body.player / body.legal-page). Unscoped
   element selectors here have caused cross-page breakage before — keep
   page layout out of this rule. */
body {
    background: var(--bg-wash);
    background-attachment: fixed;
    color: var(--text);
    font-family: var(--font-text);
    min-height: 100vh;
    -webkit-font-smoothing: antialiased;
    text-rendering: optimizeLegibility;
}

::selection { background: var(--p); color: #04121a; }

/* Thin stage-styled page scrollbar (in-game lyric scrollbars stay hidden). */
::-webkit-scrollbar { width: 10px; }
::-webkit-scrollbar-thumb { background: var(--surface-3); border-radius: 6px; border: 2px solid var(--bg); }
::-webkit-scrollbar-track { background: transparent; }

/* Screen-reader-only text (visible labels that would be redundant visually). */
.visually-hidden {
    position: absolute; width: 1px; height: 1px;
    clip-path: inset(50%); overflow: hidden; white-space: nowrap;
}

/* Inline SVG icon sizing (Lucide-style stroke glyphs pasted as raw <svg>). */
.icon {
    width: 1.1em; height: 1.1em;
    display: inline-block; vertical-align: -0.15em; flex-shrink: 0;
    stroke: currentColor; fill: none;
}

/* The brand mark: a rounded square lit like a stage light. */
.logo-dot {
    display: inline-block;
    width: 15px; height: 15px; border-radius: 4px;
    background: var(--grad-accent);
    box-shadow: 0 0 16px var(--glow-p);
    flex-shrink: 0;
}

.wordmark {
    display: inline-flex; align-items: center; gap: var(--space-3);
    font-family: var(--font-display);
    font-size: var(--text-xl); font-weight: 700;
    letter-spacing: .14em; text-transform: uppercase;
    color: var(--text-strong);
}
.wordmark .logo-dot { width: 15px; height: 15px; }

/* Universal keyboard focus ring (keyboard users only). */
:focus-visible {
    outline: none;
    border-radius: var(--r-sm);
    box-shadow: 0 0 0 3px var(--p-soft), 0 0 0 1px var(--p-line);
}

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

/* ============================================================
   3. SHARED COMPONENTS
   ============================================================ */

/* Button system — .btn + variant. (No bare `button {}` rule: page-scoped
   buttons opt in, so transport/pill variants never fight a global default.) */
.btn {
    display: inline-flex; align-items: center; justify-content: center;
    gap: var(--space-2);
    width: auto; padding: 11px 20px;
    border-radius: var(--r); border: 1px solid transparent;
    font-family: var(--font-display);
    font-size: var(--text-base); font-weight: 700; line-height: 1;
    cursor: pointer;
    transition: filter var(--dur-fast), background var(--dur-fast),
                border-color var(--dur-fast), transform var(--dur-fast),
                box-shadow var(--dur-fast);
}
.btn:active { transform: translateY(1px); }
.btn--primary {
    background: var(--grad-accent); color: #04121a;
    box-shadow: 0 6px 24px -8px var(--glow-p);
}
.btn--primary:hover { filter: brightness(1.08); box-shadow: 0 8px 30px -6px var(--glow-p); }
.btn--secondary { background: var(--surface-2); color: var(--text); border-color: var(--line); }
.btn--secondary:hover { background: var(--surface-3); border-color: var(--line-strong); }
.btn--ghost { background: transparent; color: var(--text-dim); }
.btn--ghost:hover { color: var(--text); background: var(--surface-2); }
.btn:disabled { background: var(--surface-2); color: var(--text-faint); cursor: not-allowed; filter: none; box-shadow: none; }

.panel {
    background: var(--surface);
    border: 1px solid var(--line);
    border-radius: var(--r);
    box-shadow: var(--shadow-card);
}

.pill {
    display: inline-flex; align-items: center; gap: var(--space-1);
    padding: 3px 10px; border-radius: var(--r-pill);
    font-size: var(--text-xs); font-weight: 700; letter-spacing: .04em;
}

.chip {
    display: inline-flex; align-items: center; gap: var(--space-1);
    padding: 4px 10px; border-radius: var(--r-sm);
    border: 1px solid var(--line); background: var(--surface-2);
    font-size: var(--text-sm);
}

/* Loading state on any .btn / .search-go: swap the label for a spinner. */
button.is-loading { position: relative; color: transparent !important; }
button.is-loading::after {
    content: '';
    position: absolute; top: 50%; left: 50%;
    width: 16px; height: 16px; margin: -8px 0 0 -8px;
    border: 2px solid rgba(4,18,26,.35); border-top-color: #04121a;
    border-radius: 50%;
    animation: spin .7s linear infinite;
}

/* Theme toggle (fixed top-right by default; headers override to static). */
.theme-toggle {
    position: fixed; top: 14px; right: 14px; z-index: 10000;
    width: 38px; height: 38px; padding: 0;
    display: inline-flex; align-items: center; justify-content: center;
    background: var(--surface-2); border: 1px solid var(--line);
    border-radius: var(--r-pill); color: var(--text-dim); cursor: pointer;
    transition: color var(--dur-fast), border-color var(--dur-fast),
                background var(--dur-fast), box-shadow var(--dur-fast);
}
.theme-toggle:hover { color: var(--text); border-color: var(--line-strong); box-shadow: 0 0 18px -4px var(--glow-p); }
.theme-toggle svg { width: 18px; height: 18px; display: block; }
/* Show sun in dark mode (click -> go light), moon in light mode. */
.theme-toggle .ico-moon { display: none; }
.theme-toggle .ico-sun  { display: block; }
:root[data-theme="light"] .theme-toggle .ico-sun  { display: none; }
:root[data-theme="light"] .theme-toggle .ico-moon { display: block; }

/* Shared site footer. */
.site-footer {
    width: 100%; text-align: center;
    font-size: .78rem; color: var(--text-faint); letter-spacing: .02em;
    position: relative; z-index: 1;
}
.site-footer a { color: var(--text-dim); text-decoration: none; transition: color var(--dur-fast); }
.site-footer a:hover { color: var(--p-ink); text-decoration: underline; }
.site-footer .sep { margin: 0 7px; opacity: .5; }

/* ============================================================
   4. STAGE BACKGROUND — ambient beams, vignette, EQ motif
   Two oversized conic "spotlight" wedges rotate VERY slowly (transform
   only, compositor-cheap) so no screen ever feels dead. One element per
   beam; blur is painted once into the gradient falloff, not a live filter.
   ============================================================ */
.stage-bg {
    position: fixed; inset: 0; z-index: 0;
    overflow: hidden; pointer-events: none;
}
.stage-bg .beam {
    position: absolute; left: 50%; top: 50%;
    width: 160vmax; height: 160vmax;
    margin: -80vmax 0 0 -80vmax;   /* centered, transform-origin mid */
    border-radius: 50%;
    will-change: transform;
}
.stage-bg .beam--p {
    background: conic-gradient(from 205deg,
        transparent 0deg, rgba(45,212,238,var(--beam-op)) 22deg,
        transparent 64deg, transparent 360deg);
    animation: beamSweepP 110s linear infinite;
}
.stage-bg .beam--s {
    background: conic-gradient(from 118deg,
        transparent 0deg, rgba(240,70,143,var(--beam-op)) 20deg,
        transparent 60deg, transparent 360deg);
    animation: beamSweepS 140s linear infinite;
}
@keyframes beamSweepP { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }
@keyframes beamSweepS { from { transform: rotate(360deg); } to { transform: rotate(0deg); } }
/* Soft floor glow where the beams "land" + a vignette to seat the stage. */
.stage-bg .stage-floor {
    position: absolute; left: 0; right: 0; bottom: 0; height: 34vh;
    background:
        radial-gradient(90% 100% at 50% 130%, rgba(45,212,238,.10), transparent 60%),
        radial-gradient(70% 100% at 85% 130%, rgba(240,70,143,.09), transparent 60%);
}
.stage-bg .stage-vignette {
    position: absolute; inset: 0;
    background: radial-gradient(120% 90% at 50% 40%, transparent 55%, rgba(0,0,0,.38) 100%);
}
:root[data-theme="light"] .stage-bg .stage-vignette {
    background: radial-gradient(120% 90% at 50% 40%, transparent 60%, rgba(60,50,90,.08) 100%);
}

/* Equalizer-bar motif (landing footer strip + count-in). Bars animate
   scaleY with staggered delays — transform only. */
.eq {
    display: flex; align-items: flex-end; justify-content: center;
    gap: 5px; height: 34px;
}
.eq i {
    width: 4px; height: 100%; border-radius: 2px;
    background: linear-gradient(180deg, var(--p), var(--s));
    transform-origin: 50% 100%;
    animation: eqBounce 1.1s ease-in-out infinite;
    opacity: .8;
}
.eq i:nth-child(4n+1) { animation-duration: .9s; }
.eq i:nth-child(4n+2) { animation-duration: 1.3s; animation-delay: .12s; }
.eq i:nth-child(4n+3) { animation-duration: 1s;   animation-delay: .24s; }
.eq i:nth-child(4n+4) { animation-duration: 1.5s; animation-delay: .06s; }
.eq i:nth-child(3n)   { animation-delay: .3s; }
@keyframes eqBounce {
    0%, 100% { transform: scaleY(.18); }
    50%      { transform: scaleY(1); }
}

/* ============================================================
   5. LANDING PAGE (body.landing) — the marquee
   ============================================================ */
body.landing { display: block; padding: 0 20px 40px; }

.landing-top {
    position: relative; z-index: 1;
    max-width: 1160px; margin: 0 auto;
    display: flex; align-items: center; justify-content: space-between;
    padding: 22px 0;
}
.landing-top .wordmark { font-size: var(--text-lg); }
.landing-top .theme-toggle { position: static; }

.hero {
    position: relative; z-index: 1;
    max-width: 880px; margin: 0 auto;
    text-align: center;
    padding-top: clamp(28px, 7vh, 88px);
}

/* Staged entrance: each direct child of .hero rises in sequence
   (transform+opacity). Delays choreograph kicker -> title -> tagline ->
   search -> starters -> backstage. Reduced-motion guard collapses them. */
.hero > * { animation: heroRise .7s var(--ease-out) both; }
.hero > *:nth-child(1) { animation-delay: .05s; }
.hero > *:nth-child(2) { animation-delay: .14s; }
.hero > *:nth-child(3) { animation-delay: .24s; }
.hero > *:nth-child(4) { animation-delay: .36s; }
.hero > *:nth-child(5) { animation-delay: .48s; }
.hero > *:nth-child(6) { animation-delay: .58s; }
@keyframes heroRise {
    from { opacity: 0; transform: translateY(26px); }
    to   { opacity: 1; transform: translateY(0); }
}

.hero-kicker {
    display: inline-flex; align-items: center; gap: 10px;
    font-family: var(--font-display);
    font-size: var(--text-xs); font-weight: 700;
    letter-spacing: .3em; text-transform: uppercase;
    color: var(--p-ink);
    padding: 8px 18px; border: 1px solid var(--p-line); border-radius: var(--r-pill);
    background: var(--p-soft);
}
.hero-kicker .logo-dot { width: 9px; height: 9px; border-radius: 3px; box-shadow: 0 0 10px var(--glow-p); }

.hero-title {
    margin-top: 26px;
    font-family: var(--font-display);
    font-size: clamp(3rem, 9.5vw, 6.8rem);
    font-weight: 700; line-height: .96;
    letter-spacing: -.02em; text-transform: uppercase;
    color: var(--text-strong);
    text-wrap: balance;
}
.hero-title .hl {
    background: var(--grad-accent);
    -webkit-background-clip: text; background-clip: text;
    -webkit-text-fill-color: transparent; color: transparent;
    filter: drop-shadow(0 0 26px var(--glow-p));
}

.tagline {
    margin: 22px auto 0; max-width: 34rem;
    font-size: var(--text-md); color: var(--text-dim); line-height: 1.6;
}
.tagline-sub {
    display: block; margin-top: 6px;
    font-size: var(--text-xs); color: var(--text-faint);
    letter-spacing: .18em; text-transform: uppercase;
}

/* -- The search bar IS the centerpiece: a rotating conic-gradient shell
      (registered --sbA angle) around a pill input + go button. -- */
.search-stage { margin-top: 40px; }
.search-shell {
    max-width: 640px; margin: 0 auto;
    padding: 2px; border-radius: var(--r-pill);
    background: conic-gradient(from var(--sbA),
        var(--p), var(--s), var(--matched), var(--p));
    animation: sbSpin 6s linear infinite;
    box-shadow: 0 12px 44px -12px var(--glow-p), 0 4px 18px -6px var(--glow-s);
    transition: box-shadow var(--dur-base), transform var(--dur-base);
}
.search-shell:focus-within {
    box-shadow: 0 16px 60px -10px var(--glow-p), 0 6px 26px -4px var(--glow-s);
    transform: translateY(-1px);
}
@keyframes sbSpin { to { --sbA: 360deg; } }
.search-bar {
    display: flex; align-items: center; gap: 8px;
    background: var(--surface); border-radius: var(--r-pill);
    padding: 6px 6px 6px 22px;
}
.search-bar .search-ico { color: var(--text-faint); flex-shrink: 0; display: inline-flex; }
.search-bar input {
    flex: 1; min-width: 0;
    background: transparent; border: none; outline: none;
    color: var(--text); font-family: var(--font-text);
    font-size: 1.08rem; padding: 12px 4px;
}
.search-bar input::placeholder { color: var(--text-faint); }
.search-go {
    flex-shrink: 0;
    padding: 13px 30px; border: none; border-radius: var(--r-pill);
    background: var(--grad-accent); color: #04121a;
    font-family: var(--font-display); font-size: .98rem; font-weight: 700;
    letter-spacing: .06em; text-transform: uppercase; cursor: pointer;
    transition: filter var(--dur-fast), transform var(--dur-fast);
}
.search-go:hover { filter: brightness(1.1); }
.search-go:active { transform: scale(.97); }
.search-go:disabled { filter: saturate(.4) brightness(.8); cursor: wait; }

/* Unified status messages (#status + #searchStatus share one treatment). */
#status, #searchStatus {
    margin-top: var(--space-4);
    text-align: center; font-size: var(--text-base);
    min-height: 1.2em; color: var(--text-dim); line-height: 1.5;
}
#searchStatus { margin-top: var(--space-3); }
#status.error,   #searchStatus.error   { color: var(--missed); }
#status.success, #searchStatus.success { color: var(--matched); }

/* -- Results & starter rows: "setlist cards". Each card slides up as it
      enters (staggered by DOM order); hover lifts + lights the edge. -- */
.search-results {
    display: none;
    max-width: 640px; margin: 16px auto 0;
    text-align: left;
}
.search-result-item {
    display: flex; align-items: center; gap: var(--space-3);
    padding: 12px 14px; margin-bottom: 10px;
    background: var(--surface);
    border: 1px solid var(--line); border-radius: 14px;
    cursor: pointer;
    animation: resultIn .45s var(--ease-out) both;
    transition: transform var(--dur-fast), border-color var(--dur-fast),
                box-shadow var(--dur-fast), background var(--dur-fast);
}
.search-result-item:nth-child(2) { animation-delay: .05s; }
.search-result-item:nth-child(3) { animation-delay: .1s; }
.search-result-item:nth-child(4) { animation-delay: .15s; }
.search-result-item:nth-child(5) { animation-delay: .2s; }
.search-result-item:nth-child(6) { animation-delay: .25s; }
.search-result-item:nth-child(7) { animation-delay: .3s; }
@keyframes resultIn {
    from { opacity: 0; transform: translateY(14px); }
    to   { opacity: 1; transform: translateY(0); }
}
.search-result-item:hover, .search-result-item:focus-visible {
    transform: translateY(-2px);
    border-color: var(--p-line);
    box-shadow: var(--glow-ring-p);
    background: var(--surface);
}
.search-result-item.is-best {
    border-color: var(--p-line);
    box-shadow: var(--glow-ring-p);
}
.sr-thumb {
    width: 96px; height: 54px; border-radius: 10px; object-fit: cover;
    background: var(--surface-3); flex-shrink: 0;
    transition: transform var(--dur-base) var(--ease-out);
}
.search-result-item:hover .sr-thumb { transform: scale(1.06); }
.sr-thumb-ph {
    display: inline-flex; align-items: center; justify-content: center;
    color: var(--p-ink);
    background:
        radial-gradient(120% 120% at 20% 0%, var(--p-soft), transparent 60%),
        var(--surface-3);
}
.sr-thumb-ph .icon { width: 20px; height: 20px; }
.sr-text { min-width: 0; flex: 1; }
.search-result-title {
    font-size: .98rem; font-weight: 600; color: var(--text-strong);
    margin-bottom: 2px;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.search-result-meta { font-size: .8rem; color: var(--text-faint); line-height: 1.5; }
.sr-best-pill {
    background: var(--grad-accent); color: #04121a;
    vertical-align: middle; white-space: nowrap;
}
.sr-best-pill .icon { width: .85em; height: .85em; }

/* Section divider with gradient hairlines. */
.search-divider {
    display: flex; align-items: center; gap: 16px;
    max-width: 640px; margin: 34px auto 18px;
    font-family: var(--font-display);
    color: var(--text-faint); font-size: .74rem; font-weight: 700;
    letter-spacing: .22em; text-transform: uppercase;
}
.search-divider::before, .search-divider::after {
    content: ''; flex: 1; height: 1px;
}
.search-divider::before { background: linear-gradient(90deg, transparent, var(--p-line)); }
.search-divider::after  { background: linear-gradient(90deg, var(--p-line), transparent); }

#starterRow { margin-top: 8px; }
#starterList { display: none; }

/* -- Backstage: the secondary lanes (paste fallback / local file / BYO key).
      Deliberately quieter than the hero — smaller panels, dimmer labels. -- */
.backstage {
    max-width: 640px; margin: 44px auto 0;
    display: grid; gap: 18px; text-align: left;
}
.backstage-panel {
    background: color-mix(in srgb, var(--surface) 82%, transparent);
    border: 1px solid var(--line); border-radius: var(--r-lg);
    padding: 20px 22px;
}
.backstage-title {
    font-family: var(--font-display);
    font-size: var(--text-xs); font-weight: 700;
    letter-spacing: .2em; text-transform: uppercase;
    color: var(--text-faint); margin-bottom: 14px;
}
.backstage label {
    display: block; font-size: .68rem; font-weight: 600;
    color: var(--text-dim); text-transform: uppercase;
    letter-spacing: .12em; margin-bottom: 7px;
}
.backstage input[type="text"],
.backstage input[type="password"],
.backstage input[type="file"] {
    width: 100%; padding: 11px 13px;
    background: var(--surface-2); border: 1px solid var(--line);
    border-radius: var(--r); color: var(--text);
    font-size: .95rem; font-family: inherit;
    margin-bottom: 14px;
    transition: border-color .15s, box-shadow .15s;
}
.backstage input::placeholder { color: var(--text-faint); }
.backstage input[type="text"]:focus,
.backstage input[type="password"]:focus {
    outline: none; border-color: var(--p);
    box-shadow: 0 0 0 3px var(--p-soft);
}
.backstage input[type="file"]::file-selector-button {
    margin-right: 12px; padding: 7px 14px;
    background: var(--surface-3); color: var(--text);
    border: 1px solid var(--line-strong); border-radius: var(--r-sm);
    font-family: var(--font-display); font-weight: 700; font-size: .8rem;
    cursor: pointer;
}
.form-hint {
    font-size: var(--text-sm); color: var(--text-faint);
    margin: calc(var(--space-2) * -1) 0 var(--space-3); line-height: 1.5;
}
.backstage .btn { width: 100%; }
.backstage .btn + .btn { margin-top: 10px; }

/* BYO-key disclosure — the quietest lane (a <details> drawer). */
.byok { padding: 0; }
.byok summary {
    cursor: pointer; list-style: none;
    font-family: var(--font-display);
    font-size: .82rem; font-weight: 700; letter-spacing: .1em; text-transform: uppercase;
    color: var(--text-dim);
    padding: 18px 22px;
    transition: color var(--dur-fast);
}
.byok summary:hover { color: var(--text); }
.byok summary::-webkit-details-marker { display: none; }
.byok summary::before { content: '+ '; color: var(--p-ink); font-weight: 700; }
.byok[open] summary::before { content: '- '; }
.byok .byok-body { padding: 0 22px 20px; }
.byok-actions { display: flex; gap: 8px; }
.byok-actions .btn { width: auto; }
.byok-note { font-size: .75rem; color: var(--text-faint); margin-top: 10px; line-height: 1.5; }

/* Landing EQ strip at the foot of the hero. */
.landing-eq { margin: 56px auto 0; max-width: 420px; opacity: .55; }

/* -- Desktop-only interstitial (display toggled inline by script). -- */
.unsupported-overlay {
    position: fixed; inset: 0; z-index: 9999;
    background:
        radial-gradient(120% 80% at 100% 0%, rgba(240,70,143,.14), transparent 56%),
        radial-gradient(120% 90% at 0% 100%, rgba(45,212,238,.13), transparent 56%),
        var(--bg-deep);
    color: var(--text);
    align-items: center; justify-content: center;
    text-align: center; padding: 2rem;
}
.unsupported-box {
    max-width: 30rem; padding: var(--space-7) var(--space-6);
    display: flex; flex-direction: column; align-items: center; gap: var(--space-4);
    text-align: center; border-radius: var(--r-lg);
}
.unsupported-box .logo-dot { width: 20px; height: 20px; border-radius: var(--r-sm); }
.unsupported-box h2 { font-family: var(--font-display); color: var(--text-strong); font-size: var(--text-xl); }
.unsupported-box p { max-width: 32rem; line-height: 1.6; color: var(--text-dim); }
.unsupported-box strong { color: var(--p-ink); }

/* ============================================================
   6. LEGAL DOCUMENTS (body.legal-page) — clean sheets on the stage
   ============================================================ */
body.legal-page { display: block; padding: 56px 20px 72px; }
.legal {
    max-width: 760px; margin: 0 auto;
    background: var(--surface);
    border: 1px solid var(--line); border-radius: var(--r-lg);
    padding: 44px 48px;
    box-shadow: var(--shadow-modal);
    font-family: var(--font-text);
    animation: heroRise .5s var(--ease-out) both;
}
.legal .doc-home {
    display: inline-flex; align-items: center; gap: var(--space-2);
    font-family: var(--font-display);
    color: var(--text-strong); font-weight: 700;
    letter-spacing: .12em; text-transform: uppercase;
    font-size: var(--text-base); text-decoration: none;
}
.legal .doc-home .logo-dot { width: 13px; height: 13px; }
.legal h1.doc-title {
    font-family: var(--font-display);
    font-size: var(--text-xl); text-align: left;
    margin: var(--space-5) 0 var(--space-1);
    color: var(--text-strong);
}
.legal .updated { color: var(--text-faint); font-size: .8rem; margin-bottom: 10px; }
.legal .lede { color: var(--text-dim); font-size: .95rem; line-height: 1.6; margin-bottom: 8px; }
.legal h2 {
    font-family: var(--font-display);
    font-size: var(--text-md); color: var(--text-strong);
    margin: var(--space-6) 0 var(--space-2); letter-spacing: .01em;
}
.legal p { color: var(--text); font-size: 1rem; line-height: 1.7; margin-bottom: var(--space-3); }
.legal ul, .legal ol { margin: 0 0 var(--space-3) var(--space-5); }
.legal li { color: var(--text); font-size: 1rem; line-height: 1.7; margin-bottom: var(--space-2); }
.legal a { color: var(--p-ink); text-decoration: none; }
.legal a:hover { text-decoration: underline; }
.legal strong { color: var(--text); }
.legal .callout {
    background: var(--p-soft); border: 1px solid var(--p-line);
    border-radius: var(--r); padding: 14px 16px; margin: 0 0 22px;
}
.legal .callout p { color: var(--text); margin: 0; }
.legal .disclaimer {
    border-top: 1px solid var(--line); margin-top: 28px; padding-top: 16px;
    font-size: .8rem; color: var(--text-faint);
}
.legal .doc-nav { margin-top: 22px; padding-top: 16px; border-top: 1px solid var(--line); font-size: .85rem; }
.legal .doc-nav a { color: var(--text-dim); text-decoration: none; margin-right: 18px; }
.legal .doc-nav a:hover { color: var(--p-ink); text-decoration: underline; }
body.legal-page .site-footer { max-width: 760px; margin: var(--space-7) auto 0; }

/* ============================================================
   7. PLAYER SHELL (body.player) — header, transport, video dock
   ============================================================ */
body.player { display: block; padding: 0; }

.player-header {
    position: fixed; top: 0; left: 0; right: 0; z-index: 100;
    height: var(--header-h);
    display: flex; align-items: center; gap: 14px;
    padding: 0 18px;
    background: color-mix(in srgb, var(--surface) 82%, transparent);
    backdrop-filter: blur(14px);
    -webkit-backdrop-filter: blur(14px);
    border-bottom: 1px solid var(--line);
}
.player-header .theme-toggle { position: static; flex-shrink: 0; }

.back-btn {
    display: inline-flex; align-items: center; gap: 7px;
    width: auto; padding: 8px 15px; flex-shrink: 0;
    font-size: .85rem;
}

/* Generic in-game secondary button (header, prep toolbar, mic check). */
.ctrl-btn {
    display: inline-flex; align-items: center; justify-content: center; gap: 7px;
    width: auto; padding: 8px 14px; flex-shrink: 0;
    background: var(--surface-2); color: var(--text);
    border: 1px solid var(--line); border-radius: var(--r-sm);
    font-family: var(--font-display); font-size: .9rem; font-weight: 600;
    cursor: pointer;
    transition: background var(--dur-fast), border-color var(--dur-fast),
                box-shadow var(--dur-fast), transform var(--dur-fast);
}
.ctrl-btn:hover { background: var(--surface-3); border-color: var(--line-strong); box-shadow: 0 4px 18px -6px var(--glow-p); }
.ctrl-btn:active { transform: translateY(1px); }

.player-wordmark {
    display: inline-flex; align-items: center; gap: var(--space-2);
    font-family: var(--font-display);
    font-size: var(--text-sm); font-weight: 700;
    letter-spacing: .14em; text-transform: uppercase;
    color: var(--text-dim); flex-shrink: 0;
}
.player-wordmark .logo-dot { width: 11px; height: 11px; border-radius: var(--r-sm); }

.song-title {
    flex: 1; min-width: 0;
    font-family: var(--font-display);
    font-size: 1.02rem; color: var(--text); font-weight: 600;
    letter-spacing: -.01em;
    white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}

.diff-pill {
    flex-shrink: 0;
    font-size: .62rem; font-weight: 700;
    letter-spacing: .14em; text-transform: uppercase;
    color: var(--p-ink); background: var(--p-soft);
    border: 1px solid var(--p-line); border-radius: var(--r-pill);
    padding: 4px 12px;
}

/* -- Transport bar -- */
.controls {
    position: fixed; bottom: 0; left: 0; right: 0; z-index: 100;
    height: var(--controls-h);
    display: flex; align-items: center; gap: 14px;
    padding: 0 18px;
    background: color-mix(in srgb, var(--surface) 85%, transparent);
    backdrop-filter: blur(14px);
    -webkit-backdrop-filter: blur(14px);
    border-top: 1px solid var(--line);
}

/* Round transport buttons; the play button is the downbeat — bigger, lit. */
.t-btn {
    width: 42px; height: 42px; padding: 0; flex-shrink: 0;
    display: inline-flex; align-items: center; justify-content: center;
    background: var(--surface-2); color: var(--text);
    border: 1px solid var(--line); border-radius: 50%;
    cursor: pointer;
    transition: border-color var(--dur-fast), box-shadow var(--dur-fast),
                transform var(--dur-fast), background var(--dur-fast);
}
.t-btn:hover { border-color: var(--p-line); box-shadow: 0 0 18px -2px var(--glow-p); }
.t-btn:active { transform: scale(.94); }
.t-btn .icon { width: 17px; height: 17px; }
.t-btn--play {
    width: 52px; height: 52px;
    background: var(--grad-accent); color: #04121a; border: none;
    box-shadow: 0 6px 22px -4px var(--glow-p);
}
.t-btn--play:hover { filter: brightness(1.1); box-shadow: 0 8px 28px -2px var(--glow-p); }
.t-btn--play .icon { width: 20px; height: 20px; }

/* Sliders — fully custom (no naked browser range inputs). The webkit track
   paints its fill from --fill (mirrored from JS via stage-helpers); Firefox
   uses ::-moz-range-progress. */
.slider {
    -webkit-appearance: none; appearance: none;
    height: 28px; background: transparent; cursor: pointer;
    --fill: 0%;
}
.slider--seek { flex: 1; min-width: 0; }
.slider--vol  { width: 104px; flex-shrink: 0; }
.slider::-webkit-slider-runnable-track {
    height: 6px; border-radius: 3px;
    background:
        linear-gradient(90deg, var(--p), var(--s)) 0 / var(--fill) 100% no-repeat,
        var(--surface-3);
}
.slider::-webkit-slider-thumb {
    -webkit-appearance: none; appearance: none;
    width: 15px; height: 15px; margin-top: -4.5px;
    border-radius: 50%; border: none;
    background: #fff;
    box-shadow: 0 0 0 4px var(--p-soft), 0 0 10px var(--glow-p);
    transition: transform var(--dur-fast);
}
.slider::-webkit-slider-thumb:hover { transform: scale(1.2); }
.slider::-moz-range-track { height: 6px; border-radius: 3px; background: var(--surface-3); }
.slider::-moz-range-progress { height: 6px; border-radius: 3px; background: linear-gradient(90deg, var(--p), var(--s)); }
.slider::-moz-range-thumb {
    width: 15px; height: 15px; border: none; border-radius: 50%;
    background: #fff; box-shadow: 0 0 0 4px var(--p-soft), 0 0 10px var(--glow-p);
}

#time-display {
    font-size: .85rem; color: var(--text-dim);
    flex-shrink: 0; min-width: 92px; text-align: center;
    font-variant-numeric: tabular-nums;
}
.vol-icon { display: inline-flex; align-items: center; color: var(--text-dim); flex-shrink: 0; }

/* Speech-recognition status chip (label + live dot). */
.asr-display {
    display: inline-flex; align-items: center; gap: 7px;
    flex-shrink: 0;
    padding: 5px 12px;
    border: 1px solid var(--line); border-radius: var(--r-pill);
    background: var(--surface-2);
    font-size: var(--text-xs); color: var(--text-dim);
    white-space: nowrap;
}
.asr-display::before {
    content: ""; width: 7px; height: 7px; border-radius: 50%;
    background: var(--text-faint);
    transition: background var(--dur-fast), box-shadow var(--dur-fast);
}
.asr-display.ready { color: var(--matched); border-color: color-mix(in srgb, var(--matched) 40%, transparent); }
.asr-display.ready::before {
    background: var(--matched); box-shadow: 0 0 7px var(--matched);
    animation: asrPulse 1.6s ease-in-out infinite;
}
@keyframes asrPulse { 0%,100% { opacity: 1; } 50% { opacity: .45; } }
.asr-display.error { color: var(--missed); border-color: color-mix(in srgb, var(--missed) 40%, transparent); }
.asr-display.error::before { background: var(--missed); box-shadow: 0 0 7px var(--missed); }

/* YouTube dock — a little stage monitor, bottom-right.
   HARD RULE: the iframe must stay visible, unclipped, and mostly on-screen
   (YouTube auto-pauses hidden/covered/off-screen players). Reframed, never
   hidden; the iframe is forced to FILL the wrap exactly. */
#ytplayer-wrap {
    position: fixed; right: 16px; bottom: calc(var(--controls-h) + 14px);
    width: 320px; height: 180px; z-index: 80;
    border-radius: 14px; overflow: hidden;
    background: #000;
    border: 1px solid var(--line-strong);
    box-shadow: var(--shadow-pop), 0 0 0 4px color-mix(in srgb, var(--surface) 60%, transparent),
                0 0 34px -8px var(--glow-p);
}
#ytplayer-wrap iframe { width: 100%; height: 100%; border: 0; display: block; }

/* ============================================================
   8. LYRICS & WORD STATES — the core feedback loop
   Readable from across the room: the active line is huge and spotlighted;
   words snap green/amber/red the instant the engine credits them, with a
   physical pop (transform-only) per word.
   ============================================================ */
#lyrics-container {
    position: fixed; top: var(--header-h); bottom: var(--controls-h);
    left: 0; right: 0; z-index: 1;
    overflow-y: scroll; overflow-x: hidden;
    padding: 6vh 24px;
    scroll-behavior: smooth;
    scrollbar-width: none; /* Firefox */
}
#lyrics-container::-webkit-scrollbar { display: none; }

#lyrics-scroll {
    display: flex; flex-direction: column; align-items: center;
    gap: 2.4vh;
    min-height: 100%;
    justify-content: center;
}

.lyric-line {
    position: relative;
    max-width: 1080px;
    padding: 6px 28px;
    font-family: var(--font-display);
    font-size: clamp(1.25rem, 2.4vw, 1.8rem);
    font-weight: 500; line-height: 1.4;
    color: var(--text-faint);
    text-align: center;
    transition: color .2s, font-size .2s var(--ease-out);
}
.lyric-line.upcoming { color: var(--text-dim); }
.lyric-line.active {
    color: var(--text-strong);
    font-size: clamp(1.9rem, 4.2vw, 3rem);
    font-weight: 700; letter-spacing: -.01em;
}
/* The stage light that follows the singer: a soft radial spotlight behind
   the active line (paint-only, breathes slowly). */
.lyric-line.active::before {
    content: '';
    position: absolute; inset: -56px -110px; z-index: -1;
    background: radial-gradient(50% 50% at 50% 50%, var(--active-glow), transparent 72%);
    animation: activeBreathe 2.6s ease-in-out infinite;
}
@keyframes activeBreathe {
    0%, 100% { opacity: .7; }
    50%      { opacity: 1; }
}

#no-lyrics {
    display: none;
    padding-top: 16vh;
    text-align: center;
    color: var(--text-faint); font-size: 1.2rem;
}
#no-lyrics .icon { display: block; width: 44px; height: 44px; margin: 0 auto 14px; color: var(--text-faint); }

/* Game-mode word spans. Inline-block so the match pop can scale them. */
.word-span {
    position: relative;
    display: inline-block;
    color: var(--text-faint);
    cursor: default;
    transition: color .15s, text-shadow .15s, opacity .15s;
}

/* MATCHED — the payoff. Green + glow + a physical pop. The staggered
   nth-of-type delays turn a whole-phrase clear into a left-to-right wave. */
.word-span.matched {
    color: var(--matched);
    text-shadow: 0 0 16px color-mix(in srgb, var(--matched) 55%, transparent);
    animation: wordPop .3s var(--ease-spring) both;
}
.word-span.matched:nth-of-type(2)  { animation-delay: .02s; }
.word-span.matched:nth-of-type(3)  { animation-delay: .04s; }
.word-span.matched:nth-of-type(4)  { animation-delay: .06s; }
.word-span.matched:nth-of-type(5)  { animation-delay: .08s; }
.word-span.matched:nth-of-type(6)  { animation-delay: .1s; }
.word-span.matched:nth-of-type(7)  { animation-delay: .11s; }
.word-span.matched:nth-of-type(8)  { animation-delay: .12s; }
.word-span.matched:nth-of-type(9)  { animation-delay: .13s; }
.word-span.matched:nth-of-type(10) { animation-delay: .14s; }
.word-span.matched:nth-of-type(11) { animation-delay: .15s; }
.word-span.matched:nth-of-type(12) { animation-delay: .16s; }
@keyframes wordPop {
    0%   { transform: scale(1); }
    35%  { transform: scale(1.22); }
    100% { transform: scale(1); }
}

/* PERFECT — every anchor on the line landed (the arcade's own definition), one
   tier above the green clear: prismatic gold gradient text with a slow shimmer
   sweep. text-shadow must stay off (it would silhouette the transparent
   background-clip glyphs); the glow comes from drop-shadow, which follows the
   rendered gradient instead. */
.word-span.matched.matched-perfect {
    background: linear-gradient(100deg,
        var(--perfect-1) 0%, var(--perfect-2) 22%, var(--perfect-3) 46%,
        var(--perfect-2) 68%, var(--perfect-1) 100%);
    background-size: 220% 100%;
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
    text-shadow: none;
    filter: drop-shadow(0 0 9px color-mix(in srgb, var(--perfect-2) 45%, transparent));
    animation: wordPop .3s var(--ease-spring) both, perfectShimmer 2.6s linear infinite;
}
@keyframes perfectShimmer {
    from { background-position: 0% 0; }
    to   { background-position: -220% 0; }
}
@media (prefers-reduced-motion: reduce) {
    .word-span.matched.matched-perfect { animation: wordPop .3s var(--ease-spring) both; }
}

.word-span.matched-partial {
    color: var(--partial); font-weight: 600;
    text-shadow: 0 0 12px color-mix(in srgb, var(--partial) 45%, transparent);
    animation: wordPop .25s var(--ease-spring) both;
}

.word-span.missed {
    color: var(--missed);
    opacity: .8;
}

/* Key (scored) word target cue — only on the ACTIVE line, until passed/missed:
   cyan pulse + a little target beam under the word. */
.lyric-line.active .word-span.key-word:not(.matched):not(.matched-partial):not(.missed) {
    color: var(--key);
    animation: keyPulse 1.3s ease-in-out infinite;
}
.lyric-line.active .word-span.key-word:not(.matched):not(.matched-partial):not(.missed)::after {
    content: '';
    position: absolute; left: 6%; right: 6%; bottom: -3px; height: 3px;
    border-radius: 2px;
    background: var(--grad-accent);
    box-shadow: 0 0 10px var(--glow-p);
}
@keyframes keyPulse {
    0%, 100% { text-shadow: 0 0 8px  color-mix(in srgb, var(--key) 35%, transparent); }
    50%      { text-shadow: 0 0 20px color-mix(in srgb, var(--key) 75%, transparent); }
}

/* Active line: unsung words read bright so the line you're on stands out,
   then snap to green/amber/red as you actually sing each one. */
.lyric-line.active .word-span:not(.matched):not(.matched-partial):not(.missed) {
    color: var(--text-strong);
}
.lyric-line.active .word-span.matched { color: var(--matched); }
.lyric-line.active .word-span.matched-partial { color: var(--partial); }
.lyric-line.active .word-span.missed { color: var(--missed); }

/* Insane difficulty — collapse every non-key word; only the scored key words
   show (adjacent whitespace collapses to a clean single-spaced line), and
   only ONE line at a time, pinned mid-screen (visibility keeps layout stable). */
body.insanity #lyrics-scroll .word-span:not(.key-word) { display: none; }
body.insanity #lyrics-scroll .lyric-line:not(.active) { visibility: hidden; }
body.insanity #lyrics-scroll .lyric-line.active {
    position: fixed; top: 50%; left: 0; right: 0;
    transform: translateY(-50%);
    z-index: 5;
}

/* Per-line verdict flash (PERFECT / NICE / partial) — floats up off the
   right edge of the scored line. */
.line-score-flash {
    position: absolute;
    right: var(--space-5);
    font-family: var(--font-display);
    font-size: var(--text-sm); font-weight: 800;
    letter-spacing: .1em; text-transform: uppercase;
    color: var(--matched);
    pointer-events: none;
    animation: fadeOut 1.2s ease forwards;
}
/* PERFECT flash matches the gilded line: same gold ramp, gradient through the text. */
.line-score-flash.v-perfect {
    background: linear-gradient(100deg, var(--perfect-1), var(--perfect-2) 45%, var(--perfect-3) 75%, var(--perfect-2));
    -webkit-background-clip: text;
    background-clip: text;
    color: transparent;
    filter: drop-shadow(0 0 10px color-mix(in srgb, var(--perfect-2) 55%, transparent));
}
.line-score-flash.v-nice    { color: var(--p-ink); }
.line-score-flash.v-partial { color: var(--partial); }
.line-score-flash.v-miss    { color: var(--missed); }
@keyframes fadeOut {
    0%   { opacity: 1; transform: translateY(0); }
    100% { opacity: 0; transform: translateY(-18px); }
}

/* ============================================================
   9. ARCADE HUD & ON FIRE — the instrument panel
   ============================================================ */
.score-panel {
    position: fixed; top: calc(var(--header-h) + 14px); right: 16px; z-index: 90;
    display: flex; flex-direction: column; align-items: stretch; gap: 10px;
    width: 236px;
    padding: 16px 18px;
    border-radius: var(--r-lg);
    background: color-mix(in srgb, var(--surface) 88%, transparent);
    backdrop-filter: blur(10px);
    -webkit-backdrop-filter: blur(10px);
    border: 1px solid var(--line);
    box-shadow: var(--shadow-pop);
    pointer-events: none;
    font-variant-numeric: tabular-nums;
    font-family: var(--font-text);
    transform-origin: 100% 0;
}
.sp-hero { position: relative; text-align: right; }
.ah-cap {
    font-size: var(--text-xs); font-weight: 700; letter-spacing: .28em;
    text-transform: uppercase; color: var(--text-faint); line-height: 1;
}
.ah-points {
    font-family: var(--font-display);
    font-size: 3.1rem; font-weight: 700; line-height: 1.05;
    letter-spacing: -.01em;
    color: transparent; background: var(--grad-accent);
    -webkit-background-clip: text; background-clip: text;
}

/* Floating +points reward popup — springs up and fades on every clear. */
.sp-popup {
    position: absolute; top: -4px; right: 0;
    font-family: var(--font-display);
    font-size: var(--text-lg); font-weight: 700;
    color: var(--matched);
    opacity: 0; pointer-events: none;
}
.sp-popup.show { animation: spPopup var(--dur-slow) var(--ease-spring) forwards; }
@keyframes spPopup {
    0%   { opacity: 0; transform: translateY(8px) scale(.85); }
    30%  { opacity: 1; transform: translateY(-12px) scale(1.08); }
    100% { opacity: 0; transform: translateY(-30px) scale(1); }
}
body.arcade-onfire .sp-popup { color: var(--fire-c); text-shadow: 0 0 14px rgba(255,160,60,.7); }

.sp-meta { display: flex; flex-direction: column; gap: 8px; }
.ah-mult-row { display: flex; align-items: center; gap: 10px; }
.ah-mult {
    font-family: var(--font-display);
    font-size: var(--text-md); font-weight: 700; color: var(--s-ink);
    min-width: 44px; text-align: right;
}
/* One-shot tier-up beat when the multiplier increases. */
.ah-mult.tierup { animation: tierUp var(--dur-slow) var(--ease-spring); }
@keyframes tierUp {
    0%   { transform: scale(1);   color: var(--s-ink); }
    35%  { transform: scale(1.5); color: var(--p-ink); }
    100% { transform: scale(1);   color: var(--s-ink); }
}

/* Multiplier ramp — a charge bar with a travelling sheen (tiny element,
   transform-only sheen) so the build-up reads as rising tension. */
.ah-ramp {
    flex: 1; height: 8px;
    background: var(--surface-3); border-radius: var(--r-pill);
    overflow: hidden;
}
.ah-ramp-fill {
    position: relative; overflow: hidden;
    height: 100%; width: 0%;
    background: var(--grad-accent);
    border-radius: var(--r-pill);
    box-shadow: 0 0 12px var(--glow-p);
    transition: width var(--dur-base) var(--ease-out);
}
.ah-ramp-fill::after {
    content: '';
    position: absolute; top: 0; bottom: 0; width: 24px;
    background: linear-gradient(90deg, transparent, rgba(255,255,255,.55), transparent);
    animation: rampSheen 1.4s linear infinite;
}
@keyframes rampSheen {
    from { transform: translateX(-28px); }
    to   { transform: translateX(190px); }
}

.sp-acc { display: flex; align-items: baseline; justify-content: flex-end; gap: 7px; font-size: var(--text-sm); color: var(--text-dim); }
.sp-acc-label { font-size: var(--text-xs); font-weight: 700; letter-spacing: .14em; text-transform: uppercase; color: var(--text-faint); }
.sp-acc #score-pct { color: var(--matched); font-weight: 700; font-size: var(--text-md); }

/* Streak flame — the icon licks like a real flame while the streak lives. */
.ah-streak {
    align-self: flex-end;
    display: inline-flex; align-items: center; gap: 5px;
    font-family: var(--font-display);
    font-size: var(--text-md); color: var(--s-ink); font-weight: 700;
}
.ah-streak .icon { animation: flameFlick .5s ease-in-out infinite alternate; transform-origin: 50% 90%; }
@keyframes flameFlick {
    from { transform: scale(1) rotate(-3deg); }
    to   { transform: scale(1.12) rotate(3deg); }
}

/* Streak milestone callout (10/25/50) — brand cyan, never confused with fire. */
.sp-milestone {
    align-self: center;
    font-family: var(--font-display);
    font-size: var(--text-sm); font-weight: 800; letter-spacing: .14em;
    text-transform: uppercase;
    background: var(--grad-accent);
    -webkit-background-clip: text; background-clip: text;
    -webkit-text-fill-color: transparent; color: transparent;
    opacity: 0; pointer-events: none;
}
.sp-milestone.show { animation: spMilestone 1.1s var(--ease-out) forwards; }
.sp-milestone.rescue {
    padding: 6px 12px;
    border: 1px solid color-mix(in srgb, var(--matched) 60%, transparent);
    border-radius: var(--r-pill);
    background: color-mix(in srgb, var(--matched) 15%, var(--surface-2));
    -webkit-text-fill-color: var(--matched); color: var(--matched);
    box-shadow: 0 0 22px color-mix(in srgb, var(--matched) 35%, transparent);
}
.sp-milestone.rescue.show { animation: lateRescue 1.45s var(--ease-spring) forwards; }
@keyframes spMilestone {
    0%   { opacity: 0; transform: translateY(8px) scale(.8); }
    20%  { opacity: 1; transform: translateY(0) scale(1.12); }
    80%  { opacity: 1; transform: translateY(0) scale(1); }
    100% { opacity: 0; transform: translateY(-6px) scale(1); }
}
@keyframes lateRescue {
    0%   { opacity: 0; transform: translateY(10px) scale(.72) rotate(-2deg); }
    22%  { opacity: 1; transform: translateY(0) scale(1.16) rotate(1deg); }
    72%  { opacity: 1; transform: translateY(0) scale(1); }
    100% { opacity: 0; transform: translateY(-8px) scale(1.03); }
}

/* -- ON FIRE — the spectacle players chase. Pure CSS (self-animating), so
      it needs no render loop; the reduced-motion guard freezes it vivid. -- */
.ah-fire {
    position: relative;
    display: inline-flex; align-items: center; justify-content: center; gap: var(--space-2);
    align-self: stretch;
    font-family: var(--font-display);
    font-size: var(--text-base); font-weight: 800; letter-spacing: .26em;
    color: #fff;
    background: var(--grad-fire);
    border: 1px solid rgba(255,210,140,.7);
    padding: var(--space-2) var(--space-3);
    border-radius: var(--r-pill);
    text-shadow: 0 0 10px rgba(255,80,20,.85);
    box-shadow: 0 0 22px rgba(255,140,40,.55), inset 0 0 10px rgba(255,225,160,.45);
    animation: onFireBadge .8s ease-in-out infinite;
}
@keyframes onFireBadge {
    0%, 100% { box-shadow: 0 0 18px rgba(255,130,40,.5),  inset 0 0 8px rgba(255,225,160,.4);  transform: scale(1); }
    50%      { box-shadow: 0 0 46px rgba(255,175,65,.95), inset 0 0 14px rgba(255,240,190,.65); transform: scale(1.05); }
}
.ah-fire-label { line-height: 1; }
.ah-fire-flames { position: relative; display: inline-flex; width: 18px; height: 16px; }
.ah-fire-flames .ember {
    position: absolute; bottom: 0; width: 4px; height: 4px; border-radius: 50%;
    background: var(--fire-c); box-shadow: 0 0 6px var(--fire-b);
    animation: ember 1s ease-in infinite;
}
.ah-fire-flames .ember:nth-child(1) { left: 0;   animation-delay: 0s; }
.ah-fire-flames .ember:nth-child(2) { left: 4px; animation-delay: .16s; }
.ah-fire-flames .ember:nth-child(3) { left: 8px; animation-delay: .33s; }
.ah-fire-flames .ember:nth-child(4) { left: 13px; animation-delay: .5s; }
.ah-fire-flames .ember:nth-child(5) { left: 2px; animation-delay: .68s; }
@keyframes ember {
    0%   { transform: translateY(0) scale(1); opacity: 1; }
    100% { transform: translateY(-18px) scale(.2); opacity: 0; }
}

/* The whole panel ignites: fiery border + pulsing glow. */
body.arcade-onfire .score-panel {
    border-color: var(--fire-c);
    animation: onFirePanel .8s ease-in-out infinite;
}
@keyframes onFirePanel {
    0%, 100% { box-shadow: 0 0 26px rgba(255,120,40,.4); transform: scale(1); }
    50%      { box-shadow: 0 0 54px rgba(255,155,60,.7); transform: scale(1.02); }
}
body.arcade-onfire .ah-points {
    background: var(--grad-fire);
    -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent;
    text-shadow: 0 0 24px rgba(255,140,40,.55);
}

/* On-fire active lyric: warm breathing glow; each word KEEPS its scoring
   colour (key cyan / green / amber / red) under the heat. */
body.arcade-onfire .lyric-line.active {
    animation: onFireLyric 1.5s ease-in-out infinite;
}
@keyframes onFireLyric {
    0%, 100% { filter: brightness(1)   drop-shadow(0 0 10px rgba(255,120,40,.45)); }
    50%      { filter: brightness(1.2) drop-shadow(0 0 24px rgba(255,165,70,.8)); }
}
body.arcade-onfire .lyric-line.active .word-span {
    text-shadow: 0 0 16px rgba(255,120,40,.55);
}

/* Full-bleed fire rising from the floor of the stage + corner flares.
   Additive warm wash pinned low so it never covers the centered lyric. */
.onfire-floor {
    position: fixed; left: 0; right: 0; bottom: 0; height: 46vh;
    pointer-events: none; z-index: 1; opacity: 0;
    background:
        radial-gradient(100% 100% at 50% 132%, rgba(255,106,0,.6) 0%, rgba(255,150,40,.22) 42%, transparent 72%),
        radial-gradient(70% 95% at 6% 128%, rgba(255,85,30,.4), transparent 60%),
        radial-gradient(70% 95% at 94% 128%, rgba(255,85,30,.4), transparent 60%);
    transition: opacity var(--dur-slow) var(--ease-out);
}
body.arcade-onfire .onfire-floor {
    opacity: 1;
    animation: onFireFloor 1.25s ease-in-out infinite;
}
@keyframes onFireFloor {
    0%, 100% { opacity: .82; transform: translateY(4px) scaleY(.98); }
    45%      { opacity: 1;   transform: translateY(0)   scaleY(1.04); }
    72%      { opacity: .9;  transform: translateY(2px) scaleY(1); }
}

/* ============================================================
   10. PREP OVERLAY — the backstage moment
   ============================================================ */
.prep-overlay {
    position: fixed; inset: 0; z-index: 200;
    display: flex; align-items: center; justify-content: center;
    padding: 24px; overflow-y: auto;
    background:
        radial-gradient(120% 80% at 100% 0%, rgba(240,70,143,.14), transparent 56%),
        radial-gradient(120% 90% at 0% 100%, rgba(45,212,238,.13), transparent 56%),
        var(--bg-deep);
    transition: opacity .4s;
}
.prep-box {
    display: flex; flex-direction: column; align-items: center; gap: 26px;
    max-width: 980px; padding: 24px 0;
    text-align: center;
    animation: heroRise .6s var(--ease-out) both;
}
.prep-kicker {
    font-family: var(--font-display);
    font-size: var(--text-xs); font-weight: 700;
    letter-spacing: .34em; text-transform: uppercase;
    color: var(--p-ink);
}
.prep-song {
    font-family: var(--font-display);
    font-size: clamp(1.7rem, 4.5vw, 2.9rem);
    font-weight: 700; line-height: 1.15; letter-spacing: -.01em;
    max-width: 720px;
    background: var(--grad-accent);
    -webkit-background-clip: text; background-clip: text;
    -webkit-text-fill-color: transparent; color: transparent;
    filter: drop-shadow(0 0 22px var(--glow-p));
}

.diff-gate { display: flex; flex-direction: column; align-items: center; gap: 20px; width: 100%; }
.diff-gate-label {
    font-family: var(--font-display);
    font-size: .82rem; font-weight: 700; color: var(--text-dim);
    letter-spacing: .26em; text-transform: uppercase;
}
.diff-gate-cards {
    display: flex; flex-wrap: wrap; justify-content: center;
    gap: 14px;
    width: min(920px, 94vw);
}
.diff-gate-cards.loading { opacity: .4; pointer-events: none; filter: grayscale(.4); }

/* Difficulty = choosing a challenge. Each card owns an accent (--dc):
   easy green, medium cyan, hard amber, expert magenta, insane fire. */
.diff-card {
    --dc: var(--p);
    --dc-glow: var(--glow-p);
    flex: 1 1 150px; max-width: 176px;
    position: relative;
    display: flex; flex-direction: column; align-items: center; gap: 8px;
    padding: 22px 14px 18px;
    background: color-mix(in srgb, var(--surface) 90%, transparent);
    color: var(--text);
    border: 1px solid var(--line); border-radius: 16px;
    cursor: pointer; overflow: hidden;
    transition: transform var(--dur-base) var(--ease-out),
                border-color var(--dur-fast), box-shadow var(--dur-base);
}
/* Accent strip along the card's top edge. */
.diff-card::before {
    content: '';
    position: absolute; top: 0; left: 0; right: 0; height: 3px;
    background: var(--dc); opacity: .85;
}
.diff-card[data-diff="easy"]   { --dc: var(--matched); --dc-glow: color-mix(in srgb, var(--matched) 50%, transparent); }
.diff-card[data-diff="medium"] { --dc: var(--p);       --dc-glow: var(--glow-p); }
.diff-card[data-diff="hard"]   { --dc: var(--partial); --dc-glow: color-mix(in srgb, var(--partial) 50%, transparent); }
.diff-card[data-diff="expert"] { --dc: var(--s);       --dc-glow: var(--glow-s); }
.diff-card[data-diff="insane"] { --dc: var(--fire-b);  --dc-glow: rgba(255,150,60,.5); }
.diff-card:hover, .diff-card:focus-visible {
    transform: translateY(-4px);
    border-color: var(--dc);
    box-shadow: 0 14px 40px -10px var(--dc-glow);
    outline: none;
}
.diff-card.selected {
    border-color: var(--dc);
    box-shadow: 0 0 0 1px var(--dc), 0 14px 44px -8px var(--dc-glow),
                inset 0 0 26px color-mix(in srgb, var(--dc) 12%, transparent);
}
.diff-card .dc-name {
    font-family: var(--font-display);
    font-size: 1.3rem; font-weight: 700; letter-spacing: .02em;
    color: var(--dc);
}
.diff-card .dc-desc { font-size: .76rem; color: var(--text-dim); text-align: center; line-height: 1.35; }

/* Per-difficulty preview line (sample lyric with its targets lit). */
.diff-preview {
    max-width: 600px; margin: 2px auto 0; text-align: center;
    padding: 14px 22px;
    background: color-mix(in srgb, var(--surface) 80%, transparent);
    border: 1px solid var(--line); border-radius: var(--r-lg);
}
.dp-line { font-size: 1.12rem; line-height: 1.8; font-family: var(--font-display); }
.dp-word { color: var(--text-faint); transition: color .15s; }
.dp-word.dp-anchor { color: var(--text-dim); }
.dp-word.dp-target {
    color: var(--key); font-weight: 700;
    text-shadow: 0 0 8px var(--key), 0 0 16px var(--glow-p);
}
.dp-caption { margin-top: 8px; font-size: .78rem; color: var(--text-dim); letter-spacing: .02em; }

.prep-status {
    display: flex; align-items: center; gap: 12px;
    max-width: 560px;
    color: var(--text-dim); font-size: .95rem; line-height: 1.5;
}
.prep-spinner {
    width: 20px; height: 20px; flex-shrink: 0;
    border: 2px solid var(--line-strong); border-top-color: var(--p);
    border-radius: 50%;
    animation: spin .8s linear infinite;
}

/* Secondary actions: ghost chips — present, readable, clearly secondary. */
.prep-toolbar {
    display: flex; flex-wrap: wrap; gap: 10px;
    justify-content: center; align-items: center;
}
.prep-toolbar .diff-gate-listen { margin: 0; }
.diff-gate-listen { font-size: .85rem; opacity: .9; }
.diff-gate-listen:hover { opacity: 1; }
/* Clean-mode switch dot (pressed = on). */
#cleanModeToggle .switch-dot {
    display: inline-block; width: 9px; height: 9px; border-radius: var(--r-pill);
    background: var(--text-faint);
    transition: background var(--dur-fast), box-shadow var(--dur-fast);
}
#cleanModeToggle[aria-pressed="true"] .switch-dot { background: var(--matched); box-shadow: 0 0 8px var(--matched); }
#cleanModeToggle[aria-pressed="true"] { border-color: var(--matched); color: var(--text); }

/* Mic Check panel. */
#micCheckPanel {
    max-width: 460px; margin: 4px auto 0;
    padding: 18px 20px; text-align: center;
    border-radius: var(--r-lg);
}
.mc-instr { font-size: .82rem; color: var(--text-dim); letter-spacing: .02em; }
.mc-phrase {
    font-family: var(--font-display);
    font-size: 1.05rem; color: var(--text-strong); font-weight: 600;
    margin: 6px 0 14px;
}
.mc-meter {
    height: 12px; overflow: hidden;
    background: var(--surface-2); border: 1px solid var(--line);
    border-radius: 999px;
}
.mc-meter-fill {
    height: 100%; width: 0%;
    background: var(--grad-accent);
    box-shadow: 0 0 12px var(--glow-p);
    transition: width .08s linear;
}
.mc-heard { min-height: 1.3em; margin-top: 12px; font-size: .92rem; color: var(--text-dim); font-style: italic; }
.mc-heard.has-text { color: var(--matched); font-style: normal; }
.mc-verdict { margin-top: 8px; font-size: .95rem; font-weight: 600; color: var(--text-dim); }
.mc-verdict.ok { color: var(--matched); }
.mc-verdict.warn { color: var(--partial); }

.prep-legal {
    max-width: 420px; margin: 4px auto 0;
    font-size: .74rem; line-height: 1.6;
    color: var(--text-faint); text-align: center;
}
.prep-legal a { color: var(--text-dim); text-decoration: underline; }
.prep-legal a:hover { color: var(--p-ink); }

/* ============================================================
   11. COUNT-IN — the beat drop
   Three seconds of cinema: the numeral slams in (player.js restarts the
   .countin-num animation per beat), a halo breathes behind it in time
   (0.8s loop = the countdown interval), EQ bars jump at the floor.
   ============================================================ */
.countin-overlay {
    position: fixed; inset: 0; z-index: 250; cursor: pointer;
    display: flex; align-items: center; justify-content: center;
    background:
        radial-gradient(120% 90% at 50% 32%, rgba(45,212,238,.12), transparent 60%),
        var(--bg-deep);
}
.countin-box {
    position: relative;
    display: flex; flex-direction: column; align-items: center; gap: 16px;
    text-align: center;
}
/* Halo behind the numeral — a blurred disc pulsing on the 0.8s beat. */
.countin-box::before {
    content: '';
    position: absolute; left: 50%; top: 42%;
    width: 340px; height: 340px;
    margin: -170px 0 0 -170px;
    border-radius: 50%;
    background: radial-gradient(50% 50% at 50% 50%, rgba(45,212,238,.22), rgba(240,70,143,.10) 55%, transparent 75%);
    animation: beatHalo .8s ease-out infinite;
    z-index: -1;
}
@keyframes beatHalo {
    0%   { transform: scale(.82); opacity: 1; }
    100% { transform: scale(1.12); opacity: .35; }
}
.countin-spinner {
    width: 30px; height: 30px;
    border: 3px solid var(--line-strong); border-top-color: var(--p);
    border-radius: 50%;
    animation: spin .8s linear infinite;
}
.countin-num {
    font-family: var(--font-display);
    font-size: clamp(8rem, 24vw, 15rem);
    font-weight: 700; line-height: 1; letter-spacing: -.02em;
    color: transparent;
    background: var(--grad-accent);
    -webkit-background-clip: text; background-clip: text;
    filter: drop-shadow(0 0 34px var(--glow-p));
    /* player.js restarts this per beat (style.animation='none' -> reflow -> ''). */
    animation: countBeat .78s var(--ease-slam);
}
@keyframes countBeat {
    0%   { transform: scale(2.1); opacity: 0; filter: blur(14px) drop-shadow(0 0 34px var(--glow-p)); }
    45%  { transform: scale(.96); opacity: 1; filter: blur(0) drop-shadow(0 0 34px var(--glow-p)); }
    70%  { transform: scale(1.03); }
    100% { transform: scale(1); opacity: 1; filter: blur(0) drop-shadow(0 0 34px var(--glow-p)); }
}
.countin-label {
    font-family: var(--font-display);
    font-size: var(--text-lg); font-weight: 700;
    letter-spacing: .12em; text-transform: uppercase;
    color: var(--text);
}
.countin-skip {
    font-size: .74rem; color: var(--text-dim);
    letter-spacing: .14em; text-transform: uppercase;
    margin-top: 6px;
    animation: skipBreathe 1.6s ease-in-out infinite;
}
@keyframes skipBreathe { 0%,100% { opacity: .55; } 50% { opacity: 1; } }
.countin-eq { height: 44px; margin-top: 10px; }

/* ============================================================
   12. RESULTS CEREMONY — suspense -> reveal -> payoff
   Staged via [data-stage] on .game-modal, advanced by player.js
   (overlay -> card -> grade -> points -> best -> done). The grade slams
   in with overshoot; S/A tiers rain confetti (transform-only pieces).
   ============================================================ */
.game-modal {
    position: fixed; inset: 0; z-index: 300;
    display: flex; align-items: center; justify-content: center;
    padding: 20px;
    background: color-mix(in srgb, var(--bg-deep) 82%, transparent);
    backdrop-filter: blur(8px);
    -webkit-backdrop-filter: blur(8px);
    opacity: 0;
    transition: opacity var(--dur-slow) var(--ease-out);
}
.game-modal[data-stage] { opacity: 1; }

/* Spotlight cone over the card (static paint; part of the ceremony set). */
.game-modal::before {
    content: '';
    position: absolute; inset: 0; pointer-events: none;
    background:
        radial-gradient(60% 70% at 50% 30%, rgba(45,212,238,.10), transparent 65%),
        radial-gradient(50% 60% at 50% 36%, rgba(240,70,143,.08), transparent 60%);
}

.game-modal-box {
    position: relative;
    container-type: inline-size;   /* lets the stat grid react to card width */
    width: min(560px, 94vw);
    padding: 52px 44px 36px;
    text-align: center;
    background: var(--surface);
    border: 1px solid var(--line); border-radius: 24px;
    box-shadow: var(--shadow-modal), 0 0 60px -18px var(--glow-p);
    transform: scale(.92) translateY(14px); opacity: 0;
    transition: transform .45s var(--ease-spring), opacity var(--dur-slow) var(--ease-out);
}
.game-modal:is([data-stage="card"],[data-stage="grade"],[data-stage="points"],[data-stage="best"],[data-stage="done"]) .game-modal-box {
    transform: scale(1) translateY(0); opacity: 1;
}

.grade-hero { position: relative; margin-bottom: var(--space-5); }

/* The letter is the hero: huge, brand-gradient, glows and breathes once
   landed. Slams from 2.4x with a hard overshoot (the reveal). */
.grade-letter {
    font-family: var(--font-display);
    font-size: clamp(7rem, 22vw, 9.5rem);
    font-weight: 700; line-height: 1; letter-spacing: -.02em;
    background: var(--grad-grade);
    -webkit-background-clip: text; background-clip: text;
    -webkit-text-fill-color: transparent; color: transparent;
    filter: drop-shadow(0 0 30px var(--glow-p));
    transform: scale(2.4); opacity: 0;
    transition: transform .55s var(--ease-slam), opacity .25s var(--ease-out);
}
.game-modal:is([data-stage="grade"],[data-stage="points"],[data-stage="best"],[data-stage="done"]) .grade-letter {
    transform: scale(1); opacity: 1;
    animation: gradeBreathe 2.6s ease-in-out .6s infinite;
}
@keyframes gradeBreathe {
    0%, 100% { filter: drop-shadow(0 0 22px var(--glow-p)); }
    50%      { filter: drop-shadow(0 0 40px var(--glow-s)); }
}

.grade-points {
    margin-top: 6px;
    font-family: var(--font-display);
    font-size: 1.9rem; font-weight: 800; color: var(--matched);
    font-variant-numeric: tabular-nums;
    text-shadow: 0 0 18px color-mix(in srgb, var(--matched) 40%, transparent);
}

/* Stat cells — staggered rise once the points land. Container query keeps
   the grid at 3 cols until the card gets narrow. */
.grade-stats {
    display: grid; grid-template-columns: repeat(3, 1fr);
    gap: 12px;
    margin-top: var(--space-5);
}
.grade-stat {
    padding: 12px 8px;
    background: var(--surface-2); border: 1px solid var(--line);
    border-radius: var(--r);
    opacity: 0; transform: translateY(10px);
    transition: opacity .4s var(--ease-out), transform .4s var(--ease-out);
}
.game-modal:is([data-stage="points"],[data-stage="best"],[data-stage="done"]) .grade-stat {
    opacity: 1; transform: translateY(0);
}
.game-modal .grade-stat:nth-child(2) { transition-delay: .06s; }
.game-modal .grade-stat:nth-child(3) { transition-delay: .12s; }
.game-modal .grade-stat:nth-child(4) { transition-delay: .18s; }
.game-modal .grade-stat:nth-child(5) { transition-delay: .24s; }
.game-modal .grade-stat:nth-child(6) { transition-delay: .3s; }
@container (max-width: 400px) {
    .grade-stats { grid-template-columns: repeat(2, 1fr); }
}
.gs-label {
    display: block;
    font-size: .62rem; font-weight: 700; letter-spacing: .16em;
    text-transform: uppercase; color: var(--text-faint);
    margin-bottom: 4px;
}
.gs-val {
    display: block;
    font-family: var(--font-display);
    font-size: var(--text-md); font-weight: 700; color: var(--text-strong);
    font-variant-numeric: tabular-nums;
}

/* NEW BEST ribbon — drops in last, then keeps a slow shine sweep. */
.nb-ribbon {
    position: absolute; top: -16px; left: 50%;
    transform: translateX(-50%) translateY(-8px);
    overflow: hidden;
    background: var(--grad-accent); color: #04121a;
    font-family: var(--font-display);
    font-weight: 800; font-size: var(--text-xs); letter-spacing: .16em;
    padding: 7px 18px; border-radius: var(--r-pill);
    box-shadow: 0 6px 24px -6px var(--glow-p);
    opacity: 0;
    transition: opacity var(--dur-base) var(--ease-out), transform var(--dur-base) var(--ease-spring);
}
.game-modal:is([data-stage="best"],[data-stage="done"]) .nb-ribbon[data-best="1"] {
    opacity: 1; transform: translateX(-50%) translateY(0);
}
.nb-ribbon[data-best="1"]::after {
    content: '';
    position: absolute; top: 0; bottom: 0; width: 30px;
    background: linear-gradient(90deg, transparent, rgba(255,255,255,.7), transparent);
    animation: ribbonShine 2.2s ease-in-out 1s infinite;
}
@keyframes ribbonShine {
    from { transform: translateX(-60px) skewX(-18deg); }
    to   { transform: translateX(190px) skewX(-18deg); }
}

.game-modal-actions {
    display: flex; gap: var(--space-3); justify-content: center;
    margin-top: var(--space-6);
    opacity: 0; transform: translateY(8px);
    transition: opacity .4s var(--ease-out), transform .4s var(--ease-out);
}
.game-modal:is([data-stage="best"],[data-stage="done"]) .game-modal-actions {
    opacity: 1; transform: translateY(0);
}

/* Confetti — 24 pieces rained once per ceremony, only for S/A tiers
   (stage-helpers.gradeTier -> [data-grade-tier]). Pieces are transform-only;
   nth-child spreads position, hue, delay, duration, and drift via --dx. */
.confetti { position: absolute; inset: 0; overflow: hidden; pointer-events: none; }
.confetti i {
    position: absolute; top: -24px;
    width: 9px; height: 14px; border-radius: 2px;
    background: var(--p);
    opacity: 0;
}
.game-modal[data-stage="done"][data-grade-tier="s"] .confetti i,
.game-modal[data-stage="done"][data-grade-tier="a"] .confetti i {
    animation: confettiFall 3.4s cubic-bezier(.25,.4,.45,1) forwards;
}
@keyframes confettiFall {
    0%   { opacity: 0; transform: translate3d(0, 0, 0) rotate(0deg); }
    6%   { opacity: 1; }
    100% { opacity: .9; transform: translate3d(var(--dx, 0px), 108vh, 0) rotate(660deg); }
}
.confetti i:nth-child(4n+1) { background: var(--p); }
.confetti i:nth-child(4n+2) { background: var(--s); border-radius: 50%; height: 9px; }
.confetti i:nth-child(4n+3) { background: var(--matched); }
.confetti i:nth-child(4n+4) { background: var(--fire-c); border-radius: 50%; height: 9px; }
.confetti i:nth-child(1)  { left: 6%;  --dx: 40px;  animation-delay: 0s;    animation-duration: 3.1s; }
.confetti i:nth-child(2)  { left: 12%; --dx: -60px; animation-delay: .18s;  animation-duration: 3.6s; }
.confetti i:nth-child(3)  { left: 18%; --dx: 30px;  animation-delay: .08s;  animation-duration: 2.9s; }
.confetti i:nth-child(4)  { left: 24%; --dx: -40px; animation-delay: .3s;   animation-duration: 3.4s; }
.confetti i:nth-child(5)  { left: 30%; --dx: 70px;  animation-delay: .05s;  animation-duration: 3s; }
.confetti i:nth-child(6)  { left: 36%; --dx: -30px; animation-delay: .22s;  animation-duration: 3.7s; }
.confetti i:nth-child(7)  { left: 42%; --dx: 50px;  animation-delay: .12s;  animation-duration: 3.2s; }
.confetti i:nth-child(8)  { left: 48%; --dx: -70px; animation-delay: .28s;  animation-duration: 3.5s; }
.confetti i:nth-child(9)  { left: 54%; --dx: 36px;  animation-delay: .02s;  animation-duration: 3.3s; }
.confetti i:nth-child(10) { left: 60%; --dx: -44px; animation-delay: .2s;   animation-duration: 2.8s; }
.confetti i:nth-child(11) { left: 66%; --dx: 60px;  animation-delay: .1s;   animation-duration: 3.6s; }
.confetti i:nth-child(12) { left: 72%; --dx: -36px; animation-delay: .26s;  animation-duration: 3s; }
.confetti i:nth-child(13) { left: 78%; --dx: 48px;  animation-delay: .06s;  animation-duration: 3.4s; }
.confetti i:nth-child(14) { left: 84%; --dx: -52px; animation-delay: .16s;  animation-duration: 3.1s; }
.confetti i:nth-child(15) { left: 90%; --dx: 34px;  animation-delay: .24s;  animation-duration: 3.5s; }
.confetti i:nth-child(16) { left: 94%; --dx: -40px; animation-delay: .34s;  animation-duration: 3.2s; }
.confetti i:nth-child(17) { left: 9%;  --dx: -46px; animation-delay: .4s;   animation-duration: 3.3s; }
.confetti i:nth-child(18) { left: 21%; --dx: 56px;  animation-delay: .46s;  animation-duration: 2.9s; }
.confetti i:nth-child(19) { left: 33%; --dx: -34px; animation-delay: .36s;  animation-duration: 3.6s; }
.confetti i:nth-child(20) { left: 45%; --dx: 44px;  animation-delay: .5s;   animation-duration: 3.1s; }
.confetti i:nth-child(21) { left: 57%; --dx: -58px; animation-delay: .42s;  animation-duration: 3.4s; }
.confetti i:nth-child(22) { left: 69%; --dx: 38px;  animation-delay: .54s;  animation-duration: 3s; }
.confetti i:nth-child(23) { left: 81%; --dx: -42px; animation-delay: .48s;  animation-duration: 3.7s; }
.confetti i:nth-child(24) { left: 88%; --dx: 52px;  animation-delay: .58s;  animation-duration: 3.2s; }

/* ============================================================
   13. DEBUG HUD (toggle with D) — functional, stays dark mono
   ============================================================ */
#debug-hud {
    position: fixed; top: 60px; right: 0;
    width: 400px; max-height: calc(100vh - 80px);
    overflow-y: auto;
    background: rgba(7, 7, 16, 0.94);
    border-left: 2px solid var(--p);
    font-family: var(--font-mono); font-size: var(--text-xs);
    color: var(--gray-800);
    padding: var(--space-2) var(--space-3);
    z-index: 150; line-height: 1.55;
}
#debug-hud::-webkit-scrollbar { display: none; }
.dbg-header  { color: var(--p); font-weight: bold; margin-bottom: 4px; letter-spacing: 0.04em; }
.dbg-row     { padding: 1px 0; white-space: pre-wrap; word-break: break-all; }
.dbg-label   { color: var(--gray-600); }
.dbg-matched { color: var(--matched); font-weight: bold; }
.dbg-pending { color: var(--gray-500); }
.dbg-final   { color: #88aaff; }
.dbg-interim { color: var(--partial); }
.dbg-sep     { border-top: 1px solid var(--line); margin: 5px 0; }
.dbg-ev-line  { color: var(--s); }
.dbg-ev-res   { color: #999; }
.dbg-ev-match { color: #5af; }

/* ============================================================
   14. MOTION SAFETY & RESPONSIVE
   ============================================================ */

/* Honor prefers-reduced-motion everywhere: animations/transitions collapse
   to (near) instant; visual states (on-fire glow, grade, status colors)
   remain fully intact — just still. */
@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;
    }
}

/* Landing + legal are fully responsive. */
@media (max-width: 720px) {
    .hero { padding-top: 20px; }
    .search-bar { flex-wrap: wrap; border-radius: 26px; padding: 10px; }
    .search-bar .search-ico { display: none; }
    .search-bar input { flex: 1 1 100%; padding: 10px 12px; }
    .search-go { flex: 1 1 100%; }
    .legal { padding: 32px 24px; }
    .grade-stats { grid-template-columns: repeat(2, 1fr); }
    .score-panel { width: 200px; }
    .landing-top { padding: 16px 0; }
    .sr-thumb { width: 80px; height: 45px; }
}

/* Short desktop windows: keep the prep overlay scrollable-friendly. */
@media (max-height: 760px) {
    .prep-box { gap: 16px; }
    .prep-song { font-size: clamp(1.4rem, 3.4vw, 2.2rem); }
}
