/* ============================================================
   PLUNDER v2 — full-bleed redesign.
   Loaded AFTER game.css and overrides layout only, so the original
   design is one <link> away (see index.html).
   ============================================================ */

html, body { height: 100%; overflow: hidden; }
body { background: #06121f; padding-bottom: 0; }

/* Replay embed (?replay=1): show ONLY the game scene with its real numbers —
   no chat panel, no bet bar (there is nothing to bet on in a past round). */
body.replay #panel, body.replay #betbar, body.replay #to-top { display: none !important; }
/* No jackpot in a replay. The pot is a live, forward-moving figure and it is not
   part of the hashed ledger block, so a viewer cannot verify it the way they can
   verify pools, winner and payouts. Rather than show a number that is either
   unverifiable or (for rounds settled before it was recorded) simply wrong,
   the bar is hidden — a replay only shows what the ledger can prove. */
body.replay #jackpot-bar { display: none !important; }

/* Spectator embed (?spectator=1): betting controls disabled, chat stays live.
   The buttons are visibly inert (dimmed + not clickable); the "SPECTATOR" overlay
   label was removed — it sat on top of the BET buttons and read as broken UI. */
body.spectator #bet-controls,
body.spectator #board-btns { pointer-events: none; opacity: .45; filter: grayscale(.4); }

/* ================= animated night-sea background ================= */
#bg { position: absolute; inset: 0; overflow: hidden; z-index: 0; background: #060b1e; }

/* Painterly night background (David "Movable Sea" scene, ported 1:1). A fixed
   1672×941 scene — the design's native coordinate space — scaled to COVER the
   stage so the baked moon, stars, clouds and waterline stay perfectly aligned at
   any viewport. Two stacked canvases: sky (2D: base + moon glow + stars + clouds)
   over water (WebGL living-wave shader). All motion is driven by nightbg.js. */
.plbg {
  position: absolute; left: 50%; top: 50%;
  width: 1672px; height: 941px;
  /* centred cover — keeps the baked top-right moon at its full position (uncropped) */
  transform: translate(-50%, -50%) scale(var(--plbg-s, 1));
  transform-origin: center;
}
.plbg-scene {
  position: absolute; left: 0; top: 0;
  width: 1672px; height: 941px; display: block; pointer-events: none;
}
/* mobile-only crescent moon (the baked moon is cropped off in portrait) */
.mobile-moon { display: none; }
/* a handful of extra glowing stars, on PC and mobile (in the upper-centre sky so
   they stay visible in portrait too) */
.glow-star {
  position: absolute; z-index: 2; width: 3px; height: 3px; border-radius: 50%;
  background: #fff; animation: starGlow 3s ease-in-out infinite;
}
.gs1 { top: 11%; left: 34%; animation-delay: 0s; }
.gs2 { top: 19%; left: 56%; animation-delay: 1.1s; }
.gs3 { top: 8%;  left: 47%; animation-delay: 2.2s; }
.gs4 { top: 23%; left: 40%; animation-delay: .6s; }
@keyframes starGlow {
  0%, 100% { opacity: .45; box-shadow: 0 0 4px 1px rgba(255,255,255,.5); }
  50% { opacity: 1; box-shadow: 0 0 11px 3px rgba(255,255,255,.95); }
}
@keyframes mMoonGlow { 0%, 100% { opacity: .5; transform: scale(1); } 50% { opacity: 1; transform: scale(1.28); } }

/* ---------------- full-bleed scene ---------------- */
#layout { display: block; padding: 0; margin: 0; height: 100%; gap: 0; }
#stage-wrap { position: fixed; inset: 0; z-index: 0; display: block; }

#stage {
  position: absolute; inset: 0;
  height: auto; max-height: none; min-height: 0; margin: 0;
  border: 0; border-radius: 0;
  box-shadow: inset 0 -120px 160px -60px rgba(2,6,14,.75);
  background: linear-gradient(#07182f 0%, #0a2547 34%, #10406c 58%, #092444 100%);
}
#sea, #fx { position: absolute; inset: 0; width: 100%; height: 100%; }

/* ---------------- loading screen ----------------
   Pure CSS/SVG — no three.js, no GLBs, nothing that waits on the module
   graph. Logo, then a minimalist night-sea scene (two wave layers scrolling
   in opposite directions, two bobbing ship silhouettes), then the real
   progress bar (driven by the inline script right after #loader in
   index.html) and the "Loading…" line. */
#loader {
  position: fixed; inset: 0; z-index: 200; display: grid; place-items: center;
  background: radial-gradient(120% 120% at 50% 40%, #0a1234 0%, #05070f 100%);
  transition: opacity .5s ease;
}
#loader.done { opacity: 0; pointer-events: none; }

/* Round-end screen wipe (see index.html + app.js showRoundTransition/
   hideRoundTransition). Fades in AFTER the loser has finished sinking, holds
   solid black through the reset, fades back out as Boarding opens — hiding
   the instant "ship snaps back upright" behind the black frame so it reads
   as a deliberate "new round starting" cue instead of a jump cut. Below the
   modal layer (z-index 1000) so settings/help still open on top if needed;
   above everything else in the scene/panel. */
#round-transition {
  position: fixed; inset: 0; z-index: 500;
  background: #000;
  opacity: 0; pointer-events: none;
  transition: opacity .35s ease;
}
#round-transition.show { opacity: 1; }
@media (prefers-reduced-motion: reduce) {
  #round-transition { transition: none; }
}
.loader-inner { text-align: center; display: flex; flex-direction: column; align-items: center; gap: 16px; }

.loader-logo {
  width: clamp(96px, 20vw, 200px); height: auto; display: block;
  filter: drop-shadow(0 0 26px rgba(217,164,65,.35));
  animation: loaderLogoIn .6s cubic-bezier(.2,1,.3,1) both;
}
@keyframes loaderLogoIn { from { opacity: 0; transform: translateY(-6px) scale(.96); } }

/* ---- the night-sea scene: waves + two bobbing ship silhouettes ---- */
.loader-scene {
  position: relative; width: min(340px, 78vw); height: 96px;
  border-radius: 10px; overflow: hidden;
  background: linear-gradient(180deg, rgba(10,18,40,0) 0%, rgba(6,12,28,.6) 100%);
}
.loader-moonglow {
  position: absolute; left: 50%; top: -30%; width: 140px; height: 140px;
  transform: translateX(-50%); border-radius: 50%; pointer-events: none;
  background: radial-gradient(circle, rgba(205,222,255,.16) 0%, rgba(205,222,255,0) 70%);
}
.wave-layer { position: absolute; left: 0; right: 0; bottom: 0; height: 40px; overflow: hidden; }
.wave-back { height: 46px; opacity: .55; }
.wave-front { height: 34px; opacity: .85; }
.wave-track { display: flex; width: 200%; height: 100%; }
.wave-track svg { width: 50%; height: 100%; flex: 0 0 auto; display: block; }
.wave-back .wave-track svg path { fill: rgba(120,150,205,.5); }
.wave-front .wave-track svg path { fill: rgba(178,199,235,.65); }
/* opposite directions: back layer scrolls left, front layer scrolls right —
   each track holds TWO copies of the same wave tile, so animating exactly
   -50%/0 loops seamlessly forever with no jump. */
.wave-back .wave-track { animation: waveScrollL 13s linear infinite; }
.wave-front .wave-track { animation: waveScrollR 9s linear infinite; }
@keyframes waveScrollL { from { transform: translateX(0); } to { transform: translateX(-50%); } }
@keyframes waveScrollR { from { transform: translateX(-50%); } to { transform: translateX(0); } }

.loader-ships {
  position: absolute; left: 0; right: 0; bottom: 18px;
  display: flex; justify-content: center; align-items: flex-end; gap: 30px;
}
.ship-silhouette { width: 54px; height: auto; transform-origin: 50% 90%; }
/* dark = Black Pearl, light = Interceptor — value contrast within the
   night palette rather than the ships' red/blue accent colors, so the
   loader stays moody/minimal instead of borrowing in-game UI accents. */
