/* ================================================================
   ROCKET RUSH — CLEAN CSS
   Layout (730px total):
     0   – 294px  : blank (livestream area)
     294 – 328px  : top-bar (34px)
     328 – 633px  : flight-zone (305px)
     633 – 672px  : ctrl-row (39px)
     672 – 730px  : chip-row (58px)
   ================================================================ */

/* ── FONTS ──────────────────────────────────────────────────── */
@font-face { font-family:"Sora";     src:url(assets/fonts/Sora-Medium.ttf)        format("truetype"); font-weight:500; font-display:swap; }
@font-face { font-family:"Sora";     src:url(assets/fonts/Sora-SemiBold.ttf)      format("truetype"); font-weight:600; font-display:swap; }
@font-face { font-family:"Sora";     src:url(assets/fonts/Sora-Bold.ttf)          format("truetype"); font-weight:700; font-display:swap; }
@font-face { font-family:"Orbitron"; src:url(assets/fonts/Orbitron-ExtraBold.ttf) format("truetype"); font-weight:800; font-display:swap; }
@font-face { font-family:"Orbitron"; src:url(assets/fonts/Orbitron-Black.ttf)     format("truetype"); font-weight:900; font-display:swap; }
@font-face { font-family:"Exo 2";   src:url(assets/fonts/Exo2-Bold.ttf)          format("truetype"); font-weight:700; font-display:swap; }
@font-face { font-family:"Exo 2";   src:url(assets/fonts/Exo2-ExtraBold.ttf)     format("truetype"); font-weight:800; font-display:swap; }
@font-face { font-family:"Fredoka"; src:url(assets/fonts/Fredoka-Bold.ttf)        format("truetype"); font-weight:700; font-display:swap; }

/* ── TOKENS ─────────────────────────────────────────────────── */
:root {
  --fw:      375px;
  --fh:      730px;
  --blank-h:  294px;   /* top blank — absorbs whatever the other 4 rows don't use */
  --topbar-h:  34px;
  --fz:       305px;   /* flight zone — bigger */
  --ctrl-h:    39px;
  --chip-h:    58px;   /* ctrl-h + chip-h = 97px = 375 * 1024/3974, the cockpit
                          art's own aspect ratio — any other height stretches it */
  /*
   * 294 + 34 + 305 + 39 + 58 = 730 = --fh, exactly — every pixel of the
   * design accounted for. This used to be 255 (714 total, 16px short),
   * which left an unstyled 16px strip of .game's own black background
   * below the chip row that nothing filled — invisible under the old
   * center-anchored scaling (it just blended into symmetric top/bottom
   * letterboxing) but a real, visible gap under the current
   * bottom-anchored scaling, where the chip row is expected to reach
   * the device's actual bottom edge exactly.
   */

  --bg:    #040e16;
  --teal:  #00d4c8;   /* playground only (rocket/ring/readout/alt-scale) — kept blue on purpose */
  --gold:  #ffc940;
  --coral: #ff5c5c;
  /* --mint/--sky/--muted are NOT used anywhere in the playground (verified —
     .ping was the one playground consumer of --mint and is now detached
     above), so repurposing them for the pink/red chrome reskin is safe. */
  --mint:  #4ade80;   /* win-title / leaderboard multiplier — kept a distinct green so a "win" still reads as success against the new blue/gold casino palette */
  --sky:   #4fc3f7;   /* modal titles / rule markers — bright sky-blue, matches the bottom-panel gradient */
  --text:  #e8f8f5;
  --muted: #b4dcff;   /* was muted teal #7ecfc8 — now light sky-blue; only consumer left is .ti (top-bar icon color) */

  --fd: "Orbitron", sans-serif;
  --fn: "Exo 2",    sans-serif;
  --fu: "Sora",     sans-serif;
  --fc: "Fredoka",  sans-serif;

  --arc-c: 339.29;
}

/* ── RESET ──────────────────────────────────────────────────── */
*, *::before, *::after { box-sizing:border-box; margin:0; padding:0; }
/* Transparent, not #000 — a solid black here would otherwise show through
   .game and .blank-area (also transparent now) wherever the live video is
   supposed to be visible behind this page. The actual play UI (top-bar,
   flight-bg, bottom-panel) all paint their own opaque backgrounds, so
   they're unaffected. */
html, body { width:100%; height:100%; overflow:hidden; background:transparent; }
/* Tablet / laptop: the game is one centred phone-shaped column (see updateScale in game.js);
   the page around it gets a dark space backdrop instead of being empty. */
