/* Neon Drift - shell lane stylesheet (ADR-09, ADR-11, FR-17).
   Every HUD surface is pinned to the top band of the viewport so the centre of the
   play area is never covered: G-15 measures DOM bounding boxes from 360px to 2560px. */

:root {
  /* Vertical bands the HUD is allowed to occupy. Nothing here may reach the centre. */
  --hud-band: min(12vh, 120px);
  --screen-band: min(18vh, 200px);

  --bg: #04060c;
  --ink: #d8f6ff;
  --dim: #6e8fa0;
  --cyan: #2ee9ff;
  --magenta: #ff43e0;
  --amber: #ffd36e;

  --mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Monaco, Consolas,
          "Liberation Mono", "Courier New", monospace;

  --glow-cyan: 0 0 clamp(3px, 0.9vmin, 10px) rgba(46, 233, 255, 0.75),
               0 0 clamp(8px, 2.4vmin, 28px) rgba(46, 233, 255, 0.35);
  --glow-magenta: 0 0 clamp(3px, 0.9vmin, 10px) rgba(255, 67, 224, 0.75),
                  0 0 clamp(8px, 2.4vmin, 28px) rgba(255, 67, 224, 0.32);
}

*, *::before, *::after { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  height: 100%;
  width: 100%;
  overflow: hidden;
  overscroll-behavior: none;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--mono);
  font-variant-numeric: tabular-nums;
  -webkit-font-smoothing: antialiased;
  -webkit-tap-highlight-color: transparent;
  user-select: none;
  touch-action: none;
}

/* ---------- canvas ---------- */

#canvas {
  position: fixed;
  inset: 0;
  display: block;
  width: 100%;
  height: 100%;
  z-index: 0;
  background: radial-gradient(120% 90% at 50% 50%, #0a1224 0%, #04060c 62%, #000 100%);
}

/* ---------- HUD (top band only) ---------- */

#hud {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  max-height: var(--hud-band);
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: clamp(8px, 3vw, 48px);
  padding: clamp(8px, 2.2vmin, 26px) clamp(10px, 3vmin, 44px);
  padding-top: max(clamp(8px, 2.2vmin, 26px), env(safe-area-inset-top, 0px));
  z-index: 3;
  pointer-events: none;
  opacity: 0;
  transition: opacity 220ms ease;
  /* hud.js escalates --hud-scale when its own centre-clearance check fails.
     A transform is honoured by getBoundingClientRect, so the escalation is
     measurable rather than decorative (FR-17). */
  transform: scale(var(--hud-scale, 1));
  transform-origin: top center;
}

#hud[data-screen="playing"] { opacity: 1; }

.hud-row {
  display: flex;
  flex-direction: column;
  gap: clamp(1px, 0.5vmin, 6px);
  min-width: 0;
}

.hud-row--best { align-items: flex-end; text-align: right; }

/* G-20 / G-22 — lives and stage readouts. This lane owns the elements, the
   classes and the geometry; src/render/hud.js and src/main.js own the values.
   Both sit in the same top band as SCORE and BEST, so FR-17's centre clearance
   is unaffected by them. */

.hud-row--lives,
.hud-row--stage { align-items: center; text-align: center; }

.hud-value-lives,
.hud-value-stage {
  font-size: clamp(13px, min(4vw, 3vh), 32px);
  letter-spacing: clamp(0.5px, 0.25vw, 3px);
}

.hud-value-stage {
  color: var(--amber);
  text-shadow: 0 0 clamp(3px, 0.9vmin, 10px) rgba(255, 211, 110, 0.65);
}

.hud-lives-pips {
  display: flex;
  gap: clamp(2px, 0.6vw, 5px);
  align-items: center;
  justify-content: center;
}

.hud-life {
  display: block;
  width: clamp(4px, 1.1vw, 8px);
  height: clamp(4px, 1.1vw, 8px);
  border-radius: 50%;
  background: var(--cyan);
  box-shadow: 0 0 clamp(3px, 0.9vmin, 9px) rgba(46, 233, 255, 0.8);
  transition: background-color 160ms ease, opacity 160ms ease;
}

.hud-life[data-spent="true"] {
  background: rgba(110, 143, 160, 0.35);
  box-shadow: none;
}

/* FR-46: training mode has no countable lives, so the pips stand down and the
   numeric readout carries the mode instead. */
.hud-row--lives[data-mode="training"] .hud-lives-pips { display: none; }
.hud-row--lives[data-mode="training"] .hud-value-lives { color: var(--amber); text-shadow: 0 0 clamp(3px, 0.9vmin, 10px) rgba(255, 211, 110, 0.65); }

/* FR-45: the post-hit invulnerable window has to be VISIBLE. Driven by the sim
   through `data-invuln` on the row (or on #hud) — never by a renderer-only timer,
   so the flash and the collision rule cannot drift apart (ADR-25). */
.hud-row--lives[data-invuln="true"],
#hud[data-invuln="true"] .hud-row--lives { animation: hud-invuln 420ms ease-in-out infinite; }

@keyframes hud-invuln {
  0%, 100% { opacity: 1; filter: drop-shadow(0 0 0 rgba(255, 211, 110, 0)); }
  50%      { opacity: 0.35; filter: drop-shadow(0 0 10px rgba(255, 211, 110, 0.9)); }
}