.ship-dark { color: #131a30; filter: drop-shadow(0 6px 10px rgba(0,0,0,.5)); animation: shipBob 3.4s ease-in-out infinite; }
.ship-light { color: #7f9dc9; filter: drop-shadow(0 6px 10px rgba(0,0,0,.4)); animation: shipBob 3.1s ease-in-out infinite; animation-delay: -1.4s; }
@keyframes shipBob {
  0%, 100% { transform: translateY(0) rotate(-1.6deg); }
  50% { transform: translateY(-5px) rotate(1.6deg); }
}
@media (prefers-reduced-motion: reduce) {
  .wave-back .wave-track, .wave-front .wave-track, .ship-dark, .ship-light { animation: none; }
}

.loader-sub { font-family: var(--mono); font-size: 13px; letter-spacing: 3px; text-transform: uppercase; color: #cdd7eb; }
.loader-dots::after { content: ""; animation: loaderDots 1.4s steps(4, end) infinite; }
@keyframes loaderDots { 0% { content: ""; } 25% { content: "."; } 50% { content: ".."; } 75% { content: "..."; } }

/* real progress bar — width is set by the inline driver script, not CSS */
.loader-bar { width: 180px; height: 4px; border-radius: 3px; background: rgba(255,255,255,.1); overflow: hidden; }
.loader-bar i { display: block; height: 100%; width: 0%; border-radius: 3px; background: #d9a441; }

@media (max-width: 480px) {
  .loader-scene { height: 78px; }
  .loader-ships { bottom: 14px; gap: 20px; }
  .ship-silhouette { width: 42px; }
}
@media (max-height: 480px) {
  /* mobile-landscape: the loader is short and wide — trim vertical rhythm */
  .loader-inner { gap: 10px; }
  .loader-logo { width: clamp(72px, 14vh, 120px); }
  .loader-scene { height: 62px; width: min(300px, 60vw); }
  .loader-ships { bottom: 10px; gap: 22px; }
  .ship-silhouette { width: 36px; }
}

/* ships ride the baked waterline (~54% of the David scene), stacked & separated so
   they never overlap: Black Pearl upper/back, Interceptor lower/near. */
#lane-port { top: 37%; height: 28%; }
#lane-star { top: 58%; height: 28%; }
.ship { width: clamp(180px, 19vw, 300px); }
.ship-img { width: 100%; height: auto; display: block; filter: drop-shadow(0 12px 20px rgba(0,0,0,.5)); }

/* ---------------- top bar ---------------- */
#topbar {
  position: fixed; top: 0; left: 0; right: 0; z-index: 30;
  display: flex; align-items: center; gap: 10px;
  padding: 10px 14px; background: none; border: 0; backdrop-filter: none;
}
.nav-left { display: flex; align-items: center; gap: 8px; flex: 0 0 auto; }
.brand { display: flex; align-items: center; margin-right: 6px; }
.brand h1 {
  font-family: var(--display); font-size: 22px; font-weight: 900; letter-spacing: 1.5px;
  color: #d9a441; margin: 0; line-height: 1; white-space: nowrap;
  /* navy badge like the favicon (navy square, gold letters) */
  background: #0b1020; padding: 8px 14px; border-radius: 10px;
  box-shadow: inset 0 0 0 1px rgba(217,164,65,.55);
}
.brand-p, .brand-rest { display: inline; background: none; box-shadow: none; width: auto; height: auto; }
.brand-sub { display: none; }
.nav-right { display: flex; align-items: center; gap: 8px; flex: 0 0 auto; }
.icon-btn {
  width: 34px; height: 34px; padding: 0; border-radius: 9px;
  display: flex; align-items: center; justify-content: center;
  background: #0a1526; border: 1px solid rgba(255,255,255,.2);
  color: #fff; font-weight: 800; font-size: 15px; line-height: 1;
}
.icon-btn:hover { background: #12233c; }
.icon-btn .micon { width: 18px; height: 18px; }
.icon-btn .gear-icon { width: 18px; height: 18px; }

/* ---------------- settings dropdown (gear icon) ---------------- */
.settings-wrap { position: relative; }
.settings-pop {
  position: absolute; top: calc(100% + 8px); left: 0; z-index: 60;
  min-width: 208px; padding: 8px; border-radius: 14px;
  /* glass effect: translucent + blurred, so the scene behind shows through */
  background: rgba(10,21,38,.55);
  backdrop-filter: blur(16px) saturate(160%);
  -webkit-backdrop-filter: blur(16px) saturate(160%);
  border: 1px solid rgba(255,255,255,.16);
  box-shadow: 0 16px 40px rgba(0,0,0,.5), inset 0 1px 0 rgba(255,255,255,.06);
  display: flex; flex-direction: column; gap: 2px;
  animation: settingsPopIn .16s ease-out;
}
.settings-pop[hidden] { display: none; }
@keyframes settingsPopIn {
  from { opacity: 0; transform: scale(.92) translateY(-4px); }
  to   { opacity: 1; transform: scale(1) translateY(0); }
}
.settings-row {
  display: flex; align-items: center; gap: 12px;
  width: 100%; padding: 10px; border-radius: 10px; border: 0; background: none;
  color: var(--text); font-size: 13.5px; font-family: inherit; text-align: left; cursor: pointer;
}
.settings-row:hover { background: rgba(255,255,255,.08); }
.sr-ic { width: 19px; height: 19px; flex: 0 0 auto; display: flex; color: #9db3c2; }
.sr-ic svg { width: 100%; height: 100%; }
.settings-row[aria-pressed="true"] .sr-ic { color: #01F4A0; }
.sr-label { flex: 1 1 auto; }
/* wide iOS-style switch */
.sr-switch {
  width: 42px; height: 22px; border-radius: 999px; flex: 0 0 auto; position: relative;
  background: rgba(255,255,255,.18); transition: background .18s ease;
}
.sr-switch i {
  position: absolute; top: 2px; left: 2px; width: 18px; height: 18px; border-radius: 50%;
  background: #fff; box-shadow: 0 1px 3px rgba(0,0,0,.45); transition: transform .18s ease;
}
.settings-row[aria-pressed="true"] .sr-switch { background: #01F4A0; }
.settings-row[aria-pressed="true"] .sr-switch i { transform: translateX(20px); }
.music-btn .mtext { display: none; }

/* CRASH STRIP — floating above the phase pill (#phase-ribbon, shifted down
   below to make room — see its own rule). One capsule per recent round.
   A past round is TWO crash points, not one — each ship draws its own,
   independently (server/crash.js) — so a normal crash game's single-number
   history pill doesn't fit. Each capsule stacks the Black Pearl's number
   over the Interceptor's: a coloured left edge says WHICH ship (matches the
   red/blue used on the bet buttons and ship cards everywhere else), and the
   number's own colour is heat — how far that ship got before she went down
   (same h-cold/h-low/h-mid/h-high/h-huge scale The Book uses). Scanning the
   strip answers "has this table been sinking early?" for both ships at once. */
#crash-strip {
  position: absolute; top: 8px; left: 50%; transform: translateX(-50%); z-index: 8;
  display: flex; gap: 6px; align-items: center;
  max-width: min(640px, 86vw); overflow-x: auto; overflow-y: hidden;
  padding: 2px 3px; scrollbar-width: none;
  /* fade the far edge instead of a hard clip, so a scrollable overflow reads
     as "more here" rather than looking like the strip just ends mid-pill */
  mask-image: linear-gradient(90deg, black calc(100% - 28px), transparent);
  -webkit-mask-image: linear-gradient(90deg, black calc(100% - 28px), transparent);
}
#crash-strip::-webkit-scrollbar { display: none; }
#crash-strip:empty::after {
  content: 'no rounds yet this session'; font-size: 11px; color: #8aa0a8; font-style: italic;
  white-space: nowrap; padding: 4px 2px;
}
.crash-pill {
  display: flex; flex-direction: column; gap: 1px; flex: 0 0 auto;
  padding: 3px 7px; border-radius: 7px; background: rgba(7,24,31,.72);
  border: 1px solid rgba(255,255,255,.12);
  font-family: var(--mono); font-size: 11px; line-height: 1.25; letter-spacing: -.01em;
}
/* newest pill: highlighted background + a pop-in on arrival */
#crash-strip .crash-pill:first-child {
  background: rgba(255,255,255,.1); border-color: rgba(255,255,255,.22);
  animation: crashPillIn .35s ease;
}
@keyframes crashPillIn { from { transform: scale(0); opacity: 0; } }
.cp-half { padding-left: 5px; border-left: 2px solid; }
.cp-port { border-left-color: #D92E15; }
.cp-star { border-left-color: #2E8FD9; }
/* heat: how far that ship got before she went down (mirrors The Book's scale) */
.cp-half.h-cold { color: #6b7f88; }
.cp-half.h-low  { color: #9fb4bd; }
.cp-half.h-mid  { color: #6fd39b; }
.cp-half.h-high { color: #ffce3a; }
.cp-half.h-huge { color: #ff8a3a; text-shadow: 0 0 6px rgba(255,138,58,.5); }
.cp-half.void   { color: #56666e; }

/* its own button beside the stepper; fixed width so ON/OFF never reflows */
.autobet-btn {
  flex: 1 1 0; width: auto; min-width: 0; height: 54px; margin: 0;
  padding: 0 8px; font-size: 13.5px; letter-spacing: .2px; border-radius: 13px;
  background: #08131f; border: 1px solid rgba(255,255,255,.14);
  color: var(--muted); text-align: center; white-space: nowrap; line-height: 1.15;
}
/* ON: keep the same gray background as OFF; only the border + text turn gold */
.autobet-btn.on { background: #08131f; color: var(--gold); border-color: var(--gold); }
/* hover: DON'T wash the background transparent (game.css default) — keep the gray
   and just turn the border + text gold, exactly like the clicked (.on) state. */
.autobet-btn:hover { background: #08131f; color: var(--gold); border-color: var(--gold); }

/* ---------------- floating scene chrome ---------------- */
/* phase pill — David's green-bordered status: pulse dot · label · clock, with a
   thin green progress bar directly beneath. */
#phase-ribbon {
  /* Sits just below the crash strip (#crash-strip, top:8px) — still pinned
     high in the scene, the pill is the one piece of chrome a player checks
     constantly, it just gave up the very top slot to the round history. */
  position: absolute; top: 56px; left: 50%; transform: translateX(-50%); z-index: 8;
  display: inline-flex; align-items: center; gap: 12px;
  padding: 7px 20px; border-radius: 12px; height: auto;
  background: rgba(7,24,31,.82); border: 1px solid #f5c542;   /* yellow, matches the timer bar */
}
#phase-ribbon::before {
  content: ""; width: 8px; height: 8px; border-radius: 50%; flex: 0 0 auto;
  background: #f5c542; box-shadow: 0 0 8px #f5c542;
  animation: phaseDotPulse 1.4s ease-in-out infinite;
}
@keyframes phaseDotPulse { 0%,100% { opacity: 1; } 50% { opacity: .35; } }
#phase-label { font-size: 18px; font-weight: 700; letter-spacing: .14em; color: #f4efe4; }
#phase-clock { font-size: 18px; font-weight: 700; color: #01F4A0; }
#timerbar {
  position: absolute; top: 96px; left: 50%; transform: translateX(-50%);
  width: 220px; height: 4px; border-radius: 2px;
  background: rgba(7,24,31,.7); overflow: hidden; z-index: 8;
}
/* The phase pill and its bar only matter for Boarding — the one phase with
   an actual deadline the player needs to plan around ("bet now, this long
   left"). Flight has no fixed length (it ends when the second ship sinks,
   which nobody knows in advance) and its clock only ever counted UP as
   elapsed time — not useful information, just a number climbing next to
   the ships. Between rounds there is nothing to time either. So the pill
   and bar show ONLY during Boarding. Driven by body.phase-* from ui.js
   setPhase(). */
#phase-ribbon, #timerbar { transition: opacity .25s ease; }
body:not(.phase-boarding) #phase-ribbon,
body:not(.phase-boarding) #timerbar {
  opacity: 0; pointer-events: none;
}

/* jackpot rides right next to the LAST-10 game history, as its own separated chip
   (all screen sizes). */
#jackpot-bar {
  position: static; transform: none; height: auto; box-sizing: border-box;
  display: inline-flex; align-items: center; justify-content: center; gap: 5px; flex: 0 0 auto;
  margin-left: 0; padding: 4px 12px; font-size: 12px; white-space: nowrap;
  min-width: 208px;                          /* fixed footprint — text change never moves it */
  background: #0a1526;                        /* solid, like the BET buttons: nothing shows through */
  border-radius: 11px;                        /* match the Last Rounds pill */
  backdrop-filter: none; -webkit-backdrop-filter: none;
}
/* dropping: opaque, and it must NEVER move — the old jackpotHot keyframes
   translateX(-50%) (a leftover from absolute centering) yanked it left, and the
   font-size bump resized it. Override both: same size, pulse glow only. */
#jackpot-bar.hot {
  background: #241a08; border-color: var(--gold); font-size: 12px;
  animation: jackpotHotPulse 1s ease-in-out infinite;
}
@keyframes jackpotHotPulse {
  0%, 100% { box-shadow: 0 0 14px rgba(245,197,66,.4); }
  50% { box-shadow: 0 0 30px rgba(245,197,66,.8); }
}
#jackpot-bar #jackpot-eta { font-size: 11px; }
#timerbar-fill { background: #01F4A0; }   /* green by default; fog/race keep their tints */

/* on-ship readouts stay: the pool per ship is the core read of the game */
#cards {
  position: absolute; inset: 0; z-index: 6; pointer-events: none;
  display: block; margin: 0; grid-template-columns: none;
}
/* the phase pill already names the phase — hide the redundant centre notes */
#fog-note { display: none; }

/* Small pill that hugs its text — NEVER a stretched box. Explicitly pins
   every box-model axis (width/height auto to content, bottom/right auto)
   so no OTHER stylesheet/breakpoint can reintroduce the old bug: a leftover
   mobile rule (game.css) set `bottom` on #card-star without `top` ever being
   unset, so with both top AND bottom pinned the browser stretched it to
   fill the whole gap between them — a huge translucent box. Declaring
   height/bottom/right here, on the single shared class both cards use,
   means that can't happen again regardless of what any other rule does. */
.ship-card {
  position: absolute; left: 22px; top: auto; right: auto; bottom: auto;
  width: auto; height: auto; max-width: 150px; box-sizing: border-box;
  min-height: 0; justify-content: center; align-items: center; gap: 2px;
  padding: 8px 14px; border-radius: 12px;
  background: rgba(6,14,26,.72); border: 1px solid rgba(255,255,255,.12);
  pointer-events: auto;
}
/* Card position — sits right above each ship's mast. Now shows ONLY the
   ship name — GAME-ECONOMY-DESIGN.md §1 forbids showing per-ship pool size
   or coefficient, so those readouts are gone (see index.html) and the name
   label — previously hidden by this same redesign layer to make room for
   them — is back, since a card with nothing in it at all reads as a bug.
   Both ships use the IDENTICAL .ship-card/.card-name style — only position
   and accent color (the inset box-shadow tint) differ. `left` marks each
   ship's horizontal CENTER (translateX(-50%)), not its left edge — same
   fix as mobile portrait's ≤620 override below, measured live the same way
   (window.__plunderShipBounds() projects the real 3D hull to screen %) at
   1440×900: Black Pearl centers ~38.5% across / masthead top ~38.5%,
   Interceptor centers ~18.4% / masthead top ~35.7%. The old left:55%/40%
   values (pre-transform, i.e. left EDGE not center) put both cards well to
   the right of and below their actual ships. */
#card-port { left: 38.5%; top: 31%; transform: translateX(-50%); box-shadow: inset 0 0 0 1px rgba(226,73,59,.4); }
#card-star { left: 18.4%; top: 28%; transform: translateX(-50%); box-shadow: inset 0 0 0 1px rgba(110,168,224,.4); }
/* The name is authored with an explicit <br> ("Black<br>Pearl",
   "The<br>Interceptor") — nowrap defeated that and made a single long line
   that clipped to "THE INTERCEPTOI" at narrower card widths. Let it break
   on its own line breaks instead; the card now carries a multiplier under
   the name, so vertical room is cheaper than horizontal. */
.ship-card .card-name {
  display: flex; max-width: 100%;
  white-space: normal; text-align: center;
}
/* A sunk ship's card goes down WITH her. It holds on its frozen crash value
   long enough to read (the 1.1s delay), then fades out over the back half of
   the hull's descent, so the label never outlives the ship it points at.
   The number is not lost: the bet button reports what happened to that bet,
   and the round's two crash points land in the history strip when it seals.
   Delay + duration together stay inside webgl-scene.js's SINK_DURATION. */
.ship-card { transition: opacity .5s ease; }
.ship-card.sunk {
  opacity: 0; pointer-events: none;
  transition: opacity 1s ease 1.1s;
}

/* The banner is centred at 50%/50% in game.css, which lands it straight on top of
   #card-star (left 40%, top 44%) — so the sunk ship's stake was unreadable exactly
   when you most want to check it against the result. Drop it into the clear water
   below both readouts and above the bet bar. */
#banner { top: 70%; }

/* ---------------- live panel ---------------- */
/* full height, from under the top bar to the floor.
   height:auto is REQUIRED — game.css sets height:100%, and top+height+bottom
   over-constrains the box so `bottom` gets ignored and the panel overflows. */
/* bottom edge lines up with the BET buttons (both 12px off the floor), so sea
   shows underneath the panel exactly like it does under the buttons */
#panel {
  /* starts just under the moon (top-right); ~45px taller than before */
  position: fixed; right: 12px; top: 165px; bottom: 12px; height: auto; width: 320px; z-index: 20;
  display: flex; flex-direction: column; gap: 0; min-height: 0;
  background: rgba(4,10,20,.92);
  border: 1px solid rgba(255,255,255,.12);
  border-radius: 14px; overflow: hidden; padding: 0 0 10px;
  backdrop-filter: blur(4px);
}
/* all three tabs share one blue bar; active tab is a dark chip */
#tabs { display: flex; gap: 4px; padding: 5px; background: #2E8FD9; border: 0; margin: 0; }
#tabs .tab {
  flex: 1; padding: 7px 6px; border: 0; border-radius: 8px;
  background: none; color: #06263f; font-weight: 700; font-size: 12.5px; letter-spacing: .2px;
}
#tabs .tab.sel { background: #08131f; color: #fff; }

#panel-stats { display: flex; gap: 12px; padding: 14px 16px 10px; }
.pstat { flex: 1; text-align: center; }
.pstat b {
  display: block; font-size: 21px; font-weight: 800; color: #fff;
  border-bottom: 2px solid rgba(255,255,255,.45); padding-bottom: 5px;
}
.pstat span {
  display: block; font-size: 11px; color: var(--muted); margin-top: 6px;
  text-transform: uppercase; letter-spacing: .8px;
}

/* race / sinking / intermission: betting closed → the whole bottom control cluster
   (stake stepper, chips, auto-rebet) is blocked, matching the disabled bet buttons. */
#betbar.locked #bet-controls {
  opacity: .4; pointer-events: none; filter: grayscale(.35);
  transition: opacity .2s ease;
}
/* both bet buttons share the same start and width so they read as a matched pair */
#board-btns { display: flex; gap: 10px; align-items: stretch; }
#board-btns .board { flex: 1 1 0; min-width: 0; }

/* the `hidden` attribute must win over game.css display rules */
#topbar [hidden], #betbar [hidden] { display: none !important; }
/* tabs on top, then the two headline stats, then the list */
#tabs { order: 0; }
#panel-stats { order: 1; }
.tabpane { order: 2; }

.tabpane { flex: 1 1 auto; min-height: 0; display: flex; flex-direction: column; }
.tabpane[hidden] { display: none; }

/* live bets table — masked name | stake | outcome. One row per bet, styled
   like The Book's rows (ship-coloured, WON green / LOST gray) — see
   ui.js addBetRow/resolveBetWin/resolveBetLoss, which update a row IN PLACE
   as its outcome resolves rather than appending a second line. */
.bet-row {
  display: grid; grid-template-columns: minmax(0,1fr) 68px 88px; gap: 16px; align-items: baseline;
  padding: 7px 8px 7px 2px; border-bottom: 1px solid rgba(255,255,255,.06);
  font-size: 12.5px;
}
.br-name { color: #cfd8e6; letter-spacing: .5px; font-weight: 600; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.bet-row.port .br-name { border-left: 2px solid var(--port); padding-left: 7px; }
.bet-row.star .br-name { border-left: 2px solid var(--star); padding-left: 7px; }
/* stake and outcome are fixed-width columns, both right-aligned, so the
   numbers form two clean vertical columns down the whole list instead of
   drifting left/right with each name's length. */
.br-stake { color: #fff; font-weight: 600; text-align: right; white-space: nowrap; font-variant-numeric: tabular-nums; }
.br-win { text-align: right; white-space: nowrap; font-variant-numeric: tabular-nums; }
.br-win.pending { color: #8a97a8; font-style: italic; font-weight: 500; }
.br-win.won { color: #01F4A0; font-weight: 700; }
.br-win.lost { color: #8a97a8; font-weight: 600; text-transform: uppercase; letter-spacing: .5px; font-size: 11px; }
#feed-bets, #feed {
  flex: 1 1 auto; min-height: 0; height: auto; max-height: none;
  overflow-y: auto; padding: 2px 14px 12px;
}
/* chat composer: 5px clear of both panel edges */
#chat-form { box-sizing: border-box; padding-left: 5px; padding-right: 5px; }
/* Send button uses the same blue as the tab bar */
#chat-form button { background: #2E8FD9; color: #06263f; }
/* back-to-game button: ↑ arrow, matched to the Send button — same blue, size, shape */
#to-top {
  gap: 0; padding: 10px 22px; font-size: 16px; line-height: 1; border-radius: 10px;
  background: #2E8FD9; color: #06263f; border: 0; font-weight: 800;
  backdrop-filter: none; box-shadow: 0 4px 14px rgba(0,0,0,.4);
  right: 14px;   /* line up with the Send button's right edge */
}
/* usernames (chat + bets) are gold, like the bet buttons; chat messages stay light,
   bet stakes/wins stay green. */
#feed .msg { color: #eef3f5; }
#feed .msg .who { color: var(--gold); font-weight: 700; font-family: var(--mono); }
#feed .msg .who-you { color: #fff; }      /* "(You)" marks your own messages */
#tab-bets .br-name { color: var(--gold); }
#tab-bets .br-stake { color: #01F4A0; }
#tab-bets .br-win.pending { color: #8a97a8; }
#tab-bets .br-win.won { color: #01F4A0; }
#tab-bets .br-win.lost { color: #8a97a8; }

/* The book — each round shows BOTH ships (winner + loser) with (WON)/(LOST) and pot.
   Ship names keep their colour, WON is green, LOST is gray, pots are gold. No slash. */
#rounds-list li { align-items: center; gap: 10px; }
#rounds-list .r-round { font-family: var(--mono); color: #8a97a8; flex: 0 0 auto; }
#rounds-list .r-body { flex: 1; display: flex; flex-direction: column; gap: 3px; min-width: 0; }
#rounds-list .r-line { display: flex; align-items: baseline; gap: 6px; font-size: 12.5px; }
#rounds-list .r-line.port .r-ship { color: var(--port); }
#rounds-list .r-line.star .r-ship { color: var(--star); }
#rounds-list .r-ship { font-weight: 600; white-space: nowrap; }
#rounds-list .r-res { font-size: 10.5px; text-transform: uppercase; letter-spacing: .5px; }
#rounds-list .r-res.won { color: #01F4A0; }
#rounds-list .r-res.lost { color: #8a97a8; }
#rounds-list .r-pot { margin-left: auto; font-family: var(--mono); white-space: nowrap; }
#rounds-list .r-line.won .r-pot { color: #01F4A0; }   /* winner pot green, like (WON) */
#rounds-list .r-line.lost .r-pot { color: #8a97a8; }  /* loser pot gray, like (LOST) */
/* line the note up with where the round numbers start */
#tab-book .pane-note { margin-left: 9px; }

/* (unused) Daily/Weekly/Monthly winner styles — kept harmless in case re-enabled */
#winners-cats { display: flex; gap: 5px; margin: 2px 0 8px; }
.wcat {
  flex: 1; padding: 6px 4px; border: 1px solid rgba(46,143,217,.5); border-radius: 8px;
  background: transparent; color: #9fb6cc; font-weight: 700; font-size: 12px; cursor: pointer;
}
.wcat.sel { background: #2E8FD9; color: #06263f; border-color: #2E8FD9; }
#winners-list { list-style: none; margin: 0 0 12px; padding: 0; display: flex; flex-direction: column; gap: 4px; }
#winners-list li { display: flex; align-items: center; gap: 10px; font-size: 12.5px;
  background: rgba(255,255,255,.04); padding: 6px 10px; border-radius: 8px; }
#winners-list .w-rank { font-family: var(--mono); color: #8a97a8; width: 16px; }
#winners-list .w-name { flex: 1; color: var(--gold); font-family: var(--mono); font-weight: 700; }
#winners-list .w-net { font-family: var(--mono); color: #01F4A0; font-weight: 700; }
#winners-list .w-empty { color: var(--muted); font-style: italic; background: none; justify-content: center; }
.book-note { margin-top: 4px; }


/* ---------------- bet bar ---------------- */
/* The bar STOPS before the panel (right:348px) rather than just padding itself —
   otherwise its background sheet covers the panel's bottom and hides the chat input. */
#betbar {
  position: fixed; left: 0; right: 344px; bottom: 0; z-index: 30;
  display: flex; align-items: stretch; gap: 12px; padding: 10px 0 12px 14px;
  background: none;          /* the sea shows through behind the controls */
}
#balance-box {
  flex: 0 0 auto; min-width: 136px; text-align: center;
  background: #08131f; border: 1px solid rgba(255,255,255,.14);
  border-radius: 13px; padding: 13px 18px;
  display: flex; flex-direction: column; justify-content: center;
}
.bb-label {
  font-size: 11px; letter-spacing: 1.6px; text-transform: uppercase; color: var(--muted);
}
#you-balance { font-size: 21px; font-weight: 800; color: #24d98a; margin-top: 5px; }

/* fixed column width: the chips row fills it, and the stepper + Auto Rebet span
   exactly the same width above it. Everything left over goes to the BET buttons. */
#bet-controls { flex: 0 0 414px; width: 414px; display: flex; flex-direction: column; gap: 8px; justify-content: center; }
/* transparent row — the stepper and Auto Rebet are two SEPARATE controls */
#custom-row {
  display: flex; align-items: center; gap: 8px; margin: 0; width: 100%;
  background: none; border: 0; border-radius: 0; padding: 0;
}
/* the bet field and Auto Rebet share the row equally (same width) */
#stepper {
  flex: 1 1 0; display: flex; align-items: center; gap: 4px;
  background: #08131f; border: 1px solid rgba(255,255,255,.14);
  border-radius: 13px; padding: 6px;
}
.step-btn {
  width: 40px; height: 40px; flex: 0 0 auto; border-radius: 10px; border: 0;
  background: rgba(255,255,255,.07); color: #fff; font-size: 22px; font-weight: 800; line-height: 1;
}
.step-btn:hover { background: rgba(255,255,255,.14); }
/* min-width:0 lets the field shrink below the <input>'s intrinsic size, so the
   chips row — not the input — decides how wide this column is */
.custom-field { flex: 1 1 auto; min-width: 0; border: 0; background: none; padding: 0 6px; }
.custom-field:focus-within { border-color: transparent; }
#custom-bet { width: 100%; min-width: 0; text-align: center; font-size: 17px; font-weight: 700; color: #fff; padding: 0; }

#chips { display: flex; flex-wrap: nowrap; gap: 5px; margin: 0; }
/* #chip-list holds the 4 bracket-driven fixed-stake buttons (see
   ui.renderChips()) — it's a flex container in its own right so they split
   evenly, and claims 4 "units" of #chips's row alongside 2X/5X (1 unit
   each) so the row's proportions stay the same shape as before. */
#chip-list { display: flex; gap: 5px; flex: 4 1 0; min-width: 0; }
#chips .chip, #chips .scale-btn {
  flex: 1 1 0; padding: 8px 7px; min-width: 40px; text-align: center;
  border-radius: 9px; font-size: 13.5px; font-weight: 600;
  background: #08131f; border: 1px solid rgba(255,255,255,.14); color: #cfd8e6;
}
#chips .chip.sel { background: rgba(211,162,75,.18); color: var(--gold); border-color: var(--gold-dim); }
/* "cap hit" flash (Task 3) — briefly rings the bet field when a control
   (chip/2X/5X/stepper/typed value) tried to go past this table's range and
   got clamped back into it. */
.custom-field.capped { animation: chipCapped .32s ease; }
@keyframes chipCapped { 30% { box-shadow: 0 0 0 2px rgba(226,73,59,.6); } }

#board-btns { flex: 1 1 auto; display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
.board {
  min-height: 96px; border-radius: 14px; padding: 10px;
  background: #0a1526; border: 2px solid #1d3b5e;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 3px;
}
.board.port { border-color: rgba(226,73,59,.65); background: linear-gradient(#12202f, #0d1826); }
.board.star { border-color: rgba(110,168,224,.65); background: linear-gradient(#101f31, #0c1927); }
.board .b-title { display: flex; flex-direction: column; align-items: center; gap: 2px; }
.b-verb { font-size: 20px; font-weight: 800; color: #fff; letter-spacing: 1px; white-space: nowrap; }
.b-ship { font-size: 13px; font-weight: 700; }
.board.port .b-ship { color: var(--port); }
.board.star .b-ship { color: var(--star); }
.b-mult { font-size: 15px; font-weight: 800; color: var(--gold); min-height: 0; white-space: nowrap; }
/* fixed button footprint — every state is now 3 single lines, so the size never changes */
.board { overflow: hidden; }
.board:disabled { opacity: .5; }

#foot { display: none; }   /* disclaimer lives in the Info dialog, not as a black band */

/* ---------------- laptops & tablets (…1240px) ----------------
   The side panel still fits here, but balance + controls + panel no longer do.
   Move the balance to the top-right corner and tighten everything so the BET
   buttons keep real width. Must come BEFORE the phone block so phones win. */
@media (max-width: 1240px) {
  #topbar { padding-right: 132px; }        /* reserve the corner for the balance */
  #balance-box {
    position: fixed; top: 6px; right: 10px; z-index: 40;
    flex: 0 0 auto; min-width: 0; width: auto;
    flex-direction: row; align-items: center; gap: 6px;
    padding: 6px 11px; border-radius: 10px;
  }
  #balance-box .bb-label { display: none; }
  #you-balance { font-size: 15px; margin: 0; }

  #panel { width: 284px; }
  #betbar { right: 308px; }
  #bet-controls { flex: 0 0 356px; width: 356px; }
  .autobet-btn { flex: 1 1 0; width: auto; font-size: 12.5px; }
  #chips .chip, #chips .scale-btn { font-size: 12px; padding: 7px 4px; }
  .board { min-height: 86px; }
  /* only the last line ("YOUR SPLIT ×n" / "bet $x → win $y") is long — shrink JUST
     that one so it never clips; the BET / ship-name lines keep their size. */
  .b-mult { font-size: 12px; }
}
/* the tight laptop band just ABOVE the 1240 tier: the side panel is still full
   width so the BET buttons get squeezed. Same idea — only the last line shrinks. */
@media (min-width: 1241px) and (max-width: 1560px) {
  .b-mult { font-size: 12.5px; }
}
/* the very tightest desktop band (just above the 1240 layout tier): full-width side
   panel + balance gutter squeeze the BET buttons hardest, so "bet $x → win $y"
   nearly breaks the box — shrink JUST that last line further here. */
@media (min-width: 1241px) and (max-width: 1360px) {
  .b-mult { font-size: 10.5px; letter-spacing: 0; }
}

/* ---------------- phones: normal page flow ----------------
   The first screen is ALL scene + controls; the chat sits below the fold and you
   scroll to reach it. Nothing is fixed, so nothing can cover the controls.
   #layout uses display:contents so stage / bet bar / chat become siblings we can
   order directly on the body flex column. */
@media (max-width: 1000px) {
  html, body { height: auto; min-height: 100%; overflow-x: hidden; overflow-y: auto; }
  body { display: flex; flex-direction: column; position: relative; }
  /* drop the laptop tier's balance gutter: here the balance is fixed top-right and
     the history is its own full-width row, so the reserve would just crop it */
  #topbar { flex-wrap: wrap; padding-right: 14px; }
  #layout { display: contents; }

  /* crash strip: a touch smaller, still centred above the phase pill */
  #crash-strip { max-width: 92vw; top: 6px; }
  .crash-pill { padding: 2px 6px; font-size: 10px; }

  /* Balance belongs to the header's top-right and must scroll away with it, not
     follow the viewport. It lives inside #betbar (which is absolute at the bottom
     of the first screen), so we offset back up by exactly that distance to land
     at page y=6. --betbar-h is measured in app.js, so this stays exact. */
  #balance-box {
    position: absolute; right: 10px;
    top: calc(10px - (100svh - var(--betbar-h, 200px)));
    height: 34px; box-sizing: border-box;
  }

  /* the scene owns the WHOLE first screen; the bars float on top of it */
  #stage-wrap { position: relative; order: 1; height: 100svh; }
  #stage { position: absolute; inset: 0; height: auto; border-radius: 0; }

  /* bars are absolute against <body>, so they scroll away with the page and the
     chat still begins at exactly 100svh (below the fold) */
  /* above #betbar (z-index 30) so the music volume popover overlays the balance
     (which lives inside #betbar and would otherwise render on top). */
  #topbar { position: absolute; top: 0; left: 0; right: 0; z-index: 50; }
  #betbar {
    position: absolute; left: 0; right: 0; z-index: 30; bottom: auto;
    top: calc(100svh - var(--betbar-h, 200px));
    padding: 8px 10px 12px;
  }
  #bet-controls { flex: 1 1 auto; width: auto; }   /* the desktop 414px cap doesn't apply */
  #board-btns { grid-template-columns: 1fr 1fr; }
  /* only the last line ("YOUR SPLIT ×n" / "bet $x → win $y") overflows on tablets —
     shrink just it, leave the BET / ship-name lines alone. */
  .b-mult { font-size: 12.5px; }

  /* SHIPS ON THE WATER (tablets + phones): the bars float at the bottom here, so
     over-scale the sea to fill the frame and lift it — otherwise on tall/narrow
     tablets the painted horizon sits mid-screen and the ships float in the sky.
     Black Pearl rides the water; the Interceptor anchors just above the buttons. */
  .plbg {
    top: 50%;
    transform: translate(-50%, calc(-50% - 60px)) scale(calc(var(--plbg-s, 1) * 1.2));
  }
  #lane-port { top: 46%; height: 16%; }
  #lane-star { top: calc(var(--controls-top, 700px) - 150px); height: 16%; }
  .ship { width: clamp(150px, 30vw, 230px); }

  #panel {
    position: static; order: 3; left: auto; right: auto; top: auto; bottom: auto;
    width: auto; height: 78vh; max-height: none; margin: 6px 8px 10px;
  }
}
/* narrow tablets / large phones (621–900px): the two BET buttons are cramped, so
   even "JUMP HERE" / "THE INTERCEPTOR" clip — shrink all three lines so nothing
   breaks the box. */
@media (min-width: 621px) and (max-width: 900px) {
  .b-verb { font-size: 15px; letter-spacing: .4px; }
  .b-ship { font-size: 10px; letter-spacing: .2px; }
  .b-mult { font-size: 11px; letter-spacing: 0; }
}
/* Mobile-landscape — REAL devices, not devtools' responsive-mode preview:
   a real phone's browser chrome (address bar, tab strip, etc.) eats real
   vertical space devtools doesn't show, so actual landscape viewports run
   shorter than a clean "844×390" figure suggests. Scoped by short height,
   not a width range, since landscape widths vary a lot across phones/
   tablets — max-height 460 (not 420) leaves room for that visible chrome. */
@media (min-width: 621px) and (max-height: 460px) {
  /* 1. Shorter bet bar/board buttons — trades some touch-target size for a
     visibly bigger strip of ships + sea above the controls. */
  #betbar { padding: 6px 10px 8px; gap: 8px; }
  #bet-controls { gap: 5px; }
  .board { min-height: 56px; padding: 6px 8px; }
  .b-verb { font-size: 15px; }
  .b-ship { font-size: 9.5px; }
  .b-mult { font-size: 10px; }
  #stepper { padding: 4px; }
  .step-btn { width: 30px; height: 30px; font-size: 17px; }
  #custom-bet { font-size: 15px; }
  .autobet-btn { height: 36px; font-size: 11.5px; }
  #chips .chip, #chips .scale-btn { padding: 6px 5px; font-size: 11.5px; min-width: 32px; }

  /* 2. crash strip: centred the same way it already is on desktop, sized
     for the tighter landscape topbar. */
  #crash-strip { top: 12px; max-width: 70vw; }
  .crash-pill { padding: 2px 5px; font-size: 9.5px; }

  /* 3. Ship-name labels: dropped entirely on landscape. Almost everyone
     reaches landscape by rotating out of portrait, where they already know
     which ship is which — the pills just cost space here for no new info,
     and the BET buttons are labelled with the ship name anyway. */
  .ship-card { display: none; }

  /* 4. Smaller live phase pill, now that the topbar is one row. Already
     centered via its own base rule's left:50%/translateX(-50%) — untouched
     here, so it lines up under the crash strip above. */
  #phase-ribbon { top: 54px; padding: 5px 10px; gap: 6px; }
  #phase-label, #phase-clock { font-size: 13px; }
  #phase-ribbon::before { width: 6px; height: 6px; }
  #timerbar { top: 88px; width: 150px; }

  /* 5. Same fix as portrait: the result banner's length varies round to
     round, so centering it on a fixed point risks it growing low enough to
     sit on the bet controls. Anchor to the bet bar's live-measured height
     and grow upward instead — can never reach the controls either way. */
  #banner {
    top: auto; bottom: calc(var(--betbar-h, 140px) + 10px);
    left: 50%; transform: translateX(-50%);
    max-width: min(calc(100% - 32px), 480px);
    animation-name: bannerinBottom;
  }
}
@media (max-width: 620px) {
  #betbar { flex-wrap: wrap; gap: 8px; padding: 8px 10px 12px; }
  #balance-box { min-width: 0; flex: 1 1 40%; padding: 8px 12px; }
  #balance-box .bb-label { font-size: 9.5px; }
  #you-balance { font-size: 16px; }
  /* balance rides in the top-right of the page (as it did before), freeing its
     whole row in the bet bar for the scene and controls */
  /* see the ≤1000 rule: offset up out of #betbar so it sits in the header corner.
     34px + top 10px matches the icon buttons exactly, so the row reads as one. */
  #balance-box {
    position: absolute; right: 10px; z-index: 40;
    top: calc(10px - (100svh - var(--betbar-h, 200px)));
    height: 34px; box-sizing: border-box;
    flex: 0 0 auto; min-width: 0; width: 116px;   /* match the jackpot pill width */
    flex-direction: row; align-items: center; justify-content: center; gap: 6px;
    padding: 0 10px; border-radius: 9px;
  }
  #balance-box .bb-label { display: none; }
  #you-balance { font-size: 15px; margin: 0; }
  #bet-controls { flex: 1 1 100%; }
  #custom-row { padding: 0; border-radius: 11px; }
  .step-btn { width: 38px; height: 38px; font-size: 20px; }
  #custom-bet { font-size: 17px; }
  #chips { flex-wrap: nowrap; }
  #chips .chip, #chips .scale-btn {
    flex: 1 1 0; min-width: 0; padding: 8px 4px; font-size: 12.5px;
  }
  #board-btns { flex: 1 1 100%; gap: 8px; }
  .board { min-height: 74px; padding-left: 6px; padding-right: 6px; }
  .b-verb { font-size: 18px; }
  .b-ship { font-size: 10.5px; letter-spacing: .3px; }
  /* the "bet $x → win $y" line is the longest — shrink it so it never clips/overflows */
  .b-mult { font-size: 11px; letter-spacing: 0; }
  #panel { height: 78vh; }                /* chat below the fold — scroll to reach it */
  /* Portrait's camera framing is tighter/closer than the desktop one these
     left/top %s were tuned for (see webgl-scene.js's PORTRAIT_HALF_W/MARGIN),
     so each ship sits at a different spot on screen here. Measured live via
     window.__plunderShipBounds() (projects the real 3D hull to screen %):
     Black Pearl centers ~51% across / masthead top ~43%, Interceptor centers
     ~19% across / masthead top ~41%. `left` now marks the ship's horizontal
     CENTER (translateX(-50%)), not its left edge, so the label always centers
     over the mast regardless of how wide the two-line name text renders. */
  /* Centred over each hull, measured against the real ships at this width
     (window.__plunderShipBounds(): Pearl centres ~77%, Interceptor ~27%).
     Re-measure with that helper if the ships or the portrait framing move. */
  #card-port { left: 77%; top: 34%; transform: translateX(-50%); }
  #card-star { left: 27%; top: 32%; transform: translateX(-50%); }
  /* readouts sit right above each ship's mast, not on top of them */
  .ship-card { max-width: 128px; padding: 6px 11px; }
  .ship-card .card-name { font-size: 14px; }
  /* over-scale (×1.2) so the sea fills the whole frame (no black gap at the bottom)
     and lift it so the Black Pearl rides the water; ships well separated. */
  .plbg {
    top: 50%;
    transform: translate(-50%, calc(-50% - 60px)) scale(calc(var(--plbg-s, 1) * 1.2));
  }
  /* sit the pair low on the water (not floating in the sky). The Interceptor rides
     below the Black Pearl, separated so they don't overlap, and still clear of the
     floating bet controls below. */
  /* Push the two ships as far apart as the water allows: the Black Pearl high (hull
     still on the water, not the sky), the Interceptor anchored low — just above the
     bet bar (its height is measured live into --betbar-h) so it's as low as it can
     go without being covered, on every device height. */
  #lane-port { top: 40%; height: 16%; }
  /* anchor to the TOP of the visible controls (not the bet-bar element, which
     reserves safe-area space below) so the Interceptor rides just above the
     buttons — as low as possible — on every device. */
  #lane-star { top: calc(var(--controls-top, 700px) - 150px); height: 16%; }
  .ship { width: clamp(140px, 44vw, 200px); }
  /* wordmark collapses to a P monogram so the icons + balance get real room */
  .brand-rest { display: none; }
  .brand h1 { font-size: 19px; letter-spacing: 0; background: none; padding: 0; box-shadow: none; }
  .brand-p {
    display: inline-flex; align-items: center; justify-content: center;
    width: 34px; height: 34px; border-radius: 9px;   /* same as the icon buttons */
    background: #0b1020; color: #d9a441;              /* matches the favicon: navy badge, gold P */
    box-shadow: inset 0 0 0 1px rgba(217,164,65,.6);
    font-weight: 900;
  }
  .bg-moon { left: auto; right: 5%; top: 6%; }   /* no side panel here — hug the corner */

  /* crescent moon top-right in the sky, with a pulsing glow (the exceptional bit) */
  .mobile-moon {
    display: block; position: absolute; z-index: 2;
    top: 120px; right: 24px; width: 46px; height: 46px; border-radius: 50%;
    background: transparent;
    box-shadow: inset -13px -6px 0 0 #f5edcf;
  }
  /* glow halo swells + brightens on a 3.6s loop, like the PC moon-glow pulse */
  .mobile-moon::after {
    content: ""; position: absolute; inset: -22px; border-radius: 50%;
    background: radial-gradient(circle, rgba(255,246,214,.6) 0%, rgba(255,246,214,0) 68%);
    animation: mMoonGlow 3.6s ease-in-out infinite; z-index: -1;
  }
  /* ---- balance <-> "last round" swap ----
     Balance moves into the roomy row "last round" used to occupy (easier to
     read at a glance); "last round" becomes a compact strip inline in the
     icon row, right after "?" — the topbar no longer needs a dedicated
     second row for it, so it shrinks and the live phase pill below (which
     already tracks --topbar-h live, see app.js syncBars()) rides up with it. */
  .nav-left { order: 0; }
  /* Recent-rounds strip is back at the very top row on portrait — kept small
     enough to leave the icon/balance row below it untouched. */
  #crash-strip { display: flex; top: 8px; max-width: 92vw; }
  .crash-pill { padding: 2px 6px; font-size: 10px; }
  .nav-right { order: 2; }

  /* Icon row + balance now form ROW 2, pushed down below the crash strip
     (row 1) instead of sharing the very top of the screen with it. The extra
     "+ 2.5vh" nudges the whole row a bit further down the screen. */
  #topbar { padding-top: calc(46px + 2.5vh); }

  /* Balance stays top-RIGHT, just moved down onto row 2 with the icons —
     see #topbar padding-top above. The calc() resolves to a FIXED page-Y
     (46px + 2.5vh here) regardless of viewport height — betbar's own
     `top: 100svh - betbar-h` cancels out the `100svh` here — which is what
     lets the pill (positioned inside #stage, whose `inset:0` starts at
     page-Y 0) line up with the icon row. */
  #balance-box {
    left: auto; right: 10px; width: auto; min-width: 0;
    top: calc(46px + 2.5vh - (100svh - var(--betbar-h, 200px)));
    height: 34px; padding: 0 12px; flex-direction: row; justify-content: center; gap: 6px;
    border-radius: 10px; background: rgba(7,24,31,.65); border: 1px solid rgba(255,255,255,.14);
  }
  /* Just the number — self-evident what it is without the "Balance" caption. */
  #balance-box .bb-label { display: none; }
  #you-balance { font-size: 15px; }

  /* Phase pill (Boarding/countdown) is ROW 3, below the crash strip AND the
     icon/balance row above it. */
  #phase-ribbon {
    top: 90px; left: 50%; right: auto; transform: translateX(-50%);
    padding: 6px 10px; gap: 6px;
  }
  #phase-label { font-size: 12px; letter-spacing: .08em; }
  #phase-clock { font-size: 12px; }
  #phase-ribbon::before { width: 6px; height: 6px; }
  #timerbar { top: 128px; left: 50%; right: auto; transform: translateX(-50%); width: 130px; }
  /* small screens: jackpot rides inline on the LAST-10 rounds row, after the dots */
  #jackpot-bar {
    position: static; transform: none; top: auto; left: auto; right: auto;
    flex: 0 0 auto; margin-left: 0; padding: 3px 9px; font-size: 11.5px;
  }
  /* lift the back-to-game pill clear of the chat's Send button */
  #to-top { bottom: calc(74px + env(safe-area-inset-bottom)); }   /* 10px higher, clear of Send */
  #foot { display: none; }

  /* Result/status banner ("BLACK PEARL WINS!", "Dead Calm", etc.) is centred
     via top:70% + translate(-50%,-50%) on desktop — fine there, but its
     content length varies round to round (a 2-line void message vs. a
     4-line win breakdown with the crew count and multiplier), and on a short
     phone screen a tall banner centred on a fixed point can grow low enough
     to sit on top of the bet controls. Anchor it to the BET BAR instead —
     grows upward from a fixed gap above it, so it can never reach the
     controls no matter how much text a given round's result has. */
  #banner {
    top: auto; bottom: calc(var(--betbar-h, 200px) + 14px);
    left: 50%; transform: translateX(-50%);
    max-width: calc(100% - 32px);
    animation-name: bannerinBottom;
  }
  @keyframes bannerinBottom { from { opacity: 0; transform: translate(-50%, 14px) scale(.85); } }
}

