@import url('https://fonts.googleapis.com/css2?family=Orbitron:wght@400;600;800&family=Space+Grotesk:wght@400;600;700&display=swap');

:root {
  --bg-deep: #050609;
  --bg-mid: #0b0f16;
  --ink: #e8f3ff;
  --muted: #9fb2c8;
  --teal: #52f2d5;
  --amber: #ffb347;
  --hot: #ff6b5c;
  --violet: #c07bff;
}

* { box-sizing: border-box; }

html, body {
  width: 100%;
  height: 100%;
  margin: 0;
  overflow: hidden;
  touch-action: none;
  -webkit-user-select: none;
  user-select: none;
  background: radial-gradient(1200px 800px at 50% -200px, #16202d 0%, var(--bg-mid) 55%, var(--bg-deep) 100%);
  font-family: 'Space Grotesk', system-ui, sans-serif;
  color: var(--ink);
}

canvas {
  position: fixed;
  inset: 0;
  display: block;
  width: 100%;
  height: 100%;
}

#bootmsg {
  position: fixed;
  inset: 0;
  z-index: 40;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  padding-bottom: 11vh;
  font-size: 0.8rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
}
#bootmsg.fail {
  /* Only a FAILURE earns the middle of the screen. Centring the loading line put it
     straight across the start card's verb row -- caught in a browser screenshot,
     invisible in a diff. */
  align-items: center;
  padding-bottom: 0;
  color: var(--hot);
  letter-spacing: 0.06em;
  text-transform: none;
  font-size: 1rem;
}

#ui {
  position: fixed;
  inset: 0;
  z-index: 10;
  pointer-events: none;
}

/* ---------- HUD ---------- */
.stat { display: flex; flex-direction: column; gap: 3px; }
.stat .label { font-size: 0.6rem; letter-spacing: 0.18em; text-transform: uppercase; color: var(--muted); }
.stat .value { font-size: 1rem; font-weight: 600; }
.stat .value.big {
  font-family: 'Orbitron', sans-serif;
  font-size: 1.55rem;
  font-weight: 700;
  text-shadow: 0 0 18px rgba(82, 242, 213, 0.35);
}

#hud {
  position: absolute;
  top: 18px;
  left: 18px;
  display: flex;
  gap: 18px;
  padding: 12px 16px;
  border-radius: 16px;
  border: 1px solid rgba(255, 255, 255, 0.08);
  background: rgba(8, 12, 18, 0.55);
  backdrop-filter: blur(6px);
}

#comboWrap .value { color: var(--muted); font-family: 'Orbitron', sans-serif; }
#comboWrap.active .value { color: var(--violet); text-shadow: 0 0 14px rgba(192, 123, 255, 0.5); }

#hudRight {
  position: absolute;
  top: 18px;
  right: 18px;
  display: flex;
  flex-direction: column;
  gap: 10px;
  align-items: flex-end;
  padding: 12px 16px;
  border-radius: 16px;
  border: 1px solid rgba(255, 255, 255, 0.08);
  background: rgba(8, 12, 18, 0.55);
  backdrop-filter: blur(6px);
}
#hudRight .value { font-family: 'Orbitron', sans-serif; }
#audioChip { font-size: 0.62rem; letter-spacing: 0.14em; text-transform: uppercase; color: var(--muted); opacity: 0.85; }

/* ---------- Flow meter ---------- */
#flowWrap {
  position: absolute;
  top: 20px;
  left: 50%;
  transform: translateX(-50%);
  width: min(220px, 42vw);
}
.flowTop { display: flex; justify-content: space-between; margin-bottom: 5px; }
.flowLabel { font-size: 0.6rem; letter-spacing: 0.22em; text-transform: uppercase; color: var(--muted); }
#mult { font-size: 0.72rem; font-family: 'Orbitron', sans-serif; color: var(--teal); }
#flowBar { height: 5px; border-radius: 999px; background: rgba(255, 255, 255, 0.09); overflow: hidden; }
#flowFill {
  height: 100%;
  width: 0%;
  border-radius: 999px;
  background: linear-gradient(90deg, var(--teal), var(--amber));
  transition: width 0.15s ease;
}
body.surging #flowFill { background: linear-gradient(90deg, var(--amber), var(--hot)); }

