/* ============================================================================
   KICKTABLE — the spin gym.

   One identity, and it does not move. The chrome is five greys, white, and two
   state colours; every hue you see on a mino comes from the palette in
   theme.js. Type is monospace-led because this is a readout, not a poster:
   labels are small, upper, tracked out; only a handful of things are allowed
   to be big. No gradients as decoration, no rotated cards, no glow.

   The rule that keeps it honest: nothing decorative animates. Everything that
   moves is telling you something — you lined up, you dropped, you missed.
   ========================================================================= */

:root {
  /* ground */
  --bg: #09090b;
  --panel: #0e0e11;
  --panel-2: #131318;
  --raise: #17171d;

  /* rules */
  --line: rgba(255, 255, 255, 0.065);
  --line-2: rgba(255, 255, 255, 0.13);
  --line-3: rgba(255, 255, 255, 0.28);

  /* ink */
  --ink: #f3f3f4;
  --ink-2: #9a9aa4;
  --ink-3: #616169;
  --ink-4: #3a3a41;

  /* the only colour that is not on a mino */
  --win: #56e0a0;
  --miss: #ff5f6d;
  --signal: #ffffff;

  /* board */
  --well: #060608;
  --grid: rgba(255, 255, 255, 0.042);
  --frame: rgba(255, 255, 255, 0.17);

  --mono: 'JetBrains Mono', ui-monospace, SFMono-Regular, Menlo, monospace;
  --sans: 'Archivo', 'Segoe UI', system-ui, -apple-system, sans-serif;

  --r: 3px;
  --pad: 14px;
  --bar-h: 52px;
  --dur: 0.16s;
  --ease: cubic-bezier(0.2, 0, 0, 1);

  color-scheme: dark;
}

* { box-sizing: border-box; }

/* The panels are flex containers, so [hidden] needs teeth. */
[hidden] { display: none !important; }

html, body { height: 100%; margin: 0; overflow: hidden; }

body {
  background: var(--bg);
  color: var(--ink);
  font-family: var(--mono);
  font-size: 13px;
  line-height: 1.5;
  font-feature-settings: 'tnum' 1;
  -webkit-font-smoothing: antialiased;
  display: flex;
  flex-direction: column;
}

/* A vignette, not an aurora: it exists to pull the eye to the well, and it is
   the only thing in the app made of a gradient. */
.vignette {
  position: fixed;
  inset: 0;
  pointer-events: none;
  z-index: 0;
  background: radial-gradient(115% 85% at 50% 42%, transparent 38%, rgba(0, 0, 0, 0.55) 100%);
}

::selection { background: var(--ink); color: var(--bg); }

:focus-visible {
  outline: 1px solid var(--signal);
  outline-offset: 2px;
}

/* micro-label: the workhorse of the whole design */
.panel-head h2,
.assign-label,
.q-label,
.streak-label,
.clock-label,
.gate-badge,
.setting-group h3,
.group-label {
  font-family: var(--mono);
  font-size: 9.5px;
  font-weight: 500;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin: 0;
}

/* ------------------------------------------------------------------- bar */

.bar {
  position: relative;
  z-index: 3;
  flex: none;
  height: var(--bar-h);
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  padding: 0 16px;
  border-bottom: 1px solid var(--line);
  background: var(--bg);
}

.wordmark {
  justify-self: start;
  display: flex;
  align-items: center;
  gap: 10px;
  background: none;
  border: 0;
  padding: 4px 6px 4px 0;
  color: var(--ink);
  cursor: pointer;
  font: inherit;
}

.mark { width: 17px; height: 17px; flex: none; overflow: visible; }
.mark g {
  fill: var(--ink);
  transform-origin: 14px 14px;
  transition: transform 0.45s var(--ease);
}
.wordmark:hover .mark g { transform: rotate(90deg); }
.wordmark.spun .mark g { transform: rotate(180deg); }

.wordmark-text {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  line-height: 1.05;
  font-size: 12px;
  font-weight: 700;
  letter-spacing: 0.16em;
}
.wordmark-text i {
  font-style: normal;
  font-size: 8.5px;
  font-weight: 400;
  letter-spacing: 0.2em;
  color: var(--ink-4);
  text-transform: uppercase;
}

