/* ═══════════════════════════════════════════════════════════════════════════
   CIRRUS DROP — HIGH ALTITUDE AT DUSK

   One idea, held everywhere: you are very high up, very late in the day. A deep
   indigo-violet sky, panels lifted out of it like haze catching the last light,
   one soft violet accent, cool off-white ink. Nothing is loud. The game is
   calm, so the chrome around it is calm too.

   Rules this sheet keeps, without exception:
     · Radius is 16 (buttons, chips, tiles), 24 (cards, sheets) or 999 (pills).
       Nothing else, and never 0. Rounder than a mineral world, because clouds.
     · ONE shadow, --sh, and it is violet-tinted, not neutral grey. A light
       source at dusk does not cast a black shadow.
     · Violet is a fill or a large glyph. Small violet TEXT is --accent-d, which
       clears 4.5:1 on --bg and --tint. On violet FILLS, text is --bg.
     · Motion is 200ms cubic-bezier(.2,.8,.3,1); press is scale(.97). Entrances
       are a staggered fade-up, never a slide from off-screen.
   ═══════════════════════════════════════════════════════════════════════════ */

: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:       #0F0A1C;
  --surface:  #191230;
  --tint:     #241A42;
  --tint-2:   #31245A;
  --line:     #3E2F6B;
  --ink:      #EFE9FB;
  --ink-2:    #B0A4CE;
  --ink-3:    #8B7FAB;
  --accent:   #A78BFA;
  --accent-d: #C4B2FD;
  --good:     #6EE7B7;
  --warn:     #FB7185;

  /* A soft optical serif against a calm humanist grotesque. The serif is the
     one thing here nobody expects in a game HUD, and it is what stops this
     reading as a template: dusk light wants a face with some warmth in it. */
  --f-display: "Fraunces", "Iowan Old Style", Georgia, serif;
  --f-text: "Manrope", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;

  --r: 16px;          /* buttons, chips, tiles */
  --r-lg: 24px;       /* cards, sheets, the canvas */
  --edge: 1.5px solid var(--line);
  --sh: 0 1px 2px rgba(8, 4, 22, .5), 0 16px 34px -16px rgba(70, 44, 140, .68);
  --t: 200ms cubic-bezier(.2, .8, .3, 1);
  --nav-h: 60px;
}

/* Every figure that changes on screen holds its column, so a fast-ticking
   altimeter never jitters its own layout. */
.bignum, .hero-num, .hud-score b, .fig b, .daily-v, .rw-sc, .prog-n b,
.revive span, .rw-pos {
  font-variant-numeric: tabular-nums;
  font-feature-settings: "tnum" 1;
}

*, *::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: 15px;
  line-height: 1.45;
  -webkit-font-smoothing: antialiased;
}

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

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

/* ── icons ───────────────────────────────────────────────────────────────── */

.ic {
  display: block; flex: none;
  width: 24px; height: 24px;
  fill: none;
  stroke: currentColor;
  stroke-width: 1.75;
  stroke-linecap: round;
  stroke-linejoin: round;
}
.ic-s { width: 18px; height: 18px; stroke-width: 1.9; }

/* 40px tinted chip: the icon on every card header. */
.chip {
  width: 40px; height: 40px; flex: none;
  display: grid; place-items: center;
  background: var(--tint);
  border-radius: var(--r);
  color: var(--accent-d);
}
.chip--sm { width: 34px; height: 34px; }
.chip--lg { width: 52px; height: 52px; }
.chip--lg .ic { width: 28px; height: 28px; }

/* ── containers: four roles, no new shapes ───────────────────────────────── */

.card {
  background: var(--surface);
  border: var(--edge);
  border-radius: var(--r-lg);
  box-shadow: var(--sh);
  padding: 16px;
  margin-bottom: 12px;
}
.card.is-feature { background: var(--tint); box-shadow: none; }
.card.is-outline { background: none; box-shadow: none; }

.cardhead { display: flex; align-items: center; gap: 12px; }
.ht { display: flex; flex-direction: column; min-width: 0; margin-right: auto; }
.h-t { font-size: 15px; font-weight: 700; letter-spacing: -0.01em; }
.h-s { font-style: normal; font-size: 12.5px; font-weight: 500; color: var(--ink-2); margin-top: 1px; }

/* ── type ────────────────────────────────────────────────────────────────── */