#surgeBanner {
  position: absolute;
  top: 64px;
  left: 50%;
  transform: translateX(-50%);
  font-family: 'Orbitron', sans-serif;
  font-size: 1.05rem;
  letter-spacing: 0.3em;
  color: var(--hot);
  text-shadow: 0 0 18px rgba(255, 107, 92, 0.7);
  opacity: 0;
  transition: opacity 0.3s ease;
}
#surgeBanner.visible { opacity: 1; animation: surgePulse 0.5s ease-in-out infinite alternate; }
@keyframes surgePulse {
  from { transform: translateX(-50%) scale(1); }
  to { transform: translateX(-50%) scale(1.07); }
}

/* ---------- Metronome (top): beat bead + flow-powered burn ---------- */
#metronome {
  position: absolute;
  top: 56px;
  left: 50%;
  transform: translateX(-50%);
  width: min(240px, 46vw);
  height: 16px;
  border-radius: 999px;
  border: 1px solid rgba(255, 170, 80, 0.35);
  background: rgba(8, 12, 18, 0.45);
  overflow: hidden;
  transition: box-shadow 0.2s ease, border-color 0.2s ease;
}
.m-burn {
  position: absolute;
  inset: 0;
  border-radius: 999px;
  background: linear-gradient(90deg, rgba(255, 170, 80, 0.15), rgba(255, 110, 60, 0.75), rgba(255, 220, 120, 0.35));
  opacity: 0.18;
  transform-origin: 0 50%;
}
.m-track { position: absolute; inset: 0; }
.m-bead {
  position: absolute;
  top: 0;
  bottom: 0;
  width: 8px;
  border-radius: 999px;
  background: var(--amber);
  box-shadow: 0 0 16px rgba(255, 170, 80, 0.95);
  opacity: 0.6;
}
.m-label {
  position: absolute;
  top: 18px;
  left: 50%;
  transform: translateX(-50%);
  font-size: 0.52rem;
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--muted);
}

/* ---------- Beat dots ---------- */
#dots {
  position: absolute;
  bottom: 26px;
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  gap: 12px;
}
#dots span {
  width: 9px;
  height: 9px;
  border-radius: 50%;
  background: rgba(255, 255, 255, 0.16);
  transition: transform 0.12s ease, background 0.12s ease, box-shadow 0.12s ease;
}
#dots span.on {
  transform: scale(1.7);
  background: var(--teal);
  box-shadow: 0 0 12px rgba(82, 242, 213, 0.9);
}

/* Poly (3:2) beat dots */
#dots3 {
  position: absolute;
  bottom: 10px;
  left: 50%;
  transform: translateX(-50%);
  display: flex;
  gap: 9px;
}
#dots3.hidden { display: none; }
#dots3 span {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  background: rgba(192, 123, 255, 0.18);
  transition: transform 0.1s ease, background 0.1s ease, box-shadow 0.1s ease;
}
#dots3 span.on {
  transform: scale(1.9);
  background: var(--violet);
  box-shadow: 0 0 10px rgba(192, 123, 255, 0.95);
}

/* Mode toggle */
.modeBtn {
  display: block;
  margin: 0 auto 10px;
  padding: 9px 20px;
  border-radius: 999px;
  border: 1px solid rgba(82, 242, 213, 0.4);
  background: rgba(12, 16, 24, 0.7);
  color: var(--teal);
  font-size: 0.72rem;
  font-weight: 600;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  cursor: pointer;
  transition: all 0.25s ease;
  font-family: 'Space Grotesk', sans-serif;
}
.modeBtn:hover { border-color: rgba(82, 242, 213, 0.8); box-shadow: 0 0 18px rgba(82, 242, 213, 0.2); }
.modeBtn.poly {
  border-color: rgba(192, 123, 255, 0.6);
  color: var(--violet);
  background: rgba(24, 16, 36, 0.75);
}
.modeBtn.poly:hover { box-shadow: 0 0 18px rgba(192, 123, 255, 0.3); }
/* ---------- Quote + hint ---------- */
#quote {
  position: absolute;
  bottom: 56px;
  left: 50%;
  transform: translate(-50%, 10px);
  padding: 9px 16px;
  border-radius: 14px;
  border: 1px solid rgba(255, 179, 71, 0.3);
  background: rgba(6, 10, 14, 0.62);
  max-width: 84%;
  text-align: center;
  font-size: 0.95rem;
  opacity: 0;
  transition: opacity 0.5s ease, transform 0.5s ease;
}
#quote.show { opacity: 1; transform: translate(-50%, 0); }

