/* ═══════════════════════════════════════════════════════════════════════════
   ONYXFALL, ARCADE CABINET

   A physical machine, not a dashboard. The rules, kept without exception:

     · GEOMETRY. 4px on every plate, panel, button and tile. 999px on chips
       only. Nothing else, ever.
     · ELEVATION. One shadow: 3px 3px 0 var(--sh-ink), hard, no blur. Anything
       pressable collapses that shadow to 0 and moves 3px down and right, so
       the object physically depresses under the thumb.
     · KEYLINE. 2px, never 1px. A cabinet is silkscreened, not hairlined.
     · TYPE. Syne 800 is the display face and it is only ever used LARGE, for
       numerals and the marquee. IBM Plex Sans carries every small thing.
       Labels are 11px, uppercase, 0.18em tracked.
     · COLOUR. One saturated amber, plus one hot pink used strictly as the
       cabinet's second silkscreen pass. Text on amber is always --bg.
     · RHYTHM. 16px, and multiples of it. Loose. Few objects per screen.
     · MOTION. 180ms with an overshoot. Numbers roll up when they change.
   ═══════════════════════════════════════════════════════════════════════════ */

:root {
  /* Written from JS by applySafeArea(). 0 outside Telegram fullscreen, so
     every utility that reads them collapses on its own. */
  --tg-safe-top: 0px;
  --tg-safe-bottom: 0px;

  /* Duplicated from brand.js so the splash paints correctly on frame one,
     before shell.js has stamped the palette onto <html>. */
  --bg:       #0C0B12;
  --surface:  #17161F;
  --tint:     #23212E;
  --tint-2:   #332F42;
  --line:     #4A4560;
  --ink:      #FFF4E2;
  --ink-2:    #B6AEC6;
  --ink-3:    #837C96;
  --accent:   #FFB700;
  --accent-d: #FFD24A;
  --good:     #35E08A;
  --warn:     #FF4D6D;

  /* Chrome only. game.js never reads these, so they are free to exist. */
  --hot:      #FF3D7F;   /* the second silkscreen pass */
  --sh-ink:   #000000;   /* the ink every hard shadow is printed in */

  --f-display: "Syne", "Avenir Next", "Segoe UI", sans-serif;
  --f-text: "IBM Plex Sans", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;

  --u: 16px;                       /* the whole spacing scale */
  --r: 4px;                        /* every rectangle in the app */
  --key: 2px solid var(--line);    /* the keyline */
  --hard: 3px 3px 0 var(--sh-ink); /* the only shadow */
  --e: cubic-bezier(.2, 1.45, .4, 1);
  --t: 180ms var(--e);
}

*, *::before, *::after { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }

/* Overlays set their own display, which outranks the UA rule for [hidden]. */
[hidden] { display: none !important; }

html, body {
  margin: 0; padding: 0; height: 100%;
  background: var(--bg);
  overscroll-behavior: none;
  -webkit-overflow-scrolling: touch;
}

body {
  font-family: var(--f-text);
  font-weight: 500;
  color: var(--ink);
  font-size: 14px;
  line-height: 1.45;
  -webkit-font-smoothing: antialiased;
}

button, input { font: inherit; color: inherit; }
button { border: 0; background: none; padding: 0; cursor: pointer; }

/* Anything that counts gets tabular figures, or the digits jitter as they tick. */
.rec-n, .beam b, .gauge b, .mission-v, .bezel-n, .over-n, .rw-pos, .rw-sc, .count span {
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
}

/* The icon sprite itself never renders. */
.sprite { position: absolute; width: 0; height: 0; overflow: hidden; }

/* ── icons: solid shapes, no strokes, deliberately a size up ─────────────── */

.ic {
  display: block; flex: none;
  width: 26px; height: 26px;
  fill: currentColor;
  stroke: none;
}
.ic-s { width: 20px; height: 20px; }

/* The only 999px objects in the app. */
.chip {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 6px 12px 6px 9px;
  border-radius: 999px;
  background: var(--tint);
  border: 2px solid var(--line);
  color: var(--accent-d);
  font-size: 11px; font-weight: 700;
  letter-spacing: 0.14em; text-transform: uppercase;
}
.chip .ic { width: 15px; height: 15px; }
.chip--lit { background: var(--accent); border-color: var(--accent); color: var(--bg); }