html.is-desktop { background: radial-gradient(ellipse 90% 60% at 50% 30%, #0b2a45 0%, #061626 55%, #030a12 100%); }
body { font-family:var(--fu); color:var(--text); touch-action:manipulation; }
button { border:0; cursor:pointer; font:inherit; -webkit-user-select:none; user-select:none; }
img { display:block; }
.hidden { display:none !important; }

/* ── GAME CANVAS ────────────────────────────────────────────── */
.game {
  /* Bottom-anchored, not vertically centered. --scale is now driven by
     viewport WIDTH alone (see updateScale() in game.js) so the game
     always fills the screen edge-to-edge horizontally — but that means
     on a device whose height doesn't exactly match GAME_H*scale, one
     of top/bottom has to give. Anchoring to the bottom means it's
     always the BLANK AREA (top 40%, empty by design) that gets
     trimmed/extended, while the actual play UI (top-bar, flight-zone,
     bottom-panel) stays pinned to the bottom edge and is never the
     part that's cut or gapped. transform-origin matches: scaling
     grows/shrinks the box from its bottom edge, not its middle.

     Horizontal centering still uses left:50% + translateX(-50%) (not
     grid place-items) for the same overflow-safety reason as before:
     .game's own unscaled layout size is 375×730 regardless of --scale,
     and place-items:center silently falls back to start-aligned
     whenever the item would overflow its track. */
  position: fixed;
  bottom: 0; left: 50%;
  width:  var(--fw);
  height: var(--fh);
  overflow: hidden;
  /* Transparent, not #000 — the blank livestream area (and any slack
     above it) needs to let a live video behind this page show through.
     .top-bar/.flight-bg/.bottom-panel all paint their own opaque
     backgrounds, so the actual play UI is unaffected. */
  background: transparent;
  transform: translateX(-50%) scale(var(--scale,1));
  transform-origin: center bottom;
}

/* ── BLANK AREA (top 40%) ───────────────────────────────────── */
.blank-area {
  position: absolute;
  left: 0; top: 0;
  width: var(--fw);
  height: var(--blank-h);
  background: transparent;
  z-index: 0;
}

/* ── BANNER ─────────────────────────────────────────────────── */
/* Game logo (assets/banner.png, 1137x219) over the bottom of the livestream
   area, sitting right on top of the top bar. The PNG has transparent padding
   (14px at the bottom of 219), so the box is positioned from where the ART
   ends (row 205), not from the image edge, and tucked 1px under the top bar
   (above it in z-order) so there is no gap. If banner.png is replaced, update
   the 205 and 1137 below (art-bottom row, image width). */
.banner {
  --bw: 210px;
  position: absolute;
  left: 50%;
  top: calc(var(--blank-h) - var(--bw) * 205 / 1137 + 1px);
  width: var(--bw);
  transform: translateX(-50%);
  z-index: 9;
  pointer-events: none;
  filter: drop-shadow(0 3px 6px rgba(0,8,24,.55));
}

/* ── TOP BAR ────────────────────────────────────────────────── */
/* Same visual language as the cockpit below it: a sky-blue metal bezel with
   a dark navy outline, a light glass slot for the round history, and round
   dark-navy buttons like the cockpit's dropdown circle. */
.top-bar {
  position: absolute;
  left: 0; right: 0;
  top: var(--blank-h);
  height: var(--topbar-h);
  z-index: 10;
  display: flex;
  align-items: center;
  gap: 6px;
  padding: 0 6px;
  background: linear-gradient(180deg, #86d3f3 0%, #4eaee3 45%, #2f86c8 100%);
  border-top: 1px solid #0a3055;
  border-bottom: 1.5px solid #0a3055;
  box-shadow: inset 0 1px 0 rgba(255,255,255,.65), inset 0 -1px 0 rgba(255,255,255,.22);
}

/* Recessed glass slot — same fill and dark outline as the cockpit's slots. */
.history-slot {
  flex: 1; min-width: 0;
  height: 26px;
  display: flex; align-items: center;
  border: 1.5px solid #0a3055;
  border-radius: 9px;
  background: linear-gradient(180deg, #f4f9fd 0%, #d3e5f3 100%);
  box-shadow: inset 0 1px 3px rgba(10,48,85,.38), 0 1px 0 rgba(255,255,255,.5);
  overflow: hidden;
}
.history {
  flex: 1; min-width: 0;
  display: flex; align-items: center; gap: 4px;
  padding: 0 5px;
  overflow: hidden;
  /* Edge fade on the chips only (the slot's own border stays crisp). 94%
     keeps every chip solid until right at the clipped edge. */
  -webkit-mask-image: linear-gradient(90deg, #000 0 92%, transparent);
  mask-image:         linear-gradient(90deg, #000 0 92%, transparent);
}
.hc {
  flex-shrink: 0;
  height: 18px;
  display: inline-flex; align-items: center; justify-content: center;
  border-radius: 999px; padding: 0 9px;
  font-family: var(--fn); font-size: 11.5px; font-weight: 800; letter-spacing: .1px;
  font-variant-numeric: tabular-nums; white-space: nowrap;
  border: 1px solid rgba(6,36,68,.55);
  box-shadow: inset 0 1px 0 rgba(255,255,255,.5), 0 1px 1.5px rgba(5,30,60,.32);
  animation: hcIn .32s cubic-bezier(.34,1.56,.64,1) both;
}
@keyframes hcIn {
  from { opacity:0; transform:translateX(-14px) scale(.84); }
  to   { opacity:1; transform:translateX(0) scale(1); }
}
/* Tiers, low → legend: blue, green, gold, red, purple — the same glossy
   colours as the bet chips below. */
.hc.low    { background:linear-gradient(180deg,#67b1f0,#2f78c8); color:#fff;    text-shadow:0 1px 1px rgba(5,30,70,.55); }
.hc.mid    { background:linear-gradient(180deg,#6fe07a,#2f9e45); color:#fff;    text-shadow:0 1px 1px rgba(0,50,15,.55); }
.hc.high   { background:linear-gradient(180deg,#ffd45c,#f0900a); color:#4b2900; text-shadow:0 1px 0 rgba(255,240,170,.6); }
.hc.rare   { background:linear-gradient(180deg,#ff7595,#cf2450); color:#fff;    text-shadow:0 1px 1px rgba(70,0,20,.55); }
.hc.legend { background:linear-gradient(180deg,#bb7bf7,#6a2bd0); color:#fff;    text-shadow:0 1px 1px rgba(30,0,80,.55); }
/* The newest result keeps its tier colour and gets a white + navy double
   ring (visible on the light slot). Declared AFTER the tier classes so it
   wins at equal specificity — addHistory() puts BOTH a tier class and
   "active" on the newest chip. The 2px ring plus the 18px chip fill the
   slot's inner height exactly, so nothing is clipped. */
.hc.active { box-shadow:0 0 0 1px #fff, 0 0 0 2px #0a3055; margin-left:2px; }

.top-icons { display:flex; align-items:center; gap:5px; flex-shrink:0; }
.ti {
  width:26px; height:26px;
  display:grid; place-items:center;
  border-radius:50%;
  border:1.5px solid #082747;
  background:radial-gradient(circle at 50% 28%, #1f6c9c 0%, #0c3a63 58%, #072a4b 100%);
  box-shadow: inset 0 0 0 1.5px rgba(150,205,240,.5), inset 0 2px 3px rgba(255,255,255,.22), 0 1px 1.5px rgba(5,30,60,.45);
  color:#8fdcff;
  transition:filter .15s, transform .1s;
}
.ti svg { width:14px; height:14px; fill:currentColor; stroke:none; }
/* Trophy is a picture (assets/btn-trophy.webp, 78px with ~14px of empty margin), so it is drawn at 22px and the cup lands ~15px, the same visual size as the other two icons. */
.ti img { width:22px; height:22px; object-fit:contain; pointer-events:none; -webkit-user-drag:none; filter:drop-shadow(0 1px 1px rgba(3,20,45,.5)); }
.ti svg .ln { fill:none; stroke:currentColor; stroke-width:2.2; stroke-linecap:round; stroke-linejoin:round; }
.ti.gold svg .ln { stroke-width:1.8; }
.ti .snd-slash { display:none; }
.ti.muted .snd-waves { display:none; }
.ti.muted .snd-slash { display:inline; }
.ti.muted { color:#ff9a9a; }
.ti.gold { color:#ffc940; }
.ti.red  { color:#ff9a9a; }
.ti:hover  { filter:brightness(1.18); }
.ti:active { transform:scale(.92); }

/* ── FLIGHT ZONE ────────────────────────────────────────────── */
.flight-zone {
  position: absolute;
  left: 0;
  top: calc(var(--blank-h) + var(--topbar-h));
  width: var(--fw);
  height: var(--fz);
  overflow: visible;
  z-index: 1;
}

/* Game canvas — curve line layer */
.game-canvas-el {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  z-index: 3;
  pointer-events: none;
  opacity: 0;
  transition: opacity .3s ease;
}
.game[data-phase=betting]  .game-canvas-el,
.game[data-phase=flying]  .game-canvas-el,
.game[data-phase=crashed] .game-canvas-el { opacity: 1; }

/* Background */
.flight-bg {
  position: absolute; inset: 0;
  background:
    url(assets/flight-bg-space.webp) center top / cover no-repeat,
    linear-gradient(180deg, #010d18 0%, #041e30 60%, #020e18 100%);
}
.flight-bg::after {
  content:""; position:absolute; inset:0;
  background-image:
    radial-gradient(1px 1px at 10% 15%, rgba(255,255,255,.7), transparent),
    radial-gradient(1px 1px at 28% 42%, rgba(255,255,255,.5), transparent),
    radial-gradient(1px 1px at 55% 12%, rgba(0,212,200,.5),   transparent),
    radial-gradient(1px 1px at 72% 68%, rgba(255,255,255,.5), transparent),
    radial-gradient(1px 1px at 88% 30%, rgba(92,228,255,.4),  transparent);
  background-size: 300px 200px;
  animation: starDrift 20s linear infinite;
}
@keyframes starDrift { from{background-position:0 0} to{background-position:300px 200px} }

/* Sky effects: twinkling stars, drawn between the background and the curve / rocket.
   Elements are created by buildSkyFx() in game.js. */
.sky-fx {
  position: absolute; inset: 0;
  z-index: 1;
  overflow: hidden;
  pointer-events: none;
}
.sky-star {
  position: absolute;
  border-radius: 50%;
  background: #fff;
  opacity: .2;
  animation: skyTwinkle var(--tw, 2.4s) ease-in-out var(--td, 0s) infinite;
}
.sky-star.big {
  box-shadow: 0 0 4px 1px rgba(160,235,255,.85), 0 0 9px 2px rgba(0,212,200,.45);
}
@keyframes skyTwinkle {
  0%, 100% { opacity: .12; transform: scale(.55); }
  50%      { opacity: 1;   transform: scale(1.2); }
}

/* Altitude scale */
.alt-scale {
  position:absolute; right:0; top:0; bottom:0; width:48px;
  z-index:3; pointer-events:none; opacity:0; transition:opacity .2s;
  -webkit-mask-image:linear-gradient(180deg,transparent 0,#000 8%,#000 90%,transparent);
  mask-image:        linear-gradient(180deg,transparent 0,#000 8%,#000 90%,transparent);
}
.game[data-phase=flying]  .alt-scale,
.game[data-phase=crashed] .alt-scale { opacity:1; }

.alt-line {
  position:absolute; right:8px; top:20px; bottom:28px; width:1px;
  background:linear-gradient(180deg,transparent,rgba(0,212,200,.42) 12%,rgba(255,201,64,.28) 55%,transparent);
}

/* Altitude tick labels — dynamically generated by JS */
.at {
  position:absolute; right:4px; transform:translateY(-50%);
  font-family:var(--fn); font-size:10px; font-weight:800;
  color: #e0f8ff;
  white-space:nowrap; text-align:right;
  font-variant-numeric:tabular-nums;
  text-shadow: 0 1px 3px rgba(0,0,0,.9), 0 0 8px rgba(0,212,200,.6);
}
.at::before {
  content:""; position:absolute; right:-9px; top:50%; transform:translateY(-50%);
  width:7px; height:1px; background:rgba(0,212,200,.5);
}

/* Labels container — clips overflow */
.alt-labels {
  position: absolute;
  inset: 0;
  overflow: hidden;
  pointer-events: none;
}

/* Alt dot — moves with rocket via JS */
.alt-dot {
  position:absolute; right:5px; transform:translateY(-50%);
  width:10px; height:10px; border-radius:50%;
  background:radial-gradient(circle,#fff 0 18%,#a2eeff 32%,var(--teal) 64%,transparent);
  box-shadow:0 0 8px var(--teal),0 0 16px rgba(0,212,200,.4);
  transition: top .1s linear;
  z-index:4;
}

/* Alt rail fill — fills from bottom up to dot */
.alt-fill {
  position:absolute; right:8px; bottom:28px;
  width:2px; border-radius:999px;
  background:linear-gradient(180deg, rgba(0,212,200,.8), rgba(0,212,200,.2));
  box-shadow: 0 0 6px rgba(0,212,200,.5);
  transition: height .1s linear;
  transform-origin: bottom;
  z-index:2;
}

/* Ping — custom SVG bars instead of the 📶 emoji glyph, which
   renders as a blocky, off-palette icon depending on OS/font */
.ping {
  position:absolute; right:52px; bottom:8px; z-index:8;
  font-family:var(--fu); font-size:9px; font-weight:700;
  color:rgba(0,212,200,.6); display:flex; align-items:center; gap:4px;
}
.ping-icon { color:var(--teal); flex-shrink:0; }
.ping span { color:#3dffa0; min-width:34px; }  /* was var(--mint) — detached so repurposing --mint below for the reskin doesn't touch the playground */
/* Live latency (game.js setPing): 3 bars + green under 80ms, 2 + yellow to
   200ms, 1 + red above that, all dim with "--" while offline. */
.ping[data-q=good] .pb1, .ping[data-q=good] .pb2, .ping[data-q=good] .pb3 { opacity:1; }
.ping[data-q=mid]  .pb3 { opacity:.25; }
.ping[data-q=bad]  .pb2, .ping[data-q=bad] .pb3 { opacity:.25; }
.ping[data-q=off]  .ping-icon { opacity:.35; }
.ping[data-q=mid]  .ping-icon { color:#ffc940; }
.ping[data-q=mid]  span { color:#ffc940; }
.ping[data-q=bad]  .ping-icon { color:#ff5c5c; }
.ping[data-q=bad]  span { color:#ff5c5c; }
.ping[data-q=off]  span { color:rgba(180,220,255,.6); }

/* ── COUNTDOWN RING ─────────────────────────────────────────── */
.cring {
  position:absolute; left:50%; top:28%;
  transform:translate(-50%,-50%);
  z-index:7; width:140px; height:140px;
  display:grid; place-items:center;
  opacity:0; pointer-events:none;
  transition:opacity .22s ease, transform .22s ease;
}
.game[data-phase=betting]  .cring { opacity:1; }
.game[data-phase=flying]   .cring,
.game[data-phase=crashed]  .cring { opacity:0; transform:translate(-50%,-50%) scale(.88); }

.cring-dashes { display:none; }

.cring-svg {
  position:absolute; inset:0; width:100%; height:100%; overflow:visible;
}
.cring-track { stroke:transparent; stroke-width:8; }
.cring-arc   { stroke:#00e5ff; stroke-width:10; stroke-linecap:round; fill:none; }

/* Dark center */
.cring-dark {
  position:absolute; inset:22px; border-radius:50%;
  background:radial-gradient(circle at 50% 40%,
    rgba(110,35,210,.3) 0%, rgba(55,8,130,.55) 42%,
    rgba(8,1,36,.9) 72%, rgba(2,0,14,.97) 100%);
  box-shadow:inset 0 0 32px rgba(90,25,190,.35);
  animation:darkPulse 2s ease-in-out infinite alternate;
}
@keyframes darkPulse {
  from { box-shadow:inset 0 0 28px rgba(90,25,190,.3); }
  to   { box-shadow:inset 0 0 44px rgba(90,25,190,.5); }
}

.cring-body {
  position:absolute; inset:0;
  display:flex; flex-direction:column; align-items:center; justify-content:center; gap:4px;
  pointer-events:none;
}
.cring-num {
  font-family:var(--fd); font-size:38px; font-weight:900;
  line-height:.88; color:#fff; letter-spacing:-2px;
  text-shadow:0 0 16px rgba(0,229,255,.95),0 0 32px rgba(0,229,255,.5),0 2px 0 rgba(0,20,40,.8);
  transition:color .28s, text-shadow .28s;
}
.cring-lbl {
  font-family:var(--fu); font-size:11px; font-weight:800;
  letter-spacing:3px; text-transform:uppercase;
  color:rgba(180,240,255,.88); text-shadow:0 0 10px rgba(0,229,255,.55);
}
.cring[data-urgency=mid] .cring-num { color:#ffc940; text-shadow:0 0 16px rgba(255,201,64,.95),0 0 32px rgba(255,201,64,.5),0 2px 0 rgba(80,30,0,.8); }
.cring[data-urgency=low] .cring-num { color:#ff5c5c; text-shadow:0 0 16px rgba(255,92,92,.95),0 0 32px rgba(255,92,92,.5),0 2px 0 rgba(80,0,0,.8); animation:urgPulse .5s ease-in-out infinite alternate; }
@keyframes urgPulse { from{opacity:.72;transform:scale(.97)} to{opacity:1;transform:scale(1.04)} }

/* ── READOUT ────────────────────────────────────────────────── */
.readout {
  position:absolute; left:50%; top:50%;
  transform:translate(-50%,-50%);
  z-index:4; display:flex; flex-direction:column; align-items:center; gap:4px;
  pointer-events:none; opacity:0; transition:opacity .22s;
}
.game[data-phase=flying]  .readout,
.game[data-phase=crashed] .readout { opacity:1; }
.readout strong {
  font-family:var(--fd); font-size:54px; font-weight:900;
  line-height:.9; color:var(--gold); letter-spacing:.5px;
  font-variant-numeric:tabular-nums;
  text-shadow:0 2px 0 rgba(140,60,0,.65),0 0 24px rgba(255,201,64,.55),0 10px 22px rgba(0,0,0,.62);
}
.readout strong em { font-size:32px; font-style:normal; font-weight:700; }
.readout small {
  font-family:var(--fu); font-size:10px; font-weight:700;
  letter-spacing:2.5px; text-transform:uppercase;
  color:rgba(126,207,200,.72);
}
.game[data-phase=flying]  .readout strong { color:var(--teal); text-shadow:0 2px 0 rgba(0,80,76,.72),0 0 28px rgba(0,212,200,.72),0 0 48px rgba(0,212,200,.32),0 12px 24px rgba(0,0,0,.6); animation:rFloat .9s ease-in-out infinite alternate; }
.game[data-phase=crashed] .readout strong { color:var(--coral); text-shadow:0 2px 0 rgba(120,0,0,.72),0 0 28px rgba(255,92,92,.72); }
@keyframes rFloat { from{transform:scale(1)} to{transform:scale(1.02) translateY(-3px)} }

/* ── ROCKET ─────────────────────────────────────────────────── */
.rocket {
  position: absolute;
  left: 50%; top: 72%;
  transform: translate(-50%, -50%);
  z-index: 6;
  width: 160px; height: 200px;
  display: flex; align-items: center; justify-content: center;
  opacity: 0; pointer-events: none; transition: opacity .14s;
}
.rocket img {
  width: 100%; height: 100%;
  object-fit: contain;
  filter: drop-shadow(0 0 10px rgba(0,212,200,.55)) drop-shadow(0 0 22px rgba(255,201,64,.35));
}

/* Flying — rocket smaller */
/* box matches the nose-up sprite's 72:120 shape, ~40px long in flight —
   about the size the old tilted rocket read at (~39px across) */
.game[data-phase=flying] .rocket,
.game[data-phase=crashed] .rocket {
  width: 24px;
  height: 40px;
}
.r-flame {
  position:absolute; bottom:-8px; left:50%; transform:translateX(-50%);
  width:18px; height:0; border-radius:50% 50% 44% 44%;
  background:linear-gradient(180deg,#fffde8,#ffe040 32%,rgba(0,212,200,.3));
  transform-origin:50% 0; opacity:0;
}
.r-steam {
  position:absolute; bottom:-4px; left:50%; transform:translateX(-50%);
  width:0; height:0; border-radius:55% 55% 48% 48%;
  background:radial-gradient(circle at 50% 8%,rgba(0,212,200,.7),rgba(92,228,255,.3) 38%,transparent 68%);
  filter:blur(.5px); opacity:0;
}
/* Betting — rocket visible, idle float */
/* Countdown sprite (assets/rocket-market-sprite-7.webp, 72x120) is drawn at
   ~its native size; the box is sized to it so the exhaust sits right under it. */
.game[data-phase=betting] .rocket {
  width:48px; height:80px;
  opacity:1; top:70%;
  animation:rIdle 2s ease-in-out infinite;
}
.game[data-phase=betting] .r-steam {
  width:22px; height:30px; opacity:.65;
  animation:rSteam 1.1s ease-in-out infinite alternate;
}
@keyframes rIdle  { 0%,100%{transform:translate(-50%,-50%) translateY(0)} 50%{transform:translate(-50%,-50%) translateY(-7px)} }
@keyframes rSteam { from{opacity:.4;transform:translateX(-50%) translateY(-1px) scaleX(.66) scaleY(.7)} to{opacity:.7;transform:translateX(-50%) translateY(6px) scaleX(1) scaleY(1.1)} }

/* Active bet */
.game[data-phase=betting][data-bet=active] .rocket { animation:rArmed .44s ease-in-out infinite alternate; }
.game[data-phase=betting][data-bet=active] .rocket img { filter:drop-shadow(0 0 16px rgba(92,228,255,.82)) drop-shadow(0 0 30px rgba(0,212,200,.56)); }
@keyframes rArmed { from{transform:translate(-50%,-50%) translateY(0) scale(1)} to{transform:translate(-50%,-50%) translateY(-8px) scale(1.06)} }

/* Flying — image handles rotation, no CSS transform */
.game[data-phase=flying] .rocket { opacity:1; }
/* Hide CSS flame/steam — tiltedrocket.png has its own */
.game[data-phase=flying] .r-flame,
.game[data-phase=flying] .r-steam { display: none !important; }
@keyframes flameFl { from{transform:translateX(-50%) scaleY(.84);opacity:.76} to{transform:translateX(-50%) scaleY(1.18);opacity:1} }
@keyframes steamFl { from{transform:translateX(-50%) scaleX(.82) scaleY(.82);opacity:.5} to{transform:translateX(-50%) translateY(8px) scaleX(1.08) scaleY(1.24);opacity:.8} }

/* Crashed */
/* The rocket blows up: it vanishes at once as the blast plays over it (it used
   to linger as a dim ghost for the whole 3s crash hold). */
.game[data-phase=crashed] .rocket { opacity:0; transition:opacity .1s ease-out; }

/* Stage cue */
.cue {
  position:absolute; left:50%; bottom:8px; transform:translateX(-50%);
  z-index:8; border:1px solid rgba(0,212,200,.24); border-radius:999px; padding:3px 12px;
  background:radial-gradient(circle at 50% 0,rgba(255,255,255,.1),transparent 48%),
             linear-gradient(180deg,rgba(2,28,42,.88),rgba(1,12,22,.84));
  font-family:var(--fu); font-size:9.5px; font-weight:700;
  color:rgba(162,238,255,.82); white-space:nowrap;
}
.game[data-phase=flying]  .cue { display:none; }
.game[data-phase=crashed] .cue { color:rgba(255,158,158,.88); border-color:rgba(255,92,92,.36); background:linear-gradient(180deg,rgba(62,10,10,.9),rgba(28,4,4,.88)); }

/* Crash shake */
/* Targets .flight-zone, not .game — .game's own `transform` now does
   real centering + responsive scaling (translate(-50%,-50%) scale(...)),
   and a CSS animation on a property fully REPLACES that property's
   value for its duration rather than composing with it. Shaking
   .game itself briefly wiped the centering/scale transform every
   crash, which on any viewport where scale != 1 (i.e. most real
   phones) flung the whole board off past the edge of the screen for
   that quarter-second — looked like the page going blank. */
.game[data-phase=crashed] .flight-zone { animation:canvasShake .24s ease-out; }
@keyframes canvasShake { 0%,100%{transform:translate(0)} 20%{transform:translate(-4px,0)} 40%{transform:translate(4px,0)} 60%{transform:translate(-2px,0)} 80%{transform:translate(2px,0)} }

/* ── BOTTOM PANEL ───────────────────────────────────────────── */
.bottom-panel {
  /* Every value below is a slot of the cockpit art as drawn by ::after
     below: the PNG is cropped 46px off the left (empty margin — its bezel
     starts there but ends flush with the right edge) and 14px off the top
     (a white highlight line + stray specks), then fitted to 375×97. */
  --bp-top-y: 12.85px;
  --bp-slot-h: 25.35px;
  --bp-balance-x: 47.2px;
  --bp-balance-w: 82.96px;
  --bp-bet-x: 174.7px;
  --bp-bet-w: 56.66px;
  --bp-auto-x: 248.5px;
  --bp-auto-w: 97.1px;
  --bp-chip-x: 25.45px;
  --bp-chip-y: 51.43px;
  --bp-chip-size: 38.4px;   /* visible chip diameter, not the PNG box */
  --bp-chip-gap: 2.4px;
  --bp-action-x: 239px;
  --bp-action-y: 49.25px;
  --bp-action-w: 128.4px;
  --bp-action-h: 44px;
  position: absolute;
  left: 0;
  top: calc(var(--blank-h) + var(--topbar-h) + var(--fz));
  width: var(--fw);
  height: calc(var(--ctrl-h) + var(--chip-h));
  display: block;
  overflow: hidden;
  background: #041e30;
  border: 0;
  box-shadow: none;
  z-index: 5;
}
/* Sky behind the cockpit's transparent corners and edges: the playground's
   own image at the playground's own scale, flipped vertically so the row the
   playground ends on sits at the panel's top and the two meet with no
   visible seam. The image is 375px wide (cover) = ~666px tall, and the
   playground is top-aligned, showing its first 305px, so that last row is at
   y=305 — hence the -207px offset (98px box height minus 305). */
.bottom-panel::before {
  content: "";
  /* 1px taller than the panel, hanging off the top (clipped by overflow),
     so it overlaps the seam instead of just touching it. */
  position: absolute; inset: -1px 0 0 0;
  z-index: 0;
  background: url("assets/flight-bg-space.webp") 0 -207px / 375px auto no-repeat;
  transform: scaleY(-1);
  pointer-events: none;
}
.bottom-panel::after {
  content: "";
  position: absolute; inset: 0;
  z-index: 1;
  background: url("assets/rocket-bottom-cockpit-v2-clean.png") -4.39px -1.34px / 379.4px 98.35px no-repeat;
  pointer-events: none;
}

/* ── ROW 1: Balance | Coins | Auto | BET ───────────────────── */
.ctrl-row {
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: 40px;
  display: block;
  padding: 0;
  border-bottom: 0;
  z-index: 2;
}

/* Balance box — star coin LEFT + amount RIGHT.
   Light glass, not dark navy — the panel behind it is white-to-sky-
   blue, so a dark card sat on it like a cut-out patch. This is a
   frosted-white card (bright glass highlight top, a soft blue-tinted
   falloff at the bottom for depth, a real drop shadow lifting it off
   the panel) so it reads as part of the same light, airy surface. */
.bal-box {
  position: absolute;
  left: var(--bp-balance-x);
  top: var(--bp-top-y);
  display: flex; flex-direction: row; align-items: center;
  justify-content: center;
  gap: 0; padding: 0 4px;
  width: var(--bp-balance-w); height: var(--bp-slot-h); flex-shrink: 0;
  border: 0; border-radius: 0;
  background: transparent;
  box-shadow: none;
}
.bal-box strong { font-family:var(--fn); font-size:14px; font-weight:800; color:#7b4c00; white-space:nowrap; letter-spacing:.1px; text-shadow:0 1px 0 rgba(255,255,255,.9), 0 1px 2px rgba(72,42,0,.22); }

/* Bet box — coin smaller. Same light-glass treatment, sky-blue rim
   instead of gold (this one isn't currency, it's the live bet). */
.bet-box {
  position: absolute;
  left: var(--bp-bet-x);
  top: var(--bp-top-y);
  display: flex; align-items: center; justify-content: center; gap: 3px;
  width: var(--bp-bet-w); height: var(--bp-slot-h); border: 0; border-radius: 0;
  background: transparent;
  padding: 0 2px;
  box-shadow: none;
}
/* Same gold as the balance amount, centred in its slot. */
.bet-box span { font-family:var(--fn); font-size:14px; font-weight:800; color:#7b4c00; white-space:nowrap; letter-spacing:.1px; font-variant-numeric:tabular-nums; text-shadow:0 1px 0 rgba(255,255,255,.9), 0 1px 2px rgba(72,42,0,.22); }

/* Auto box — bigger. Same treatment again, for a matched set of three. */
.auto-box {
  position: absolute;
  left: var(--bp-auto-x);
  top: var(--bp-top-y);
  display: flex; align-items: center; justify-content: center; gap: 4px;
  width: var(--bp-auto-w); height: var(--bp-slot-h); padding: 0; flex-shrink: 0;
  border: 0; border-radius: 0;
  background: transparent;
  cursor: pointer; transition: border-color .15s;
  box-shadow: none;
}
.auto-box:hover  { filter: brightness(1.05); }
.auto-box:active { transform: scale(.96); }
.auto-lbl { font-family:var(--fu); font-size:8.5px; font-weight:700; color:rgba(32,73,105,.72); text-transform:none; }
.auto-box strong { font-family:var(--fn); font-size:15px; font-weight:800; color:#073763; text-shadow:0 1px 0 rgba(255,255,255,.65), 0 1px 2px rgba(0,42,78,.22); }
/* The dropdown arrow is baked into the cockpit art; this stays in the DOM but out of the flex flow, or it pushes "Auto 2.00x" left of centre. */
.auto-arr { position:absolute; font-size:12px; color:rgba(7,55,99,.65); opacity:0; pointer-events:none; }

/* BET button */
.act-btn {
  --act-art: url("assets/rocket-action-launch-active-lite.webp");
  --act-art-filter: saturate(.98) brightness(.98);
  --act-title-color: #4b2900;
  --act-sub-color: rgba(91,48,0,.8);
  --act-tint: rgba(255,238,126,.18);
  --act-tint-opacity: .14;
  flex-shrink: 0;
  position: absolute;
  left: var(--bp-action-x);
  top: var(--bp-action-y);
  width: var(--bp-action-w);
  height: var(--bp-action-h);
  margin: 0;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 1px;
  border: 0;
  border-radius: 0;
  background: transparent;
  color: var(--act-title-color); text-align: center; text-transform: uppercase;
  overflow: visible;
  text-shadow: 0 1px 0 rgba(255,232,124,.42), 0 -1px 1px rgba(89,37,0,.14);
  box-shadow: none;
  transition: filter .14s, transform .14s;
  pointer-events: auto;
}
/* All three art files (launch / collect-reward / ready-disabled) share one
   365×150 canvas with transparent glow padding around the frame: the frame
   itself spans x 11–359, y 13–145. The layer below is sized and offset so
   that FRAME — not the whole canvas — lands exactly on the button box,
   which is itself the frame of the button baked into the cockpit art, so
   the art covers it edge to edge whichever state is showing. */
.act-btn::after {
  --sx: calc(var(--bp-action-w) / 349);
  --sy: calc(var(--bp-action-h) / 132);
  content:"";
  position:absolute;
  left: calc(-11 * var(--sx));
  top: calc(-13 * var(--sy));
  width: calc(365 * var(--sx));
  height: calc(150 * var(--sy));
  z-index:0;
  background: var(--act-art) 0 0 / 100% 100% no-repeat;
  filter: var(--act-art-filter);
  pointer-events:none;
}
.act-btn::before {
  content:"";
  position:absolute;
  z-index:1;
  top:7px;
  right:10px;
  bottom:7px;
  left:10px;
  border-radius:12px;
  background:
    radial-gradient(ellipse at 50% 32%, var(--act-tint), transparent 62%),
    linear-gradient(90deg, transparent, rgba(255,255,255,.08), transparent);
  opacity: var(--act-tint-opacity);
  pointer-events:none;
}
.act-btn[data-state=launch]::before,
.act-btn[data-state=cashout]::before { animation:btnSheen 1.8s ease-in-out infinite; }
.act-btn[data-state=launch],
.act-btn[data-state=cashout] { animation:actPulse .96s ease-in-out infinite alternate; }
@keyframes btnSheen { 0%,36%{filter:brightness(1)} 70%,100%{filter:brightness(1.22)} }
@keyframes actPulse {
  from { filter:brightness(1); }
  to   { filter:brightness(1.08); }
}
.act-btn[data-state=cashout] {
  --act-art: url("assets/rocket-action-collect-reward-lite.webp");
  --act-art-filter: saturate(.98) brightness(.98);
  --act-title-color: #123d17;
  --act-sub-color: rgba(231,255,199,.92);
  --act-tint: rgba(121,255,152,.28);
  --act-tint-opacity: .28;
  border-color: transparent;
  background: transparent;
  color: var(--act-title-color);
  text-shadow: 0 1px 0 rgba(220,255,180,.42), 0 -1px 1px rgba(0,50,20,.16);
  animation: cashPulse .62s ease-in-out infinite alternate;
  width: var(--bp-action-w);
  height: var(--bp-action-h);
}
.act-btn[data-state=cashed] {
  --act-art: url("assets/rocket-action-collect-reward-lite.webp");
  /* Looks the same as CASH OUT (colours, art, text); only the pulse is off. */
  --act-art-filter: saturate(.98) brightness(.98);
  --act-title-color: #123d17;
  --act-sub-color: rgba(231,255,199,.92);
  --act-tint: rgba(121,255,152,.28);
  --act-tint-opacity: .28;
  border-color: transparent;
  background: transparent;
  color: var(--act-title-color);
  text-shadow: 0 1px 0 rgba(220,255,180,.42), 0 -1px 1px rgba(0,50,20,.16);
  animation: none;
  width: var(--bp-action-w);
  height: var(--bp-action-h);
}
@keyframes cashPulse { from{filter:brightness(1)} to{filter:brightness(1.1);} }
.act-btn[data-state=wait],
.act-btn[data-state=ended] {
  --act-art: url("assets/rocket-action-ready-disabled-lite.webp");
  --act-art-filter: saturate(.96) brightness(1.02);
  --act-title-color: rgba(186,207,225,.72);
  --act-sub-color: rgba(176,197,220,.58);
  --act-tint: rgba(255,221,126,.18);
  --act-tint-opacity: .22;
  border-color:transparent;
  background:transparent;
  animation:none;
  width:var(--bp-action-w);
  height:var(--bp-action-h);
}
/* WATCH (spectating, no bet) — same orange art and engraved brown text as
   LAUNCH; only CANCEL (data-state=wait) keeps the purple art above. */
.act-btn[data-state=ended] {
  --act-art: url("assets/rocket-action-launch-active-lite.webp");
  --act-art-filter: saturate(.98) brightness(.98);
  --act-title-color: #4b2900;
  --act-sub-color: rgba(91,48,0,.8);
  --act-tint: rgba(255,238,126,.18);
  --act-tint-opacity: .14;
  text-shadow: 0 1px 0 rgba(255,232,124,.42), 0 -1px 1px rgba(89,37,0,.14);
}
/* CANCEL (bet placed, waiting for take-off) keeps its purple art; only the
   text is brightened (it was a dim grey) and given a dark edge, like the
   white multiplier on CASH OUT. Declared after the shared wait/ended block. */
.act-btn[data-state=wait] {
  --act-title-color: #fff;
  text-shadow: 0 1px 2px rgba(20,0,70,.85), 0 0 1px rgba(20,0,70,.7);
}

/* Backing plate. The art's outer rim is only partly opaque, and its
   chamfered corners are cut deeper than the button baked into the cockpit,
   so a thin line of the baked orange showed around every state. This paints
   a solid rim-coloured octagon (the baked button's outline) behind the art
   to hide it. Kept after the state rules above so their `background:
   transparent` doesn't win. */
.act-btn,
.act-btn[data-state] {
  --act-rim: #7a2600;
  background: var(--act-rim);
  clip-path: polygon(9px 0, calc(100% - 9px) 0, 100% 10px, 100% calc(100% - 10px),
                     calc(100% - 9px) 100%, 9px 100%, 0 calc(100% - 10px), 0 10px);
}
.act-btn[data-state=cashout],
.act-btn[data-state=cashed] { --act-rim: #1f4a06; }
.act-btn[data-state=wait]   { --act-rim: #240a6e; }
.act-btn strong { position:relative; z-index:2; font-family:var(--fd); font-size:12px; line-height:1.1; display:block; color:var(--act-title-color); }
/* CASH OUT / CASHED: the live multiplier underneath is set in the same
   Orbitron + engraved colour as the title, not the small light-mint Sora. */
.act-btn[data-state=cashout] strong,
.act-btn[data-state=cashed] strong { font-size:12px; }
.act-btn[data-state=cashout] small,
.act-btn[data-state=cashed] small  { font-family:var(--fd); font-weight:700; font-size:12px; line-height:1.1; color:var(--act-title-color); }
/* Live multiplier while cashing out is white, with a dark-green edge so it stays readable on the bright green art. */
.act-btn[data-state=cashout] small,
.act-btn[data-state=cashed] small { color:#fff; text-shadow:0 1px 2px rgba(0,50,10,.75), 0 0 1px rgba(0,50,10,.6); }
.act-btn small  { position:relative; z-index:2; font-family:var(--fu); color:var(--act-sub-color); font-size:8px; display:block; line-height:1.2; }
.act-btn:active { transform:translateY(2px); filter:brightness(1.12); }
.act-btn:disabled { opacity:.82; cursor:not-allowed; }

/* ── ROW 2: Chips + BET button ─────────────────────────────── */
.chip-row {
  position: absolute;
  left: 0;
  top: 0;
  width: 100%;
  height: 92px;
  display: flex;
  align-items: flex-start;
  padding: var(--bp-chip-y) 0 0 var(--bp-chip-x);
  gap: var(--bp-chip-gap);
  flex-shrink: 0;
  /* No background of its own — lets .bottom-panel's sky-blue gradient
     flow through underneath uninterrupted, from the ctrl-row above. */
  background: transparent;
  border-top: 0;
  z-index: 2;
  pointer-events: none;
}

.chip {
  position: relative;
  flex: 0 0 var(--bp-chip-size);
  width: var(--bp-chip-size);
  min-width: var(--bp-chip-size);
  height: var(--bp-chip-size);
  display: flex; align-items: center; justify-content: center;
  background: transparent; border: none;
  cursor: pointer; padding: 0;
  pointer-events: auto;
  transition: transform .1s, filter .1s;
  -webkit-tap-highlight-color: transparent;
  overflow: visible;
}
/* The five chip PNGs are different sizes and each has transparent padding
   around the ~150px chip, so fitting the whole image into a square gave
   chips of different, too-small visible sizes with big gaps. Instead each
   image is scaled so its visible 150px chip is exactly --bp-chip-size wide
   and shifted so that chip's centre (--cx/--cy, from the PNG's alpha
   bounds) sits at the centre of the button. */
.chip { --k: calc(var(--bp-chip-size) / 150); }
.chip[data-v="10"]   { --iw:161; --ih:156; --cx:77;   --cy:77.5; }
.chip[data-v="50"]   { --iw:180; --ih:157; --cx:88.5; --cy:79.5; }
.chip[data-v="100"]  { --iw:188; --ih:161; --cx:91.5; --cy:82; }
.chip[data-v="500"]  { --iw:182; --ih:162; --cx:92;   --cy:82.5; }
.chip[data-v="1000"] { --iw:165; --ih:161; --cx:89.5; --cy:84.5; }
.chip img {
  position: absolute;
  left: calc(var(--bp-chip-size) / 2 - var(--cx) * var(--k));
  top:  calc(var(--bp-chip-size) / 2 - var(--cy) * var(--k));
  width:  calc(var(--iw) * var(--k));
  height: calc(var(--ih) * var(--k));
  max-width: none;
  max-height: none;
  transform-origin: calc(var(--cx) * var(--k)) calc(var(--cy) * var(--k));
  object-fit: fill;
  filter: drop-shadow(0 3px 8px rgba(0,0,0,.72));
  pointer-events: none;
  transition: filter .1s, transform .1s;
  display: block;
}
.chip[data-v="10"]:hover   img { filter:drop-shadow(0 3px 6px rgba(0,0,0,.6)) drop-shadow(0 0 6px rgba(92,228,255,.85));  transform:scale(1.05); }
.chip[data-v="50"]:hover   img { filter:drop-shadow(0 3px 6px rgba(0,0,0,.6)) drop-shadow(0 0 6px rgba(32,232,144,.85));  transform:scale(1.05); }
.chip[data-v="100"]:hover  img { filter:drop-shadow(0 3px 6px rgba(0,0,0,.6)) drop-shadow(0 0 6px rgba(255,208,32,.85));  transform:scale(1.05); }
.chip[data-v="500"]:hover  img { filter:drop-shadow(0 3px 6px rgba(0,0,0,.6)) drop-shadow(0 0 6px rgba(255,96,32,.85));   transform:scale(1.05); }
.chip[data-v="1000"]:hover img { filter:drop-shadow(0 3px 6px rgba(0,0,0,.6)) drop-shadow(0 0 6px rgba(184,72,252,.85));  transform:scale(1.05); }
.chip.active img { transform:scale(1.06); filter:drop-shadow(0 4px 8px rgba(0,0,0,.6)) drop-shadow(0 0 7px rgba(255,220,80,.72)); }
.chip.active { animation:chipPulse 1.4s ease-in-out infinite; }
@keyframes chipPulse { 0%,100%{filter:brightness(1)} 50%{filter:brightness(1.2) saturate(1.15)} }
.chip:active img { transform:scale(.92); filter:drop-shadow(0 2px 4px rgba(0,0,0,.75)) brightness(1.22); }

/* ── BLAST EXPLOSION ─────────────────────────────────────── */
.blast {
  position: absolute;
  z-index: 20;
  pointer-events: none;
  transform: translate(-50%, -50%);
  width: 1px; height: 1px;
  mix-blend-mode: screen;
  filter: drop-shadow(0 0 18px rgba(255, 125, 16, .62));
}
.blast-fireball {
  position: absolute;
  left: 50%; top: 50%;
  width: 150px; height: 150px;
  transform: translate(-50%, -50%) scale(.62) rotate(-8deg);
  transform-origin: 50% 50%;
  background: url("assets/rocket-crash-fireball-sprite.webp") 0 0 / 1200px 150px no-repeat;
  opacity: 0;
  animation: blastFireball .64s steps(8) both;
}
.blast-flare {
  position: absolute;
  left: 50%; top: 50%;
  width: 190px; height: 110px;
  transform: translate(-50%, -50%) rotate(-16deg) scale(.74);
  background: url("assets/crash-burst.svg") center / contain no-repeat;
  opacity: 0;
  filter: saturate(1.35) brightness(1.18) drop-shadow(0 0 18px rgba(255, 198, 40, .42));
  animation: blastFlare .54s ease-out both;
}
.blast-ring {
  position: absolute;
  left: 50%; top: 50%;
  width: 10px; height: 10px;
  border-radius: 50%;
  border: 3px solid rgba(255,218,64,.9);
  transform: translate(-50%, -50%) scale(1);
  /* `both` = backwards too: stays invisible during animation-delay
     instead of sitting there as a static dot */
  animation: blastRing .82s ease-out both;
}
.blast-ring.r1 {
  animation-delay: .08s;
  border-color: rgba(255,120,0,.72);
}
.blast-ring.r2 {
  animation-delay: .16s;
  border-color: rgba(255,60,36,.52);
}

.blast-core {
  position: absolute;
  left: 50%; top: 50%;
  width: 30px; height: 30px;
  border-radius: 50%;
  transform: translate(-50%,-50%) scale(0);
  background: radial-gradient(circle,
    #fff 0%, #fff8b8 18%, #ffe040 34%, #ff8c00 58%, rgba(255,50,0,.42) 80%, transparent 100%);
  box-shadow: 0 0 22px rgba(255, 232, 88, .72), 0 0 46px rgba(255, 86, 20, .48);
  animation: blastCore .62s ease-out forwards;
}

.blast-particle {
  position: absolute;
  left: 50%; top: 50%;
  width: 7px; height: 7px;
  border-radius: 50%;
  background: radial-gradient(circle, #fff 0 18%, #ffd74c 42%, #ff691f 72%, transparent 100%);
  box-shadow: 0 0 9px rgba(255, 170, 35, .72);
  transform: translate(-50%, -50%);
  animation: blastParticle .86s ease-out forwards;
}

@keyframes blastFireball {
  0%   { opacity: 0; background-position: 0 0; transform: translate(-50%, -50%) scale(.42) rotate(-8deg); filter: brightness(1.35) saturate(1.25); }
  10%  { opacity: 1; }
  72%  { opacity: .96; }
  100% { opacity: 0; background-position: -1200px 0; transform: translate(-50%, -50%) scale(1.16) rotate(8deg); filter: brightness(.9) saturate(.82) blur(.5px); }
}
@keyframes blastFlare {
  0%   { opacity: 0; transform: translate(-50%, -50%) rotate(-22deg) scale(.48); }
  18%  { opacity: .92; }
  100% { opacity: 0; transform: translate(-50%, -50%) rotate(-8deg) scale(1.22); }
}
@keyframes blastRing {
  0%   { width:10px;  height:10px;  opacity:0; transform:translate(-50%,-50%) scale(1); }
  8%   { opacity:.9; }
  100% { width:170px; height:170px; opacity:0; transform:translate(-50%,-50%) scale(1); }
}
@keyframes blastCore {
  0%   { transform:translate(-50%,-50%) scale(0); opacity:1; }
  36%  { transform:translate(-50%,-50%) scale(3.2); opacity:.94; }
  100% { transform:translate(-50%,-50%) scale(6.8); opacity:0; }
}
@keyframes blastParticle {
  0%   { opacity:1; transform:translate(-50%,-50%) translate(0,0) scale(var(--ps, 1)); }
  72%  { opacity:.86; }
  100% { opacity:0; transform:translate(-50%,-50%) translate(var(--px),var(--py)) scale(0.18); }
}
/* Cash-out popup: same bezel + glass-panel language as the modals and the
   cockpit, with the trophy art on a round navy badge sitting on the top edge. */
.win-overlay {
  /* Starts below the blank livestream area, like the modals, so the stream
     is never dimmed. */
  position:absolute; top:var(--blank-h); left:0; right:0; bottom:0; z-index:22;
  display:grid; place-items:center;
  background:rgba(2,14,32,.62);
  backdrop-filter:blur(2px);
}
.win-card {
  position:relative;
  width:230px;
  margin-top:34px;
  padding:52px 10px 10px;
  display:flex; flex-direction:column; align-items:center; gap:6px;
  border:2px solid #0a3055; border-radius:16px;
  background:linear-gradient(180deg,#86d3f3 0%,#4eaee3 45%,#2f86c8 100%);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.65), 0 0 0 1px rgba(150,205,240,.4), 0 0 34px rgba(255,201,64,.28), 0 12px 32px rgba(0,8,24,.6);
  animation:winIn .32s cubic-bezier(.34,1.56,.64,1) both;
}
@keyframes winIn { from{opacity:0;transform:scale(.8) translateY(-18px)} to{opacity:1;transform:scale(1) translateY(0)} }

.win-badge {
  position:absolute; left:50%; top:-40px; transform:translateX(-50%);
  width:84px; height:84px;
  display:grid; place-items:center;
  border-radius:50%;
  border:2px solid #082747;
  background:radial-gradient(circle at 50% 30%, #2a7fb0 0%, #0c3a63 60%, #072a4b 100%);
  box-shadow:inset 0 0 0 2px rgba(150,205,240,.5), inset 0 3px 5px rgba(255,255,255,.22), 0 0 0 3px rgba(255,201,64,.55), 0 4px 12px rgba(5,30,60,.6);
  animation:winGlow 1.4s ease-in-out infinite alternate;
}
.win-badge img { width:78px; height:78px; object-fit:contain; pointer-events:none; filter:drop-shadow(0 2px 3px rgba(3,20,45,.55)); }
@keyframes winGlow {
  from { box-shadow:inset 0 0 0 2px rgba(150,205,240,.5), inset 0 3px 5px rgba(255,255,255,.22), 0 0 0 3px rgba(255,201,64,.45), 0 4px 12px rgba(5,30,60,.6); }
  to   { box-shadow:inset 0 0 0 2px rgba(150,205,240,.5), inset 0 3px 5px rgba(255,255,255,.22), 0 0 0 3px rgba(255,214,90,.95), 0 0 20px rgba(255,201,64,.75), 0 4px 12px rgba(5,30,60,.6); }
}

.win-title {
  font-family:var(--fd); font-size:14px; font-weight:800; letter-spacing:2px;
  color:#062a4d; text-shadow:0 1px 0 rgba(255,255,255,.55);
}

/* Light glass panel, same fill and outline as the cockpit slots */
.win-panel {
  width:100%;
  padding:10px 8px 11px;
  display:flex; flex-direction:column; align-items:center; gap:7px;
  border:1.5px solid #0a3055; border-radius:11px;
  background:linear-gradient(180deg,#f4f9fd 0%,#d3e5f3 100%);
  box-shadow:inset 0 1px 3px rgba(10,48,85,.38), 0 1px 0 rgba(255,255,255,.5);
}
.win-amt {
  font-family:var(--fd); font-size:34px; font-weight:800; line-height:1; letter-spacing:.5px;
  font-variant-numeric:tabular-nums;
  color:#7b4c00; text-shadow:0 1px 0 rgba(255,255,255,.9), 0 2px 3px rgba(72,42,0,.25);
}
.win-mult {
  padding:3px 12px; border-radius:999px;
  background:linear-gradient(180deg,#6fe07a,#2f9e45); border:1px solid rgba(6,60,25,.5);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.45);
  font-family:var(--fn); font-size:13px; font-weight:800; color:#fff; text-shadow:0 1px 1px rgba(0,50,15,.55);
  font-variant-numeric:tabular-nums;
}

/* ── MODAL OVERLAYS (leaderboard / rules / exit) ─────────────── */
/* Same language as the top bar and cockpit: a sky-blue metal bezel (header
   + frame) around a light glass panel, dark-navy outlines, round navy
   badges/buttons, glossy pills. */
.modal-overlay {
  /* Starts below the blank livestream area, not inset:0 — this dark
     backdrop is only meant to dim the actual play UI while a modal
     (leaderboard/rules/exit) is open, not cover the transparent stream
     area above it, which needs to stay visible at all times. */
  position:absolute; top:var(--blank-h); left:0; right:0; bottom:0; z-index:26;
  display:grid; place-items:center;
  padding:18px;
  background:rgba(2,14,32,.66);
  backdrop-filter:blur(3px);
}
.modal-card {
  position:relative;
  width:100%; max-width:312px;
  max-height:92%;
  display:flex; flex-direction:column;
  border:2px solid #0a3055; border-radius:16px;
  background:linear-gradient(180deg,#86d3f3 0%,#4eaee3 45%,#2f86c8 100%);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.65), 0 0 0 1px rgba(150,205,240,.4), 0 12px 32px rgba(0,8,24,.6);
  overflow:hidden;
  animation:winIn .28s cubic-bezier(.34,1.56,.64,1) both;
}
.modal-card--sm { max-width:272px; text-align:center; }

/* Header sits on the bezel */
.modal-head {
  position:relative;
  flex-shrink:0;
  display:flex; align-items:center; gap:10px;
  padding:9px 10px 8px;
}
.modal-title {
  flex:1; min-width:0;
  font-family:var(--fd); font-size:13px; font-weight:800; letter-spacing:1.6px;
  color:#062a4d; text-align:left;
  text-shadow:0 1px 0 rgba(255,255,255,.55);
}
.modal-card--sm .modal-head { flex-direction:column; gap:6px; padding:12px 12px 8px; }
.modal-card--sm .modal-title { flex:none; text-align:center; }

/* Round navy badge, like the top-bar buttons, just bigger */
.modal-badge {
  flex-shrink:0;
  width:36px; height:36px;
  display:grid; place-items:center;
  border-radius:50%;
  border:1.5px solid #082747;
  background:radial-gradient(circle at 50% 28%, #1f6c9c 0%, #0c3a63 58%, #072a4b 100%);
  box-shadow:inset 0 0 0 1.5px rgba(150,205,240,.5), inset 0 2px 3px rgba(255,255,255,.22), 0 1px 2px rgba(5,30,60,.5);
  color:#8fdcff;
}
.modal-badge img { width:30px; height:30px; object-fit:contain; pointer-events:none; filter:drop-shadow(0 1px 1px rgba(3,20,45,.5)); }
.modal-badge svg { width:18px; height:18px; fill:currentColor; }
.modal-badge svg .ln { fill:none; stroke:currentColor; stroke-width:2.2; stroke-linecap:round; stroke-linejoin:round; }
.modal-card--sm .modal-badge { width:44px; height:44px; }
.modal-card--sm .modal-badge img { width:36px; height:36px; }
.modal-card--sm .modal-badge svg { width:22px; height:22px; }

.modal-close {
  flex-shrink:0;
  width:26px; height:26px;
  display:grid; place-items:center;
  border-radius:50%;
  border:1.5px solid #082747;
  background:radial-gradient(circle at 50% 28%, #1f6c9c 0%, #0c3a63 58%, #072a4b 100%);
  box-shadow:inset 0 0 0 1.5px rgba(150,205,240,.5), inset 0 2px 3px rgba(255,255,255,.22), 0 1px 1.5px rgba(5,30,60,.45);
  color:#ff9a9a;
  transition:filter .15s, transform .1s;
}
.modal-close svg { width:13px; height:13px; }
.modal-close svg .ln { fill:none; stroke:currentColor; stroke-width:2.4; stroke-linecap:round; }
.modal-close:hover  { filter:brightness(1.18); }
.modal-close:active { transform:scale(.92); }

/* Light glass body, same fill and outline as the cockpit slots */
.modal-body {
  flex:1; min-height:0;
  margin:0 8px 8px;
  padding:9px;
  overflow-y:auto;
  border:1.5px solid #0a3055; border-radius:11px;
  background:linear-gradient(180deg,#f4f9fd 0%,#d3e5f3 100%);
  box-shadow:inset 0 1px 3px rgba(10,48,85,.38), 0 1px 0 rgba(255,255,255,.5);
}
.modal-sub { font-family:var(--fu); font-size:12px; font-weight:600; color:#1c4670; line-height:1.55; }
.modal-sub strong { display:block; margin:2px 0; font-family:var(--fd); font-size:24px; font-weight:800; color:#7b4c00; text-shadow:0 1px 0 rgba(255,255,255,.9), 0 1px 2px rgba(72,42,0,.22); }

/* Leaderboard rows */
.lb-list { display:flex; flex-direction:column; gap:6px; }
.lb-list:empty::before { content:"No winners yet — be the first!"; padding:14px 6px; text-align:center; font-family:var(--fu); font-size:12px; font-weight:600; color:#4a7096; }
.lb-row {
  display:flex; align-items:center; gap:8px;
  padding:5px 9px 5px 6px; border-radius:10px;
  background:linear-gradient(180deg,#ffffff,#e2edf7);
  border:1px solid rgba(10,48,85,.3);
  box-shadow:0 1px 1.5px rgba(10,48,85,.16);
  font-family:var(--fu);
}
.lb-rank {
  flex-shrink:0; width:24px; height:24px;
  display:grid; place-items:center;
  border-radius:50%;
  border:1px solid rgba(10,48,85,.45);
  background:linear-gradient(180deg,#e6f0f9,#b9d0e6);
  font-family:var(--fd); font-size:10px; font-weight:800; color:#2b5b88;
  box-shadow:inset 0 1px 0 rgba(255,255,255,.7);
}
.lb-row:nth-child(1) .lb-rank { background:linear-gradient(180deg,#ffe08a,#f0a30a); border-color:#8a5200; color:#5a3300; }
.lb-row:nth-child(2) .lb-rank { background:linear-gradient(180deg,#f3f6fa,#aab8c6); border-color:#5b6b7b; color:#34424f; }
.lb-row:nth-child(3) .lb-rank { background:linear-gradient(180deg,#f2b989,#c2712f); border-color:#7a3f10; color:#4a2408; }
.lb-name { flex:1; min-width:0; font-size:12px; font-weight:700; color:#0a2f55; white-space:nowrap; overflow:hidden; text-overflow:ellipsis; }
.lb-mult {
  flex-shrink:0; padding:2px 8px; border-radius:999px;
  background:linear-gradient(180deg,#6fe07a,#2f9e45); border:1px solid rgba(6,60,25,.5);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.45);
  font-family:var(--fn); font-size:11px; font-weight:800; color:#fff; text-shadow:0 1px 1px rgba(0,50,15,.55);
  font-variant-numeric:tabular-nums;
}
.lb-amt { flex-shrink:0; min-width:58px; text-align:right; font-family:var(--fn); font-size:12.5px; font-weight:800; color:#7b4c00; font-variant-numeric:tabular-nums; text-shadow:0 1px 0 rgba(255,255,255,.9); }

/* Rules list — numbered navy badges instead of browser list markers */
.rules-list { list-style:none; counter-reset:rule; display:flex; flex-direction:column; gap:8px; font-family:var(--fu); font-size:11.5px; font-weight:600; line-height:1.45; color:#1c4670; }
.rules-list li { counter-increment:rule; position:relative; min-height:22px; padding-left:30px; }
.rules-list li::before {
  content:counter(rule);
  position:absolute; left:0; top:0;
  width:22px; height:22px; display:grid; place-items:center;
  border-radius:50%; border:1.5px solid #082747;
  background:radial-gradient(circle at 50% 28%, #1f6c9c 0%, #0c3a63 58%, #072a4b 100%);
  box-shadow:inset 0 0 0 1px rgba(150,205,240,.45);
  font-family:var(--fd); font-size:10px; font-weight:800; color:#8fdcff;
}
.rules-list strong { color:#b25e00; font-weight:800; }

/* Confirm / exited buttons — glossy pills, same colours as the game's buttons */
.modal-btn-row { display:flex; gap:10px; width:100%; margin-top:12px; }
.modal-btn {
  flex:1; height:36px; padding:0 10px; border-radius:999px;
  font-family:var(--fd); font-size:11.5px; font-weight:800; letter-spacing:1px; text-transform:uppercase;
  box-shadow:inset 0 1px 0 rgba(255,255,255,.5), 0 2px 3px rgba(5,30,60,.35);
  transition:filter .15s, transform .1s;
}
.modal-btn:hover  { filter:brightness(1.08); }
.modal-btn:active { transform:translateY(1px) scale(.98); }
.modal-btn--ghost {
  background:linear-gradient(180deg,#fafdff,#cfe2f2); border:1.5px solid #0a3055; color:#0a3055;
}
.modal-btn--danger {
  background:linear-gradient(180deg,#ff7d7d,#d02a2a); border:1.5px solid #6a0f0f;
  color:#fff; text-shadow:0 1px 1px rgba(80,0,0,.55);
}
.modal-btn--primary {
  background:linear-gradient(180deg,#ffd45c,#f0900a); border:1.5px solid #7a3a00;
  color:#4b2900; text-shadow:0 1px 0 rgba(255,240,170,.6);
}

/* Exiting freezes the board underneath */
.game[data-phase=exited] .flight-zone,
.game[data-phase=exited] .bottom-panel,
.game[data-phase=exited] .top-bar { filter:blur(2px) brightness(.5); pointer-events:none; }

/* ── RESPONSIVE ─────────────────────────────────────────────── */
/* No media queries here on purpose — .game is a fixed 375×730 design
   that's scaled as a whole via the --scale var (set by game.js's
   updateScale(), recalculated on load/resize/orientation-change) so
   it fits any viewport at any aspect ratio while every internal
   layout number in this file stays exactly as authored. */

/* ── REDUCED MOTION ─────────────────────────────────────────── */
@media (prefers-reduced-motion: reduce) {
  .sky-star { animation: none; opacity: .6; }
  *, *::before, *::after { animation-duration:.001ms !important; transition-duration:.001ms !important; }
}