#hint {
  position: absolute;
  bottom: 104px;
  left: 50%;
  transform: translateX(-50%);
  font-size: 0.68rem;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--muted);
  opacity: 0;
  transition: opacity 0.6s ease;
}
#hint.show { opacity: 0.9; }

/* ---------- Popups ---------- */
#popups { position: absolute; inset: 0; overflow: hidden; }
.pop {
  position: absolute;
  transform: translate(-50%, -50%) scale(0.55);
  font-family: 'Orbitron', sans-serif;
  font-weight: 700;
  font-size: 0.95rem;
  letter-spacing: 0.08em;
  white-space: nowrap;
  opacity: 0;
  pointer-events: none;
  transition: transform 0.45s cubic-bezier(0.2, 0.9, 0.3, 1.4), opacity 0.45s ease;
}
.pop.go { opacity: 1; transform: translate(-50%, -170%) scale(1); }
.pop.fade { opacity: 0; transform: translate(-50%, -230%) scale(0.95); transition: transform 0.4s ease, opacity 0.4s ease; }
.pop--onbeat { color: var(--teal); text-shadow: 0 0 14px rgba(82, 242, 213, 0.8); }
.pop--miss { color: #8b8fa8; text-shadow: 0 0 12px rgba(120, 126, 158, 0.7); }
.pop--close { color: var(--amber); text-shadow: 0 0 14px rgba(255, 179, 71, 0.8); }
/* Gate beats: amber, uppercase, a notch under PERFECT so the corridor always
   reads as progress toward the groove bonus rather than as noise. */
.pop--gate {
  color: var(--amber);
  font-size: 0.95rem;
  letter-spacing: 0.16em;
  text-shadow: 0 0 16px rgba(255, 179, 71, 0.85), 0 0 6px rgba(255, 217, 160, 0.6);
  text-transform: uppercase;
}
/* The hop's own colour: warm gold, between the gate amber and the teal of a
   perfect shift, because clearing something with air time is its own dialect of
   "you were on the beat". */
.pop--hop {
  color: #ffe6a8;
  font-size: 1rem;
  letter-spacing: 0.15em;
  text-shadow: 0 0 18px rgba(255, 214, 120, 0.9), 0 0 6px rgba(255, 179, 71, 0.7);
  text-transform: uppercase;
}
/* The road talking. The gantry board carries the same copy, but a 1.5 m plate is
   only legible for about half a second at speed, so the line gets captioned here
   too — quieter than a score, because it is a joke and not a reward. */
.pop--sign {
  color: #f2f8f4;
  font-size: 1rem;
  font-style: italic;
  letter-spacing: 0.07em;
  text-shadow: 0 0 14px rgba(82, 242, 213, 0.5), 0 1px 3px rgba(0, 0, 0, 0.85);
}
.pop--orb { color: var(--amber); text-shadow: 0 0 12px rgba(255, 179, 71, 0.7); font-size: 0.85rem; }
.pop--scoop { color: #ff8fab; text-shadow: 0 0 12px rgba(255, 143, 171, 0.75); font-size: 0.85rem; }
.pop--shard { color: var(--teal); text-shadow: 0 0 12px rgba(55, 230, 255, 0.75); font-size: 0.85rem; }
.pop--gold { color: #ffd166; text-shadow: 0 0 16px rgba(255, 209, 102, 0.9); font-size: 1rem; font-weight: 800; letter-spacing: 0.08em; }
.pop--half { color: rgba(172, 190, 212, 0.92); text-shadow: 0 0 8px rgba(120, 140, 165, 0.45); font-size: 0.78rem; letter-spacing: 0.16em; }
.pop--shield { color: var(--violet); text-shadow: 0 0 14px rgba(192, 123, 255, 0.8); }
.pop--combo { color: var(--violet); font-size: 1.25rem; letter-spacing: 0.18em; text-shadow: 0 0 20px rgba(192, 123, 255, 0.85); }
.pop--surge { color: var(--hot); font-size: 1.5rem; letter-spacing: 0.3em; text-shadow: 0 0 24px rgba(255, 107, 92, 0.9); }

/* ---------- Surge / crash overlays ---------- */
#surgeGlow {
  position: absolute;
  inset: 0;
  opacity: 0;
  transition: opacity 0.5s ease;
  box-shadow: inset 0 0 180px rgba(255, 120, 80, 0.22), inset 0 0 60px rgba(255, 179, 71, 0.12);
}
body.surging #surgeGlow { opacity: 1; }

#flash {
  position: absolute;
  inset: 0;
  opacity: 0;
  background: radial-gradient(circle at 50% 60%, rgba(255, 90, 70, 0.5), rgba(255, 60, 40, 0.18) 70%);
}

/* ---------- Overlays ---------- */
.overlay {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  /* Was 0.88-0.94 black across the whole viewport with a 4px blur, which measured p95=19 --
     i.e. the death screen painted the world out to nothing at exactly the moment it started
     telling you what was in it. Now a scrim, not a lid: the middle of the frame, where the
     body and the thing that killed him are, stays almost clear, and the dark sits at the
     edges where it only has to help the text. */
  background: radial-gradient(1100px 760px at 50% 46%, rgba(6, 9, 14, 0.06), rgba(5, 7, 11, 0.52) 58%, rgba(3, 5, 9, 0.88));
  backdrop-filter: blur(1.5px);
  pointer-events: none;
  opacity: 0;
  transition: opacity 0.45s ease;
}
.overlay.visible { opacity: 1; pointer-events: auto; }

.card {
  max-width: 520px;
  margin: 0 16px;
  padding: 28px 32px;
  border-radius: 24px;
  border: 1px solid rgba(82, 242, 213, 0.25);
  background: rgba(7, 10, 16, 0.93);
  box-shadow: 0 30px 80px rgba(0, 0, 0, 0.45);
  text-align: center;
}
.card h1 {
  margin: 0 0 10px;
  font-family: 'Orbitron', sans-serif;
  font-size: 3rem;
  letter-spacing: 0.12em;
  color: var(--teal);
  text-shadow: 0 0 22px rgba(82, 242, 213, 0.4);
}
.card .sub { margin: 0 0 14px; color: var(--muted); font-size: 0.95rem; line-height: 1.5; }

/* ---- The start card, after Jordi said the quiet part: "you just keep adding shit to
   the text and it's getting uglier and more overwhelming." The prose, the chip row and
   the eight-row key table are gone; the doorway, the title, the tempo, three verbs and
   one button remain. ---- */
.startCard { max-width: 430px; padding: 28px 30px 24px; }
.startGate {
  display: block;
  width: 74px;
  margin: 0 auto;
  fill: #ffb347;
  filter: drop-shadow(0 0 14px rgba(255, 179, 71, 0.55));
  /* Breathing at exactly 112 BPM, in pure CSS, no JS: the doorway is the thing you
     spend the whole game steering towards, and it is already moving at the game's real
     tempo before you have read or pressed anything. 60 / 112 = 0.5357 s. */
  animation: gateBreath 0.5357s ease-in-out infinite;
}
@keyframes gateBreath {
  0%, 100% { opacity: 0.72; transform: scale(1); }
  50% { opacity: 1; transform: scale(1.035); }
}
.startCard h1 { margin: 6px 0 2px; font-size: 3.3rem; }
.startTempo {
  margin: 0 0 22px;
  font-size: 0.6rem;
  letter-spacing: 0.44em;
  text-indent: 0.44em;
  text-transform: uppercase;
  color: var(--muted);
}
.verbRow {
  list-style: none;
  display: flex;
  gap: 24px;
  justify-content: center;
  margin: 0 0 24px;
  padding: 0;
}
.verbRow li { display: flex; flex-direction: column; align-items: center; gap: 8px; }
.verbKey {
  display: grid;
  place-items: center;
  width: 50px;
  height: 50px;
  border-radius: 15px;
  border: 1px solid rgba(82, 242, 213, 0.28);
  background: rgba(12, 16, 24, 0.8);
  font-family: 'Orbitron', sans-serif;
  font-size: 0.92rem;
  letter-spacing: 0.02em;
  color: var(--teal);
}
.verbWhat {
  font-size: 0.58rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--muted);
}
/* The pickup drawn as itself rather than described: a record, so it can never be
   mistaken for the road's traffic cone again -- the confusion that killed Jordi twice. */