/* ── the press: every interactive object is a physical key ───────────────── */

.dep {
  box-shadow: var(--hard);
  transition: transform var(--t), box-shadow var(--t), background var(--t), color var(--t);
}
.dep:active { transform: translate(3px, 3px); box-shadow: 0 0 0 var(--sh-ink); }

/* ── labels ──────────────────────────────────────────────────────────────── */

.lbl {
  display: block;
  font-size: 11px; font-weight: 700;
  letter-spacing: 0.18em; text-transform: uppercase;
  color: var(--ink-3);
}

.note {
  font-size: 12px; font-weight: 500; line-height: 1.55;
  color: var(--ink-3);
  margin: 0;
}

/* ── buttons ─────────────────────────────────────────────────────────────── */

.key {
  display: inline-flex; align-items: center; justify-content: center; gap: 10px;
  width: 100%;
  padding: 15px 18px;
  border-radius: var(--r);
  border: 2px solid var(--line);
  background: var(--tint);
  color: var(--ink);
  font-size: 13px; font-weight: 700;
  letter-spacing: 0.14em; text-transform: uppercase;
}
.key--lit { background: var(--accent); border-color: var(--accent); color: var(--bg); }
.key--out { background: transparent; }
.key--sm { width: auto; padding: 10px 14px; font-size: 11px; gap: 7px; }
.key--sm .ic { width: 18px; height: 18px; }

/* A square key: back, pause, close. Big target, same physics. */
.keysq {
  width: 46px; height: 46px; flex: none;
  display: grid; place-items: center;
  border-radius: var(--r);
  border: 2px solid var(--line);
  background: var(--tint);
  color: var(--ink);
}

/* ── splash: the marquee lighting up ─────────────────────────────────────── */

#splash {
  position: fixed; inset: 0; z-index: 90;
  background: var(--bg);
  display: flex; flex-direction: column;
  align-items: center; justify-content: center;
  gap: var(--u);
  transition: opacity 220ms var(--e);
}
#splash.out { opacity: 0; }
.boot-mark {
  width: 72px; height: 72px;
  display: grid; place-items: center;
  border-radius: var(--r);
  background: var(--accent);
  color: var(--bg);
  box-shadow: var(--hard);
  animation: drop-in 300ms var(--e) both;
}
.boot-mark .ic { width: 42px; height: 42px; }
.boot-name {
  font-family: var(--f-display);
  font-size: 34px; font-weight: 800;
  letter-spacing: 0.16em; text-indent: 0.16em;
  animation: drop-in 300ms var(--e) 70ms both;
}
.boot-sub {
  font-size: 11px; font-weight: 700;
  letter-spacing: 0.3em; text-transform: uppercase;
  color: var(--accent);
  animation: drop-in 300ms var(--e) 140ms both;
}

@keyframes drop-in {
  from { transform: translateY(-14px); opacity: 0; }
  to   { transform: none; opacity: 1; }
}

/* ── frame ───────────────────────────────────────────────────────────────── */

#app {
  position: fixed; inset: 0;
  display: flex; flex-direction: column;
  background: var(--bg);
}

main { flex: 1; min-height: 0; position: relative; }

/* No persistent top bar: on a cabinet the name is printed on the machine, not
   repeated above every screen. Each screen carries the fullscreen top inset. */
.screen {
  position: absolute; inset: 0;
  display: none;
  flex-direction: column;
  gap: var(--u);
  overflow-y: auto;
  padding: calc(max(var(--tg-safe-top), env(safe-area-inset-top, 0px)) + var(--u))
           var(--u) calc(var(--u) + 8px);
}
.screen.is-active { display: flex; }
.screen--play { overflow: hidden; gap: 12px; padding: calc(max(var(--tg-safe-top), env(safe-area-inset-top, 0px)) + 10px) 12px 10px; }

/* ── bottom nav: four keys on the control panel ──────────────────────────── */

