/* ═══════════════════════════════════════════════════════════════════════════
   TIDECALL — PIER ARCADE CABINET

   A machine bolted to a boardwalk, not a dashboard. The rules this sheet
   keeps, without exception:

     · GEOMETRY. Every panel, plate, key and row is BADGE SHAPED: 4px on the
       top corners, deeply rounded on the bottom, the way a marquee hangs off
       the top of a cabinet. Chips are 999px. There is no plain rectangle in
       the app.
     · ELEVATION. One shadow: 3px 3px 0 var(--print). Hard, no blur, printed
       in the darkest ink there is. Anything pressable collapses that shadow
       to nothing 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. Bungee is the display face, a signwriter's face, and it is used
       LARGE and in caps ONLY: the score plate, the marquee, PLAY, the count
       in play. Archivo carries every small thing. Captions are 11px, caps,
       0.18em tracked.
     · COLOUR. Exactly two silkscreen inks on the body. AQUA is the water and
       every number that came out of it. TANGERINE is every button you are
       meant to push. Text on either is always --bg.
     · RHYTHM. 16px and multiples of it. Loose, big targets, few objects.
     · 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:       #050A1C;
  --surface:  #0C1631;
  --tint:     #132447;
  --tint-2:   #1E3A6E;
  --line:     #2E528F;
  --ink:      #F2FAFF;
  --ink-2:    #A8BFDC;
  --ink-3:    #7089AE;
  --accent:   #19E3C4;
  --accent-d: #5DF2DA;
  --good:     #B8F241;
  --warn:     #FF3B5C;

  /* Chrome only. game.js never reads these, so they are free to exist. */
  --bulb:  #FF7A29;   /* the second silkscreen pass: the button ink */
  --print: #01050E;   /* the ink every hard shadow is printed in */

  --f-display: "Bungee", "Impact", "Haettenschweiler", sans-serif;
  --f-text: "Archivo", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;

  --u: 16px;                          /* the whole spacing scale */

  /* The badge. Flat across the top where it bolts on, deep at the bottom. */
  --r-panel: 4px 4px 26px 26px;
  --r-key:   4px 4px 18px 18px;
  --r-sq:    4px 4px 14px 14px;
  --r-bar:   3px 3px 9px 9px;

  --key: 2px solid var(--line);
  --hard: 3px 3px 0 var(--print);
  --e: cubic-bezier(.2, 1.5, .38, 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. */
.plate-n, .bez-n, .card-n, .ctr b, .tgt-v, .rw-pos, .rw-sc, .count span {
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
}

/* The die-cut sheet itself never renders. */
.diecut { position: absolute; width: 0; height: 0; overflow: hidden; }

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

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

/* ── captions and small print ────────────────────────────────────────────── */

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

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

/* ── chips: the only 999px objects in the machine ────────────────────────── */

.chip {
  display: inline-flex; align-items: center; gap: 6px;
  padding: 6px 12px;
  border-radius: 999px;
  background: var(--tint);
  border: 2px solid var(--line);
  color: var(--accent-d);
  font-size: 10.5px; font-weight: 700;
  letter-spacing: 0.16em; text-transform: uppercase;
  white-space: nowrap;
}
.chip .ico { width: 14px; height: 14px; }
.chip--lit { background: var(--accent); border-color: var(--accent); color: var(--bg); }
.chip--hot { background: var(--bulb); border-color: var(--bulb); color: var(--bg); }
.chip--lg {
  width: 48px; height: 48px; flex: none;
  padding: 0; justify-content: center;
  border-radius: 999px;
  color: var(--accent);
}
.chip--lg .ico { width: 26px; height: 26px; }

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

.push {
  box-shadow: var(--hard);
  transition: transform var(--t), box-shadow var(--t), background var(--t), color var(--t), border-color var(--t);
}
.push:active { transform: translate(3px, 3px); box-shadow: 0 0 0 var(--print); }

/* ── controls ────────────────────────────────────────────────────────────── */

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

/* The ad control carries three lines of its own, so it stops being a button
   shape and becomes a labelled plate with a mark on the left. */
.ctrl--ad { justify-content: flex-start; text-align: left; text-transform: none; letter-spacing: 0; padding: 13px 15px; }
.ad-tx { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.ad-tx b { font-size: 13px; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase; }
.ad-tx i { font-style: normal; font-size: 11.5px; font-weight: 500; color: var(--ink-2); line-height: 1.4; }
.ad-tx i:empty { display: none; }

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

/* ── splash: the marquee coming on before the machine does ───────────────── */

#splash {
  position: fixed; inset: 0; z-index: 90;
  background: var(--bg);
  display: flex; flex-direction: column;
  align-items: center; justify-content: center;
  gap: 14px;
  transition: opacity 220ms var(--e);
}
#splash.out { opacity: 0; }
.boot-badge {
  width: 78px; height: 60px;
  display: grid; place-items: center;
  border-radius: var(--r-key);
  background: var(--accent);
  color: var(--bg);
  box-shadow: var(--hard);
  animation: bolt-on 300ms var(--e) both;
}
.boot-badge .ico { width: 44px; height: 44px; }
.boot-word {
  font-family: var(--f-display);
  font-size: 32px; line-height: 1;
  letter-spacing: 0.04em;
  animation: bolt-on 300ms var(--e) 70ms both;
}
.boot-tag {
  font-size: 10.5px; font-weight: 700;
  letter-spacing: 0.3em; text-transform: uppercase;
  color: var(--bulb);
  animation: bolt-on 300ms var(--e) 140ms both;
}
@keyframes bolt-on {
  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 standing brand bar: on a cabinet the name is printed on the machine
   once, on the marquee. Each screen therefore carries the fullscreen top
   inset itself. */
.scr {
  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)) + 14px)
           var(--u) calc(var(--u) + 6px);
}
.scr.is-active { display: flex; }
/* Plates are bolted on at their own size: nothing squeezes to fit the column,
   the screen scrolls instead. .cab overrides this to fill the Play screen. */