.verbRecord {
  border-color: rgba(255, 143, 178, 0.42);
  background: radial-gradient(circle at 50% 50%, #ff8fab 0 17%, #140b12 18% 100%);
  box-shadow: 0 0 18px rgba(255, 143, 178, 0.35);
}
.playBtn {
  min-width: 196px;
  padding: 16px 30px;
  font-size: 1.02rem;
  letter-spacing: 0.26em;
}
.startFoot {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 14px;
  margin: 16px 0 0;
}
.startFoot .small { margin-top: 0; }
.modeNote {
  margin: 8px 0 0;
  font-size: 0.58rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: rgba(207, 219, 232, 0.5);
}

.button {
  display: inline-block;
  border: none;
  padding: 13px 26px;
  border-radius: 999px;
  background: linear-gradient(135deg, var(--teal), var(--amber));
  color: #0b0f14;
  font-weight: 700;
  font-family: 'Space Grotesk', sans-serif;
  font-size: 0.95rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  cursor: pointer;
  transition: transform 0.2s ease, box-shadow 0.2s ease;
}
.button:hover { transform: translateY(-2px); box-shadow: 0 12px 26px rgba(82, 242, 213, 0.35); }
.button.ghost {
  background: transparent;
  color: var(--teal);
  border: 1px solid rgba(82, 242, 213, 0.4);
  margin-left: 8px;
}
.button.ghost:hover { box-shadow: 0 12px 26px rgba(82, 242, 213, 0.18); }

.small { font-size: 0.68rem; letter-spacing: 0.12em; text-transform: uppercase; color: var(--muted); margin-top: 12px; }

/* ---------- Game over ---------- */
#overGrade {
  font-family: 'Orbitron', sans-serif;
  font-size: 4.2rem;
  font-weight: 800;
  line-height: 1;
  margin: 4px 0 14px;
}
.grade-S { color: var(--hot); text-shadow: 0 0 34px rgba(255, 107, 92, 0.8); }
.grade-A { color: var(--teal); text-shadow: 0 0 30px rgba(82, 242, 213, 0.8); }
.grade-B { color: var(--amber); text-shadow: 0 0 26px rgba(255, 179, 71, 0.7); }
.grade-C { color: #9fd8ff; text-shadow: 0 0 22px rgba(159, 216, 255, 0.6); }
.grade-D { color: var(--muted); }

.overGrid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 8px; margin: 0 0 20px; }
/* Two columns of tiles made the dead card roughly the height of the viewport, which meant
   the card stood in front of the very object it was naming. On wide screens the tiles go
   four-across, the grade shrinks, and the card leaves the top of the frame free for the
   frozen tableau and its X. */