/* ---------------- bracket lobby (GAME-ECONOMY-DESIGN.md §4) ---------------- */
/* CS2-inspired table-pick: four tall vertical "stake bracket" cards sitting
   side-by-side (2x2 on tablet, swipeable carousel on phone). Each card has a
   unique themed background scene (CSS-only — no image assets), a Roman-
   numeral identifier, a thematic emblem, the bracket's display name, a
   tagline, the stake range, and a live "X online" pulse. Reuses the
   project's .modal-overlay/.modal-box chrome for a consistent dialog feel
   — only the body is redesigned. */
.lobby-box {
  max-width: min(1120px, 95vw);
  width: 100%;
  padding: 0;
  overflow: hidden;
  /* keep the lobby small enough to fit in laptop viewports (≥ 720h) without
     scrolling — the 4 cards + header comfortably fit at 88vh. */
  max-height: 88vh;
}
.lobby-head {
  text-align: center;
  padding: 16px 28px 14px;
  border-bottom: 1px solid var(--line);
  background:
    radial-gradient(ellipse 60% 100% at 50% 0%, rgba(245, 197, 66, 0.06), transparent 70%),
    var(--panel-solid);
}
.lobby-eyebrow {
  display: inline-block;
  font-size: 10px;
  letter-spacing: 3px;
  text-transform: uppercase;
  color: var(--gold);
  font-weight: 700;
  margin-bottom: 4px;
  font-family: var(--display);
}
.lobby-title {
  font-family: var(--display);
  font-size: clamp(20px, 2.2vw, 26px);
  font-weight: 900;
  letter-spacing: 1.2px;
  color: var(--text);
  margin: 0 0 4px;
  line-height: 1.05;
}
.lobby-sub {
  color: var(--muted);
  font-size: 12px;
  margin: 0;
  letter-spacing: 0.2px;
}

