/* ═══════════════════════════════════════════════════════════════════════════
   GITATO — game surface (GITATO Design System v2)

   ds.css is linked BEFORE this file (see index.html) and owns the substrate,
   the ink ramp, signals, type, radii, motion curves and the focus ring.
   <body data-gt="game"> selects the theme: signal = cyan, signal-2 = magenta.

   What stays local, and why:
   • Legacy variable names. app.bundle.js writes `var(--cyan)` and `var(--mag)`
     into inline styles (gamepad menu highlight; local-loop category tags), so
     those two names must keep resolving. They are aliases onto DS tokens now,
     not a second palette. --red / --gold / --bg follow the same rule.
   • The HUD keeps px sizes and its glow, but each group (combo, score, meter
     labels, theme badge) now sits on a small opaque --gt-hud plate: it floats
     over a live WebGL canvas, so without one the ink has no contrast guarantee.
     The plate goes on the containers only — app.bundle.js overwrites #combo-x
     colour/size/text-shadow inline every frame from its own tier table.
   • Round shapes (reticle, spinner, DROP button, transport buttons) keep 50%.
     That is a shape, not a value off the radius scale.
   ═══════════════════════════════════════════════════════════════════════════ */

:root{
  /* aliases consumed by app.bundle.js — do not remove */
  --cyan: var(--gt-cyan);
  --mag:  var(--gt-magenta);
  --red:  var(--gt-red);
  --gold: var(--gt-gold);
  --bg:   var(--gt-void);

  /* Surface-specific: the menus sit on top of a live canvas, so their backdrop
     is a scrim rather than a solid. DS substrate colours at scrim alpha. */
  --g-scrim-in:  rgba(15, 18, 24, .88);   /* --gt-sub-1 */
  --g-scrim-out: rgba(6, 7, 10, .97);     /* --gt-void  */

  /* Tracking for lowercase descriptive lines. The DS tracking scale is built
     for caps; sentence-case help text reads wrong at .16em. */
  --g-track-desc: .05em;

  /* HUD emission: the glow on the text (the plate under it is --gt-hud). */
  --g-hud-glow: 0 0 12px rgba(25, 224, 255, .5);
}

*{ margin:0; padding:0; box-sizing:border-box; }
html,body{ width:100%; height:100%; overflow:hidden;
  background:var(--bg); color:var(--gt-ink-1);
  font-family:var(--gt-font-ui); user-select:none; }
#game{ position:fixed; inset:0; width:100%; height:100%; display:block; touch-action:none; }
.hidden{ display:none !important; }

/* ── Focus. Rule 4 of the spec: everything clickable gets a visible ring. ──── */
.btn:focus-visible,
.theme-opt:focus-visible,
.char-opt:focus-visible,
.jb-btn:focus-visible,
#apk-link:focus-visible,
#demucs-btn:focus-visible,
input[type=range]:focus-visible{
  outline:none;
  box-shadow:var(--gt-focus-ring);
}
/* The lit plates (.btn.primary, .theme-opt.active) deliberately keep the SAME
   ring. Two reasons, both checked in the browser:
   1. Re-declaring --gt-focus-ink/--gt-focus-gap on the element does nothing —
      --gt-focus-ring is declared on :root, so its var() references are already
      substituted there and only the result inherits down.
   2. The inverted ring would be worse here anyway: white against magenta is
      ~3.2:1, and its dark outer edge would land on a near-black scrim. The
      default dark-gap-then-white ring reads strongly against both. */
/* #drop-btn animates its own box-shadow when ready, and an animation beats a
   normal declaration — so this one ring is drawn with outline instead. */
#drop-btn:focus-visible{ outline:2px solid var(--gt-focus-ink); outline-offset:3px; }

/* touch DROP button — only rendered on coarse pointers during a run */
#drop-btn{ position:fixed; right:max(18px, env(safe-area-inset-right)); bottom:max(84px, calc(env(safe-area-inset-bottom) + 64px));
  z-index:12; width:88px; height:88px; border-radius:50%; pointer-events:auto; cursor:pointer;
  /* Opaque, per the DS note on HUD surfaces: a translucent control over a WebGL
     canvas has no contrast guarantee, and dropping backdrop-filter also removes
     a per-frame blur from the one surface that can least afford it.
     ink-3 on --gt-hud measures 6.8:1 whatever the game draws behind it. */
  background:var(--gt-hud); color:var(--gt-ink-3); font-family:var(--gt-font-ui);
  font-weight:800; font-size:var(--gt-t-md); letter-spacing:var(--gt-track-btn);
  border:2px solid var(--gt-cyan-dk);
  transition:background var(--gt-d-2) var(--gt-ease-soft), color var(--gt-d-2) var(--gt-ease-soft),
             border-color var(--gt-d-2) var(--gt-ease-soft); touch-action:none; }