.nav {
  flex: none;
  display: flex; gap: 6px;
  padding: 8px 10px;
  padding-bottom: calc(8px + max(var(--tg-safe-bottom), env(safe-area-inset-bottom, 0px)));
  background: var(--surface);
  border-top: 2px solid var(--line);
}
.navkey {
  flex: 1; position: relative;
  display: flex; flex-direction: column; align-items: center; gap: 5px;
  padding: 9px 2px 7px;
  border-radius: var(--r);
  color: var(--ink-3);
  font-size: 9.5px; font-weight: 700;
  letter-spacing: 0.14em; text-transform: uppercase;
  transition: color var(--t);
}
.navkey::before {
  content: ""; position: absolute; inset: 0;
  border-radius: var(--r);
  background: var(--accent);
  opacity: 0;
  transform: scale(.74);
  transition: opacity var(--t), transform var(--t);
}
.navkey .ic, .navkey span { position: relative; }
.navkey .ic { width: 22px; height: 22px; }
.navkey.is-on { color: var(--bg); }
.navkey.is-on::before { opacity: 1; transform: none; }

/* Play is the machine and nothing else. */
[data-screen="play"] .nav { display: none; }

/* ═══════════════════════ HOME ══════════════════════════════════════════════
   The cabinet, read top to bottom: the score plate is the screen, the marquee
   is the printed name below it, and the one enormous amber key is the control
   panel. Everything after that is bezel. */

/* ── the record plate: the biggest object in the app ─────────────────────── */

.record {
  flex: none;
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 14px;
  padding: 18px;
  border-radius: var(--r);
  border: 2px solid var(--accent);
  background: var(--surface);
  box-shadow: var(--hard);
}
.record-main { min-width: 0; display: flex; flex-direction: column; }
.record .chip { align-self: flex-start; margin-top: 12px; }
.rec-n {
  display: block;
  font-family: var(--f-display);
  font-weight: 800;
  line-height: 0.8;
  letter-spacing: -0.045em;
  white-space: nowrap;
  /* Syne 800 sets a digit at roughly one em, so a long score would run into
     the column beside it. The second declaration divides the track by the
     glyph count the script stamps on --len; if a browser rejects dividing by
     a var, the plain clamp above is what survives. */
  font-size: clamp(56px, 21vw, 104px);
  font-size: min(clamp(56px, 21vw, 104px), calc((100vw - 130px) / var(--len, 3)));
  color: var(--accent);
  margin: 10px 0 8px;
}
.rec-u { font-size: 11px; font-weight: 700; letter-spacing: 0.18em; text-transform: uppercase; color: var(--ink-2); }

/* The column, drawn. Each bar is a landed slab and each is narrower than the
   one above it, because the overhang sheared off. The dashed block on the top
   bar is that overhang, the instant before it goes. This is the game. */
.column {
  width: 44px; flex: none;
  display: flex; flex-direction: column; gap: 4px;
  align-items: center; justify-content: flex-start;
  padding-top: 4px;
}
.column i {
  display: block; height: 13px;
  background: var(--accent);
  border-radius: 1px;
  position: relative;
}
/* the first bar is still falling, so it sits off the stack */
.column i:nth-child(1) { margin-bottom: 9px; }
/* Newest slab on top, oldest at the base, so the column widens on the way
   down: every landing above it shaved something off. */
.column i:nth-child(1) { width: 44%; background: none; box-shadow: inset 0 0 0 2px var(--accent); }
.column i:nth-child(2) { width: 44%; }
.column i:nth-child(3) { width: 52%; }
.column i:nth-child(4) { width: 60%; }
.column i:nth-child(5) { width: 68%; }
.column i:nth-child(6) { width: 76%; }
.column i:nth-child(7) { width: 88%; }
.column i:nth-child(8) { width: 96%; }
/* the slab still in the air, and the piece of it about to be sheared off */
.column i:nth-child(1)::after {
  content: ""; position: absolute; top: 0; right: -17px;
  width: 15px; height: 100%;
  border: 2px dashed var(--hot);
  border-radius: 1px;
}

/* ── the marquee: the game's name, printed on the machine ────────────────── */

.marquee {
  flex: none;
  text-align: center;
  padding: 14px 12px;
  border-radius: var(--r);
  border: var(--key);
  background: var(--tint);
  box-shadow: var(--hard);
}
.marquee b {
  display: block;
  font-family: var(--f-display);
  font-size: 30px; font-weight: 800;
  letter-spacing: 0.2em; text-indent: 0.2em;
  color: var(--ink);
  line-height: 1;
}
.marquee span {
  display: block; margin-top: 8px;
  font-size: 10px; font-weight: 700;
  letter-spacing: 0.34em; text-indent: 0.34em; text-transform: uppercase;
  color: var(--hot);
}