.lobby-loading { color: var(--muted); font-size: 13.5px; padding: 32px; display: block; text-align: center; }

/* the 4-up vertical card grid — main stage for the CS2-style redesign */
.bracket-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 14px;
  padding: 18px 24px 22px;
  overflow-y: auto;
  /* fill the modal-box column so the grid scrolls INSIDE the modal instead
     of pushing the modal past 88vh and clipping the cards. */
  flex: 1 1 auto;
  min-height: 0;
  background: var(--panel-solid);
}
@media (max-width: 900px) {
  .bracket-grid { grid-template-columns: repeat(2, 1fr); gap: 12px; padding: 16px 20px 20px; }
}
@media (max-width: 640px) {
  /* Mobile: convert the grid to a horizontal scroll carousel so one card
     dominates the viewport — much more readable than a stacked column of
     truncated cards, and matches the swipe-to-explore feel. */
  .bracket-grid {
    grid-template-columns: none;
    grid-auto-flow: column;
    grid-auto-columns: 78%;
    gap: 12px;
    padding: 16px;
    overflow-x: auto;
    overflow-y: hidden;
    scroll-snap-type: x mandatory;
    scroll-padding: 0 16px;
  }
  .lobby-head { padding: 14px 16px 10px; }
  .lobby-sub { display: none; }
}