.scr > * { flex: none; }
.scr--play {
  overflow: hidden; gap: 10px;
  padding: calc(max(var(--tg-safe-top), env(safe-area-inset-top, 0px)) + 8px) 12px 10px;
}

/* ── the control deck: four keys along the bottom ────────────────────────── */

.deck {
  flex: none;
  display: flex; gap: 6px;
  padding: 8px;
  padding-bottom: calc(8px + max(var(--tg-safe-bottom), env(safe-area-inset-bottom, 0px)));
  background: var(--surface);
  border-top: 2px solid var(--line);
}
.deck-k {
  flex: 1;
  display: flex; flex-direction: column; align-items: center; gap: 3px;
  padding: 8px 2px 7px;
  border-radius: var(--r-sq);
  border: 2px solid transparent;
  color: var(--ink-3);
  font-size: 9px; font-weight: 700;
  letter-spacing: 0.14em; text-transform: uppercase;
  transition: background var(--t), color var(--t), border-color var(--t);
}
.deck-k .ico { width: 22px; height: 22px; }
.deck-k.is-on {
  background: var(--accent);
  border-color: var(--accent);
  color: var(--bg);
  box-shadow: var(--hard);
}
/* The machine owns the whole screen once a run is on. */
html[data-screen="play"] .deck { display: none; }

/* ═══════════════════════ HOME ═══════════════════════ */

/* ── the marquee ─────────────────────────────────────────────────────────── */

.marq {
  flex: none; position: relative;
  padding: 20px 16px 15px;
  text-align: center;
  background: var(--surface);
  border: var(--key);
  border-radius: var(--r-panel);
  box-shadow: var(--hard);
  overflow: hidden;
}
/* The bulb strip that runs along the top edge of every seafront marquee. */
.marq-bulbs {
  position: absolute; left: 0; right: 0; top: 6px; height: 8px;
  background-image: radial-gradient(circle at center, var(--bulb) 0 2.4px, transparent 2.9px);
  background-size: 21px 8px;
}
.marq-word {
  display: block;
  font-family: var(--f-display); font-weight: 400;
  font-size: 30px; line-height: 1;
  letter-spacing: 0.05em;
}
.marq-tag {
  display: block; margin-top: 7px;
  font-size: 10px; font-weight: 700;
  letter-spacing: 0.28em; text-transform: uppercase;
  color: var(--ink-3);
}

/* ── the score plate: the hero object, lit, with the standing bolted on ──── */