.lbl {
  display: block;
  font-size: 10.5px; font-weight: 700;
  letter-spacing: 0.12em; text-transform: uppercase;
  color: var(--ink-2);
  font-style: normal;
}

.bignum {
  font-family: var(--f-display);
  font-size: clamp(64px, 21vw, 78px);
  font-weight: 700;
  letter-spacing: -0.04em;
  font-variant-numeric: tabular-nums;
  line-height: 1;
  margin: 12px 0 2px;
}
.bignum--mid { font-size: 60px; margin: 6px 0 2px; }

.lede {
  margin: 2px 2px 14px;
  font-size: 14.5px; line-height: 1.5;
  color: var(--ink-2);
}
.note { margin: 12px 0; font-size: 13.5px; line-height: 1.5; color: var(--ink-2); }
.sub  { margin: 6px 0 0; font-size: 13.5px; color: var(--ink-2); }
.footnote {
  margin: 4px 4px 6px;
  font-size: 12px; line-height: 1.5;
  color: var(--ink-3);
}

/* ── pills ───────────────────────────────────────────────────────────────── */

.pill {
  display: inline-flex; align-items: center; gap: 5px;
  background: var(--tint-2);
  color: var(--accent-d);
  border-radius: 999px;
  padding: 5px 11px;
  font-size: 11.5px; font-weight: 700;
  letter-spacing: 0.01em;
  white-space: nowrap;
}
.pill--rank { background: var(--surface); border: var(--edge); }
.pill--quiet { background: none; color: var(--ink-2); padding: 5px 0; }
.pill--quiet:empty { display: none; }
.pill--big { font-size: 13px; padding: 6px 14px; margin-top: 10px; }
.pill.is-done { background: rgba(110, 231, 183, .13); color: var(--good); }

/* ── progress track ──────────────────────────────────────────────────────── */

.track {
  height: 10px;
  background: var(--tint);
  border-radius: 999px;
  overflow: hidden;
  margin-top: 14px;
}
.track .fill {
  display: block; height: 100%; width: 0;
  border-radius: 999px;
  background: var(--accent);
  transition: width var(--t), background var(--t);
}
.track .fill.is-low { background: var(--warn); }

.prog { display: flex; justify-content: space-between; gap: 12px; margin-top: 10px; }
.prog-n { display: flex; flex-direction: column; }
.prog-n--end { text-align: right; }
.prog-n b {
  font-family: var(--f-display);
  font-size: 20px; font-weight: 700; line-height: 1.15;
  font-variant-numeric: tabular-nums;
}
.prog-n i {
  font-style: normal; font-size: 11px; font-weight: 600;
  letter-spacing: 0.06em; text-transform: uppercase; color: var(--ink-2);
  margin-top: 2px;
}

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

.btn {
  display: flex; align-items: center; justify-content: center; gap: 9px;
  width: 100%;
  border-radius: var(--r);
  padding: 14px 16px;
  font-size: 14.5px; font-weight: 700;
  letter-spacing: -0.005em;
  text-align: left;
}
/* Dark ground-colour type on the violet fill: --bg on --accent clears ~7:1.
   Off-white would wash out on it, the fill is light, so the text is dark. */
/* Colored glow shadow: the button throws its own violet, not a grey smudge. */
.btn--accent { background: var(--accent); color: var(--bg); box-shadow: 0 1px 2px rgba(8, 4, 22, .5), 0 14px 30px -14px rgba(167, 139, 250, .78); }
.btn--soft { background: var(--tint); color: var(--accent-d); border: var(--edge); }
.btn--outline { background: var(--surface); color: var(--ink); border: var(--edge); }
.btn:disabled { opacity: .5; }

.press { transition: transform var(--t), box-shadow var(--t), background var(--t); }
.press:active { transform: scale(.97); }

.btn--play { padding: 15px 16px; margin-bottom: 12px; }
.btn-ic {
  width: 40px; height: 40px; flex: none;
  display: grid; place-items: center;
  background: rgba(255, 255, 255, .30);
  border-radius: var(--r);
}
.btn-tx { display: flex; flex-direction: column; margin-right: auto; }
.btn-tx b { font-family: var(--f-display); font-size: 22px; font-weight: 700; line-height: 1.1; }
.btn-tx i { font-style: normal; font-size: 12.5px; font-weight: 600; opacity: .82; margin-top: 2px; }
.btn-ch { opacity: .65; }