/* ---- single bracket card ---- */
.bracket-card {
  position: relative;
  display: block;
  width: 100%;
  /* 5:8 keeps the card "tall" but compact enough to fit name + tagline +
     range + online in a typical laptop viewport without scrolling. */
  aspect-ratio: 5 / 8;
  max-height: 460px;
  min-height: 360px;
  border-radius: 14px;
  overflow: hidden;
  border: 1px solid rgba(255, 255, 255, 0.10);
  background: #050810;
  cursor: pointer;
  font: inherit;
  color: var(--text);
  text-align: left;
  padding: 0;
  transition: transform .28s cubic-bezier(.2, 1.2, .4, 1),
              border-color .2s ease,
              box-shadow .28s ease;
  isolation: isolate;
  /* for the mobile carousel: snap each card to the start of the viewport */
  scroll-snap-align: start;
}
@media (max-width: 900px) {
  .bracket-card { aspect-ratio: 4 / 5; max-height: 400px; min-height: 320px; }
}
@media (max-width: 640px) {
  /* the carousel needs a fixed height per card so swipes feel consistent
     regardless of device width — 70vh ≈ a phone-screen full of card. */
  .bracket-card { aspect-ratio: auto; width: 100%; height: 70vh; max-height: 540px; min-height: 380px; }
}
.bracket-card:hover, .bracket-card:focus-visible {
  outline: none;
  transform: translateY(-5px) scale(1.015);
  border-color: var(--gold);
  box-shadow:
    0 18px 50px rgba(0, 0, 0, 0.65),
    0 0 0 1px rgba(245, 197, 66, 0.35);
}
.bracket-card[disabled] {
  opacity: .4;
  cursor: not-allowed;
  pointer-events: none;
}