#drop-btn.ready{ color:var(--gt-ink-on-lit); background:linear-gradient(135deg,var(--gt-sig),#fff); border-color:#fff;
  box-shadow:0 0 34px var(--gt-sig); animation:dropPulse .8s var(--gt-ease-soft) infinite alternate; }
@keyframes dropPulse{ to{ transform:scale(1.08); box-shadow:0 0 50px var(--gt-sig); } }

/* control hints per input type */
.pointer-coarse{ display:none; }
@media (pointer: coarse){
  .pointer-fine{ display:none; }
  .pointer-coarse{ display:flex; }
  /* #pause-hint is .pointer-fine and is the last child of #screen-pause, so on a
     touch device it cannot carry the centring margin. Hand it to .menu. */
  #screen-pause .menu{ margin-bottom:auto; }
}

/* ── HUD ──────────────────────────────────────────────────────────────────── */
#hud{ position:fixed; inset:0; pointer-events:none; z-index:10;
  text-shadow:var(--g-hud-glow); }
#hud-top{ position:absolute; top:24px; left:0; right:0; display:flex; justify-content:space-between; padding:0 36px; }
#combo{ display:flex; flex-direction:column; }
/* Opaque plate under each HUD group. ink-2 on --gt-hud measures 11.2:1 and
   ink-3 6.8:1 whatever the canvas draws; the glow stays on the text. Only the
   containers get it — #combo-x and #score are styled inline by app.bundle.js. */
#combo,#score-wrap,#theme-badge,#energy-label,#drop-label{ background:var(--gt-hud);
  border:1px solid var(--gt-edge-hair); border-radius:var(--gt-r-2); padding:4px 10px; }
#theme-badge:empty{ display:none; }   /* no empty plate before the bundle writes the theme name */
#combo-x{ font-size:52px; font-weight:800; line-height:var(--gt-lh-tight); color:var(--gt-ink-1);
  text-shadow:0 0 24px var(--gt-cyan); transition:transform .08s var(--gt-ease-snap), color var(--gt-d-2) var(--gt-ease-soft); }
#combo-label{ font-size:14px; letter-spacing:var(--gt-track-tag); color:var(--gt-ink-2); }
#score-wrap{ text-align:right; }
#score{ font-size:40px; font-weight:700; color:var(--gt-gold-ink); text-shadow:0 0 18px var(--gt-gold); }
#score-label{ display:block; font-size:13px; letter-spacing:var(--gt-track-tag); color:var(--gt-ink-2); }
#hud-left,#hud-right{ position:absolute; top:50%; transform:translateY(-50%); width:18px; height:42vh; }
#hud-left{ left:30px; } #hud-right{ right:30px; }
#energy-wrap,#drop-wrap{ position:absolute; inset:0; border:1px solid var(--gt-edge-lip);
  border-radius:var(--gt-r-1); overflow:hidden; background:var(--gt-void); }
#energy-bar{ position:absolute; bottom:0; left:0; right:0; height:100%; background:linear-gradient(0deg,var(--gt-red),var(--gt-gold));
  transition:height .12s var(--gt-ease-soft); }
#drop-bar{ position:absolute; bottom:0; left:0; right:0; height:0%; background:linear-gradient(0deg,var(--gt-sig),#fff);
  transition:height .12s var(--gt-ease-soft); }
/* Anchored to the meter's outer edge (not centred on it), so the plate can only
   grow inwards: centred, the 82px ENERGY plate started 2px off-screen at 1366. */
#energy-label,#drop-label{ position:absolute; bottom:-26px;
  font-size:11px; letter-spacing:var(--gt-track-tag); color:var(--gt-ink-2); white-space:nowrap; }