/* G-22 / FR-48 — the brief stage-advance announcement. Bottom band: clear of the
   HUD band above and of the central 40% x 40% play area (FR-17). */
.stage-announce {
  position: fixed;
  left: 50%;
  bottom: max(14vh, clamp(48px, 12vmin, 132px));
  transform: translateX(-50%);
  margin: 0;
  z-index: 5;
  pointer-events: none;
  white-space: nowrap;
  font-size: clamp(11px, min(3.4vw, 2.4vh), 24px);
  letter-spacing: clamp(2px, 1vw, 10px);
  text-indent: clamp(2px, 1vw, 10px);
  text-transform: uppercase;
  color: var(--amber);
  text-shadow: 0 0 clamp(5px, 1.6vmin, 18px) rgba(255, 211, 110, 0.85);
  opacity: 0;
  transition: opacity 220ms ease;
}

.stage-announce[data-active="true"] { opacity: 1; }
.stage-announce:empty { display: none; }

/* Speed meter: hud.js drives `--speed` and the fill's scaleX. */
.hud-meter {
  position: absolute;
  left: clamp(10px, 3vmin, 44px);
  right: clamp(10px, 3vmin, 44px);
  bottom: 0;
  height: 2px;
  background: rgba(110, 143, 160, 0.22);
  overflow: hidden;
}

.hud-meter-fill {
  width: 100%;
  height: 100%;
  transform: scaleX(0);
  transform-origin: left center;
  background: linear-gradient(90deg, var(--cyan) 0%, var(--magenta) 100%);
  box-shadow: 0 0 8px rgba(46, 233, 255, 0.7);
}

/* Impact / near-miss flashes toggled by hud.js. */
#hud.hud--impact { animation: hud-impact 260ms ease-out; }
#hud.hud--near-miss { animation: hud-near-miss 260ms ease-out; }

@keyframes hud-impact {
  0%   { filter: drop-shadow(0 0 0 rgba(255, 67, 224, 0)); }
  25%  { filter: drop-shadow(0 0 18px rgba(255, 67, 224, 0.95)); }
  100% { filter: drop-shadow(0 0 0 rgba(255, 67, 224, 0)); }
}

@keyframes hud-near-miss {
  0%   { filter: drop-shadow(0 0 0 rgba(46, 233, 255, 0)); }
  30%  { filter: drop-shadow(0 0 12px rgba(46, 233, 255, 0.8)); }
  100% { filter: drop-shadow(0 0 0 rgba(46, 233, 255, 0)); }
}

.hud-label {
  font-size: clamp(8px, min(2.2vw, 1.5vh), 15px);
  letter-spacing: clamp(1.5px, 0.7vw, 7px);
  color: var(--dim);
  text-transform: uppercase;
}

.hud-value {
  font-size: clamp(18px, min(6vw, 4.4vh), 54px);
  line-height: 1;
  letter-spacing: clamp(0.5px, 0.35vw, 4px);
  color: var(--cyan);
  text-shadow: var(--glow-cyan);
}

.hud-value-alt {
  color: var(--magenta);
  text-shadow: var(--glow-magenta);
  font-size: clamp(14px, min(4.4vw, 3.2vh), 38px);
}

/* ---------- screens (top band only, so the tunnel stays visible) ---------- */

.screen {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  max-height: var(--screen-band);
  display: none;
  flex-direction: column;
  align-items: center;
  justify-content: flex-start;
  gap: clamp(2px, 0.9vmin, 12px);
  padding: clamp(10px, 3vmin, 34px) clamp(12px, 4vmin, 56px);
  padding-top: max(clamp(10px, 3vmin, 34px), env(safe-area-inset-top, 0px));
  z-index: 4;
  pointer-events: none;
  text-align: center;
}

.screen[data-active="true"] { display: flex; }

.screen-heading {
  margin: 0;
  font-size: clamp(20px, min(8.4vw, 7vh), 82px);
  line-height: 1.02;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: clamp(2px, 1.5vw, 18px);
  text-indent: clamp(2px, 1.5vw, 18px); /* balance the trailing letter-space */
  color: var(--ink);
  text-shadow: var(--glow-cyan), 0 0 clamp(14px, 4vmin, 46px) rgba(255, 67, 224, 0.4);
}

/* R-01 information hierarchy. "RUN ENDED" used to render at 36.8px while the SCORE
   below it rendered at 23.2px — the label outranked the payload, and PC-05 says the
   score is what has to be memorable after a run. The status line is now a small
   kicker and the score is the dominant element on the screen (see .screen-stat--score
   below). Demoted deliberately, not shrunk to make room. */
.screen-heading-small {
  font-size: clamp(10px, min(2.6vw, 1.9vh), 19px);
  letter-spacing: clamp(2px, 1vw, 9px);
  color: var(--magenta);
  opacity: 0.85;
  text-shadow: 0 0 clamp(4px, 1.2vmin, 12px) rgba(255, 67, 224, 0.5);
}

/* R-01. The flavour line and the line that tells you the CONTROLS were the same size,
   so decoration ranked equal with the only instruction on the screen. Flavour is now
   clearly subordinate: smaller, dimmer, and tighter than the hint below it. */
.screen-sub {
  margin: 0;
  font-size: clamp(7px, min(1.9vw, 1.3vh), 13px);
  letter-spacing: clamp(1px, 0.55vw, 5px);
  text-transform: uppercase;
  color: var(--dim);
  opacity: 0.62;
}