.plate {
  flex: none; position: relative;
  margin-bottom: 12px;                 /* room for the badge hanging off it */
  padding: 14px 16px 22px;
  text-align: center;
  background: var(--accent);
  border: 2px solid var(--accent);
  border-radius: var(--r-panel);
  box-shadow: var(--hard);
  color: var(--bg);
}
.plate-cap {
  display: block;
  font-size: 10.5px; font-weight: 700;
  letter-spacing: 0.2em; text-transform: uppercase;
  opacity: .72;
}
.plate-n {
  display: block;
  font-family: var(--f-display); font-weight: 400;
  font-size: 76px; line-height: .96;
  letter-spacing: 0.01em;
  margin: 4px 0 2px;
}
.plate-u {
  display: block;
  font-size: 11px; font-weight: 700;
  letter-spacing: 0.24em; text-transform: uppercase;
  opacity: .72;
}
.plate-tag {
  position: absolute; left: 50%; bottom: -13px;
  transform: translateX(-50%);
  box-shadow: var(--hard);
}

/* ── THE LAUNCH WINDOW ───────────────────────────────────────────────────────
   The one module this game earns. A swell rolls past a fixed launch line at
   the tempo the machine actually runs it; the striped band is water that will
   carry a stone; the lamp fires the instant a crest sits on the line.

   Three animations, all pure transform or opacity, all started together so
   they stay in phase: the strip crosses exactly one tile (300 user units, one
   container width) every 3.2s, which is three crests, so the bulb and the
   lamp each run on a 3.2/3 = 1.0667s cycle with the crest at 0%.
   ───────────────────────────────────────────────────────────────────────── */

.win {
  flex: none;
  padding: 13px 13px 12px;
  background: var(--surface);
  border: var(--key);
  border-radius: var(--r-panel);
  box-shadow: var(--hard);
}
.win-head {
  display: flex; align-items: center; gap: 10px;
  margin-bottom: 10px;
}
.win-head b {
  flex: 1; min-width: 0;
  font-size: 11px; font-weight: 700;
  letter-spacing: 0.18em; text-transform: uppercase;
  color: var(--ink-2);
}
/* The foam lamp. Lit by default, so with motion off it reads as the answer. */
.win-lamp {
  background: var(--accent); border-color: var(--accent); color: var(--bg);
  animation: lamp 1.0667s linear infinite;
}
@keyframes lamp {
  0%, 9%     { opacity: 1; }
  23%, 100%  { opacity: .22; }
}

.win-box {
  position: relative;
  height: 96px;                        /* 1:1 with the viewBox, so the bulb
                                          can be placed in plain pixels */
  border-radius: var(--r-bar);
  background: var(--bg);
  border: 2px solid var(--line);
  overflow: hidden;
}
.win-strip {
  position: absolute; top: 0; left: 0; bottom: 0;
  width: 200%;
  animation: sea-run 3.2s linear infinite;
}
@keyframes sea-run { to { transform: translateX(-50%); } }

.win-sea { display: block; width: 100%; height: 100%; }
.win-band { fill: var(--accent); opacity: .15; }
.win-fill { fill: var(--tint); }
.win-line { fill: none; stroke: var(--accent-d); stroke-width: 3; }

/* The launch line, fixed. Everything else moves past it. */
.win-mark {
  position: absolute; top: 0; bottom: 0; left: 50%;
  width: 2px; margin-left: -1px;
  background: repeating-linear-gradient(var(--ink) 0 5px, transparent 5px 10px);
  opacity: .55;
}
/* The stone riding the swell. Parked on the crest when motion is off. */
.win-bulb {
  position: absolute; top: 0; left: 50%;
  width: 13px; height: 13px; margin: -6px 0 0 -6px;
  border-radius: 999px;
  background: var(--ink);
  box-shadow: 0 0 0 3px rgba(25, 227, 196, .35);
  transform: translateY(28px);
  animation: ride 1.0667s linear infinite;
}
/* y = 48 - 20cos(2π t), sampled every 30 degrees: the crest at 0%. */
@keyframes ride {
  0%     { transform: translateY(28px); }
  8.33%  { transform: translateY(30.7px); }
  16.67% { transform: translateY(38px); }
  25%    { transform: translateY(48px); }
  33.33% { transform: translateY(58px); }
  41.67% { transform: translateY(65.3px); }
  50%    { transform: translateY(68px); }
  58.33% { transform: translateY(65.3px); }
  66.67% { transform: translateY(58px); }
  75%    { transform: translateY(48px); }
  83.33% { transform: translateY(38px); }
  91.67% { transform: translateY(30.7px); }
  100%   { transform: translateY(28px); }
}

