:root {
  /* palette — "three modes on graphite" from the endless mockups: one
     neutral chrome for every mode; the track, spine and accent are the
     mode's own (below). */
  --bg: #0f0f10;
  --bg-raised: #171719;
  --track: #151a21;
  --spine: #33414f;
  --border: #27272b;

  --text: #f2f2f4;
  --text-dim: #b5b5bc;
  --text-faint: #8b8b93;
  --label: #8b8b93;
  --ghost: #232326;
  --seg-locked: #55555c;

  --left: #2ec7d6;
  --left-glow: rgba(46, 199, 214, 0.5);
  --right: #e4629b;
  --right-glow: rgba(228, 98, 155, 0.45);
  --mint: #7ef0c8;
  --violet: #a682f2;
  --accent: var(--mint);
  --accent-glow: rgba(126, 240, 200, 0.45);
  --accent-wash: rgba(126, 240, 200, 0.22);
  --accent-band: rgba(126, 240, 200, 0.14);
  --idle-mult: #5f5f66;
  --miss: #e8675a;

  --font-ui: 'Space Grotesk', system-ui, sans-serif;
  --font-mono: 'IBM Plex Mono', ui-monospace, monospace;

  /* geometry */
  --play-w: 420px;   /* width of the track + pads column */
  --play-h: 797px;   /* plus the 3px mode strip = the mockups' 800 */
  --lane-w: 150px;
  --lane-gap: 10px;   /* half the gap between the two lanes */
  --note-h: 48px;
  --strike-y: 36px;   /* how far up the plane a note is when it's due */
  --above-targets: 62px;   /* screen-space height just clear of the targets */
  --drawer-w: 400px;
}

/* Each mode is an accent on its own track: training mint on slate, challenge
   violet on violet-black, endless pink on a warm track. Lane colours, pads,
   keys and hit window stay exactly the same so muscle memory carries over.
   An endless run swaps between the three as complicators land (data-tint,
   which outranks the mode). */
body[data-mode][data-tint='mint'] {
  --track: #151a21;
  --spine: #33414f;
  --accent: var(--mint);
  --accent-glow: rgba(126, 240, 200, 0.45);
  --accent-wash: rgba(126, 240, 200, 0.22);
  --accent-band: rgba(126, 240, 200, 0.14);
}

body[data-mode='challenge'],
body[data-mode][data-tint='violet'] {
  --track: #17151f;
  --spine: #3d3850;
  --accent: var(--violet);
  --accent-glow: rgba(166, 130, 242, 0.45);
  --accent-wash: rgba(166, 130, 242, 0.22);
  --accent-band: rgba(166, 130, 242, 0.14);
}

body[data-mode='endless'],
body[data-mode][data-tint='pink'] {
  --track: #1a1613;
  --spine: #4a3f35;
  --accent: var(--right);
  --accent-glow: rgba(228, 98, 155, 0.45);
  --accent-wash: rgba(228, 98, 155, 0.22);
  --accent-band: rgba(228, 98, 155, 0.14);
}

/* Parts of the page that belong to some modes only carry a for-<mode>
   class per mode they show in. */
body[data-mode='training'] :is(.for-challenge, .for-endless):not(.for-training),
body[data-mode='challenge'] :is(.for-training, .for-endless):not(.for-challenge),
body[data-mode='endless'] :is(.for-training, .for-challenge):not(.for-endless) { display: none !important; }

/* --pulse is set from JS every frame while running: 1 on the beat, decaying
   to 0. Everything that breathes with the metronome reads it. */
.app { --pulse: 0; }

* { box-sizing: border-box; margin: 0; padding: 0; }
[hidden] { display: none !important; }

body {
  min-height: 100vh;
  display: grid;
  align-items: center;
  overflow: hidden;
  background: linear-gradient(180deg, var(--bg-raised) 0%, var(--bg) 300px) var(--bg);
  font-family: var(--font-ui);
  color: var(--text);
}

/* ---------- app shell ----------
   Full window width, fixed play height (the track's horizon doesn't grow
   with the window yet), centred vertically. The track and pads are centred
   in a --play-w column. */

.app {
  position: relative;
  height: var(--play-h);
  display: flex;
  flex-direction: column;
  transition: margin-right 0.2s ease;
}

/* The setup drawer opens beside the play column, never over it. */
.is-drawer-open .app { margin-right: var(--drawer-w); }

/* ---------- mode strip & toggle ---------- */

.mode-strip {
  position: fixed;
  top: 0;
  left: 0;
  right: 0;
  height: 3px;
  background: var(--accent);
}

.modes {
  position: relative;
  flex-shrink: 0;
  height: 56px;
  display: flex;
  align-items: center;
  justify-content: center;
}

.mode-pill {
  position: relative;
  display: flex;
  align-items: center;
  gap: 2px;
  padding: 3px;
  border-radius: 22px;
  background: var(--bg-raised);
  border: 1px solid var(--border);
}

.mode-seg {
  width: 104px;
  height: 34px;
  border: none;
  border-radius: 18px;
  background: transparent;
  color: var(--text-dim);
  font-family: var(--font-mono);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.16em;
  cursor: pointer;
}

.mode-seg[aria-pressed='true'] {
  background: var(--accent);
  color: var(--bg);
  font-weight: 600;
  cursor: default;
}