.modes {
  justify-self: center;
  display: flex;
  gap: 2px;
  padding: 2px;
  border: 1px solid var(--line);
  border-radius: var(--r);
}

.mode {
  appearance: none;
  border: 0;
  background: none;
  color: var(--ink-3);
  font-family: var(--mono);
  font-size: 10px;
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  padding: 5px 11px;
  border-radius: 2px;
  cursor: pointer;
  transition: color var(--dur) var(--ease), background var(--dur) var(--ease);
}
.mode:hover { color: var(--ink-2); }
.mode.is-on { background: var(--ink); color: var(--bg); }

.bar-right {
  justify-self: end;
  display: flex;
  align-items: center;
  gap: 10px;
}

.bar-sep { width: 1px; height: 16px; background: var(--line); }

.palettes { display: flex; gap: 5px; }

.swatch {
  width: 13px;
  height: 13px;
  padding: 0;
  border: 1px solid transparent;
  border-radius: 1px;
  background-clip: padding-box;
  cursor: pointer;
  opacity: 0.45;
  transition: opacity var(--dur) var(--ease), transform var(--dur) var(--ease);
}
.swatch:hover { opacity: 0.85; }
.swatch.on {
  opacity: 1;
  box-shadow: 0 0 0 1px var(--bg), 0 0 0 2px var(--line-3);
}

.icon-btn {
  width: 26px;
  height: 26px;
  display: grid;
  place-items: center;
  padding: 0;
  border: 1px solid transparent;
  border-radius: var(--r);
  background: none;
  color: var(--ink-3);
  cursor: pointer;
  transition: color var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.icon-btn:hover { color: var(--ink); border-color: var(--line-2); }
.icon-btn svg { width: 15px; height: 15px; }
.icon-btn svg path,
.icon-btn svg circle {
  fill: none;
  stroke: currentColor;
  stroke-width: 1.2;
  stroke-linecap: round;
}
.icon-btn svg .ico-spk { fill: currentColor; stroke-linejoin: round; }
.ico-x { opacity: 0; }
.is-muted #soundBtn .ico-waves { opacity: 0; }
.is-muted #soundBtn .ico-x { opacity: 1; }
.is-muted #soundBtn { color: var(--ink-4); }

/* ------------------------------------------------------------------ grid */

.grid {
  position: relative;
  z-index: 1;
  flex: 1;
  min-height: 0;
  display: grid;
  /* The well is height-constrained, so the centre column would otherwise sit in
     a lake of dead space on a wide screen. Let the rails take the slack first. */
  grid-template-columns: minmax(220px, 300px) minmax(0, 1fr) minmax(252px, 330px);
  gap: 1px;
  background: var(--line);
}

.col {
  display: flex;
  flex-direction: column;
  min-height: 0;
  background: var(--bg);
  gap: 1px;
}

.panel {
  background: var(--panel);
  padding: var(--pad);
  display: flex;
  flex-direction: column;
  min-height: 0;
}

.panel + .panel { border-top: 1px solid var(--line); }

.panel-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  margin-bottom: 11px;
  flex: none;
}

.panel-tag {
  font-size: 9.5px;
  letter-spacing: 0.1em;
  color: var(--ink-4);
  text-transform: uppercase;
}