.win-foot {
  display: flex; justify-content: space-between; gap: 10px;
  margin-top: 9px;
  font-size: 10px; font-weight: 700;
  letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--ink-3);
}
.win-pay { color: var(--bulb); }

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

.playkey {
  flex: none;
  display: block; width: 100%;
  padding: 16px 18px 18px;
  text-align: center;
  background: var(--bulb);
  border: 2px solid var(--bulb);
  border-radius: var(--r-panel);
  color: var(--bg);
}
.playkey b {
  display: block;
  font-family: var(--f-display); font-weight: 400;
  font-size: 42px; line-height: 1;
  letter-spacing: 0.08em; text-indent: 0.08em;
}
.playkey i {
  display: block; margin-top: 6px;
  font-style: normal;
  font-size: 10.5px; font-weight: 700;
  letter-spacing: 0.16em; text-transform: uppercase;
  opacity: .74;
}

/* ── the counters: a row of stamped badges, not a grid of tiles ──────────── */

.ctrs { display: flex; flex-wrap: wrap; gap: 8px; }
.ctr {
  display: inline-flex; align-items: baseline; gap: 7px;
  padding: 7px 13px;
  border-radius: 999px;
  background: var(--tint);
  border: 2px solid var(--line);
  color: var(--ink-3);
  font-size: 10px; font-weight: 700;
  letter-spacing: 0.16em; text-transform: uppercase;
}
.ctr b {
  font-family: var(--f-display); font-weight: 400;
  font-size: 15px; letter-spacing: 0;
  color: var(--ink);
}

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

.tgt {
  padding: 13px 14px 14px;
  background: var(--surface);
  border: var(--key);
  border-radius: var(--r-panel);
  box-shadow: var(--hard);
}
.tgt-top { display: flex; align-items: center; gap: 10px; }
.tgt-top .cap { flex: 1; min-width: 0; letter-spacing: 0.1em; color: var(--ink-2); }
.tgt-state.is-done { background: var(--good); border-color: var(--good); color: var(--bg); }

.rail {
  height: 12px; margin: 11px 0 8px;
  background: var(--tint);
  border: 2px solid var(--line);
  border-radius: var(--r-bar);
  overflow: hidden;
}
.rail > i {
  display: block; height: 100%; width: 0;
  background: var(--accent);
  transition: width 260ms var(--e);
}
.tgt-v {
  display: block;
  font-family: var(--f-display); font-weight: 400;
  font-size: 13px; color: var(--accent-d);
}

/* ── the optional offer, which this build never shows ────────────────────── */

.offer {
  display: flex; align-items: center; gap: 12px;
  padding: 12px 13px;
  background: var(--surface);
  border: var(--key);
  border-radius: var(--r-panel);
  box-shadow: var(--hard);
}
.offer-tx { display: flex; flex-direction: column; margin-right: auto; min-width: 0; }
.offer-tx b { font-size: 13px; font-weight: 700; letter-spacing: 0.04em; text-transform: uppercase; }
.offer-tx i { font-style: normal; font-size: 11.5px; font-weight: 500; color: var(--ink-3); }
.offer-tx i span:empty { display: none; }

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

/* Keys first, on the side the thumb already is; the count printed large on
   the right where nothing overlaps it. */
.bez {
  flex: none;
  display: flex; align-items: center; gap: 8px;
}
.bez .ctrlsq { width: 44px; height: 44px; }
.bez-sc { margin-left: auto; text-align: right; line-height: 1; }
.bez-n {
  display: block;
  font-family: var(--f-display); font-weight: 400;
  font-size: 40px; line-height: .94;
  color: var(--accent);
}
.bez-sc i {
  display: block; margin-top: 4px;
  font-style: normal;
  font-size: 10px; font-weight: 700;
  letter-spacing: 0.2em; text-transform: uppercase;
  color: var(--ink-3);
}

