/* ============================================================
   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; }
/* 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); }

/* ---------------- 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%);
}
/* ---------------- 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; }
}

/* ---------------- 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; }
.icon-btn .htext-sm, .icon-btn .itext-sm { display: none; }
.icon-btn .htext-lg, .icon-btn .itext-lg { display: inline; }

/* LAST 20 — David's winners bar: a dark pill, label + colour-coded dots
   (red = Black Pearl won, blue = Interceptor won). */
/* transparent centering rail holding two SEPARATE pills: rounds + jackpot */
#history-wrap {
  position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);
  min-width: 0; margin: 0; z-index: 2;
  display: inline-flex; align-items: stretch; gap: 12px;   /* both pills same height */
  padding: 0; background: none; border: 0;
}
#rounds-pill {
  display: inline-flex; flex-direction: column; align-items: stretch; gap: 6px;
  padding: 8px 16px; border-radius: 11px;
  background: rgba(7,24,31,.65); border: 1px solid rgba(255,255,255,.14);
}
.hist-row { display: flex; align-items: center; gap: 10px; }
.last20-label {
  font-family: var(--mono); font-size: 10px; letter-spacing: .14em;
  color: #8aa0a8; white-space: nowrap; flex: 0 0 auto;
}
#history-strip {
  display: flex; gap: 6px; overflow: hidden; flex-wrap: nowrap;
  align-items: center; max-width: 100%;
}
/* "show older rounds" toggle, sits right of the last-10 strip */
.hist-more-btn {
  display: flex; align-items: center; justify-content: center; flex: 0 0 auto;
  width: 18px; height: 18px; padding: 0; margin-left: 2px; border-radius: 6px;
  background: rgba(255,255,255,.06); border: 1px solid rgba(255,255,255,.18); color: #8aa0a8;
}
.hist-more-btn:hover { background: rgba(255,255,255,.12); color: #cdd7eb; }
.hist-more-btn svg { transition: transform .2s ease; }
.hist-more-btn.open svg { transform: rotate(180deg); }
/* rounds 11–20 — a second row directly beneath the first, revealed by the toggle */
.history-strip-more {
  display: flex; gap: 6px; overflow: hidden; flex-wrap: nowrap; align-items: center; max-width: 100%;
}
.history-strip-more[hidden] { display: none; }
.hdot {
  width: 13px; height: 13px; border-radius: 50%; flex: 0 0 auto;
  display: grid; place-items: center; font-size: 9px; color: #fff;
}
.hdot.port { background: #D92E15; }   /* Black Pearl won */
.hdot.star { background: #2E8FD9; }   /* Interceptor won */
.hdot.void { background: #56666e; }
.hdot.cur { width: 16px; height: 16px; }   /* current round: just the ★, no ring */

/* 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 {
  position: absolute; top: 60px; 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: 100px; left: 50%; transform: translateX(-50%);
  width: 220px; height: 4px; border-radius: 2px;
  background: rgba(7,24,31,.7); overflow: hidden; z-index: 8;
}
#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); }
.ship-card .card-name {
  display: flex; max-width: 100%; overflow: hidden;
  white-space: nowrap; text-overflow: ellipsis;
}
/* Fog hides the ships themselves (body.fog-on, see ui.js setPhase) — the name
   labels sat on top of the fog and stayed legible even though the ships
   underneath didn't, which gave away who's who while betting is meant to be
   blind. Hide them the same way, on the same fade. */
.ship-card { transition: opacity .5s ease; }
body.fog-on .ship-card { opacity: 0; pointer-events: none; }

/* 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 | win */
.bet-row {
  display: grid; grid-template-columns: minmax(0,1fr) auto auto; gap: 10px; 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; }
.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/win hug the far right edge (empty win collapses to 0) */
.br-stake { color: #fff; font-weight: 600; min-width: 0; text-align: right; }
.br-win { color: #24d98a; font-weight: 700; min-width: 0; text-align: right; }
#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, #tab-bets .br-win { color: #01F4A0; }

/* 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; }

  /* the winners strip gets its own full-width row under the logo, right above the
     scene's timer — in the top bar it was squeezed to two visible pills */
  #history-wrap {
    position: static; transform: none;
    flex: 1 0 100%; order: 3;
    flex-direction: row; align-items: stretch; justify-content: space-between; gap: 8px;
    background: none; border: 0; padding: 4px 0 0;
  }
  #rounds-pill {
    flex-direction: column; align-items: flex-start; gap: 4px;   /* "Last Rounds" over the dots */
    padding: 6px 10px;
  }
  .hist-row { flex-direction: column; align-items: flex-start; gap: 4px; }
  .history-strip-more { margin-top: 2px; }
  #history-wrap::-webkit-scrollbar { display: none; }
  #history-strip {
    overflow: visible; max-width: none; flex: 0 0 auto; flex-wrap: nowrap;
    justify-content: flex-start; padding-right: 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; }

  #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. "last round" collapses onto one row (topbar drops from two rows to
     one, freeing vertical room) — landscape is wide enough that, unlike
     portrait, it doesn't need to squeeze in next to "?" to fit; centered
     the same way it already is on desktop (position:absolute + left:50%)
     reads better and matches the live phase pill's own centering below it. */
  #history-wrap {
    position: absolute; left: 50%; top: 12px; transform: translateX(-50%);
    flex: 0 0 auto; margin: 0;
  }
  #rounds-pill { flex-direction: row; align-items: center; padding: 4px 8px; gap: 0; }
  .hist-row { gap: 4px; }
  .last20-label { display: none; }
  #history-strip { gap: 3px; }
  .hpill { padding: 2px 4px; font-size: 8.5px; }
  .history-strip-more, .hist-more-btn { display: none; }

  /* 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 "last round" 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. */
  #card-port { left: 51%; top: 34%; transform: translateX(-50%); }
  #card-star { left: 19%; top: 33%; 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; }
  #history-strip { gap: 5px; }
  .hpill { font-size: 10.5px; padding: 3px 6px; }
  /* 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;
  }
  /* ---- 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; }
  #history-wrap {
    position: static; order: 1; flex: 0 1 auto; margin: 0 0 0 6px;
    align-items: center;
  }
  #rounds-pill { flex-direction: row; align-items: center; padding: 5px 9px; gap: 0; }
  .hist-row { gap: 5px; }
  .last20-label { display: none; }         /* no inline room for the text label — the dots alone read fine */
  #history-strip { gap: 4px; }
  .hpill { padding: 2px 5px; font-size: 9px; }
  .history-strip-more, .hist-more-btn { display: none; }   /* "older rounds" — desktop/tablet only at this width */
  .nav-right { order: 2; }

  /* Small pill again (was briefly a full-width bar — that read as way too
     wide), left-aligned directly under the settings/help icons. Its calc()
     always resolves to a FIXED page-Y of 58px regardless of viewport height
     (betbar's own `top: 100svh - betbar-h` cancels out the `100svh` here —
     see the comment on #phase-ribbon below, which relies on that same fact). */
  #balance-box {
    left: 14px; right: auto; width: auto; min-width: 0;
    top: calc(58px - (100svh - var(--betbar-h, 200px)));
    height: 36px; 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);
  }
  #balance-box .bb-label { display: inline; font-size: 10px; }
  #you-balance { font-size: 15px; }

  /* The live phase pill moves up into the row balance used to fill alone —
     right-docked (mirrors the icon buttons' own right:10px corner anchor)
     so it can never collide with balance's width, whatever the player's
     balance renders as. #balance-box's calc() above always resolves to a
     fixed page-Y of 58px (the point of that formula: the 100svh terms
     cancel), and #phase-ribbon's positioning root (#stage, `inset:0`) starts
     at page-Y 0 too, so the same plain 58px lines them up in one row without
     needing that calc() trick here. Un-center it (drop left:50%) and shrink
     it slightly so "AT ANCHOR 88s" comfortably fits the space balance's
     shrink left free. */
  #phase-ribbon {
    top: 58px; left: auto; right: 10px; transform: none;
    padding: 6px 12px; gap: 8px;
  }
  #phase-label, #phase-clock { font-size: 14px; }
  #phase-ribbon::before { width: 6px; height: 6px; }
  #timerbar { top: 96px; left: auto; right: 10px; transform: none; width: 160px; }
  /* 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.
   Also covers the other continuous/periodic decorative pulses defined in
   game.css (helpPulse, youpulse, the fog-blob drift) — many low-tier/older
   phones have this flipped on by an OS battery saver, so honoring it here
   is a free perf win on exactly the devices that need it, not just an
   accessibility nicety. */
@media (prefers-reduced-motion: reduce) {
  .bracket-online::before { animation: none; }
  .bracket-card, .bracket-emblem { transition: none; }
  .music-btn.muted { animation: none; }
  .av.you { animation: none; }
  .f1, .f2, .f3, .f4, .f5 { animation: none; }
}