.btn--ad { align-items: flex-start; text-align: left; margin-top: 10px; }
.ad-tx { display: flex; flex-direction: column; gap: 3px; }
.ad-tx b { font-size: 14px; font-weight: 700; }
.ad-tx i { font-style: normal; font-size: 11.5px; font-weight: 600; color: var(--ink-2); }
.ad-tx i:empty { display: none; }

.iconbtn {
  width: 40px; height: 40px; flex: none;
  display: grid; place-items: center;
  background: var(--surface);
  border: var(--edge);
  border-radius: var(--r);
  color: var(--ink);
}

/* ── splash ──────────────────────────────────────────────────────────────── */

#splash {
  position: fixed; inset: 0; z-index: 90;
  background: var(--bg);
  display: flex; flex-direction: column;
  align-items: center; justify-content: center;
  gap: 4px;
  transition: opacity 200ms cubic-bezier(.2, .8, .3, 1);
}
#splash.out { opacity: 0; }
.sp-mark {
  position: relative;
  width: 74px; height: 74px;
  display: grid; place-items: center;
  background: var(--tint);
  border: var(--edge);
  border-radius: var(--r-lg);
  box-shadow: var(--sh);
  color: var(--accent-d);
  margin-bottom: 16px;
}
/* Breathing glow halo: a separate blurred layer, so the pulse animates opacity
   and scale only and never the mark's own shadow. */
.sp-mark::after {
  content: ""; position: absolute; inset: -34%;
  border-radius: 999px;
  background: radial-gradient(closest-side, rgba(167, 139, 250, .55), transparent 72%);
  filter: blur(10px);
  z-index: -1;
  animation: halo 3.4s ease-in-out infinite;
}
@keyframes halo {
  0%, 100% { opacity: .45; transform: scale(.94); }
  50%      { opacity: .95; transform: scale(1.08); }
}
.sp-mark .ic { width: 36px; height: 36px; }
.sp-name {
  font-family: var(--f-display);
  font-size: 34px; font-weight: 600; letter-spacing: -0.02em;
  animation: rise-in 520ms cubic-bezier(.2, .8, .3, 1) both;
}
.sp-sub {
  font-size: 13px; font-weight: 600; color: var(--ink-2);
  animation: rise-in 520ms cubic-bezier(.2, .8, .3, 1) 90ms both;
}

/* The one entrance gesture in the app: a few pixels up, fading in. Used for
   the splash line and for each block of a screen as it becomes active. */
@keyframes rise-in {
  from { opacity: 0; transform: translateY(8px); }
  to   { opacity: 1; transform: none; }
}

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

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

/* ── the sky behind everything ────────────────────────────────────────────────
   Three large soft glows over the ground colour: a warm plum where the sun
   just went, a cool violet high up, a faint one low. A flat fill would read
   as a dark box; this reads as air. It is one static layer plus one very slow
   drift — the entire ambient motion budget of the app, spent here. */
#app::before {
  content: ""; position: absolute; inset: -20% -10%;
  pointer-events: none; z-index: 0;
  background:
    radial-gradient(52% 34% at 72% 6%,  rgba(167, 139, 250, .20), transparent 70%),
    radial-gradient(60% 30% at 18% 24%, rgba(196, 122, 190, .13), transparent 72%),
    radial-gradient(70% 38% at 50% 96%, rgba(120, 92, 220, .11), transparent 74%);
  animation: sky-drift 74s ease-in-out infinite alternate;
}
@keyframes sky-drift {
  from { transform: translate3d(-2%, -1.5%, 0) scale(1); }
  to   { transform: translate3d(2.5%, 2%, 0) scale(1.08); }
}
/* Everything real sits above the sky. */
.topbar, main, .navbar { position: relative; z-index: 1; }

/* The top element carries the fullscreen top inset — the whole chrome band is
   reserved here so the brand line clears Telegram's floating Close / ⋯ row. */
.topbar {
  flex: none;
  padding-top: max(var(--tg-safe-top), env(safe-area-inset-top, 0px));
}
/* Fullscreen already reserves the chrome inset; trim a cosmetic sliver so the
   brand line does not read as a gap, floored at the inset itself. */