.ghost-btn {
  appearance: none;
  background: none;
  border: 1px solid var(--line-2);
  border-radius: 2px;
  color: var(--ink-3);
  font-family: var(--mono);
  font-size: 9px;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  padding: 3px 7px;
  cursor: pointer;
  transition: color var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.ghost-btn:hover { color: var(--ink); border-color: var(--line-3); }

.panel-foot {
  flex: none;
  margin: 10px 0 0;
  font-size: 10px;
  line-height: 1.5;
  color: var(--ink-4);
}

/* -------------------------------------------------------------- the index */

.panel-index { flex: 1 1 auto; }
.panel-career { flex: 0 0 auto; max-height: 30vh; }

.drill-list {
  flex: 1;
  min-height: 0;
  overflow-y: auto;
  overscroll-behavior: contain;
  scrollbar-width: thin;
  scrollbar-color: var(--line-2) transparent;
  margin: 0 calc(var(--pad) * -1);
  padding: 0 var(--pad);
  /* so a half-visible row at the fold reads as "more below", not as a bug */
  mask-image: linear-gradient(to bottom, #000 calc(100% - 20px), transparent);
}
.drill-list::-webkit-scrollbar { width: 6px; }
.drill-list::-webkit-scrollbar-thumb { background: var(--line-2); }

.group-label {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 14px 0 6px;
  color: var(--ink-4);
}
.group-label:first-child { padding-top: 0; }
.group-label::after {
  content: '';
  flex: 1;
  height: 1px;
  background: var(--line);
}

.drill {
  width: 100%;
  display: grid;
  grid-template-columns: 22px 1fr auto;
  align-items: center;
  gap: 9px;
  padding: 6px 8px 6px 6px;
  margin: 0 -6px;
  width: calc(100% + 12px);
  background: none;
  border: 0;
  border-left: 2px solid transparent;
  color: var(--ink-2);
  font: inherit;
  text-align: left;
  cursor: pointer;
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease);
}
.drill:hover { background: var(--panel-2); color: var(--ink); }
.drill.is-on {
  background: var(--panel-2);
  border-left-color: var(--ink);
  color: var(--ink);
}
.drill canvas { width: 22px; height: 18px; display: block; opacity: 0.85; }

/* A cheese preset and a finesse set have no piece to draw, so the icon slot
   takes a number or an abbreviation instead. Same column, same weight. */
.drill-badge {
  display: grid;
  place-items: center;
  height: 18px;
  font-size: 9px;
  font-weight: 700;
  letter-spacing: 0.04em;
  color: var(--ink-3);
  border: 1px solid var(--line-2);
}
.drill.is-on .drill-badge { color: var(--ink); border-color: var(--line-3); }
.drill.is-on canvas { opacity: 1; }

.drill-name {
  font-family: var(--sans);
  font-size: 12.5px;
  font-weight: 500;
  line-height: 1.25;
  letter-spacing: -0.005em;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.drill-sub {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 9px;
  color: var(--ink-4);
  letter-spacing: 0.06em;
}
.acc-bar { width: 26px; height: 2px; background: var(--line-2); overflow: hidden; }
.acc-bar i { display: block; height: 100%; background: var(--ink-3); transition: width 0.3s var(--ease); }
.drill.is-on .acc-bar i { background: var(--win); }

.pool-box {
  width: 13px;
  height: 13px;
  border: 1px solid var(--line-2);
  border-radius: 1px;
  position: relative;
  transition: border-color var(--dur) var(--ease), background var(--dur) var(--ease);
}
.pool-box:hover { border-color: var(--line-3); }
.pool-box.on { background: var(--ink); border-color: var(--ink); }
.pool-box.on::after {
  content: '';
  position: absolute;
  left: 3px;
  top: 1px;
  width: 4px;
  height: 7px;
  border: solid var(--bg);
  border-width: 0 1.6px 1.6px 0;
  transform: rotate(42deg);
}

/* career */

.bar-list {
  overflow-y: auto;
  scrollbar-width: thin;
  scrollbar-color: var(--line-2) transparent;
  display: grid;
  gap: 8px;
  padding-right: 4px;
}
.bar-row { display: grid; gap: 4px; }
.bar-top {
  display: flex;
  justify-content: space-between;
  font-size: 10px;
  letter-spacing: 0.06em;
  color: var(--ink-2);
}
.bar-top b { color: var(--ink-4); font-weight: 400; }
.bar-track { height: 2px; background: var(--line-2); }
.bar-track i { display: block; height: 100%; background: var(--ink-3); }
.empty-note { margin: 0; font-size: 10px; color: var(--ink-4); }

/* The four numbers that survive a session: what you have placed, landed,
   wasted and beaten. Same leader-line ledger as the session panel. */
.career-ledger {
  flex: none;
  margin: 0 0 12px;
  padding-bottom: 12px;
  border-bottom: 1px solid var(--line);
}

/* ----------------------------------------------------------------- stage */

.stage {
  background: var(--bg);
  display: flex;
  flex-direction: column;
  align-items: center;
  min-height: 0;
  padding: 16px 18px 12px;
  gap: 12px;
}

.assignment {
  flex: none;
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 0 2px 11px;
  width: 100%;
  max-width: 520px;
  border-bottom: 1px solid var(--line);
}
.assign-piece { width: 26px; height: 26px; flex: none; }
.assign-text { min-width: 0; flex: 1; display: grid; gap: 1px; }
.assign-name {
  font-family: var(--sans);
  font-size: 18px;
  font-weight: 600;
  letter-spacing: -0.02em;
  margin: 0;
  line-height: 1.1;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.assign-meta {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 10px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-3);
  white-space: nowrap;
}
.assign-meta .dot { width: 2px; height: 2px; background: var(--ink-4); }

.play {
  flex: 1;
  min-height: 0;
  display: flex;
  align-items: stretch;
  justify-content: center;
  gap: 16px;
}

.queue {
  width: 66px;
  flex: none;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
  padding-top: 2px;
}
.q-label { align-self: flex-start; }
.q-note {
  margin-top: 2px;
  font-size: 9px;
  letter-spacing: 0.14em;
  color: var(--ink-4);
}
.slot {
  width: 66px;
  height: 46px;
  border: 1px solid var(--line);
  background: var(--panel);
}
.slot-sm { height: 38px; opacity: 0.5; }

.board-wrap {
  position: relative;
  min-height: 0;
  height: 100%;
  aspect-ratio: 1 / 2;
}
#board { width: 100%; height: 100%; display: block; }

/* the verdict — big, mono, centred, gone in under a second */
.verdict {
  position: absolute;
  left: 0;
  right: 0;
  top: 43%;
  text-align: center;
  font-family: var(--mono);
  font-size: clamp(15px, 2.6vw, 22px);
  font-weight: 700;
  letter-spacing: 0.16em;
  color: var(--ink);
  text-shadow: 0 2px 18px rgba(0, 0, 0, 0.9);
  pointer-events: none;
  opacity: 0;
}
.verdict.win { color: var(--win); }
.verdict.miss { color: var(--miss); }
.verdict.show { animation: verdict 0.78s var(--ease) forwards; }
@keyframes verdict {
  0% { opacity: 0; transform: scale(0.94); letter-spacing: 0.05em; }
  14% { opacity: 1; transform: scale(1); }
  70% { opacity: 1; letter-spacing: 0.16em; }
  100% { opacity: 0; letter-spacing: 0.3em; }
}

.combo {
  position: absolute;
  left: 0;
  right: 0;
  top: 35%;
  text-align: center;
  font-size: 10px;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--ink-3);
  pointer-events: none;
  opacity: 0;
}
.combo.show { animation: comboFade 1s var(--ease) forwards; }

/* The answer is one key away and people were not finding it. This says so on
   the board itself, parked in the band of the well that nothing reaches. The
   deepest field in the gym is Dig's nine rows of cheese, whose lip sits at
   55% — so the pill rides just above that, clear of the garbage in every room
   and well below the spawn. It is chrome, not decoration: hairline, grey, and
   gone the moment the answer is actually on screen. */
.tab-hint {
  position: absolute;
  left: 50%;
  top: 46%;
  transform: translateX(-50%);
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 4px 8px;
  border: 1px solid var(--line-2);
  border-radius: var(--r);
  background: rgba(6, 6, 8, 0.72);
  color: var(--ink-3);
  font-family: var(--mono);
  font-size: 9px;
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  white-space: nowrap;
  cursor: pointer;
  transition: color var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.tab-hint kbd { border-color: var(--line-2); }
.tab-hint:hover { color: var(--ink); border-color: var(--line-3); }
.tab-hint:hover kbd { color: var(--ink); border-color: var(--line-3); }
.tab-hint.nudge { color: var(--ink); border-color: var(--line-3); animation: nudge 1.5s var(--ease) infinite; }
@keyframes comboFade {
  0% { opacity: 0; transform: translateY(4px); }
  18% { opacity: 1; transform: none; }
  100% { opacity: 0; }
}

/* gate */

.gate {
  position: absolute;
  inset: 0;
  display: grid;
  place-items: center;
  background: rgba(6, 6, 8, 0.86);
  backdrop-filter: blur(3px);
  z-index: 2;
}
.gate[hidden] { display: none; }
.gate-inner {
  text-align: center;
  padding: 22px;
  max-width: 270px;
  animation: gateIn 0.4s var(--ease);
}
@keyframes gateIn {
  from { opacity: 0; transform: translateY(6px); }
}
.gate-badge {
  display: inline-block;
  padding: 3px 8px;
  border: 1px solid var(--line-2);
  color: var(--ink-3);
  margin-bottom: 14px;
}
.gate-inner h2 {
  font-family: var(--sans);
  font-size: 26px;
  font-weight: 600;
  letter-spacing: -0.03em;
  margin: 0 0 8px;
}
.gate-inner p {
  color: var(--ink-2);
  font-size: 11.5px;
  line-height: 1.65;
  margin: 0 0 20px;
}
.gate-keys {
  font-size: 9.5px !important;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-4) !important;
  margin: 12px 0 0 !important;
}

.primary {
  appearance: none;
  border: 0;
  background: var(--ink);
  color: var(--bg);
  font-family: var(--mono);
  font-size: 10.5px;
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  padding: 11px 20px;
  cursor: pointer;
  transition: transform var(--dur) var(--ease), background var(--dur) var(--ease);
}
.primary:hover { background: #fff; transform: translateY(-1px); }
.primary:active { transform: translateY(0); }

/* readout — the voice, demoted from a mascot to one dry line */

.readout {
  flex: none;
  display: flex;
  align-items: baseline;
  gap: 8px;
  margin: 0;
  height: 16px;
  font-size: 11.5px;
  color: var(--ink-2);
  max-width: 100%;
  overflow: hidden;
  white-space: nowrap;
}
.caret {
  width: 5px;
  height: 9px;
  background: var(--ink-4);
  flex: none;
  animation: blink 1.15s steps(1) infinite;
}
@keyframes blink { 50% { opacity: 0; } }
.readout.pop #readout { animation: readIn 0.3s var(--ease); }
@keyframes readIn {
  from { opacity: 0; transform: translateX(-3px); }
}
.readout.win-line { color: var(--win); }
.readout.miss-line { color: var(--miss); }

/* legend */

.legend {
  flex: none;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 4px 12px;
  font-size: 9.5px;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-4);
}
.legend > * { display: flex; align-items: center; gap: 4px; }

kbd {
  font-family: var(--mono);
  font-size: 9px;
  font-weight: 500;
  line-height: 1;
  padding: 3px 4px;
  min-width: 15px;
  text-align: center;
  border: 1px solid var(--line-2);
  border-radius: 2px;
  color: var(--ink-3);
  background: var(--panel);
}

.legend-hot {
  appearance: none;
  background: none;
  border: 0;
  padding: 0;
  font: inherit;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-2);
  cursor: pointer;
  transition: color var(--dur) var(--ease);
}
.legend-hot kbd { border-color: var(--line-3); color: var(--ink); }
.legend-hot:hover { color: var(--ink); }
.legend-hot.nudge { color: var(--ink); animation: nudge 1.5s var(--ease) infinite; }
@keyframes nudge {
  0%, 100% { opacity: 0.55; }
  50% { opacity: 1; }
}