/* ── the one very large key ──────────────────────────────────────────────── */

.beam {
  flex: none;
  display: flex; align-items: center; gap: 14px;
  width: 100%;
  padding: 20px;
  border-radius: var(--r);
  border: 2px solid var(--accent);
  background: var(--accent);
  color: var(--bg);
  text-align: left;
}
.beam .ic { width: 34px; height: 34px; }
.beam b {
  display: block;
  font-family: var(--f-display);
  font-size: 32px; font-weight: 800; line-height: 1;
  letter-spacing: 0.1em;
}
.beam i {
  display: block; font-style: normal; margin-top: 6px;
  font-size: 11px; font-weight: 700;
  letter-spacing: 0.12em; text-transform: uppercase;
  opacity: .72;
}
.beam-tx { margin-right: auto; }

/* ── counters ────────────────────────────────────────────────────────────── */

.gauges { flex: none; display: grid; grid-template-columns: repeat(4, 1fr); gap: 8px; }
.gauge {
  padding: 12px 6px 10px;
  text-align: center;
  border-radius: var(--r);
  border: var(--key);
  background: var(--surface);
  box-shadow: var(--hard);
}
.gauge b {
  display: block;
  font-family: var(--f-display);
  font-size: 24px; font-weight: 800; line-height: 1;
  color: var(--ink);
}
.gauge span {
  display: block; margin-top: 7px;
  font-size: 8.5px; font-weight: 700;
  letter-spacing: 0.12em; text-transform: uppercase;
  color: var(--ink-3);
}

/* ── the daily target ────────────────────────────────────────────────────── */

.mission {
  flex: none;
  padding: 14px 16px 16px;
  border-radius: var(--r);
  border: var(--key);
  background: var(--surface);
  box-shadow: var(--hard);
}
.mission-top { display: flex; align-items: center; gap: 10px; }
.mission-top .lbl { flex: 1; min-width: 0; color: var(--ink-2); letter-spacing: 0.1em; }
.mission-state {
  font-size: 10px; font-weight: 700;
  letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--ink-3);
}
.mission-state.is-done { color: var(--good); }
/* A segmented gauge, the way a cabinet prints a bar: ticks, not a gradient. */
.bar {
  height: 14px; margin: 12px 0 8px;
  border: var(--key);
  border-radius: var(--r);
  background:
    repeating-linear-gradient(90deg, var(--tint) 0 8px, transparent 8px 10px),
    var(--bg);
  overflow: hidden;
}
.bar i {
  display: block; height: 100%; width: 0;
  background: var(--accent);
  transition: width var(--t);
}
.mission-v { font-size: 11px; font-weight: 700; letter-spacing: 0.1em; color: var(--accent-d); }

/* ── the optional offer, one element so it vanishes whole ────────────────── */

.offer {
  flex: none;
  display: flex; align-items: center; gap: 12px;
  padding: 14px;
  border-radius: var(--r);
  border: 2px dashed var(--line);
  background: transparent;
}
.offer .ic { width: 26px; height: 26px; color: var(--accent-d); }
.offer-tx { flex: 1; min-width: 0; }
.offer-tx b { display: block; font-size: 13px; font-weight: 700; }
.offer-tx i {
  display: block; font-style: normal; margin-top: 3px;
  font-size: 10.5px; font-weight: 600; color: var(--ink-3);
  letter-spacing: 0.06em;
}

[data-screen="home"] .note { margin-top: auto; padding-top: 8px; }

/* ═══════════════════════ PLAY ══════════════════════════════════════════════ */

.bezel {
  flex: none;
  display: flex; align-items: center; gap: 10px;
}
.bezel-n {
  font-family: var(--f-display);
  font-weight: 800; line-height: 1;
  letter-spacing: -0.03em;
  white-space: nowrap;
  font-size: 42px;
  font-size: min(42px, calc((100vw - 176px) / var(--len, 3)));
  color: var(--accent);
  display: block;
}
.bezel-tx { margin-right: auto; }
.bezel-tx .lbl { margin-top: 4px; font-size: 9px; letter-spacing: 0.2em; }
.bezel .keysq { width: 42px; height: 42px; }
.bezel .keysq .ic { width: 22px; height: 22px; }