.combo {
  display: inline-flex; align-items: center;
  padding: 5px 11px;
  border-radius: 999px;
  background: var(--bulb); color: var(--bg);
  font-family: var(--f-display); font-weight: 400;
  font-size: 14px;
  opacity: 0; transform: scale(.8);
  transition: opacity var(--t), transform var(--t);
}
.combo.is-on { opacity: 1; transform: scale(1); }
.buoy {
  display: inline-flex; align-items: center; gap: 5px;
  padding: 5px 11px;
  border-radius: 999px;
  background: var(--tint); border: 2px solid var(--line);
  color: var(--accent-d);
  font-size: 10px; font-weight: 700;
  letter-spacing: 0.14em; text-transform: uppercase;
}

/* ── the swell gauge ─────────────────────────────────────────────────────────
   It carries the same number the game scores: the height of the water under
   the stone. The striped section is water that will carry a stone at some
   point in the run, and the tick at the far end is the true crest. Fill the
   bar into the stripes and tap. The rule of the game, printed instead of
   written down. */
.gauge { flex: none; margin: 4px 0 2px; }
.gauge .cap { font-size: 10px; letter-spacing: 0.2em; }
.gauge-t {
  position: relative;
  height: 16px; margin-top: 7px;
  background: var(--tint);
  border: 2px solid var(--line);
  border-radius: var(--r-bar);
}
.gauge-f {
  position: relative; z-index: 1;
  display: block; height: 100%; width: 0;
  background: var(--accent);
  border-radius: 1px 0 0 7px;
  transition: background var(--t);
}
.gauge-f.is-low { background: var(--warn); }
/* the water that carries */
.gauge-t::before {
  content: ""; position: absolute; z-index: 2;
  top: 0; bottom: 0; left: 57%; right: 0;
  border-left: 2px solid var(--ink-3);
  background-image: repeating-linear-gradient(112deg,
    rgba(242, 250, 255, .20) 0 3px, transparent 3px 8px);
  pointer-events: none;
}
/* the crest itself */
.gauge-t::after {
  content: ""; position: absolute; z-index: 2;
  top: -4px; bottom: -4px; left: 93%;
  width: 3px;
  background: var(--ink);
  pointer-events: none;
}

/* ── the screen ──────────────────────────────────────────────────────────── */

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

/* The attract screen. Deliberately not blurred: the sea keeps rolling behind
   it, so the player has watched a swell rise and break before they launch. */