/* ---------------------------------------------------------- the recipe */

.panel-recipe { position: relative; flex: 0 0 auto; }

/* The old version of this was a 40px ghost link nobody found. It is now the
   loudest object in the right column, and it says what it does. */
.show-me {
  display: flex;
  align-items: center;
  gap: 9px;
  width: 100%;
  padding: 10px 11px;
  margin-bottom: 12px;
  background: var(--raise);
  border: 1px solid var(--line-2);
  border-radius: var(--r);
  color: var(--ink);
  font-family: var(--mono);
  font-size: 10.5px;
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  cursor: pointer;
  transition: background var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.show-me:hover { background: #1d1d24; border-color: var(--line-3); }
.show-me .show-label { flex: 1; text-align: left; }
.show-me kbd { background: transparent; }
.show-ico {
  width: 0;
  height: 0;
  flex: none;
  border-left: 7px solid var(--ink);
  border-top: 4.5px solid transparent;
  border-bottom: 4.5px solid transparent;
  margin-left: 1px;
}
.show-me.pulse {
  animation: showPulse 1.9s var(--ease) infinite;
  border-color: var(--line-3);
}
@keyframes showPulse {
  0%, 100% { box-shadow: 0 0 0 0 rgba(255, 255, 255, 0); }
  40% { box-shadow: 0 0 0 3px rgba(255, 255, 255, 0.09); }
}
.demoing .show-ico {
  border: 0;
  width: 8px;
  height: 8px;
  background: var(--win);
  margin-left: 0;
  animation: blink 0.7s steps(1) infinite;
}

.recipe-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  gap: 1px;
}

.step {
  display: grid;
  grid-template-columns: 14px 34px 1fr;
  align-items: baseline;
  gap: 8px;
  padding: 5px 6px;
  margin: 0 -6px;
  font-size: 11px;
  color: var(--ink-2);
  border-left: 1px solid transparent;
  transition: color var(--dur) var(--ease), background var(--dur) var(--ease);
}
.step-n {
  font-size: 9px;
  color: var(--ink-4);
  font-variant-numeric: tabular-nums;
}
.step-keys { display: flex; align-items: center; gap: 3px; }
.rep { font-size: 9px; color: var(--ink-4); }
.step-label { font-family: var(--sans); font-size: 12px; letter-spacing: -0.005em; }

.step.twist { color: var(--ink); }
.step.twist .step-label { font-weight: 600; }
.step.twist kbd { border-color: var(--line-3); color: var(--ink); }
.step-note {
  grid-column: 3;
  font-size: 10px;
  line-height: 1.45;
  color: var(--ink-4);
  white-space: normal;
}
/* Dig has no recipe, only rules — same row, minus the key column. */
.step.rule { grid-template-columns: 14px 1fr; color: var(--ink); }
.step.rule .step-label { font-weight: 600; }
.step.rule .step-note { grid-column: 2; }

.step.on {
  background: var(--panel-2);
  border-left-color: var(--win);
  color: var(--ink);
}
.step.on kbd { border-color: var(--win); color: var(--win); }
.step-empty { font-size: 10.5px; color: var(--ink-4); padding: 4px 0; }

/* first-run coach mark */
.coachmark {
  position: absolute;
  left: var(--pad);
  right: var(--pad);
  top: calc(100% - 6px);
  z-index: 4;
  background: var(--ink);
  color: var(--bg);
  padding: 11px 12px;
  border-radius: var(--r);
  box-shadow: 0 14px 40px rgba(0, 0, 0, 0.6);
  animation: markIn 0.35s var(--ease);
}
.coachmark[hidden] { display: none; }
.coachmark::before {
  content: '';
  position: absolute;
  top: -5px;
  left: 26px;
  width: 10px;
  height: 10px;
  background: var(--ink);
  transform: rotate(45deg);
}
.coachmark p {
  margin: 0 0 9px;
  font-size: 11px;
  line-height: 1.5;
  font-family: var(--sans);
}
.coachmark kbd {
  background: rgba(0, 0, 0, 0.08);
  border-color: rgba(0, 0, 0, 0.25);
  color: var(--bg);
}
.coachmark .ghost-btn {
  border-color: rgba(0, 0, 0, 0.3);
  color: rgba(0, 0, 0, 0.65);
}
.coachmark .ghost-btn:hover { border-color: var(--bg); color: var(--bg); }
@keyframes markIn {
  from { opacity: 0; transform: translateY(-6px); }
}

/* ------------------------------------------------------------- numbers */

.panel-streak { flex: none; }
.streak-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  margin-bottom: 9px;
}
.streak-num {
  font-family: var(--sans);
  font-size: 30px;
  font-weight: 700;
  line-height: 0.9;
  letter-spacing: -0.04em;
  font-variant-numeric: tabular-nums;
  transition: color 0.2s var(--ease);
}
.streak-num.hot { color: var(--win); }

