/* keyblab — Keychron K2 typing lab
   Palette: validated data-viz reference instance (blue sequential ramp for heat,
   status hues reserved for good/bad, blue<->red for signed change). Dark is a
   selected mode, not an inversion. */

:root {
  color-scheme: dark;
  --bg:            #0d0d0d;
  --surface-1:     #1a1a19;
  --surface-2:     #212120;
  --surface-3:     #2a2a28;
  --text-primary:  #ffffff;
  --text-secondary:#c3c2b7;
  --muted:         #898781;
  --grid:          #2c2c2a;
  --baseline:      #383835;
  --border:        rgba(255,255,255,0.10);
  --border-strong: rgba(255,255,255,0.16);
  --series-1:      #3987e5;
  --series-1-soft: rgba(57,135,229,0.16);
  --diverge-warm:  #e66767;
  --good:          #0ca30c;
  --warning:       #fab219;
  --serious:       #ec835a;
  --critical:      #d03b3b;
  /* Keycaps, as on the board: lighter alphas, darker modifiers, one accent esc */
  --cap-hi:        #5c5b57;
  --cap-lo:        #474643;
  --cap-edge:      #232322;
  --cap-ink:       #eceae4;
  --cap2-hi:       #2e2e2c;
  --cap2-lo:       #222221;
  --cap2-edge:     #171716;
  --cap2-ink:      #cbc9c2;
  --cap-accent-hi: #cf9a72;
  --cap-accent-lo: #bd8760;
  --cap-accent-ink:#2b1d13;
  --case:          #161614;
  --case-edge:     #000;
  --wood-1:        #a6825a;
  --wood-2:        #856544;
  --wood-3:        #96734e;

  /* Frosted surfaces. The alpha has to stay high enough that 15px body text on
     glass still clears contrast once the mesh drifts underneath it. */
  --glass-1:       rgba(22, 22, 26, 0.75);
  --glass-2:       rgba(26, 26, 30, 0.62);
  --glass-edge-a:  rgba(255,255,255,0.055);
  --glass-edge-b:  rgba(255,255,255,0.20);
  --aura-a:        74 108 132;
  --aura-b:        44 66 92;
  --aura-i:        0;

  --mono: ui-monospace, SFMono-Regular, "SF Mono", Menlo, Consolas, monospace;
  --sans: system-ui, -apple-system, "Segoe UI", sans-serif;
  --r: 10px;
  --shadow: 0 1px 2px rgba(0,0,0,.4), 0 8px 24px rgba(0,0,0,.28);
}

:root[data-theme="light"] {
  color-scheme: light;
  --bg:            #f9f9f7;
  --surface-1:     #fcfcfb;
  --surface-2:     #f3f2ee;
  --surface-3:     #e9e8e2;
  --text-primary:  #0b0b0b;
  --text-secondary:#52514e;
  --muted:         #898781;
  --grid:          #e1e0d9;
  --baseline:      #c3c2b7;
  --border:        rgba(11,11,11,0.10);
  --border-strong: rgba(11,11,11,0.18);
  --series-1:      #2a78d6;
  --series-1-soft: rgba(42,120,214,0.12);
  --diverge-warm:  #e34948;
  --cap-hi:        #fbfaf7;
  --cap-lo:        #eae8e1;
  --cap-edge:      #c9c7bf;
  --cap-ink:       #2f2e2a;
  --cap2-hi:       #dedcd4;
  --cap2-lo:       #cbc9c0;
  --cap2-edge:     #adaba2;
  --cap2-ink:      #3a3934;
  --cap-accent-hi: #dda87f;
  --cap-accent-lo: #cb9469;
  --cap-accent-ink:#332317;
  --case:          #23231f;
  --case-edge:     #0d0d0b;
  --wood-1:        #bb9163;
  --wood-2:        #98734b;
  --wood-3:        #ab8256;
  --shadow: 0 1px 2px rgba(11,11,11,.08), 0 8px 24px rgba(11,11,11,.07);
  /* Light glass is a brighter frost, and its edge highlight has to come from
     shadow rather than white, or the ring vanishes into the page. */
  --glass-1:       rgba(255, 255, 254, 0.72);
  --glass-2:       rgba(255, 255, 254, 0.55);
  --glass-edge-a:  rgba(11,11,11,0.07);
  --glass-edge-b:  rgba(11,11,11,0.20);
}

* { box-sizing: border-box; }
html, body { margin: 0; padding: 0; }
/* Reserve the scrollbar gutter always: the live board scales to its container,
   so a scrollbar that comes and goes would make it oscillate. The root needs the
   page colour too, or the reserved strip renders as bare canvas. */
html { scrollbar-gutter: stable; background: var(--bg); }
body {
  /* Deliberately transparent: html carries the page colour, and a background
     here would paint over .mesh and .aura. Block backgrounds are painted after
     negative-z-index children, so an opaque body hides anything behind it. */
  background: transparent;
  color: var(--text-primary);
  font-family: var(--sans);
  font-size: 15px;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
}
h1, h2, h3 { margin: 0; font-weight: 600; letter-spacing: -0.01em; }
h2 { font-size: 17px; }
h3 { font-size: 13.5px; color: var(--text-secondary); font-weight: 600;
     text-transform: uppercase; letter-spacing: .07em; }
p { margin: 0 0 10px; }
a { color: var(--series-1); }
.empty { color: var(--muted); font-size: 13px; margin: 6px 0; }
.mono { font-family: var(--mono); }
.num { font-variant-numeric: tabular-nums; }

/* ---------- shell ---------- */
.wrap { max-width: 1180px; margin: 0 auto; padding: 0 22px 72px; }

.topbar {
  position: sticky; top: 0; z-index: 40;
  background: color-mix(in srgb, var(--bg) 86%, transparent);
  backdrop-filter: blur(14px);
  border-bottom: 1px solid var(--border);
}
.topbar-in {
  max-width: 1180px; margin: 0 auto; padding: 12px 22px;
  display: flex; align-items: center; gap: 14px; flex-wrap: wrap;
}
.brand { display: flex; align-items: baseline; gap: 10px; margin-right: auto; }
.brand b { font-size: 17px; letter-spacing: -0.02em; }
.brand span { color: var(--muted); font-size: 12.5px; font-family: var(--mono); }
.brand .dot {
  width: 7px; height: 7px; border-radius: 50%; background: var(--series-1);
  box-shadow: 0 0 0 3px var(--series-1-soft); align-self: center;
}

.tabs { display: flex; gap: 2px; padding: 3px; background: var(--surface-2);
        border: 1px solid var(--border); border-radius: 999px; }
.tab {
  appearance: none; border: 0; background: transparent; color: var(--text-secondary);
  font: inherit; font-size: 13.5px; padding: 6px 15px; border-radius: 999px;
  cursor: pointer; transition: background .16s, color .16s;
}
.tab:hover { color: var(--text-primary); }
.tab[aria-selected="true"] { background: var(--surface-1); color: var(--text-primary);
  box-shadow: 0 1px 2px rgba(0,0,0,.25); }