/* themed "scene" painted entirely in CSS (no image assets).
   Each theme = sky-to-sea gradient + a small radial highlight (sun/lightning/
   glow). ::after is the per-theme foreground detail (sun, ship, stars). */
.bracket-bg { position: absolute; inset: 0; z-index: 0; }
.bracket-bg::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
}

/* R1 — Cala Mira: dawn over a calm cove. Warm peach sky, turquoise water,
   soft sun on the horizon. The most inviting card. */
.bracket-card[data-theme="calm"] .bracket-bg {
  background:
    radial-gradient(ellipse 90% 35% at 50% 38%, rgba(255, 220, 160, 0.45), transparent 70%),
    linear-gradient(180deg,
      #ffd1a0 0%,
      #ffb38a 12%,
      #e08a78 22%,
      #6a8aaa 38%,
      #2f5d7a 58%,
      #143554 82%,
      #0a1f3a 100%);
}
.bracket-card[data-theme="calm"] .bracket-bg::after {
  background:
    radial-gradient(circle at 50% 36%, #fff6dc 0%, #ffd58a 14%, transparent 22%),
    radial-gradient(ellipse 220px 4px at 50% 70%, rgba(255, 240, 200, 0.25), transparent 70%);
  filter: blur(0.5px);
  opacity: .9;
}

/* R2 — Smuggler's Strait: golden hour, low sun, treasure-laden waters.
   Dramatic amber-to-violet sky, dark blue sea. */
.bracket-card[data-theme="sunset"] .bracket-bg {
  background:
    radial-gradient(ellipse 110% 40% at 50% 48%, rgba(255, 190, 90, 0.45), transparent 70%),
    linear-gradient(180deg,
      #2a1a3e 0%,
      #5a2a55 10%,
      #b14a3e 22%,
      #e8884a 34%,
      #d5703a 44%,
      #4a2a3a 58%,
      #1a2238 80%,
      #08101e 100%);
}
.bracket-card[data-theme="sunset"] .bracket-bg::after {
  background:
    radial-gradient(circle at 50% 42%, #ffcb7a 0%, #ff8a3a 18%, transparent 28%),
    radial-gradient(ellipse 280px 5px at 50% 70%, rgba(255, 180, 80, 0.3), transparent 70%);
  filter: blur(0.5px);
  opacity: .85;
}

/* R3 — Cape Maelstrom: storm rolling in. Slate-grey clouds, choppy dark
   water, a flash of distant lightning. */
.bracket-card[data-theme="storm"] .bracket-bg {
  background:
    radial-gradient(ellipse 100% 30% at 50% 12%, rgba(190, 210, 230, 0.45), transparent 70%),
    linear-gradient(180deg,
      #141c2a 0%,
      #283242 18%,
      #3a4252 32%,
      #2a3340 48%,
      #14202e 70%,
      #070d18 100%);
}
.bracket-card[data-theme="storm"] .bracket-bg::after {
  background:
    radial-gradient(ellipse 220px 6px at 30% 14%, rgba(255, 255, 255, 0.7), transparent 70%),
    radial-gradient(ellipse 280px 5px at 70% 22%, rgba(220, 230, 240, 0.5), transparent 70%),
    radial-gradient(ellipse 160px 4px at 50% 8%, rgba(255, 255, 255, 0.45), transparent 70%),
    repeating-linear-gradient(180deg, transparent 0 8px, rgba(255,255,255,.04) 8px 9px);
  filter: blur(0.5px);
  opacity: .9;
}

/* R4 — The Devil's Deep: pitch-black ocean, a faint violet aurora at the
   top, scattered stars. The most ominous card. */
.bracket-card[data-theme="abyss"] .bracket-bg {
  background:
    radial-gradient(ellipse 60% 18% at 50% 18%, rgba(120, 60, 160, 0.35), transparent 70%),
    radial-gradient(ellipse 40% 8% at 30% 12%, rgba(80, 30, 120, 0.4), transparent 70%),
    linear-gradient(180deg,
      #03060e 0%,
      #070c1c 22%,
      #0a1224 45%,
      #040810 75%,
      #01030a 100%);
}
.bracket-card[data-theme="abyss"] .bracket-bg::after {
  background-image:
    radial-gradient(1px 1px at 12% 8%,  rgba(255,255,255,.9), transparent 60%),
    radial-gradient(1px 1px at 28% 14%, rgba(255,255,255,.55), transparent 60%),
    radial-gradient(1.5px 1.5px at 42% 6%,  rgba(255,255,255,.7), transparent 60%),
    radial-gradient(1px 1px at 56% 18%, rgba(255,255,255,.45), transparent 60%),
    radial-gradient(1px 1px at 68% 9%,  rgba(255,255,255,.8), transparent 60%),
    radial-gradient(1px 1px at 84% 13%, rgba(255,255,255,.5), transparent 60%),
    radial-gradient(1px 1px at 8%  22%, rgba(255,255,255,.4), transparent 60%),
    radial-gradient(1.5px 1.5px at 92% 24%, rgba(255,255,255,.6), transparent 60%),
    radial-gradient(1px 1px at 22% 28%, rgba(255,255,255,.5), transparent 60%),
    radial-gradient(1px 1px at 78% 30%, rgba(255,255,255,.4), transparent 60%);
  background-repeat: no-repeat;
}

/* dark gradient at the bottom of every card — keeps the text legible over
   any background palette without making the whole card dark. */
.bracket-card::before {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 1;
  background: linear-gradient(180deg,
    rgba(0, 0, 0, 0) 0%,
    rgba(0, 0, 0, 0) 38%,
    rgba(0, 0, 0, 0.35) 62%,
    rgba(0, 0, 0, 0.75) 88%,
    rgba(0, 0, 0, 0.92) 100%);
  pointer-events: none;
}

/* Roman-numeral identifier at the top-left, like a film slate / CS2 map group label */
.bracket-num {
  position: absolute;
  top: 14px;
  left: 16px;
  z-index: 3;
  font-family: var(--display);
  font-size: 13px;
  font-weight: 900;
  letter-spacing: 3px;
  color: rgba(255, 255, 255, 0.85);
  text-shadow: 0 2px 8px rgba(0, 0, 0, 0.7);
  padding: 4px 9px 3px;
  border: 1px solid rgba(255, 255, 255, 0.25);
  border-radius: 4px;
  background: rgba(0, 0, 0, 0.3);
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
}

/* central emblem (themed icon in a circular medallion) */
.bracket-emblem {
  position: absolute;
  top: 42%;
  left: 50%;
  transform: translate(-50%, -50%);
  z-index: 3;
  width: 76px;
  height: 76px;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(6, 10, 22, 0.55);
  border: 1px solid rgba(255, 255, 255, 0.22);
  border-radius: 50%;
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  box-shadow:
    0 8px 24px rgba(0, 0, 0, 0.5),
    inset 0 1px 0 rgba(255, 255, 255, 0.08);
  transition: transform .3s cubic-bezier(.2, 1.2, .4, 1),
              border-color .2s ease,
              box-shadow .28s ease;
}
.bracket-card:hover .bracket-emblem {
  transform: translate(-50%, -50%) scale(1.08);
  border-color: var(--gold);
  box-shadow:
    0 10px 32px rgba(0, 0, 0, 0.55),
    0 0 28px rgba(245, 197, 66, 0.35),
    inset 0 1px 0 rgba(255, 255, 255, 0.12);
}
.bracket-emblem svg {
  width: 40px;
  height: 40px;
  stroke: var(--gold);
  fill: none;
  stroke-width: 1.4;
  stroke-linecap: round;
  stroke-linejoin: round;
  filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.5));
}

/* bottom info panel — name, tagline, range + online */
.bracket-info {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  z-index: 4;
  padding: 14px 12px 12px;
  text-align: center;
}
.bracket-name {
  display: block;
  font-family: var(--display);
  font-size: 15px;
  font-weight: 800;
  letter-spacing: 1.3px;
  color: #fff;
  text-transform: uppercase;
  line-height: 1.1;
  margin: 0 0 3px;
  text-shadow: 0 2px 10px rgba(0, 0, 0, 0.85);
  text-wrap: balance;
  /* keep the name on a single line — overflow clips rather than wrapping mid-phrase */
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.bracket-tagline {
  display: block;
  font-size: 9.5px;
  letter-spacing: 1.2px;
  text-transform: uppercase;
  color: rgba(255, 255, 255, 0.7);
  margin: 0 0 9px;
  font-weight: 500;
  font-style: italic;
  text-shadow: 0 1px 4px rgba(0, 0, 0, 0.6);
  /* keep on one line, ellipsize if the artist's copy is long */
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.bracket-stats {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  padding-top: 8px;
  border-top: 1px solid rgba(255, 255, 255, 0.18);
}
.bracket-range {
  font-family: var(--mono);
  font-size: 11.5px;
  font-weight: 600;
  color: var(--gold);
  letter-spacing: 0.3px;
  text-shadow: 0 1px 4px rgba(0, 0, 0, 0.7);
}
.bracket-online {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: 9.5px;
  color: rgba(255, 255, 255, 0.75);
  text-transform: uppercase;
  letter-spacing: 1.1px;
  font-weight: 600;
  text-shadow: 0 1px 4px rgba(0, 0, 0, 0.7);
}
.bracket-online::before {
  content: '';
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: #4ade80;
  box-shadow: 0 0 8px rgba(74, 222, 128, 0.7);
  animation: bracketPulse 2s ease-in-out infinite;
}
.bracket-online b {
  color: #fff;
  font-family: var(--mono);
  font-weight: 700;
  font-size: 12px;
  letter-spacing: 0;
  margin-right: 2px;
}
@keyframes bracketPulse {
  0%, 100% { opacity: 1; transform: scale(1); }
  50%      { opacity: 0.55; transform: scale(0.85); }
}

/* respect reduced-motion: drop the pulse + hover lift animations */
@media (prefers-reduced-motion: reduce) {
  .bracket-online::before { animation: none; }
  .bracket-card, .bracket-emblem { transition: none; }
}


/* ═══ crash states on the two ship buttons ═══════════════════════════════
   .mine     bet placed, waiting for the ships to sail
   .cashout  LIVE — money on the table, worth more every frame
   .cashed   got out in time, at the multiplier shown
   .lost     went down with the gold still aboard
   The two buttons are independent, so any combination can be on screen at
   once — including .cashed on one ship and .cashout on the other, which is
   exactly what a hedged round looks like mid-flight. */
.board.mine { outline: 2px solid var(--gold); outline-offset: -2px; }
.board.mine .b-verb { color: var(--gold); }
.board.mine .b-mult { color: #ffe9a8; }

/* THE CASH-OUT STATE — deliberately the loudest thing on screen. It is the
   only control in the game with a deadline nobody knows in advance. */
.board.cashout {
  background: linear-gradient(160deg, #17c46a, #0b7f45);
  border-color: #2effa0;
  box-shadow: 0 0 0 1px #2effa0, 0 6px 26px rgba(46,255,160,.4);
  outline: none;
  animation: cashPulse 1.05s ease-in-out infinite;
}
.board.cashout .b-verb { color: #eafff4; font-weight: 800; letter-spacing: .6px; }
.board.cashout .b-ship { color: #cdfbe6; }
.board.cashout .b-mult { color: #fff; font-weight: 800; font-variant-numeric: tabular-nums; }
@keyframes cashPulse {
  50% { box-shadow: 0 0 0 1px #2effa0, 0 8px 34px rgba(46,255,160,.66); }
}
@media (prefers-reduced-motion: reduce) { .board.cashout { animation: none; } }

.board.cashed {
  background: linear-gradient(160deg, #12603d, #0a3d28);
  border-color: rgba(46,255,160,.5);
}
.board.cashed .b-verb { color: #7ff0bb; }
.board.cashed .b-mult { color: #d8fff0; font-weight: 700; font-variant-numeric: tabular-nums; }

.board.lost {
  background: linear-gradient(160deg, #2a2f38, #171b21);
  border-color: rgba(255,255,255,.12);
}
.board.lost .b-verb { color: #8794a1; }
.board.lost .b-ship { color: #6d7883; }
.board.lost .b-mult { color: #6d7883; text-decoration: line-through; }

/* A disabled ship button must stay READABLE — in flight it is the only
   on-screen record of what happened to that bet, so it cannot fade out the
   way an inert control normally would. This deliberately overrides the
   generic `.board:disabled { opacity: .5 }` above. */
.board:disabled { opacity: .85; cursor: default; }
.board.mine:disabled, .board.cashed:disabled, .board.lost:disabled { opacity: 1; }

/* the per-ship multiplier on the stage cards, at the v2 scale */
.card-mult { font-size: 22px; }
@media (max-width: 700px) { .card-mult { font-size: 17px; } }


/* ═══ The Book: one line per round ═══════════════════════════════════════
   Both ships named, each with the multiplier it sank at. Colour is heat —
   how far that ship got — not who "won", because a crash round has no
   winner: each ship simply went down where it went down. */
#rounds-list { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 4px; }
#rounds-list li {
  display: flex; align-items: center; gap: 10px;
  padding: 6px 9px; border-radius: 8px;
  background: rgba(255,255,255,.035); border: 1px solid rgba(255,255,255,.07);
}
#rounds-list li.cur { background: rgba(255,255,255,.09); border-color: rgba(255,255,255,.2); }
#rounds-list li.empty { justify-content: center; color: #8aa0a8; font-style: italic; }
#rounds-list .r-round {
  font-family: var(--mono); font-size: 10.5px; color: #8aa0a8;
  flex: 0 0 auto; min-width: 46px;
}
#rounds-list .r-body { display: flex; flex: 1 1 auto; gap: 8px; min-width: 0; }
#rounds-list .r-line {
  display: flex; align-items: baseline; justify-content: space-between; gap: 6px;
  flex: 1 1 0; min-width: 0; padding-left: 6px; border-left: 2px solid;
}
#rounds-list .r-line.port { border-left-color: #D92E15; }
#rounds-list .r-line.star { border-left-color: #2E8FD9; }
#rounds-list .r-ship {
  font-size: 11px; font-weight: 600; color: #b8c6d0;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
#rounds-list .r-line.port .r-ship { color: #e58a7c; }
#rounds-list .r-line.star .r-ship { color: #8dbde8; }
#rounds-list .r-mult {
  font-family: var(--mono); font-size: 12px; font-weight: 600;
  font-variant-numeric: tabular-nums; flex: 0 0 auto;
}
/* heat: how far that ship got before she went down */
#rounds-list .h-cold { color: #6b7f88; }
#rounds-list .h-low  { color: #9fb4bd; }
#rounds-list .h-mid  { color: #6fd39b; }
#rounds-list .h-high { color: #ffce3a; }
#rounds-list .h-huge { color: #ff8a3a; text-shadow: 0 0 6px rgba(255,138,58,.5); }
#rounds-list .void   { color: #56666e; }


/* ═══ music opt-in prompt ════════════════════════════════════════════════
   Nothing plays until this is answered. A corner card rather than a modal:
   a round may already be running behind it and it must not block the bet
   buttons or the scene. */
#music-ask {
  position: fixed; z-index: 90;
  left: 50%; transform: translateX(-50%);
  bottom: calc(var(--betbar-h, 120px) + 58px);
  display: flex; align-items: center; gap: 8px;
  padding: 8px 10px 8px 14px; border-radius: 12px;
  background: rgba(7,24,31,.92); border: 1px solid rgba(255,255,255,.18);
  box-shadow: 0 8px 28px rgba(0,0,0,.5);
  animation: maIn .22s ease;
}
#music-ask.closing { opacity: 0; transition: opacity .2s ease; }
@keyframes maIn { from { opacity: 0; transform: translate(-50%, 6px); } }
#music-ask .ma-txt { font-size: 13px; font-weight: 600; color: #e6eef5; white-space: nowrap; }
#music-ask .ma-btn {
  padding: 5px 14px; border-radius: 8px; font-size: 12.5px; font-weight: 700;
  border: 1px solid rgba(255,255,255,.2); background: rgba(255,255,255,.07); color: #cdd7eb;
}
#music-ask .ma-btn:hover { background: rgba(255,255,255,.15); color: #fff; }
#music-ask .ma-yes { border-color: var(--gold); color: var(--gold); }
@media (prefers-reduced-motion: reduce) { #music-ask { animation: none; } }