.mode-seg:focus-visible { outline: 2px solid var(--text); outline-offset: 2px; }

/* Locked during a run: the other modes grey out and a lock hangs off the
   pill's bottom edge, centred. */
.mode-lock {
  position: absolute;
  left: 50%;
  top: 100%;
  width: 26px;
  height: 26px;
  transform: translate(-50%, -50%);
  display: none;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background: var(--bg-raised);
  border: 1px solid var(--border);
  box-shadow: 0 0 0 3px var(--bg-raised);
  color: var(--label);
  pointer-events: none;
}

.is-locked .mode-lock { display: flex; }
.is-locked .mode-seg[aria-pressed='false'] { color: var(--seg-locked); cursor: not-allowed; }

/* Sits over the stat labels for a moment, so it needs its own ground. */
.mode-nudge {
  position: absolute;
  top: calc(100% - 6px);
  left: 50%;
  z-index: 4;
  transform: translateX(-50%);
  padding: 5px 12px;
  border-radius: 12px;
  background: var(--bg-raised);
  border: 1px solid var(--border);
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.08em;
  white-space: nowrap;
  color: #c9a86a;
  pointer-events: none;
}

/* ---------- HUD ---------- */

.hud {
  position: relative;
  flex-shrink: 0;
  width: var(--play-w);
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 12px;
  padding: 4px 24px 0;
  font-family: var(--font-mono);
}

.stats {
  width: 100%;
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  text-align: center;
}

.stat {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
}

.label {
  font-size: 10px;
  letter-spacing: 0.18em;
  color: var(--label);
}

.value {
  font-size: 30px;
  font-weight: 600;
  line-height: 1.1;
}

.value--accent { color: var(--accent); }

/* Endless's best score sits back from the live score beside it. */
.value--best {
  font-size: 18px;
  line-height: 33px;
  color: var(--text-dim);
}

.unit {
  font-size: 16px;
  color: var(--text-dim);
}

.lives {
  height: 33px;
  display: flex;
  align-items: center;
  gap: 6px;
}

.life {
  width: 14px;
  height: 14px;
  border-radius: 4px;
  background: var(--accent);
  transform: rotate(45deg);
}

.life.is-lost {
  background: transparent;
  border: 2px solid #4a3f35;
}

/* Training: early/late meter. Spans the hit window; the band is v1's
   "perfect" window, something to aim for. Dots are placed from JS. */
.meter {
  height: 28px;
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 10px;
  letter-spacing: 0.14em;
  color: var(--label);
}

.meter-rail {
  position: relative;
  width: 240px;
  height: 16px;
}

.meter-line {
  position: absolute;
  left: 0;
  right: 0;
  top: 7px;
  height: 2px;
  border-radius: 1px;
  background: var(--border);
}

.meter-band {
  position: absolute;
  left: calc(50% - var(--band, 31px));
  width: calc(2 * var(--band, 31px));
  top: 5px;
  height: 6px;
  border-radius: 3px;
  background: var(--accent-band);
}

.meter-centre {
  position: absolute;
  left: calc(50% - 1px);
  top: 0;
  width: 2px;
  height: 16px;
  background: var(--text-faint);
}

.meter-dot {
  position: absolute;
  top: 4px;
  width: 8px;
  height: 8px;
  margin-left: -4px;
  border-radius: 50%;
  background: var(--accent);
}

.meter-dot.is-latest {
  top: 3px;
  width: 10px;
  height: 10px;
  margin-left: -5px;
  box-shadow: 0 0 10px var(--accent-glow);
}

/* Challenge: progress to the next multiplier. */
.mult-bar {
  height: 28px;
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: 12px;
  font-weight: 600;
}

.mult-from { color: var(--accent); }
.mult-to { color: var(--idle-mult); }

.mult-rail {
  position: relative;
  width: 200px;
  height: 6px;
  border-radius: 3px;
  background: var(--ghost);
}

.mult-fill {
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  width: 0;
  border-radius: 3px;
  background: var(--accent);
  box-shadow: 0 0 12px var(--accent-glow);
}

/* Same 40px slot in both modes; challenge leaves it empty on purpose. */
.settings-line { height: 40px; }

/* Endless's chase line: "1,240 TO BEST" and a bar to a mark, then
   "+460 PAST YOUR BEST · #1 OF 13". Empty between runs. */
.chase {
  display: flex;
  align-items: center;
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.12em;
}

/* The chip is a settings-chip, so these need .chase to outrank it. */
.chase .chase-to,
.chase .chase-past,
.chase .board-chip { display: none; align-items: center; }
.chase:not([data-state='to'], [data-state='past']) .board-chip { display: flex; }
.board-chip-count { color: var(--text-faint); }
.chase[data-state='to'] .chase-to { display: flex; gap: 10px; }
.chase[data-state='past'] .chase-past { display: flex; gap: 8px; color: var(--accent); }

.chase-gap { color: var(--accent); }

.chase-rail {
  position: relative;
  width: 150px;
  height: 4px;
  border-radius: 2px;
  background: var(--ghost);
}

.chase-fill {
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  border-radius: 2px;
  background: var(--accent);
  box-shadow: 0 0 10px var(--accent-glow);
}