[data-fullscreen="1"] .topbar {
  padding-top: max(var(--tg-safe-top),
    calc(max(var(--tg-safe-top), env(safe-area-inset-top, 0px)) - 1.4vh));
}
.brandline {
  display: flex; align-items: center; gap: 9px;
  padding: 11px 16px 9px;
}
.mark {
  width: 30px; height: 30px; flex: none;
  display: grid; place-items: center;
  background: var(--tint);
  border-radius: 9px;
  color: var(--accent-d);
}
.mark .ic { width: 18px; height: 18px; }
.wordmark {
  font-family: var(--f-display);
  font-size: 18px; font-weight: 700; letter-spacing: -0.02em;
}
/* Rank badge on the right of the brand bar. shell.js writes every
   [data-rank-badge], so this stays in sync with the home hero. */
.brand-rank {
  margin-left: auto;
  display: inline-flex; align-items: center; gap: 5px;
  color: var(--accent-d);
  font-size: 12px; font-weight: 700;
}

/* ── bottom nav bar: the four tabs, standard mobile position ──────────────────
   A flex-column child of #app, so it pins to the bottom of the fixed viewport
   above the scrolling content (no overlap, no content padding needed). Icon
   above a short label; active tab wears an accent pill. Pads the bottom inset. */
.navbar {
  flex: none;
  display: flex;
  padding: 6px 8px;
  padding-bottom: calc(6px + max(var(--tg-safe-bottom), env(safe-area-inset-bottom, 0px)));
  border-top: 1px solid var(--line);
  background: var(--surface);
}
.navtab {
  flex: 1; position: relative;
  display: flex; flex-direction: column; align-items: center; gap: 3px;
  padding: 7px 4px 6px;
  border-radius: var(--r);
  color: var(--ink-3);
  font-size: 10.5px; font-weight: 700;
  letter-spacing: 0.04em;
  transition: color var(--t), background var(--t);
}
.navtab .ic { width: 22px; height: 22px; }
.navtab.is-on { color: var(--accent-d); background: var(--tint); }

/* Play is the game and nothing else — the top brand bar and bottom nav both
   step aside so the game owns the screen. */
[data-screen="play"] .topbar,
[data-screen="play"] .navbar { display: none; }

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

.screen {
  position: absolute; inset: 0;
  display: none;
  flex-direction: column;
  overflow-y: auto;
  padding: 8px 14px 20px;
}
.screen.is-active { display: flex; }
.screen.play { overflow: hidden; padding: 4px 12px 8px; }

/* Staggered fade-up reveal. Toggling display re-runs it, so every tab change
   gets the same short cascade instead of a hard cut. Capped at six steps and
   160ms of delay so it never feels like waiting. */
.screen.is-active > * { animation: rise-in 320ms cubic-bezier(.2, .8, .3, 1) both; }
.screen.is-active > *:nth-child(1) { animation-delay: 0ms; }
.screen.is-active > *:nth-child(2) { animation-delay: 24ms; }
.screen.is-active > *:nth-child(3) { animation-delay: 48ms; }
.screen.is-active > *:nth-child(4) { animation-delay: 72ms; }
.screen.is-active > *:nth-child(5) { animation-delay: 96ms; }
.screen.is-active > *:nth-child(n+6) { animation-delay: 120ms; }
/* The play screen is the exception: the canvas must be live on frame one. */
.screen.play > * { animation: none; }

/* ── home (HUD) ────────────────────────────────────────────────────────────── */

/* Thin hairline rule between console sections — no filled cards. */
.rule { height: 1px; background: var(--line); margin: 16px 2px; }

/* Bare hero: the record as a raw number, not wrapped in a card. */
.hero { margin: 8px 2px 0; }
.hero-num {
  font-family: var(--f-display);
  font-size: clamp(66px, 23vw, 92px);
  font-weight: 700; letter-spacing: -0.045em; line-height: 0.9;
  font-variant-numeric: tabular-nums;
}
.hero-meta { display: flex; align-items: center; gap: 10px; margin-top: 8px; }
.hero-meta .lbl { margin-right: auto; }
.rankline {
  display: inline-flex; align-items: center; gap: 5px;
  color: var(--accent-d);
  font-size: 12.5px; font-weight: 700;
}

/* Stats as one inline row, thin vertical dividers between figures. */
.figrow { display: flex; margin: 0 2px; }
.fig {
  flex: 1; position: relative;
  display: flex; flex-direction: column; gap: 2px;
  padding: 0 14px;
}
.fig:first-child { padding-left: 0; }
.fig:last-child { padding-right: 0; }
.fig + .fig::before {
  content: ""; position: absolute; left: 0; top: 3px; bottom: 3px; width: 1px;
  background: var(--line);
}
.fig b {
  font-family: var(--f-display);
  font-size: 25px; font-weight: 700; line-height: 1.1;
  font-variant-numeric: tabular-nums;
}
.fig span {
  font-size: 10px; font-weight: 700;
  letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--ink-2);
}