/* The chain is the one thing that pops mid run, so it snaps in and sits lit. */
.combo {
  opacity: 0;
  padding: 7px 13px;
  border-radius: 999px;
  background: var(--hot);
  color: var(--bg);
  font-family: var(--f-display);
  font-size: 17px; font-weight: 800; line-height: 1;
  letter-spacing: 0.02em;
  transition: opacity var(--t);
}
.combo.is-on { opacity: 1; animation: chainpop 200ms var(--e); }
@keyframes chainpop {
  0%   { transform: scale(.6); }
  100% { transform: scale(1); }
}

.guard {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 7px 11px;
  border-radius: 999px;
  background: var(--tint-2);
  color: var(--accent-d);
  font-size: 10px; font-weight: 700;
  letter-spacing: 0.14em; text-transform: uppercase;
}
.guard .ic { width: 15px; height: 15px; }

/* How much stone is left to aim at. This gauge IS the life bar. */
.stone { flex: none; display: flex; align-items: center; gap: 12px; }
.stone .lbl { flex: none; font-size: 9px; letter-spacing: 0.18em; }
.stone .bar { flex: 1; margin: 0; height: 12px; }
.stone .bar i { width: 100%; }
.stone .bar i.is-low { background: var(--warn); }

.crt {
  flex: 1; min-height: 0; position: relative;
  border-radius: var(--r);
  border: var(--key);
  background: var(--bg);
  box-shadow: var(--hard);
  overflow: hidden;
}
#stage { display: block; width: 100%; height: 100%; touch-action: none; }

/* Attract mode: the whole panel is the start target. */
.attract {
  position: absolute; inset: 0;
  display: flex; align-items: center; justify-content: center;
  background: var(--bg);
  padding: 18px;
  overflow-y: auto;
}
.attract-in { width: 100%; max-width: 320px; }
.attract-t {
  display: block; text-align: center;
  font-family: var(--f-display);
  font-size: 20px; font-weight: 800;
  letter-spacing: 0.16em; text-indent: 0.16em; text-transform: uppercase;
  color: var(--accent);
  margin-bottom: 6px;
  animation: drop-in 240ms var(--e) both;
}
.attract-s {
  display: block; text-align: center;
  font-size: 10px; font-weight: 700;
  letter-spacing: 0.28em; text-indent: 0.28em; text-transform: uppercase;
  color: var(--ink-3);
  margin-bottom: 20px;
  animation: drop-in 240ms var(--e) 50ms both;
}
.steps { list-style: none; margin: 0 0 20px; padding: 0; display: flex; flex-direction: column; gap: 10px; }
.step {
  display: flex; align-items: center; gap: 12px;
  padding: 12px;
  border-radius: var(--r);
  border: var(--key);
  background: var(--surface);
  box-shadow: var(--hard);
  animation: drop-in 240ms var(--e) both;
}
.step:nth-child(1) { animation-delay: 80ms; }
.step:nth-child(2) { animation-delay: 120ms; }
.step:nth-child(3) { animation-delay: 160ms; }
.step > .ic { color: var(--accent); }
.step-tx { min-width: 0; }
.step-tx b { display: block; font-size: 12px; font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase; }
.step-tx i { display: block; font-style: normal; margin-top: 3px; font-size: 12px; font-weight: 500; color: var(--ink-2); line-height: 1.4; }
.attract-in .key { animation: drop-in 240ms var(--e) 200ms both; }

/* ═══════════════════════ RANK ══════════════════════════════════════════════ */

.seg { flex: none; display: flex; gap: 8px; }
.seg-btn {
  flex: 1;
  display: flex; align-items: center; justify-content: center; gap: 8px;
  padding: 13px 8px;
  border-radius: var(--r);
  border: var(--key);
  background: var(--surface);
  box-shadow: var(--hard);
  color: var(--ink-3);
  font-size: 11px; font-weight: 700;
  letter-spacing: 0.14em; text-transform: uppercase;
  transition: background var(--t), color var(--t), border-color var(--t);
}
.seg-btn .ic { width: 18px; height: 18px; }
.seg-btn.is-on { background: var(--accent); border-color: var(--accent); color: var(--bg); }

.head {
  flex: none;
  font-size: 11px; font-weight: 700;
  letter-spacing: 0.2em; text-transform: uppercase;
  color: var(--ink-3);
}