.chase-mark {
  position: absolute;
  right: -1px;
  top: -5px;
  width: 2px;
  height: 14px;
  border-radius: 1px;
  background: var(--text);
}

.chase-to svg { color: var(--text); }
.chase-rank { color: var(--text-faint); }

/* Past your best: the score lights up and the old best is crossed out. */
.is-past-best .score { color: var(--accent); text-shadow: 0 0 18px var(--accent-glow); }
.is-past-best .best-label { color: var(--accent); }
.is-past-best .endless-best { color: var(--text-faint); text-decoration: line-through; }

/* Endless's leaderboard drawer. */
.lb-tabs { padding: 8px 24px 12px; }

.lb-global { display: flex; align-items: center; justify-content: center; gap: 8px; }
.drawer .lb-global:disabled { opacity: 1; color: var(--seg-locked); }

.lb-soon {
  font-size: 9px;
  padding: 2px 5px;
  border-radius: 4px;
  border: 1px solid var(--seg-locked);
}

.lb-head,
.lb-row {
  display: grid;
  grid-template-columns: 40px 1fr auto;
  align-items: center;
  font-family: var(--font-mono);
}

.lb-head { padding: 4px 26px 6px; }

.lb-list {
  flex: 1;
  overflow-y: auto;
  list-style: none;
  padding: 0 12px;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.lb-row {
  padding: 10px 14px;
  border-radius: 10px;
}

.lb-row.is-latest { background: var(--accent-band); }

.lb-rank { font-size: 14px; color: var(--text-faint); }
.lb-row:is([data-rank='1'], [data-rank='2'], [data-rank='3']) .lb-rank { font-weight: 600; color: var(--text-dim); }
.lb-row[data-rank='1'] .lb-rank { color: var(--accent); }

.lb-when { font-size: 11px; letter-spacing: 0.12em; color: var(--text-dim); }
.is-latest .lb-when { color: var(--text); }

.lb-score { font-size: 18px; color: var(--text-dim); }
.lb-row:is([data-rank='1'], [data-rank='2'], [data-rank='3']) .lb-score { font-weight: 600; color: var(--text); }
.is-latest .lb-score { color: var(--accent); }

.lb-empty {
  flex: 1;
  padding: 16px 26px;
  font-size: 13px;
  line-height: 1.5;
  color: var(--label);
}

/* Training's settings line is the button into setup. */
.settings-chip {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 0 12px 0 14px;
  border-radius: 20px;
  border: 1px solid var(--spine);
  background: var(--bg-raised);
  color: var(--text-dim);
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.12em;
  cursor: pointer;
}

/* Challenge's level picker, in the same slot. */
.level-picker {
  max-width: 100%;
  display: flex;
  align-items: center;
  gap: 8px;
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.12em;
  color: var(--text-dim);
}

.level-step {
  width: 32px;
  height: 32px;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 16px;
  border: 1px solid var(--spine);
  background: var(--bg-raised);
  color: var(--text);
  cursor: pointer;
}

.level-step:hover:not(:disabled) { border-color: var(--accent); }
.level-step:focus-visible { outline: 2px solid var(--text); outline-offset: 2px; }
.level-step:disabled { opacity: 0.3; cursor: default; }
.is-running .level-step { visibility: hidden; }

.level-rating {
  min-width: 22px;
  height: 22px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 4px;
  border: 1px solid var(--spine);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0;
  color: var(--text-faint);
}

.level-rating[data-rating='S'] { color: var(--bg); background: var(--accent); border-color: var(--accent); }
.level-rating[data-rating='A'] { color: var(--text); border-color: var(--text-faint); }
.level-rating[data-rating='B'],
.level-rating[data-rating='C'],
.level-rating[data-rating='D'] { color: var(--text-dim); }

.settings-chip:hover { border-color: var(--text-faint); color: var(--text); }
.settings-chip:focus-visible { outline: 2px solid var(--text); outline-offset: 2px; }

.settings-chip[aria-expanded='true'] {
  border-color: var(--accent);
  background: var(--accent-band);
  color: var(--text);
}

.chip-key {
  font-family: var(--font-mono);
  font-size: 10px;
  padding: 2px 6px;
  border-radius: 4px;
  border: 1px solid var(--spine);
  color: var(--text-dim);
}

.chip-icon--lock { display: none; }

/* During a run: dimmed, a lock instead of the sliders, no key hint. */
.is-locked .settings-chip {
  border-color: transparent;
  background: transparent;
  color: var(--text-faint);
  cursor: default;
}
.is-locked .chip-icon--sliders,
.is-locked .chip-key { display: none; }
.is-locked .chip-icon--lock { display: block; }

/* ---------- stage & track ---------- */

.stage {
  flex: 1;
  position: relative;
  overflow: hidden;
  perspective: 1050px;
  perspective-origin: 50% 100%;
}

.track {
  position: absolute;
  bottom: 0;
  left: 50%;
  width: var(--play-w);
  margin-left: calc(var(--play-w) / -2);
  height: 1500px;
  transform: rotateX(57deg);
  transform-origin: 50% 100%;
  transform-style: preserve-3d;
}

.track-surface {
  position: absolute;
  inset: 0 24px;
  border-radius: 60px 60px 0 0;
  background: linear-gradient(180deg, transparent 0%, var(--track) 55%);
}

.track-pulse {
  position: absolute;
  inset: 0 24px;
  border-radius: 60px 60px 0 0;
  background: linear-gradient(180deg, transparent 35%, var(--accent-wash) 100%);
  opacity: 0;
}

.is-running .track-pulse { opacity: calc(0.12 + 0.83 * var(--pulse)); }

.spine {
  position: absolute;
  top: 0;
  bottom: 0;
  left: calc(50% - 2px);
  width: 4px;
  background: linear-gradient(180deg, transparent 0%, var(--spine) 60%);
}

.is-running .spine { opacity: calc(0.4 + 0.6 * var(--pulse)); }

/* Targets and notes share one footprint: --strike-y up the plane. */
.target,
.note {
  position: absolute;
  bottom: var(--strike-y);
  width: var(--lane-w);
  height: var(--note-h);
}

.target {
  --outline: 0.55;
  border: 2px solid;
}

.is-running .target { --outline: calc(0.45 + 0.4 * var(--pulse)); }

.target-glow {
  position: absolute;
  inset: -2px;
  border-radius: inherit;
  opacity: 0;
}

.target--L {
  right: 50%;
  margin-right: var(--lane-gap);
  border-color: rgb(46 199 214 / var(--outline));
  border-radius: 24px 6px 6px 24px;
  background: rgba(46, 199, 214, 0.06);
}

.target--R {
  left: 50%;
  margin-left: var(--lane-gap);
  border-color: rgb(228 98 155 / var(--outline));
  border-radius: 6px 24px 24px 6px;
  background: rgba(228, 98, 155, 0.06);
}

.target-glow--L { background: var(--left); box-shadow: 0 0 50px var(--left); }
.target-glow--R { background: var(--right); box-shadow: 0 0 50px var(--right); }

/* Hidden hands: one neutral target straddling the spine; the hand targets
   step back. */
.target--C {
  left: 50%;
  margin-left: calc(var(--lane-w) / -2);
  border-color: rgb(201 205 212 / var(--outline));
  border-radius: 24px;
  background: rgba(201, 205, 212, 0.06);
  display: none;
}

.is-blind .target--C { display: block; }
.is-blind :is(.target--L, .target--R) { opacity: 0.25; }

/* Every note sits at the strike position; JS lifts it up the plane with
   translateY and fades it in from the horizon. */
.note {
  will-change: transform, opacity;
}

.note--L {
  right: 50%;
  margin-right: var(--lane-gap);
  border-radius: 24px 6px 6px 24px;
  background: var(--left);
  box-shadow: 0 0 60px var(--left-glow);
}

.note--C {
  left: 50%;
  margin-left: calc(var(--lane-w) / -2);
  border-radius: 24px;
  background: #c9cdd4;
  box-shadow: 0 0 60px rgba(201, 205, 212, 0.35);
}

.note.note--missed {
  filter: saturate(0.2) brightness(0.6);
  box-shadow: none;
}

.note--R {
  left: 50%;
  margin-left: var(--lane-gap);
  border-radius: 6px 24px 24px 6px;
  background: var(--right);
  box-shadow: 0 0 60px var(--right-glow);
}

/* ---------- combo (ghost number up the highway) ---------- */

.combo {
  position: absolute;
  top: 4px;
  left: 0;
  right: 0;
  display: grid;
  place-items: center;
  pointer-events: none;
  font-family: var(--font-mono);
  font-weight: 600;
  line-height: 1;
}

.combo > * { grid-area: 1 / 1; }

.combo-count {
  font-size: 120px;
  color: var(--ghost);
}

.combo-mult {
  font-size: 46px;
  color: var(--accent);
  text-shadow: 0 2px 14px var(--bg), 0 0 26px var(--accent-glow);
}

.combo-mult--idle {
  color: var(--idle-mult);
  text-shadow: none;
}

/* ---------- change cue and line ---------- */

/* Over the combo slot, clear of the notes coming down the track. */
.cue {
  position: absolute;
  top: 6px;
  left: 0;
  right: 0;
  width: fit-content;
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  padding: 10px 18px 8px;
  border: 1px solid var(--accent);
  border-radius: 14px;
  background: rgb(8 11 15 / 0.82);
  box-shadow: 0 0 30px var(--accent-glow);
  pointer-events: none;
  white-space: nowrap;
  visibility: hidden;
}

.cue.is-shown { visibility: visible; }

/* Passing your best: same card as the cue, dropped below it if one's up. */
.best-toast {
  position: absolute;
  top: 6px;
  left: 0;
  right: 0;
  z-index: 3;
  width: fit-content;
  margin: 0 auto;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  padding: 10px 22px;
  border: 1px solid var(--accent);
  border-radius: 14px;
  background: rgb(8 11 15 / 0.82);
  box-shadow: 0 0 30px var(--accent-glow);
  pointer-events: none;
  white-space: nowrap;
}

.cue.is-shown ~ .best-toast { top: 132px; }

.best-toast-tag {
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.2em;
  color: var(--accent);
}

.best-toast-title {
  font-size: 26px;
  font-weight: 700;
  letter-spacing: 0.04em;
}

.best-toast-sub {
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.16em;
  color: var(--text-dim);
}
.cue.is-shown ~ .combo { visibility: hidden; }
.is-paused .cue { opacity: 0.5; }

.cue-tags {
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.2em;
  color: var(--accent);
}

.cue-values {
  font-size: 22px;
  font-weight: 700;
  letter-spacing: 0.04em;
  color: var(--text);
}

.cue-count {
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.16em;
  color: var(--text-dim);
}

/* The last bar counts its beats onto the change, pulsing with the click. */
.cue-count.is-beat {
  font-size: 26px;
  font-weight: 600;
  letter-spacing: 0;
  color: var(--accent);
  transform: scale(calc(1 + 0.25 * var(--pulse)));
}

/* Across the track where the next section starts. */
.change-line {
  position: absolute;
  bottom: calc(var(--strike-y) - 12px);   /* just ahead of the section's first note */
  left: 36px;
  right: 36px;
  height: 6px;
  border-radius: 3px;
  background: var(--accent);
  box-shadow: 0 0 40px var(--accent-glow);
  will-change: transform, opacity;
}

/* ---------- judgment ---------- */

.judgment {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 49px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  pointer-events: none;
  white-space: nowrap;
}

.judgment-word {
  font-size: 38px;
  font-weight: 700;
  letter-spacing: 0.06em;
  color: var(--accent);
  text-shadow: 0 2px 18px rgba(8, 11, 15, 0.95), 0 0 30px var(--accent-glow);
}

/* Grades step down from the accent: GREAT in plain text, GOOD dimmed. */
.judgment[data-kind='great'] .judgment-word {
  color: var(--text);
  text-shadow: 0 2px 18px rgba(8, 11, 15, 0.95);
}

.judgment[data-kind='good'] .judgment-word {
  font-size: 32px;
  color: var(--text-dim);
  text-shadow: 0 2px 18px rgba(8, 11, 15, 0.95);
}

.judgment[data-kind='miss'] .judgment-word {
  color: var(--miss);
  text-shadow: 0 2px 18px rgba(8, 11, 15, 0.95), 0 0 30px rgba(232, 103, 90, 0.4);
}

.judgment-detail {
  font-family: var(--font-mono);
  font-size: 13px;
  color: var(--text-dim);
  text-shadow: 0 2px 12px rgba(8, 11, 15, 0.95);
}

/* ---------- beat dots & hint ---------- */

.beat-dots {
  position: absolute;
  left: 0;
  right: 0;
  bottom: var(--above-targets);
  display: flex;
  justify-content: center;
  gap: 12px;
  pointer-events: none;
  opacity: 0;
}

.is-counting-in .beat-dots { opacity: 1; }

.beat-dot {
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background: var(--accent);
  opacity: 0.22;
}

.beat-dot.is-current {
  opacity: calc(0.9 + 0.1 * var(--pulse));
  transform: scale(calc(1 + 0.35 * var(--pulse)));
}

.hint {
  position: absolute;
  left: 0;
  right: 0;
  bottom: var(--above-targets);
  text-align: center;
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.18em;
  color: var(--text-faint);
  pointer-events: none;
}

.is-running .hint { display: none; }
.is-paused .hint { display: block; color: var(--text-dim); }

/* Paused: the frozen track steps back so the hint reads. */
.track { transition: opacity 0.2s; }
.is-paused .track { opacity: 0.3; }

/* ---------- pads ---------- */

.pads {
  position: relative;
  z-index: 2;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 18px;
  justify-content: center;
  padding: 16px 0 22px;
  background: var(--bg-raised);
  border-top: 1px solid var(--border);
}

.strike-line {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 2px;
  background: var(--accent);
  opacity: 0;
}

.is-running .strike-line { opacity: calc(0.12 + 0.83 * var(--pulse)); }

/* pd-lit from mockup 3a: the pad floods with its lane colour on press. */
.pad-glow {
  position: absolute;
  inset: -2px;
  border-radius: inherit;
  opacity: 0;
  pointer-events: none;
}

.pad-glow--L { background: rgba(46, 199, 214, 0.55); box-shadow: 0 0 40px rgba(46, 199, 214, 0.85); }
.pad-glow--R { background: rgba(228, 98, 155, 0.5); box-shadow: 0 0 40px rgba(228, 98, 155, 0.8); }

.pad-label { position: relative; }

/* ---------- hit burst ---------- */

.burst {
  position: absolute;
  z-index: 3;
  width: 300px;
  height: 300px;
  border-radius: 50%;
  opacity: 0;
  pointer-events: none;
  transform: translate(-50%, -50%);
}

.burst--L {
  background: radial-gradient(circle, rgba(255, 255, 255, 0.95) 0%, rgba(126, 240, 200, 0.7) 18%,
    rgba(46, 199, 214, 0.35) 40%, rgba(46, 199, 214, 0) 70%);
}

.burst--R {
  background: radial-gradient(circle, rgba(255, 255, 255, 0.95) 0%, rgba(255, 205, 230, 0.7) 18%,
    rgba(228, 98, 155, 0.35) 40%, rgba(228, 98, 155, 0) 70%);
}

/* the pad console runs down to the bottom of the window */
.pads::after {
  content: '';
  position: absolute;
  top: 100%;
  left: 0;
  right: 0;
  height: 100vh;
  background: var(--bg-raised);
}

.pad {
  position: relative;
  width: var(--lane-w);
  height: 58px;
  display: flex;
  align-items: center;
  justify-content: center;
  border: 2px solid;
  font-family: var(--font-mono);
  font-size: 16px;
  letter-spacing: 0.2em;
  user-select: none;
  cursor: pointer;
  touch-action: manipulation;
}

.pad kbd {
  margin-left: 0.6em;
  font: inherit;
  font-size: 11px;
  letter-spacing: 0;
  opacity: 0.5;
}

.is-counting-in .pad {
  transform: scaleY(calc(1 + 0.06 * var(--pulse)));
  opacity: calc(0.62 + 0.38 * var(--pulse));
}

.pad--L {
  justify-self: end;
  border-color: var(--left);
  border-radius: 29px 6px 6px 29px;
  background: rgba(46, 199, 214, 0.1);
  color: var(--left);
}

.pad--R {
  justify-self: start;
  border-color: var(--right);
  border-radius: 6px 29px 29px 6px;
  background: transparent;
  color: var(--right);
}

/* ---------- switch confirm (paused only) ---------- */

.confirm {
  position: absolute;
  inset: 0;
  z-index: 5;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(5, 7, 10, 0.72);
}

.confirm-box {
  width: calc(var(--play-w) - 48px);
  display: flex;
  flex-direction: column;
  gap: 14px;
  padding: 24px;
  border-radius: 16px;
  background: var(--bg-raised);
  border: 1px solid var(--spine);
}

.confirm-title {
  font-size: 20px;
  font-weight: 700;
}

.confirm-body {
  font-size: 14px;
  line-height: 1.5;
  color: var(--text-dim);
}

.confirm-actions {
  display: flex;
  justify-content: flex-end;
  gap: 10px;
  margin-top: 6px;
}

.btn {
  height: 44px;
  padding: 0 18px;
  border-radius: 22px;
  font-family: var(--font-mono);
  font-size: 12px;
  letter-spacing: 0.12em;
  cursor: pointer;
}

.btn:focus-visible { outline: 2px solid var(--text); outline-offset: 2px; }

.btn--ghost {
  border: 1px solid var(--spine);
  background: transparent;
  color: var(--text);
}

/* The confirm button wears the colour of the mode you're switching to. */
.btn--solid {
  border: none;
  background: var(--mint);
  color: #0e1116;
  font-weight: 600;
}

.confirm[data-to='challenge'] .btn--solid { background: var(--violet); }
.confirm[data-to='endless'] .btn--solid { background: var(--right); }

/* ---------- drawers: training setup, challenge levels, leaderboard ---------- */

.drawer {
  position: fixed;
  top: 3px;   /* under the mode strip */
  right: 0;
  bottom: 0;
  z-index: 6;
  width: var(--drawer-w);
  display: flex;
  flex-direction: column;
  background: var(--bg-raised);
  border-left: 1px solid var(--border);
}

.setup-view {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
}

:where(.drawer) button { font-family: inherit; cursor: pointer; }
.drawer button:disabled { cursor: default; opacity: 0.4; }
.drawer button:focus-visible,
.drawer input:focus-visible { outline: 2px solid var(--text); outline-offset: 2px; }

.setup-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 20px 24px 8px;
}