/* Daily challenge: one slim strip — label + state + inline bar + value. */
.daily { display: flex; align-items: center; gap: 10px; margin: 0 2px; }
.daily-l {
  min-width: 0; flex-shrink: 1;
  font-size: 12.5px; font-weight: 600; color: var(--ink-2);
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.daily-state {
  flex: none;
  font-size: 10px; font-weight: 700; letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--ink-3);
}
.daily-state.is-done { color: var(--good); }
.daily-bar {
  flex: 1; min-width: 40px; height: 6px;
  background: var(--tint); border-radius: 999px; overflow: hidden;
}
.daily-bar i {
  display: block; height: 100%; width: 0;
  background: var(--accent);
  transition: width var(--t), background var(--t);
}
.daily-v {
  flex: none;
  font-family: var(--f-display);
  font-size: 14px; font-weight: 700; font-variant-numeric: tabular-nums;
}

/* Boost offer: a slim inline strip, not a padded card. */
.offer-row { display: flex; align-items: center; gap: 11px; margin: 0 2px; }
.offer-tx { display: flex; flex-direction: column; margin-right: auto; min-width: 0; }
.offer-tx b { font-size: 14px; font-weight: 700; }
.offer-tx i { font-style: normal; font-size: 11.5px; font-weight: 600; color: var(--ink-2); }
.offer-tx i span:empty { display: none; }

/* ── play ────────────────────────────────────────────────────────────────── */

.hud {
  flex: none;
  display: flex; align-items: center; gap: 10px;
  padding: 4px 2px 0;
  padding-top: calc(max(var(--tg-safe-top), env(safe-area-inset-top, 0px)) + 8px);
}
.hud-score { display: flex; flex-direction: column; margin-right: auto; line-height: 1; }
.hud-score b {
  font-family: var(--f-display);
  font-size: 40px; font-weight: 700; letter-spacing: -0.04em;
  font-variant-numeric: tabular-nums;
}
.hud-score .lbl { margin-top: 3px; }

/* The in-game pause control: the player's only way out of a round, so it is
   an obvious violet-tinted icon button, never blended into the dusk HUD. */
.hud .iconbtn {
  background: var(--tint-2);
  border-color: var(--accent);
  color: var(--accent-d);
}

.pill--combo { opacity: 0; transition: opacity var(--t); background: var(--accent); color: var(--bg); font-size: 15px; }
.pill--combo.is-on { opacity: 1; }
.pill--shield { background: var(--tint); border: var(--edge); }

.meter { flex: none; margin: 12px 2px 10px; }
.meter .track { margin-top: 6px; }

/* The stage is a window cut into the sky, not a card sitting on it: a violet
   hairline, a soft outward bloom of the same violet, and the canvas painting
   its own sky right up to the rounded corners. */
.stagewrap {
  flex: 1; min-height: 0; position: relative;
  border: var(--edge);
  border-radius: var(--r-lg);
  box-shadow: var(--sh), 0 0 0 1px rgba(167, 139, 250, .10), 0 0 46px -14px rgba(167, 139, 250, .34);
  background: var(--bg);
  overflow: hidden;
  margin-bottom: 6px;
}
#stage { display: block; width: 100%; height: 100%; touch-action: none; }

/* The pre-round panel reads as haze over the sky, not as an opaque lid: the
   canvas is already drawing behind it and that first glimpse is the hook. */