/* R-02 control discoverability. The primary action on both screens used to exist only
   as a sentence ("press any key or tap to run again") — not a control, not focusable,
   and invisible to anyone who does not read the hint. It is now a real button; the hint
   remains as the keyboard shortcut it always described. Deliberately NOT a second audio
   control: ADR-22 ruled that out, and this improves discoverability without it. */
.screen-action {
  font-family: var(--mono);
  font-size: clamp(11px, min(3.2vw, 2.2vh), 22px);
  letter-spacing: clamp(2px, 0.9vw, 8px);
  text-indent: clamp(2px, 0.9vw, 8px);
  text-transform: uppercase;
  color: var(--ink);
  background: rgba(46, 233, 255, 0.10);
  border: 1px solid var(--cyan);
  border-radius: 2px;
  padding: clamp(8px, 1.8vmin, 15px) clamp(16px, 4vmin, 34px);
  cursor: pointer;
  text-shadow: var(--glow-cyan);
  transition: color 140ms ease, border-color 140ms ease, background-color 140ms ease;
}

.screen-action:hover { background: rgba(46, 233, 255, 0.2); }
.screen-action:active { background: rgba(46, 233, 255, 0.3); }
.screen-action:focus { outline: 2px solid var(--magenta); outline-offset: 3px; }

.screen-hint {
  margin: 0;
  font-size: clamp(9px, min(2.6vw, 1.8vh), 18px);
  letter-spacing: clamp(1px, 0.5vw, 5px);
  text-transform: uppercase;
  color: var(--cyan);
  opacity: 0.92;
  animation: pulse 2.4s ease-in-out infinite;
}

.screen-stats {
  margin: 0;
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: center;
  gap: clamp(8px, 2.6vw, 40px);
}

/* The score is the result; best is context; the seed is diagnostic. Rank them by
   size and stack the score on its own line so it is read first (R-01). */
.screen-stat--score {
  flex-basis: 100%;
  justify-content: center;
}

.screen-stat {
  display: inline-flex;
  align-items: baseline;
  gap: clamp(4px, 1vw, 10px);
}

/* Two-class selectors so these beat the shared .hud-label / .hud-value sizes
   that hud.js also applies to these nodes. */
.screen-stat .stat-label {
  font-size: clamp(8px, min(2.2vw, 1.5vh), 15px);
  letter-spacing: clamp(1px, 0.5vw, 5px);
  color: var(--dim);
}

.screen-stat .stat-value {
  font-size: clamp(13px, min(3.4vw, 2.4vh), 26px);
  letter-spacing: clamp(0.5px, 0.2vw, 2px);
  color: var(--cyan);
  text-shadow: var(--glow-cyan);
}

.screen-stat .stat-value-alt { color: var(--magenta); text-shadow: var(--glow-magenta); }

.screen-stat .stat-value-seed {
  color: var(--amber);
  text-shadow: 0 0 clamp(3px, 0.9vmin, 10px) rgba(255, 211, 110, 0.6);
  font-size: clamp(9px, min(2.2vw, 1.6vh), 16px);
  opacity: 0.8;
}

/* The dominant element on the game-over screen. */
.screen-stat--score .stat-value {
  font-size: clamp(34px, min(11vw, 8.4vh), 104px);
  letter-spacing: clamp(1px, 0.4vw, 4px);
  line-height: 1;
}

.screen-stat--score .stat-label {
  font-size: clamp(9px, min(2.4vw, 1.6vh), 16px);
}

/* R-01. "NEW PERSONAL BEST" is the single most meaningful thing that can happen in a
   run, and it rendered at 14.4px — below the navigation hint telling you to press a key.
   A celebration ranked under wayfinding is a hierarchy inversion; it now outranks both
   the hint and the surrounding stats. */
.over-new-best {
  margin: 0;
  font-size: clamp(12px, min(3.6vw, 2.5vh), 26px);
  letter-spacing: clamp(2px, 1vw, 10px);
  text-transform: uppercase;
  color: var(--amber);
  text-shadow: 0 0 clamp(4px, 1.2vmin, 14px) rgba(255, 211, 110, 0.8);
}

/* ---------- title screen: difficulty, lives and settings, directly on it ----------

   FR-37 / ADR-28 (supersedes ADR-22). The user asked twice for the settings to be
   on the main page, so the title screen now carries a four-preset difficulty
   selector, a lives/training selector and its own settings control.

   ADR-28's stated consequence is that FR-13/FR-17 is the binding constraint and is
   stricter now that the screen carries more: NOTHING here may reach the central
   40% x 40% of the viewport at 360, 768, 1280 or 2560 px. The sizes below are
   chosen to leave real margin rather than to fill the band, and `src/ui/title.js`
   measures the result and scales `--title-scale` down if any of it is wrong. The
   guarantee is behaviour; this stylesheet is only the first guess at it. */

.screen--title {
  /* The band cap the other screens use would clip nothing (overflow is visible)
     while making the section's own box lie about its height. The height here is
     the content's real height, which is what title.js measures and holds. */
  max-height: none;
  gap: clamp(3px, 0.8vmin, 9px);
  padding-top: max(clamp(8px, 2.2vmin, 24px), env(safe-area-inset-top, 0px));
  padding-bottom: clamp(2px, 0.5vmin, 6px);
  transform: scale(var(--title-scale, 1));
  transform-origin: top center;
}