.table { flex: none; }
/* Rows are built by shell.js, so these class names are fixed by contract. */
.rw {
  display: grid;
  grid-template-columns: 30px 34px 1fr auto;
  align-items: center; gap: 12px;
  padding: 11px 14px;
  margin-bottom: 8px;
  border-radius: var(--r);
  border: var(--key);
  background: var(--surface);
  box-shadow: var(--hard);
}
.rw-pos {
  font-family: var(--f-display);
  font-size: 17px; font-weight: 800;
  color: var(--ink-3);
  text-align: center;
}
.rw-av {
  width: 34px; height: 34px;
  display: grid; place-items: center;
  border-radius: 999px;
  background: hsl(var(--h), 80%, 58%);
  color: var(--bg);
  font-size: 14px; font-weight: 700;
}
.rw-nm {
  font-family: var(--f-display);
  font-size: 16px; font-weight: 800;
  letter-spacing: 0.12em; text-transform: uppercase;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
.rw-sc {
  font-family: var(--f-display);
  font-size: 19px; font-weight: 800;
  color: var(--accent);
}
.rw--top .rw-pos { color: var(--hot); }
.rw--me { border-color: var(--accent); }
.rw--me .rw-nm { color: var(--accent-d); }

/* ═══════════════════════ MORE ══════════════════════════════════════════════ */

.rows { flex: none; display: flex; flex-direction: column; gap: 8px; }
.row {
  display: flex; align-items: center; gap: 14px;
  width: 100%;
  padding: 14px;
  border-radius: var(--r);
  border: var(--key);
  background: var(--surface);
  box-shadow: var(--hard);
  color: var(--ink);
  font-size: 13px; font-weight: 600;
  text-align: left;
}
.row > span { flex: 1; min-width: 0; }
.row > .ic { color: var(--accent-d); }
.row .chev { color: var(--ink-3); width: 20px; height: 20px; }

/* Square switch: this cabinet has no round parts except chips. */
.sw {
  appearance: none; -webkit-appearance: none;
  flex: none; position: relative;
  width: 52px; height: 28px; margin: 0;
  border-radius: var(--r);
  border: var(--key);
  background: var(--tint);
  transition: background var(--t), border-color var(--t);
}
.sw::after {
  content: ""; position: absolute; top: 2px; left: 2px;
  width: 20px; height: 20px;
  border-radius: 1px;
  background: var(--ink-3);
  transition: transform var(--t), background var(--t);
}
.sw:checked { background: var(--accent); border-color: var(--accent); }
.sw:checked::after { transform: translateX(24px); background: var(--bg); }

/* ═══════════════════════ OVERLAYS ══════════════════════════════════════════ */

.scrim { position: fixed; inset: 0; z-index: 40; background: rgba(4, 3, 8, .78); }

.sheet {
  position: fixed; z-index: 50;
  left: 12px; right: 12px;
  bottom: calc(12px + max(var(--tg-safe-bottom), env(safe-area-inset-bottom, 0px)));
  display: flex; flex-direction: column;
  border-radius: var(--r);
  border: var(--key);
  background: var(--surface);
  box-shadow: var(--hard);
  max-height: calc(100dvh - max(var(--tg-safe-top), env(safe-area-inset-top, 0px)) - 24px);
  /* Deliberately NOT animated. A sheet that slides in from below sits, for the
     length of the animation, with its own Close button under the fold. */
}
.sheet-head {
  flex: none;
  display: flex; align-items: center; gap: 12px;
  padding: 14px;
  border-bottom: 2px solid var(--line);
}
.sheet-head b {
  flex: 1; min-width: 0;
  font-family: var(--f-display);
  font-size: 16px; font-weight: 800;
  letter-spacing: 0.08em; text-transform: uppercase;
}
.sheet-head .keysq { width: 38px; height: 38px; }
.sheet-head .keysq .ic { width: 18px; height: 18px; }
.sheet-body {
  flex: 1; min-height: 0;
  overflow-y: auto;
  padding: var(--u) var(--u) 4px;
  font-size: 13.5px; line-height: 1.6; font-weight: 500;
  color: var(--ink-2);
}
.sheet-body p { margin: 0 0 12px; }
.sheet-body ul { margin: 0 0 12px; padding-left: 0; list-style: none; }
.sheet-body li { position: relative; padding-left: 20px; margin-bottom: 10px; }
.sheet-body li::before {
  content: ""; position: absolute; left: 0; top: 7px;
  width: 9px; height: 9px;
  background: var(--accent);
}
.sheet-body b { font-weight: 700; color: var(--ink); }
.sheet-foot { flex: none; padding: 12px var(--u) var(--u); border-top: 2px solid var(--line); }

.modal {
  position: fixed; inset: 0; z-index: 55;
  display: flex; align-items: center; justify-content: center;
  padding: 20px;
  pointer-events: none;
}
.panel {
  pointer-events: auto;
  width: 100%; max-width: 330px;
  padding: 20px;
  border-radius: var(--r);
  border: var(--key);
  background: var(--surface);
  box-shadow: var(--hard);
  text-align: center;
  animation: slam 180ms var(--e);
}
@keyframes slam { from { transform: scale(.88); opacity: 0; } to { transform: none; opacity: 1; } }
.panel .chip { margin-bottom: 12px; }
.panel .key + .key { margin-top: 10px; }
.panel-t {
  display: block;
  font-family: var(--f-display);
  font-size: 24px; font-weight: 800;
  letter-spacing: 0.14em; text-transform: uppercase;
  margin-bottom: 8px;
}
.over-n {
  display: block;
  font-family: var(--f-display);
  font-weight: 800; line-height: 0.86;
  letter-spacing: -0.04em;
  color: var(--accent);
  margin: 6px 0 10px;
  white-space: nowrap;
  font-size: 68px;
  font-size: min(68px, calc(286px / var(--len, 3)));
}
.panel .note { margin-top: 6px; }
.panel-keys { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin-top: var(--u); }
.panel-keys .key { padding: 14px 8px; font-size: 11px; gap: 8px; letter-spacing: 0.1em; }
.panel-keys .ic { width: 18px; height: 18px; }
.adkey { text-align: left; }
.adkey .ic { color: var(--accent-d); }
.adkey b { display: block; font-size: 12px; font-weight: 700; letter-spacing: 0.08em; }
.adkey i {
  display: block; font-style: normal; margin-top: 3px;
  font-size: 10.5px; font-weight: 500; letter-spacing: 0.02em;
  text-transform: none; color: var(--ink-3);
}

.count {
  position: fixed; inset: 0; z-index: 60;
  display: grid; place-items: center;
  pointer-events: none;
}
.count span {
  display: grid; place-items: center;
  width: 130px; height: 130px;
  border-radius: var(--r);
  border: 2px solid var(--accent);
  background: var(--surface);
  box-shadow: var(--hard);
  font-family: var(--f-display);
  font-size: 68px; font-weight: 800;
  color: var(--accent);
  animation: slam 180ms var(--e);
}

.toast {
  position: fixed; z-index: 70;
  left: var(--u); right: var(--u);
  bottom: calc(100px + max(var(--tg-safe-bottom), env(safe-area-inset-bottom, 0px)));
  padding: 14px 18px;
  border-radius: var(--r);
  border: var(--key);
  background: var(--tint);
  box-shadow: var(--hard);
  font-size: 12px; font-weight: 700;
  letter-spacing: 0.08em; text-transform: uppercase;
  text-align: center;
}

/* ── numbers roll up when they change ────────────────────────────────────── */

.roll { display: block; }
.roll.rolling { animation: rollup 180ms var(--e); }
@keyframes rollup {
  from { transform: translateY(0.34em); opacity: .35; }
  to   { transform: none; opacity: 1; }
}

/* ── reduce motion: kill all of it ───────────────────────────────────────── */

[data-reduce-motion="1"] *,
[data-reduce-motion="1"] *::before,
[data-reduce-motion="1"] *::after {
  animation: none !important;
  transition: none !important;
}

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

/* Short phones: the display numerals give first, nothing else moves. */
@media (max-height: 700px) {
  .rec-n { font-size: min(clamp(48px, 18vw, 82px), calc((100vw - 130px) / var(--len, 3))); }
  .column i { height: 9px; }
  .beam { padding: 16px; }
  .beam b { font-size: 26px; }
  .marquee { padding: 11px 12px; }
  .marquee b { font-size: 24px; }
  .over-n { font-size: 54px; }
  .bezel-n { font-size: 34px; }
}