.startover {
  position: absolute; inset: 0;
  display: flex; align-items: center; justify-content: center;
  background: linear-gradient(180deg, rgba(15, 10, 28, .72), rgba(25, 18, 48, .90));
  -webkit-backdrop-filter: blur(9px);
  backdrop-filter: blur(9px);
  border-radius: var(--r-lg);
  padding: 18px;
  overflow-y: auto;
  animation: rise-in 300ms cubic-bezier(.2, .8, .3, 1) both;
}
.start-in { width: 100%; max-width: 320px; text-align: left; }
.start-in .chip--lg { margin: 0 auto 12px; }
.start-t {
  display: block; text-align: center;
  font-family: var(--f-display);
  font-size: 24px; font-weight: 700; letter-spacing: -0.025em;
  margin-bottom: 16px;
}
.steps { list-style: none; margin: 0 0 18px; padding: 0; display: flex; flex-direction: column; gap: 10px; }
.step {
  display: flex; align-items: center; gap: 10px;
  border: var(--edge);
  border-radius: var(--r);
  padding: 10px 12px;
}
.step-n {
  width: 22px; height: 22px; flex: none;
  display: grid; place-items: center;
  border-radius: 999px;
  background: var(--accent-d);
  color: var(--bg);
  font-size: 12px; font-weight: 700;
}
.step-tx { display: flex; flex-direction: column; min-width: 0; }
.step-tx b { font-size: 14px; font-weight: 700; }
.step-tx i { font-style: normal; font-size: 12.5px; color: var(--ink-2); line-height: 1.35; margin-top: 1px; }

/* ── rank ────────────────────────────────────────────────────────────────── */

.seg {
  display: flex; gap: 4px;
  background: var(--tint);
  border-radius: 999px;
  padding: 4px;
  margin: 4px 0 14px;
}
.seg-btn {
  flex: 1;
  display: flex; align-items: center; justify-content: center; gap: 6px;
  padding: 9px 8px;
  border-radius: 999px;
  font-size: 13px; font-weight: 700;
  color: var(--ink-2);
  transition: background var(--t), color var(--t), box-shadow var(--t);
}
.seg-btn.is-on { background: var(--surface); color: var(--accent-d); box-shadow: var(--sh); }

.board { display: flex; flex-direction: column; margin-top: 6px; }
.rw {
  position: relative;
  display: flex; align-items: center; gap: 11px;
  padding: 10px 4px;
  border-radius: var(--r);
}
/* The divider is a pseudo-element, not a border-top: a 1px border on a rounded
   box curves up at both ends and reads as a wobble. */
.rw + .rw::before, .row + .row::before {
  content: ""; position: absolute; left: 0; right: 0; top: 0; height: 1px;
  background: var(--line);
}
.rw--me::before, .rw--me + .rw::before { display: none; }
.rw-pos {
  min-width: 22px;
  font-size: 13px; font-weight: 700;
  font-variant-numeric: tabular-nums;
  color: var(--ink-3);
  text-align: center;
}
.rw-av {
  width: 32px; height: 32px; flex: none;
  display: grid; place-items: center;
  border-radius: 999px;
  /* shell.js hands each name a hue; keep it quiet so the violet stays the one
     lit colour on the screen. Dark chip, light glyph, reads on the sky. */
  background: hsl(var(--h) 26% 20%);
  color: hsl(var(--h) 45% 72%);
  font-size: 13px; font-weight: 700;
}
.rw-nm { flex: 1; font-size: 14.5px; font-weight: 600; letter-spacing: -0.01em; }
.rw-sc {
  font-family: var(--f-display);
  font-size: 17px; font-weight: 700;
  font-variant-numeric: tabular-nums;
  letter-spacing: -0.02em;
}
.rw--top .rw-pos { color: var(--accent-d); }
.rw--me {
  background: var(--tint);
  padding-left: 8px; padding-right: 8px;
  margin: 4px 0;
}
.rw--me + .rw, .rw--me { border-top-color: transparent; }
.rw--me .rw-nm { font-weight: 700; }
.rw--me .rw-sc { color: var(--accent-d); }

/* ── more ────────────────────────────────────────────────────────────────── */

.rows { margin-top: 6px; }
.card > .rows:first-child { margin-top: 0; }
.card.is-outline { padding: 6px 16px; }
.row {
  position: relative;
  display: flex; width: 100%; align-items: center; gap: 12px;
  padding: 13px 2px;
  font-size: 14.5px; font-weight: 600; text-align: left;
  color: var(--ink);
  border-radius: var(--r);
}
.row > span { flex: 1; min-width: 0; }
.row > .ic { color: var(--accent-d); }
.rowbtn { transition: background var(--t); }
.rowbtn:active { background: var(--tint); }
.chev { width: 18px; height: 18px; color: var(--ink-3); }
.row.is-danger, .row.is-danger > .ic, .row.is-danger .chev { color: var(--warn); }