/* The hint is wayfinding, and it now sits below controls that say the same thing
   in a more direct way; it does not need the size it had when it was the only
   instruction on the screen (R-01). */
.screen--title .screen-hint { font-size: clamp(9px, min(2.3vw, 1.5vh), 15px); }

/* Demoted from the v0.2.0 sizes: the heading was the only thing on this screen and
   could afford to be enormous. It now shares the band with the controls the user
   asked for, and a title that crowds them out would be the wrong trade (R-01). */
.screen--title .screen-heading {
  font-size: clamp(18px, min(6.2vw, 4.2vh), 50px);
  letter-spacing: clamp(2px, 1.1vw, 13px);
  text-indent: clamp(2px, 1.1vw, 13px);
}

.screen--title .screen-sub { font-size: clamp(7px, min(1.6vw, 1.1vh), 11px); }

.screen--title .screen-action {
  font-size: clamp(11px, min(3vw, 1.9vh), 19px);
  padding: clamp(5px, 1vmin, 10px) clamp(14px, 3.4vmin, 30px);
}

/* ---------- the two selectors ---------- */

.title-setup {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-start;
  justify-content: center;
  gap: clamp(6px, 2vw, 34px) clamp(10px, 3vw, 48px);
  max-width: 100%;
  /* .screen is pointer-events: none so the tunnel stays draggable through it;
     these are real controls and have to take the pointer back. */
  pointer-events: auto;
}

.title-group {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: clamp(2px, 0.6vmin, 5px);
  min-width: 0;
}

.title-group-label {
  font-size: clamp(7px, min(1.7vw, 1.2vh), 11px);
  letter-spacing: clamp(1.5px, 0.7vw, 6px);
  text-indent: clamp(1.5px, 0.7vw, 6px);
  text-transform: uppercase;
  color: var(--dim);
  opacity: 0.75;
}

.title-choice {
  display: flex;
  flex-wrap: wrap;
  align-items: stretch;
  justify-content: center;
  gap: clamp(3px, 0.8vw, 8px);
  max-width: 100%;
}

.title-option {
  font-family: var(--mono);
  font-size: clamp(9px, min(2.2vw, 1.5vh), 14px);
  line-height: 1.2;
  letter-spacing: clamp(0.8px, 0.4vw, 4px);
  text-indent: clamp(0.8px, 0.4vw, 4px);
  text-transform: uppercase;
  white-space: nowrap;
  color: var(--dim);
  background: rgba(6, 12, 22, 0.66);
  border: 1px solid rgba(46, 233, 255, 0.24);
  border-radius: 2px;
  padding: clamp(4px, 0.95vmin, 9px) clamp(7px, 1.9vmin, 16px);
  margin: 0;
  cursor: pointer;
  transition: color 140ms ease, border-color 140ms ease, background-color 140ms ease;
}

.title-option:hover { color: var(--ink); border-color: rgba(46, 233, 255, 0.6); }

/* The selected preset, stated in the same way the settings toggles state "ON":
   colour AND a border, never colour alone. */
.title-option[aria-pressed="true"] {
  color: var(--ink);
  background: rgba(46, 233, 255, 0.16);
  border-color: var(--cyan);
  text-shadow: 0 0 clamp(3px, 0.9vmin, 9px) rgba(46, 233, 255, 0.75);
}

.title-group--lives .title-option[aria-pressed="true"] {
  background: rgba(255, 67, 224, 0.14);
  border-color: var(--magenta);
  text-shadow: 0 0 clamp(3px, 0.9vmin, 9px) rgba(255, 67, 224, 0.7);
}

/* :focus, not only :focus-visible — G-11 asserts the keyboard route is visible,
   and a ring that depends on the browser's heuristic is a ring that sometimes
   is not there. */
.title-option:focus,
.title-actions .title-settings:focus {
  outline: 2px solid var(--magenta);
  outline-offset: 2px;
  color: var(--ink);
}

/* FR-32 / FR-46: never changeable mid-run. The title screen is already hidden
   during play; this is what it looks like if anything ever shows it anyway. */
.title-option:disabled { opacity: 0.4; cursor: default; }

/* ---------- best for the selected difficulty, and the training notice ---------- */

.title-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  justify-content: center;
  gap: clamp(4px, 1.4vw, 20px);
  max-width: 100%;
}

.title-best {
  margin: 0;
  display: inline-flex;
  align-items: baseline;
  gap: clamp(3px, 0.8vw, 9px);
}

.title-best-label {
  font-size: clamp(7px, min(1.7vw, 1.2vh), 11px);
  letter-spacing: clamp(1.5px, 0.7vw, 6px);
  text-transform: uppercase;
  color: var(--dim);
}

.title-best-value {
  font-size: clamp(11px, min(3vw, 2vh), 20px);
  letter-spacing: clamp(0.5px, 0.2vw, 2px);
  color: var(--magenta);
  text-shadow: var(--glow-magenta);
}

/* FR-36: a best set on CRUISE is not the same record as one set on EXTREME, so
   the number never appears without the preset it belongs to. */
.title-best-scope {
  font-size: clamp(7px, min(1.6vw, 1.1vh), 11px);
  letter-spacing: clamp(1px, 0.5vw, 5px);
  text-transform: uppercase;
  color: var(--dim);
  opacity: 0.8;
}

/* FR-47 / ADR-26: stated before the run, beside the record it applies to.
   Always present, and raised to amber while training is the live choice. */