.attract {
  position: absolute; inset: 0;
  display: flex; align-items: center; justify-content: center;
  padding: 16px;
  overflow-y: auto;
  background: rgba(5, 10, 28, .82);
}
.attract-in { width: 100%; max-width: 330px; }
.attract-t {
  display: block; margin-bottom: 14px;
  text-align: center;
  font-family: var(--f-display); font-weight: 400;
  font-size: 24px; letter-spacing: 0.04em;
  color: var(--accent);
}
.steps { list-style: none; margin: 0 0 16px; padding: 0; display: grid; gap: 10px; }
.step {
  display: flex; align-items: flex-start; gap: 12px;
  padding: 11px 13px;
  background: var(--surface);
  border: var(--key);
  border-radius: var(--r-key);
  box-shadow: var(--hard);
}
.step-n {
  flex: none;
  width: 30px; height: 30px;
  display: grid; place-items: center;
  border-radius: var(--r-sq);
  background: var(--bulb); color: var(--bg);
  font-family: var(--f-display); font-weight: 400;
  font-size: 15px; line-height: 1;
}
.step-tx { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.step-tx b { font-size: 12.5px; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase; }
.step-tx i { font-style: normal; font-size: 12.5px; font-weight: 500; color: var(--ink-2); line-height: 1.45; }

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

.seg { display: flex; gap: 10px; }
.seg-btn {
  flex: 1;
  display: inline-flex; align-items: center; justify-content: center; gap: 7px;
  padding: 12px 10px;
  border-radius: var(--r-key);
  border: 2px solid var(--line);
  background: var(--tint);
  color: var(--ink-3);
  font-size: 11px; font-weight: 700;
  letter-spacing: 0.16em; text-transform: uppercase;
}
.seg-btn.is-on { background: var(--accent); border-color: var(--accent); color: var(--bg); }

/* A stencilled plaque instead of a heading: it names the plate below it. */
.plaque {
  display: flex; align-items: baseline; gap: 10px;
  margin-bottom: -6px;
  font-size: 10.5px; font-weight: 700;
  letter-spacing: 0.18em; text-transform: uppercase;
  color: var(--ink-3);
}
.plaque span { flex: 1; min-width: 0; }
.plaque b { color: var(--bulb); }

.board {
  background: var(--surface);
  border: var(--key);
  border-radius: var(--r-panel);
  box-shadow: var(--hard);
  overflow: hidden;
}
.rw {
  display: grid;
  grid-template-columns: 30px 32px 1fr auto;
  align-items: center; gap: 11px;
  padding: 10px 13px;
  border-bottom: 2px solid var(--line);
}
.rw:last-child { border-bottom: 0; }
.rw--me { background: var(--tint); }
.rw-pos {
  font-family: var(--f-display); font-weight: 400;
  font-size: 14px; color: var(--ink-3);
}
.rw--top .rw-pos { color: var(--bulb); }
/* An initials token, not an avatar. shell.js hands each row a hue, but this
   machine is silkscreened in two inks and a rainbow of discs would break it,
   so the hue is ignored and STANDING is what colours the token instead. */
.rw-av {
  width: 32px; height: 32px;
  display: grid; place-items: center;
  border-radius: var(--r-sq);
  background: var(--tint-2);
  border: 2px solid var(--line);
  color: var(--ink);
  font-size: 12.5px; font-weight: 700;
}
.rw--top .rw-av { background: var(--bulb); border-color: var(--bulb); color: var(--bg); }
.rw--me  .rw-av { background: var(--accent); border-color: var(--accent); color: var(--bg); }
.rw-nm {
  min-width: 0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
  font-size: 12.5px; font-weight: 700;
  letter-spacing: 0.08em; text-transform: uppercase;
}
.rw-sc {
  font-family: var(--f-display); font-weight: 400;
  font-size: 15px; color: var(--accent);
}
.rw--me .rw-sc { color: var(--bulb); }

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

.rows {
  background: var(--surface);
  border: var(--key);
  border-radius: var(--r-panel);
  box-shadow: var(--hard);
  overflow: hidden;
}
.row {
  width: 100%;
  display: flex; align-items: center; gap: 13px;
  padding: 14px 14px;
  border-bottom: 2px solid var(--line);
  color: var(--ink);
  font-size: 13px; font-weight: 600;
  text-align: left;
}
.row:last-child { border-bottom: 0; }
.row > .ico:first-child { color: var(--accent); }
.row > span { flex: 1; min-width: 0; }
.row .chev { width: 17px; height: 17px; color: var(--ink-3); }
/* The rows sit inside a plate, so they depress without their own shadow. */
.rows .push { box-shadow: none; }
.rows .push:active { transform: none; background: var(--tint); }

/* ── the settings switches: a rocker, not a pill ─────────────────────────── */

.sw {
  appearance: none; -webkit-appearance: none;
  position: relative; flex: none;
  width: 52px; height: 30px; margin: 0;
  background: var(--tint);
  border: 2px solid var(--line);
  border-radius: var(--r-sq);
  box-shadow: inset 2px 2px 0 rgba(0, 0, 0, .34);
  transition: background var(--t), border-color var(--t);
}
.sw::after {
  content: ""; position: absolute; top: 2px; left: 2px;
  width: 22px; height: 22px;
  background: var(--ink-3);
  border-radius: 3px 3px 8px 8px;
  transition: transform var(--t), background var(--t);
}
.sw:checked { background: var(--tint-2); border-color: var(--accent); }
.sw:checked::after { transform: translateX(22px); background: var(--accent); }

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

.scrim { position: fixed; inset: 0; z-index: 40; background: rgba(1, 5, 14, .74); }

.sheet {
  position: fixed; z-index: 50;
  left: 10px; right: 10px;
  bottom: calc(10px + max(var(--tg-safe-bottom), env(safe-area-inset-bottom, 0px)));
  display: flex; flex-direction: column;
  max-height: calc(100dvh - max(var(--tg-safe-top), env(safe-area-inset-top, 0px)) - 24px);
  background: var(--surface);
  border: var(--key);
  border-radius: var(--r-panel);
  box-shadow: var(--hard);
  /* 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, and if
     a client throttles animations it stays there. The sheet just appears. */
}
.sheet-head {
  flex: none;
  display: flex; align-items: center; gap: 12px;
  padding: 13px 13px 12px;
  border-bottom: 2px solid var(--line);
}
.sheet-head .chip--lg { width: 42px; height: 42px; }
.sheet-head .chip--lg .ico { width: 23px; height: 23px; }
.sheet-head b {
  flex: 1; min-width: 0;
  font-family: var(--f-display); font-weight: 400;
  font-size: 17px; letter-spacing: 0.03em;
}
.sheet-head .ctrlsq { width: 42px; height: 42px; }
.sheet-body {
  flex: 1; min-height: 0;
  overflow-y: auto;
  padding: 14px 16px 4px;
  font-size: 13.5px; line-height: 1.55;
  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);
  border-radius: 2px 2px 4px 4px;
}
.sheet-body b { font-weight: 700; color: var(--ink); }
.sheet-foot { flex: none; padding: 12px 16px 16px; 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;
}
.card {
  pointer-events: auto;
  width: 100%; max-width: 330px;
  padding: 18px 16px 16px;
  text-align: center;
  background: var(--surface);
  border: var(--key);
  border-radius: var(--r-panel);
  box-shadow: var(--hard);
  animation: bolt-on 200ms var(--e);
}
.card-tag { margin-bottom: 10px; }
.card-tag--warn { background: var(--warn); border-color: var(--warn); color: var(--bg); }
.card-n {
  display: block;
  font-family: var(--f-display); font-weight: 400;
  font-size: 62px; line-height: .96;
  color: var(--accent);
}
.card-u {
  display: block; margin-top: 2px;
  font-size: 10.5px; font-weight: 700;
  letter-spacing: 0.24em; text-transform: uppercase;
  color: var(--ink-3);
}
.card-t {
  display: block; margin: 4px 0 6px;
  font-family: var(--f-display); font-weight: 400;
  font-size: 30px; letter-spacing: 0.05em;
}
.card-sub {
  display: block; margin: 8px 0 0;
  font-size: 12.5px; font-weight: 500; line-height: 1.5;
  color: var(--ink-2);
}
.card .ctrl { margin-top: 12px; }
.card-btns { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin-top: 14px; }
.card-btns .ctrl { margin-top: 0; padding: 13px 8px; font-size: 11px; gap: 7px; }