#energy-label{ left:0; text-align:left; }
#drop-label{ right:0; text-align:right; }
#judgement{ position:absolute; top:38%; left:50%; transform:translate(-50%,-50%); font-size:54px;
  font-weight:800; opacity:0; letter-spacing:var(--gt-track-hero); }
#rank-flash{ position:absolute; top:50%; left:50%; transform:translate(-50%,-50%); font-size:200px;
  font-weight:900; opacity:0; color:var(--gt-ink-1); }
#rec-dot{ position:absolute; top:24px; left:50%; transform:translateX(-50%); color:var(--gt-red-ink);
  font-weight:700; letter-spacing:var(--gt-track-label); animation:blink 1s steps(2) infinite; }
@keyframes blink{ 50%{ opacity:.25 } }
#theme-badge{ position:absolute; bottom:24px; left:50%; transform:translateX(-50%); font-size:13px;
  letter-spacing:var(--gt-track-label); color:var(--gt-ink-3); text-transform:uppercase; }

/* Reticle */
#reticle{ position:fixed; width:60px; height:60px; margin:-30px 0 0 -30px; z-index:11; pointer-events:none;
  border:2px solid var(--gt-sig); border-radius:50%; box-shadow:0 0 18px var(--gt-sig), inset 0 0 12px var(--gt-sig);
  transition:width .06s var(--gt-ease-out), height .06s var(--gt-ease-out), border-color var(--gt-d-1) var(--gt-ease-soft); }
#reticle.charging{ border-color:var(--gt-gold); box-shadow:0 0 26px var(--gt-gold), inset 0 0 16px var(--gt-gold); }

/* ── Screens ──────────────────────────────────────────────────────────────── */
.screen{ position:fixed; inset:0; z-index:20; display:flex; flex-direction:column; align-items:center;
  gap:var(--gt-s-5); background:radial-gradient(circle at 50% 40%, var(--g-scrim-in), var(--g-scrim-out));
  overflow-y:auto; overflow-x:hidden; padding:var(--gt-s-7) 0; }
/* Auto margins centre the stack while still allowing it to scroll when it is
   taller than the viewport. Both edge children MUST be rendered for this to
   work — a display:none element cannot carry the margin, and the stack then
   drops to the bottom edge. That is why #tribute-credit / #ownership-note are
   no longer absolutely positioned, why #demucs-btn (hidden until a desktop
   bridge reports Demucs) was moved off the last position in #screen-title, and
   why #screen-pause gets the coarse-pointer rule further down. */
.screen > :first-child { margin-top: auto; }
.screen > :last-child { margin-bottom: auto; }
.screen::-webkit-scrollbar { width: 8px; }
.screen::-webkit-scrollbar-thumb { background: var(--gt-edge-bezel); border-radius: var(--gt-r-1); }
.screen::-webkit-scrollbar-thumb:hover { background: var(--gt-edge-lip); }
/* The PNG is 1024×1024 with the glyph in rows 338–684 — two thirds of it is
   transparent padding. Sized by height and cropped to the glyph band with
   object-fit, so the menu stays above the fold on 1366×768. */
#logo{ width:auto; height:min(19vh, 215px); aspect-ratio:1024/352; object-fit:cover; object-position:center;
  filter:drop-shadow(0 0 40px rgba(25,224,255,.4)); }
#subtitle{ font-size:var(--gt-t-xl); letter-spacing:var(--gt-track-tag); color:var(--gt-sig-2-ink);
  text-shadow:0 0 20px var(--gt-sig-2); margin-top:-6px; }

.menu{ display:flex; flex-direction:column; gap:var(--gt-s-3); margin-top:var(--gt-s-3); width:min(86vw,420px); }

/* Machined plate — the quiet default action. */
.btn{ pointer-events:auto; cursor:pointer;
  font-family:var(--gt-font-ui); font-size:var(--gt-t-lg); font-weight:700;
  letter-spacing:var(--gt-track-btn); text-align:left; color:var(--gt-ink-1);
  background:linear-gradient(180deg, var(--gt-pl-2), var(--gt-pl-1));
  border:1px solid var(--gt-edge-bezel); border-radius:var(--gt-r-2);
  padding:var(--gt-s-3) var(--gt-s-5); box-shadow:var(--gt-e-1);
  transition:background var(--gt-d-2) var(--gt-ease-soft),
             border-color var(--gt-d-2) var(--gt-ease-soft),
             box-shadow var(--gt-d-2) var(--gt-ease-soft),
             transform var(--gt-d-1) var(--gt-ease-snap); }