.title-note {
  margin: 0;
  font-size: clamp(7px, min(1.7vw, 1.2vh), 11px);
  letter-spacing: clamp(1px, 0.5vw, 5px);
  text-transform: uppercase;
  color: var(--dim);
  opacity: 0.62;
  transition: color 160ms ease, opacity 160ms ease;
}

.title-note--active {
  color: var(--amber);
  opacity: 1;
  text-shadow: 0 0 clamp(3px, 1vmin, 10px) rgba(255, 211, 110, 0.55);
}

/* ---------- the action row ---------- */

.title-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: clamp(6px, 1.8vw, 22px);
  pointer-events: auto;
}

/* ADR-28: a settings control directly on the title screen. The fixed launcher
   (bottom right) stands down while this one is up, so there is exactly one
   settings control on screen at a time — ADR-22's objection to two controls for
   one thing survives its supersession. */
.title-actions .title-settings {
  font-size: clamp(9px, min(2.2vw, 1.5vh), 14px);
  padding: clamp(4px, 0.95vmin, 9px) clamp(8px, 2vmin, 17px);
}

[hidden] { display: none; }

@keyframes pulse {
  0%, 100% { opacity: 0.95; }
  50%      { opacity: 0.42; }
}

/* ---------- fatal surface (FR-16 / ADR-10) ---------- */

#fatal {
  position: fixed;
  inset: 0;
  z-index: 9;
  display: none;
  align-items: center;
  justify-content: center;
  padding: clamp(16px, 6vmin, 64px);
  background: rgba(3, 5, 10, 0.965);
}

#fatal[data-active="true"] { display: flex; }

.fatal-box {
  max-width: 46ch;
  border: 1px solid rgba(255, 67, 224, 0.55);
  border-radius: 2px;
  padding: clamp(14px, 4vmin, 40px);
  background: rgba(10, 4, 16, 0.9);
  box-shadow: 0 0 clamp(12px, 4vmin, 48px) rgba(255, 67, 224, 0.25);
}

.fatal-title {
  margin: 0 0 clamp(8px, 2vmin, 20px);
  font-size: clamp(12px, min(3.4vw, 2.6vh), 24px);
  letter-spacing: clamp(2px, 0.9vw, 9px);
  text-transform: uppercase;
  color: var(--magenta);
  text-shadow: var(--glow-magenta);
}

.fatal-message {
  margin: 0;
  font-size: clamp(12px, min(3.2vw, 2.4vh), 20px);
  line-height: 1.65;
  letter-spacing: 0.4px;
  color: var(--ink);
  overflow-wrap: anywhere;
}

/* ---------- narrow phones: tighten the bands further ---------- */

@media (max-width: 420px) {
  :root {
    --hud-band: min(11vh, 92px);
    --screen-band: min(17vh, 150px);
  }
  .screen-sub { display: none; }
  /* Two selectors and four presets do not fit one 360 px row; they stack rather
     than shrink to unreadable, which is what FR-13 means by "shrink or stack". */
  .title-setup { gap: 5px 10px; }
  .title-choice { gap: 3px; }
  .title-option { letter-spacing: 0.8px; text-indent: 0.8px; padding: 4px 6px; }
  .title-actions { gap: 6px; }
}

/* ---------- landscape phones have very little height to spare ---------- */