.sw {
  appearance: none; -webkit-appearance: none;
  width: 46px; height: 27px; flex: none;
  background: var(--tint-2);
  border-radius: 999px;
  position: relative; margin: 0;
  transition: background var(--t);
}
.sw::after {
  content: ""; position: absolute; top: 3px; left: 3px;
  width: 21px; height: 21px;
  background: #fff;
  border-radius: 999px;
  box-shadow: 0 1px 2px rgba(8, 4, 22, .45);
  transition: transform var(--t);
}
.sw:checked { background: var(--accent); }
.sw:checked::after { transform: translateX(19px); }

/* ── section header (rank / more, HUD-style hairline sections) ────────────── */

.sect-h {
  font-size: 11px; font-weight: 700;
  letter-spacing: 0.12em; text-transform: uppercase;
  color: var(--ink-3);
  margin: 4px 2px 8px;
}
.screen[data-screen="more"] .sect-h:not(:first-child) { margin-top: 4px; }
.board { margin-top: 2px; }

/* Squared small-radius button — the "interface" variant. */
.btn--sq { width: auto; flex: none; border-radius: 9px; padding: 9px 13px; font-size: 12.5px; gap: 6px; }

/* ── primary action: in-content Play button ───────────────────────────────────
   A normal button in the Home flow (not a fixed bar), so it never collides
   with the bottom nav. Full-width violet, label left, arrow right. */
.playcta {
  display: flex; align-items: center; gap: 12px;
  width: 100%;
  margin: 16px 2px 0;
  background: var(--accent); color: var(--bg);
  padding: 15px 18px;
  border-radius: var(--r);
  box-shadow: 0 1px 2px rgba(8, 4, 22, .5), 0 16px 32px -14px rgba(167, 139, 250, .78);
}
.playcta-tx { display: flex; flex-direction: column; margin-right: auto; text-align: left; line-height: 1.1; }
.playcta-tx b { font-family: var(--f-display); font-size: 20px; font-weight: 700; letter-spacing: -0.01em; }
.playcta-tx i { font-style: normal; font-size: 12px; font-weight: 600; opacity: .82; margin-top: 1px; }
.playcta-ar { width: 24px; height: 24px; opacity: .8; }

/* ── overlays ────────────────────────────────────────────────────────────── */

.scrim { position: fixed; inset: 0; z-index: 40; background: rgba(0, 0, 0, .62); }

.sheet {
  position: fixed; z-index: 50;
  left: 10px; right: 10px;
  bottom: calc(10px + max(var(--tg-safe-bottom), env(safe-area-inset-bottom, 0px)));
  background: var(--surface);
  border: var(--edge);
  border-radius: var(--r-lg);
  box-shadow: var(--sh);
  display: flex; flex-direction: column;
  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 — 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: 14px 14px 12px;
  border-bottom: 1px solid var(--line);
}
.sheet-head b {
  flex: 1; min-width: 0;
  font-family: var(--f-display);
  font-size: 19px; font-weight: 700; letter-spacing: -0.02em;
}
.sheet-body {
  flex: 1; min-height: 0;
  overflow-y: auto;
  padding: 14px 16px 4px;
  font-size: 14px; 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: 2px; top: 8px;
  width: 8px; height: 8px;
  background: var(--accent);
  border-radius: 999px;
}
.sheet-body b { font-weight: 700; color: var(--ink); }
.sheet-foot { flex: none; padding: 12px 16px 16px; border-top: 1px solid var(--line); }

.modal {
  position: fixed; inset: 0; z-index: 55;
  display: flex; align-items: center; justify-content: center;
  padding: 20px;
  pointer-events: none;
}
.modal-card {
  pointer-events: auto;
  width: 100%; max-width: 330px;
  background: var(--surface);
  border: var(--edge);
  border-radius: var(--r-lg);
  box-shadow: var(--sh);
  padding: 20px 18px;
  text-align: center;
  animation: rise 200ms cubic-bezier(.2, .8, .3, 1);
}
@keyframes rise { from { transform: translateY(10px); opacity: 0; } to { transform: translateY(0); opacity: 1; } }
.modal-card .chip--lg { margin: 0 auto 4px; }
.modal-card .btn { justify-content: center; }
.modal-t { display: block; font-family: var(--f-display); font-size: 22px; font-weight: 700; letter-spacing: -0.02em; margin-top: 10px; }
.modal-btns { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin-top: 16px; }
.modal-btns .btn { padding: 13px 10px; font-size: 13.5px; gap: 7px; }
.modal-btns .ic { width: 19px; height: 19px; }