.setup-head--back { justify-content: flex-start; gap: 12px; }

.setup-title {
  font-size: 22px;
  font-weight: 700;
}

.icon-btn {
  width: 44px;
  height: 44px;
  flex-shrink: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  border-radius: 10px;
  border: 1px solid var(--border);
  background: var(--track);
  color: var(--text);
}

.icon-btn:hover:not(:disabled) { border-color: var(--spine); }

.setup-body {
  flex: 1;
  overflow-y: auto;
  padding: 8px 24px 16px;
  display: flex;
  flex-direction: column;
  gap: 22px;
}

.field {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.field-label {
  font-family: var(--font-mono);
  font-size: 11px;
  font-weight: 500;
  letter-spacing: 0.16em;
  color: var(--label);
}

/* Rudiment card and picker rows: name over sticking chips. */
.rud-card,
.rud-row {
  display: flex;
  align-items: center;
  gap: 12px;
  color: var(--text);
  text-align: left;
}

.rud-card {
  padding: 12px 14px;
  border-radius: 12px;
  border: 1px solid var(--border);
  background: var(--track);
}

.rud-card:hover,
.rud-row:hover { background: #18202a; }

.rud-text {
  flex: 1;
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.rud-name { font-size: 16px; font-weight: 500; }

.rud-change {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.12em;
  color: var(--text-dim);
}

.rud-card svg { color: var(--text-dim); }

.chips {
  display: flex;
  flex-wrap: wrap;
  gap: 3px;
  font-family: var(--font-mono);
}

.chip {
  width: 18px;
  height: 22px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 4px;
  font-size: 12px;
  font-weight: 600;
  color: var(--text-faint);
}

.chip--L { color: var(--left); background: rgba(46, 199, 214, 0.14); }
.chip--R { color: var(--right); background: rgba(228, 98, 155, 0.14); }
.chip-gap { width: 6px; }

.tempo-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
}

.bpm-value { font-size: 30px; font-weight: 700; }

.bpm-unit {
  font-family: var(--font-mono);
  font-size: 11px;
  letter-spacing: 0.12em;
  color: var(--text-dim);
}

.tempo-row {
  display: flex;
  align-items: center;
  gap: 10px;
}

.bpm-input {
  flex: 1;
  min-width: 0;
  height: 44px;
  accent-color: var(--accent);
  cursor: pointer;
}

/* Segmented choice, as on the mode toggle but square-cornered. */
.segs {
  display: flex;
  gap: 2px;
  padding: 3px;
  border-radius: 11px;
  background: var(--bg);
  border: 1px solid var(--border);
}

.seg {
  flex: 1;
  height: 40px;
  border: none;
  border-radius: 8px;
  background: transparent;
  color: var(--text-dim);
  font-family: var(--font-mono);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.1em;
}

.seg:hover:not([aria-pressed='true']) { color: var(--text); }

.seg[aria-pressed='true'] {
  background: var(--accent);
  color: var(--bg);
  font-weight: 600;
}

.setup-foot {
  display: flex;
  flex-direction: column;
  gap: 8px;
  padding: 16px 24px 24px;
  border-top: 1px solid var(--border);
}

.start-btn {
  height: 52px;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  border: none;
  border-radius: 12px;
  background: var(--accent);
  color: var(--bg);
  font-size: 16px;
  font-weight: 700;
  letter-spacing: 0.04em;
}

.start-btn kbd {
  font-family: var(--font-mono);
  font-size: 10px;
  font-weight: 600;
  padding: 2px 6px;
  border-radius: 4px;
  border: 1px solid rgba(14, 17, 22, 0.35);
}

.setup-note {
  font-size: 12px;
  color: var(--text-dim);
  text-align: center;
}

.rud-list {
  flex: 1;
  overflow-y: auto;
  padding: 8px 16px 24px;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.rud-row {
  padding: 10px 14px;
  border: none;
  border-radius: 10px;
  background: transparent;
}

.rud-row .rud-text { gap: 6px; }
.rud-row .rud-name { font-size: 15px; }
.rud-check { color: var(--accent); visibility: hidden; }
.rud-row[aria-checked='true'] { background: var(--accent-band); }
.rud-row[aria-checked='true'] .rud-check { visibility: visible; }

.custom-field {
  display: flex;
  flex-direction: column;
  gap: 6px;
  padding: 8px 14px 4px;
}

.custom-input {
  height: 44px;
  padding: 0 12px;
  border-radius: 10px;
  border: 1px solid var(--spine);
  background: var(--bg);
  color: var(--text);
  font-family: var(--font-mono);
  font-size: 16px;
  letter-spacing: 0.2em;
}

/* Before a run the track shows what's coming, a step back from live notes. */
.is-preview .note { filter: saturate(0.7) brightness(0.75); }

/* ---------- results ----------
   Over the track only: the mode toggle, HUD and pads stay where they are. */

.results {
  position: absolute;
  inset: 0;
  z-index: 5;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(5, 7, 10, 0.72);
}

.results-card {
  width: calc(var(--play-w) - 32px);
  display: flex;
  flex-direction: column;
  gap: 16px;
  padding: 20px 20px 18px;
  border-radius: 16px;
  background: var(--bg-raised);
  border: 1px solid var(--spine);
  font-family: var(--font-mono);
}

.results-top {
  display: flex;
  flex-direction: column;
  gap: 4px;
  text-align: center;
}

.results-title {
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.2em;
  color: var(--accent);
}

.results[data-outcome='gameover'] .results-title { color: var(--miss); }

/* Endless keeps it short: the score, where it sits among your runs, three
   stats. No summary, grades or timing. */
.results[data-mode='endless'] .results-title { color: var(--accent); }
.results[data-mode='endless'] :is(.results-summary, .grade-tally, .results-timing) { display: none; }
.results:not([data-mode='endless']) .results-board { display: none; }

.results-board {
  list-style: none;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.board-row {
  display: grid;
  grid-template-columns: 34px 1fr auto;
  align-items: center;
  height: 32px;
  padding: 0 12px;
  border: 1px solid transparent;
  border-radius: 8px;
}

.board-rank { font-size: 12px; color: var(--text-faint); }
.board-when { font-size: 10px; letter-spacing: 0.14em; color: var(--label); }
.board-score { font-size: 14px; color: var(--text-dim); }

.board-row.is-this {
  height: 36px;
  background: var(--accent-band);
  border-color: var(--accent);
}

.is-this .board-rank { font-weight: 600; color: var(--accent); }
.is-this .board-when { color: var(--text); }
.is-this .board-score { font-size: 15px; font-weight: 600; color: var(--text); }

.results-summary {
  font-size: 10px;
  letter-spacing: 0.14em;
  color: var(--label);
}

.results-headline {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
}

.results-big {
  font-family: var(--font-ui);
  font-size: 56px;
  font-weight: 700;
  line-height: 1;
}

.results-card .value { font-size: 24px; }

/* Level ratings: S in the accent, A in plain text, the rest dimmed. */
.results-big[data-rating] { font-size: 64px; }
.results-big[data-rating='S'] { color: var(--accent); text-shadow: 0 0 30px var(--accent-glow); }
.results-big[data-rating='B'],
.results-big[data-rating='C'],
.results-big[data-rating='D'] { color: var(--text-dim); }
.results-big-label.is-new-best { color: var(--accent); }

.results-timing {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.hist-head {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
}

.verdict {
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.16em;
  color: var(--accent);
}

.hist {
  position: relative;
  height: 64px;
  display: flex;
  align-items: flex-end;
  gap: 3px;
  padding-bottom: 1px;
  border-bottom: 2px solid var(--border);
}

.hist-bar {
  flex: 1;
  min-height: 0;
  border-radius: 3px 3px 0 0;
  background: var(--spine);
}

.hist-bar[data-grade='perfect'] { background: var(--accent); }
.hist-bar[data-grade='great'] { background: var(--text-faint); }

.grade-tally {
  display: flex;
  justify-content: center;
  gap: 16px;
  font-size: 10px;
  letter-spacing: 0.14em;
  color: var(--label);
}

.tally b { font-size: 13px; font-weight: 600; margin-left: 4px; color: var(--text-dim); }
.tally[data-grade='perfect'] b { color: var(--accent); }
.tally[data-grade='great'] b { color: var(--text); }

.hist-centre {
  position: absolute;
  left: calc(50% - 1px);
  top: 0;
  bottom: 0;
  width: 2px;
  background: var(--text-faint);
  opacity: 0.5;
}

.hist-axis {
  display: flex;
  justify-content: space-between;
  font-size: 10px;
  letter-spacing: 0.14em;
  color: var(--label);
}

.hist-stats { color: var(--text-dim); letter-spacing: 0.06em; }

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

.results-actions .btn {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  padding: 0 11px;
  white-space: nowrap;
}

.results-again { flex: 1; }
.results .btn--solid { background: var(--accent); color: var(--bg); }

.results-actions kbd {
  font-family: var(--font-mono);
  font-size: 9px;
  padding: 1px 5px;
  border-radius: 4px;
  border: 1px solid currentColor;
  opacity: 0.6;
}

/* ---------- rating bar (cleared levels) ----------
   Score as a share of the level's maximum, with the cut-offs marked. */

.rating-bar {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-top: -4px;
}

.rating-track {
  position: relative;
  height: 8px;
  margin-top: 16px;   /* room for the letters */
  border-radius: 4px;
  background: var(--ghost);
}

.rating-fill {
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  border-radius: 4px;
  background: var(--accent);
  box-shadow: 0 0 12px var(--accent-glow);
}

.rating-tick {
  position: absolute;
  top: -16px;
  bottom: 0;
  width: 2px;
  margin-left: -1px;
  background: linear-gradient(transparent 14px, var(--bg-raised) 14px);
  font-size: 10px;
  font-weight: 600;
  line-height: 12px;
  text-indent: -3px;
  color: var(--label);
}

/* D sits at 0: no divider, letter inside the bar's start. */
.rating-tick:last-child { background: none; text-indent: 0; margin-left: 0; }
.rating-tick.is-earned { color: var(--accent); }

.rating-foot {
  display: flex;
  justify-content: space-between;
  font-size: 10px;
  letter-spacing: 0.12em;
  color: var(--label);
}

.rating-score { color: var(--text-dim); letter-spacing: 0.04em; }

/* ---------- level picker button & level list ---------- */

.level-open {
  min-width: 0;
  height: 40px;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 0 10px 0 12px;
  border-radius: 20px;
  border: 1px solid var(--spine);
  background: var(--bg-raised);
  color: var(--text-dim);
  font: inherit;
  letter-spacing: inherit;
  cursor: pointer;
}

.level-open:hover:not(:disabled) { border-color: var(--text-faint); color: var(--text); }
.level-open:focus-visible { outline: 2px solid var(--text); outline-offset: 2px; }
.level-open[aria-expanded='true'] { border-color: var(--accent); background: var(--accent-band); color: var(--text); }
.level-open svg { flex-shrink: 0; }

.level-name {
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  text-transform: uppercase;
}

/* During a run: just the level, dimmed, like training's locked line. */
.is-running .level-open {
  border-color: transparent;
  background: transparent;
  color: var(--text-faint);
  cursor: default;
}
.is-running .level-open .chip-key,
.is-running .level-open svg { display: none; }

.level-list {
  flex: 1;
  overflow-y: auto;
  padding: 8px 16px 24px;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.level-row {
  display: flex;
  align-items: center;
  gap: 14px;
  padding: 10px 14px;
  border: none;
  border-radius: 10px;
  background: transparent;
  color: var(--text);
  text-align: left;
}

.level-row:hover:not(:disabled) { background: var(--ghost); }
.level-row[aria-checked='true'] { background: var(--accent-band); }
.drawer .level-row:disabled { opacity: 0.45; }

.level-row-num {
  font-family: var(--font-mono);
  font-size: 13px;
  font-weight: 600;
  color: var(--label);
}

.level-row[aria-checked='true'] .level-row-num { color: var(--accent); }

.level-row-text {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.level-row-name { font-size: 15px; font-weight: 500; }

.level-row-detail {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.1em;
  line-height: 1.4;
  color: var(--label);
}

.level-row-best {
  display: flex;
  align-items: center;
  gap: 8px;
  color: var(--text-faint);
}

.level-row-score {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--text-dim);
}

.level-row-new {
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: 0.14em;
  color: var(--accent);
}