.pips { display: flex; gap: 3px; }
.pips i {
  flex: 1;
  height: 3px;
  background: var(--line-2);
  transition: background 0.2s var(--ease);
}
.pips i.on { background: var(--ink-2); }
.pips i.hot { background: var(--win); }

.panel-numbers { flex: none; }
.numbers { margin: 0; display: grid; gap: 6px; }
.numbers > div {
  display: flex;
  align-items: baseline;
  gap: 8px;
  justify-content: space-between;
}
.numbers dt { font-size: 10.5px; color: var(--ink-3); letter-spacing: 0.04em; }
.numbers > div::after {
  content: '';
  order: 1;
  flex: 1;
  height: 1px;
  background: var(--line);
  transform: translateY(-3px);
}
.numbers dd {
  order: 2;
  margin: 0;
  font-size: 11.5px;
  color: var(--ink);
  font-variant-numeric: tabular-nums;
}

.meter-box {
  margin-top: 14px;
  padding-top: 12px;
  border-top: 1px solid var(--line);
  display: grid;
  gap: 2px;
}

.clock {
  font-family: var(--sans);
  font-size: 28px;
  font-weight: 600;
  line-height: 1;
  letter-spacing: -0.03em;
  font-variant-numeric: tabular-nums;
}
.clock.low { color: var(--miss); }