/* ink-3 instead of opacity: dimming the whole element faded the frame with the
   text and made both harder to read. */
.btn span{ display:block; font-family:var(--gt-font-body); font-size:var(--gt-t-sm);
  font-weight:400; letter-spacing:var(--g-track-desc); color:var(--gt-ink-3); margin-top:2px;
  text-transform:none; }
a.btn{ display:block; text-decoration:none; }
.btn:hover{ background:linear-gradient(180deg, var(--gt-pl-3), var(--gt-pl-2));
  border-color:var(--gt-sig); box-shadow:var(--gt-e-1), var(--gt-bloom-sm); transform:translateY(-1px); }
.btn:active{ transform:translateY(1px); background:var(--gt-pl-4); }

/* Emissive plate — the primary action. A lit face carrying dark stencil text;
   white text fails AA on every signal colour we own, dark text passes on all. */
.btn.primary{ color:var(--gt-ink-on-lit); background:var(--gt-sig-2); border-color:var(--gt-magenta-dk);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.45),
              inset 0 -1px 0 rgba(0,0,0,.30),
              0 1px 2px rgba(0,0,0,.7),
              0 0 14px -4px var(--gt-sig-2); }
/* ink-on-lit at 85% keeps the hierarchy under the label and still measures
   5.45:1 against the magenta face. Solid would be 6.24:1 but flattens the two
   lines into one weight. */
.btn.primary span{ color:rgba(7,9,12,.85); }
.btn.primary:hover{ background:var(--gt-sig-2); border-color:var(--gt-magenta-dk);
  filter:brightness(1.11) saturate(1.04);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.45),
              inset 0 -1px 0 rgba(0,0,0,.30),
              0 1px 2px rgba(0,0,0,.7),
              0 0 22px -4px var(--gt-sig-2), 0 0 52px -18px var(--gt-sig-2); }
.btn.primary:active{ filter:brightness(.94); background:var(--gt-sig-2); }

/* ── Theme picker (chips) ─────────────────────────────────────────────────── */
#theme-picker{ display:flex; gap:var(--gt-s-2); align-items:center; margin-top:var(--gt-s-2);
  font-family:var(--gt-font-ui); font-size:var(--gt-t-sm); letter-spacing:var(--gt-track-label);
  color:var(--gt-ink-3); }
.theme-opt{ pointer-events:auto; cursor:pointer;
  font-family:var(--gt-font-ui); font-size:var(--gt-t-sm); font-weight:600;
  letter-spacing:var(--gt-track-label); text-transform:uppercase;
  color:var(--gt-ink-2); background:var(--gt-pl-2);
  border:1px solid var(--gt-edge-hair); border-radius:var(--gt-r-1); padding:7px 13px;
  transition:background var(--gt-d-2) var(--gt-ease-soft), color var(--gt-d-2) var(--gt-ease-soft),
             border-color var(--gt-d-2) var(--gt-ease-soft); }
.theme-opt:hover{ color:var(--gt-ink-1); border-color:var(--gt-edge-bezel); background:var(--gt-pl-3); }
/* Selected = lit face + dark ink. The state is carried by the fill inversion,
   not by hue alone. */
.theme-opt.active{ color:var(--gt-ink-on-lit); background:var(--gt-sig-2); border-color:var(--gt-magenta-dk); font-weight:700; }

#tribute-credit{ font-family:var(--gt-font-body); font-size:var(--gt-t-sm);
  letter-spacing:var(--gt-track-tag); color:var(--gt-ink-3); text-align:center; }

/* ── APK link / Demucs toggle ─────────────────────────────────────────────── */
#apk-link{ pointer-events:auto; display:inline-flex; align-items:center; gap:var(--gt-s-2);
  margin-top:var(--gt-s-2); font-family:var(--gt-font-ui); font-size:var(--gt-t-sm); font-weight:600;
  letter-spacing:var(--gt-track-btn); color:var(--gt-green-ink); text-decoration:none;
  background:var(--gt-pl-1); border:1px solid var(--gt-green-dk); border-radius:var(--gt-r-2);
  padding:8px 16px;
  transition:border-color var(--gt-d-2) var(--gt-ease-soft), box-shadow var(--gt-d-2) var(--gt-ease-soft),
             background var(--gt-d-2) var(--gt-ease-soft); }