/* The dead card is anchored low so the band above it holds the thing being named. The
   centred layout put a ~full-height panel exactly over the corpse and its X. */
#overScreen { align-items: flex-end; padding-bottom: 2.4vh; }
@media (min-width: 720px) {
  .overGrid { grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 7px; }
  .ostat { padding: 7px 6px; border-radius: 11px; }
  .ostat .num { font-size: 0.9rem; }
  #overScreen .card { padding: 20px 24px 22px; }
  #overGrade { font-size: 3rem; margin: 2px 0 10px; }
  #overScreen .button { padding: 12px 26px; }
}
.ostat { padding: 10px; border-radius: 14px; border: 1px solid rgba(255, 255, 255, 0.06); background: rgba(12, 16, 24, 0.7); }
.ostat .label { display: block; font-size: 0.58rem; letter-spacing: 0.18em; text-transform: uppercase; color: var(--muted); margin-bottom: 4px; }
.ostat .num { font-family: 'Orbitron', sans-serif; font-size: 1rem; font-weight: 700; }

/* The one line on the dead screen that is not a statistic: what ended the run, in the
   hazard's own colour, spanning the grid. Jordi could name the thing that killed him
   only as "an ice cream" and "a blue diamond" -- both of which are LOOT -- so the game
   now says the word instead of leaving him to guess it from a silhouette at 20 m/s. */