/* --------------------------------------------------------------- sheet */

.sheet {
  border: 0;
  padding: 0;
  background: none;
  color: var(--ink);
  max-width: 460px;
  width: calc(100% - 32px);
  max-height: 86vh;
}
.sheet::backdrop { background: rgba(4, 4, 6, 0.72); backdrop-filter: blur(4px); }
.sheet[open] { animation: gateIn 0.24s var(--ease); }

.sheet-inner {
  background: var(--panel);
  border: 1px solid var(--line-2);
  border-radius: var(--r);
  max-height: 86vh;
  overflow-y: auto;
  scrollbar-width: thin;
  scrollbar-color: var(--line-2) transparent;
}

.sheet-head {
  position: sticky;
  top: 0;
  z-index: 1;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 14px 16px;
  background: var(--panel);
  border-bottom: 1px solid var(--line);
}
.sheet-head h2 {
  font-family: var(--sans);
  font-size: 15px;
  font-weight: 600;
  letter-spacing: -0.01em;
  margin: 0;
}

.setting-group { padding: 16px; }
.setting-group + .setting-group { border-top: 1px solid var(--line); }
.setting-group h3 { margin-bottom: 12px; }
.group-note {
  display: block;
  font-size: 10px;
  line-height: 1.55;
  color: var(--ink-4);
  margin: 8px 0 12px;
}