/* The three-count before a continue: a coin dropping into the slot. */
.count {
  position: fixed; inset: 0; z-index: 60;
  display: grid; place-items: center;
  pointer-events: none;
}
.count span {
  display: grid; place-items: center;
  width: 128px; height: 128px;
  background: var(--accent);
  border: 2px solid var(--accent);
  border-radius: var(--r-panel);
  box-shadow: var(--hard);
  color: var(--bg);
  font-family: var(--f-display); font-weight: 400;
  font-size: 72px; line-height: 1;
  animation: slam 200ms var(--e);
}
@keyframes slam {
  from { transform: scale(.8) translateY(-10px); opacity: 0; }
  to   { transform: none; opacity: 1; }
}

.toast {
  position: fixed; z-index: 70;
  left: 16px; right: 16px;
  bottom: calc(96px + max(var(--tg-safe-bottom), env(safe-area-inset-bottom, 0px)));
  padding: 13px 18px;
  text-align: center;
  background: var(--ink);
  border: 2px solid var(--ink);
  border-radius: var(--r-key);
  box-shadow: var(--hard);
  color: var(--bg);
  font-size: 12.5px; font-weight: 700;
  letter-spacing: 0.06em;
}

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

.roll { display: block; }
.roll.is-rolling { animation: roll-up 180ms var(--e); }
@keyframes roll-up {
  from { transform: translateY(0.30em); opacity: 0; }
  to   { transform: none; opacity: 1; }
}

/* ── reduce motion: the machine stops, and stops on the useful frame ─────── */

[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) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
  }
  .boot-badge, .boot-word, .boot-tag { opacity: 1; transform: none; }
  /* The launch window parks with a crest on the line and the lamp lit, which
     is the single frame that says what the game wants. */
  .win-strip { transform: none; }
  .win-bulb { transform: translateY(28px); }
  .win-lamp { opacity: 1; }
}

/* ── short phones: the plate and the key give first ──────────────────────── */

@media (max-height: 700px) {
  .scr { gap: 12px; }
  .plate { padding: 11px 16px 18px; }
  .plate-n { font-size: 58px; }
  .playkey { padding: 13px 18px 14px; }
  .playkey b { font-size: 34px; }
  .marq { padding: 17px 16px 13px; }
  .marq-word { font-size: 25px; }
  .bez-n { font-size: 34px; }
  .step { padding: 9px 11px; }
}