@media (max-height: 480px) {
  :root {
    --hud-band: min(14vh, 78px);
    --screen-band: min(20vh, 112px);
  }
  .screen-sub { display: none; }
  .screen { padding-top: 6px; padding-bottom: 4px; gap: 2px; }
  #hud { padding-top: 6px; padding-bottom: 4px; }
  .screen--title { padding-top: 5px; padding-bottom: 3px; gap: 2px; }
  .title-setup { gap: 4px 12px; }
  .title-group { gap: 1px; }
  .title-option { padding: 3px 7px; }
  .screen--title .screen-action { padding: 4px 12px; }
  .title-actions .title-settings { padding: 3px 8px; }
  .hud-lives-pips { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  * { animation-duration: 0.001ms !important; animation-iteration-count: 1 !important; }
  #hud { transition: none; }
  .screen-hint { opacity: 0.92; }
}

/* settings:start */
/* Settings overlay — FR-28, FR-29 / ADR-17, ADR-11.

   Same visual language as the rest of the shell: near-black glass, a 1px cyan
   edge, uppercase letter-spaced labels, magenta for anything destructive.

   Geometry: the panel is pinned to the SAME top band the screens use, because
   G-14 holds the open panel to FR-17 — nothing may reach the central 40% x 40%
   of the viewport at 360, 768, 1280 or 2560 px. settings.js measures that and
   scales the panel through --settings-scale until it is true; the CSS below only
   has to keep the panel top-anchored and narrower than the viewport. */

/* FR-28: the panel opens from the title screen AND from the game-over screen.
   Each screen carries its own launcher INSIDE it — `#title-settings` and
   `#settings-launch` — rather than one shared control pinned to the viewport.

   The fixed-position version this replaces failed twice over. A control anchored
   to the bottom-right corner is not part of either screen: it was invisible to an
   inventory that walks a screen's subtree, `offsetParent` is null for a fixed
   element so half the usual visibility predicates report it as absent, and hiding
   it while the title screen showed its own control left the game-over screen with
   no settings route at all. Two in-screen buttons, exactly one visible at a time
   because its screen is, is simpler than one control with two hiding rules. */
.settings-launch { margin: 0; }

/* The action row on the game-over screen, mirroring `.title-actions`. */
.over-actions {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: clamp(6px, 1.8vw, 22px);
  pointer-events: auto;
}

/* FR-28: not a pause feature. No control, no keyboard route, no overlay. */
body[data-screen="playing"] .settings-launch { display: none; }
body[data-settings="open"] .settings-launch { display: none; }

/* The panel occupies the band the active screen was using, so the two never
   stack on top of each other in the one strip of viewport both are allowed. */
body[data-settings="open"] .screen { display: none; }

.settings-button,
.settings-launch {
  font-family: var(--mono);
  font-size: clamp(9px, min(2.4vw, 1.7vh), 15px);
  line-height: 1;
  letter-spacing: clamp(1px, 0.45vw, 4.5px);
  text-indent: clamp(1px, 0.45vw, 4.5px);
  text-transform: uppercase;
  color: var(--cyan);
  background: rgba(6, 12, 22, 0.72);
  border: 1px solid rgba(46, 233, 255, 0.42);
  border-radius: 2px;
  padding: clamp(6px, 1.5vmin, 11px) clamp(9px, 2.2vmin, 18px);
  cursor: pointer;
  text-shadow: 0 0 clamp(3px, 0.8vmin, 8px) rgba(46, 233, 255, 0.55);
  transition: color 140ms ease, border-color 140ms ease, background-color 140ms ease;
}

.settings-button:hover,
.settings-launch:hover {
  color: var(--ink);
  border-color: var(--cyan);
  background: rgba(46, 233, 255, 0.14);
}

.settings-button:active,
.settings-launch:active { background: rgba(46, 233, 255, 0.22); }

/* :focus, not only :focus-visible — G-13 asserts the keyboard route is visible,
   and a ring that depends on the browser's heuristic is a ring that sometimes
   is not there. */
.settings-button:focus,
.settings-launch:focus,
.settings-toggle:focus {
  outline: 2px solid var(--magenta);
  outline-offset: 2px;
  color: var(--ink);
}

.settings-button--danger {
  color: var(--magenta);
  border-color: rgba(255, 67, 224, 0.45);
  text-shadow: 0 0 clamp(3px, 0.8vmin, 8px) rgba(255, 67, 224, 0.5);
}

.settings-button--danger:hover {
  color: var(--ink);
  border-color: var(--magenta);
  background: rgba(255, 67, 224, 0.16);
}

/* ---------- the panel ---------- */

.settings-panel {
  position: fixed;
  top: max(clamp(6px, 1.8vmin, 20px), env(safe-area-inset-top, 0px));
  left: 50%;
  transform: translateX(-50%) scale(var(--settings-scale, 1));
  transform-origin: top center;
  width: min(560px, calc(100vw - clamp(16px, 6vw, 64px)));
  z-index: 6;
  display: none;
  flex-direction: column;
  gap: clamp(5px, 1.2vmin, 9px);
  padding: clamp(9px, 1.8vmin, 15px) clamp(11px, 2.6vmin, 24px);
  background: rgba(4, 8, 16, 0.94);
  border: 1px solid rgba(46, 233, 255, 0.4);
  border-radius: 3px;
  box-shadow:
    0 0 clamp(10px, 3vmin, 40px) rgba(46, 233, 255, 0.2),
    0 0 clamp(26px, 8vmin, 90px) rgba(255, 67, 224, 0.12),
    inset 0 0 clamp(12px, 4vmin, 44px) rgba(46, 233, 255, 0.05);
  text-align: left;
  pointer-events: auto;
}

.settings-panel[data-active="true"] { display: flex; }

.settings-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: clamp(8px, 2.4vw, 28px);
  padding-bottom: clamp(4px, 1.1vmin, 10px);
  border-bottom: 1px solid rgba(46, 233, 255, 0.18);
}

.settings-heading {
  margin: 0;
  font-size: clamp(11px, min(3.2vw, 2.3vh), 22px);
  line-height: 1;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: clamp(2px, 1vw, 10px);
  text-indent: clamp(2px, 1vw, 10px);
  color: var(--ink);
  text-shadow: var(--glow-cyan);
}

.settings-body {
  display: flex;
  flex-direction: column;
  gap: clamp(4px, 1vmin, 8px);
}

.settings-section {
  display: flex;
  flex-direction: column;
  gap: clamp(4px, 1vmin, 8px);
  min-width: 0;
}

/* Two columns as soon as there is width for them. The panel is held to the same
   top band as the screens (FR-17), so its budget is vertical; width is the one
   resource it has spare on anything bigger than a phone. RUN SETUP takes the left
   column because its rows are the widest; AUDIO and DATA stack in the right. */
@media (min-width: 620px) {
  .settings-panel { width: min(860px, calc(100vw - clamp(16px, 6vw, 64px))); }

  .settings-body {
    display: grid;
    grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
    column-gap: clamp(14px, 3vw, 44px);
    align-items: start;
  }

  .settings-section--setup { grid-column: 1; grid-row: 1 / span 2; }
  .settings-section--audio { grid-column: 2; grid-row: 1; }
  .settings-section--data  { grid-column: 2; grid-row: 2; }
}

.settings-row {
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto auto;
  align-items: center;
  gap: clamp(6px, 2vw, 18px);
  min-height: 0;
}