#apk-link:hover{ border-color:var(--gt-green); background:var(--gt-pl-2); box-shadow:0 0 14px -4px var(--gt-green); }
/* already inside the installed app (TWA/PWA) — don't advertise the app */
@media all and (display-mode: fullscreen), (display-mode: standalone), (display-mode: minimal-ui){
  #apk-link{ display:none; }
}
#demucs-btn{ pointer-events:auto; cursor:pointer; display:inline-flex; align-items:center; gap:var(--gt-s-2);
  margin-top:var(--gt-s-2); font-family:var(--gt-font-ui); font-size:var(--gt-t-sm); font-weight:600;
  letter-spacing:var(--gt-track-btn); color:var(--gt-ink-2);
  background:linear-gradient(180deg, var(--gt-pl-2), var(--gt-pl-1));
  border:1px solid var(--gt-edge-hair); border-radius:var(--gt-r-2); padding:8px 14px;
  box-shadow:var(--gt-e-1);
  transition:border-color var(--gt-d-2) var(--gt-ease-soft), color var(--gt-d-2) var(--gt-ease-soft),
             box-shadow var(--gt-d-2) var(--gt-ease-soft); }
#demucs-btn:hover{ border-color:var(--gt-sig); color:var(--gt-ink-1); box-shadow:var(--gt-e-1), var(--gt-bloom-sm); }
/* Installed = green ink AND a left edge bar, so the state is not colour-only. */
#demucs-btn.installed{ position:relative; border-color:var(--gt-green-dk); color:var(--gt-green-ink); padding-left:18px; }
#demucs-btn.installed::before{ content:""; position:absolute; left:0; top:0; bottom:0; width:3px;
  background:var(--gt-green); border-radius:var(--gt-r-2) 0 0 var(--gt-r-2); }

#pad-toast{ position:fixed; top:20px; left:50%; transform:translateX(-50%); z-index:30;
  background:var(--gt-hud); border:1px solid var(--gt-edge-bezel); color:var(--gt-ink-1);
  border-radius:var(--gt-r-3); padding:8px 18px;
  font-family:var(--gt-font-ui); font-size:var(--gt-t-base); letter-spacing:var(--g-track-desc);
  opacity:0; transition:opacity var(--gt-d-4) var(--gt-ease-out);
  box-shadow:var(--gt-e-2); pointer-events:none; }

#controls-hint{ margin-top:var(--gt-s-2); display:flex; flex-direction:column; gap:3px;
  font-family:var(--gt-font-body); font-size:var(--gt-t-xs); letter-spacing:var(--g-track-desc);
  color:var(--gt-ink-3); }
/* No display: rule here — .pointer-fine / .pointer-coarse own that, and a
   higher-specificity display would defeat the input-type gating. */
#controls-hint .ch b{ color:var(--gt-sig-ink); font-weight:600; }
#controls-hint .gi{ color:var(--gt-ink-2); margin-right:5px; }

/* ── Reaction-buffer slider ───────────────────────────────────────────────── */
#buffer-picker{ display:flex; gap:var(--gt-s-3); align-items:center; margin-top:var(--gt-s-3);
  font-family:var(--gt-font-ui); font-size:var(--gt-t-sm); letter-spacing:var(--gt-track-label);
  flex-wrap:wrap; justify-content:center; }
/* :first-child, not `> span` — #buffer-value is also a direct span child and a
   plain `> span` rule outranks its id selector on specificity. */
#buffer-picker > span:first-child{ color:var(--gt-ink-3); }
#buffer-picker em{ font-family:var(--gt-font-body); font-style:normal; color:var(--gt-ink-3);
  font-size:var(--gt-t-xs); letter-spacing:var(--g-track-desc); }
#buffer-value{ color:var(--gt-sig-ink); min-width:46px; text-align:right; }
#buffer-slider{ width:min(60vw, 320px); accent-color:var(--gt-sig); pointer-events:auto; cursor:pointer;
  border-radius:var(--gt-r-pill); }