.seg {
  display: flex;
  gap: 1px;
  background: var(--line);
  border: 1px solid var(--line);
  border-radius: var(--r);
  overflow: hidden;
}
.seg-btn {
  flex: 1;
  appearance: none;
  border: 0;
  background: var(--panel);
  color: var(--ink-3);
  font-family: var(--mono);
  font-size: 9.5px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  padding: 8px 4px;
  cursor: pointer;
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease);
}
.seg-btn:hover { color: var(--ink); }
.seg-btn.on { background: var(--ink); color: var(--bg); }

.presets { display: flex; gap: 6px; margin-bottom: 16px; flex-wrap: wrap; }
.preset {
  appearance: none;
  background: none;
  border: 1px solid var(--line-2);
  border-radius: 2px;
  color: var(--ink-3);
  font-family: var(--mono);
  font-size: 9.5px;
  letter-spacing: 0.08em;
  padding: 6px 9px;
  cursor: pointer;
  transition: color var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.preset:hover { color: var(--ink); border-color: var(--line-3); }
.preset.on { background: var(--ink); border-color: var(--ink); color: var(--bg); }

.slider { display: block; margin-bottom: 15px; }
.slider > span {
  display: flex;
  justify-content: space-between;
  font-size: 10.5px;
  color: var(--ink-2);
  letter-spacing: 0.06em;
  margin-bottom: 7px;
}
.slider b { color: var(--ink); font-weight: 500; font-variant-numeric: tabular-nums; }
.slider small {
  display: block;
  margin-top: 6px;
  font-size: 9.5px;
  line-height: 1.5;
  color: var(--ink-4);
}

input[type='range'] {
  appearance: none;
  width: 100%;
  height: 14px;
  background: none;
  cursor: pointer;
}
input[type='range']::-webkit-slider-runnable-track { height: 1px; background: var(--line-2); }
input[type='range']::-moz-range-track { height: 1px; background: var(--line-2); }
input[type='range']::-webkit-slider-thumb {
  appearance: none;
  width: 3px;
  height: 13px;
  background: var(--ink);
  border: 0;
  border-radius: 0;
  margin-top: -6px;
}
input[type='range']::-moz-range-thumb {
  width: 3px;
  height: 13px;
  background: var(--ink);
  border: 0;
  border-radius: 0;
}

.check {
  display: flex;
  align-items: center;
  gap: 9px;
  font-size: 11.5px;
  color: var(--ink-2);
  padding: 5px 0;
  cursor: pointer;
}
.check input {
  appearance: none;
  width: 14px;
  height: 14px;
  margin: 0;
  border: 1px solid var(--line-2);
  border-radius: 1px;
  position: relative;
  cursor: pointer;
  flex: none;
}
.check input:checked { background: var(--ink); border-color: var(--ink); }
.check input:checked::after {
  content: '';
  position: absolute;
  left: 4px;
  top: 1px;
  width: 4px;
  height: 8px;
  border: solid var(--bg);
  border-width: 0 1.6px 1.6px 0;
  transform: rotate(42deg);
}
.check:hover { color: var(--ink); }

.binds { display: grid; grid-template-columns: 1fr 1fr; gap: 5px; margin-bottom: 12px; }
.bind {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 8px;
  background: none;
  border: 1px solid var(--line);
  border-radius: 2px;
  padding: 7px 9px;
  color: var(--ink-3);
  font-family: var(--mono);
  font-size: 10px;
  cursor: pointer;
  transition: border-color var(--dur) var(--ease), color var(--dur) var(--ease);
}
.bind:hover { border-color: var(--line-2); color: var(--ink-2); }
.bind b { color: var(--ink); font-weight: 500; }
.bind.listening { border-color: var(--ink); color: var(--ink); }

/* -------------------------------------------------------------- responsive */

@media (max-width: 1180px) {
  .grid { grid-template-columns: 200px minmax(0, 1fr) 244px; }
  .mode { padding: 5px 8px; letter-spacing: 0.1em; }
}

@media (max-width: 1000px) {
  html, body { overflow: auto; }
  .grid {
    grid-template-columns: minmax(0, 1fr);
    grid-template-areas: 'stage' 'right' 'left';
  }
  .stage { grid-area: stage; height: 78vh; }
  .col-left { grid-area: left; }
  .col-right { grid-area: right; }
  .panel-index { max-height: 46vh; }
  .panel-career { max-height: none; }
  .bar { grid-template-columns: auto 1fr auto; gap: 10px; }
  .modes {
    justify-self: center;
    max-width: 100%;
    overflow-x: auto;
    scrollbar-width: none;
  }
  .modes::-webkit-scrollbar { display: none; }
  .mode { flex: none; }
}

@media (max-width: 620px) {
  /* Five rooms will not fit beside the wordmark, and a mode you cannot see is
     a mode that does not exist. Give them their own full-width row. */
  .bar {
    height: auto;
    grid-template-columns: auto 1fr;
    grid-template-areas: 'brand right' 'modes modes';
    row-gap: 8px;
    padding: 8px 12px;
  }
  .wordmark { grid-area: brand; }
  .bar-right { grid-area: right; }
  .modes {
    grid-area: modes;
    justify-self: stretch;
    justify-content: space-between;
  }
  .mode { padding: 5px 6px; letter-spacing: 0.06em; }

  .wordmark-text i { display: none; }
  .queue { width: 48px; }
  .slot { width: 48px; height: 34px; }
  .slot-sm { height: 28px; }
  .play { gap: 8px; }
  /* Everything in the legend is discoverable elsewhere except the one line
     that points at the answer, so that is the line that survives. */
  .legend > span { display: none; }
}

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
  .caret { opacity: 1; }
}