.settings-value--best {
  color: var(--magenta);
  text-shadow: var(--glow-magenta);
  min-width: 4ch;
}

/* FR-36: the reset row now carries WHICH best it is showing, so it needs a fourth
   column. Label — preset — number — RESET. */
.settings-row--reset { grid-template-columns: minmax(0, 1fr) auto auto auto; }

/* ---------- RUN SETUP: the same two selectors the title screen carries ---------- */

.settings-row--difficulty,
.settings-row--lives { grid-template-columns: auto minmax(0, 1fr); }

.settings-choice {
  display: flex;
  flex-wrap: wrap;
  align-items: stretch;
  justify-content: flex-end;
  gap: clamp(3px, 0.8vw, 7px);
  min-width: 0;
}

/* Same control, same appearance, wherever it is shown — a difficulty button that
   looked different in the panel would read as a different setting. */
.settings-option {
  font-family: var(--mono);
  font-size: clamp(8px, min(2vw, 1.4vh), 13px);
  line-height: 1.2;
  letter-spacing: clamp(0.6px, 0.3vw, 3px);
  text-indent: clamp(0.6px, 0.3vw, 3px);
  text-transform: uppercase;
  white-space: nowrap;
  color: var(--dim);
  background: rgba(6, 12, 22, 0.66);
  border: 1px solid rgba(46, 233, 255, 0.24);
  border-radius: 2px;
  padding: clamp(3px, 0.8vmin, 7px) clamp(6px, 1.6vmin, 13px);
  margin: 0;
  cursor: pointer;
  transition: color 140ms ease, border-color 140ms ease, background-color 140ms ease;
}

.settings-option:hover { color: var(--ink); border-color: rgba(46, 233, 255, 0.6); }

.settings-option[aria-pressed="true"] {
  color: var(--ink);
  background: rgba(46, 233, 255, 0.16);
  border-color: var(--cyan);
  text-shadow: 0 0 clamp(3px, 0.9vmin, 9px) rgba(46, 233, 255, 0.75);
}

.settings-row--lives .settings-option[aria-pressed="true"] {
  background: rgba(255, 67, 224, 0.14);
  border-color: var(--magenta);
  text-shadow: 0 0 clamp(3px, 0.9vmin, 9px) rgba(255, 67, 224, 0.7);
}

.settings-option:focus {
  outline: 2px solid var(--magenta);
  outline-offset: 2px;
  color: var(--ink);
}

.settings-option:disabled { opacity: 0.4; cursor: default; }

.settings-group-label--setup { margin-top: 0; }

.settings-value--scope {
  color: var(--dim);
  opacity: 0.85;
  min-width: 0;
}

/* FR-47 / ADR-26: said wherever the best is shown, in the same words the title
   screen uses. One rule, one sentence. */
.settings-note {
  margin: 0;
  font-family: var(--mono);
  font-size: clamp(7px, min(1.7vw, 1.2vh), 11px);
  letter-spacing: clamp(1.2px, 0.6vw, 5px);
  text-transform: uppercase;
  color: var(--dim);
  opacity: 0.66;
  transition: color 160ms ease, opacity 160ms ease;
}

.settings-note--active {
  color: var(--amber);
  opacity: 1;
  text-shadow: 0 0 clamp(3px, 1vmin, 10px) rgba(255, 211, 110, 0.5);
}

/* The notice now sits beside the LIVES control rather than beside the best, and
   that control is still on screen while the reset confirmation is up — so it stays
   too. Hiding it would have bought a row of height by removing the one sentence
   explaining why the record being cleared is the record it is. */

/* The confirmation REPLACES the reset row rather than stacking under it: the
   panel lives in the same top band the screens use, and a row of extra height
   is a row the centre-clearance guard would have to scale away (G-14). */
.settings-panel[data-confirming="true"] .settings-row--reset { display: none; }

.settings-label {
  font-size: clamp(8px, min(2.3vw, 1.6vh), 14px);
  letter-spacing: clamp(1.2px, 0.6vw, 6px);
  text-transform: uppercase;
  color: var(--dim);
  overflow-wrap: anywhere;
  cursor: pointer;
}

.settings-label--best { cursor: default; }

.settings-value {
  font-size: clamp(8px, min(2.3vw, 1.6vh), 14px);
  letter-spacing: clamp(1px, 0.4vw, 4px);
  color: var(--dim);
  min-width: 3.4ch;
  text-align: right;
}

.settings-row[data-on="true"] .settings-value {
  color: var(--cyan);
  text-shadow: 0 0 clamp(3px, 0.8vmin, 8px) rgba(46, 233, 255, 0.6);
}

/* ---------- the switch: a real checkbox, restyled ---------- */

.settings-toggle {
  --track-w: clamp(34px, 9vw, 46px);
  --track-h: clamp(16px, 4.4vw, 22px);
  appearance: none;
  -webkit-appearance: none;
  margin: 0;
  padding: 0;
  position: relative;
  flex: none;
  width: var(--track-w);
  height: var(--track-h);
  border: 1px solid rgba(110, 143, 160, 0.5);
  border-radius: 999px;
  background: rgba(110, 143, 160, 0.14);
  cursor: pointer;
  transition: background-color 160ms ease, border-color 160ms ease;
}