.ostat.killer {
  grid-column: 1 / -1;
  display: flex;
  align-items: baseline;
  gap: 10px;
  flex-wrap: wrap;
  border-color: rgba(255, 143, 178, 0.30);
  background: rgba(26, 10, 18, 0.8);
}
.ostat.killer .label { margin-bottom: 0; }
.ostat.killer .num { font-size: 1.22rem; text-transform: capitalize; text-shadow: 0 0 18px currentColor; }
.ostat.killer em {
  font-family: 'Space Grotesk', sans-serif;
  font-size: 0.64rem;
  font-style: normal;
  letter-spacing: 0.03em;
  color: var(--muted);
  text-shadow: none;
}
.loot-stat.scoop .num { color: #ff8fab; text-shadow: 0 0 12px rgba(255, 143, 171, 0.55); }
.loot-stat.gem .num { color: var(--teal); text-shadow: 0 0 12px rgba(55, 230, 255, 0.55); }
.loot-stat.battery .num { color: #ff5fa2; text-shadow: 0 0 12px rgba(255, 95, 162, 0.55); }
.loot-stat.gold .num { color: #ffd166; text-shadow: 0 0 12px rgba(255, 209, 102, 0.55); }

/* The eulogy: one line under the killer, italic and dim. It is the only joke on the
   death card, so it gets the smallest voice in the room. */
.epitaph {
  margin: 0.15rem 0 0.35rem;
  font-size: 0.78rem;
  font-style: italic;
  color: rgba(200, 214, 235, 0.72);
  letter-spacing: 0.02em;
}

/* ---------- Loot HUD ---------- */
#perfectWrap .value { color: #9ff7ec; font-family: 'Orbitron', sans-serif; text-shadow: 0 0 14px rgba(159, 247, 236, 0.5); }

/* ---------- Atmosphere: scanlines, grain, vignette ---------- */
body::before {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 40;
  pointer-events: none;
  background: repeating-linear-gradient(0deg, rgba(0,0,0,0.05) 0px, rgba(0,0,0,0.05) 1px, transparent 1px, transparent 3px);
  mix-blend-mode: overlay;
  opacity: 0.55;
}
body::after {
  content: "";
  position: fixed;
  inset: 0;
  z-index: 39;
  pointer-events: none;
  background: radial-gradient(120% 120% at 50% 50%, transparent 55%, rgba(2, 4, 8, 0.72) 100%);
}
#ui {
  position: fixed;
  inset: 0;
  z-index: 10;
  pointer-events: none;
  background: radial-gradient(900px 500px at 50% 120%, rgba(82, 242, 213, 0.06), transparent 70%);
}

/* ---------- New popup styles ---------- */
.pop--perfect {
  color: #bffef5;
  font-size: 1.12rem;
  letter-spacing: 0.14em;
  text-shadow: 0 0 22px rgba(159, 247, 236, 0.95), 0 0 8px rgba(82, 242, 213, 0.8);
  text-transform: uppercase;
}
.pop--streak {
  color: var(--violet);
  font-size: 0.82rem;
  letter-spacing: 0.2em;
  text-shadow: 0 0 14px rgba(192, 123, 255, 0.7);
  text-transform: uppercase;
}
.pop--section {
  color: #ffffff;
  font-size: 1.35rem;
  letter-spacing: 0.32em;
  text-shadow: 0 0 26px rgba(255, 255, 255, 0.8), 0 0 12px rgba(82, 242, 213, 0.6);
  text-transform: uppercase;
}

/* ---------- Loot HUD ---------- */
#lootHud {
  position: absolute;
  top: 86px;
  left: 18px;
  display: flex;
  gap: 14px;
  padding: 7px 12px;
  border-radius: 12px;
  border: 1px solid rgba(255, 255, 255, 0.08);
  background: rgba(8, 12, 18, 0.5);
  backdrop-filter: blur(6px);
}
.lootItem { display: inline-flex; align-items: center; gap: 5px; }
.lootDot { width: 8px; height: 8px; border-radius: 50%; display: inline-block; }
.lootItem b { font-family: 'Orbitron', sans-serif; font-size: 0.78rem; font-weight: 700; }

/* ---------- Mobile ---------- */
#hopBtn {
  display: none;
}
/* Touch players need an explicit jump: tapping the halves of the screen is taken
   by shifting, and a swipe would add latency to a game that judges 50 ms. So it
   is a button, shown only where there is no keyboard to press space with. */