/* ── Character picker ─────────────────────────────────────────────────────── */
#char-picker{ display:flex; gap:var(--gt-s-3); align-items:center; margin-top:var(--gt-s-3);
  font-family:var(--gt-font-ui); font-size:var(--gt-t-sm); letter-spacing:var(--gt-track-label); }
#char-picker > span{ color:var(--gt-ink-3); }
.char-opt{ position:relative; pointer-events:auto; cursor:pointer;
  background:var(--gt-pl-1); border:1px solid var(--gt-edge-hair); border-radius:var(--gt-r-3);
  padding:6px 6px 8px; display:flex; flex-direction:column; align-items:center; gap:2px;
  transition:background var(--gt-d-2) var(--gt-ease-soft), border-color var(--gt-d-2) var(--gt-ease-soft),
             box-shadow var(--gt-d-2) var(--gt-ease-soft); }
.char-opt img{ width:64px; height:86px; object-fit:contain; filter:drop-shadow(0 0 8px rgba(25,224,255,.3)); }
.char-opt em{ font-family:var(--gt-font-ui); font-style:normal; font-size:var(--gt-t-xs);
  letter-spacing:var(--gt-track-label); color:var(--gt-ink-3); }
.char-opt:hover{ border-color:var(--gt-edge-bezel); background:var(--gt-pl-2); }
.char-opt.active{ border-color:var(--gt-sig); background:var(--gt-pl-2); box-shadow:var(--gt-bloom-sm); }
.char-opt.active em{ color:var(--gt-ink-1); }
/* Second, non-colour channel for "selected": a lit bar under the tile. */
.char-opt.active::after{ content:""; position:absolute; left:8px; right:8px; bottom:3px; height:2px;
  background:var(--gt-sig); border-radius:var(--gt-r-1); }

/* In-game cockpit avatar */
#cockpit-avatar{ position:fixed; bottom:0; left:50%; transform:translateX(-50%); height:26vh; z-index:9;
  pointer-events:none; opacity:.9; filter:drop-shadow(0 0 24px rgba(25,224,255,.35));
  transition:opacity var(--gt-d-4) var(--gt-ease-soft); }

/* ── Forge ────────────────────────────────────────────────────────────────── */
.forge-title{ font-family:var(--gt-font-ui); font-size:var(--gt-t-3xl); font-weight:800;
  letter-spacing:var(--gt-track-head); color:var(--gt-ink-1); text-shadow:0 0 30px var(--gt-sig);
  text-transform:uppercase; line-height:var(--gt-lh-head); text-align:center; }
.forge-sub{ font-family:var(--gt-font-ui); font-size:var(--gt-t-md); letter-spacing:var(--gt-track-label);
  color:var(--gt-sig-2-ink); text-align:center; }
#forge-spinner{ width:120px; height:120px; border:4px solid var(--gt-pl-3); border-top-color:var(--gt-sig);
  border-radius:50%; animation:spin .8s linear infinite; margin:var(--gt-s-3); }
@keyframes spin{ to{ transform:rotate(360deg) } }
.forge-status{ font-family:var(--gt-font-body); font-size:var(--gt-t-base); color:var(--gt-ink-3);
  letter-spacing:var(--g-track-desc); }

/* ── Settings ─────────────────────────────────────────────────────────────── */
#settings-reinforce{ display:flex; flex-direction:column; gap:var(--gt-s-2);
  margin-bottom:var(--gt-s-5); align-items:center; }
.setting-label{ font-family:var(--gt-font-ui); font-size:var(--gt-t-base); font-weight:600;
  letter-spacing:var(--gt-track-label); text-transform:uppercase; color:var(--gt-ink-2); }
.setting-note{ font-family:var(--gt-font-body); font-size:var(--gt-t-xs); line-height:var(--gt-lh-body);
  letter-spacing:var(--g-track-desc); color:var(--gt-ink-3); text-align:center; }
#settings-kick-slider{ width:100%; accent-color:var(--gt-sig); cursor:pointer; }
#pause-hint{ font-family:var(--gt-font-ui); font-size:var(--gt-t-sm);
  letter-spacing:var(--gt-track-label); color:var(--gt-ink-3); }

/* Local loops (list rows are built by app.bundle.js — do not restyle by tag) */
#local-loops-list{ display:flex; flex-direction:column; gap:var(--gt-s-2); width:min(90vw, 600px);
  max-height:60vh; overflow-y:auto; padding-right:10px; margin-top:var(--gt-s-5); text-align:left; }