.settings-toggle::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 2px;
  width: calc(var(--track-h) - 8px);
  height: calc(var(--track-h) - 8px);
  border-radius: 50%;
  background: var(--dim);
  transform: translate(0, -50%);
  transition: transform 160ms ease, background-color 160ms ease, box-shadow 160ms ease;
}

.settings-toggle:checked {
  background: rgba(46, 233, 255, 0.2);
  border-color: rgba(46, 233, 255, 0.75);
}

.settings-toggle:checked::after {
  background: var(--cyan);
  box-shadow: 0 0 clamp(4px, 1.2vmin, 12px) rgba(46, 233, 255, 0.85);
  transform: translate(calc(var(--track-w) - var(--track-h) + 2px), -50%);
}

/* ---------- the guarded reset (FR-29) ---------- */

.settings-confirm {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: clamp(6px, 2vw, 16px);
  padding: clamp(4px, 1vmin, 8px) clamp(6px, 1.4vmin, 12px);
  border: 1px solid rgba(255, 67, 224, 0.38);
  border-radius: 2px;
  background: rgba(24, 4, 20, 0.72);
}

.settings-confirm-text {
  margin: 0;
  font-size: clamp(8px, min(2.3vw, 1.6vh), 14px);
  letter-spacing: clamp(1px, 0.5vw, 5px);
  text-transform: uppercase;
  color: var(--amber);
  text-shadow: 0 0 clamp(3px, 1vmin, 10px) rgba(255, 211, 110, 0.55);
}

.settings-confirm-actions {
  display: flex;
  align-items: center;
  gap: clamp(5px, 1.6vw, 12px);
}

.settings-status {
  margin: 0;
  font-size: clamp(8px, min(2.1vw, 1.5vh), 13px);
  letter-spacing: clamp(1px, 0.5vw, 5px);
  text-transform: uppercase;
  color: var(--amber);
  text-shadow: 0 0 clamp(3px, 1vmin, 10px) rgba(255, 211, 110, 0.5);
}

.settings-status:empty { display: none; }

/* ---------- tight viewports: the top band is all we get ---------- */

@media (max-width: 420px) {
  .settings-panel { gap: 4px; padding: 8px 10px; }
  .settings-body { gap: 4px; }
  .settings-header { padding-bottom: 3px; }
}

@media (max-height: 480px) {
  .settings-panel { gap: 3px; padding: 6px 10px; }
  .settings-body { gap: 3px; }
  .settings-confirm { padding: 4px 8px; }
  .settings-button, .settings-launch { padding: 4px 8px; }
}

/* R-02 control discoverability. The panel was a flat list: two audio toggles and an
   irreversible "clear personal best" all at the same visual rank, so nothing told you
   what kind of control you were about to touch. Grouped under labelled sections, with
   the destructive one visually separated. */
.settings-group-label {
  margin: 0;
  font-family: var(--mono);
  font-size: clamp(7px, min(1.7vw, 1.2vh), 11px);
  letter-spacing: clamp(1.5px, 0.7vw, 6px);
  text-transform: uppercase;
  color: var(--dim);
  opacity: 0.7;
}

.settings-group-label--danger {
  color: var(--amber);
  opacity: 0.75;
  margin-top: clamp(4px, 1.2vmin, 10px);
  padding-top: clamp(4px, 1.2vmin, 10px);
  border-top: 1px solid rgba(255, 211, 110, 0.28);
}


/* R-02. Escape closes the panel, and nothing said so — a keyboard route that exists
   only for whoever guesses it is not a discoverable control. The CLOSE button already
   covers pointer users; this covers the rest without adding another control. */
.settings-hint {
  margin: 0;
  font-family: var(--mono);
  font-size: clamp(7px, min(1.7vw, 1.2vh), 11px);
  letter-spacing: clamp(1.5px, 0.7vw, 6px);
  text-transform: uppercase;
  color: var(--dim);
  opacity: 0.66;
}

/* settings:end */

/* --- pause (FR-51) ------------------------------------------------------- */
/* Bottom-left so it cannot collide with the settings launcher (bottom-right) or
   the top HUD strip, and stays clear of the play-area centre FR-17 protects. */
.pause-btn {
  position: fixed;
  left: max(12px, env(safe-area-inset-left));
  bottom: max(12px, env(safe-area-inset-bottom));
  z-index: 6;
  font-family: var(--mono);
  font-size: clamp(11px, min(3vw, 2.1vh), 18px);
  letter-spacing: 2px;
  color: var(--cyan);
  background: rgba(6, 12, 22, 0.72);
  border: 1px solid rgba(46, 233, 255, 0.42);
  border-radius: 2px;
  padding: clamp(8px, 1.8vmin, 14px) clamp(12px, 2.6vmin, 20px);
  cursor: pointer;
  text-shadow: 0 0 clamp(3px, 0.8vmin, 8px) rgba(46, 233, 255, 0.55);
}
.pause-btn:focus { outline: 2px solid var(--magenta); outline-offset: 2px; }
body[data-screen="playing"] .pause-btn { display: block; }
body:not([data-screen="playing"]) .pause-btn { display: none; }

.paused-overlay {
  position: fixed;
  left: 0; right: 0;
  top: max(12px, env(safe-area-inset-top));
  z-index: 8;
  display: none;
  flex-direction: column;
  align-items: center;
  gap: clamp(6px, 1.6vmin, 14px);
  padding: clamp(8px, 2vmin, 16px);
  text-align: center;
}
.paused-overlay[data-active="true"] { display: flex; }