@media (pointer: coarse) {
  #hopBtn {
    display: flex;
    /* #ui is pointer-events:none and that property is inherited, so anything drawn on the
       HUD layer is invisible to hit-testing unless it opts back in. The overlay buttons get
       their `auto` from .overlay.visible; this button is not inside an overlay, so it never
       did. Measured on the live site with a phone emulated: tapping the big amber arrow moved
       the runner one lane RIGHT twice and hopped zero times, because the tap landed on the
       canvas and tap-to-shift reads x > half-width as "right". On a touch device the hop is
       the only answer to a gnome, a sweeping bar and the floating loot, so the one control
       built for it had to be reachable -- without stealing a tap from tap-to-shift anywhere
       else on the road. */
    pointer-events: auto;
    position: absolute;
    right: 14px;
    bottom: 26px;
    z-index: 12;
    width: 76px;
    height: 76px;
    align-items: center;
    justify-content: center;
    border-radius: 50%;
    border: 1px solid rgba(255, 214, 120, 0.55);
    background: radial-gradient(circle at 50% 38%, rgba(255, 179, 71, 0.3), rgba(20, 16, 26, 0.72) 70%);
    color: #ffe6a8;
    font-family: inherit;
    font-size: 1.9rem;
    line-height: 1;
    text-shadow: 0 0 14px rgba(255, 214, 120, 0.8);
    box-shadow: 0 0 20px rgba(255, 179, 71, 0.22);
    touch-action: manipulation;
    -webkit-tap-highlight-color: transparent;
    user-select: none;
  }
  #hopBtn:active {
    background: radial-gradient(circle at 50% 38%, rgba(255, 214, 120, 0.5), rgba(30, 22, 34, 0.8) 70%);
    transform: translateY(2px) scale(0.97);
  }
}
@media (max-width: 720px) {
  #hud { flex-direction: column; gap: 8px; padding: 10px 12px; }
  #lootHud { top: auto; bottom: 118px; left: 50%; transform: translateX(-50%); gap: 10px; padding: 6px 10px; }
  #hudRight { padding: 10px 12px; }
  .stat .value.big { font-size: 1.2rem; }
  .card { padding: 22px; }
  .card h1 { font-size: 2.3rem; }
  #overGrade { font-size: 3.4rem; }
  #quote { font-size: 0.88rem; bottom: 48px; }
  #dots { bottom: 20px; }
  #hint { bottom: 92px; }
}

/* ---------- Career update: settings, career, modes ---------- */
/* A settings gear on the start card, next to the mode button. Small and low-contrast on
   purpose: it is a door, not a feature, and the card's rule is that nothing competes with
   Play. */
.gearBtn {
  width: 40px;
  height: 40px;
  border-radius: 999px;
  border: 1px solid rgba(255, 255, 255, 0.14);
  background: rgba(12, 16, 24, 0.8);
  color: var(--muted);
  font-size: 1.1rem;
  line-height: 1;
  cursor: pointer;
  transition: all 0.2s ease;
}
.gearBtn:hover { color: var(--teal); border-color: rgba(82, 242, 213, 0.5); box-shadow: 0 0 14px rgba(82, 242, 213, 0.2); }

/* The two lines under the mode button. Best score has always been here; the career line is
   the running total, and it only appears once there is a career to show. */
.startMeta { display: flex; flex-direction: column; gap: 4px; margin-top: 12px; }
.startMeta .small { margin-top: 0; }
.careerLine { color: rgba(207, 219, 232, 0.62); }

/* Practice is a different promise from Classic and Poly, so its button says so in the
   danger colour the road itself uses for "this is not the scored game". */
.modeBtn.practice { border-color: rgba(255, 107, 92, 0.55); color: var(--hot); background: rgba(30, 14, 14, 0.75); }
.modeBtn.practice:hover { box-shadow: 0 0 18px rgba(255, 107, 92, 0.3); }

/* The badge that says the road cannot kill you right now. */
.modeBadge {
  position: absolute;
  top: 88px;
  left: 50%;
  transform: translateX(-50%);
  font-family: 'Orbitron', sans-serif;
  font-size: 0.58rem;
  letter-spacing: 0.34em;
  text-transform: uppercase;
  color: var(--violet);
  text-shadow: 0 0 14px rgba(192, 123, 255, 0.8);
  opacity: 0;
  transition: opacity 0.3s ease;
  pointer-events: none;
}
.modeBadge.visible { opacity: 1; }

/* NEW BEST. Reserved space so the card never jumps when it appears, and a slow pulse so it
   reads as a celebration rather than an alarm. */