/* ── Results ──────────────────────────────────────────────────────────────── */
#result-rank{ font-size:180px; font-weight:900; color:var(--gt-ink-1); text-shadow:0 0 50px var(--gt-gold);
  line-height:var(--gt-lh-tight); }
#result-stats{ font-family:var(--gt-font-ui); font-size:var(--gt-t-md); color:var(--gt-ink-2);
  text-align:center; line-height:1.8; }
#result-stats b{ color:var(--gt-ink-1); font-variant-numeric:tabular-nums; }
#ownership-note{ font-family:var(--gt-font-body); font-size:var(--gt-t-sm);
  letter-spacing:var(--g-track-desc); color:var(--gt-ink-3); text-align:center; }

/* ── Jukebox / GITATO RADIO ───────────────────────────────────────────────── */
#jb-title{ font-family:var(--gt-font-ui); font-size:var(--gt-t-2xl); font-weight:900;
  letter-spacing:var(--gt-track-head); color:var(--gt-ink-1); text-shadow:0 0 28px var(--gt-sig-2); }
#jb-now{ text-align:center; margin:6px 0 4px; }
#jb-genre{ font-family:var(--gt-font-ui); font-size:var(--gt-t-xl); font-weight:800;
  letter-spacing:var(--gt-track-head); color:var(--gt-sig-ink); text-transform:uppercase;
  text-shadow:0 0 20px var(--gt-sig); }
#jb-bpm{ font-size:var(--gt-t-base); letter-spacing:var(--gt-track-tag); color:var(--gt-ink-3); }
#jb-viz{ display:flex; gap:6px; justify-content:center; height:48px; align-items:flex-end; margin-top:var(--gt-s-3); }
#jb-viz span{ width:10px; background:linear-gradient(0deg,var(--gt-sig-2),var(--gt-sig)); border-radius:var(--gt-r-1);
  height:20%; box-shadow:0 0 10px var(--gt-sig); animation:jbbar .6s var(--gt-ease-soft) infinite alternate; }
#jb-viz span:nth-child(2){ animation-delay:.1s } #jb-viz span:nth-child(3){ animation-delay:.2s }
#jb-viz span:nth-child(4){ animation-delay:.3s } #jb-viz span:nth-child(5){ animation-delay:.15s }
@keyframes jbbar{ to{ height:100% } }
#jb-sliders{ display:flex; flex-direction:column; gap:var(--gt-s-2); width:min(86vw,420px); margin-top:var(--gt-s-2); }
#jb-sliders label{ display:flex; align-items:center; justify-content:space-between; gap:var(--gt-s-3);
  font-family:var(--gt-font-ui); font-size:var(--gt-t-sm); font-weight:600;
  letter-spacing:var(--gt-track-label); color:var(--gt-ink-2); }
#jb-sliders input[type=range]{ flex:1; accent-color:var(--gt-sig-2); cursor:pointer; }
#jb-controls{ display:flex; gap:var(--gt-s-3); align-items:center; margin-top:var(--gt-s-4); }
.jb-btn{ pointer-events:auto; cursor:pointer; width:52px; height:52px; border-radius:50%;
  background:linear-gradient(180deg, var(--gt-pl-2), var(--gt-pl-1));
  border:1px solid var(--gt-edge-bezel); color:var(--gt-ink-1); box-shadow:var(--gt-e-1);
  display:flex; align-items:center; justify-content:center;
  transition:border-color var(--gt-d-2) var(--gt-ease-soft), box-shadow var(--gt-d-2) var(--gt-ease-soft),
             transform var(--gt-d-1) var(--gt-ease-snap); }
.jb-btn .gi{ width:24px; height:24px; }
.jb-btn:hover{ border-color:var(--gt-sig); box-shadow:var(--gt-e-1), var(--gt-bloom-sm); transform:translateY(-2px); }
.jb-btn:active{ transform:translateY(1px); }
/* The skip button is the transport's primary: larger AND on the second signal. */
.jb-btn.big{ width:64px; height:64px; border-color:var(--gt-sig-2); }
.jb-btn.big .gi{ width:30px; height:30px; }
#jb-learn{ font-family:var(--gt-font-ui); font-size:var(--gt-t-sm); letter-spacing:var(--gt-track-label);
  color:var(--gt-ink-3); margin-top:var(--gt-s-4); }