button, select, input[type="text"], input[type="number"] {
  font: inherit; font-size: 13.5px; color: var(--text-primary);
  background: var(--surface-2); border: 1px solid var(--border);
  border-radius: 8px; padding: 6px 11px;
}
button { cursor: pointer; transition: background .15s, border-color .15s, transform .06s; }
button:hover { border-color: var(--border-strong); background: var(--surface-3); }
button:active { transform: translateY(1px); }
button.primary { background: var(--series-1); border-color: transparent; color: #fff; font-weight: 600; }
button.primary:hover { background: color-mix(in srgb, var(--series-1) 88%, #fff); }
button.primary { position: relative; overflow: hidden; isolation: isolate; }
button.primary::after {
  content: ""; position: absolute; inset: -80% -30%; pointer-events: none; z-index: 0;
  background: linear-gradient(105deg, transparent 38%, rgba(255,255,255,.34) 48%, transparent 58%);
  transform: translateX(-70%) rotate(8deg); transition: transform .55s cubic-bezier(.16,1,.3,1);
}
button.primary:hover::after { transform: translateX(70%) rotate(8deg); }
button.ghost { background: transparent; }
button.danger:hover { border-color: var(--critical); color: var(--critical); }
select { padding-right: 26px; }
label.field { display: inline-flex; align-items: center; gap: 7px; font-size: 13px;
              color: var(--text-secondary); }
input[type="checkbox"] { accent-color: var(--series-1); }

.view { display: none; padding-top: 22px; }
.view.is-on { display: block; animation: fade .22s ease; }
@keyframes fade { from { opacity: 0; transform: translateY(4px); } to { opacity: 1; transform: none; } }

/* Frosted acrylic: a translucent fill over the mesh, blurred, with the 1px edge
   drawn as a masked gradient ring instead of a flat border — a real border can
   only be one colour, and glass catches light unevenly along its rim. */
.card {
  position: relative;
  background: var(--glass-1);
  backdrop-filter: blur(20px) saturate(135%);
  -webkit-backdrop-filter: blur(20px) saturate(135%);
  border: 0;
  border-radius: 14px; padding: 18px; box-shadow: var(--shadow);
}
.card::before {
  content: ""; position: absolute; inset: 0; border-radius: inherit;
  padding: 1px; pointer-events: none;
  background: conic-gradient(from var(--kb-angle),
    var(--glass-edge-a), var(--glass-edge-b) 18%, var(--glass-edge-a) 38%,
    var(--glass-edge-a) 62%, var(--glass-edge-b) 78%, var(--glass-edge-a));
  -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  -webkit-mask-composite: xor;
  mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
  mask-composite: exclude;
}
.card + .card { margin-top: 16px; }
.card-head { display: flex; align-items: center; gap: 12px; margin-bottom: 14px; flex-wrap: wrap; }
.card-head .spacer { margin-left: auto; }
.sub { color: var(--muted); font-size: 12.5px; }
.grid2 { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
@media (max-width: 860px) { .grid2 { grid-template-columns: 1fr; } }

/* one filter row above everything it scopes */
.filters {
  position: relative; overflow: hidden;
  display: flex; align-items: center; gap: 16px; flex-wrap: wrap;
  padding: 11px 16px; margin-bottom: 16px;
  background: var(--surface-1); border: 1px solid var(--border); border-radius: 12px;
}

/* ---------- stat tiles ---------- */
.stats { display: grid; grid-template-columns: repeat(4, 1fr); gap: 12px; margin-bottom: 16px; }
@media (max-width: 720px) { .stats { grid-template-columns: repeat(2, 1fr); } }
.stat {
  position: relative;
  background: var(--glass-2);
  backdrop-filter: blur(14px) saturate(125%);
  -webkit-backdrop-filter: blur(14px) saturate(125%);
  border: 1px solid var(--border);
  border-radius: 12px; padding: 13px 15px;
}

/* React Bits-inspired Spotlight Card, translated to the app's vanilla stack.
   The typing card is excluded so decoration can never cross the passage. */
:root[data-mode="precision"] body:not(.fx-off) .ui-spotlight:not(.type-card)::after {
  content: ""; position: absolute; inset: 0; border-radius: inherit;
  pointer-events: none; z-index: 3;
  background: radial-gradient(240px circle at var(--spot-x, 50%) var(--spot-y, 50%),
    rgb(var(--aura-a) / .13), rgba(255,255,255,.035) 38%, transparent 68%);
  opacity: 1; animation: ui-spot-in .24s ease both;
}
@keyframes ui-spot-in { from { opacity: 0; } to { opacity: 1; } }

.stat .k { font-size: 11.5px; color: var(--muted); text-transform: uppercase; letter-spacing: .07em; }
.stat .v { font-size: 30px; font-weight: 650; letter-spacing: -0.03em; line-height: 1.15; margin-top: 3px; }
.stat .v small { font-size: 13px; font-weight: 500; color: var(--muted); margin-left: 3px; letter-spacing: 0; }
.stat .d { font-size: 12px; color: var(--text-secondary); margin-top: 2px; }
.delta-up { color: var(--good); } .delta-down { color: var(--critical); }
.delta-flat { color: var(--muted); }

/* ---------- typing surface ---------- */
/* The passage is the anchor of the page: bigger type, three lines at a time,
   and the surrounding chrome recedes while a run is in progress. */
.type-card { position: relative; padding: 22px 26px 20px; }
.passage {
  position: relative; font-family: var(--mono); font-size: 29px; line-height: 1.72;
  letter-spacing: .005em; height: 5.16em; overflow: hidden; padding: 6px 2px;
  cursor: text; user-select: none; outline: none;
}
@media (max-width: 720px) { .passage { font-size: 22px; } }
.passage-inner, .passage .caret { transition: transform .18s cubic-bezier(.22,.7,.3,1), filter .2s, opacity .2s; }
.passage.is-blurred .passage-inner { filter: blur(4px); opacity: .45; }
.passage.is-blurred .caret { opacity: 0; }
.w { display: inline-block; white-space: nowrap; }
/* pre keeps the inter-word space from being collapsed away at the end of a word */
.c { color: var(--muted); transition: color .1s; white-space: pre; }
.c.is-correct { color: var(--text-primary); }
.c.is-wrong { color: var(--critical); background: color-mix(in srgb, var(--critical) 16%, transparent);
              border-radius: 3px; }
.c.is-wrong.is-space { background: color-mix(in srgb, var(--critical) 34%, transparent); }
.caret {
  position: absolute; width: 2.5px;
  background: rgb(var(--aura-a));
  box-shadow: 0 0 10px rgb(var(--aura-a) / .85);
  border-radius: 2px;
  transition: transform .075s cubic-bezier(.16, 1, .3, 1), height .1s;
  will-change: transform;
  animation: blink 1.05s steps(1) infinite;
}
@keyframes blink { 0%,60% { opacity: 1; } 61%,100% { opacity: .18; } }
.passage.is-typing .caret { animation: none; opacity: 1; }
.focus-veil {
  position: absolute; inset: 0; display: grid; place-items: center;
  font-size: 14px; color: var(--text-secondary); cursor: pointer; z-index: 2;
}
.focus-veil span {
  padding: 7px 15px; border-radius: 999px; background: var(--surface-2);
  border: 1px solid var(--border); box-shadow: var(--shadow);
}
kbd {
  font-family: var(--mono); font-size: .85em; padding: 1px 6px; border-radius: 5px;
  background: var(--surface-3); border: 1px solid var(--border); color: var(--text-primary);
}
body.is-running .stats,
body.is-running .topbar { opacity: .42; transition: opacity .35s ease; }
.stats, .topbar { transition: opacity .35s ease; }

.run-meta { display: flex; gap: 18px; align-items: center; flex-wrap: wrap;
            font-size: 12.5px; color: var(--muted); margin-top: 14px; }
.run-meta b { color: var(--text-primary); font-variant-numeric: tabular-nums; font-weight: 600; }
.progress { height: 3px; background: var(--surface-3); border-radius: 3px; overflow: hidden; flex: 1; min-width: 120px; }
.progress i { display: block; height: 100%; background: var(--series-1); width: 0;
              transition: width .12s linear; }

/* ---------- live board disclosure ---------- */
.board-card { padding: 0; }
.disclosure {
  display: flex; align-items: center; gap: 11px; width: 100%; text-align: left;
  background: none; border: 0; border-radius: 14px; padding: 16px 18px; color: inherit;
}
.disclosure:hover { background: var(--surface-2); border-color: transparent; }
.disclosure .chev { color: var(--muted); font-size: 12px; transition: transform .24s ease; }
.board-card.is-open .disclosure .chev { transform: rotate(90deg); }
.board-card.is-open .disclosure { border-radius: 14px 14px 0 0; }
.disclosure .sub { margin-left: auto; text-align: right; }
.board-body {
  display: grid; grid-template-rows: 0fr; opacity: 0;
  transition: grid-template-rows .3s cubic-bezier(.3,.8,.35,1), opacity .22s ease;
}
.board-card.is-open .board-body { grid-template-rows: 1fr; opacity: 1; }
.board-inner { min-height: 0; overflow: hidden; padding: 0 18px 18px; }
.board-card.is-settled .board-inner { overflow: visible; }

/* ---------- keyboard ---------- */
.kbd-case { border-radius: 12px; padding: 0; }
/* The K2's wooden flanks: two solid side panels with vertical grain, the black
   case sunk between them. */
.kbd-case[data-case="wood"] {
  padding: 5px 26px;
  border-radius: 13px;
  background:
    linear-gradient(180deg, rgba(255,255,255,.14), rgba(0,0,0,.16) 55%, rgba(0,0,0,.3)),
    repeating-linear-gradient(90deg,
      var(--wood-2) 0 2px, var(--wood-3) 2px 4px, var(--wood-1) 4px 7px,
      var(--wood-3) 7px 10px, var(--wood-2) 10px 13px),
    var(--wood-2);
  box-shadow: var(--shadow), inset 0 0 0 1px rgba(0,0,0,.28);
}
.kbd-case[data-case="dark"] {
  padding: 5px; border-radius: 13px;
  background: linear-gradient(180deg, #2a2a28, #1b1b19);
  box-shadow: var(--shadow), inset 0 0 0 1px rgba(255,255,255,.05);
}
.kbd-shell {
  background: linear-gradient(180deg, color-mix(in srgb, var(--case) 86%, #fff 5%), var(--case));
  border: 1px solid var(--case-edge); border-radius: 7px;
  padding: 12px 11px 14px;
  box-shadow: inset 0 1px 0 rgba(255,255,255,.06), 0 3px 10px rgba(0,0,0,.45);
}
.kbd { --u: 42px; --gap: 4px; display: flex; flex-direction: column; gap: var(--gap); }
.kbd-row { display: flex; gap: var(--gap); }
.kbd-row.is-spread { justify-content: space-between; }
.kbd-spacer { width: calc(var(--w) * var(--u)); flex: 0 0 auto; }
.key {
  --w: 1;
  position: relative; flex: 0 0 auto;
  width: calc(var(--w) * var(--u) + (var(--w) - 1) * var(--gap));
  height: var(--u);
  border-radius: calc(var(--u) * .16);
  background: linear-gradient(180deg, var(--cap-hi), var(--cap-lo));
  border: 1px solid var(--border);
  box-shadow: 0 2px 0 var(--cap-edge), 0 3px 5px rgba(0,0,0,.25);
  color: var(--cap-ink);
  transition: transform .08s ease, box-shadow .08s ease, background-color .25s ease, color .25s ease;
  overflow: hidden;
}
.key::before {
  content: ""; position: absolute; inset: 7% 8% 17% 8%;
  border-radius: calc(var(--u) * .1);
  background: linear-gradient(180deg, rgba(255,255,255,.11), rgba(255,255,255,0) 58%, rgba(0,0,0,.11));
  pointer-events: none;
}
.key--space::before { inset: 12% 2% 22% 2%; }

.key-cap {
  position: absolute; inset: 0; display: flex; flex-direction: column;
  align-items: flex-start; justify-content: flex-end;
  padding: calc(var(--u) * .12);
  font-size: calc(var(--u) * .27); line-height: 1.05;
}
.key--fn .key-cap, .key--nav .key-cap, .key--mod .key-cap,
.key--esc .key-cap { font-size: calc(var(--u) * .195); }
.key--space .key-cap { font-size: 0; }
.key-sub { font-size: .8em; opacity: .62; margin-bottom: auto; }
.key-label { font-family: var(--mono); }
.key--mod .key-label, .key--nav .key-label { font-family: var(--sans); letter-spacing: .01em; }
.key--mod .key-cap { font-size: calc(var(--u) * .215); }

/* Modifiers, navigation and the F-row sit a shade darker than the alphas. */
.key--mod, .key--nav, .key--fn {
  background: linear-gradient(180deg, var(--cap2-hi), var(--cap2-lo));
  box-shadow: 0 2px 0 var(--cap2-edge), 0 3px 5px rgba(0,0,0,.25);
  color: var(--cap2-ink);
}
/* The accent escape cap is a K2 trait — the K724 keeps a plain one until the
   real board says otherwise. */
[data-case="wood"] .key--esc {
  background: linear-gradient(180deg, var(--cap-accent-hi), var(--cap-accent-lo));
  color: var(--cap-accent-ink);
  box-shadow: 0 2px 0 rgba(0,0,0,.35), 0 3px 5px rgba(0,0,0,.25);
}
[data-case="dark"] .key--esc {
  background: linear-gradient(180deg, var(--cap2-hi), var(--cap2-lo));
  color: var(--cap2-ink);
  box-shadow: 0 2px 0 var(--cap2-edge), 0 3px 5px rgba(0,0,0,.25);
}
/* Alphas and numbers read centred, the way the caps are printed. */
.key--alpha .key-cap, .key--esc .key-cap { align-items: center; justify-content: center; }
.key--num .key-cap, .key--punc .key-cap { align-items: center; }
.key--nav .key-cap { align-items: center; justify-content: center; }
.key--fn .key-cap { align-items: center; justify-content: flex-end; gap: 2px; }
.key-ico {
  width: calc(var(--u) * .32); height: calc(var(--u) * .32);
  margin-bottom: auto; margin-top: calc(var(--u) * .04); opacity: .82;
}
.key--fn .key-label { font-size: .92em; opacity: .78; }
.key.is-home::after {                       /* the F/J homing bar, as on the board */
  content: ""; position: absolute; bottom: calc(var(--u) * .13); left: 50%;
  transform: translateX(-50%); width: calc(var(--u) * .3); height: 2px;
  border-radius: 2px; background: currentColor; opacity: .45;
}
.key--alpha .key-cap { text-transform: uppercase; letter-spacing: .02em; }

.key.is-next {
  border-color: var(--series-1);
  box-shadow: 0 0 0 1px var(--series-1), 0 2px 0 var(--cap-edge), 0 0 18px var(--series-1-soft);
}
.key.is-next-mod { border-color: color-mix(in srgb, var(--series-1) 55%, transparent); }
.key.is-hit { animation: strike .26s ease-out; }
.key.is-miss { animation: strikebad .26s ease-out; }
@keyframes strike {
  0%   { transform: translateY(2px) scale(.985); box-shadow: 0 0 0 2px var(--series-1), 0 0 22px var(--series-1); }
  100% { transform: none; box-shadow: 0 2px 0 var(--cap-edge), 0 3px 5px rgba(0,0,0,.25); }
}
@keyframes strikebad {
  0%   { transform: translateY(2px) scale(.985); box-shadow: 0 0 0 2px var(--critical), 0 0 22px var(--critical); }
  100% { transform: none; box-shadow: 0 2px 0 var(--cap-edge), 0 3px 5px rgba(0,0,0,.25); }
}

.kbd.is-heated .key.is-heat {
  background: var(--heat); color: var(--heat-ink); border-color: transparent;
}
.kbd.is-heated .key.is-nodata { opacity: .34; }
.kbd.is-heated .key.is-flagged { box-shadow: 0 0 0 2px var(--critical), 0 2px 0 var(--cap-edge); }
.kbd.is-heated .key { cursor: crosshair; }

.legend { display: flex; align-items: center; gap: 10px; font-size: 12px; color: var(--muted); }
.legend .ramp { width: 132px; height: 9px; border-radius: 5px; border: 1px solid var(--border); }
.legend .flag { display: inline-flex; align-items: center; gap: 6px; }
.legend .flag i { width: 11px; height: 11px; border-radius: 3px; border: 2px solid var(--critical); }

.seg { display: inline-flex; background: var(--surface-2); border: 1px solid var(--border);
       border-radius: 9px; padding: 2px; gap: 2px; }
.seg button {
  border: 0; background: transparent; padding: 4px 11px; border-radius: 7px;
  font-size: 12.5px; color: var(--text-secondary);
}
.seg button[aria-pressed="true"] { background: var(--surface-1); color: var(--text-primary);
  box-shadow: 0 1px 2px rgba(0,0,0,.22); }

/* ---------- tables (the accessible twin of every chart) ---------- */
.tbl-wrap { overflow-x: auto; }
table { width: 100%; border-collapse: collapse; font-size: 13px; }
th, td { text-align: right; padding: 7px 10px; border-bottom: 1px solid var(--grid); }
th:first-child, td:first-child { text-align: left; }
th { color: var(--muted); font-weight: 600; font-size: 11.5px; text-transform: uppercase;
     letter-spacing: .06em; white-space: nowrap; }
td { font-variant-numeric: tabular-nums; color: var(--text-secondary); }
td:first-child { color: var(--text-primary); }
tbody tr:hover td { background: var(--surface-2); }
tbody tr:last-child td { border-bottom: 0; }
th.sortable { cursor: pointer; user-select: none; }
th.sortable:hover { color: var(--text-primary); }
th[aria-sort]:not([aria-sort="none"])::after { content: " ▾"; color: var(--series-1); }
th[aria-sort="ascending"]::after { content: " ▴"; }
.pair { font-family: var(--mono); font-size: 14px; letter-spacing: .06em;
        background: var(--surface-3); padding: 2px 7px; border-radius: 5px; }
.pair .sp { color: var(--muted); }
.bar-cell { position: relative; }
.bar-cell i { position: absolute; left: 0; top: 50%; transform: translateY(-50%);
              height: 60%; background: var(--series-1-soft); border-radius: 3px; }
.bar-cell span { position: relative; }

.tagrow { display: flex; gap: 6px; flex-wrap: wrap; }
.tag { font-family: var(--mono); font-size: 12.5px; padding: 3px 9px; border-radius: 6px;
       background: var(--series-1-soft); color: var(--series-1); border: 1px solid transparent; }
.tag.warm { background: color-mix(in srgb, var(--critical) 14%, transparent); color: var(--critical); }

/* ---------- tooltip ---------- */
.tip {
  position: fixed; top: 0; left: 0; z-index: 90; pointer-events: none;
  background: var(--surface-1); border: 1px solid var(--border-strong);
  border-radius: 9px; padding: 9px 11px; box-shadow: var(--shadow);
  font-size: 12.5px; min-width: 132px; opacity: 0; transition: opacity .12s;
}
.tip.is-on { opacity: 1; }
.tip-title { font-weight: 650; margin-bottom: 5px; font-family: var(--mono); }
.tip-row { display: flex; justify-content: space-between; gap: 16px; color: var(--muted); }
.tip-row b { color: var(--text-primary); font-variant-numeric: tabular-nums; }
.tip-sub { font-size: 11.5px; color: var(--muted); margin: -3px 0 6px; }
.tip-row + .tip-row { margin-top: 2px; }
.tip-note { margin-top: 6px; padding-top: 5px; border-top: 1px solid var(--border-strong);
            font-size: 11.5px; color: var(--muted); max-width: 190px; }
.tip-sep { margin-top: 7px; padding-top: 6px; border-top: 1px solid var(--border-strong);
           font-size: 11px; letter-spacing: .04em; text-transform: uppercase; color: var(--muted); }
.tip-sep + .tip-row { margin-top: 4px; }
.tip-pair { font-family: var(--mono); color: var(--text-primary); }

/* ---------- misc ---------- */
.note { font-size: 12.5px; color: var(--muted); border-left: 2px solid var(--border-strong);
        padding-left: 11px; margin: 12px 0 0; }
.pill { display: inline-flex; align-items: center; gap: 6px; font-size: 12px;
        padding: 3px 9px; border-radius: 999px; background: var(--surface-2);
        border: 1px solid var(--border); color: var(--text-secondary); }
.pill i { width: 7px; height: 7px; border-radius: 50%; background: var(--muted); }
.pill.good i { background: var(--good); } .pill.bad i { background: var(--critical); }
.pill.warn i { background: var(--warning); }
.toast {
  position: fixed; left: 50%; bottom: 26px; transform: translate(-50%, 20px);
  background: var(--surface-1); border: 1px solid var(--border-strong); color: var(--text-primary);
  padding: 10px 16px; border-radius: 10px; box-shadow: var(--shadow); font-size: 13.5px;
  opacity: 0; pointer-events: none; transition: opacity .2s, transform .2s; z-index: 95;
}
.toast.is-on { opacity: 1; transform: translate(-50%, 0); }
.dlg {
  border: 1px solid var(--border-strong); border-radius: 14px; padding: 22px;
  background: var(--surface-1); color: var(--text-primary); width: min(440px, calc(100vw - 40px));
  box-shadow: var(--shadow);
}
.dlg::backdrop { background: rgba(0,0,0,.55); backdrop-filter: blur(3px); }
.dlg h2 { margin-bottom: 4px; }
.dlg .sub { display: block; margin-bottom: 16px; }
.dlg-field { display: block; margin-bottom: 13px; }
.dlg-field span { display: block; font-size: 12px; color: var(--muted);
                  text-transform: uppercase; letter-spacing: .06em; margin-bottom: 5px; }
.dlg-field input, .dlg-field select { width: 100%; padding: 9px 11px; }
.dlg-field input:focus { outline: 2px solid var(--series-1); outline-offset: 1px; }
.dlg-field input.is-invalid { border-color: var(--critical); }
.dlg-actions { display: flex; justify-content: flex-end; gap: 8px; margin-top: 18px; }

.chart { width: 100%; }
.result-row { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; margin-top: 14px; }
.hidden { display: none !important; }

/* ---- recording toggle ------------------------------------------------ */
/* Reads as a state, not an action: a live dot when runs are being saved, a
   hollow ring and warning tint when they are being thrown away. */
button.rec { display: inline-flex; align-items: center; gap: 7px; }
button.rec i { width: 8px; height: 8px; border-radius: 50%; background: var(--good);
               box-shadow: 0 0 0 3px color-mix(in srgb, var(--good) 22%, transparent); }
button.rec.is-off { color: var(--warning);
                    border-color: color-mix(in srgb, var(--warning) 45%, var(--border)); }
button.rec.is-off i { background: transparent; box-shadow: none;
                      border: 1.5px solid var(--warning); }

/* A run that is not being saved should be obvious while you type it, not only
   in the result row afterwards. Tinting the card avoids touching .passage,
   which is a fixed-height box a border would shift. */
body.is-casual .type-card {
  --glass-edge-a: color-mix(in srgb, var(--warning) 22%, transparent);
  --glass-edge-b: color-mix(in srgb, var(--warning) 62%, transparent);
  background: color-mix(in srgb, var(--warning) 5%, var(--glass-1));
}

/* ---- people table ---------------------------------------------------- */
#peopleTable tr.is-active td { background: color-mix(in srgb, var(--series-1) 7%, transparent); }
.row-actions { display: flex; gap: 6px; justify-content: flex-end; white-space: nowrap; }
.row-actions button { padding: 4px 10px; font-size: 12.5px; }

/* ====================================================================== */
/* atmosphere                                                             */
/* ====================================================================== */
/* Registering the angle is what lets a conic gradient animate at all — an
   unregistered custom property is a string, and strings do not interpolate.
   Where @property is unsupported the ring simply sits still, which is a fine
   place to land. */
@property --kb-angle {
  syntax: "<angle>";
  inherits: false;
  initial-value: 0deg;
}

/* The mesh is static and always on: it is what the frosted cards refract. With
   a flat page colour behind them, backdrop-filter has nothing to blur and the
   glass reads as plain grey. */
.mesh {
  position: fixed; inset: 0; z-index: -2; pointer-events: none;
  background:
    radial-gradient(58% 44% at 10% 4%,
      color-mix(in srgb, var(--series-1) 20%, transparent), transparent 70%),
    radial-gradient(48% 38% at 90% 2%,
      color-mix(in srgb, #7b5cf0 16%, transparent), transparent 72%),
    radial-gradient(72% 46% at 50% 106%,
      color-mix(in srgb, var(--series-1) 13%, transparent), transparent 72%);
}

/* The speed aura is anchored to the four edges, never the middle: it is allowed
   to tint the room, not the data. Colour comes from --aura-a/--aura-b, which
   js/fx.js interpolates from live wpm, and --aura-i is the master intensity that
   falls to 0 the moment typing stops. */
.aura {
  position: fixed; inset: 0; z-index: -1; pointer-events: none;
  opacity: var(--aura-i);
  transition: opacity .55s ease;
  background:
    radial-gradient(38% 58% at -8% 50%,  rgb(var(--aura-a) / .58), transparent 72%),
    radial-gradient(38% 58% at 108% 50%, rgb(var(--aura-a) / .58), transparent 72%),
    radial-gradient(80% 30% at 50% -6%,  rgb(var(--aura-b) / .52), transparent 74%),
    radial-gradient(92% 34% at 50% 106%, rgb(var(--aura-b) / .52), transparent 74%);
}
/* 110 wpm and over: the edges breathe. */
.aura.is-blaze { animation: aura-pulse 2.4s ease-in-out infinite; }
@keyframes aura-pulse {
  0%, 100% { opacity: var(--aura-i); }
  50%      { opacity: calc(var(--aura-i) * .58); }
}

/* Border-beam: a neon highlight that sweeps the active card. Only the card you
   are typing into gets one, and only while a run is actually moving — a beam on
   every card at once is wallpaper, not a signal. The hue is the aura's, so the
   sweep and the room agree about how fast you are going. */
body.is-running .type-card::before {
  background:
    conic-gradient(from var(--kb-angle),
      transparent 0 68%,
      rgb(var(--aura-a) / .06) 72%,
      rgb(var(--aura-a) / .80) 76.5%,
      rgb(var(--aura-a) / .06) 81%,
      transparent 85%),
    conic-gradient(from var(--kb-angle),
      var(--glass-edge-a), var(--glass-edge-b) 18%, var(--glass-edge-a) 38%,
      var(--glass-edge-a) 62%, var(--glass-edge-b) 78%, var(--glass-edge-a));
  animation: kb-beam 9s linear infinite;
}
@keyframes kb-beam { to { --kb-angle: 360deg; } }

/* ---- the board, given depth ---- */
/* Perspective on the live board only. The Analysis heatmap is a chart: tilting
   it would foreshorten the far rows and quietly make two equal cells look
   unequal, which is the one thing a heat layer must never do. */
.board-card .kbd-case {
  transform: perspective(800px) rotateX(4deg);
  transform-origin: 50% 92%;
  transition: transform .45s cubic-bezier(.2,.7,.3,1);
}
body.is-running .board-card .kbd-case {
  transform: perspective(800px) rotateX(7.5deg) translateY(-2px) scale(1.006);
}
.kbd { position: relative; }

/* Underglow: a bloom under the legend, clipped by the cap's own overflow so it
   looks like light coming out from beneath the keycap. js/fx.js animates it. */
.key-glow {
  position: absolute; left: 50%; top: 62%;
  width: 165%; aspect-ratio: 1; border-radius: 50%;
  transform: translate(-50%, -50%) scale(.55);
  opacity: 0; pointer-events: none; z-index: 0;
  background: radial-gradient(circle,
    rgb(var(--aura-a) / .95), rgb(var(--aura-a) / .35) 42%, transparent 68%);
}
.key-glow.is-bad {
  background: radial-gradient(circle,
    color-mix(in srgb, var(--critical) 92%, transparent),
    color-mix(in srgb, var(--critical) 32%, transparent) 42%, transparent 68%);
}
.key-cap { z-index: 1; }

/* Strike sparks live above the caps in their own layer, because .key clips its
   own overflow to keep the cap gloss inside the cap. */
.kbd-sparks { position: absolute; inset: 0; pointer-events: none; z-index: 3; }
.kb-spark {
  position: absolute; width: 4px; height: 4px; border-radius: 50%;
  transform: translate(-50%, -50%); opacity: 0;
  background: rgb(var(--aura-a));
  box-shadow: 0 0 7px rgb(var(--aura-a) / .85);
}
.kb-spark.is-bad {
  background: var(--critical);
  box-shadow: 0 0 7px color-mix(in srgb, var(--critical) 75%, transparent);
}

/* ---- speed-reactive typography ---- */
.stat .v.is-fast { color: rgb(var(--aura-a)); text-shadow: 0 0 14px rgb(var(--aura-a) / .55); }
.stat .v.is-ultra { color: rgb(var(--aura-a)); text-shadow: 0 0 20px rgb(var(--aura-a) / .85); font-weight: 700; }
.stat .v.is-hyper {
  color: #ff9a2e;
  text-shadow: 0 0 24px rgba(255, 154, 46, 0.9), 0 0 40px rgba(255, 92, 38, 0.6);
  animation: kb-hyper 0.7s infinite alternate;
}
@keyframes kb-hyper {
  from { transform: scale(1); filter: brightness(1); }
  to { transform: scale(1.03); filter: brightness(1.25); }
}

/* ---- live combo HUD badge ---- */
.combo-hud {
  position: absolute; right: 18px; top: 16px;
  display: flex; align-items: baseline; gap: 6px;
  padding: 4px 14px; border-radius: 999px;
  background: color-mix(in srgb, var(--surface-2) 80%, transparent);
  border: 1px solid var(--border);
  box-shadow: var(--shadow);
  opacity: 0; transform: translateY(6px) scale(0.92);
  transition: opacity .2s, transform .2s cubic-bezier(.16,1,.3,1), border-color .2s, background .2s;
  pointer-events: none; z-index: 5;
}
.combo-hud.is-on { opacity: 1; transform: translateY(0) scale(1); }
.combo-hud .combo-val { font-family: var(--mono); font-size: 19px; font-weight: 700; color: rgb(var(--aura-a)); }
.combo-hud .combo-lbl { font-size: 10px; font-weight: 700; letter-spacing: .09em; color: var(--muted); text-transform: uppercase; }
.combo-hud.is-fire {
  background: rgba(255,154,46,0.14); border-color: rgba(255,154,46,0.5);
  box-shadow: 0 0 16px rgba(255,154,46,0.3);
}
.combo-hud.is-fire .combo-val { color: #ff9a2e; }
.combo-hud.is-blaze {
  background: rgba(255,92,38,0.22); border-color: rgba(255,92,38,0.85);
  box-shadow: 0 0 24px rgba(255,92,38,0.55);
}
.combo-hud.is-blaze .combo-val { color: #ff5c26; }

/* The streak belongs to run status, not to the passage. Keeping a reserved
   counter slot below the text prevents it from covering words or shifting the
   layout when it appears. */
.run-meta .combo-hud {
  position: static; right: auto; top: auto; flex: 0 0 82px; min-width: 82px;
  justify-content: center; padding: 3px 10px; visibility: hidden;
  transform: translateY(3px) scale(.96); box-shadow: none;
}
.run-meta .combo-hud.is-on { visibility: visible; transform: none; }

/* ---- sound & fx toggles ---- */
.sound-toggle[aria-pressed="true"] { color: var(--text-primary); }
.sound-toggle[aria-pressed="false"] { color: var(--muted); opacity: 0.6; }

/* ---- gamified pilot cards (3D holographic) ---- */
.pilot-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
  gap: 16px; margin-top: 14px;
}
.pilot-card {
  position: relative; padding: 18px; border-radius: var(--r);
  background: color-mix(in srgb, var(--surface-1) 85%, transparent);
  border: 1px solid var(--border); box-shadow: var(--shadow);
  transition: transform .22s cubic-bezier(.2,.7,.3,1), border-color .2s, box-shadow .2s;
  transform-style: preserve-3d; overflow: hidden;
}
.pilot-card:hover { border-color: var(--border-strong); }
.pilot-card.is-active {
  border-color: rgb(var(--aura-a) / .6);
  box-shadow: 0 0 20px rgb(var(--aura-a) / .22), var(--shadow);
}
.pilot-glare {
  position: absolute; inset: 0; pointer-events: none; opacity: 0;
  transition: opacity .25s; mix-blend-mode: overlay; z-index: 2;
}
.pilot-card-top { display: flex; align-items: center; gap: 12px; }
.pilot-avatar {
  width: 44px; height: 44px; border-radius: 12px;
  background: color-mix(in srgb, var(--series-1) 18%, var(--surface-2));
  border: 1px solid var(--border-strong);
  display: flex; align-items: center; justify-content: center;
  font-weight: 700; font-size: 18px; color: var(--series-1);
  position: relative; flex-shrink: 0;
}
.active-badge {
  position: absolute; top: -6px; right: -6px; font-style: normal;
  font-size: 11px; width: 18px; height: 18px; border-radius: 50%;
  background: var(--good); color: #fff; display: grid; place-items: center;
  box-shadow: 0 0 8px rgba(12,163,12,0.8);
}
.pilot-id-info { flex: 1; min-width: 0; }
.pilot-name { font-size: 16px; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
.pilot-archetype { font-size: 12px; color: var(--text-secondary); }
.pilot-level-tag {
  font-size: 11px; font-family: var(--mono); padding: 3px 8px; border-radius: 6px;
  background: var(--surface-3); border: 1px solid var(--border); color: var(--text-secondary);
}
.pilot-level-tag b { color: var(--text-primary); }

.xp-bar-wrap { margin: 12px 0 14px; }
.xp-bar-labels {
  display: flex; justify-content: space-between; font-size: 10px;
  color: var(--muted); margin-bottom: 4px; font-family: var(--mono);
}
.xp-track { height: 5px; border-radius: 3px; background: var(--surface-3); overflow: hidden; }
.xp-fill {
  height: 100%; border-radius: 3px;
  background: linear-gradient(90deg, var(--series-1), rgb(var(--aura-a)));
  transition: width .4s ease;
}

.pilot-stats-mini {
  display: grid; grid-template-columns: repeat(4, 1fr); gap: 6px;
  padding: 8px 0; border-top: 1px solid var(--border); border-bottom: 1px solid var(--border);
  margin-bottom: 12px;
}
.p-stat { display: flex; flex-direction: column; align-items: center; }
.p-stat .pk { font-size: 9.5px; text-transform: uppercase; color: var(--muted); }
.p-stat .pv { font-size: 13px; font-weight: 600; font-family: var(--mono); }
.p-stat .pv small { font-size: 9px; color: var(--muted); margin-left: 2px; }
.pilot-actions { display: flex; gap: 8px; align-items: center; }
.pilot-actions .small { padding: 4px 10px; font-size: 12px; }

/* ---- podium leaderboard ---- */
.podium-card { margin-top: 16px; }
.podium-wrap {
  display: flex; justify-content: center; align-items: flex-end; gap: 18px;
  min-height: 230px; padding: 24px 12px 12px;
}
.podium-col {
  display: flex; flex-direction: column; align-items: center;
  flex: 1; max-width: 220px; text-align: center;
}
.podium-pilot { margin-bottom: 12px; display: flex; flex-direction: column; align-items: center; }
.podium-badge { font-size: 30px; margin-bottom: 4px; }
.place-1 .podium-badge { filter: drop-shadow(0 0 12px rgba(255,215,0,0.65)); }
.place-2 .podium-badge { filter: drop-shadow(0 0 10px rgba(192,192,192,0.55)); }
.place-3 .podium-badge { filter: drop-shadow(0 0 10px rgba(205,127,50,0.55)); }
.podium-name { font-weight: 600; font-size: 15px; }
.podium-wpm { font-size: 21px; font-weight: 700; font-family: var(--mono); color: var(--series-1); }
.podium-wpm small { font-size: 12px; color: var(--muted); }
.podium-sub { font-size: 11px; color: var(--muted); }
.podium-step {
  width: 100%; border-radius: 8px 8px 0 0; background: var(--surface-2);
  border: 1px solid var(--border); border-bottom: none;
  display: flex; justify-content: center; align-items: center;
  font-weight: 700; font-size: 13px; letter-spacing: .08em;
  color: var(--text-secondary); box-shadow: var(--shadow);
}
.place-1 .podium-step {
  height: 115px;
  background: linear-gradient(180deg, rgba(255, 215, 0, 0.16), var(--surface-2));
  border-color: rgba(255, 215, 0, 0.45); color: #ffd700;
}
.place-2 .podium-step {
  height: 80px;
  background: linear-gradient(180deg, rgba(192, 192, 192, 0.14), var(--surface-2));
  border-color: rgba(192, 192, 192, 0.38); color: #c0c0c0;
}
.place-3 .podium-step {
  height: 55px;
  background: linear-gradient(180deg, rgba(205, 127, 50, 0.14), var(--surface-2));
  border-color: rgba(205, 127, 50, 0.38); color: #cd7f32;
}

/* ---- radar & 1v1 duel breakdown ---- */
.radar-legend {
  display: grid; grid-template-columns: repeat(2, 1fr); gap: 10px;
  margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--border);
}
.radar-legend-item { display: flex; flex-direction: column; }
.radar-legend-item span { font-size: 10.5px; text-transform: uppercase; color: var(--muted); }
.radar-legend-item b { font-size: 13px; color: var(--text-primary); }

.duel-breakdown { margin-top: 12px; }
.duel-meters { display: flex; flex-direction: column; gap: 8px; }
.duel-row {
  display: flex; justify-content: space-between; align-items: center;
  padding: 6px 12px; border-radius: 6px; background: var(--surface-2);
  border: 1px solid var(--border); font-family: var(--mono); font-size: 13px;
}
.duel-row .d-pilot-a { color: var(--series-1); font-weight: 600; width: 35%; text-align: left; }
.duel-row .d-metric { color: var(--text-secondary); font-size: 11px; font-family: var(--sans); text-transform: uppercase; width: 30%; text-align: center; }
.duel-row .d-pilot-b { color: #e66767; font-weight: 600; width: 35%; text-align: right; }

/* ---- achievement badge cards ---- */
.badge-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: 12px; margin-top: 14px;
}
.badge-card {
  display: flex; align-items: flex-start; gap: 12px; padding: 12px 14px;
  border-radius: 8px; background: var(--surface-2); border: 1px solid var(--border);
  transition: transform .2s, border-color .2s;
}
.badge-card.is-unlocked {
  border-color: rgba(57, 135, 229, 0.4);
  background: color-mix(in srgb, var(--surface-2) 90%, var(--series-1));
}
.badge-card.is-locked { opacity: 0.55; }
.badge-icon { font-size: 24px; line-height: 1; flex-shrink: 0; }
.badge-title { font-size: 13px; font-weight: 600; }
.badge-desc { font-size: 11.5px; color: var(--muted); margin: 2px 0 4px; line-height: 1.35; }
.badge-status { font-size: 11px; font-family: var(--mono); }
.badge-status .status-ok { color: var(--good); font-weight: 600; }
.badge-status .status-lock { color: var(--muted); }

/* ---- the escape hatch ---- */
/* Everything above, off. Same layout, same colours for the data, no blur, no
   motion, nothing compositing behind the passage — for a session where you care
   about the number and not the room. */
body.fx-off .mesh, body.fx-off .aura,
body.fx-off .key-glow, body.fx-off .kbd-sparks { display: none; }
body.fx-off .card {
  background: var(--surface-1);
  backdrop-filter: none; -webkit-backdrop-filter: none;
}
body.fx-off .stat {
  background: var(--surface-1);
  backdrop-filter: none; -webkit-backdrop-filter: none;
}
body.fx-off .card::before,
body.fx-off.is-running .type-card::before {
  background: var(--border); animation: none;
}
body.fx-off .board-card .kbd-case,
body.fx-off.is-running .board-card .kbd-case { transform: none; }
.fx-toggle[aria-pressed="false"] { color: var(--muted); }

@media (prefers-reduced-motion: reduce) {
  * { animation-duration: .01ms !important; transition-duration: .01ms !important; }
  /* Crushing the duration of an *infinite* animation makes it strobe rather than
     stop, so the looping atmospherics are switched off by name. */
  .aura.is-blaze, body.is-running .type-card::before {
    animation-name: none !important;
  }
  .board-card .kbd-case, body.is-running .board-card .kbd-case {
    transform: perspective(800px) rotateX(4deg);
  }
  button.primary::after { display: none; }
}

/* ====================================================================== */
/* 2026 product shell — precision instrument                              */
/* ====================================================================== */
.wrap { max-width: 1240px; padding-top: 8px; }
.topbar { background: color-mix(in srgb, var(--bg) 92%, transparent); }
.topbar-in { max-width: 1240px; min-height: 68px; padding-block: 10px; flex-wrap: nowrap; }
.brand { min-width: 230px; gap: 9px; }
.brand b { font-weight: 720; }
.brand-divider { width: 1px; height: 15px; background: var(--border-strong); }
.tabs { margin-inline: auto; }
.mode-toggle { display: inline-flex; align-items: center; gap: 7px; white-space: nowrap; }
.mode-toggle[aria-pressed="true"] { color: var(--series-1); border-color: color-mix(in srgb, var(--series-1) 45%, var(--border)); }

.utility-menu { position: relative; }
.utility-menu summary {
  list-style: none; display: flex; align-items: center; gap: 8px; min-width: 112px;
  padding: 5px 8px 5px 5px; border: 1px solid var(--border); border-radius: 999px;
  background: var(--surface-2); color: var(--text-primary); cursor: pointer; font-size: 13px;
}
.utility-menu summary::-webkit-details-marker { display: none; }
.profile-mark {
  display: grid; place-items: center; width: 28px; height: 28px; border-radius: 50%;
  color: #fff; background: linear-gradient(145deg, var(--series-1), #7459dc); font-weight: 700;
  box-shadow: inset 0 1px 0 rgba(255,255,255,.24);
}
.workspace-copy { display: grid; line-height: 1.05; }
.workspace-copy small { color: var(--muted); font-size: 8.5px; letter-spacing: .08em; text-transform: uppercase; }
.workspace-copy > span { margin-top: 3px; }
.menu-chev { color: var(--muted); margin-left: auto; }
.utility-menu[open] .menu-chev { transform: rotate(180deg); }
.utility-popover {
  position: absolute; top: calc(100% + 10px); right: 0; width: 310px; padding: 14px;
  border: 1px solid var(--border-strong); border-radius: 14px; background: var(--surface-1);
  box-shadow: 0 24px 70px rgba(0,0,0,.38); z-index: 60;
}
.utility-label {
  margin: 2px 3px 8px; color: var(--muted); font-size: 10.5px; font-weight: 700;
  letter-spacing: .1em; text-transform: uppercase;
}
.menu-field { display: grid; grid-template-columns: 92px 1fr; align-items: center; gap: 10px; margin-bottom: 8px; font-size: 12px; color: var(--text-secondary); }
.menu-field select { width: 100%; }
.menu-links { display: grid; gap: 4px; padding: 7px 0 12px; margin-bottom: 12px; border-bottom: 1px solid var(--border); }
.menu-links button { display: flex; justify-content: space-between; width: 100%; text-align: left; }
.menu-actions { display: grid; grid-template-columns: repeat(3, 1fr); gap: 6px; }
.menu-actions button { display: grid; justify-items: center; gap: 2px; padding: 8px 5px; font-size: 16px; }
.menu-actions button span { font-size: 10px; color: var(--muted); }

.type-stats {
  display: grid; grid-template-columns: repeat(4, 1fr); gap: 0; margin: 8px 0 18px;
  padding: 7px 0; border-block: 1px solid var(--border); background: transparent;
}
.type-stats .stat {
  border: 0; border-right: 1px solid var(--border); border-radius: 0; padding: 9px 18px;
  background: transparent; box-shadow: none; backdrop-filter: none;
}
.type-stats .stat:last-child { border-right: 0; }
.type-stats .stat .v { font-size: 27px; }
.type-stats .stat .k { letter-spacing: .11em; }

.calibration {
  display: grid; grid-template-columns: 1fr auto auto; align-items: center; gap: 24px;
  margin-bottom: 16px; padding: 14px 16px; border: 1px solid color-mix(in srgb, var(--series-1) 30%, var(--border));
  border-radius: 12px; background: linear-gradient(100deg, var(--series-1-soft), transparent 48%), var(--surface-1);
}
.calibration-copy { display: grid; grid-template-columns: auto 1fr; column-gap: 10px; align-items: baseline; }
.calibration-copy strong { font-size: 14px; }
.calibration-copy > span:last-child { grid-column: 1 / -1; color: var(--text-secondary); font-size: 12.5px; margin-top: 2px; }
.eyebrow { color: var(--series-1); font-size: 10px; font-weight: 750; letter-spacing: .12em; text-transform: uppercase; }
.calibration-progress { display: flex; align-items: center; gap: 10px; color: var(--muted); font: 11px var(--mono); }
.calibration-dots { display: flex; gap: 5px; }
.calibration-dots i { width: 24px; height: 4px; border-radius: 2px; background: var(--surface-3); }
.calibration-dots i.is-done { background: var(--series-1); }

.type-card { padding: 26px 28px 22px; border-radius: 16px; }
.type-card .card-head { margin-bottom: 12px; }
.run-heading { display: flex; align-items: baseline; gap: 10px; }
.run-heading .eyebrow { writing-mode: initial; }
.passage { font-size: 33px; line-height: 1.62; height: 4.86em; letter-spacing: -.005em; padding-top: 10px; }
.run-meta { justify-content: space-between; }
.run-meta .progress { order: 0; }
.key-help { white-space: nowrap; }
body.is-running .type-stats { opacity: .2; }
body.is-running .topbar { opacity: .3; }

.result-row {
  display: grid; grid-template-columns: auto 1fr auto; gap: 18px 28px; align-items: center;
  margin: 20px -4px -2px; padding: 20px; border: 1px solid var(--border-strong); border-radius: 12px;
  background: color-mix(in srgb, var(--surface-2) 74%, transparent); animation: result-in .48s cubic-bezier(.16,1,.3,1);
}
@keyframes result-in { from { opacity: 0; transform: translateY(10px) scale(.985); } }
.result-kicker { grid-column: 1 / -1; color: var(--good); font-size: 10.5px; font-weight: 750; letter-spacing: .12em; text-transform: uppercase; }
.result-metrics { display: flex; gap: 24px; }
.result-metrics div { display: grid; }
.result-metrics strong { font-size: 27px; line-height: 1; letter-spacing: -.04em; }
.result-metrics strong small { font-size: 13px; color: var(--muted); }
.result-metrics span, .result-advice > span { margin-top: 5px; color: var(--muted); font-size: 9.5px; letter-spacing: .08em; text-transform: uppercase; }
.result-advice { padding-left: 20px; border-left: 1px solid var(--border); }
.result-advice p { margin: 3px 0 0; color: var(--text-secondary); font-size: 13px; }
.result-advice b { color: var(--text-primary); font-family: var(--mono); }
.result-actions { display: flex; gap: 8px; }

.card { box-shadow: 0 1px 1px rgba(0,0,0,.2), 0 18px 50px rgba(0,0,0,.16); }
.board-card { margin-top: 14px; box-shadow: none; background: color-mix(in srgb, var(--glass-1) 62%, transparent); }
.pilot-glare { display: none; }
.pilot-card:hover { transform: translateY(-2px) !important; }

/* ====================================================================== */
/* Typewriter mode — paper, ink, mechanical restraint                     */
/* ====================================================================== */
:root[data-mode="typewriter"] {
  color-scheme: light;
  --bg: #d7cdb7;
  --surface-1: #eee5d1;
  --surface-2: #e3d8c1;
  --surface-3: #d2c4aa;
  --text-primary: #241f19;
  --text-secondary: #51483b;
  --muted: #776b59;
  --grid: rgba(51,42,31,.16);
  --baseline: #9f927c;
  --border: rgba(50,39,27,.18);
  --border-strong: rgba(50,39,27,.34);
  --series-1: #8d3929;
  --series-1-soft: rgba(141,57,41,.11);
  --good: #42613d;
  --warning: #a56a1d;
  --critical: #9c2f26;
  --glass-1: rgba(239,230,210,.96);
  --glass-2: rgba(228,216,193,.76);
  --shadow: 0 2px 0 rgba(58,45,30,.12), 0 12px 28px rgba(58,45,30,.10);
  --mono: "Courier New", Courier, monospace;
  --sans: "Courier New", Courier, monospace;
}
:root[data-mode="typewriter"] html { background: var(--bg); }
:root[data-mode="typewriter"] body {
  background:
    linear-gradient(rgba(255,255,255,.12), rgba(255,255,255,.12)),
    repeating-linear-gradient(0deg, rgba(72,55,35,.018) 0, rgba(72,55,35,.018) 1px, transparent 1px, transparent 4px);
}
:root[data-mode="typewriter"] .aura,
:root[data-mode="typewriter"] .key-glow,
:root[data-mode="typewriter"] .kbd-sparks { display: none !important; }
:root[data-mode="typewriter"] .topbar {
  background: rgba(224,214,192,.96); border-bottom: 2px solid var(--text-primary); backdrop-filter: none;
}
:root[data-mode="typewriter"] .brand .dot { width: 8px; height: 8px; border-radius: 0; transform: rotate(45deg); background: var(--series-1); box-shadow: none; }
:root[data-mode="typewriter"] .brand b { text-transform: uppercase; letter-spacing: .09em; }
:root[data-mode="typewriter"] .tabs { padding: 0; gap: 15px; border: 0; border-radius: 0; background: transparent; }
:root[data-mode="typewriter"] .tab { padding: 7px 2px 5px; border-bottom: 2px solid transparent; border-radius: 0; text-transform: uppercase; letter-spacing: .06em; }
:root[data-mode="typewriter"] .tab[aria-selected="true"] { background: transparent; border-color: var(--series-1); color: var(--series-1); box-shadow: none; }
:root[data-mode="typewriter"] button,
:root[data-mode="typewriter"] select,
:root[data-mode="typewriter"] input { border-radius: 2px; box-shadow: 1px 2px 0 rgba(44,34,23,.14); }
:root[data-mode="typewriter"] button.primary { background: var(--series-1); }
:root[data-mode="typewriter"] button.primary::after { display: block; }
:root[data-mode="typewriter"] .profile-mark { border-radius: 2px; background: var(--text-primary); box-shadow: none; }
:root[data-mode="typewriter"] .utility-menu summary { border-radius: 2px; }
:root[data-mode="typewriter"] .utility-popover { border-radius: 2px; box-shadow: 6px 8px 0 rgba(55,43,29,.15); }
:root[data-mode="typewriter"] .card,
:root[data-mode="typewriter"] .stat {
  background: var(--glass-1); border: 1px solid var(--border-strong); border-radius: 2px;
  box-shadow: var(--shadow); backdrop-filter: none; -webkit-backdrop-filter: none;
}
:root[data-mode="typewriter"] .card::before { display: none; }
:root[data-mode="typewriter"] .type-stats { border-block: 1px solid var(--border-strong); background: rgba(239,230,210,.4); box-shadow: none; }
:root[data-mode="typewriter"] .type-stats .stat { border: 0; border-right: 1px dashed var(--border-strong); box-shadow: none; background: transparent; }
:root[data-mode="typewriter"] .type-stats .stat:last-child { border-right: 0; }
:root[data-mode="typewriter"] .calibration { border-radius: 2px; border-style: dashed; background: rgba(239,230,210,.7); }
:root[data-mode="typewriter"] .calibration-dots i { border-radius: 0; }
:root[data-mode="typewriter"] .type-card {
  position: relative; padding: 30px 36px 24px; border-width: 1px 1px 3px;
  background:
    linear-gradient(90deg, transparent 0 27px, rgba(141,57,41,.14) 27px 28px, transparent 28px),
    var(--surface-1);
}
:root[data-mode="typewriter"] .type-card::after {
  content: "KEYBLAB / PERSONAL TYPING RECORD"; position: absolute; right: 34px; bottom: -27px;
  color: rgba(91,51,37,.28); font-size: 9px; letter-spacing: .14em; transform: rotate(-1deg);
}
:root[data-mode="typewriter"] .passage { font-size: 32px; font-weight: 600; letter-spacing: .015em; }
:root[data-mode="typewriter"] .c { color: #8a7e69; }
:root[data-mode="typewriter"] .c.is-correct { color: var(--text-primary); text-shadow: .35px .2px 0 rgba(36,31,25,.35); }
:root[data-mode="typewriter"] .c.is-wrong { color: var(--critical); background: transparent; text-decoration: underline 2px wavy; }
:root[data-mode="typewriter"] .caret { width: 9px; height: 3px !important; margin-top: 1.34em; background: var(--text-primary); border-radius: 0; box-shadow: none; }
:root[data-mode="typewriter"] .progress { height: 2px; border-radius: 0; background: var(--surface-3); }
:root[data-mode="typewriter"] .progress i { background: var(--series-1); }
:root[data-mode="typewriter"] kbd { border-radius: 1px; background: transparent; border-color: var(--border-strong); box-shadow: 1px 1px 0 var(--border-strong); }
:root[data-mode="typewriter"] .board-card { background: rgba(239,230,210,.6); }
:root[data-mode="typewriter"] .board-card .kbd-case,
:root[data-mode="typewriter"] body.is-running .board-card .kbd-case { transform: none; }
:root[data-mode="typewriter"] .result-row { border-radius: 0; border-style: double; border-width: 3px; background: rgba(227,216,193,.65); }
:root[data-mode="typewriter"] .result-kicker { color: var(--series-1); }
:root[data-mode="typewriter"] .pill,
:root[data-mode="typewriter"] .tag,
:root[data-mode="typewriter"] .seg { border-radius: 2px; }
:root[data-mode="typewriter"] .pilot-card:hover { transform: none !important; }

@media (max-width: 980px) {
  .brand { min-width: auto; }
  .brand #brandBoard, .brand-divider { display: none; }
  .mode-toggle { font-size: 0; }
  .mode-toggle span { font-size: 15px; }
  .result-row { grid-template-columns: 1fr; }
  .result-advice { border-left: 0; border-top: 1px solid var(--border); padding: 13px 0 0; }
}
@media (max-width: 720px) {
  .topbar-in { flex-wrap: wrap; }
  .tabs { order: 3; width: 100%; justify-content: center; }
  .utility-menu { margin-left: auto; }
  .type-stats { grid-template-columns: repeat(2, 1fr); }
  .type-stats .stat:nth-child(2) { border-right: 0; }
  .type-stats .stat:nth-child(-n+2) { border-bottom: 1px solid var(--border); }
  .calibration { grid-template-columns: 1fr; gap: 12px; }
  .passage { font-size: 25px; }
  .type-card { padding: 20px; }
  .result-actions { flex-wrap: wrap; }
}

/* ---- Typewriter immersion pass -------------------------------------- */
.typewriter-platen { display: none; }

:root[data-mode="typewriter"] body {
  min-height: 100vh;
  background:
    linear-gradient(90deg, rgba(255,255,255,.025), transparent 15%, rgba(0,0,0,.06) 48%, transparent 76%),
    repeating-linear-gradient(92deg, #3a271a 0 3px, #412c1d 3px 7px, #352318 7px 10px, #462f1f 10px 16px);
  background-attachment: fixed;
}
:root[data-mode="typewriter"] .wrap { max-width: 1120px; padding-top: 18px; }
:root[data-mode="typewriter"] .topbar {
  color: #eee3cd; background:
    linear-gradient(180deg, rgba(255,255,255,.055), transparent 38%), #24211d;
  border-bottom: 1px solid #070605;
  box-shadow: inset 0 -1px 0 rgba(255,255,255,.07), 0 5px 18px rgba(0,0,0,.28);
}
:root[data-mode="typewriter"] .topbar-in { min-height: 72px; }
:root[data-mode="typewriter"] .brand b { color: #f1e6d0; text-shadow: 0 1px 0 #000; }
:root[data-mode="typewriter"] .brand span { color: #aa9e89; }
:root[data-mode="typewriter"] .brand .dot { background: #b64a34; box-shadow: 0 0 0 1px #090807, 0 0 0 3px #665746; }
:root[data-mode="typewriter"] .brand-divider { background: rgba(238,227,205,.18); }
:root[data-mode="typewriter"] .tabs { gap: 7px; }
:root[data-mode="typewriter"] .tab {
  min-width: 92px; padding: 8px 12px; color: #c6baa4; border: 1px solid #090807;
  border-bottom-width: 3px; background: linear-gradient(#39352f, #282521); box-shadow: inset 0 1px 0 rgba(255,255,255,.09), 0 2px 0 #090807;
}
:root[data-mode="typewriter"] .tab:hover { color: #fff7e8; background: linear-gradient(#464038, #302c27); }
:root[data-mode="typewriter"] .tab[aria-selected="true"] {
  color: #fff6e3; border-color: #0c0a08; border-bottom-color: #a64231;
  background: linear-gradient(#4a443c, #302c27); transform: translateY(1px); box-shadow: inset 0 1px 0 rgba(255,255,255,.12), 0 1px 0 #080706;
}
:root[data-mode="typewriter"] .topbar .mode-toggle,
:root[data-mode="typewriter"] .topbar .utility-menu summary {
  color: #eee3cd; border-color: #080706; background: linear-gradient(#3c3832, #282521); box-shadow: inset 0 1px 0 rgba(255,255,255,.09), 0 2px 0 #080706;
}
:root[data-mode="typewriter"] .topbar .mode-toggle { color: #d77a62; }
:root[data-mode="typewriter"] .workspace-copy small,
:root[data-mode="typewriter"] .menu-chev { color: #9b907e; }
:root[data-mode="typewriter"] .profile-mark { color: #221e19; background: #e4d8bf; border: 1px solid #090807; }

:root[data-mode="typewriter"] .type-stats {
  position: relative; margin: 4px 10px 18px; color: #eee3cd; border: 1px solid #0a0907;
  background: linear-gradient(180deg, #302c27, #201e1a); box-shadow: inset 0 1px 0 rgba(255,255,255,.07), 0 5px 14px rgba(0,0,0,.25);
}
:root[data-mode="typewriter"] .type-stats::before {
  content: "MECHANICAL PERFORMANCE COUNTER"; position: absolute; left: 16px; top: -7px;
  padding: 0 6px; color: #8e816e; background: #292621; font-size: 8px; letter-spacing: .12em;
}
:root[data-mode="typewriter"] .type-stats .stat { border-right-color: rgba(238,227,205,.15); }
:root[data-mode="typewriter"] .type-stats .stat .k,
:root[data-mode="typewriter"] .type-stats .stat .d,
:root[data-mode="typewriter"] .type-stats .stat .v small { color: #9f947f; }
:root[data-mode="typewriter"] .type-stats .stat .v { color: #f4ead6; text-shadow: 0 1px 0 #000; }

:root[data-mode="typewriter"] .calibration {
  position: relative;
  margin-inline: 10px; border: 1px solid rgba(53,41,28,.5); background:
    linear-gradient(96deg, rgba(141,57,41,.08), transparent 46%), #e8dec8;
  box-shadow: 2px 3px 0 rgba(15,11,7,.16); transform: rotate(-.12deg);
}
:root[data-mode="typewriter"] .calibration::before {
  content: "FILE NOTE"; position: absolute; left: 14px; top: -7px; padding: 0 5px;
  color: var(--series-1); background: #e8dec8; font-size: 9px; letter-spacing: .12em;
}

:root[data-mode="typewriter"] .typewriter-platen {
  position: relative; z-index: 3; display: grid; grid-template-columns: 42px 1fr 42px;
  align-items: center; width: calc(100% - 12px); height: 42px; margin: 30px auto -17px;
}
:root[data-mode="typewriter"] .platen-knob {
  width: 42px; height: 24px; border: 1px solid #050403; border-radius: 5px;
  background: repeating-linear-gradient(90deg, #171512 0 3px, #2b2823 3px 5px);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.1), 0 3px 5px rgba(0,0,0,.4);
}
:root[data-mode="typewriter"] .platen-rail {
  position: relative; height: 30px; display: flex; align-items: center; justify-content: center;
  border: 1px solid #030302; border-radius: 8px; background:
    linear-gradient(180deg, #555049 0, #1c1a17 24%, #0d0c0a 68%, #302d28 100%);
  box-shadow: inset 0 2px 1px rgba(255,255,255,.18), 0 5px 10px rgba(0,0,0,.38);
}
:root[data-mode="typewriter"] .platen-rail::before,
:root[data-mode="typewriter"] .platen-rail::after {
  content: ""; position: absolute; top: -10px; width: 3px; height: 21px; background: #a9a195; border: 1px solid #3c3832;
}
:root[data-mode="typewriter"] .platen-rail::before { left: 13%; }
:root[data-mode="typewriter"] .platen-rail::after { right: 13%; }
:root[data-mode="typewriter"] .platen-rail b {
  position: relative; z-index: 1; padding: 2px 12px; color: #b9ad96; background: #201e1a;
  border: 1px solid #090807; font-size: 8px; font-weight: 400; letter-spacing: .17em;
}
:root[data-mode="typewriter"] .platen-rail span {
  position: absolute; top: 5px; width: 34%; height: 3px; background: #a33d2c; opacity: .72;
}
:root[data-mode="typewriter"] .platen-rail span:first-child { left: 3%; }
:root[data-mode="typewriter"] .platen-rail span:last-child { right: 3%; }

:root[data-mode="typewriter"] .type-card {
  z-index: 2; width: calc(100% - 58px); min-height: 365px; margin: 0 auto; padding: 42px 50px 28px;
  border: 0; border-top: 1px solid rgba(255,255,255,.55); border-bottom: 2px solid rgba(52,40,27,.34);
  background:
    linear-gradient(90deg, transparent 0 37px, rgba(164,56,43,.2) 37px 38px, transparent 38px),
    radial-gradient(circle at 14% 22%, rgba(94,71,43,.035) 0 1px, transparent 1.5px),
    radial-gradient(circle at 78% 62%, rgba(94,71,43,.03) 0 1px, transparent 1.5px),
    #f1e8d4;
  background-size: auto, 13px 17px, 19px 23px, auto;
  box-shadow: 0 2px 0 #b5aa94, 0 10px 0 #27231f, 0 18px 24px rgba(0,0,0,.34);
  transform-origin: 50% 0;
}
:root[data-mode="typewriter"] .type-card::after {
  content: "KEYBLAB / SHEET 01 / PERSONAL TYPING RECORD"; right: 48px; bottom: 11px;
  color: rgba(91,51,37,.25); font-size: 8px; letter-spacing: .14em; transform: rotate(-.5deg);
}
:root[data-mode="typewriter"] .type-card.paper-feed { animation: paper-feed .42s cubic-bezier(.2,.72,.3,1); }
@keyframes paper-feed {
  0% { opacity: .45; transform: translateY(-18px) scaleY(.975); }
  65% { transform: translateY(2px) scaleY(1); }
  100% { opacity: 1; transform: none; }
}
:root[data-mode="typewriter"] .type-card .card-head { padding-bottom: 12px; border-bottom: 1px solid rgba(61,47,31,.16); }
:root[data-mode="typewriter"] .run-heading .eyebrow { color: #a33d2c; }
:root[data-mode="typewriter"] .type-card .seg {
  padding: 4px; border-color: #17130f; background: #29251f; box-shadow: inset 0 1px 2px #080706, 0 1px 0 rgba(255,255,255,.35);
}
:root[data-mode="typewriter"] .type-card .seg button {
  min-width: 38px; color: #4c4336; border: 1px solid #a89c85; border-radius: 50%;
  background: radial-gradient(circle at 40% 32%, #f2e9d6, #c9bca3 75%); box-shadow: 0 2px 0 #6b6151;
}
:root[data-mode="typewriter"] .type-card .seg button[aria-pressed="true"] {
  color: #f4ead6; border-color: #080706; background: radial-gradient(circle at 40% 32%, #4d4840, #1e1b18 75%); box-shadow: 0 1px 0 #050403;
}
:root[data-mode="typewriter"] .type-card #recordBtn,
:root[data-mode="typewriter"] .type-card #newRunBtn { background: #e6dcc6; }

:root[data-mode="typewriter"] .passage {
  margin-left: -4px; padding: 13px 10px 5px 19px; border-left: 1px solid rgba(164,56,43,.28);
  font-family: "Courier New", Courier, monospace; font-size: 31px; font-weight: 700; line-height: 1.72;
  letter-spacing: .022em; height: 5.16em;
  background: repeating-linear-gradient(to bottom, transparent 0 calc(1.72em - 1px), rgba(70,54,35,.065) calc(1.72em - 1px) 1.72em);
}
:root[data-mode="typewriter"] .c { color: #a39986; }
:root[data-mode="typewriter"] .c.is-correct { color: #1e1a16; text-shadow: -.3px 0 rgba(30,26,22,.36), .45px .25px rgba(30,26,22,.2); }
:root[data-mode="typewriter"] .w:nth-child(3n) .c.is-correct { text-shadow: .55px .2px rgba(30,26,22,.34); }
:root[data-mode="typewriter"] .w:nth-child(5n) .c.is-correct { opacity: .94; }
:root[data-mode="typewriter"] .caret {
  width: 2px; margin: 0 0 0 -1px; background: #a33d2c; box-shadow: 0 0 0 1px rgba(163,61,44,.12), 0 0 8px rgba(163,61,44,.28);
}
:root[data-mode="typewriter"] .passage.is-typing .caret { animation: typebar-tick .1s steps(1); }
@keyframes typebar-tick { 0% { opacity: .35; filter: blur(.4px); } }
:root[data-mode="typewriter"] .run-meta { color: #716653; }
:root[data-mode="typewriter"] .run-meta .combo-hud {
  color: #d8ccb5; border-color: #090806; border-radius: 2px;
  background: linear-gradient(#35312b, #1d1a17); box-shadow: inset 0 1px 0 rgba(255,255,255,.08);
}
:root[data-mode="typewriter"] .run-meta .combo-val { color: #d76a53; text-shadow: 0 1px 0 #000; }
:root[data-mode="typewriter"] .run-meta .combo-lbl { color: #9c907c; }
:root[data-mode="typewriter"] .progress { border: 1px solid rgba(52,40,27,.22); background: transparent; }
:root[data-mode="typewriter"] .progress i { background: repeating-linear-gradient(90deg, #9d3d2c 0 7px, transparent 7px 9px); }
:root[data-mode="typewriter"] .board-card { display: none; }
:root[data-mode="typewriter"] #view-type::after {
  content: ""; display: block; width: calc(100% - 18px); height: 64px; margin: -3px auto 0;
  border: 1px solid #090806; border-radius: 0 0 42px 42px;
  background:
    radial-gradient(ellipse at 50% -20%, #575149 0 24%, transparent 25%),
    linear-gradient(180deg, #35312b, #1c1916 70%, #100e0c);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.1), 0 15px 25px rgba(0,0,0,.3);
}
:root[data-mode="typewriter"] body.is-running .calibration { opacity: .12; }
:root[data-mode="typewriter"] body.is-running .type-stats { opacity: .16; }
:root[data-mode="typewriter"] body.is-running .topbar { opacity: .18; }

@media (max-width: 720px) {
  :root[data-mode="typewriter"] .typewriter-platen { grid-template-columns: 25px 1fr 25px; }
  :root[data-mode="typewriter"] .platen-knob { width: 25px; }
  :root[data-mode="typewriter"] .type-card { width: calc(100% - 18px); padding: 30px 24px 24px; }
  :root[data-mode="typewriter"] .passage { font-size: 23px; }
}

/* ====================================================================== */
/* Cinematic backgrounds + restrained highlights                          */
/* ====================================================================== */

/* Precision is a luminous instrument floating in a deep blue room. The
   gradients move slowly enough to feel environmental. The broad light sweep
   is intentionally occasional so it reads as atmosphere, not a screensaver. */
:root[data-mode="precision"] html {
  background: #070a13;
}
:root[data-mode="precision"] .mesh {
  overflow: hidden;
  background:
    radial-gradient(62% 52% at 12% 2%, rgba(22,167,255,.46), transparent 68%),
    radial-gradient(58% 56% at 93% 13%, rgba(126,68,255,.38), transparent 70%),
    radial-gradient(70% 62% at 52% 106%, rgba(13,108,225,.32), transparent 72%),
    conic-gradient(from 220deg at 52% 42%, #07101f, #0c0a22 28%, #07121f 56%, #090711 78%, #07101f);
  background-size: 125% 125%, 132% 132%, 120% 120%, 100% 100%;
  animation: precision-aurora 16s ease-in-out infinite alternate;
}
:root[data-mode="precision"] .mesh::before {
  content: ""; position: absolute; inset: 0;
  background-image:
    linear-gradient(rgba(103,179,255,.075) 1px, transparent 1px),
    linear-gradient(90deg, rgba(103,179,255,.075) 1px, transparent 1px);
  background-size: 56px 56px;
  -webkit-mask-image: linear-gradient(to bottom, transparent, #000 18%, #000 76%, transparent);
  mask-image: linear-gradient(to bottom, transparent, #000 18%, #000 76%, transparent);
  transform: perspective(520px) rotateX(58deg) scale(1.65) translateY(12%);
  transform-origin: 50% 100%; opacity: .52;
}
:root[data-mode="precision"] .mesh::after {
  content: ""; position: absolute; inset: -35%;
  background: linear-gradient(112deg, transparent 38%, rgba(89,196,255,.09) 45%, rgba(190,122,255,.18) 49%, rgba(255,255,255,.12) 51%, transparent 59%);
  transform: translateX(-42%) rotate(-6deg);
  animation: room-shine 32s cubic-bezier(.45,0,.55,1) infinite;
}
@keyframes precision-aurora {
  0% { background-position: 0% 0%, 100% 0%, 50% 100%, 0 0; filter: saturate(1); }
  100% { background-position: 8% 10%, 90% 16%, 58% 88%, 0 0; filter: saturate(1.24); }
}
@keyframes room-shine {
  0%, 76% { transform: translateX(-44%) rotate(-6deg); opacity: 0; }
  82%, 89% { opacity: .55; }
  96%, 100% { transform: translateX(44%) rotate(-6deg); opacity: 0; }
}

/* The chrome carries the same spectrum as the room instead of remaining flat. */
:root[data-mode="precision"] body:not(.fx-off) .brand b {
  color: transparent;
  background: linear-gradient(100deg, #fff 14%, #7dd7ff 34%, #b68cff 50%, #fff 66%, #7dd7ff 86%);
  background-size: 240% 100%; background-clip: text; -webkit-background-clip: text;
  background-position: 48% 0;
}
:root[data-mode="precision"] body:not(.fx-off) button.primary {
  background: linear-gradient(115deg, #147be7, #6c55e8 45%, #1ba4ea 75%, #147be7);
  background-size: 220% 100%; animation: primary-gradient 18s ease infinite;
  box-shadow: 0 9px 28px rgba(43,113,235,.3), inset 0 1px 0 rgba(255,255,255,.24);
}
:root[data-mode="precision"] body:not(.fx-off) .card::before {
  background: conic-gradient(from var(--kb-angle),
    rgba(255,255,255,.05), rgba(70,179,255,.72), rgba(173,102,255,.76),
    rgba(255,255,255,.07), rgba(70,179,255,.62), rgba(255,255,255,.05));
  animation: kb-beam 28s linear infinite;
}
:root[data-mode="precision"] body:not(.fx-off) .stat { overflow: hidden; }
:root[data-mode="precision"] body:not(.fx-off) .stat::before {
  content: ""; position: absolute; inset: -80% -40%; pointer-events: none; z-index: 2;
  background: linear-gradient(110deg, transparent 42%, rgba(105,195,255,.18) 48%, rgba(194,139,255,.22) 51%, transparent 58%);
  transform: translateX(-55%); animation: tile-shine 26s ease-in-out infinite;
}
:root[data-mode="precision"] body:not(.fx-off) .stat:nth-child(2)::before { animation-delay: .55s; }
:root[data-mode="precision"] body:not(.fx-off) .stat:nth-child(3)::before { animation-delay: 1.1s; }
:root[data-mode="precision"] body:not(.fx-off) .stat:nth-child(4)::before { animation-delay: 1.65s; }
@keyframes primary-gradient { 0%,100% { background-position: 0% 50%; } 50% { background-position: 100% 50%; } }
@keyframes tile-shine {
  0%, 82% { transform: translateX(-58%); opacity: 0; }
  88% { opacity: .65; }
  96%, 100% { transform: translateX(58%); opacity: 0; }
}

/* Typewriter is now a warm desk under a moving tungsten lamp. The wood lives
   on the mesh so the vignette and light can move independently without ever
   washing out the sheet. */
:root[data-mode="typewriter"] html { background: #1d120b; }
:root[data-mode="typewriter"] body { background: transparent; }
:root[data-mode="typewriter"] .mesh {
  display: block; overflow: hidden;
  background:
    radial-gradient(ellipse 82% 66% at 20% -10%, rgba(255,185,94,.34), transparent 63%),
    radial-gradient(ellipse 46% 40% at 86% 16%, rgba(182,74,42,.18), transparent 70%),
    linear-gradient(90deg, rgba(255,255,255,.035), transparent 18%, rgba(0,0,0,.13) 52%, transparent 79%),
    repeating-linear-gradient(92deg, #392318 0 3px, #4a2d1d 3px 7px, #301e15 7px 10px, #503120 10px 16px);
  animation: tungsten-room 13s ease-in-out infinite alternate;
}
:root[data-mode="typewriter"] .mesh::before {
  content: ""; position: absolute; inset: -10%;
  background:
    radial-gradient(circle at 16% 8%, rgba(255,227,165,.3), transparent 15%),
    radial-gradient(ellipse at 50% 25%, transparent 25%, rgba(10,5,2,.28) 78%);
  mix-blend-mode: screen; animation: lamp-sway 11s ease-in-out infinite alternate;
}
:root[data-mode="typewriter"] .mesh::after {
  content: ""; position: absolute; inset: 0;
  background:
    repeating-linear-gradient(106deg, transparent 0 92px, rgba(255,214,146,.035) 94px, transparent 98px),
    radial-gradient(ellipse at 50% 120%, transparent 36%, rgba(5,2,1,.42) 86%);
  opacity: .8;
}
@keyframes tungsten-room {
  from { background-position: 0 0, 100% 0, 0 0, 0 0; filter: brightness(.92) saturate(.95); }
  to { background-position: 7% 5%, 91% 8%, 0 0, 18px 0; filter: brightness(1.08) saturate(1.12); }
}
@keyframes lamp-sway {
  from { transform: translate3d(-3%, -1%, 0) scale(1.02); opacity: .62; }
  to { transform: translate3d(5%, 3%, 0) scale(1.09); opacity: 1; }
}

/* Warm, unmistakable reflections for the machine itself. */
:root[data-mode="typewriter"] body:not(.fx-off) .platen-rail {
  background:
    linear-gradient(105deg, transparent 22%, rgba(255,221,164,.46) 29%, transparent 36%) 0 0 / 240% 100%,
    linear-gradient(180deg, #666058 0, #211e1a 24%, #090806 68%, #38332d 100%);
  animation: platen-glint 24s ease-in-out infinite;
}
:root[data-mode="typewriter"] body:not(.fx-off) .type-card::before {
  display: block; content: ""; position: absolute; inset: 0; padding: 0;
  border-radius: 0; pointer-events: none; z-index: 0;
  -webkit-mask: none; mask: none;
  background: linear-gradient(108deg, transparent 30%, rgba(255,244,206,.34) 44%, rgba(255,255,255,.2) 49%, transparent 62%);
  background-size: 230% 100%; animation: paper-lamp 28s ease-in-out infinite;
}
:root[data-mode="typewriter"] body:not(.fx-off) .type-stats { overflow: hidden; }
:root[data-mode="typewriter"] body:not(.fx-off) .type-stats::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(105deg, transparent 34%, rgba(230,172,94,.15) 46%, rgba(255,235,190,.2) 50%, transparent 62%);
  transform: translateX(-65%); animation: brass-counter-shine 24s ease-in-out infinite;
}
:root[data-mode="typewriter"] body:not(.fx-off) button.primary {
  background: linear-gradient(115deg, #7f2d22, #bd6841 46%, #8e3427 72%, #6f281f);
  background-size: 220% 100%; animation: primary-gradient 18s ease infinite;
  box-shadow: 0 4px 0 #421711, 0 10px 18px rgba(50,20,10,.22), inset 0 1px 0 rgba(255,224,188,.32);
}
:root[data-mode="typewriter"] button.primary::after {
  background: linear-gradient(105deg, transparent 38%, rgba(255,223,166,.55) 49%, transparent 59%);
}
:root[data-mode="typewriter"] body:not(.fx-off) .ui-spotlight:not(.type-card)::after {
  content: ""; position: absolute; inset: 0; border-radius: inherit; pointer-events: none; z-index: 3;
  background: radial-gradient(260px circle at var(--spot-x, 50%) var(--spot-y, 50%), rgba(255,210,135,.2), transparent 68%);
  animation: ui-spot-in .24s ease both;
}
@keyframes platen-glint {
  0%, 72% { background-position: 130% 0, 0 0; }
  94%, 100% { background-position: -120% 0, 0 0; }
}
@keyframes paper-lamp {
  0%, 76% { background-position: 130% 0; opacity: .12; }
  85%, 92% { opacity: .55; }
  100% { background-position: -120% 0; opacity: .12; }
}
@keyframes brass-counter-shine {
  0%, 80% { transform: translateX(-65%); opacity: 0; }
  87% { opacity: .65; }
  96%, 100% { transform: translateX(65%); opacity: 0; }
}

body.fx-off button.primary::after,
body.fx-off .stat::before { display: none; }
:root[data-mode="typewriter"] body.fx-off .mesh { display: none; }

@media (prefers-reduced-motion: reduce) {
  :root[data-mode="precision"] .mesh,
  :root[data-mode="precision"] .mesh::after,
  :root[data-mode="typewriter"] .mesh,
  :root[data-mode="typewriter"] .mesh::before { animation: none !important; }
}

/* ---------------------------------------------------------------- */
/* challenges: the head-to-head card and the share grid             */
/* ---------------------------------------------------------------- */
.challenge-card .run-heading h2 { margin: 0; }
.challenge-card.is-active { border-color: color-mix(in srgb, var(--warning) 34%, var(--border)); }
.challenge-body { margin-top: 14px; display: grid; gap: 12px; }
.challenge-from { margin: 0; color: var(--text-secondary); font-size: 13px; }
.challenge-from b { color: var(--text-primary); }
.challenge-warn {
  margin: 0; padding: 9px 11px; border-radius: 8px; font-size: 12.5px;
  color: var(--text-secondary);
  background: color-mix(in srgb, var(--warning) 12%, transparent);
  border: 1px solid color-mix(in srgb, var(--warning) 30%, transparent);
}
.challenge-actions { display: flex; gap: 8px; flex-wrap: wrap; }
.challenge-fallback {
  width: 100%; font: 12px/1.5 var(--mono); resize: vertical;
  background: var(--surface-2); color: var(--text-secondary);
  border: 1px solid var(--border); border-radius: 8px; padding: 8px 10px;
}

/* The grid is 25 blocks over the passage in order. Colour is the quick read,
   but each cell carries its own label and the legend names every state it
   uses, so the meaning never rides on hue alone (D12). */
.challenge-grid { display: grid; gap: 8px; justify-items: start; }

/* friends: shared snapshots stay visually distinct from local typing profiles */
.social-hero {
  display: flex; align-items: center; justify-content: space-between; gap: 24px;
  padding: 24px 26px; overflow: hidden;
  background: linear-gradient(120deg, color-mix(in srgb, var(--series-1) 12%, var(--surface-1)), var(--surface-1) 58%);
}
.social-hero h2 { margin: 5px 0 6px; font-size: 25px; }
.social-hero p { margin: 0; max-width: 680px; }
.social-actions { display: flex; gap: 8px; flex: 0 0 auto; }
.social-stats { grid-template-columns: repeat(3, 1fr); margin-top: 16px; }
.social-leader { font-size: 22px !important; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.social-grid { align-items: start; }
#friendLeaderboard .is-you td { background: color-mix(in srgb, var(--series-1) 8%, transparent); }
.friend-rank { width: 52px; font-size: 16px; }
.friend-avatar {
  display: inline-grid; place-items: center; width: 25px; height: 25px; margin-right: 8px;
  border-radius: 8px; background: var(--series-1-soft); color: var(--series-1);
  border: 1px solid color-mix(in srgb, var(--series-1) 35%, var(--border)); font-weight: 750;
}
.friend-avatar.large { width: 38px; height: 38px; margin: 0; border-radius: 11px; font-size: 15px; }
.friend-list { display: grid; gap: 8px; margin-top: 8px; }
.friend-row {
  display: grid; grid-template-columns: auto 1fr auto auto; align-items: center; gap: 10px;
  padding: 10px; border: 1px solid var(--border); border-radius: 10px; background: var(--surface-2);
}
.friend-copy { display: grid; min-width: 0; }
.friend-copy b { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.friend-copy small { color: var(--muted); margin-top: 2px; }
.friend-empty { min-height: 250px; display: grid; place-content: center; justify-items: center; text-align: center; color: var(--muted); }
.friend-empty > span { font-size: 40px; color: var(--series-1); margin-bottom: 8px; }
.friend-empty b { color: var(--text-primary); }
.friend-empty p { max-width: 290px; margin: 5px 0 0; font-size: 12px; line-height: 1.5; }

@media (max-width: 760px) {
  .social-hero { align-items: flex-start; flex-direction: column; }
  .social-actions { width: 100%; flex-wrap: wrap; }
  .social-stats { grid-template-columns: 1fr; }
  .friend-row { grid-template-columns: auto 1fr auto; }
  .friend-row [data-friend-remove] { grid-column: 3; }
}
.glabel { color: var(--muted); font: 11px var(--mono); letter-spacing: .04em; }
.ggrid { display: grid; grid-template-columns: repeat(5, 1fr); gap: 4px; }
.gcell {
  width: 20px; height: 20px; border-radius: 4px; display: block;
  background: var(--surface-3); border: 1px solid var(--border);
  position: relative;
}
.gcell.is-faster  { background: var(--good); border-color: transparent; }
.gcell.is-par     { background: var(--surface-3); }
.gcell.is-slower  { background: var(--critical); border-color: transparent; }
.gcell.is-error   { background: var(--warning); border-color: transparent; }
/* A mistype gets a mark as well as a colour — the one state you should not have
   to compare hues to spot. */
.gcell.is-error::after {
  content: '×'; position: absolute; inset: 0;
  display: grid; place-items: center;
  font: 700 13px/1 var(--mono); color: rgba(0,0,0,.62);
}
.gcell.is-nodata  { background: transparent; border-style: dashed; }

.glegend { display: flex; gap: 12px; flex-wrap: wrap; }
.glegend-item {
  display: inline-flex; align-items: center; gap: 6px;
  color: var(--muted); font-size: 11.5px;
}
.glegend-item .gcell { width: 11px; height: 11px; border-radius: 3px; }
.glegend-item .gcell.is-error::after { font-size: 8px; }

/* Typewriter mode keeps its square-edged, mechanical vocabulary. */
:root[data-mode="typewriter"] .gcell,
:root[data-mode="typewriter"] .challenge-warn,
:root[data-mode="typewriter"] .challenge-fallback { border-radius: 2px; }