.newBest {
  min-height: 1.1em;
  font-family: 'Orbitron', sans-serif;
  font-size: 0.7rem;
  letter-spacing: 0.34em;
  text-transform: uppercase;
  color: var(--amber);
  text-shadow: 0 0 16px rgba(255, 179, 71, 0.8);
  opacity: 0;
  transform: translateY(4px);
  transition: opacity 0.35s ease, transform 0.35s ease;
}
.newBest.visible { opacity: 1; transform: none; animation: newBestPulse 0.7s ease-in-out infinite alternate; }
@keyframes newBestPulse { from { transform: scale(1); } to { transform: scale(1.06); } }

/* The practice card's killer line is replaced by the honest reason the run ended. */
.ostat.killer.practice { border-color: rgba(192, 123, 255, 0.35); background: rgba(20, 12, 30, 0.8); }
.ostat.killer.practice .num { color: var(--violet); }

/* ---------- Settings / career panel ---------- */
.settingsCard { max-width: 480px; padding: 24px 26px 20px; }
.settingsCard h1 { font-size: 2rem; margin-bottom: 14px; }
.settingsBody { display: flex; flex-direction: column; gap: 9px; margin-bottom: 16px; }
.settingRow {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
  padding: 9px 14px;
  border-radius: 14px;
  border: 1px solid rgba(255, 255, 255, 0.07);
  background: rgba(12, 16, 24, 0.7);
}
.settingRow label, .settingName {
  font-size: 0.68rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--muted);
  text-align: left;
}
.settingVal { font-family: 'Orbitron', sans-serif; font-size: 0.78rem; color: var(--teal); min-width: 44px; text-align: right; }
.volSlider { flex: 1; min-width: 90px; accent-color: var(--teal); cursor: pointer; }
.toggle {
  min-width: 62px;
  padding: 7px 14px;
  border-radius: 999px;
  border: 1px solid rgba(82, 242, 213, 0.35);
  background: rgba(8, 12, 18, 0.8);
  color: var(--muted);
  font-family: 'Space Grotesk', sans-serif;
  font-size: 0.66rem;
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  cursor: pointer;
  transition: all 0.2s ease;
}
.toggle.on {
  border-color: var(--teal);
  color: #06231d;
  background: linear-gradient(135deg, var(--teal), var(--amber));
  box-shadow: 0 0 16px rgba(82, 242, 213, 0.35);
}
.careerHead {
  margin: 2px 0 10px;
  font-family: 'Orbitron', sans-serif;
  font-size: 0.74rem;
  letter-spacing: 0.3em;
  text-transform: uppercase;
  color: var(--muted);
}
.careerGrid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 7px; margin-bottom: 18px; }
.crow {
  padding: 8px 6px;
  border-radius: 10px;
  border: 1px solid rgba(255, 255, 255, 0.06);
  background: rgba(12, 16, 24, 0.7);
  text-align: center;
}
.clabel { display: block; font-size: 0.5rem; letter-spacing: 0.12em; text-transform: uppercase; color: var(--muted); margin-bottom: 3px; }
.cnum { font-family: 'Orbitron', sans-serif; font-size: 0.8rem; font-weight: 700; color: var(--ink); }
#settingsScreen .button { margin-top: 2px; }

/* The two buttons on the dead card need to share a line without colliding. */
#overScreen .button { margin: 0 4px; }

/* ---------- Reduced motion ---------- */
/* The setting removes involuntary motion only: the doorway stops breathing, the surge
   banner stops pulsing, the NEW BEST badge stops scaling, and the scanline overlay dims.
   Everything that carries information -- the metronome, the road, the hazards -- still
   moves, because a runner game that stops moving is not a game. */
body.reduced-motion .startGate { animation: none; }
body.reduced-motion #surgeBanner.visible { animation: none; }
body.reduced-motion .newBest.visible { animation: none; }
body.reduced-motion .m-bead { transition: none; }
body.reduced-motion #flowFill { transition: none; }
body.reduced-motion::before { opacity: 0.28; }

/* The OS-level preference seeds the setting on a first visit; after that the player's own
   choice is what is stored and honoured. */
@media (prefers-reduced-motion: reduce) {
  .startGate { animation: none; }
}

@media (max-width: 720px) {
  .settingsCard { padding: 20px 18px 16px; }
  .careerGrid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .settingRow { padding: 8px 10px; }
  .modeBadge { top: 78px; }
}