#jb-learn span{ color:var(--gt-sig-ink); }

/* ── mobile ───────────────────────────────────────────────────────────────── */
@media (max-width: 640px){
  #hud-top{ top:14px; padding:0 16px; }
  #combo-x{ font-size:34px; }
  #combo-label{ font-size:11px; }
  #score{ font-size:26px; }
  #score-label{ font-size:10px; }
  #hud-left{ left:10px; } #hud-right{ right:10px; }
  #hud-left,#hud-right{ width:14px; height:32vh; }
  /* The meter labels used to be centred on a 14px-wide column pinned 10px from
     the viewport edge, so "ENERGY" (~42px) was clipped at the screen edge. They
     are now anchored to the meter's outer edge at every width (see the base
     rule). One rung down on the tracking scale, since .30em is a caps-tagline
     value on a small label. 11px, not 9: 9px was below the legible floor. */
  #energy-label,#drop-label{ font-size:11px; letter-spacing:var(--gt-track-label); }
  #judgement{ font-size:32px; }
  #rank-flash{ font-size:110px; }
  #rec-dot{ top:14px; font-size:12px; }
  #theme-badge{ bottom:12px; font-size:11px; }
  #cockpit-avatar{ height:16vh; }
  #reticle{ width:74px; height:74px; margin:-37px 0 0 -37px; }

  .screen{ gap:var(--gt-s-3); padding:var(--gt-s-5) 0; }
  #logo{ height:min(16vh, 120px); }
  .menu{ gap:9px; width:min(92vw,420px); }
  .btn{ padding:var(--gt-s-3) var(--gt-s-4); }
  #theme-picker{ flex-wrap:wrap; justify-content:center; max-width:94vw; }
  /* 44px touch targets (were 32 / 34 px) */
  .theme-opt{ padding:12px 14px; min-height:44px; }
  #apk-link{ min-height:44px; padding:10px 16px; }
  #char-picker{ flex-wrap:wrap; justify-content:center; }
  .char-opt img{ width:52px; height:70px; }
  #buffer-picker{ max-width:94vw; }
  #buffer-slider{ width:min(70vw,320px); }
  #controls-hint{ padding:0 14px; text-align:center; align-items:center; }

  #forge-spinner{ width:80px; height:80px; }
  #result-rank{ font-size:110px; }
  #result-stats{ padding:0 16px; }
  #ownership-note{ padding:0 16px; }
  .jb-btn{ width:56px; height:56px; }
  .jb-btn.big{ width:68px; height:68px; }
}

/* ═══════════════════════════════════════════════════════════════════════════
   MOTION PREFERENCE
   ds.css already collapses every duration. These rules give the decorative
   loops a sensible resting state instead of the last frame of the keyframe.
   ═══════════════════════════════════════════════════════════════════════════ */
@media (prefers-reduced-motion: reduce){
  #forge-spinner{ animation:none; border-top-color:var(--gt-sig); border-right-color:var(--gt-sig); }
  #jb-viz span{ animation:none; height:60%; }
  #jb-viz span:nth-child(2){ height:85% } #jb-viz span:nth-child(3){ height:45% }
  #jb-viz span:nth-child(4){ height:100% } #jb-viz span:nth-child(5){ height:70% }
  #rec-dot{ animation:none; opacity:1; }
  #drop-btn.ready{ animation:none; }
  .btn:hover, .btn.primary:hover, .jb-btn:hover, .jb-btn:active, .btn:active{ transform:none; }
}

/* ── Focus beats hover and beats the lit plates ───────────────────────────────
   The :focus-visible rules at the top tie on specificity with .btn:hover,
   .btn.primary, .char-opt.active and .jb-btn:hover, and those come later, so
   the ring vanished while the pointer rested on a focused control and never
   showed on the primary plate at all (WCAG 2.4.7). Last in the file, higher
   specificity. */
.btn:hover:focus-visible, .btn.primary:focus-visible, .btn.primary:hover:focus-visible,
.char-opt.active:focus-visible, .jb-btn:hover:focus-visible,
#apk-link:hover:focus-visible, #demucs-btn:hover:focus-visible{
  box-shadow:var(--gt-focus-ring);
}