.revive {
  position: fixed; inset: 0; z-index: 60;
  display: grid; place-items: center;
  pointer-events: none;
}
.revive span {
  display: grid; place-items: center;
  width: 132px; height: 132px;
  background: var(--tint);
  border: var(--edge);
  border-radius: 999px;
  box-shadow: var(--sh);
  font-family: var(--f-display);
  font-size: 68px; font-weight: 700; color: var(--accent-d);
  animation: pop 200ms cubic-bezier(.2, .8, .3, 1);
}
@keyframes pop { from { transform: scale(.86); opacity: 0; } to { transform: scale(1); 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)));
  background: var(--surface);
  border: var(--edge);
  border-radius: 999px;
  box-shadow: var(--sh);
  padding: 13px 18px;
  font-size: 13.5px; font-weight: 600;
  text-align: center;
}

/* ── 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; transition-duration: 0.01ms !important; }
}

/* Short phones: the big number and the Play block give first. */
@media (max-height: 690px) {
  .bignum { font-size: 58px; }
  .btn-tx b { font-size: 20px; }
  .lede { margin-bottom: 10px; }
  .step { padding: 8px 10px; }
}

/* ── display face tuning ──────────────────────────────────────────────────────
   Fraunces is an optical serif, not a grotesque: at these sizes it wants a
   lighter weight, looser tracking and its SOFT axis turned up. Set once here so
   every display element inherits the same voice instead of being tuned locally.
   Ignored harmlessly when the webfont has not loaded and Georgia stands in. */
.bignum, .hero-num, .hud-score b, .sp-name, .start-t, .modal-t, .sheet-head b,
.wordmark, .fig b, .rw-sc, .daily-v, .prog-n b, .revive span, .playcta-tx b,
.btn-tx b {
  font-weight: 600;
  font-variation-settings: "SOFT" 40, "WONK" 0, "opsz" 40;
  letter-spacing: -0.012em;
}
.bignum, .hero-num {
  letter-spacing: -0.026em;
  font-variation-settings: "SOFT" 70, "WONK" 0, "opsz" 96;
}
.hud-score b { letter-spacing: -0.018em; }

/* The metre count is the altimeter: it gets the accent, because it is the
   single number the whole round is about. */
.hud-score b { color: var(--ink); }
.hud-score .lbl { color: var(--ink-3); }

/* Combo pill: a clean centre in a row. It arrives with a small pop rather than
   a plain fade, so the reward registers in peripheral vision. */
.pill--combo {
  background: var(--accent); color: var(--bg);
  box-shadow: 0 0 20px -4px rgba(167, 139, 250, .8);
  transform: scale(.86);
  transition: opacity var(--t), transform var(--t);
}
.pill--combo.is-on { transform: scale(1); }

/* Shield pill wears the accent ring rather than a fill, so the canopy meter
   stays the only violet bar in the HUD. */
.pill--shield { background: var(--tint); border: 1.5px solid var(--accent); color: var(--accent-d); }

/* The canopy meter is the one gauge in the game, so it gets a lit track and a
   soft bloom off the fill. Below a quarter it turns rose on its own (.is-low). */
.meter .track { background: var(--tint); box-shadow: inset 0 0 0 1px rgba(167, 139, 250, .12); }
.meter .fill { box-shadow: 0 0 14px -2px rgba(167, 139, 250, .85); }

/* Step chips in the pre-round panel sit on haze, so they need their own fill to
   stay legible against the moving canvas behind the blur. */
.startover .step { background: rgba(36, 26, 66, .58); }

/* ── world mark ───────────────────────────────────────────────────────────────
   The decorative deck illustration at the foot of Home. `margin-top: auto`
   makes it hug the bottom of the flex column, so on a tall phone it fills the
   space under the console instead of leaving a hole, and on a short one it
   simply scrolls with everything else. */
.worldmark {
  margin: auto 0 0;
  padding: 26px 0 2px;
  pointer-events: none;
}
.worldmark svg { display: block; width: 100%; height: auto; max-height: 190px; }
.wm-deck { fill: var(--tint-2); }
.wm-deck--far  { opacity: .42; }
.wm-deck--mid  { opacity: .66; }
.wm-deck--near { opacity: .92; }
.wm-path {
  fill: none;
  stroke: var(--accent-d);
  stroke-width: 1.6; stroke-linecap: round;
  stroke-dasharray: 2 6;
  opacity: .5;
}
.wm-lit { fill: var(--accent); }
.wm-seed { fill: var(--ink); }
