/* ── CONTENTS (grep the section banner name; line numbers drift) ──────────
   :root vars (colors, bevels --raised/--raised-sm, safe areas --sa-t/r/b/l)
   Base: Desktop background · Window chrome (XP-style) · WinXP inactive window ·
     Luna themes · Panel body (felt) · Headline label · Daily modifier banner ·
     Sunken readout box · Logo / brand · Buttons · Unified button sizing
   Game UI: Player's Choice picker · Cards: Balatro-readable · BJ inactive
     split hands · Split-result vertical rhythm · Overlapping card fan ·
     BJ bet screen · Chip selector · Hand progress dots · Info row ·
     Game manifest tile · Pay table · Roulette · Results screen ·
     Score distribution chart · Toast · Hold-card toggle
   Windows/menus: Info modal · Player Profile window · Dropdown menus ·
     Mod-badge · XP Notification Balloon · Desktop-only: draggable window
   Responsive: Mobile / small screen (≤480px, incl. Short-screen button
     visibility) · Desktop / large screen (≥1024px, per-screen overrides:
     Intro/BJ/UTH/Roulette/Results/Dev stats) · Tall desktop (1024×880+) ·
     Wider tall (1280×880+) · Narrow-tall (1024×1060+) · Tallest (1280×1060+) ·
     Large-display scaling (2560/3840 zoom tiers)
   ─────────────────────────────────────────────────────────────────────── */

*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
button { touch-action: manipulation; font-family: var(--btn-f); }

:root {
  --desktop:    #142a22;
  --desktop2:   #081612;
  --panel:      #dcd2b6;
  --panel2:     #e8e0c4;
  --shadow:     #5a5238;
  --highlight:  #fbf5dc;
  --ink:        #1a1814;
  --dim:        #6b6450;
  /* XP Luna blue title bar */
  --title-grad: linear-gradient(180deg, #3a82e8 0%, #1060d4 36%, #0a50c0 62%, #1262d4 78%, #0840a0 100%);
  --title-edge: #0a3478;
  --title-text: #ffffff;
  /* Felt-green play area */
  --felt:       #1d6e4d;
  --felt-light: #2b8c66;
  --felt-dark:  #134b35;
  --felt-edge:  #0b2e21;
  /* Card colors */
  --gold:       #c4933a;
  --gold-hi:    #dfb95e;
  --gold-lo:    #7a5a18;
  --red:        #c43030;
  --red-deep:   #a32f24;
  --close-red:  #c83a3a;
  /* Status colors */
  --win:        #1fa845;
  --win-hi:     #3ecf62;
  --win-lo:     #0f7a2c;
  --win-fg:     #f4ead0;
  --lose:       #cc2222;
  --lose-hi:    #e03030;
  --lose-lo:    #8a1515;
  --push:       #6b6450;
  /* Fonts */
  --f:        'Tahoma', 'Segoe UI', sans-serif;
  --display:  'Tahoma', 'Segoe UI', sans-serif;
  --btn-f:    'VT323', 'Courier New', monospace;
  --cream:    #fbf5dc;
  --raised: inset 1.5px 1.5px 0 var(--highlight), inset -2px -2px 0 var(--shadow);
  --raised-sm: inset 1px 1px 0 var(--highlight), inset -1px -1px 0 var(--shadow);
  /* Unified button metrics: every action/gold/clear/all-in button and the bet box
     shares one height + font size per breakpoint. Overridden in the media queries below.
     Forced with !important on the button rules so per-screen tweaks can't make the
     same control a different size from one game to the next. */
  --btn-h:  44px;
  --btn-fs: 1.3rem;
  /* Fixed bet-box width: identical across every screen at a given size, so the bet inlay box is
     pixel-perfect the same wherever it appears (bet phase, play, reveal, result). It never stretches
     with the window; the controls AROUND it do. 350 fits flanked by Clear + All In within the tightest
     desktop panel (1024); it widens to 420 at >=1280 and narrows to the phone panel on mobile. */
  --bet-box-w: 350px;
  /* Near-full-panel control width: the bet-row (Clear + box + All In), Deal, and the play/result
     button row all stretch to this, so they're wider than the fixed box and span most of the window.
     width:100% lets it shrink on panels narrower than this. */
  --ctrl-w: 680px;
  /* The lone action button (Deal / Final Spin / Next Game / Next Hand …) sits slightly WIDER than the
     bet/inlay box rather than exactly matching it: a consistent ~12% at every breakpoint, so the
     proportion reads the same on desktop as on mobile (where the button already overhangs the box).
     Mobile pins it back to the box width (the button is already full-panel there); see the mobile :root. */
  --act-btn-w: calc(var(--bet-box-w) * 1.12);
  --btn-px: 14px;
  /* iOS Safari safe-area insets (Dynamic Island/status bar, home indicator, landscape
     notch). Defaults to env() which is 0 off-iOS; declared as vars so the layout tests
     can simulate non-zero insets in headless Chromium (where env() is always 0). */
  --sa-t: env(safe-area-inset-top, 0px);
  --sa-r: env(safe-area-inset-right, 0px);
  --sa-b: env(safe-area-inset-bottom, 0px);
  --sa-l: env(safe-area-inset-left, 0px);
}

/* ── Desktop background ─────────────────────────────────── */
body {
  background:
    repeating-linear-gradient(0deg, var(--desktop2) 0 1px, transparent 1px 4px),
    repeating-linear-gradient(90deg, var(--desktop2) 0 1px, transparent 1px 4px),
    var(--desktop);
  background-attachment: fixed;
  color: var(--ink);
  font-family: var(--btn-f);
  font-size: 28px;
  min-height: 100vh;
  -webkit-font-smoothing: antialiased;
}

.app {
  width: 100%; max-width: 620px;
  margin: 0 auto;
  padding: 14px 14px 30px;
  position: relative; z-index: 1;
}

/* ── Window chrome (XP-style) ───────────────────────────── */
.window {
  background: var(--panel);
  border: 1px solid var(--ink);
  box-shadow: inset 1px 1px 0 var(--highlight), inset -2px -2px 0 var(--shadow);
  display: flex; flex-direction: column;
  min-height: calc(100svh - 44px);
  border-radius: 8px 8px 0 0;
}

/* Soft outer vignette on body for the desktop framing */
@media (min-width: 1024px) {
  body::before {
    content: ''; position: fixed; inset: 0;
    background: radial-gradient(ellipse at center, transparent 40%, rgba(0,0,0,0.45) 100%);
    pointer-events: none; z-index: 0;
  }
}
.title-bar {
  background:
    linear-gradient(180deg,
      rgba(255,255,255,0.60) 0%,
      rgba(255,255,255,0.03) 2px,
      rgba(255,255,255,0.08) 38%,
      rgba(255,255,255,0) 52%),
    var(--title-grad);
  color: var(--title-text);
  padding: 5px 6px;
  font-size: 24px;
  font-family: var(--btn-f);
  letter-spacing: 0.02em;
  border-bottom: 1px solid var(--ink);
  display: flex; justify-content: space-between; align-items: center;
  line-height: 1; gap: 8px;
  text-shadow: 1px 1px 0 rgba(0,0,0,0.35);
  border-radius: 7px 7px 0 0;
  overflow: hidden; /* a long title must never push the window wider than the viewport */
}
.tb-title { display: flex; align-items: center; gap: 8px; white-space: nowrap; min-width: 0; overflow: hidden; text-overflow: ellipsis; }
.tb-icon {
  width: 16px; height: 16px; flex-shrink: 0;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 14px; line-height: 1;
  text-shadow: 1px 1px 0 rgba(0,0,0,0.45);
}
.tb-btns { display: flex; gap: 3px; flex-shrink: 0; }
.tb-btn {
  width: 22px; height: 19px;
  background: linear-gradient(180deg, rgba(255,255,255,0.44) 0%, rgba(120,170,245,0.22) 100%);
  color: #fff;
  display: inline-flex; align-items: center; justify-content: center;
  font-size: 14px; line-height: 1; text-shadow: 1px 1px 0 rgba(0,0,0,0.55);
  border: 1px solid rgba(0,40,150,0.65);
  box-shadow: inset 1px 1px 0 rgba(255,255,255,0.72), inset -1px -1px 0 rgba(0,0,80,0.28);
  cursor: pointer; border-radius: 3px;
}
.tb-btn:hover { background: linear-gradient(180deg, rgba(255,255,255,0.58) 0%, rgba(140,190,255,0.38) 100%); }
.tb-btn:active { background: linear-gradient(180deg, rgba(80,130,220,0.55) 0%, rgba(40,80,180,0.55) 100%); box-shadow: inset 1px 1px 0 rgba(0,0,0,0.20), inset -1px -1px 0 rgba(255,255,255,0.25); }
.tb-btn.close {
  background: linear-gradient(180deg, #ea5555 0%, #c82020 100%);
  color: #fff; border-color: #8b0f0f;
  box-shadow: inset 1px 1px 0 rgba(255,200,200,0.55), inset -1px -1px 0 rgba(0,0,0,0.30);
}
.tb-btn.close:hover { background: linear-gradient(180deg, #f06060 0%, #e03030 100%); }
.tb-btn.close:active { background: linear-gradient(180deg, #b01818 0%, #8a1010 100%); }

.menu-bar {
  background: var(--panel);
  padding: 0 4px 0 0;
  font-size: 1.05rem;
  font-family: var(--btn-f);
  display: flex; gap: 2px; align-items: stretch;
  border-bottom: 1px solid var(--ink);
  box-shadow: inset 0 1px 0 var(--highlight);
  white-space: nowrap; color: var(--ink);
}
.menu-bar .mb-item { cursor: pointer; flex-shrink: 0; padding: 4px 8px; border-radius: 0; display: flex; align-items: center; }
.menu-bar .mb-item:hover { background: #316AC5; color: #fff; }
.menu-bar .mb-item u { text-decoration: underline; }
.menu-bar .mb-right { margin-left: auto; }
.chip-badge {
  display: inline-flex; align-items: center; gap: 5px;
  font-family: var(--btn-f); font-size: 1.45rem; font-weight: 700; letter-spacing: 0.02em;
  color: var(--ink); background: var(--panel);
  border: 1px solid var(--shadow); border-radius: 2px;
  padding: 0 8px; line-height: 1;
  margin: 2px 0;
  box-shadow: inset 1px 1px 0 var(--shadow), inset -1px -1px 0 var(--highlight);
}
/* line-height:1 on the badge keeps its height governed by the chip glyph (≈ the
   original emoji badge height) so the menu bar doesn't grow. The glyph reads a touch
   larger than the digits and is vertically centered by the flex box. */
.chip-badge .ic { width: 1.05em; height: 1.05em; vertical-align: 0; }

.status-bar {
  background: var(--panel);
  padding: 3px 6px;
  border-top: 1px solid var(--ink);
  font-size: 0.95rem;
  font-family: var(--btn-f);
  color: var(--shadow);
  display: flex; justify-content: space-between; gap: 6px;
  white-space: nowrap;
}
.status-bar > span {
  padding: 1px 8px; min-width: 0;
  box-shadow: inset 1px 1px 0 var(--shadow), inset -1px -1px 0 var(--highlight);
}
.status-bar > span:first-child {
  flex: 1; overflow: hidden; text-overflow: ellipsis;
}
.status-bar > span:last-child {
  flex-shrink: 0;
  background: #c8bfaa;
  border-left: 1px solid var(--shadow);
  padding-left: 8px;
  display: flex; align-items: center; gap: 5px;
}

/* ── WinXP inactive window ──────────────────────────────── */
/* Applies both when the whole tab loses focus (body.win-inactive) and when a single popup is
   deactivated by a desktop click-away (.info-box.win-inactive: see _infoOverlayClick). */
body.win-inactive .title-bar,
.info-box.win-inactive .title-bar {
  background: linear-gradient(180deg, #c8c8c8 0%, #a8a8a8 100%);
}
body.win-inactive .tb-title,
.info-box.win-inactive .tb-title { opacity: 0.6; text-shadow: none; }
body.win-inactive .tb-btn,
body.win-inactive .tb-btn.close,
.info-box.win-inactive .tb-btn,
.info-box.win-inactive .tb-btn.close {
  background: #c0c0c0;
  border-color: #888;
  box-shadow: inset 1px 1px 0 rgba(255,255,255,0.65), inset -1px -1px 0 rgba(0,0,0,0.18);
  color: #555;
  text-shadow: none;
}
body.win-inactive .tb-btn:hover,
body.win-inactive .tb-btn.close:hover,
.info-box.win-inactive .tb-btn:hover,
.info-box.win-inactive .tb-btn.close:hover {
  background: #cccccc;
}

/* ── Luna themes ─────────────────────────────────────────── */
body.theme-olive  { --title-grad: linear-gradient(180deg, #9aac4a 0%, #7e8e32 36%, #647024 62%, #7e8e32 78%, #526018 100%); }
body.theme-silver { --title-grad: linear-gradient(180deg, #b8c0cc 0%, #909aa8 36%, #788090 62%, #909aa8 78%, #687080 100%); }
body.theme-green  { --title-grad: linear-gradient(180deg, #2ba868 0%, #1d8050 36%, #156438 62%, #1d8050 78%, #0e5030 100%); }

/* ── Panel body (felt) ──────────────────────────────────── */
.panel {
  background: var(--felt);
  background-image:
    url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='160' height='160'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/><feColorMatrix values='0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.12 0'/></filter><rect width='100%' height='100%' filter='url(%23n)'/></svg>"),
    radial-gradient(ellipse at 50% 30%, var(--felt-light) 0%, var(--felt) 60%, var(--felt-dark) 100%);
  padding: 14px;
  flex: 1;
  min-height: 540px;
  display: flex; flex-direction: column; gap: 10px;
  position: relative;
  border: 1px solid var(--felt-edge);
  border-left: 0; border-right: 0;
  box-shadow: inset 0 0 0 1px rgba(0,0,0,0.18);
}
.panel.cream {
  background: var(--panel); background-image: none;
  border-color: transparent; box-shadow: none;
}

/* Etched groove on felt and cream */
.divider {
  height: 0; border-top: 1px solid rgba(0,0,0,0.35); border-bottom: 1px solid rgba(255,255,255,0.10);
  margin: 6px 0;
}
.panel.cream .divider {
  border-top: 1px solid var(--shadow); border-bottom: 1px solid var(--highlight);
}

/* ── Even bands: align content using the dividers ────────────
   A content band between two dividers fills an equal share of the panel (flex:1) and centers its
   content vertically (equal space above/below). With the panel's symmetric gap + divider margins, the
   interior dividers then land exactly on the split lines: 1 interior divider → dead centre between the
   top and bottom dividers, 2 interior → even thirds. min-height:0 lets a band shrink on short screens. */
.vband { flex: 1 1 0; min-height: 0; display: flex; flex-direction: column; justify-content: center; }
/* Split play is the exception to even bands: the active hand plus its aside (the other hands' summary)
   needs far more room than the dealer, so the dealer band sizes to content and the middle divider moves
   UP, handing the rest of the board to the active hand. Keeps the cards at full size with no bet-box overlap. */
.panel:has(.bj-split-active) #bj-dealer-section { flex: 0 0 auto; }

/* ── Headline label (section) ───────────────────────────── */
.sec {
  font-family: var(--btn-f);
  font-size: 1.4rem; color: var(--cream); opacity: 0.85;
  text-transform: uppercase; letter-spacing: 0.18em;
  font-weight: 400; margin-bottom: 8px;
}
.panel.cream .sec { color: var(--shadow); opacity: 1; }

/* ── Daily modifier banner ──────────────────────────────── */
.mod-banner {
  border: 1px solid var(--ink);
  background: linear-gradient(180deg, #f5eabc 0%, #ead89a 100%);
  box-shadow: inset 1px 1px 0 var(--highlight), inset -2px -2px 0 var(--shadow);
  padding: 8px 12px;
  margin: 0 0 14px 0;
  font-family: var(--btn-f);
  display: flex; justify-content: space-between; align-items: center; gap: 14px;
  font-size: 1.4rem;
  cursor: pointer;   /* a button: opens today's modifier help (LAYOUT.md: raised bevel = clickable) */
}
/* Button feedback matching .act-btn/.btn-gold: hover brightens, press sinks (translate + inverted bevel). */
.mod-banner:hover  { background: linear-gradient(180deg, #f9f1cc 0%, #f0e0a8 100%); }
.mod-banner:active { transform: translate(1px,1px); box-shadow: inset 2px 2px 0 var(--shadow), inset -1px -1px 0 var(--highlight); }
.mod-banner-l { flex-shrink: 0; white-space: nowrap; }
.mod-banner-label { font-size: 1rem; color: var(--shadow); letter-spacing: 0.14em; }
.mod-banner-title { font-size: 1.7rem; font-weight: 700; line-height: 1.1; color: var(--ink); margin-top: 1px; }
/* Daily-mod star: solid gold with a dark outline so it pops on the pale-gold banner.
   stroke-width is in viewBox units (256 = 1em), so it scales with the title font. */
.ic.mod-star { color: #ffd11a; stroke: var(--ink); stroke-width: 24px; stroke-linejoin: round; paint-order: stroke; }
.mod-banner-r { font-size: 1.35rem; color: var(--ink); text-align: right; line-height: 1.3; min-width: 0; }

/* ── Logo / brand ───────────────────────────────────────── */
.logo {
  font-family: var(--btn-f);
  font-size: 6rem; font-weight: 700;
  line-height: 0.95; letter-spacing: 0.04em;
  color: var(--ink);
}
.logo-spade { color: var(--ink); margin-right: 0.12em; }
.logo-sub { font-size: 1.7rem; color: var(--ink); letter-spacing: 0.18em; margin-top: 8px; text-transform: uppercase; }
/* Intro: distribute the three groups (title · CTA · program) down the panel so they
   spread across the felt on slack layouts; within each group spacing stays tight. */
/* The daily-mod banner is injected as the panel's first child and stays pinned at the
   top (original spacing). The content lives in .intro-body, which fills the remaining
   felt and distributes the three groups with even breathing room between them. */
.intro-panel { display: flex; flex-direction: column; }
.intro-body { flex: 1; display: flex; flex-direction: column; justify-content: space-evenly; gap: 16px; }
.intro-title { text-align: center; }
.intro-cta { text-align: center; }
.intro-lead { font-size: 1.8rem; color: var(--cream); }
.intro-lead b { color: var(--gold-hi); }
.intro-sub { font-size: 1.4rem; color: var(--cream); opacity: 0.7; margin-top: 4px; }
.intro-start { margin-top: 16px; }
.intro-prog-label { font-size: 1.4rem; color: var(--cream); opacity: 0.7; letter-spacing: 0.16em;
                    text-transform: uppercase; margin: 0 2px 8px; text-align: center; }
/* Mini logo for the About window (smaller than the start-screen 5.4rem). */
.logo-mini { font-size: 3rem; }

/* ── Buttons ────────────────────────────────────────────── */
.btn-gold {
  display: flex; align-items: center; justify-content: center;
  width: 100%;
  background: var(--gold); color: var(--ink);
  border: 1px solid var(--ink);
  box-shadow: inset 1.5px 1.5px 0 var(--gold-hi), inset -2.5px -2.5px 0 var(--gold-lo);
  font-family: var(--btn-f); font-weight: 700;
  letter-spacing: 0.04em; cursor: pointer;
  white-space: nowrap;
}
.btn-gold .ic { margin-right: 0.45em; } /* breathing room between a leading icon and the label */
.btn-gold:active { transform: translate(1px,1px); box-shadow: inset 2.5px 2.5px 0 var(--gold-lo), inset -1.5px -1.5px 0 var(--gold-hi); }
.btn-gold:disabled { opacity: 0.4; cursor: not-allowed; transform: none; }
/* btn-lg (Start / Borrow CTAs) is intentionally outside the unified-button system. */
.btn-gold.btn-lg { padding: 22px 24px; font-size: 2.2rem; }

/* ── Unified button sizing ─────────────────────────────────
   Every in-game button (Hit/Stand/Double/Split, Check/Raise/Fold,
   Deal/Place Bet/Spin/All In, Clear, and the bet box) is locked to the
   same height + font per breakpoint so a control is never a different
   size across games. !important defeats the per-screen overrides further
   down the file; box-sizing:border-box means height alone fixes the box. */
.act-btn,
.btn-gold:not(.btn-lg),
.ch-clear, .ch-allin,
.bet-amt {
  height: var(--btn-h) !important;
  min-height: var(--btn-h) !important;
  font-size: var(--btn-fs) !important;
  padding-top: 0 !important; padding-bottom: 0 !important;
}

.act-btns { display: flex; gap: 8px; }
.act-btn {
  flex: 1; padding: 0 12px;
  display: flex; align-items: center; justify-content: center;
  background: var(--panel); color: var(--ink);
  border: 1px solid var(--ink);
  box-shadow: inset 1.5px 1.5px 0 var(--highlight), inset -2.5px -2.5px 0 var(--shadow);
  font-family: var(--btn-f); font-weight: 700;
  letter-spacing: 0.04em; cursor: pointer;
  white-space: nowrap; text-align: center;
}
.act-btn:active:not(:disabled) { transform: translate(1px,1px); box-shadow: inset 2.5px 2.5px 0 var(--shadow), inset -1.5px -1.5px 0 var(--highlight); }
.act-btn:disabled { opacity: 0.38; cursor: not-allowed; }
.act-btn.primary { background: var(--gold); box-shadow: inset 1.5px 1.5px 0 var(--gold-hi), inset -2.5px -2.5px 0 var(--gold-lo); }

/* ── Game controls cluster (play / reveal / result) ────────
   The fixed-width bet inlay box stacked above the main game button row. The cluster stretches to the
   near-full-panel --ctrl-w, and the buttons fill it: so they're WIDER than the centered box (which
   stays --bet-box-w). The box and the buttons both carry --btn-h, so their heights line up. */
.game-controls {
  width: 100%; max-width: var(--ctrl-w); margin-left: auto; margin-right: auto;
  display: flex; flex-direction: column; align-items: center; gap: 10px;
}
.game-controls > * { margin: 0 !important; }
/* Multi-button play rows fill the cluster (full control width) so 3-4 buttons never cramp. */
.game-controls .act-btns, .game-controls > #uth-actions-ui { width: 100%; }
.game-controls > #uth-actions-ui { display: flex; flex-direction: column; align-items: center; }
/* A LONE action button (Next Hand/Game, See Results, See Turn & River, Showdown, Draw: the single
   advances stacked under the box; Deal/Final Spin live in #db) sits slightly wider than the bet box and
   centers, so the action button overhangs the box above it. Multi-button rows above are .act-btns. */
.game-controls > .btn-gold,
.game-controls > #uth-actions-ui > .btn-gold { width: var(--act-btn-w); }
.game-controls > .bet-amt { width: var(--bet-box-w); }
/* Control position parity (see .claude/LAYOUT.md): bottom-anchor the cluster so the box + button land at
   the same Y on every play/result screen. The bet screens anchor via their flex:1 spacer + #db; here the
   cluster pulls leftover felt into the gap ABOVE it, which the enlarged result cards/text then fill. */
.panel > .game-controls:last-child { margin-top: auto; }
/* The bet inlay box is the .bet-amt readout used outside the bet phase. The centered variant holds
   UTH's single-line "Ante · Blind · Raise" summary, so it overrides the left/right span layout. */
.bet-inlay-center { justify-content: center; gap: 6px; color: var(--ink); white-space: nowrap; }

/* ── Player's Choice picker ────────────────────────────────
   Options are raised buttons (not the flat gold banner) so they read as "pick me".
   Always horizontal bars stacked vertically (icon beside text) at every width; the
   header scales up as large as each breakpoint allows. */
.pc-head { font-family: var(--btn-f); font-size: 2rem; letter-spacing: 0.12em; color: var(--gold-hi); margin: 12px 0 4px; line-height: 1.05; }
.pc-sub  { font-size: 1.2rem; color: var(--cream); opacity: 0.72; margin-bottom: 16px; }
.pc-grid { display: flex; flex-direction: column; gap: 12px; align-items: stretch; }
/* Center the (short) picker vertically at every size; the screen never carries a
   modifier banner (the pick IS the modifier), so nothing needs to stay pinned on top. */
.pc-panel { justify-content: center; }
.pc-option {
  display: flex; flex-direction: row; align-items: center; gap: 16px;
  padding: 18px 20px; cursor: pointer; text-align: left;
  background: var(--panel); color: var(--ink);
  border: 1px solid var(--ink);
  box-shadow: inset 1.5px 1.5px 0 var(--highlight), inset -2.5px -2.5px 0 var(--shadow);
  transition: background 0.08s;
}
.pc-option:hover { background: var(--gold); box-shadow: inset 1.5px 1.5px 0 var(--gold-hi), inset -2.5px -2.5px 0 var(--gold-lo); }
.pc-option:active { transform: translate(1px,1px); box-shadow: inset 2.5px 2.5px 0 var(--shadow), inset -1.5px -1.5px 0 var(--highlight); }
.pc-text { display: flex; flex-direction: column; gap: 4px; min-width: 0; flex: 1; }
.pc-icon { font-size: 2.4rem; line-height: 1; flex-shrink: 0; }
.pc-title { font-family: var(--btn-f); font-size: 1.6rem; font-weight: 700; line-height: 1.1; }
.pc-desc { font-size: 1.15rem; opacity: 0.8; line-height: 1.35; }
@media (max-width: 480px) {
  .pc-head { font-size: 1.7rem; letter-spacing: 0.08em; }
  .pc-option { padding: 14px 16px; gap: 14px; }
  .pc-icon { font-size: 2.1rem; }
  .pc-title { font-size: 1.55rem; }
}
/* Desktop: lots of room, go big on the header and bars so they fill the window like
   substantial buttons. */
@media (min-width: 1024px) {
  .pc-head { font-size: 3.4rem; letter-spacing: 0.18em; margin-bottom: 10px; }
  .pc-sub { font-size: 1.5rem; margin-bottom: 28px; }
  .pc-grid { gap: 18px; }
  .pc-option { padding: 28px 36px; gap: 26px; }
  .pc-icon { font-size: 3.4rem; }
  .pc-title { font-size: 2.3rem; }
  .pc-desc { font-size: 1.45rem; }
}

/* ── Balance anchors: borrow dialog + roulette result ─────────────────────────
   Auto margins on a flex-column .panel distribute leftover felt at the marked seams
   (the modifier banner, always the panel's first child, stays pinned to the top).
   Borrow: center the whole dialog block. Roulette result: number + headline stay up
   top, the payout rows center in the slack, and the advance button ends
   bottom-anchored, mirroring the card games' result screens. The !importants beat
   the elements' inline margins, which would otherwise silently win. */
.borrow-panel > .borrow-ico { margin-top: auto !important; }
.borrow-panel > .ch-clear:last-child { margin-bottom: auto; }
.r-result-panel > .game-manifest { margin-top: auto !important; margin-bottom: auto !important; }

/* Desktop: the borrow dialog is sparse on a tall panel; scale its type and spacing up
   so the centered block reads as a substantial dialog rather than a lost strip. */
@media (min-width: 1024px) {
  .borrow-panel > .borrow-ico { font-size: 3.6rem !important; }
  .borrow-panel .result-hl { font-size: 3.2rem; }
  .borrow-panel .result-sub { font-size: 1.6rem; }
  .borrow-panel > div[style*="line-height"] { font-size: 1.5rem !important; padding-bottom: 20px !important; }
  .borrow-panel > .btn-gold { padding-top: 16px; padding-bottom: 16px; }
  .borrow-panel > .ch-clear:last-child { margin-top: 18px !important; }
}

/* ── Cards: Balatro-readable ──────────────────────────── */
.card {
  display: inline-block; position: relative;
  background: var(--cream);
  background-image:
    radial-gradient(ellipse 75% 50% at 50% 28%, rgba(255,255,255,0.55), transparent 70%);
  border: 1px solid var(--ink); border-radius: 5px;
  /* 0.5px spread shadow acts as a 'sealant' for sub-pixel gaps on mobile */
  box-shadow:
    0 2px 0 rgba(0,0,0,0.20),
    0 4px 8px rgba(0,0,0,0.25);
  user-select: none; line-height: 1; overflow: hidden;
  font-family: var(--f);
}
.card.lg { width: 88px; height: 124px; }
.card.md { width: 76px; height: 108px; }
.card.sm { width: 60px; height: 84px; }

.ctl, .cbr {
  position: absolute; display: flex; flex-direction: column;
  align-items: center; line-height: 0.95;
}
.ctl { top: 5px; left: 7px; }
.cbr { bottom: 5px; right: 7px; transform: rotate(180deg); }
/* On small cards, pull the corner indices tight to the edge so the center suit glyph
   has room to breathe (and can run a touch larger) without crowding the corners. */
.card.sm .ctl { top: 3px; left: 4px; }
.card.sm .cbr { bottom: 3px; right: 4px; }
.ct-r { font-family: var(--display); font-weight: 700; line-height: 0.95; }
.ct-s { font-family: var(--f); line-height: 1; margin-top: 1px; }
/* Suit glyphs are flat text, never emoji. The trailing U+FE0E in cardHTML handles older engines;
   font-variant-emoji is the standardised hint (Chrome 131+, Firefox, Safari 17.4+) and stops mobile
   browsers from substituting an oversized multicolor emoji for ♥/♦. */
.ct-s, .cbody .csuit { font-variant-emoji: text; }
.card.lg .ct-r { font-size: 1.35rem; }   .card.lg .ct-s { font-size: 1.1rem; }
.card.md .ct-r { font-size: 1.1rem; }    .card.md .ct-s { font-size: 0.95rem; }
.card.sm .ct-r { font-size: 0.9rem; }    .card.sm .ct-s { font-size: 0.75rem; }
/* Tighten "10" so it fits the corner */
.ct-r[data-r="10"] { font-size: 1.05rem !important; letter-spacing: -0.06em; }
.card.md .ct-r[data-r="10"] { font-size: 0.9rem !important; }
.card.sm .ct-r[data-r="10"] { font-size: 0.72rem !important; }

.cbody {
  position: absolute; inset: 0;
  display: flex; align-items: center; justify-content: center;
  pointer-events: none;
}
.cbody .csuit { font-family: var(--f); line-height: 1; }
.card.lg .csuit { font-size: 3.4rem; }
.card.md .csuit { font-size: 2.8rem; }
.card.sm .csuit { font-size: 2.2rem; }
/* Inline SVG icons (see src/icons.js). Sized in em, color via currentColor. */
.ic { width: 1em; height: 1em; vertical-align: -0.15em; flex: 0 0 auto; }
/* The ♦ glyph is the narrowest suit in virtually every system font (Tahoma: ♦≈27px vs ♣≈35px at the
   same size), so a diamond reads visibly smaller than ♠♥♣: most noticeable on the tiny split cards
   where the centre suit is the only suit shown. Scale diamonds up so all four suits look balanced.
   These elements are flex items (.cbody / .ctl / .cbr are flex), so transform applies and, scaling
   about the default centre origin, keeps the glyph centred and the corner rank in place. */
.card.suit-d .csuit { transform: scale(1.12); }
.card.suit-d .ct-s  { transform: scale(1.1); }

.card.red, .card.red .ct-r, .card.red .ct-s, .card.red .csuit { color: var(--red); }
.card.blk, .card.blk .ct-r, .card.blk .ct-s, .card.blk .csuit { color: var(--ink); }
body.four-color .card.suit-d .ct-r,
body.four-color .card.suit-d .ct-s,
body.four-color .card.suit-d .csuit { color: #1a6fcc; }
body.four-color .card.suit-c .ct-r,
body.four-color .card.suit-c .ct-s,
body.four-color .card.suit-c .csuit { color: #1a7a3a; }
/* Suit-colored spans (used in help text, responds to four-color pref) */
.sym-s, .sym-c { color: var(--ink); }
.sym-h, .sym-d { color: var(--red); }
body.four-color .sym-d { color: #1a6fcc; }
body.four-color .sym-c { color: #1a7a3a; }

/* Card back */
.card.back {
  background: #8b2820;
  background-image:
    repeating-linear-gradient(45deg, rgba(251,245,220,0.10) 0 1px, transparent 1px 5px),
    repeating-linear-gradient(-45deg, rgba(251,245,220,0.10) 0 1px, transparent 1px 5px),
    radial-gradient(ellipse at center, #a13428 0%, #8b2820 75%);
}
.card.back::after {
  content: ''; position: absolute; inset: 9px;
  border: 1px dashed rgba(251,245,220,0.30); border-radius: 3px;
}
.card.back::before {
  content: 'G'; position: absolute; inset: 0;
  display: flex; align-items: center; justify-content: center;
  font-family: var(--btn-f); font-weight: 700;
  color: #fbf5dc; text-shadow: 2px 2px 0 rgba(0,0,0,0.40);
  letter-spacing: 0.02em;
}
.card.lg.back::before { font-size: 3.2rem; }
.card.md.back::before { font-size: 2.7rem; }
.card.sm.back::before { font-size: 2.1rem; }
/* Maroon felt (unlockable at 2500+ PB) */
body.felt-maroon { --felt: #611018; --felt-light: #8a1825; --felt-dark: #3d0a10; --felt-edge: #200508; }

/* Golden card back (unlockable) */
body.cardback-gold .card.back {
  background: #1e1206;
  background-image:
    linear-gradient(155deg, #f0c84a 0%, #b07820 20%, #7a5010 38%, #c4933a 52%, #f5d060 62%, #9a6818 80%, #f0c84a 100%);
}
body.cardback-gold .card.back::after { display: none; }
body.cardback-gold .card.back::before { content: ''; text-shadow: none; }
/* Orange card back (unlockable at 1500+ PB) */
body.cardback-orange .card.back {
  background: #8c3a00;
  background-image:
    repeating-linear-gradient(45deg, rgba(251,245,220,0.10) 0 1px, transparent 1px 5px),
    repeating-linear-gradient(-45deg, rgba(251,245,220,0.10) 0 1px, transparent 1px 5px),
    radial-gradient(ellipse at center, #f06010 0%, #8c3a00 75%);
}
/* Emoji deck (unlockable at 3500+ PB): replace suit symbols and ranks with emoji */
body.deck-emoji .ct-s,
body.deck-emoji .csuit,
body.deck-emoji .ct-r[data-r="A"],  body.deck-emoji .ct-r[data-r="2"],
body.deck-emoji .ct-r[data-r="3"],  body.deck-emoji .ct-r[data-r="4"],
body.deck-emoji .ct-r[data-r="5"],  body.deck-emoji .ct-r[data-r="6"],
body.deck-emoji .ct-r[data-r="7"],  body.deck-emoji .ct-r[data-r="8"],
body.deck-emoji .ct-r[data-r="9"],  body.deck-emoji .ct-r[data-r="10"],
body.deck-emoji .ct-r[data-r="J"],  body.deck-emoji .ct-r[data-r="Q"],
body.deck-emoji .ct-r[data-r="K"] { visibility: hidden; display: inline-block; position: relative; }
body.deck-emoji .ct-s::after,
body.deck-emoji .csuit::after,
body.deck-emoji .ct-r[data-r="A"]::after,  body.deck-emoji .ct-r[data-r="2"]::after,
body.deck-emoji .ct-r[data-r="3"]::after,  body.deck-emoji .ct-r[data-r="4"]::after,
body.deck-emoji .ct-r[data-r="5"]::after,  body.deck-emoji .ct-r[data-r="6"]::after,
body.deck-emoji .ct-r[data-r="7"]::after,  body.deck-emoji .ct-r[data-r="8"]::after,
body.deck-emoji .ct-r[data-r="9"]::after,  body.deck-emoji .ct-r[data-r="10"]::after,
body.deck-emoji .ct-r[data-r="J"]::after,  body.deck-emoji .ct-r[data-r="Q"]::after,
body.deck-emoji .ct-r[data-r="K"]::after { visibility: visible; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); }
body.deck-emoji .csuit::after { font-size: 0.8em; }
body.deck-emoji .suit-s .ct-s::after, body.deck-emoji .suit-s .csuit::after { content: '💧'; }
body.deck-emoji .suit-h .ct-s::after, body.deck-emoji .suit-h .csuit::after { content: '🔥'; }
body.deck-emoji .suit-d .ct-s::after, body.deck-emoji .suit-d .csuit::after { content: '💨'; }
body.deck-emoji .suit-c .ct-s::after, body.deck-emoji .suit-c .csuit::after { content: '🌱'; }
body.deck-emoji .ct-r[data-r="A"]::after  { content: '🅰️'; }
body.deck-emoji .ct-r[data-r="2"]::after  { content: '2️⃣'; }
body.deck-emoji .ct-r[data-r="3"]::after  { content: '3️⃣'; }
body.deck-emoji .ct-r[data-r="4"]::after  { content: '4️⃣'; }
body.deck-emoji .ct-r[data-r="5"]::after  { content: '5️⃣'; }
body.deck-emoji .ct-r[data-r="6"]::after  { content: '6️⃣'; }
body.deck-emoji .ct-r[data-r="7"]::after  { content: '7️⃣'; }
body.deck-emoji .ct-r[data-r="8"]::after  { content: '8️⃣'; }
body.deck-emoji .ct-r[data-r="9"]::after  { content: '9️⃣'; }
body.deck-emoji .ct-r[data-r="10"]::after { content: '🔟'; }
body.deck-emoji .ct-r[data-r="J"]::after  { content: '🇯'; }
body.deck-emoji .ct-r[data-r="Q"]::after  { content: '🇶'; }
body.deck-emoji .ct-r[data-r="K"]::after  { content: '🇰'; }

/* Whale card back (unlockable at 5000+ PB) */
body.cardback-whale .card.back {
  background: #0a2a50;
  background-image:
    repeating-linear-gradient(45deg, rgba(180,220,255,0.10) 0 1px, transparent 1px 5px),
    repeating-linear-gradient(-45deg, rgba(180,220,255,0.10) 0 1px, transparent 1px 5px),
    radial-gradient(ellipse at center, #1a5aaa 0%, #0a2a50 75%);
}
body.cardback-whale .card.back::before { content: '🐋'; }

.deal-anim {
  animation: deal 0.55s cubic-bezier(.22,.61,.36,1) both;
  will-change: transform;
  backface-visibility: hidden;
}
@keyframes deal { from { opacity: 0; transform: translateY(-24px) scale(.9); } to { opacity: 1; transform: translateZ(0); } }
@keyframes fadein { from { opacity: 1; transform: translateY(6px); } to { opacity: 1; transform: none; } }

/* Cross-screen view transitions (navRender): crossfade ONLY the centered .panel card between
   significantly different screens: a new game, a hand's result panel, the next hand. We take the
   root OUT of the transition (view-transition-name:none) so the full viewport is never snapshotted
   or animated: that whole-screen capture+composite scaled with pixel count and was the source of
   the desktop lag (big window means big textures; mobile's small viewport was always cheap). The static
   window frame, background, and status bar now swap instantly while the bounded panel crossfades.
   Exactly one .panel exists per render (even BJ split nests its aside hands inside it), so the name
   stays unique. Gated in JS (feature-detect + the test flag); reduced-motion guard belt-and-suspenders. */
:root { view-transition-name: none; }
.panel { view-transition-name: gambdle-panel; }
::view-transition-old(gambdle-panel),
::view-transition-new(gambdle-panel) { animation-duration: 0.18s; }
@media (prefers-reduced-motion: reduce) {
  :root, .panel { view-transition-name: none; }
}

.hand {
  display: flex; gap: 8px; align-items: flex-end; justify-content: center; flex-wrap: wrap;
  isolation: isolate;
}
/* Dealer cards + (optional) peek button on one centered row, peek to the right. */
.dealer-hand-row { display: flex; align-items: center; justify-content: center; gap: 16px; }
.dealer-hand-row #peek-btn-wrap, .dealer-hand-row #tt-btn-wrap { flex-shrink: 0; }
.hand-val {
  font-family: var(--btn-f); font-size: 2.6rem;
  color: var(--cream); text-align: center; margin-top: 10px;
  letter-spacing: 0.04em; line-height: 1;
}
.panel.cream .hand-val { color: var(--ink); }
.hand-val.bust { color: var(--lose-hi); }
.hand-val.bj { color: var(--gold-hi); }

/* UTH bet screen: middle column that takes the role the BJ bet table plays. flex:1 so it eats all
   the panel slack, pinning the chip selector + Deal button to the exact same spot as Blackjack, and
   space-evenly so the pay table + its caption are spread evenly through whatever slack exists. */
.uth-bet-center {
  flex: 1; min-height: 0;
  display: flex; flex-direction: column;
  justify-content: center; align-items: center;
  gap: 6px;
}
/* Pay-table box + its caption as one group, caption hugging right below the box. The group is
   centred in the slack the spacer holds. */
.uth-pt-wrap {
  display: flex; flex-direction: column; align-items: center;
  gap: 4px; width: 100%;
}
.uth-pt-wrap #uth-pt-head { margin: 0; text-align: center; } /* caption sits right under the box, centered */
/* Compact + inlaid (recessed): a small, sunken pay table keeps the centre of the UTH bet screen open
   to breathe. Per-breakpoint font/padding are shrunk in the desktop @media blocks below. */
.panel:has(#uth-summary) .ptable { width: 100%; max-width: 320px;
  box-shadow: inset 1px 1px 0 var(--shadow), inset -1px -1px 0 var(--highlight); }
/* The Ante+Blind+total summary now lives INSIDE the bet box (replacing the plain "Bet" readout),
   so it must stay compact enough to match the Blackjack bet box's size. */
.uth-bet-sum {
  font-family: var(--btn-f); color: var(--ink);
  font-size: 1.05rem; line-height: 1.12; text-align: center;
  white-space: nowrap;
}
/* The summary sits inside the bet box, sharing one row with the Clear and All In buttons (the bet box
   flexes to take the leftover width). Text is compact (numbers only) so a single non-wrapping line fits
   beside the buttons at every size; centred vertically in the box and enlarged toward the clamp cap. */
.panel:has(#uth-summary) .bet-amt { align-items: center; }
.panel:has(#uth-summary) #uth-summary.uth-bet-sum {
  font-size: clamp(0.72rem, 2.2vw, 1.35rem);
  margin: 0 !important; line-height: 1.12;
  white-space: nowrap; text-align: center;
}

/* ── BJ inactive split hands ────────────────────────────── */
.bj-split-aside { display: flex; justify-content: space-evenly; margin-bottom: 10px; }
.bj-split-lbl { font-size: 1.1rem; margin-bottom: 4px; }
.bj-split-val { font-size: 1.4rem; font-weight: 700; margin-top: 2px; }
.bj-active-lbl { font-size: 1.4rem; }
/* Bet amount folded into the active-hand label, slightly dimmed so the hand number
   reads first (cream, not shadow: shadow is too dark to read on the felt). */
.bj-active-bet { opacity: 0.7; }

/* ── Split-result vertical rhythm ───────────────────────────
   Spread leftover panel height evenly across the gaps BETWEEN the result-body
   elements (headline → sub → dealer → hands → running total), instead of pooling
   it into one big band under the dots. The dots stay pinned at the top and the
   Next-Hand button stays tucked under the running total: neither boundary gap
   grows. Auto-margins split the free space equally among the elements that carry one. */
/* The headline + chip-delta now ride together in one .result-head block, which carries the
   auto-margin (its internal gap keeps the sub tucked tight under the headline). */
.bj-split-result > .result-head,
.bj-split-result > .bj-sr-dealer,
.bj-split-result > .bj-sr-hands,
.bj-split-result > .game-controls { margin-top: auto !important; }
/* Breathing room inside the result dealer block: DEALER → card → value → divider.
   (Spends slack reclaimed by tightening the headline/sub into one unit.) Skipped on
   the 4-hand grid, which has no spare height. */
.bj-split-result:not(.sr-4) .bj-sr-dealer .sec { margin-bottom: 8px; }
.bj-split-result:not(.sr-4) .bj-sr-dealer .hand-val { margin-top: 8px !important; }
.bj-split-result:not(.sr-4) > .bj-sr-dealer { margin-bottom: 10px !important; }

/* ── Overlapping card fan (split hands) ─────────────────── */
.hand-fan { flex-wrap: nowrap; gap: 0; }
.hand-fan .card + .card { margin-left: -28px; }
/* Auto-fan when 5+ cards would overflow */
.hand:has(.card:nth-child(5)) { flex-wrap: nowrap; gap: 0; }
.hand:has(.card:nth-child(5)) .card + .card { margin-left: -28px; }
/* UTH community cards: cancel auto-fan, keep all 5 evenly spaced */
#uth-community-hand.hand:has(.card:nth-child(5)) { flex-wrap: nowrap; gap: 5px; }
#uth-community-hand.hand:has(.card:nth-child(5)) .card + .card { margin-left: 0; }

/* ── Sixth Sense (uth_sixth_card): a private 6th community card ───────────
   Six cards (5 shared + the player's private one) on one row: shrink the community cards so the row
   still fits the 360px floor. The private card carries a gold glow + a "YOU" tag. */
#uth-community-hand.sixth-sense.hand:has(.card:nth-child(5)) { gap: 4px; }
#uth-community-hand.sixth-sense .card { width: 48px; height: 67px; }
#uth-community-hand.sixth-sense .card .ct-r { font-size: 0.74rem; }
#uth-community-hand.sixth-sense .card .ct-s { font-size: 0.6rem; }
#uth-community-hand.sixth-sense .card .csuit { font-size: 1.7rem; }
#uth-community-hand.sixth-sense .card .ct-r[data-r="10"] { font-size: 0.58rem !important; }
.uth-priv-slot { position: relative; display: flex; align-items: flex-end; }
.uth-priv-tag {
  position: absolute; top: -7px; left: 50%; transform: translateX(-50%);
  background: var(--gold); color: var(--ink);
  font-family: var(--btn-f); font-size: 0.5rem; font-weight: 700; letter-spacing: 0.08em;
  padding: 1px 5px; border-radius: 3px; border: 1px solid var(--ink); z-index: 2; line-height: 1.25;
}

/* ── Double Vision (bj_two_hands): pick one of two candidate hands ────────
   Cards sit side by side in the middle (each a blackjack hand). The keep action is two solid-gold
   buttons in the action-button zone (.act-btn.primary, height-locked to --btn-h) so the bottom cluster
   matches the play screen and the bet inlay lands in exactly the same spot. */
.bj-pick-row { display: flex; gap: 18px; justify-content: center; align-items: flex-start; margin-top: 10px; }
.bj-pick-cards { flex-wrap: nowrap; gap: 5px; } /* two candidate cards stay side by side, never stacked */
.bj-pick-val { font-family: var(--btn-f); font-size: 1.5rem; color: var(--cream); letter-spacing: 0.04em; line-height: 1; margin-top: 8px; }
.panel.cream .bj-pick-val { color: var(--ink); }
.bj-pick-btn { flex-direction: column; gap: 1px; line-height: 1.05; }
.bj-pick-btn-lbl { font-size: 0.8rem; letter-spacing: 0.06em; opacity: 0.85; }
.bj-pick-btn-val { font-size: 1.2rem; font-weight: 700; }

/* ── BJ bet screen: empty card slots framing the chip selector ── */
.bj-bet-table {
  flex: 1; min-height: 0;
  display: flex; flex-direction: column;
  justify-content: space-around; align-items: center;
  gap: 8px; padding: 4px 0;
}
.bj-bet-slot-row { display: flex; flex-direction: column; align-items: center; gap: 4px; }
.bj-bet-slot-lbl {
  font-family: var(--btn-f); font-size: 1rem;
  color: var(--cream); opacity: 0.55; letter-spacing: 0.18em;
  text-transform: uppercase; line-height: 1;
}
.bj-bet-slots { display: flex; gap: 8px; }
.card-slot {
  width: 60px; height: 84px;
  border: 2px dashed rgba(251, 245, 220, 0.22);
  border-radius: 5px;
  background: rgba(0, 0, 0, 0.07);
}
/* Casino felt rules: small uppercase text between dealer & player slots */
.felt-rules {
  text-align: center; line-height: 1.4;
  color: var(--cream); opacity: 0.7;
  font-family: var(--btn-f);
  font-size: 0.95rem; letter-spacing: 0.16em;
  text-transform: uppercase;
  text-shadow: 0 1px 0 rgba(0, 0, 0, 0.4);
  padding: 4px 0;
}
.felt-rule-line { white-space: nowrap; }

/* ── Chip selector ──────────────────────────────────────── */
/* Chip row never wraps: chips that don't fit shrink via flex-shrink rather than
   spilling onto a second row. Mobile re-asserts nowrap with tighter gap below. */
.chip-row { display: flex; gap: 8px; justify-content: center; margin-bottom: 14px; flex-wrap: nowrap; }
.chbtn {
  position: relative; width: 60px; height: 60px;
  border-radius: 50%;
  border: 1.5px solid rgba(0,0,0,0.8);
  cursor: pointer; padding: 0;
  background:
    /* Top lighting/gloss */
    radial-gradient(ellipse 60% 40% at 50% 25%, rgba(255,255,255,0.25) 0%, transparent 100%),
    /* Thick Recessed Bevel Shadow */
    radial-gradient(circle, transparent 40%, rgba(0,0,0,0.3) 48%, transparent 55%),
    /* Multi-color Edge Inserts (Base + Stripe + Accent) */
    radial-gradient(circle, var(--c-base) 0% 58%, transparent 59%),
    repeating-conic-gradient(
      var(--c-base) 0deg 12deg,
      var(--c-stripe) 12deg 24deg,
      var(--c-accent) 24deg 36deg,
      var(--c-base) 36deg 60deg
    );
  box-shadow:
    inset 0 -4px 6px rgba(0,0,0,0.28),
    inset 0 2px 4px rgba(255,255,255,0.14),
    0 4px 0 rgba(0,0,0,0.55),
    0 6px 14px rgba(0,0,0,0.35);
  color: var(--cream);
}
.chbtn > span {
  position: relative; z-index: 2;
  display: flex; align-items: center; justify-content: center;
  width: 100%; height: 100%;
  font-family: var(--btn-f); font-size: 1.2rem;
  text-shadow: 1px 1px 0 rgba(0,0,0,0.55);
  letter-spacing: 0.04em;
}
.chbtn:hover:not(:disabled) { filter: brightness(1.1); }
.chbtn:active:not(:disabled) {
  transform: translateY(2px);
  box-shadow: inset 0 4px 6px rgba(0,0,0,0.28), inset 0 -2px 4px rgba(255,255,255,0.14), 0 1px 0 rgba(0,0,0,0.5), 0 2px 6px rgba(0,0,0,0.3);
}
.chbtn:disabled { opacity: 0.32; cursor: not-allowed; }

.ch-10   { --c-base: #b8b6b0; --c-stripe: #ffffff; --c-accent: #444444; color: var(--ink); }
.ch-10 > span  { text-shadow: 1px 1px 0 rgba(255,255,255,0.6); color: var(--ink); }
.ch-25   { --c-base: #b52030; --c-stripe: #ffffff; --c-accent: #1a60ae; }
.ch-50   { --c-base: #0d6834; --c-stripe: #ffffff; --c-accent: #dfb95e; }
.ch-100  { --c-base: #1e1e1e; --c-stripe: #ffffff; --c-accent: #b52030; }
.ch-250  { --c-base: #1a60ae; --c-stripe: #ffffff; --c-accent: #b52030; }
.ch-500  { --c-base: #c06818; --c-stripe: #ffffff; --c-accent: #1a60ae; }
.ch-1000 { --c-base: #5522a8; --c-stripe: #ffffff; --c-accent: #dfb95e; }

/* The bet-row stretches to the near-full-panel --ctrl-w and centers. The box keeps its fixed
   --bet-box-w; Clear (left) + All In (right) flex-grow to fill the rest, so [Clear][box][All In]
   spans most of the window. flex-wrap lets Clear/All In drop below the box on panels too narrow to
   flank it (tight desktop / phone). */
.bet-row { display: flex; flex-wrap: wrap; align-items: stretch; justify-content: center; gap: 10px;
  width: 100%; max-width: var(--ctrl-w); margin-left: auto; margin-right: auto; }
.bet-row > .bet-amt { flex: 0 0 auto; width: var(--bet-box-w); }
.bet-row > .ch-clear, .bet-row > .ch-allin { flex: 1 1 0; min-width: 0; }
.bet-amt {
  /* flex:0 0 auto (NOT a flex-basis of --bet-box-w): in .game-controls (a column flex) a flex-basis
     would set the box HEIGHT. Width is pinned via `width` so it's the cross-axis size there and the
     main size in the bet-row: identical --bet-box-w either way; height stays --btn-h. */
  flex: 0 0 auto; width: var(--bet-box-w); min-width: 0;
  padding: 0 8px;
  color: var(--ink);
  background: var(--panel); border: 1px solid var(--ink);
  box-shadow: inset 1px 1px 0 var(--shadow), inset -1px -1px 0 var(--highlight);
  /* The amount is vertically centered in the box; the "Bet" label centers against the amount to its
     right (align-items:center), not on its baseline. */
  display: flex; flex-direction: row; align-items: center; justify-content: center; gap: 8px;
}
/* Uniform horizontal padding so the box is pixel-identical across every screen (the unified-button rule
   above already forces vertical padding to 0). !important beats the scattered per-screen/per-breakpoint
   .panel:has(...) .bet-amt padding overrides: the box is fixed-width with centered content, so one
   padding value reads the same everywhere. */
.bet-amt { padding-left: 14px !important; padding-right: 14px !important; }
/* "Bet" label sits to the LEFT of the amount on one line. Both are black (the plain box uses ink for
   amount + label; UTH/roulette keep their gold emphasis numbers via inner <b>). */
.bet-amt span:first-child { font-family: var(--btn-f); font-size: 0.7em; color: var(--ink); letter-spacing: 0.14em; text-transform: uppercase; line-height: 1.05; }
.bet-amt span:last-child { font-family: var(--btn-f); font-size: 1em; color: var(--ink); line-height: 1.05; }
.ch-clear, .ch-allin {
  flex-shrink: 0;
  padding: 0 10px; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  font-family: var(--btn-f);
  background: var(--panel); color: var(--ink);
  border: 1px solid var(--ink);
  box-shadow: var(--raised);
  white-space: nowrap;
}
.ch-allin { background: var(--gold); box-shadow: inset 1.5px 1.5px 0 var(--gold-hi), inset -2px -2px 0 var(--gold-lo); }
.ch-clear:active, .ch-allin:active { transform: translate(1px,1px); }
.ch-allin:disabled { opacity: 0.35; cursor: not-allowed; }

/* ── Hand progress dots (pills) ─────────────────────────── */
.dots-row { display: flex; gap: 8px; margin: 4px 0 4px; }
/* UTH wraps its dots in #uth-dots-container (for surgical re-renders). Make that wrapper always
   generate no box (display:contents) so .dots-row is a direct flex child of the panel on every UTH
   phase, otherwise the wrapper introduces margin-collapse and block-layout quirks that shift the
   dots-row by 2-6px between bet and play phases depending on viewport width. */
#uth-dots-container { display: contents; }
.hand-dot {
  flex: 1; min-width: 0; padding: 4px 10px;
  background: var(--panel); color: var(--shadow);
  border: 1px solid var(--ink);
  box-shadow: none;
  font-family: var(--btn-f);
  font-size: 1.4rem; text-align: center; line-height: 1.1;
  letter-spacing: 0.06em;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.hand-dot.cur  { background: var(--gold); color: var(--ink); font-weight: 700;
  box-shadow: inset 2px 2px 0 var(--gold-lo), inset -1px -1px 0 var(--gold-hi); }
.hand-dot.won, .hand-dot.lost { color: var(--ink); font-weight: 700; opacity: 0.6; }
.hand-dot.won  .dot-detail { color: var(--win); }
.hand-dot.lost .dot-detail { color: var(--lose); }
.hand-dot.push { color: var(--shadow); opacity: 0.6; }
.hand-dot.pend { color: var(--shadow); opacity: 0.6; }

/* ── Info row (label / value pair) ──────────────────────── */
.irow {
  display: flex; justify-content: space-between; align-items: baseline;
  padding: 6px 12px;
  background: var(--panel); color: var(--ink);
  border: 1px solid var(--ink);
  box-shadow: var(--raised-sm);
}
.ik { font-size: 1.4rem; color: var(--shadow); letter-spacing: 0.04em; }
.iv { font-family: var(--btn-f); font-size: 1.35rem; color: var(--ink); }
.sec-sm { font-size: 1rem; }
/* ── Dev-stats grouped boxes ── each category is one inlaid (recessed) box; the boxes flow into
   two columns so the screen fits. The box provides the chrome, so its rows drop their own tile. */
.dvs-groups { columns: 2; column-gap: 6px; text-align: left; }
.dvs-box {
  break-inside: avoid; -webkit-column-break-inside: avoid;
  background: var(--panel); color: var(--ink);
  border: 1px solid var(--ink);
  box-shadow: inset 1px 1px 0 var(--shadow), inset -1px -1px 0 var(--highlight);
  padding: 2px 0 4px;
  margin-bottom: 6px;
}
.dvs-box .irow { border: none; box-shadow: none; background: transparent; padding: 2px 8px; }
.dvs-box .irow + .irow { border-top: 1px solid rgba(0,0,0,0.07); }
/* Dev-stats group label: small, gold; header inside each inlay box. */
.dvs-grp-lbl {
  font-family: var(--btn-f);
  font-size: 0.82rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--gold);
  text-align: left;
  margin: 0 0 2px;
  padding: 2px 8px 3px;
  border-bottom: 1px solid rgba(0,0,0,0.14);
}
/* Standalone section label (no surrounding box): e.g. the Score Distribution chart heading. */
.dvs-grp-lbl-bare { border-bottom: none; padding: 0 0 0 2px; }
/* Desktop: dev stats carries many groups + the chart, so tighten boxes/rows (scoped to
   #devstats-body) to keep the whole screen on one window at 1280×800. */
@media (min-width: 1024px) {
  #devstats-body .dvs-box { padding: 1px 0 3px; margin-bottom: 4px; }
  #devstats-body .irow { padding: 1px 8px; }
  #devstats-body .dvs-grp-lbl { padding: 1px 8px 2px; }
}
.gold-divider { width: 60%; height: 1px; background: rgba(196,147,58,0.1); align-self: center; }
.result-hl { font-family: var(--btn-f); font-size: 3rem; margin-bottom: 4px; text-shadow: 2px 2px 0 rgba(0,0,0,0.4); }
.result-sub { font-family: var(--btn-f); font-size: 2rem; margin-bottom: 14px; }
/* Borrow screen "0 chips remaining": a touch smaller than a normal result-sub. */
.result-sub.borrow-rem { font-size: 1.7rem; }
/* ── Result head ────────────────────────────────────────── */
/* The win/lose headline with the chip delta tucked right beneath it, as one unit: used by
   EVERY result screen (BJ single + split, UTH showdown/fold, Roulette, Poker) so the spacing
   reads identically across games. The head is one flex child of the panel; we zero the
   element directly above it (the divider, or roulette's number-name line) and the one directly
   below it, so the panel's own flex `gap` plus the head's small symmetric margin space it
   EQUALLY top and bottom at every breakpoint: the block stays centered between its neighbors,
   while the chip line hugs the headline via the tight internal `gap`. */
.result-head { display: flex; flex-direction: column; gap: 4px; margin: 3px 0; text-align: center; }
.result-head > .result-hl, .result-head > .result-sub { margin: 0 !important; }
*:has(+ .result-head) { margin-bottom: 0 !important; }
.result-head + * { margin-top: 0 !important; }
.uth-cards-col { display:flex; flex-direction:column; gap:12px; align-items:center; margin:12px 0; }
.uth-bets-grid { display:grid; grid-template-columns:1fr auto; gap:3px 14px; margin-bottom:10px; }
.bj-celebrate-txt { font-family: var(--btn-f); font-size: 2.8rem; color: var(--gold-hi); letter-spacing: 0.04em; margin-top: 14px; text-shadow: 0 0 28px rgba(196,147,58,0.55); }

/* ── Game manifest tile (intro screen) ──────────────────── */
.game-manifest {
  background: var(--panel); color: var(--ink);
  border: 1px solid var(--ink);
  box-shadow: var(--raised-sm);
}
/* On the results page the game-summary box reads as an inlay (recessed): flip to the
   canonical inlay bevel: shadow top-left, highlight bottom-right, same as .bet-amt. */
.results-panel .game-manifest {
  box-shadow: inset 1px 1px 0 var(--shadow), inset -1px -1px 0 var(--highlight);
}
.gm-row {
  display: grid; grid-template-columns: 32px 1fr;
  gap: 10px; align-items: center;
  padding: 8px 12px;
}
.gm-sep { height: 1px; background: var(--ink); }
.rnd-ic { font-size: 1.6rem; line-height: 1; }
.rnd-nm { font-size: 2.1rem; font-weight: 700; line-height: 1; letter-spacing: 0.02em; display: flex; align-items: baseline; }
.rnd-dc { font-size: 1.6rem; color: var(--shadow); font-weight: 400; margin-left: auto; } /* push the "· 3 hands" desc to the right edge of the row */

/* ── Pay table ──────────────────────────────────────────── */
.ptable { display: grid; grid-template-columns: 1fr auto; gap: 2px 14px;
  background: var(--panel); padding: 10px 12px;
  border: 1px solid var(--ink);
  box-shadow: var(--raised-sm);
}
.pname { font-size: 1.65rem; color: var(--ink); }
.ppay  { font-size: 1.5rem; color: var(--ink); font-weight: 700; text-align: right; font-family: var(--btn-f); }

/* ── Roulette ───────────────────────────────────────────── */
/* flex-shrink:0 + overflow-y:hidden: the board must always be fully visible.
   Without these, the flex panel can shrink this wrap when content is tall, and
   because overflow-x:auto forces overflow-y to compute to `auto`, the lower
   betting rows (dozens / even-money) silently scroll out of view. The board
   never scrolls vertically on any view; horizontal scroll stays for narrow
   mobile widths only. */
.r-board-wrap { overflow-x: auto; overflow-y: hidden; flex-shrink: 0; margin: 0 -10px; padding: 0 10px 4px; -webkit-overflow-scrolling: touch; }
/* Slack-absorbing spacer (mirrors .bj-bet-table / .uth-bet-center): bottom-anchors the chip selector
   + Final Spin to the SAME spot as the other bet screens, so placing bets never scoots the controls. */
.r-bet-center { flex: 1; min-height: 0; display: flex; flex-direction: column; align-items: center; }
/* Two stacked boxes fill the spacer: the SELECTION box (natural height) then the BETS tracker (grows to
   fill the felt). */
.r-bet-center { gap: 6px; }
/* Selection box: shows the picked tile + its payout (one centered line); a prompt when nothing's picked. */
.r-sel-box { background: var(--panel); border: 1px solid var(--ink); box-shadow: inset 1px 1px 0 var(--shadow), inset -1px -1px 0 var(--highlight);
  flex: 0 0 auto; padding: 5px 12px; text-align: center; font-family: var(--btn-f); color: var(--ink);
  font-size: 1.35rem; }
.rsb-prompt { color: var(--shadow); text-align: center; }
/* Three equal-width columns (left/center/right anchored) so the groups stay evenly spaced and a long
   label or big payout never shifts the other sections. */
.rsb-box { display: flex; align-items: baseline; gap: 6px; font-variant-numeric: tabular-nums; }
.rsb-on   { flex: 1 1 0; min-width: 0; text-align: left; white-space: nowrap; overflow: hidden; }
.rsb-on b { font-weight: 700; }        /* wheel color comes from the rbz-red/blk/grn class on the same <b> */
.rsb-pays { flex: 1 1 0; min-width: 0; text-align: center; color: var(--shadow); white-space: nowrap; }
.rsb-win  { flex: 1 1 0; min-width: 0; text-align: right; color: var(--ink); font-weight: 700; white-space: nowrap; }
/* Bets tracker: grows to fill the remaining slack (capped); title pinned to the TOP, grid below it. */
.r-bets-zone { background: var(--panel); border: 1px solid var(--ink); box-shadow: inset 1px 1px 0 var(--shadow), inset -1px -1px 0 var(--highlight);
  padding: 6px 12px; margin: 0; overflow-y: auto;
  flex: 1 1 auto; min-height: 72px; max-height: 190px;
  display: flex; flex-direction: column; justify-content: flex-start; }
.rbz-title { text-align: center; font-family: var(--btn-f); color: var(--ink); font-size: 1.5rem;
  letter-spacing: 0.04em; padding: 2px 0 8px; }
.rbz-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 4px 18px; }
.rbz-item { display: flex; justify-content: space-between; align-items: baseline; padding: 2px 0; gap: 8px; }
.rbz-lbl { font-size: 1.4rem; font-weight: 700; color: var(--ink); white-space: nowrap; }
.rbz-red { color: #a32f24; }  /* wheel colors, matching the board tiles */
.rbz-blk { color: #1f1c18; }
.rbz-grn { color: #156c3a; }
/* tabular-nums + fixed-width right-aligned slots so the stake and winnings line up in columns down each
   grid column regardless of how many digits the payout has. */
.rbz-win { font-family: var(--btn-f); font-size: 1.15rem; color: var(--shadow); display: flex; align-items: baseline; gap: 3px; white-space: nowrap; font-variant-numeric: tabular-nums; }
.rbz-bet { text-align: right; min-width: 2.2em; }
.rbz-won { color: var(--ink); font-weight: 700; text-align: right; min-width: 3.4em; }
.rbz-win button { background: none; border: none; color: var(--shadow); cursor: pointer; font-size: 1.25rem; padding: 0 2px; line-height: 1; }
.rbz-open { color: var(--shadow); opacity: 0.5; font-size: 1.2rem; }
/* Single-bet mod (r_max_bets:1): one centered slot, larger text in both boxes (more room with one bet). */
.panel:has(#r-bets-zone) .r-one .rbz-grid { grid-template-columns: 1fr; justify-items: center; }
.panel:has(#r-bets-zone) .r-one .rbz-item { justify-content: center; gap: 14px; }
.panel:has(#r-bets-zone) .r-one .r-sel-box { font-size: 1.5rem; }
.panel:has(#r-bets-zone) .r-one .rbz-title { font-size: 1.75rem; }
.panel:has(#r-bets-zone) .r-one .rbz-lbl { font-size: 1.85rem; }
.panel:has(#r-bets-zone) .r-one .rbz-win { font-size: 1.4rem; }
.panel:has(#r-bets-zone) .r-one .rbz-open { font-size: 1.6rem; }
/* Three-bet mod (r_max_bets:3): single centered column so 3 slots stack evenly instead of 2+1 lopsided. */
.panel:has(#r-bets-zone) .r-three .rbz-grid { grid-template-columns: 1fr; justify-items: center; }
.panel:has(#r-bets-zone) .r-three .rbz-item { justify-content: center; gap: 14px; }
/* Few-bet days (1 or 3 slots) don't fill the reserved box, so vertically center the title+slots as a
   group instead of bunching them against the top with dead felt below. (6-bet fills the box, so its
   default flex-start is untouched.) */
.panel:has(#r-bets-zone) .r-one #r-bets-zone,
.panel:has(#r-bets-zone) .r-three #r-bets-zone { justify-content: center; }
.btn-icon-gap { margin-left: 6px; }
/* Roulette's selection + bets boxes keep the centered chip-cluster width. */
.panel:has(#r-bets-zone) #r-sel-box,
.panel:has(#r-bets-zone) #r-bets-zone { width: 100%; max-width: 468px; margin-left: auto !important; margin-right: auto !important; }
/* Spin screen reuses the bare .r-bets-zone class (no #id), so the id-scoped rule above doesn't
   reach it: match its width and centering here, keyed off the spin panel's wheel canvas. */
.panel:has(#rwheel) .r-bets-zone { width: 100%; max-width: 468px; margin: 0 auto; }
/* Blackjack/UTH/Poker Deal and roulette's Final Spin (the lone commit button on each bet screen) sit
   slightly wider than the bet box and center, so the action button overhangs the box. */
.panel:has(.bj-bet-table) > #db,
.panel:has(#uth-summary) > #db,
.panel:has(.ptable) > #db,
.panel:has(#r-bets-zone) > #db { width: 100%; max-width: var(--act-btn-w); margin-left: auto !important; margin-right: auto !important; }
/* The play/result control cluster is capped to the bet-box width so the box (and the buttons under it)
   match the bet box on every screen. */
.game-controls { margin-left: auto !important; margin-right: auto !important; }
.rboard, .rboard-sub {
  display: grid;
  grid-template-columns: 30px repeat(12, 1fr) 42px;
  gap: 3px; margin-bottom: 3px;
}
.rboard { grid-template-rows: 42px 42px 42px; margin-top: 2px; }
.rboard-sub { grid-auto-rows: 34px; }
.rn {
  border: 1px solid var(--ink); cursor: pointer;
  font-family: var(--btn-f); font-size: 1.15rem;
  color: var(--cream); padding: 0; position: relative;
  display: flex; align-items: center; justify-content: center;
  box-shadow: inset 1.5px 1.5px 0 rgba(255,255,255,0.18), inset -2px -2px 0 rgba(0,0,0,0.40);
}
.rn:hover { filter: brightness(1.15); }
.rn.r-sel { box-shadow: inset 1.5px 1.5px 0 rgba(255,255,255,0.18), inset -2px -2px 0 rgba(0,0,0,0.40), 0 0 0 2px var(--gold); z-index: 3; }
.rn-red { background: #a32f24; }
.rn-blk { background: #1f1c18; color: #ffffff; }
.rn-grn { background: #156c3a; }
.r2to1, .rout {
  background: var(--panel); color: var(--ink);
  border: 1px solid var(--ink); cursor: pointer; padding: 0;
  font-family: var(--btn-f); font-size: 1.45rem; font-weight: 700;
  display: flex; align-items: center; justify-content: center;
  box-shadow: var(--raised); letter-spacing: 0.02em;
  position: relative;
}
.r2to1:hover, .rout:hover { filter: brightness(1.06); }
.r2to1.r-sel, .rout.r-sel { background: var(--gold); color: var(--ink); box-shadow: inset 1.5px 1.5px 0 var(--gold-hi), inset -2px -2px 0 var(--gold-lo); }
.rout-r { box-shadow: var(--raised), inset 4px 0 0 #a32f24; padding-left: 5px; }
.rout-b { box-shadow: var(--raised), inset 4px 0 0 var(--ink); padding-left: 5px; }
.r-boost { box-shadow: inset 1.5px 1.5px 0 rgba(255,255,255,0.18), inset -2px -2px 0 rgba(0,0,0,0.40), 0 0 0 2px var(--gold-hi); animation: r-pulse 1.4s ease-in-out infinite; }
@keyframes r-pulse { 50% { box-shadow: inset 1.5px 1.5px 0 rgba(255,255,255,0.18), inset -2px -2px 0 rgba(0,0,0,0.40), 0 0 0 3px var(--gold); } }
.r-boost-fire { box-shadow: inset 1.5px 1.5px 0 rgba(255,200,80,0.15), inset -2px -2px 0 rgba(0,0,0,0.40), 0 0 0 2px #e05500; animation: r-pulse-fire 1.1s ease-in-out infinite; }
@keyframes r-pulse-fire { 50% { box-shadow: inset 1.5px 1.5px 0 rgba(255,200,80,0.15), inset -2px -2px 0 rgba(0,0,0,0.40), 0 0 0 3px #ff8c00; } }
.btn-peek-glow { border-color: #e05500 !important; box-shadow: 0 0 0 1px #e05500, 0 0 10px 2px rgba(224,85,0,0.4); animation: btn-peek-pulse 1.1s ease-in-out infinite; }
@keyframes btn-peek-pulse { 50% { box-shadow: 0 0 0 1px #ff8c00, 0 0 14px 4px rgba(255,140,0,0.55); border-color: #ff8c00 !important; } }
.btn-timetravel-glow { border-color: #2b7fff !important; box-shadow: 0 0 0 1px #2b7fff, 0 0 10px 2px rgba(43,127,255,0.4); animation: btn-timetravel-pulse 1.1s ease-in-out infinite; }
@keyframes btn-timetravel-pulse { 50% { box-shadow: 0 0 0 1px #5aa0ff, 0 0 14px 4px rgba(90,160,255,0.55); border-color: #5aa0ff !important; } }
/* Force-group mod: tiles that can't win (outside the group) or are guaranteed wins (cover the whole
   group) are blocked: greyed and unclickable. No win/lose highlighting; the playable area + the
   today's-modifier banner communicate the forced group. */
.r-blocked { opacity: 0.22; cursor: not-allowed; pointer-events: none; }

.r-chip {
  position: absolute; top: -6px; right: -6px;
  width: 22px; height: 22px; border-radius: 50%;
  font-family: var(--btn-f); font-weight: 700; font-size: 0.9rem;
  display: flex; align-items: center; justify-content: center;
  line-height: 1; z-index: 10; pointer-events: none;
}
.r-chip-placed {
  background: var(--gold); color: var(--ink);
  border: 1px solid var(--ink);
  box-shadow: inset 1.5px 1.5px 0 var(--gold-hi), inset -2px -2px 0 var(--gold-lo);
}
.r-chip-sel { background: rgba(196,147,58,0.25); border: 1px dashed var(--gold); }
/* Column 2:1 buttons sit at the top of the board; move their chip to the bottom to avoid clip */
.r2to1 .r-chip { top: auto; bottom: -6px; }
.r-pay-lbl {
  position: absolute; bottom: -22px; left: 0; right: 0;
  font-size: 0.75rem; font-weight: 700; color: var(--gold-hi);
  text-align: center; line-height: 1; pointer-events: none;
}
/* In-tile corner flame for a boosted mid-grid pocket (e.g. Sweet Sixteen on 16), where the
   below-tile .r-pay-lbl would collide with the dozens row beneath the number grid. */
.r-fire-badge {
  position: absolute; top: -3px; right: -2px;
  font-size: 0.62rem; line-height: 1; pointer-events: none;
  filter: drop-shadow(0 1px 1px rgba(0,0,0,0.7));
}

.wheel-outer { display: flex; flex-direction: column; align-items: center; margin: 6px 0 14px; }
.wheel-pointer { width: 0; height: 0; border-left: 12px solid transparent; border-right: 12px solid transparent; border-top: 22px solid var(--gold); margin-bottom: -3px; position: relative; z-index: 2; filter: drop-shadow(0 3px 4px rgba(0,0,0,0.5)); }
#rwheel { display: block; border-radius: 50%; box-shadow: 0 0 0 2px var(--gold-hi), 0 0 0 5px var(--gold-lo), 0 0 40px rgba(0,0,0,0.7); }
.r-res-num {
  width: 96px; height: 96px; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  font-family: var(--btn-f); font-size: 2.4rem;
  border: 2px solid var(--ink);
  box-shadow: inset 0 0 0 2px rgba(255,255,255,0.25), 0 4px 0 rgba(0,0,0,0.3), 0 8px 16px rgba(0,0,0,0.4);
  animation: popIn 0.5s cubic-bezier(.34,1.56,.64,1) both;
}
@keyframes popIn { from { transform: scale(.5) rotate(-20deg); opacity: 0; } to { transform: scale(1) rotate(0); opacity: 1; } }

/* ── Results screen ─────────────────────────────────────── */
/* The daily-modifier banner's pale-gold gradient and ink border, but pressed into the panel
   via the canonical inlay bevel (shadow top-left, highlight bottom-right, same as .bet-amt)
   so it reads as a recessed plaque, not a raised button/overlay. */
.share-box {
  background: linear-gradient(180deg, #f5eabc 0%, #ead89a 100%); color: var(--ink);
  border: 1px solid var(--ink);
  box-shadow: inset 1px 1px 0 var(--shadow), inset -1px -1px 0 var(--highlight);
  padding: 12px 14px;
  font-family: var(--btn-f); font-size: 1.4rem;
  line-height: 1.6; text-align: center;
  white-space: pre-line; letter-spacing: 0.02em;
}
/* Share box + its Copy & Share button travel as one unit: the cluster shrinks to the share
   text's longest line and centers, and both children stretch to fill it, so the button is
   always locked to the share box's width. Desktop overrides the cluster width to a centred
   half-window card (see the results desktop block). */
.share-cluster {
  display: flex; flex-direction: column; gap: 8px;
  width: fit-content; max-width: 100%;
  margin-left: auto; margin-right: auto;
}


/* ── Score distribution chart ───────────────────────────── */
/* Daily-streak line on the results screen: its own prominent gold line under the chip
   total (there's no "chips" label; the big number reads as chips on its own). */
.results-streak {
  color: var(--gold-hi); font-weight: 700;
  font-size: 1.5rem; line-height: 1.1; letter-spacing: 0.04em;
  margin: 5px 0 9px; white-space: nowrap;
  text-shadow: 1px 1px 0 rgba(0,0,0,0.4);
}
/* Tier + chip total + streak grow into one block that floats centered in the gap
   between the modifier banner and the results box: flex:1 absorbs the panel's
   vertical slack here, so the manifest/chart/share settle below as a group. When
   the panel is tight (360×780, short desktop) the slack is ~0 and it just stacks. */
.results-hero {
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  flex: 1 1 auto; min-height: 0;
}
.results-tier { font-size: 1.15rem; }

.dist-bars {
  display: flex; align-items: flex-end; gap: 4px;
  height: 50px; padding: 0 4px;
  border-bottom: 1px solid var(--ink);
  position: relative; margin: 18px 4px 24px;
}
.dist-bar {
  flex: 1; background: var(--gold); border: 1px solid var(--ink);
  position: relative;
}
.dist-bar.you {
  background: var(--gold-hi);
}
.dist-count {
  position: absolute; top: -16px; left: 50%; transform: translateX(-50%);
  font-size: 0.9rem; color: var(--gold-hi); white-space: nowrap;
}
.dist-lbl {
  position: absolute; bottom: -16px; left: 50%; transform: translateX(-50%);
  font-size: 0.9rem; color: var(--gold); white-space: nowrap;
}
.dist-you-line {
  position: absolute; top: -20px; bottom: 0; width: 0;
  border-left: 2px dashed var(--ink); pointer-events: none; z-index: 1;
  margin-left: -1px;
}
.dist-you-lbl {
  position: absolute; top: 0;
  font-size: 0.85rem; color: var(--ink); white-space: nowrap;
}

/* ── Toast ──────────────────────────────────────────────── */
#toast {
  position: fixed; top: 18px; left: 50%;
  transform: translateX(-50%) translateY(calc(-100% - 20px));
  background: var(--gold); color: var(--ink);
  border: 1px solid var(--ink);
  box-shadow: inset 1.5px 1.5px 0 var(--gold-hi), inset -2px -2px 0 var(--gold-lo), 0 6px 14px rgba(0,0,0,0.4);
  padding: 10px 22px; font-family: var(--btn-f); font-size: 1.5rem; font-weight: 700;
  z-index: 200; transition: transform 0.3s cubic-bezier(.34,1.56,.64,1);
}
#toast.show { transform: translateX(-50%) translateY(0); }

/* ── Hold-card toggle (video poker) ─────────────────────── */
.hold-wrap { display: flex; flex-direction: column; align-items: center; gap: 5px; cursor: pointer; }
.hold-tag { font-size: 1.1rem; font-weight: 700; letter-spacing: 0.08em; height: 14px; color: var(--gold-hi); }

/* ── Info modal ─────────────────────────────────────────── */
.info-modal {
  position: fixed; inset: 0; z-index: 500;
  background: rgba(0,0,0,0.7);
  display: flex; align-items: center; justify-content: center;
  padding: 18px; animation: fadein .2s ease both;
}
.info-box {
  background: var(--panel); color: var(--ink);
  border: 1px solid var(--ink);
  box-shadow: inset 1px 1px 0 var(--highlight), inset -2px -2px 0 var(--shadow), 0 16px 40px rgba(0,0,0,0.6);
  max-width: 560px; width: 100%; max-height: 80vh; overflow-y: auto;
  border-radius: 8px 8px 0 0;   /* rounded top corners like the main .window */
}
/* Titled info modal (help windows, modifier popups, About): pin the WinXP blue bar at the top and
   scroll the body beneath it. overflow:hidden clips the bar to the box's rounded top corners. */
.info-box.info-box-titled { padding: 0; display: flex; flex-direction: column; overflow: hidden; }
.info-box-titled > .title-bar { border-radius: 7px 7px 0 0; flex-shrink: 0; }
.info-box-titled > .info-content { flex: 1; min-height: 0; overflow-y: auto; padding: 18px; }

/* Desktop floating windows: non-blocking. The full-screen overlay goes transparent and click-through
   so the game stays clickable + draggable underneath; only the .info-box itself catches pointer
   events. Multiple coexist (one per type), each raised via an inline z-index on focus. */
.info-modal.float-win { background: transparent; pointer-events: none; }
.info-modal.float-win > .info-box { pointer-events: auto; }

/* ── Player Profile window (File → Player Profile) ───────── */
.pf-tier { text-align: center; font-family: var(--btn-f); font-size: 1.6rem; color: var(--gold); margin-bottom: 10px; }
.pf-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 6px; margin-bottom: 12px; }
.pf-stat {
  background: var(--cream); border: 1px solid var(--ink);
  box-shadow: var(--raised-sm);
  padding: 7px 4px; text-align: center;
}
.pf-stat b { display: block; font-family: var(--btn-f); font-size: 1.6rem; line-height: 1.1; color: var(--ink); }
.pf-stat b.pf-pos { color: var(--win); }
.pf-stat b.pf-neg { color: var(--lose); }
.pf-stat span { font-size: 0.72rem; color: var(--shadow); text-transform: uppercase; letter-spacing: 0.08em; }
.pf-sec { font-size: 0.78rem; color: var(--shadow); text-transform: uppercase; letter-spacing: 0.1em; margin: 10px 0 5px; }
.pf-cal { display: grid; grid-template-columns: auto repeat(7, 1fr); gap: 4px 5px; align-items: center; }
.pf-cal-wk { font-size: 0.62rem; color: var(--shadow); text-align: right; padding-right: 3px; white-space: nowrap; }
.pf-cal i, .pf-legend i { display: block; aspect-ratio: 1; border-radius: 2px; border: 1px solid rgba(0,0,0,0.18); }
.pf-c-profit { background: var(--win); }
.pf-c-loss   { background: #e08878; }  /* lighter red: finished down but not busted */
.pf-c-bust   { background: var(--lose); }
.pf-c-miss   { background: rgba(0,0,0,0.10); }
.pf-legend { display: flex; gap: 12px; justify-content: center; margin-top: 6px; font-size: 0.75rem; color: var(--shadow); }
.pf-legend span { display: flex; align-items: center; gap: 4px; }
.pf-legend i { width: 9px; height: 9px; aspect-ratio: auto; }
.pf-badges { display: grid; grid-template-columns: repeat(3, 1fr); gap: 6px; }
.pf-badge {
  background: var(--cream); border: 1px solid var(--ink);
  box-shadow: var(--raised-sm);
  padding: 7px 2px; text-align: center; font-size: 0.78rem; color: var(--ink);
  display: flex; flex-direction: column; align-items: center; gap: 2px;
}
.pf-badge-ic { font-size: 1.25rem; line-height: 1; }
.pf-badge.pf-locked { opacity: 0.45; }
.pf-badge-hint { font-family: var(--btn-f); font-size: 0.85rem; color: var(--shadow); }
/* Mobile: the longest tier titles (Down the Hole · NN days played) must stay on one line
   in the 360px modal, so the tier line steps down a size. */
@media (max-width: 480px) {
  .pf-tier { font-size: 1.25rem; }
}

.feedback-textarea {
  width: 100%; min-height: 110px; resize: vertical;
  background: var(--cream); color: var(--ink);
  border: 1px solid var(--ink);
  box-shadow: inset 1px 1px 0 var(--shadow), inset -1px -1px 0 var(--highlight);
  padding: 6px 8px;
  font-family: var(--btn-f); font-size: 1rem; line-height: 1.4;
  box-sizing: border-box;
}
.feedback-textarea:focus { outline: 2px solid #316AC5; outline-offset: -1px; }

/* ── Dropdown menus (WinXP-style) ──────────────────────── */
.dropdown {
  position: fixed; z-index: 400;
  background: var(--panel);
  border: 1px solid var(--ink);
  box-shadow: var(--raised-sm), 3px 3px 0 rgba(0,0,0,0.5);
  min-width: 190px; padding: 2px 0;
  font-family: var(--btn-f);
}
.dd-item {
  display: flex; align-items: center;
  padding: 3px 18px 3px 22px; gap: 8px;
  font-size: 1.05rem; color: var(--ink);
  cursor: pointer; white-space: nowrap; user-select: none;
}
.dd-item:hover:not(.dd-disabled) { background: #316AC5; color: #fff; }
.dd-item:hover:not(.dd-disabled) .dd-key { color: rgba(255,255,255,0.7); }
.dd-disabled { color: var(--shadow); cursor: default; }
.dd-key { margin-left: auto; padding-left: 16px; font-size: 0.8rem; color: var(--shadow); }
.dd-sep { height: 0; margin: 3px 2px; border-top: 1px solid var(--shadow); border-bottom: 1px solid var(--highlight); }
.dd-submenu { z-index: 401; }
.dd-item.dd-active { background: var(--gold-lo); color: var(--cream); }
.dd-item.dd-active .dd-key { color: rgba(255,255,255,0.6); }
.dd-archive-list { max-height: 260px; overflow-y: auto; }
.dd-inline-sub { border-left: 1px solid var(--shadow); margin: 1px 0 1px 14px; }
.dd-inline-sub.dd-level-2 { margin-left: 28px; }
.dd-game-lbl { padding: 4px 22px 1px; font-size: .8rem; color: var(--shadow); letter-spacing: .08em; text-transform: uppercase; }
.dd-game-row { display: flex; gap: 4px; padding: 2px 8px 4px 22px; flex-wrap: wrap; }
.dd-game-btn { font-family: var(--btn-f); font-size: .95rem; padding: 1px 8px; border: 1px solid var(--shadow); background: transparent; color: var(--ink); cursor: pointer; }
.dd-game-btn.active { background: var(--gold); border-color: var(--gold-lo); }
.dd-game-btn:hover:not(.active) { background: var(--highlight); }

/* ── XP Notification Balloon ─────────────────────────────── */
#xp-balloon {
  position: fixed; z-index: 300;
  width: 272px; display: none;
  /* drop-shadow wraps the body + tail together for a unified shadow */
  filter: drop-shadow(2px 4px 10px rgba(0,0,0,0.55));
}
#xp-balloon.xpb-visible {
  display: block; pointer-events: auto;
  animation: xpb-in 0.28s cubic-bezier(.34,1.56,.64,1) both;
}
#xp-balloon.xpb-hiding {
  display: block; pointer-events: none;
  animation: xpb-out 0.22s ease forwards;
}
.xpb-inner {
  background: #ffffe1;
  border: 1px solid #b9a96a;
  border-radius: 6px;
  overflow: hidden; position: relative; z-index: 1;
}
/* Diamond tail below the balloon: sits in front so its fill hides the body's
   bottom border across the base, leaving a clean point with no horizontal line. */
.xpb-tail {
  position: absolute;
  bottom: -8px; right: 30px;
  width: 16px; height: 16px;
  background: #ffffe1;
  border-right: 1px solid #b9a96a;
  border-bottom: 1px solid #b9a96a;
  transform: rotate(45deg);
  z-index: 2;
}
.xpb-header {
  display: flex; align-items: center; gap: 7px;
  padding: 5px 6px 5px 8px;
}
.xpb-icon {
  width: 16px; height: 16px; flex-shrink: 0;
  border-radius: 50%;
  background: radial-gradient(circle at 35% 30%, #5fa0f0, #0848b8);
  border: 1.5px solid #0838a0;
  display: flex; align-items: center; justify-content: center;
  color: #fff; font-style: italic; font-weight: 900;
  font-size: 11px; line-height: 1;
  font-family: 'Georgia', 'Times New Roman', serif;
  text-shadow: 0 1px 2px rgba(0,0,0,0.55);
}
.xpb-title {
  flex: 1;
  font-family: 'Tahoma', 'Segoe UI', sans-serif;
  font-size: 12px; font-weight: 700;
  color: #000; line-height: 1.3; letter-spacing: 0;
}
.xpb-close {
  background: none; border: none; cursor: pointer;
  width: 16px; height: 16px; flex-shrink: 0;
  color: #444; font-size: 13px; line-height: 1;
  display: flex; align-items: center; justify-content: center;
  border-radius: 2px; padding: 0;
  font-family: 'Tahoma', sans-serif;
}
.xpb-close:hover { background: rgba(196,48,48,0.14); color: #c83030; }
.xpb-body {
  padding: 2px 10px 12px;
  font-family: 'Tahoma', 'Segoe UI', sans-serif;
  font-size: 12px; color: #000; line-height: 1.45;
}
@keyframes xpb-in {
  from { opacity: 0; transform: translateY(10px) scale(0.96); }
  to   { opacity: 1; transform: translateY(0) scale(1); }
}
@keyframes xpb-out {
  from { opacity: 1; transform: translateY(0); }
  to   { opacity: 0; transform: translateY(8px); }
}

/* ── Desktop-only: draggable window cursor ──────────────── */
@media (hover: hover) and (min-width: 481px) {
  .window { overflow: hidden; }
  .title-bar { cursor: move; }
  .title-bar .tb-btn { cursor: pointer; }
}

/* ── The Ladder ─────────────────────────────────────────── */
/* Fixed skeleton: every zone keeps a constant min-height so phase changes
   never move elements: only contents swap. The action zone is a flex column
   so the call row and the big button share one width: the big button spans
   exactly the combined span of the two call buttons above it. */
.lad-head  { min-height: 38px; }
/* Pot/stake bar: the project's sunken-cream readout (matches BJ/UTH stack boxes). */
/* Readout: a flex row of one or more sunken boxes. Most phases use a single box;
   the climb phase splits Pot / Next rung into two side-by-side boxes (see ladder.js). */
.lad-read  { height: 56px; margin: 6px auto 8px; width: 94%; box-sizing: border-box;
             display: flex; gap: 8px; justify-content: center; }
/* Two equal, FIXED-size boxes (always 50/50, fixed height) so they never resize or
   shift between phases regardless of the text. Long values wrap inside the box
   (label over value) rather than changing its footprint. */
.lad-read-box { flex: 1 1 0; min-width: 0; font-size: 1.25rem; color: var(--ink); font-family: var(--btn-f);
             background: var(--panel2); border: 1px solid var(--ink);
             box-shadow: inset 1px 1px 0 var(--shadow), inset -1px -1px 0 var(--highlight);
             padding: 4px 10px; box-sizing: border-box; line-height: 1.15; text-align: center;
             display: flex; align-items: center; justify-content: center; }
/* flex:1 makes the card pair the slack absorber (cards stay vertically centered in
   whatever height is spare), so leftover panel height never pools below the buttons. */
.lad-cards { min-height: 124px; flex: 1 0 auto; display: flex; justify-content: center; gap: 16px;
             align-items: center; }
.lad-cards .card.md { width: 88px; height: 124px; }
.lad-cards .card.md .csuit { font-size: 3.2rem; }
.lad-cards .card.md .ct-r  { font-size: 1.25rem; }
.lad-cards .card.md .ct-s  { font-size: 1rem; }
.lad-msg   { min-height: 32px; font-size: 1.05rem; color: var(--cream); opacity: .9; }
/* Action zone: fixed height, contents bottom-anchored so the primary button
   (Free Entry / Cash Out / See Results) sits at the SAME Y in every phase and
   never jumps; Higher/Lower then lines up with the bet row above it. margin-top:auto
   pins the zone to the panel bottom (same control-position anchor as the other games)
   whenever .lad-cards is already at its minimum. */
/* gap matches the .panel column gap, so the chips → bet row → button spacing inside the
   zone lines up with the other games' bet screens, where those are direct panel children. */
.lad-act   { min-height: 190px; margin-top: auto; display: flex; flex-direction: column; gap: 10px; }
.lad-act > *:first-child { margin-top: auto; }
.lad-hl { font-family: var(--btn-f); font-size: 1.7rem; letter-spacing: .06em; color: var(--gold-hi); }
.lad-hl-bad  { color: #ff8a80; }
.lad-hl-good { color: #9be79b; }
.lad-strip { display: flex; justify-content: center; gap: 4px; margin: 8px 0; }
/* Rung tiles styled like the hand-progress pills (cream panel, gold "current"). */
.lad-rung  { flex: 0 1 44px; padding: 5px 0 4px; font-size: .95rem; text-align: center;
             font-family: var(--btn-f); background: var(--panel); color: var(--shadow);
             border: 1px solid var(--ink); }
.lad-rung.done  { background: var(--gold); color: var(--ink); font-weight: 700;
                  box-shadow: inset 2px 2px 0 var(--gold-lo), inset -1px -1px 0 var(--gold-hi); }
.lad-rung.next  { color: var(--gold-lo); font-weight: 700; border-color: var(--gold);
                  box-shadow: var(--raised-sm); }
.lad-rung.crash { background: var(--lose); color: #fff; font-weight: 700;
                  box-shadow: inset 1px 1px 0 var(--lose-hi), inset -1px -1px 0 #7a0000; }
.lad-gold { color: var(--gold-lo); }
.lad-bad  { color: var(--lose-hi); }
.lad-good { color: var(--win-hi); }
.lad-read .lad-gold { color: var(--gold-lo); }
.lad-read .lad-bad  { color: var(--lose); }
.lad-read .lad-good { color: var(--win-lo); }
.lad-call-row { display: flex; gap: 10px; margin-bottom: 8px; }
.lad-call { flex: 1; font-size: 1.15rem; }
.lad-btn-big { width: 100%; margin-top: 4px; font-size: 1.15rem; }
.lad-chips-locked { opacity: .45; pointer-events: none; }

/* Desktop: the bonus round shows little content, so fill the panel slack:
   bigger cards, ladder tiles, readout and buttons, with more breathing room. */
@media (min-width: 1024px) {
  .lad-head  { min-height: 52px; }
  .lad-hl    { font-size: 2.5rem; }
  .lad-strip { gap: 7px; margin: 16px 0; }
  .lad-rung  { flex-basis: 66px; font-size: 1.3rem; padding: 11px 0 9px; }
  .lad-read  { height: 72px; margin: 14px auto 16px; gap: 12px; }
  .lad-read-box { font-size: 1.6rem; padding: 6px 14px; }
  .lad-cards { min-height: 184px; gap: 32px; }
  .lad-cards .card.md { width: 124px; height: 174px; }
  .lad-cards .card.md .csuit { font-size: 4.4rem; }
  .lad-cards .card.md .ct-r  { font-size: 1.55rem; }
  .lad-cards .card.md .ct-s  { font-size: 1.2rem; }
  .lad-msg   { min-height: 44px; font-size: 1.4rem; }
  .lad-act   { min-height: 210px; }
  .lad-call-row { gap: 18px; margin-bottom: 16px; }
  .lad-call, .lad-btn-big { font-size: 1.6rem; padding: 18px 0; }
}

/* Short desktop (1280×800 / 1440×900): the full desktop sizes above overflow the fixed
   window and push the Deal/Cash Out button below the fold, so step every zone partway
   back toward the mobile scale. */
@media (min-width: 1024px) and (max-height: 959px) {
  .lad-head  { min-height: 40px; }
  .lad-hl    { font-size: 1.9rem; }
  .lad-strip { gap: 5px; margin: 8px 0; }
  .lad-rung  { flex-basis: 52px; font-size: 1.05rem; padding: 7px 0 6px; }
  .lad-read  { height: 60px; margin: 8px auto 10px; }
  .lad-read-box { font-size: 1.35rem; }
  .lad-cards { min-height: 148px; gap: 24px; }
  .lad-cards .card.md { width: 106px; height: 148px; }
  .lad-cards .card.md .csuit { font-size: 3.8rem; }
  .lad-cards .card.md .ct-r  { font-size: 1.3rem; }
  .lad-cards .card.md .ct-s  { font-size: 1rem; }
  .lad-msg   { min-height: 36px; font-size: 1.15rem; }
  .lad-act   { min-height: 170px; }
  .lad-call-row { gap: 12px; margin-bottom: 10px; }
  .lad-call, .lad-btn-big { font-size: 1.25rem; padding: 10px 0; }
}

/* ── Mobile / small screen ──────────────────────────────── */
@media (max-width: 480px) {
  body { font-size: 24px; }
  /* On phones the box fills the control width (so it cleanly takes its own row and Clear/All In wrap
     below it); box == ctrl width here, equal rather than the box being narrower as on desktop. */
  :root { --btn-h: 40px; --btn-fs: 1.1rem; --btn-px: 8px; --bet-box-w: 316px; --ctrl-w: 316px; --act-btn-w: var(--bet-box-w); }
  /* Reduce outer chrome. The 30px bottom padding was the biggest offender */
  /* Cap the shell at the viewport so it can never grow past it (the XP window
     must stay put). Content that would exceed it is handled by the inner
     overflow:hidden + the one designated scroll region (#r-bets-zone), never by
     the window expanding. All non-roulette screens already fit within 100svh. */
  /* 100dvh (not svh) tracks the *currently visible* viewport, so the window never
     hides under Safari's floating bottom toolbar; the safe-area padding keeps the
     title bar clear of the Dynamic Island/status bar and the bottom clear of the
     home indicator. Requires viewport-fit=cover (set in index.html). */
  /* Vertical scrolling is the fallback when a phone is smaller than a screen is
     designed for; horizontal scrolling is never allowed. */
  html, body { overflow-x: hidden; }
  body { min-height: 100vh; min-height: 100svh; min-height: 100dvh; }
  .app {
    padding: calc(5px + var(--sa-t)) calc(5px + var(--sa-r)) calc(5px + var(--sa-b)) calc(5px + var(--sa-l));
    /* Fill the visible viewport (dvh excludes Safari's toolbar; vh/svh are fallbacks for
       pre-iOS-15.4). NO max-height: if a screen's content is taller than the phone, the
       app grows past the viewport and the page scrolls vertically so buttons stay reachable,
       never clipped. On phones the content fits, this just fills the screen. */
    min-height: 100vh; min-height: 100svh; min-height: 100dvh;
    display: flex; flex-direction: column;
  }
  /* flex:1 0 auto + no overflow clip = fill the app when content is short, grow with the
     content (scrolling into view) when it's tall. Never clips a button off-screen. */
  .window { flex: 1 0 auto; min-height: 0; }
  .panel { flex: 1 0 auto; }
  .panel { padding: 8px; min-height: 0; gap: 6px; }
  .divider { margin: 2px 0; }
  .title-bar { font-size: 18px; }
  .menu-bar { padding: 0 6px 0 0; font-size: 0.9rem; gap: 0; }
  .menu-bar .mb-item { padding: 2px 6px; }
  .chip-badge { font-size: 1.15rem; padding: 0 6px; }
  .mod-banner { padding: 6px 10px; gap: 2px; margin-bottom: 6px; flex-direction: column; align-items: stretch; }
  .mod-banner-slim .mod-banner-r { display: none; }
  .mod-banner-l { display: flex; flex-direction: row; align-items: baseline; gap: 6px; white-space: nowrap; overflow: hidden; }
  .mod-banner-label { font-size: 0.85rem; letter-spacing: 0.08em; flex-shrink: 0; }
  .mod-banner-title { font-size: 1.25rem; overflow: hidden; text-overflow: ellipsis; min-width: 0; }
  .mod-banner-r { font-size: 1.05rem; text-align: left; }
  .tb-detail, .btn-detail, .dot-detail { display: none; }
  .tb-prefix { display: none; } /* drop "Gambdle" prefix on mobile; the long game name then fits */
  .sb-prefix, .sb-suffix { display: none; }
  /* Section labels */
  .sec { font-size: 1.2rem; margin-bottom: 3px; }
  .uth-result-panel .sec { font-size: 0.8rem; margin-bottom: 2px; }
  /* Progress dots */
  .dots-row { margin: 0; gap: 5px; }
  .hand-dot { padding: 2px 6px; font-size: 1.2rem; }
  /* Info rows */
  .ik { font-size: 1.2rem; }
  .iv { font-size: 1.15rem; }
  .irow { padding: 4px 10px; }
  /* Buttons */
  .btn-gold { padding: 10px 12px; font-size: 1.2rem; }
  .btn-gold.btn-lg { padding: 14px 16px; font-size: 1.5rem; }
  /* Control-position parity (.claude/LAYOUT.md): match the bet screen's #db offset from the panel bottom
     (its 3px margin-bottom) so the box + button land at the same Y on every play/result screen. */
  .game-controls { margin-bottom: 3px; }
  /* Hand value under cards */
  .hand-val { font-size: 2rem; margin-top: 4px; }
  /* Intro logo */
  .logo { font-size: 4rem; }
  .logo-sub { font-size: 1.4rem; margin-top: 4px; }
  /* Cards: modestly smaller to reclaim vertical space */
  .card.lg { width: 80px; height: 114px; }
  .card.md { width: 72px; height: 102px; }
  .card.sm { width: 58px; height: 82px; }
  .card.lg .csuit { font-size: 2.2rem; }
  .card.md .csuit { font-size: 1.85rem; }
  .card.sm .csuit { font-size: 1.5rem; }
  /* Live play board (UTH): mobile had no per-board glyph tuning (desktop tunes it in
     its own media blocks), so the center suit ran oversized for the sm community cards.
     With the corner indices now pulled tight to the edge (.card.sm above), 1.4rem sits
     comfortably clear of them while staying prominent. */
  .panel:has(#uth-actions-ui) .card.sm .csuit { font-size: 1.4rem; }
  /* Roulette board: reduce row heights; horizontal scroll is acceptable */
  .rboard, .rboard-sub { grid-template-columns: 22px repeat(12, 1fr) 32px; }
  .r2to1, .rout { font-size: 0.95rem; }
  .rboard { grid-template-rows: 23px 23px 23px; }
  .rboard-sub { grid-auto-rows: 19px; }
  .rn { font-size: 0.9rem; }
  /* A full bet list must fit a window that can't grow, with the board fully
     visible and nothing scrolling. Keep the inter-element margins and the
     placed-bets rows tight so 5 bets still fit at 375×812. */
  .panel:has(#r-bets-zone) > #db { margin: 4px auto !important; }
  /* Match the mobile chip cluster (40px chips → ~316px). (.game-controls keeps its --bet-box-w cap.) */
  .panel:has(#r-bets-zone) > #db,
  .panel:has(.bj-bet-table) > #db,
  .panel:has(#uth-summary) > #db { max-width: 316px; }
  .panel:has(#r-bets-zone) #r-bets-zone { max-width: 316px; min-height: 52px; }
  .panel:has(#r-bets-zone) #r-sel-box { max-width: 316px; font-size: 0.85rem; padding: 2px 8px; }
  .panel:has(#r-bets-zone) .r-bet-center { gap: 3px; }
  .panel:has(#r-bets-zone) { gap: 4px; }
  /* Roulette's chip selector now matches BJ/UTH: full-size chips at the same vertical spot: by letting
     the bets-zone (flex + scrollable) give up the height. The roulette panel's tighter `gap:4px` shaves
     2px off the chip->bet-row gap vs BJ/UTH, so add it back onto the chip-row margin to land the chips
     at the identical Y (verified by the chip-selector-parity test). */
  .panel:has(#r-bets-zone) .chip-row { margin-bottom: 16px; }
  .panel:has(#r-bets-zone) > .divider { margin: 2px 0; }
  .panel:has(#r-bets-zone) .rbz-title { font-size: 1.15rem; padding: 0 0 3px; }
  .panel:has(#r-bets-zone) .rbz-item { line-height: 1.05; }
  .panel:has(#r-bets-zone) .rbz-win { font-size: 0.82rem; }
  /* Spin-screen bets box: same mobile cap + font-shrink as the bet screen's #r-bets-zone, so the
     full bet set fits 360 without horizontal scroll. */
  .panel:has(#rwheel) .r-bets-zone { max-width: 316px; }
  .panel:has(#rwheel) .rbz-title { font-size: 1.15rem; padding: 0 0 3px; }
  .panel:has(#rwheel) .rbz-item { line-height: 1.05; }
  .panel:has(#rwheel) .rbz-win { font-size: 0.82rem; }
  .panel:has(#rwheel) .rbz-lbl { font-size: 1rem; }
  /* Single-bet mod on mobile: enlarge, but keep the selection line short enough not to overflow 360. */
  .panel:has(#r-bets-zone) .r-one .r-sel-box { font-size: 1rem; }
  .panel:has(#r-bets-zone) .r-one .rbz-title { font-size: 1.35rem; }
  .panel:has(#r-bets-zone) .r-one .rbz-lbl { font-size: 1.45rem; }
  .panel:has(#r-bets-zone) .r-one .rbz-win { font-size: 1.05rem; }
  .panel:has(#r-bets-zone) .r-one .rbz-open { font-size: 1.3rem; }
  /* Mobile can't grow the window, so the box would flex-grow to the full 190px multi-bet reservation
     even on a 1- or 3-bet day, leaving its handful of slots stranded at the top. Cap it just above the
     filled-content height (kept above the content so it stays slack-bound and never resizes as bets are
     placed), then center the sel-box + box group in the reclaimed felt. */
  .panel:has(#r-bets-zone) .r-three #r-bets-zone { max-height: 132px; }
  .panel:has(#r-bets-zone) .r-one #r-bets-zone { max-height: 84px; }
  .panel:has(#r-bets-zone) .r-three,
  .panel:has(#r-bets-zone) .r-one { justify-content: center; }
  .panel:has(#r-bets-zone) .rbz-lbl { font-size: 1rem; }
  .panel:has(#r-bets-zone) > .divider { margin: 1px 0; }
  .r-board-wrap { padding-bottom: 1px; }
  .r-board-wrap { margin: 0 -8px; padding: 0 8px 4px; scrollbar-width: none; -ms-overflow-style: none; }
  .r-board-wrap::-webkit-scrollbar { display: none; }
  /* Chip selector. Bigger chips than before (40→44px): the inline bet-row below frees the row the bet
     box used to occupy on its own, and 7×44 + 6×5px gaps = 338px still clears the 360px floor's ~344px
     panel content width on a single nowrap row (guarded by the "chip selector stays on a single row"
     tests). */
  .chip-row { flex-wrap: nowrap; gap: 5px; }
  .chbtn { width: 44px; height: 44px; }
  .ch-1000 > span { font-size: 0.95rem; }
  /* Bet row: inline on phones too: [✕ Clear][box][All In] on ONE row, matching desktop. The box
     flex-shrinks to fill whatever the natural-width buttons leave (the same shrink roulette's box already
     uses on desktop to pack its 4 items, styles.css:2145). nowrap keeps it on one line; the box gives up
     width before anything wraps. This frees the row the box used to occupy on its own: spent on larger
     chips above. The box is no longer pixel-width-identical to the play/result inlay box at phone width;
     that width parity is now a desktop guarantee (it already was for roulette, at every size). */
  .bet-row { gap: 6px; flex-wrap: nowrap; max-width: none; }
  /* No `order` overrides: source order is Clear, box, (roulette) Place Bet, All In: so it reads
     [✕ Clear][box][Place Bet][All In] left-to-right, exactly like the desktop bet-row. */
  .bet-row > .bet-amt { flex: 1 1 auto; width: auto; min-width: 0; }
  .bet-row > .ch-clear, .bet-row > .ch-allin { flex: 0 0 auto; }
  /* Roulette's Place Bet: natural width (may shrink), so the box keeps the rest of the row. */
  .bet-row > #pb-add { flex: 0 1 auto; width: auto; min-width: 0; }
  /* BJ bet table: compact slots on mobile */
  .bj-bet-table { gap: 4px; padding: 2px 0; }
  .card-slot { width: 44px; height: 62px; border-width: 1.5px; }
  .bj-bet-slot-lbl { font-size: 0.78rem; letter-spacing: 0.14em; }
  .felt-rules { font-size: 0.72rem; letter-spacing: 0.12em; padding: 2px 0; line-height: 1.3; }
  /* Intro game manifest */
  .gm-row { grid-template-columns: 22px 1fr; gap: 8px; padding: 5px 10px; }
  .rnd-ic { font-size: 1.1rem; }
  .rnd-nm { font-size: 1.3rem; }
  .rnd-dc { font-size: 0.85rem; white-space: nowrap; margin-top: 1px; }
  /* Action buttons */
  .act-btns { gap: 6px; }
  .act-btn { font-size: 1.1rem; padding: 12px 5px; white-space: normal; }
  /* Results screen: even vertical rhythm. The mod banner stays pinned to the top,
     so spare height collects at the bottom; use some of it to fill the page (larger
     hero number, consistent section gaps) while staying clear of the status bar even
     after the async ~110px distribution chart renders. */
  .panel.results-panel { gap: 8px; }
  .big-chips { font-size: 3.1rem !important; line-height: 1; }
  .results-streak { font-size: 1.35rem; margin: 0; }
  .res-row { padding: 2px 10px !important; }
  .results-panel .game-manifest { margin-bottom: 2px !important; }
  /* Center the "Score Distribution" title in the gap between the game results box (above)
     and the top of the chart (the "You" marker / count labels sit ~20px above the bars).
     Split the title's top/bottom margins so the gap above ≈ the gap below to that topmost
     graph element; keeping (margin-top + margin-bottom) constant per tier leaves the chart
     in place (no fit change), just repositions the title. Tuned per height tier below. */
  .results-panel #dist-title { margin-top: 2px !important; margin-bottom: 15px !important; }
  .dist-bars { height: 50px; margin-top: 8px; margin-bottom: 8px; }
  .share-box { padding: 5px 14px; font-size: 0.9rem; line-height: 1.18; }
  /* BJ split result */
  .bj-split-result .result-hl { font-size: 1.55rem; margin-bottom: 0; }
  .bj-split-result .result-sub { font-size: 1.08rem; margin-bottom: 0; }
  .bj-split-result:not(.sr-4) .result-hl { font-size: 2.4rem; }
  .bj-split-result:not(.sr-4) .result-sub { font-size: 1.6rem; }
  .bj-sr-dealer { margin-bottom: 0; }
  .bj-sr-dealer .hand-val { font-size: 1.1rem !important; }
  .bj-sr-dealer .card.sm { width: 40px; height: 56px; }
  .bj-sr-hands { margin-bottom: 0 !important; gap: 6px !important; }
  /* Split hands */
  .bj-split-lbl { font-size: 0.86rem; white-space: nowrap; }
  .bj-split-val { font-size: 2rem; }
  .bj-active-lbl { font-size: 1.5rem; }
  .bj-split-active .card.lg { width: 76px; height: 106px; }
  .bj-split-active .card.lg .csuit { font-size: 2rem; }
  .bj-split-active .card.lg .ct-r { font-size: 1.35rem; }
  .bj-split-active .card.lg .ct-s { font-size: 1.12rem; }
  .bj-split-active .card.lg .ct-r[data-r="10"] { font-size: 1.1rem !important; }
  .bj-split-active .hand-val { font-size: 2rem; }
  /* Control-position parity: the active-hand section absorbs the spare height (flex:1) and the control
     cluster sits flush at the panel bottom, so the box + buttons land at the same Y as every other screen
     (the enlarged active cards fill the freed felt). */
  .panel:has(.bj-split-active) .bj-split-active { flex: 1 1 auto !important; min-height: 0; }
  .panel:has(.bj-split-active) > div:last-child { margin-top: 0 !important; }
  /* Tighten the dividers on the dense split-play screen so the bet inlay box + buttons fit under a full
     mod banner. The control-cluster gap stays at the standard 10px (the flex:1 active hand absorbs the
     slack) so the box lands at the same Y as every other screen. */
  .panel:has(.bj-split-active) .divider { margin: 2px 0; }
  /* UTH */
  .uth-summary { font-size: 0.9rem; }
  /* UTH blind pay table */
  .pname { font-size: 1.1rem; }
  .ppay  { font-size: 1.0rem; }
  /* UTH result screen */
  .uth-result-panel .result-hl { font-size: 2rem; margin-bottom: 2px; }
  .uth-result-panel .result-sub { font-size: 1.4rem; margin-bottom: 2px; }
  .uth-cards-col { gap: 4px; margin: 2px 0; }
  .uth-result-panel .card.md { width: 44px; height: 62px; }
  .uth-result-panel .card.md .csuit { font-size: 1.1rem; }
  .uth-result-panel .card.md .ct-r { font-size: 0.82rem; }
  .uth-result-panel .card.md .ct-s { font-size: 0.68rem; }
  .uth-result-panel .card.md .ct-r[data-r="10"] { font-size: 0.66rem !important; }
  .uth-bets-grid { display:flex; flex-wrap:wrap; justify-content:center; gap:2px 10px; margin-bottom:6px; }
  /* Keep tight screens' cards at original size: they have no room for growth */
  #bj-dealer-section .card.lg { width: 72px; height: 102px; }
  .uth-result-panel .card.sm { width: 44px; height: 62px; }
  /* Even bands centre the dealer in its half, so it needs no extra bottom margin. */
  /* The face-down dealer's value line is a hidden spacer (.hand-val-ghost) reserving the reveal
     height. On the tight mobile play screens, collapse it to reclaim the dealer-card-to-separator gap:
     the slack the bet inlay box + action buttons now need under a full mod banner. The reveal
     re-renders to its own visible-value layout, so nothing is clipped there. */
  #bj-dealer-section .hand-val-ghost { height: 0 !important; min-height: 0 !important; margin: 0 !important; line-height: 0 !important; }
  .bj-split-aside { margin-bottom: 2px; }
  .bj-split-aside .card.sm { width: 43px; height: 60px; }
  .bj-split-aside .card.sm .csuit { font-size: 1.1rem; }
  /* BJ 4-way split result: compact result hand cards */
  .bj-sr-hands .card.sm { width: 39px; height: 55px; }
  /* Match the prominent center glyph of the showdown / dealer cards (~0.55 of card
     height) now that the corner indices are tucked tight: see the tiny-card block above. */
  .bj-sr-hands .card.sm .csuit { font-size: 1.4rem; }
  .bj-sr-hands .hand-val { font-size: 1.1rem !important; }
  .bj-sr-hands .sec { font-size: 0.84rem !important; }
  /* 4-way cards are the smallest (39–40px): shrink the corner rank+suit so the
     now-restored corner suit sits proportionately (like the bigger split cards)
     and stays clear of the center pip. */
  .sr-4 .card.sm .ct-r { font-size: 0.62rem; }
  .sr-4 .card.sm .ct-s { font-size: 0.5rem; }
  /* 2-/3-hand result splits show one row (vs the 4-way 2×2 grid) and have far
     more vertical room: grow their cards to fill it. (.sr-N set in bj.js.) */
  .sr-2 .bj-sr-dealer .card.sm { width: 50px; height: 70px; }
  .sr-2 .bj-sr-hands .card.sm { width: 56px; height: 78px; }
  .sr-2 .card.sm .csuit { font-size: 1.9rem; }
  .sr-2 .hand-val { font-size: 1.45rem !important; }
  .sr-2 .bj-sr-hands .sec { font-size: 1rem !important; }
  .sr-3 .bj-sr-dealer .card.sm { width: 46px; height: 64px; }
  .sr-3 .bj-sr-hands .card.sm { width: 50px; height: 70px; }
  .sr-3 .card.sm .csuit { font-size: 1.7rem; }
  .sr-3 .hand-val { font-size: 1.3rem !important; }
  .sr-3 .bj-sr-hands .sec { font-size: 0.92rem !important; }
  /* UTH showdown: override inline divider margins */
  .uth-result-panel .uth-cards-col .divider { margin: 2px 0 !important; }
  .uth-result-panel .uth-hand-name { font-size: 1.05rem !important; margin-top: 1px !important; }
  /* ── Short-screen button visibility ──────────────────────────────────────────
     Keep bottom-anchored buttons (Next Hand, raises) above the status bar once iOS
     chrome (Dynamic Island + Safari toolbar) shrinks the window. Tested in WebKit
     via npm run test:webkit. */
  /* BJ result (non-split): tighten the inline dealer/player stack + shrink result cards. */
  .panel > div[style*="gap:16px"] { gap: 6px !important; margin-bottom: 4px !important; }
  /* Result screens (BJ result, UTH fold/showdown): distribute leftover felt evenly between
     the headline, the hands stack, and the bottom cluster, instead of pooling it all in one
     band above the Total box. Desktop gets the same treatment in its ≥880-height tier. */
  .uth-result-panel > .result-head,
  .panel:has(> div[style*="gap:16px"]) > .result-head { margin-top: auto; }
  .uth-result-panel > .uth-cards-col { margin-top: auto; margin-bottom: auto; }
  .panel > div[style*="gap:16px"] { margin-top: auto !important; margin-bottom: auto !important; }
  /* …and drop the control cluster's own auto margin here, so the gap above the Total box
     gets ONE share of the slack like every other gap, not two. */
  .uth-result-panel > .game-controls:last-child,
  .panel:has(> div[style*="gap:16px"]) > .game-controls:last-child { margin-top: 0; }
  .panel > div[style*="gap:16px"] .card.sm { width: 48px; height: 68px; }
  .panel > div[style*="gap:16px"] .hand-val { font-size: 1.4rem !important; }
  /* Tiny result/summary cards (UTH showdown, BJ split & multi-hand results, non-split
     BJ result): push the corner indices hard into the corners and tuck the corner suit
     up snug under the rank, freeing the most center space on the smallest cards. The
     `.card` keeps specificity (0,3,0) at/above the global `.card.sm .ctl` so it wins
     here by source order; covers both sm and md cards in these contexts. */
  .uth-result-panel .card .ctl,
  .bj-sr-hands .card .ctl, .bj-sr-dealer .card .ctl,
  .bj-split-aside .card .ctl,
  .panel > div[style*="gap:16px"] .card .ctl { top: 1px; left: 2px; }
  .uth-result-panel .card .cbr,
  .bj-sr-hands .card .cbr, .bj-sr-dealer .card .cbr,
  .bj-split-aside .card .cbr,
  .panel > div[style*="gap:16px"] .card .cbr { bottom: 1px; right: 2px; }
  .uth-result-panel .card .ct-s,
  .bj-sr-hands .card .ct-s, .bj-sr-dealer .card .ct-s,
  .bj-split-aside .card .ct-s,
  .panel > div[style*="gap:16px"] .card .ct-s { margin-top: -1px; }
  /* UTH play (preflop/flop/turn): reclaim space around the bet chips. */
  .uth-bet-chips { margin: 4px 0 !important; }
  .uth-bet-chip { padding: 4px 14px !important; }
  /* Roulette placed bets: compact list and spin button */
  #db { margin: 3px 0 !important; }
  /* Center the selection box + bets zone inside the bet screen's slack spacer, so the
     leftover felt splits above and below instead of pooling in one band over the chips.
     Mobile only: the desktop pixel-parity assertions pin the spacer's top layout. */
  .r-bet-center { justify-content: center; }
  /* Hide the "Roulette · " / etc. prefix on mobile: title bar already shows the game */
  .sec-game-prefix { display: none; }
  .r-bets-zone .rbz-title { font-size: 1.3rem; padding-bottom: 4px; }
  .r-bets-zone .rbz-item { margin-bottom: 0 !important; }
  /* Emoji deck */
  body.deck-emoji .ct-s::after { font-size: 0.72em; }
}

/* Results: taller phones leave bottom slack (≈62px at 812h, ≈102px at 852h, vs only ≈30px
   on the 780h support floor). Spend that slack on bigger gaps between the stacked elements
   rather than leaving dead space at the bottom. Tiered by height so the 360×780 floor (which
   has little slack and must fit without scrolling) keeps its tight 8px gap. */
@media (max-width: 480px) and (min-height: 800px) {
  .panel.results-panel { gap: 12px; }
  /* Keep the title centered between the results box and the chart top (see base rule). */
  .results-panel #dist-title { margin-top: 4px !important; margin-bottom: 18px !important; }
  .results-panel .dist-bars { height: 58px; }
  /* Anchored controls free a band of felt on the result screens; spend it on modestly bigger cards + text
     (control-position parity keeps the box/button pinned regardless). Tiered: floor 360×780 stays small,
     and the growth is capped to fit the tightest tested device, iPhone 15 393×852 with Safari chrome. */
  .uth-result-panel .card.md, .uth-result-panel .card.sm { width: 46px; height: 64px; }
  .uth-result-panel .card.md .csuit, .uth-result-panel .card.sm .csuit { font-size: 1.2rem; }
  .uth-result-panel .card.md .ct-r, .uth-result-panel .card.sm .ct-r { font-size: 0.84rem; }
  .uth-result-panel .card.md .ct-s, .uth-result-panel .card.sm .ct-s { font-size: 0.72rem; }
  .uth-result-panel .result-hl { font-size: 2.15rem; }
  .uth-result-panel .uth-hand-name { font-size: 1.12rem !important; }
  .uth-result-panel .sec { font-size: 0.86rem; }
  .panel > div[style*="gap:16px"] .card.sm { width: 54px; height: 76px; }
  .panel > div[style*="gap:16px"] .card.sm .csuit { font-size: 1.65rem; }
  .panel > div[style*="gap:16px"] .hand-val { font-size: 1.55rem !important; }
}
@media (max-width: 480px) and (min-height: 845px) {
  /* Tall phones have a little spare felt, but the async chart still makes the screen tall, so keep
     gaps + hero modest enough that the whole results screen fits without scrolling (it must fit the
     393×852 floor; the racy old test hid the overflow). The chart keeps a bit more bottom margin so
     the bucket labels clear the share box. */
  .panel.results-panel { gap: 13px; }
  .results-panel #dist-title { margin-top: 6px !important; margin-bottom: 20px !important; }
  .results-panel .results-tier { font-size: 1.15rem; }
  .results-panel .big-chips { font-size: 3.2rem !important; }
  .results-panel .results-streak { font-size: 1.4rem; }
  .results-panel .dist-bars { height: 62px; margin-bottom: 16px; }
}
/* Short phones (360×780) have the smallest panel gap, so the chart's bucket labels (22px below
   the bars, out of flow) nearly touch the share box. Add chart bottom margin to clear them,
   funded by the ~30px of bottom slack on this floor. Taller phones already have the room via
   the bigger panel gap above, so this is scoped to short windows only. */
@media (max-width: 480px) and (max-height: 799px) {
  /* Short phones (360×780): the "You" marker sits ~20px above the bars and was overlapping the
     "Score Distribution" title. Add top room so it clears the title, and shrink the hero chips to
     fund that height (so the screen still fits with no scroll). margin-bottom still clears the
     bucket labels from the share box. The taller bars + roomier gaps here are funded by the hero's
     surrounding slack (it stops greedily centering in dead space), keeping the no-scroll floor. */
  .panel.results-panel .dist-bars { height: 48px; margin-top: 15px; margin-bottom: 21px; }
  .panel.results-panel .big-chips { font-size: 2.8rem !important; }
  /* Floor: keep the title centered (see base rule). Its bigger .dist-bars top margin (15px)
     means a smaller split keeps the gaps even. */
  .panel.results-panel #dist-title { margin-top: 3px !important; margin-bottom: 9px !important; }
}

/* ── Desktop / large screen ─────────────────────────────── */
/* Goal: fill the wider window without growing it. Hard no-scroll inside
   the panel (parallels the mobile philosophy). Extra space is absorbed by
   chrome, fonts, padding, chips, roulette/board cells, and scoped card
   growth only where the 1280x800 layout has measured slack. */
/* Real desktops (>=1280) have room for a wider fixed bet box; 1024 keeps 350 so Clear + box + All In
   still flank without clipping in the tightest panel. */
@media (min-width: 1280px) { :root { --bet-box-w: 420px; } }

@media (min-width: 1024px) {
  /* Shell: fluid window, capped well below viewport so the desktop frames it.
     Width:  620px at 1024w  →  810px at 1440w  →  880px at 1920w (capped).
     Height: 704px at 768h   →  836px at 900h   →  940px at 1080h (capped).  */
  body { font-size: 22px; overflow-x: hidden; overflow-y: auto; }
  :root { --btn-h: 46px; --btn-fs: 1.35rem; --btn-px: 16px; }
  .app { max-width: clamp(620px, 56vw, 880px); padding: 16px 16px; }
  .window {
    /* min-height (not a fixed height) so the window stays at the framed clamp size when content
       fits: preserving the XP look: but GROWS when content is genuinely taller than it (a short
       window, or a user's enlarged browser/OS fonts). The page then scrolls vertically so every
       button stays reachable, instead of the panel clipping the bottom one off-screen. */
    min-height: clamp(700px, calc(100svh - 32px), 960px);
    box-shadow:
      inset 1px 1px 0 var(--highlight),
      inset -2px -2px 0 var(--shadow),
      0 0 0 1px rgba(0,0,0,0.5),
      0 18px 50px rgba(0,0,0,0.55);
  }
  /* flex:1 0 auto (fill when content is short, never shrink below content when tall) + no overflow
     clip lets a too-tall panel push the window taller and the page scroll, rather than clipping the
     bottom button. Mirrors the mobile shell. Horizontal bleed is still caught by body overflow-x. */
  .panel { padding: 6px 22px; flex: 1 0 auto; min-height: 0; gap: 4px; }
  .panel.cream { padding: 10px 24px; }
  .divider { margin: 2px 0; }

  /* Chrome */
  .title-bar { font-size: 26px; padding: 5px 8px; }
  .chip-badge { font-size: 1.55rem; padding: 1px 12px; }
  .menu-bar { font-size: 1.18rem; padding: 0 8px 0 0; }
  .menu-bar .mb-item { padding: 4px 10px; }
  .status-bar { font-size: 1.08rem; padding: 3px 10px; }

  /* Mod banner: fill width, modest */
  .mod-banner { padding: 8px 18px; font-size: 1.45rem; margin-bottom: 5px; }
  .mod-banner-label { font-size: 1.05rem; }
  .mod-banner-title { font-size: 1.78rem; }
  .mod-banner-r { font-size: 1.38rem; }

  /* Section labels + info rows */
  .sec { font-size: 1.3rem; margin-bottom: 3px; }
  .sec-sm { font-size: 1.05rem; }
  .ik { font-size: 1.3rem; }
  .iv { font-size: 1.3rem; }
  .irow { padding: 5px 14px; }

  /* Hand-progress dots */
  .dots-row { gap: 8px; margin: 2px 0; }
  /* Bet panels have gap:8px (panel:has(> #db:last-child)); cancel the extra 4px so dots-row top
     stays at the same distance from the mod-banner as on play panels (gap:4px + margin:2px = 6px). */
  .panel:has(> #db:last-child) .dots-row { margin-top: -2px; }
  .hand-dot { padding: 4px 12px; font-size: 1.25rem; }

  /* Hand values under cards */
  .hand-val { font-size: 2.2rem; margin-top: 6px; }

  /* Desktop cards: modest upscale from mobile sizes (~10% larger). */
  .card.lg { width: 88px; height: 124px; }
  .card.md { width: 78px; height: 110px; }
  .card.sm { width: 62px; height: 87px; }
  .card.lg .csuit { font-size: 3.4rem; }
  .card.md .csuit { font-size: 2.85rem; }
  .card.sm .csuit { font-size: 2.25rem; }
  .card.lg .ct-r { font-size: 1.35rem; }
  .card.lg .ct-s { font-size: 1.1rem; }
  .card.md .ct-r { font-size: 1.15rem; }
  .card.md .ct-s { font-size: 0.95rem; }
  .card.sm .ct-r { font-size: 0.92rem; }
  .card.sm .ct-s { font-size: 0.78rem; }
  .card.lg .ct-r[data-r="10"] { font-size: 1.05rem !important; }
  .card.md .ct-r[data-r="10"] { font-size: 0.92rem !important; }
  .card.sm .ct-r[data-r="10"] { font-size: 0.75rem !important; }

  /* Chip selector: slightly larger and roomier */
  .chbtn { width: 56px; height: 56px; }
  .chbtn > span { font-size: 1.15rem; }
  .chip-row { gap: 10px; margin-bottom: 8px; }
  .bet-row { gap: 10px; }
  .bet-amt { padding: 5px 14px; }
  .bet-amt span:first-child { font-size: 1.05rem; }
  .bet-amt span:last-child { font-size: 1.65rem; }
  .ch-clear, .ch-allin { padding: 7px 16px; font-size: 1.15rem; }
  /* order/flex for the stacked bet-row come from the main (max-width:480px) block above. */

  /* Action buttons */
  .act-btn { padding: 12px 14px; font-size: 1.5rem; }
  .btn-gold { padding: 12px 16px; font-size: 1.45rem; }
  .btn-gold.btn-lg { padding: 16px 20px; font-size: 1.9rem; }

  /* ── Intro screen ─────────────────────────────── */
  .logo { font-size: 4.4rem; }
  .logo-sub { font-size: 1.45rem; margin-top: 4px; }
  .game-manifest .gm-row { padding: 6px 14px; gap: 12px; }
  .game-manifest .rnd-ic { font-size: 1.4rem; }
  .game-manifest .rnd-nm { font-size: 1.55rem; }
  .game-manifest .rnd-dc { font-size: 1.15rem; margin-top: 1px; }

  /* ── BJ play (normal) ─────────────────────────── */
  #bj-dealer-section .hand-val { font-size: 1.9rem; margin-top: 3px; }
  .bj-celebrate-txt { font-size: 2rem; margin-top: 6px; }
  .act-btns { gap: 6px; }
  /* Tighten the bet-readout irow margin-top (inline 10px) on play screens */
  .bj-split-active ~ div .irow,
  #bj-player-hand ~ * .irow { margin-top: 4px !important; padding: 4px 12px !important; }

  /* BJ normal play: scale dealer/player cards + UI up to pull in the centered
     slack between the dealer divider, the player hand, and the buttons. Scoped
     to #bj-player-hand so the dense 4-way split (already tight) is untouched.
     Card width is held in check by the multi-card fan on the narrow 1024 panel,
     so height grows a little more than width; the widest sizes are gated to
     wider windows below. Daily-mod banner and progress dots are left alone. */
  /* Even bands: the player block matches the dealer band (both .vband flex:1) so the middle divider
     stays dead-centre between the top and bottom dividers. (Was content-sized + margin-auto group-centered.) */
  .panel:has(#bj-player-hand) > div:has(#bj-player-hand) { flex: 1 1 0 !important; }
  .panel:has(#bj-player-hand) .card.lg { width: 92px; height: 130px; }
  .panel:has(#bj-player-hand) .card.lg .csuit { font-size: 3.6rem; }
  .panel:has(#bj-player-hand) .card.lg .ct-r { font-size: 1.42rem; }
  .panel:has(#bj-player-hand) .card.lg .ct-s { font-size: 1.16rem; }
  .panel:has(#bj-player-hand) .card.lg .ct-r[data-r="10"] { font-size: 1.1rem !important; }
  .panel:has(#bj-player-hand) .card.lg.back::before { font-size: 3.4rem; }
  .panel:has(#bj-player-hand) .sec { font-size: 1.35rem; }
  .panel:has(#bj-player-hand) .hand-val { font-size: 2.2rem; margin-top: 4px; }
  .panel:has(#bj-player-hand) #bj-dealer-section .hand-val { font-size: 2.1rem; }
  .panel:has(#bj-player-hand) .act-btn { font-size: 1.55rem; padding: 12px 14px; }
  .panel:has(#bj-player-hand) #bj-player-hand ~ * .irow,
  .panel:has(#bj-player-hand) .irow { padding: 6px 14px !important; }
  .panel:has(#bj-player-hand) .ik,
  .panel:has(#bj-player-hand) .iv { font-size: 1.4rem; }

  /* BJ result screens: shrink headline/sub from base 3rem/2rem */
  .panel .result-hl { font-size: 2.2rem; margin-bottom: 2px; }
  .panel .result-sub { font-size: 1.5rem; margin-bottom: 6px; }
  .panel .result-sub.borrow-rem { font-size: 1.3rem; }
  .panel .result-hl ~ .result-sub { margin-bottom: 4px; }
  /* BJ result-win detail: target the inline flex column with gap:16px */
  .panel > div[style*="gap:16px"] { gap: 6px !important; margin-bottom: 4px !important; }
  /* Compact hand-val on BJ result screens */
  .panel > div[style*="gap:16px"] .hand-val { font-size: 1.2rem !important; margin-top: 2px !important; }

  /* ── BJ 4-way split play / result ─────────────── */
  /* Heaviest screens: tightest possible to fit the 4-hand active layout */
  .bj-split-aside { margin-bottom: 2px; }
  .bj-split-lbl { font-size: 1rem; }
  .bj-split-val { font-size: 1.3rem; margin-top: 1px; }
  .bj-split-aside .card.sm { width: 48px; height: 67px; }
  .bj-split-aside .card.sm .csuit { font-size: 1.2rem; }
  .bj-active-lbl { font-size: 1.05rem; margin-bottom: 1px; }
  /* Split play: dealer and active hand share one size so they read as balanced
     (active was bigger than the dealer). Tuned to stay vertically neutral: the
     dealer's growth is paid for by the active's reduction. */
  .panel:has(.bj-split-active) #bj-dealer-section .card.lg,
  .bj-split-active .card.lg { width: 90px; height: 126px; }
  .panel:has(.bj-split-active) #bj-dealer-section .card.lg .csuit,
  .bj-split-active .card.lg .csuit { font-size: 3.4rem; }
  .panel:has(.bj-split-active) #bj-dealer-section .card.lg .ct-r,
  .bj-split-active .card.lg .ct-r { font-size: 1.4rem; }
  .panel:has(.bj-split-active) #bj-dealer-section .card.lg .ct-s,
  .bj-split-active .card.lg .ct-s { font-size: 1.14rem; }
  .panel:has(.bj-split-active) #bj-dealer-section .card.lg .ct-r[data-r="10"],
  .bj-split-active .card.lg .ct-r[data-r="10"] { font-size: 1.08rem !important; }
  .panel:has(.bj-split-active) #bj-dealer-section .card.lg.back::before { font-size: 3.1rem; }
  .bj-split-active .hand-val { font-size: 1.8rem !important; margin-top: 7px !important; }
  /* Tight act-btns under split. No padding-top: it would push the box up off the canonical Y (the
     box→button spacing is the .game-controls gap, kept uniform for control-position parity). */
  .bj-split-active + div .act-btns,
  .bj-split-active ~ div .act-btns { gap: 4px; }
  /* Split-play-only panel overrides: most aggressive */
  .panel:has(.bj-split-active) { padding: 4px 28px !important; gap: 2px !important; }
  .panel:has(.bj-split-active) #bj-dealer-section { margin-bottom: 0 !important; }
  /* Cards scaled down a touch; spend the savings on label→card breathing room and
     slightly larger labels/values. */
  .panel:has(.bj-split-active) #bj-dealer-section .sec { font-size: 1.1rem; margin-bottom: 8px; }
  .panel:has(.bj-split-active) #bj-dealer-section .hand-val { font-size: 1.35rem; margin-top: 7px; }
  .panel:has(.bj-split-active) .divider { margin: 1px 0; }
  .panel:has(.bj-split-active) .bj-active-lbl { font-size: 1.15rem; margin-bottom: 8px; }
  .panel:has(.bj-split-active) .dots-row { margin: 0; }
  .panel:has(.bj-split-active) .hand-dot { padding: 3px 10px; font-size: 1.1rem; }
  .panel:has(.bj-split-active) .act-btn { padding: 6px 10px; font-size: 1.15rem; }
  .panel:has(.bj-split-active) .irow { padding: 3px 12px !important; margin-top: 4px !important; }
  /* Override the result hl/sub specifically for the bj-split-result panel (base rule above was 2.2rem) */
  .bj-split-result { padding: 4px 24px !important; gap: 2px !important; }
  .bj-split-result .result-hl { font-size: 1.7rem !important; margin-bottom: 0 !important; }
  .bj-split-result .result-sub { font-size: 1.2rem !important; margin-bottom: 1px !important; }
  .bj-split-result:not(.sr-4) .result-hl { font-size: 2.1rem !important; }
  .bj-split-result:not(.sr-4) .result-sub { font-size: 1.5rem !important; }
  .bj-sr-dealer { margin-bottom: 2px; }
  .bj-sr-dealer .hand-val { font-size: 1.1rem !important; margin-top: 1px !important; }
  .bj-sr-dealer .card.sm { width: 45px; height: 63px; }
  .bj-sr-dealer .card.sm .csuit { font-size: 1.15rem; }
  .bj-sr-hands { margin-bottom: 2px !important; gap: 4px !important; }
  .bj-sr-hands .card.sm { width: 45px; height: 63px; }
  .bj-sr-hands .card.sm .csuit { font-size: 1.15rem; }
  .bj-sr-hands .hand-val { font-size: 1.1rem !important; margin-top: 1px !important; }
  .bj-sr-hands .sec { font-size: 0.94rem !important; }
  /* 2-/3-hand result splits: single row + ~70px spare on short desktop. */
  .sr-2 .bj-sr-dealer .card.sm { width: 66px; height: 92px; }
  .sr-2 .bj-sr-hands .card.sm { width: 76px; height: 106px; }
  .sr-2 .card.sm .csuit { font-size: 1.9rem; }
  .sr-2 .hand-val { font-size: 1.7rem !important; }
  .sr-2 .bj-sr-hands .sec { font-size: 1.25rem !important; }
  .sr-3 .bj-sr-dealer .card.sm { width: 58px; height: 81px; }
  .sr-3 .bj-sr-hands .card.sm { width: 64px; height: 90px; }
  .sr-3 .card.sm .csuit { font-size: 1.6rem; }
  .sr-3 .hand-val { font-size: 1.55rem !important; }
  .sr-3 .bj-sr-hands .sec { font-size: 1.12rem !important; }
  .bj-split-result .btn-gold { padding: 8px 12px; font-size: 1.2rem; }
  /* Spacing of the result group is handled globally (.bj-split-result auto-margins). */

  .panel:has(#uth-actions-ui) {
    padding-top: 6px;
    padding-bottom: 6px;
    gap: 2px;
  }
  /* gap:2px → banner_mb(5)+gap(2)+dots_mt = 11 → dots_mt = 4px */
  .panel:has(#uth-actions-ui) .dots-row { margin-top: 4px; }
  .panel:has(#uth-actions-ui) .divider { margin: 1px 0; }
  .panel:has(#uth-actions-ui) .sec { font-size: 1.2rem; margin-bottom: 1px; }
  .panel:has(#uth-actions-ui) .card.md { width: 72px; height: 102px; }
  .panel:has(#uth-actions-ui) .card.sm { width: 54px; height: 76px; }
  .panel:has(#uth-actions-ui) .card.md .csuit { font-size: 2.45rem; }
  .panel:has(#uth-actions-ui) .card.sm .csuit { font-size: 1.75rem; }
  .panel:has(#uth-actions-ui) .card.md .ct-r { font-size: 1.08rem; }
  .panel:has(#uth-actions-ui) .card.md .ct-s { font-size: 0.9rem; }
  .panel:has(#uth-actions-ui) .card.sm .ct-r { font-size: 0.82rem; }
  .panel:has(#uth-actions-ui) .card.sm .ct-s { font-size: 0.7rem; }
  .panel:has(#uth-actions-ui) .card.md .ct-r[data-r="10"] { font-size: 0.86rem !important; }
  .panel:has(#uth-actions-ui) .card.sm .ct-r[data-r="10"] { font-size: 0.66rem !important; }
  .panel:has(#uth-actions-ui) .uth-bet-chips { margin: 2px 0 !important; }
  .panel:has(#uth-actions-ui) .uth-bet-chip { padding: 3px 12px !important; }
  .panel:has(#uth-actions-ui) .act-btn,
  .panel:has(#uth-actions-ui) .btn-gold { padding: 8px 12px; font-size: 1.25rem; }

  /* UTH bet chips block (preflop/flop/turn/reveal): compact margin + inner padding */
  .uth-bet-chips { margin: 4px 0 !important; gap: 8px !important; }
  .uth-bet-chip { padding: 4px 14px !important; }
  .uth-bet-chip > div:first-child { font-size: 0.78rem !important; }
  .uth-bet-chip > div:last-child { font-size: 1.4rem !important; }

  /* ── UTH bet screen ───────────────────────────── */
  /* The pay table is the chunk that pushes UTH bet over: compact it */
  .ptable { gap: 0 18px; padding: 4px 14px; }
  .pname { font-size: 1.1rem; }
  .ppay { font-size: 1.05rem; }
  .uth-summary { font-size: 1.15rem; }

  /* ── UTH bet panel: scale up to fill the empty bottom on desktop ── */
  /* Tuned for 1280×800. Larger viewports get further bumps in the 1440+
     and 1920+ blocks below. Summary is a natural one-line block (no flex);
     remaining slack at larger viewports gets eaten by the ptable/chip/dot
     scale-ups, not by an invisible padding band around the summary text. */
  .panel:has(#uth-summary) { gap: 6px; justify-content: flex-start; }
  .panel:has(#uth-summary) #uth-summary { font-size: 1.4rem; margin: 0 !important; }
  /* chbtn flex-shrink: 1 lets the chips squish a hair when the panel is at its
     min width (620px → 576px inner), so 7 chips always fit without wrapping. */
  .panel:has(#uth-summary) .chip-row { gap: 8px; margin: 2px 0 8px; }
  .panel:has(#uth-summary) .chbtn { width: 66px; height: 66px; flex-shrink: 1; min-width: 0; }
  .panel:has(#uth-summary) .chbtn > span { font-size: 1.2rem; }
  .panel:has(#uth-summary) .bet-amt { padding: 6px 14px; }
  .panel:has(#uth-summary) .bet-amt span:last-child { font-size: 1.75rem; }
  .panel:has(#uth-summary) #db { padding: 10px 16px; font-size: 1.4rem; margin-top: 2px !important; }
  .panel:has(.bj-bet-table) #db,
  .panel:has(#r-bets-zone) #db { margin-top: 2px !important; }  /* match UTH bet's bet->Deal gap so the chip selector lands at the same Y */
  .panel:has(#uth-summary) > .divider { margin: 5px 0; }
  .panel:has(.bj-bet-table) > .dots-row + .divider { margin-top: 5px; }  /* match UTH bet's dots->divider gap */
  .panel:has(#uth-summary) .ptable { padding: 5px 14px; gap: 1px 18px; }
  .panel:has(#uth-summary) .pname { font-size: 1rem; }
  .panel:has(#uth-summary) .ppay  { font-size: 0.95rem; }

  /* ── UTH play (preflop / flop / turn) ─────────── */
  /* 4 sections + dividers + bet chips + actions: keep things tight */

  /* ── UTH showdown result (win/lose/fold) ──────── */
  /* Cards scaled up to fill the short (800h) window; content vertically
     centered so the larger residual on tall monitors balances top/bottom
     instead of pooling at the bottom. Height-gated bumps below grow the
     cards further on taller windows. */
  .uth-result-panel { min-height: 0 !important; padding: 5px 28px !important; gap: 2px !important; }
  .uth-result-panel > .divider { margin: 2px 0; }
  .uth-result-panel .result-hl { font-size: 1.55rem; margin-bottom: 0; }
  .uth-result-panel .result-sub { font-size: 1.2rem; margin-bottom: 1px; }
  .uth-cards-col { gap: 2px; margin: 0; }
  .uth-result-panel .uth-cards-col .divider { margin: 2px 0 !important; }
  .uth-result-panel .card.md { width: 54px; height: 76px; }
  .uth-result-panel .card.md .csuit { font-size: 1.5rem; }
  .uth-result-panel .card.md .ct-r { font-size: 0.95rem; }
  .uth-result-panel .card.md .ct-s { font-size: 0.8rem; }
  .uth-result-panel .card.md .ct-r[data-r="10"] { font-size: 0.8rem !important; }
  .uth-result-panel .card.sm { width: 46px; height: 64px; }
  .uth-result-panel .card.sm .csuit { font-size: 1.25rem; }
  .uth-result-panel .card.sm .ct-r { font-size: 0.82rem; }
  .uth-result-panel .card.sm .ct-s { font-size: 0.68rem; }
  .uth-result-panel .card.sm .ct-r[data-r="10"] { font-size: 0.68rem !important; }
  .uth-result-panel .sec { font-size: 0.88rem; margin-bottom: 0; }
  .uth-hand-name { font-size: 0.92rem !important; margin-top: 1px !important; }
  .uth-result-panel .uth-bets-grid { gap: 0 14px; margin-bottom: 2px; }
  .uth-result-panel .irow { margin-top: 2px !important; padding: 3px 12px !important; }
  /* No margin-top here: the box→button spacing is the .game-controls gap, kept uniform across screens
     for control-position parity (a btn margin-top would offset the box vs the bet/play screens). */
  .uth-result-panel .btn-gold { padding: 7px 14px !important; font-size: 1.25rem; }
  /* The split result + split play panels sit 2px shy of the others on desktop (their panel padding
     differs); lift the cluster so its box + button match the canonical bet-screen Y. */
  .bj-split-result > .game-controls,
  .panel:has(.bj-split-active) .game-controls { margin-bottom: 2px; }
  /* Fold has no bet-breakdown row, so it carries a constant extra band of slack.
     Center its card stack between the dots and the button (banner stays pinned). */
  .uth-result-panel:not(:has(.uth-bets-grid)) .uth-cards-col { margin-top: auto; }
  .uth-result-panel:not(:has(.uth-bets-grid)) > .btn-gold:last-child { margin-bottom: auto; }

  /* ── Roulette ─────────────────────────────────── */
  /* Board cells fill more of the wider window */
  .rboard, .rboard-sub { gap: 3px; }
  .rboard { grid-template-rows: 46px 46px 46px; grid-template-columns: 34px repeat(12, 1fr) 46px; }
  .rboard-sub { grid-auto-rows: 38px; grid-template-columns: 34px repeat(12, 1fr) 46px; }
  .rn { font-size: 1.3rem; }
  .r2to1, .rout { font-size: 1.45rem; }
  /* Roulette's selection + bets boxes track the desktop chip cluster (56px chips → 452px). */
  .panel:has(#r-bets-zone) #r-bets-zone,
  .panel:has(#r-bets-zone) #r-sel-box { max-width: 452px; }
  /* Deal / Final Spin sit slightly wider than the bet box (see base rule). */
  .panel:has(.bj-bet-table) > #db,
  .panel:has(#uth-summary) > #db,
  .panel:has(.ptable) > #db,
  .panel:has(#r-bets-zone) > #db { max-width: var(--act-btn-w); }
  /* Roulette packs Clear + box + Place Bet + All In on ONE line: the box shrinks to 200px (its parity
     is a bj/uth-only guarantee), Clear + All In are content-sized, and Place Bet flex-grows so it's the
     largest of the three buttons. (Phones stack the bet-row via the order rules instead.) */
  /* nowrap keeps all four on one line; the box (flex-shrink:1) absorbs the overflow on the tight 1024
     panel, shrinking from 200px so Place Bet (whose nowrap text can't shrink) never wraps. */
  .panel:has(#r-bets-zone) .bet-row { flex-wrap: nowrap; }
  .panel:has(#r-bets-zone) .bet-row > .bet-amt { flex: 0 1 auto; width: 200px; min-width: 0; }
  .panel:has(#r-bets-zone) .bet-row > .ch-clear,
  .panel:has(#r-bets-zone) .bet-row > .ch-allin { flex: 0 0 auto; }
  .panel:has(#r-bets-zone) .bet-row > #pb-add { flex: 1 1 0; width: auto; }
  /* Compact the placed-bets list so a full set of bets fits a short desktop
     window without pushing the panel over (the list still scrolls as a last
     resort, but should not need to at the default 5-bet max). */
  .panel:has(#r-bets-zone) .rbz-title { font-size: 1.55rem; padding-bottom: 6px; }
  .panel:has(#r-bets-zone) .rbz-item { padding: 2px 0 !important; margin-bottom: 3px !important; }
  .panel:has(#r-bets-zone) .rbz-lbl { font-size: 1.4rem; }
  .panel:has(#r-bets-zone) .rbz-win { font-size: 1.15rem; }

  /* ── Results screen ───────────────────────────── */
  /* big-chips + result-row padding kept tight here: 1280×800 (the only desktop in this base
     block) has no spare height, and the chart now reserves margin for the You label (top) and
     bucket labels (bottom), so the rows/hero give that space back. */
  .results-panel { padding: 5px 28px !important; gap: 2px !important; }
  .results-panel .big-chips { font-size: 2.5rem !important; }
  .results-panel .results-tier { font-size: 0.98rem; margin-bottom: 1px; }
  .results-panel .results-streak { font-size: 1.15rem; margin: 2px 0 4px; }
  /* !important to beat the inline margin-bottom:6px and let the title's split margins
     center it between the box and the chart (see the desktop #dist-title rule below). */
  .results-panel .game-manifest { margin-bottom: 0 !important; }
  .results-panel .res-row { padding: 2px 16px !important; }
  .results-panel .res-row span:first-child,
  .results-panel .res-row .ik { font-size: 1.1rem !important; }
  .results-panel .res-row .iv { font-size: 1.1rem; }
  .results-panel .res-net { font-size: 1.3rem !important; }
  .results-panel .lb-row { padding: 2px 16px !important; }
  /* Tight base values (the only desktop here is 1280×800, height < 880, ~no slack with the
     chart). The narrower share box wraps one extra line, so trim the chart margins + share
     line-height to claw that back. Taller windows override .dist-bars / .share-box below. */
  .results-panel .share-box { font-size: 0.96rem; padding: 5px 12px; line-height: 1.2; }
  /* Split top/bottom so the title centers between the results box (margin-bottom:0 above)
     and the chart's topmost element (the "You" marker, ~20px above the bars). The split
     tracks .dist-bars margin-top per height tier (22/18/16px below) so the gaps stay even;
     this base value pairs with the 22px margin (1024×640 / 1280×800). */
  #dist-title { margin-top: 6px !important; margin-bottom: 3px !important; }
  /* Top margin must clear the You line/label (~20px ABOVE the bars, out of flow) so it doesn't
     overlap the Score Distribution title; bottom margin must clear the bucket labels (~22px
     BELOW the bars) and leave a gap before the share box. Both overhangs are out of flow, so the
     margins carry them. */
  .dist-bars { height: 34px; margin: 22px 4px 27px; }
  /* Cap the results column to a centred ~620px so the share box, Copy button, result rows
     and chart don't stretch super-wide on big windows (the felt frames them). On narrower
     desktop windows the window is itself < this width, so the cap simply doesn't bite:
     side-whitespace appears only where there is spare width. */
  /* width:100% is REQUIRED: auto margins on a column flex item disable align-items:stretch,
     so without a definite width the item shrinks to content. #dist-chart's bars are flex:1 with
     no intrinsic width (their labels are absolutely positioned), so it would collapse to slivers. */
  .results-panel .game-manifest,
  .results-panel #dist-title,
  .results-panel #dist-chart { width: 100%; max-width: 620px; margin-left: auto; margin-right: auto; }
  /* Share box + its Copy & Share button (wrapped in .share-cluster): a centred card ~half the
     window wide, scaling WITH the window so every desktop size matches the 1920 narrow-card look
     (not just the big ones). min-width keeps the longest share line ("Finished with N chips
     (Top X%)") from wrapping on the narrowest (1024) window. width:50% is of the panel content
     box; both children stretch to fill it, so the button stays locked to the share box width.
     gap:4px preserves the tight box→button spacing the tight 1280×800 layout needs. */
  .results-panel > .share-cluster { width: 50%; min-width: 340px; max-width: 460px; gap: 4px; margin-left: auto; margin-right: auto; }
  /* .results-hero (flex:1) absorbs the slack between the banner and the box and floats
     the tier/chips/streak centered in it, so the manifest/chart/share/button group settles
     at the bottom. No auto-margins here: they'd claim the free space and starve that grow. */

  /* ── Dev stats / borrow / 5-card poker ────────── */
  /* Devstats has lots of slack: base font rules absorb it.
     Poker is not a priority; existing base rules suffice. */

  /* ── BJ bet: slots flex-grow to fill slack; chips/bet scaled up ────── */
  .panel:has(> #db:last-child) { justify-content: flex-start; gap: 8px; }
  .panel:has(> #db:last-child) .sec { font-size: 1.45rem; text-align: center; margin-bottom: 0; }
  .panel:has(> #db:last-child) .chip-row { gap: 12px; margin-bottom: 18px; }
  .panel:has(> #db:last-child) .chbtn { width: 72px; height: 72px; }
  .panel:has(> #db:last-child) .chbtn > span { font-size: 1.3rem; }
  .panel:has(> #db:last-child) .bet-row { gap: 12px; }
  .panel:has(> #db:last-child) .bet-amt { padding: 8px 18px; }
  /* Bet-box label/value font-size intentionally NOT overridden here: the bet-phase box uses the same
     base .bet-amt span rules as the play/result betInlay box, so the readout looks identical. */
  .panel:has(> #db:last-child) .ch-clear,
  .panel:has(> #db:last-child) .ch-allin { padding: 9px 18px; font-size: 1.2rem; }
  .panel:has(> #db:last-child) > #db { padding: 12px 18px; font-size: 1.55rem; }
  /* Desktop slots: bigger and breathe more vertical space */
  .panel:has(> #db:last-child) .bj-bet-table { gap: 10px; padding: 6px 0; }
  .panel:has(> #db:last-child) .card-slot { width: 76px; height: 106px; }
  .panel:has(> #db:last-child) .bj-bet-slot-lbl { font-size: 1.1rem; }
  .panel:has(> #db:last-child) .felt-rules { font-size: 1.05rem; padding: 6px 0; }

  /* Poker card screens have the most desktop slack; let the cards breathe. */
  .panel:has(.hold-wrap) .card.md,
  .panel:has(.result-hl) .hand:has(> .card.md:nth-child(5)) .card.md {
    width: 128px;
    height: 182px;
  }
  .panel:has(.hold-wrap) .card.md .csuit,
  .panel:has(.result-hl) .hand:has(> .card.md:nth-child(5)) .card.md .csuit { font-size: 4.4rem; }
  .panel:has(.hold-wrap) .card.md .ct-r,
  .panel:has(.result-hl) .hand:has(> .card.md:nth-child(5)) .card.md .ct-r { font-size: 1.6rem; }
  .panel:has(.hold-wrap) .card.md .ct-s,
  .panel:has(.result-hl) .hand:has(> .card.md:nth-child(5)) .card.md .ct-s { font-size: 1.3rem; }
  .panel:has(.hold-wrap) .card.md .ct-r[data-r="10"],
  .panel:has(.result-hl) .hand:has(> .card.md:nth-child(5)) .card.md .ct-r[data-r="10"] { font-size: 1.25rem !important; }
  .panel:has(.hold-wrap) .pk-hold-status { margin-top: auto; font-size: 1rem !important; }
  .panel:has(.hold-wrap) .hold-tag { font-size: 1.25rem; height: 18px; }
  .panel:has(.hold-wrap) .btn-gold { padding: 14px 18px; font-size: 1.55rem; }
  .panel:has(.hold-wrap) > .irow:last-child { margin-bottom: auto; }
  .panel:has(.hand > .card.md:nth-child(5)) > .result-hl { margin-top: auto; }
  .panel:has(.hand > .card.md:nth-child(5)) > .btn-gold:last-child { margin-bottom: auto; }

  /* Roulette result: keep the modifier pinned; center only the result stack. */
  .panel:has(.r-res-num) {
    justify-content: flex-start;
    gap: 10px;
  }
  .panel:has(.r-res-num) > div:has(> .r-res-num) { margin-top: auto; }
  .panel:has(.r-res-num) > .btn-gold:last-child,
  .panel:has(.r-res-num) > div:last-child:has(> .btn-gold:last-child) { margin-bottom: auto; }
  .panel:has(.r-res-num) .r-res-num {
    width: 108px;
    height: 108px;
    font-size: 2.7rem;
  }

  /* Roulette spin: wheel scaled down to fit the narrower window. */
  .panel:has(#rwheel) { justify-content: flex-start; }
  .panel:has(#rwheel) .wheel-outer { margin-top: auto; margin-bottom: 14px; }
  .panel:has(#rwheel) #rwheel { width: 280px; height: 280px; }
  .panel:has(#rwheel) .wheel-pointer {
    border-left-width: 13px;
    border-right-width: 13px;
    border-top-width: 24px;
    margin-bottom: -4px;
  }
  .panel:has(#rwheel) > div:last-child { margin-bottom: auto; }

  /* Even bands centre each half; with both bands flex:1 these margin-top:auto resolve to 0 (no free
     space left after flex-grow), so they're harmless and the dividers split the board evenly. */
  .panel:has(#bj-player-hand) #bj-dealer-section,
  .panel:has(#uth-actions-ui) #uth-dealer-container {
    margin-top: auto;
  }
  .panel:has(#bj-player-hand) > div:has(#bj-player-hand),
  .panel:has(.bj-split-active) .bj-split-active {
    display: flex;
    flex-direction: column;
    justify-content: center;
    min-height: 0;
  }
  /* The bet box + button cluster is BOTTOM-anchored (not centered): the dealer's margin-top:auto above
     absorbs the panel's spare height, so the box sits at the same distance from the panel bottom on
     every screen (sparse or dense) and never jumps vertically. */
  .panel:has(#bj-player-hand) > div:last-child,
  .panel:has(.bj-split-active) > div:last-child,
  .panel:has(#uth-actions-ui) #uth-actions-ui {
    margin-top: 0 !important;
    margin-bottom: 0;
  }

  /* Spend result-screen slack on cards; tight split/showdown layouts stay compact. */
  .panel > div[style*="gap:16px"] .card.sm {
    width: 74px;
    height: 104px;
  }
  .panel > div[style*="gap:16px"] .card.sm .csuit { font-size: 2.8rem; }
  .panel > div[style*="gap:16px"] .card.sm .ct-r { font-size: 1.12rem; }
  .panel > div[style*="gap:16px"] .card.sm .ct-s { font-size: 0.95rem; }
  .panel > div[style*="gap:16px"] .card.sm .ct-r[data-r="10"] { font-size: 0.9rem !important; }
  /* Center the BJ win-result head (banner + dots stay pinned at the top). The headline+chip
     block carries auto-margins top AND bottom so its slack splits evenly above (to the divider)
     and below (to the cards): the whole unit floats vertically centered between them. */
  .panel:has(> div[style*="gap:16px"]) > .result-head { margin-top: auto; margin-bottom: auto; }
  .panel:has(> div[style*="gap:16px"]) > .btn-gold:last-child { margin-bottom: auto; }
  .panel:has(> div[style*="gap:16px"]) .hand-val { font-size: 1.5rem !important; }
  .panel:has(> div[style*="gap:16px"]) .sec-sm { font-size: 1.1rem; }

  /* UTH dealer-reveal screen (and similar): the inline gap:12px stack of cards
     plus pay-summary tends to leave slack; nothing to do, already centered. */
}

/* ── Tall desktop (1024×880+): fill more slack on the UTH bet panel.
   Chip/font scale-ups use the SAME chbtn width as the base so the chip row
   always fits the narrow (1024 wide → 576px inner) panel without wrapping. */
/* Short desktop windows (e.g. 1280x800, 1024x640): the big desktop card slots make the BJ bet-table
   too tall to fit, overflowing the panel and pushing the chip selector ~76px below where the (more
   compact) UTH pay table puts it. Shrink the slots here so BJ fits like UTH and the chips align. */
@media (min-width: 1024px) and (max-height: 879px) {
  .panel:has(> #db:last-child) .bj-bet-table { gap: 6px; padding: 4px 0; }
  .panel:has(> #db:last-child) .card-slot { width: 56px; height: 78px; }
  .panel:has(> #db:last-child) .bj-bet-slot-lbl { font-size: 1rem; }
  .panel:has(> #db:last-child) .felt-rules { font-size: 0.95rem; padding: 4px 0; }
}
/* Short desktop windows (e.g. 1024×640 landscape) lack the vertical room for the full split cards, so the
   active hand would spill into the bet box. Shrink the split cards just here (only where forced) so the
   active hand clears the controls: every taller window keeps the full size. */
@media (min-width: 1024px) and (max-height: 720px) {
  .panel:has(.bj-split-active) #bj-dealer-section .card.lg,
  .bj-split-active .card.lg { width: 72px; height: 100px; }
  .panel:has(.bj-split-active) #bj-dealer-section .card.lg .csuit,
  .bj-split-active .card.lg .csuit { font-size: 2.7rem; }
  .panel:has(.bj-split-active) #bj-dealer-section .card.lg .ct-r,
  .bj-split-active .card.lg .ct-r { font-size: 1.1rem; }
  .panel:has(.bj-split-active) #bj-dealer-section .card.lg .ct-s,
  .bj-split-active .card.lg .ct-s { font-size: 0.92rem; }
  .panel:has(.bj-split-active) #bj-dealer-section .card.lg.back::before { font-size: 2.5rem; }
  .bj-split-active .hand-val { font-size: 1.5rem !important; margin-top: 4px !important; }
}
@media (min-width: 1024px) and (min-height: 880px) {
  :root { --btn-h: 50px; --btn-fs: 1.42rem; }
  /* On tall desktop the bet panel's box→commit gap tightens to 8px while the UTH result panel keeps 10;
     match it (gap 8 + 2px lift) so the box + button stay at the canonical bet-screen Y (parity). */
  .uth-result-panel > .game-controls { gap: 8px; margin-bottom: 2px; }
  /* Roomy desktop: grow the centered results hero above its tight 1280×800 base. */
  .results-panel .results-tier { font-size: 1.32rem; }
  .results-panel .big-chips { font-size: 3.55rem !important; }
  .results-panel .results-streak { font-size: 1.62rem; }
  /* Intro has little content; on tall desktop spend the felt slack on bigger elements.
     Tiles grow modestly so the long Hold'em name still fits one line on the narrow 1024 panel. */
  .intro-panel .logo { font-size: 5.5rem; }
  .intro-panel .logo-sub { font-size: 1.9rem; }
  .intro-lead { font-size: 2.2rem; }
  .intro-sub { font-size: 1.65rem; }
  .intro-prog-label { font-size: 1.6rem; }
  /* Split play leaves deep vertical slack on tall desktop (~160px at 1440×900):
     spend it on the active hand. Width tracks normal play's 118px ceiling so a
     multi-card fan still fits the narrow 1024 panel. Aside hands grow modestly. */
  .panel:has(.bj-split-active) #bj-dealer-section .card.lg,
  .bj-split-active .card.lg { width: 100px; height: 140px; }
  .panel:has(.bj-split-active) #bj-dealer-section .card.lg .csuit,
  .bj-split-active .card.lg .csuit { font-size: 3.7rem; }
  .panel:has(.bj-split-active) #bj-dealer-section .card.lg .ct-r,
  .bj-split-active .card.lg .ct-r { font-size: 1.5rem; }
  .panel:has(.bj-split-active) #bj-dealer-section .card.lg .ct-s,
  .bj-split-active .card.lg .ct-s { font-size: 1.22rem; }
  .panel:has(.bj-split-active) #bj-dealer-section .card.lg .ct-r[data-r="10"],
  .bj-split-active .card.lg .ct-r[data-r="10"] { font-size: 1.16rem !important; }
  .panel:has(.bj-split-active) #bj-dealer-section .card.lg.back::before { font-size: 3.5rem; }
  .bj-split-active .hand-val { font-size: 1.95rem !important; }
  .bj-split-aside .card.sm { width: 54px; height: 76px; }
  .bj-split-aside .card.sm .csuit { font-size: 1.7rem; }
  .bj-split-aside .card.sm .ct-r { font-size: 0.95rem; }
  .panel:has(#uth-summary) #uth-summary { font-size: 1.5rem; margin: 4px 0 !important; }
  .panel:has(#uth-summary) .chip-row { gap: 10px; margin: 4px 0 12px; }
  .panel:has(#uth-summary) .chbtn { width: 70px; height: 70px; }
  .panel:has(#uth-summary) .chbtn > span { font-size: 1.3rem; }
  .panel:has(#uth-summary) .bet-amt span:last-child { font-size: 1.85rem; }
  /* Roomy desktop: grow the pay-table box into some of the slack (wider + larger text). */
  .panel:has(#uth-summary) .ptable { padding: 6px 16px; gap: 2px 20px; max-width: 340px; }
  .panel:has(#uth-summary) .pname { font-size: 1.1rem; }
  .panel:has(#uth-summary) .ppay  { font-size: 1.05rem; }

  /* BJ normal play: grow cards/UI on taller windows */
  .panel:has(#bj-player-hand) .card.lg { width: 104px; height: 146px; }
  .panel:has(#bj-player-hand) .card.lg .csuit { font-size: 4rem; }
  .panel:has(#bj-player-hand) .card.lg .ct-r { font-size: 1.6rem; }
  .panel:has(#bj-player-hand) .card.lg .ct-s { font-size: 1.3rem; }
  .panel:has(#bj-player-hand) .card.lg .ct-r[data-r="10"] { font-size: 1.25rem !important; }
  .panel:has(#bj-player-hand) .card.lg.back::before { font-size: 3.8rem; }
  .panel:has(#bj-player-hand) .sec { font-size: 1.5rem; }
  .panel:has(#bj-player-hand) .hand-val { font-size: 2.6rem; margin-top: 6px; }
  .panel:has(#bj-player-hand) #bj-dealer-section .hand-val { font-size: 2.4rem; }
  .panel:has(#bj-player-hand) .act-btn { font-size: 1.7rem; padding: 15px 14px; }

  /* BJ win result: grow cards on taller windows */
  .panel > div[style*="gap:16px"] .card.sm { width: 92px; height: 128px; }
  .panel > div[style*="gap:16px"] .card.sm .csuit { font-size: 3.4rem; }
  .panel > div[style*="gap:16px"] .card.sm .ct-r { font-size: 1.35rem; }
  .panel > div[style*="gap:16px"] .card.sm .ct-s { font-size: 1.1rem; }
  .panel > div[style*="gap:16px"] .card.sm .ct-r[data-r="10"] { font-size: 1.05rem !important; }
  .panel:has(> div[style*="gap:16px"]) .result-hl { font-size: 3rem; }
  .panel:has(> div[style*="gap:16px"]) .hand-val { font-size: 1.7rem !important; }

  /* BJ split result: grow cards on taller windows */
  .bj-sr-dealer .card.sm,
  .bj-sr-hands .card.sm { width: 59px; height: 83px; }
  .bj-sr-dealer .card.sm .csuit,
  .bj-sr-hands .card.sm .csuit { font-size: 1.52rem; }
  .bj-split-result .result-hl { font-size: 2.05rem !important; }
  .bj-split-result .result-sub { font-size: 1.42rem !important; }
  .bj-split-result:not(.sr-4) .result-hl { font-size: 2.5rem !important; }
  .bj-split-result:not(.sr-4) .result-sub { font-size: 1.75rem !important; }
  .bj-sr-dealer .hand-val,
  .bj-sr-hands .hand-val { font-size: 1.38rem !important; }
  .bj-sr-hands .sec { font-size: 1.08rem !important; }
  /* 2-/3-hand result splits: taller window, single row */
  .sr-2 .bj-sr-dealer .card.sm { width: 80px; height: 112px; }
  .sr-2 .bj-sr-hands .card.sm { width: 92px; height: 129px; }
  .sr-2 .card.sm .csuit { font-size: 2.2rem; }
  .sr-2 .hand-val { font-size: 1.9rem !important; }
  .sr-2 .bj-sr-hands .sec { font-size: 1.4rem !important; }
  .sr-3 .bj-sr-dealer .card.sm { width: 70px; height: 98px; }
  .sr-3 .bj-sr-hands .card.sm { width: 78px; height: 109px; }
  .sr-3 .card.sm .csuit { font-size: 1.9rem; }
  .sr-3 .hand-val { font-size: 1.7rem !important; }
  .sr-3 .bj-sr-hands .sec { font-size: 1.25rem !important; }

  /* Roulette result: grow the result number + outcome on taller windows */
  .panel:has(.r-res-num) .r-res-num { width: 124px; height: 124px; font-size: 3.1rem; }
  .panel:has(.r-res-num) .result-hl { font-size: 3rem; }
  .panel:has(.r-res-num) .result-sub { font-size: 1.8rem; }
  .panel:has(.r-res-num) .res-row,
  .panel:has(.r-res-num) .game-manifest > div { font-size: 1.15rem; }
  .panel:has(.r-res-num) .ik,
  .panel:has(.r-res-num) .iv { font-size: 1.3rem; }
  .panel:has(.r-res-num) .btn-gold { font-size: 1.6rem; padding: 14px 16px; }
  /* Roulette spin: wheel up to its native 300px (sharp); transient screen. */
  .panel:has(#rwheel) #rwheel { width: 300px; height: 300px; }

  /* Final results: scale up on taller windows. Open the gaps between the stacked elements so
     the group isn't cramped, and pay for it by shrinking the share box and trimming the chart
     margins (with the distribution chart shown the panel is nearly full, so this stays roughly
     height-neutral rather than overflowing). Result rows + chip number are kept compact here so
     the larger chart-to-share gap fits even with a long daily modifier (which wraps the share box). */
  .results-panel { gap: 6px !important; }
  .results-panel .big-chips { font-size: 4.4rem !important; }
  .results-panel .results-tier { font-size: 1.6rem; }
  .results-panel .results-streak { font-size: 2rem; margin: 4px 0 7px; }
  .results-panel .res-row { padding: 3px 16px !important; }
  .results-panel .res-row span:first-child,
  .results-panel .res-row .ik,
  .results-panel .res-row .iv { font-size: 1.25rem !important; }
  .results-panel .res-net { font-size: 1.45rem !important; }
  .results-panel .share-box { font-size: 0.98rem; padding: 6px 14px; line-height: 1.3; }
  .dist-bars { height: 42px; margin: 18px 4px 25px; }
  /* .dist-bars top margin is 18px here → re-center the title (see desktop base rule). */
  #dist-title { margin-top: 4px !important; margin-bottom: 5px !important; }

  /* UTH mid-hand (preflop/flop/turn): grow cards/UI to shrink the
     margin-auto gaps above the dealer and below the actions. */
  .panel:has(#uth-actions-ui) { gap: 4px; }
  /* gap:4px → banner_mb(5)+gap(4)+dots_mt = 11 → dots_mt = 2px (reset to standard) */
  .panel:has(#uth-actions-ui) .dots-row { margin-top: 2px; }
  .panel:has(#uth-actions-ui) .divider { margin: 3px 0; }
  .panel:has(#uth-actions-ui) .sec { font-size: 1.4rem; margin-bottom: 2px; }
  .panel:has(#uth-actions-ui) .card.md { width: 82px; height: 116px; }
  .panel:has(#uth-actions-ui) .card.sm { width: 62px; height: 88px; }
  .panel:has(#uth-actions-ui) .card.md .csuit { font-size: 2.8rem; }
  .panel:has(#uth-actions-ui) .card.sm .csuit { font-size: 2.05rem; }
  .panel:has(#uth-actions-ui) .card.md .ct-r { font-size: 1.25rem; }
  .panel:has(#uth-actions-ui) .card.md .ct-s { font-size: 1rem; }
  .panel:has(#uth-actions-ui) .card.sm .ct-r { font-size: 0.95rem; }
  .panel:has(#uth-actions-ui) .card.sm .ct-s { font-size: 0.8rem; }
  .panel:has(#uth-actions-ui) .card.md .ct-r[data-r="10"] { font-size: 1rem !important; }
  .panel:has(#uth-actions-ui) .card.sm .ct-r[data-r="10"] { font-size: 0.78rem !important; }
  .panel:has(#uth-actions-ui) .uth-bet-chips { margin: 5px 0 !important; gap: 12px !important; }
  .panel:has(#uth-actions-ui) .uth-bet-chip { padding: 6px 16px !important; }
  .panel:has(#uth-actions-ui) .uth-bet-chip > div:first-child { font-size: 0.92rem !important; }
  .panel:has(#uth-actions-ui) .uth-bet-chip > div:last-child { font-size: 1.8rem !important; }
  .panel:has(#uth-actions-ui) .act-btn,
  .panel:has(#uth-actions-ui) .btn-gold { padding: 12px 14px; font-size: 1.45rem; }

  /* UTH showdown result: grow cards on taller windows */
  .uth-result-panel .result-hl { font-size: 1.9rem; }
  .uth-result-panel .result-sub { font-size: 1.4rem; }
  .uth-result-panel .card.md { width: 68px; height: 96px; }
  .uth-result-panel .card.md .csuit { font-size: 2rem; }
  .uth-result-panel .card.md .ct-r { font-size: 1.05rem; }
  .uth-result-panel .card.md .ct-s { font-size: 0.88rem; }
  .uth-result-panel .card.md .ct-r[data-r="10"] { font-size: 0.88rem !important; }
  .uth-result-panel .card.sm { width: 58px; height: 82px; }
  .uth-result-panel .card.sm .csuit { font-size: 1.6rem; }
  .uth-result-panel .card.sm .ct-r { font-size: 0.95rem; }
  .uth-result-panel .card.sm .ct-s { font-size: 0.8rem; }
  .uth-result-panel .card.sm .ct-r[data-r="10"] { font-size: 0.8rem !important; }
  .uth-result-panel .sec { font-size: 1.05rem; }
  .uth-hand-name { font-size: 1.15rem !important; }
  .uth-result-panel .btn-gold { font-size: 1.4rem; padding: 10px 16px !important; }
}

/* ── Wider tall desktop (1280×880+): wider panel can fit larger chips. */
@media (min-width: 1280px) and (min-height: 880px) {
  /* Wide + tall: the program tiles have room to grow and still stay one line. */
  .intro-panel .gm-row { padding: 13px 18px; gap: 16px; }
  .intro-panel .rnd-ic { font-size: 1.8rem; }
  .intro-panel .rnd-nm { font-size: 2.1rem; }
  .intro-panel .rnd-dc { font-size: 1.5rem; }
  .panel:has(#uth-summary) .chbtn { width: 76px; height: 76px; }
  .panel:has(#uth-summary) .chbtn > span { font-size: 1.35rem; }
  .panel:has(#uth-summary) .chip-row { gap: 14px; margin: 4px 0 14px; }
  .panel:has(#uth-summary) #uth-summary { font-size: 1.6rem; margin: 6px 0 !important; }
  /* Tallest desktops have the most slack: grow the pay-table box a little more. */
  .panel:has(#uth-summary) .ptable { padding: 7px 18px; gap: 2px 22px; max-width: 360px; }
  .panel:has(#uth-summary) .pname { font-size: 1.15rem; }
  .panel:has(#uth-summary) .ppay  { font-size: 1.1rem; }
  /* 2-/3-hand result splits: wide window removes the narrow-panel width cap,
     so cards can grow larger than the 1024-tier value. */
  .sr-2 .bj-sr-dealer .card.sm { width: 92px; height: 129px; }
  .sr-2 .bj-sr-hands .card.sm { width: 104px; height: 146px; }
  .sr-2 .card.sm .csuit { font-size: 2.5rem; }
  .sr-2 .hand-val { font-size: 2rem !important; }
  .sr-3 .bj-sr-dealer .card.sm { width: 80px; height: 112px; }
  .sr-3 .bj-sr-hands .card.sm { width: 90px; height: 126px; }
  .sr-3 .card.sm .csuit { font-size: 2.2rem; }
  .sr-3 .hand-val { font-size: 1.85rem !important; }
}

/* ── Narrow-tall desktop (1024×1060+): fills the empty bands when the user
   has a tall but narrow window. Chip width can't grow here (1024 inner is
   576px), so we lean on font + padding scale-ups instead. */
@media (min-width: 1024px) and (min-height: 1060px) {
  :root { --btn-h: 52px; --btn-fs: 1.48rem; }
  /* Even more felt at 1080h+: push the intro elements larger still (tiles kept to a
     size that still fits the long Hold'em name on one line at the narrow 1024 width). */
  .intro-panel .logo { font-size: 6.6rem; }
  .intro-panel .logo-sub { font-size: 2.1rem; }
  .intro-lead { font-size: 2.6rem; }
  .intro-sub { font-size: 1.9rem; }
  .intro-prog-label { font-size: 1.8rem; }
  /* BJ normal play: narrow-but-tall window: hold card width back so a
     multi-card fan still fits the 1024 panel; lean on height + fonts. */
  .panel:has(#bj-player-hand) .card.lg { width: 118px; height: 168px; }
  .panel:has(#bj-player-hand) .card.lg .csuit { font-size: 4.5rem; }
  .panel:has(#bj-player-hand) .card.lg .ct-r { font-size: 1.8rem; }
  .panel:has(#bj-player-hand) .card.lg .ct-s { font-size: 1.46rem; }
  .panel:has(#bj-player-hand) .card.lg .ct-r[data-r="10"] { font-size: 1.4rem !important; }
  .panel:has(#bj-player-hand) .card.lg.back::before { font-size: 4.3rem; }
  /* Split play: ~250px of slack here; push the active hand close to normal-play
     size (118px width ceiling for fan fit), and enlarge the aside hands too. */
  .panel:has(.bj-split-active) #bj-dealer-section .card.lg,
  .bj-split-active .card.lg { width: 106px; height: 148px; }
  .panel:has(.bj-split-active) #bj-dealer-section .card.lg .csuit,
  .bj-split-active .card.lg .csuit { font-size: 3.9rem; }
  .panel:has(.bj-split-active) #bj-dealer-section .card.lg .ct-r,
  .bj-split-active .card.lg .ct-r { font-size: 1.6rem; }
  .panel:has(.bj-split-active) #bj-dealer-section .card.lg .ct-s,
  .bj-split-active .card.lg .ct-s { font-size: 1.28rem; }
  .panel:has(.bj-split-active) #bj-dealer-section .card.lg .ct-r[data-r="10"],
  .bj-split-active .card.lg .ct-r[data-r="10"] { font-size: 1.24rem !important; }
  .panel:has(.bj-split-active) #bj-dealer-section .card.lg.back::before { font-size: 3.7rem; }
  .bj-split-active .hand-val { font-size: 2.2rem !important; }
  .bj-split-aside .card.sm { width: 60px; height: 84px; }
  .bj-split-aside .card.sm .csuit { font-size: 1.9rem; }
  .bj-split-aside .card.sm .ct-r { font-size: 1.05rem; }
  .panel:has(#bj-player-hand) .hand-val { font-size: 3.1rem; }
  .panel:has(#bj-player-hand) .act-btn { font-size: 1.9rem; padding: 20px 14px; }

  /* BJ win result: narrow-tall: bigger cards, width held for the fan */
  .panel > div[style*="gap:16px"] .card.sm { width: 100px; height: 140px; }
  .panel > div[style*="gap:16px"] .card.sm .csuit { font-size: 3.7rem; }
  .panel > div[style*="gap:16px"] .card.sm .ct-r { font-size: 1.5rem; }
  .panel > div[style*="gap:16px"] .card.sm .ct-s { font-size: 1.2rem; }
  .panel > div[style*="gap:16px"] .card.sm .ct-r[data-r="10"] { font-size: 1.15rem !important; }
  .panel:has(> div[style*="gap:16px"]) .result-hl { font-size: 3.3rem; }
  .panel:has(> div[style*="gap:16px"]) .hand-val { font-size: 1.9rem !important; }

  /* BJ split result: narrow-tall */
  .bj-sr-dealer .card.sm,
  .bj-sr-hands .card.sm { width: 72px; height: 101px; }
  .bj-sr-dealer .card.sm .csuit,
  .bj-sr-hands .card.sm .csuit { font-size: 1.85rem; }
  .bj-split-result .result-hl { font-size: 2.3rem !important; }
  .bj-split-result:not(.sr-4) .result-hl { font-size: 2.8rem !important; }
  .bj-split-result:not(.sr-4) .result-sub { font-size: 2rem !important; }
  .bj-sr-dealer .hand-val,
  .bj-sr-hands .hand-val { font-size: 1.6rem !important; }
  .bj-sr-hands .sec { font-size: 1.25rem !important; }
  /* 2-/3-hand result splits: tallest tier. Width-capped by the narrow 1024 panel
     (2-hand = 50%, 3-hand = 33% of a 576px inner width). */
  .sr-2 .bj-sr-dealer .card.sm { width: 86px; height: 120px; }
  .sr-2 .bj-sr-hands .card.sm { width: 100px; height: 140px; }
  .sr-2 .card.sm .csuit { font-size: 2.5rem; }
  .sr-2 .hand-val { font-size: 2rem !important; }
  .sr-2 .bj-sr-hands .sec { font-size: 1.5rem !important; }
  .sr-3 .bj-sr-dealer .card.sm { width: 72px; height: 101px; }
  .sr-3 .bj-sr-hands .card.sm { width: 78px; height: 109px; }
  .sr-3 .card.sm .csuit { font-size: 2rem; }
  .sr-3 .hand-val { font-size: 1.8rem !important; }
  .sr-3 .bj-sr-hands .sec { font-size: 1.3rem !important; }

  /* Roulette result: tallest windows */
  .panel:has(.r-res-num) .r-res-num { width: 144px; height: 144px; font-size: 3.6rem; }
  .panel:has(.r-res-num) .result-hl { font-size: 3.3rem; }
  .panel:has(.r-res-num) .res-row,
  .panel:has(.r-res-num) .game-manifest > div { font-size: 1.3rem; }

  /* Final results: tallest windows. Slightly wider gaps; share box + chart margins trimmed
     to keep it from overflowing when the chart is present. Result-row padding stays modest so
     the chart's reserved top/bottom label margins fit (esp. the narrow-tall 1024×1080). */
  .results-panel { gap: 8px !important; }
  .results-panel .big-chips { font-size: 5.6rem !important; }
  .results-panel .results-tier { font-size: 1.85rem; }
  .results-panel .results-streak { font-size: 2.35rem; }
  .results-panel .res-row { padding: 5px 16px !important; }
  .results-panel .res-row span:first-child,
  .results-panel .res-row .ik,
  .results-panel .res-row .iv { font-size: 1.35rem !important; }
  .results-panel .res-net { font-size: 1.55rem !important; }
  .results-panel .share-box { font-size: 1.04rem; padding: 7px 14px; }
  .dist-bars { height: 50px; margin: 16px 4px 28px; }
  /* .dist-bars top margin is 16px here → re-center the title (see desktop base rule). */
  #dist-title { margin-top: 3px !important; margin-bottom: 6px !important; }

  .panel:has(#uth-summary) #uth-summary { font-size: 1.6rem; margin: 4px 0 !important; }
  .panel:has(#uth-summary) .chip-row { gap: 10px; margin: 4px 0 12px; }
  .panel:has(#uth-summary) #db { padding: 12px 18px; font-size: 1.5rem; margin-top: 2px !important; }
  .panel:has(.bj-bet-table) #db,
  .panel:has(#r-bets-zone) #db { margin-top: 2px !important; }  /* match UTH bet's bet->Deal gap + the play box->button gap so the box Y matches */
  .panel:has(#uth-summary) > .divider { margin: 8px 0; }
  .panel:has(.bj-bet-table) > .dots-row + .divider { margin-top: 8px; }  /* match UTH bet's dots->divider gap */
  .panel:has(#uth-summary) .ptable { padding: 6px 16px; gap: 2px 20px; max-width: 340px; }
  .panel:has(#uth-summary) .pname { font-size: 1.1rem; }
  .panel:has(#uth-summary) .ppay  { font-size: 1.05rem; }

  /* UTH mid-hand (preflop/flop/turn): largest cards/UI on the tallest windows */
  .panel:has(#uth-actions-ui) { gap: 6px; }
  /* gap:6px → banner_mb(5)+gap(6)+dots_mt = 11 → dots_mt = 0 */
  .panel:has(#uth-actions-ui) .dots-row { margin-top: 0; }
  .panel:has(#uth-actions-ui) .divider { margin: 5px 0; }
  .panel:has(#uth-actions-ui) .sec { font-size: 1.55rem; margin-bottom: 3px; }
  .panel:has(#uth-actions-ui) .card.md { width: 94px; height: 132px; }
  .panel:has(#uth-actions-ui) .card.sm { width: 72px; height: 100px; }
  .panel:has(#uth-actions-ui) .card.md .csuit { font-size: 3.2rem; }
  .panel:has(#uth-actions-ui) .card.sm .csuit { font-size: 2.4rem; }
  .panel:has(#uth-actions-ui) .card.md .ct-r { font-size: 1.45rem; }
  .panel:has(#uth-actions-ui) .card.md .ct-s { font-size: 1.15rem; }
  .panel:has(#uth-actions-ui) .card.sm .ct-r { font-size: 1.1rem; }
  .panel:has(#uth-actions-ui) .card.sm .ct-s { font-size: 0.92rem; }
  .panel:has(#uth-actions-ui) .card.md .ct-r[data-r="10"] { font-size: 1.15rem !important; }
  .panel:has(#uth-actions-ui) .card.sm .ct-r[data-r="10"] { font-size: 0.9rem !important; }
  .panel:has(#uth-actions-ui) .uth-bet-chips { margin: 8px 0 !important; gap: 14px !important; }
  .panel:has(#uth-actions-ui) .uth-bet-chip { padding: 9px 20px !important; }
  .panel:has(#uth-actions-ui) .uth-bet-chip > div:first-child { font-size: 1rem !important; }
  .panel:has(#uth-actions-ui) .uth-bet-chip > div:last-child { font-size: 2rem !important; }
  .panel:has(#uth-actions-ui) .act-btn,
  .panel:has(#uth-actions-ui) .btn-gold { padding: 15px 16px; font-size: 1.6rem; }

  /* UTH showdown result: largest cards on the tallest windows */
  .uth-result-panel { gap: 5px !important; }
  .uth-result-panel > .divider { margin: 4px 0; }
  .uth-result-panel .uth-cards-col { gap: 5px; }
  .uth-result-panel .uth-cards-col .divider { margin: 6px 0 !important; }
  .uth-result-panel .result-hl { font-size: 2.1rem; }
  .uth-result-panel .result-sub { font-size: 1.5rem; }
  .uth-result-panel .card.md { width: 78px; height: 110px; }
  .uth-result-panel .card.md .csuit { font-size: 2.4rem; }
  .uth-result-panel .card.md .ct-r { font-size: 1.15rem; }
  .uth-result-panel .card.md .ct-s { font-size: 0.95rem; }
  .uth-result-panel .card.md .ct-r[data-r="10"] { font-size: 0.95rem !important; }
  .uth-result-panel .card.sm { width: 64px; height: 90px; }
  .uth-result-panel .card.sm .csuit { font-size: 1.8rem; }
  .uth-result-panel .card.sm .ct-r { font-size: 1.05rem; }
  .uth-result-panel .card.sm .ct-s { font-size: 0.85rem; }
  .uth-result-panel .card.sm .ct-r[data-r="10"] { font-size: 0.85rem !important; }
  .uth-result-panel .sec { font-size: 1.15rem; }
  .uth-hand-name { font-size: 1.3rem !important; }
}

/* ── Tallest desktop (1280×1060+): fill remaining empty bands on UTH bet.
   Locked to min-width 1280 because the 82px chip row + larger ptable rows
   would not fit the 576px inner width of a 1024-wide panel. */
@media (min-width: 1280px) and (min-height: 1060px) {
  /* Widest + tallest: biggest one-line program tiles. */
  .intro-panel .gm-row { padding: 18px 22px; gap: 18px; }
  .intro-panel .rnd-ic { font-size: 2.1rem; }
  .intro-panel .rnd-nm { font-size: 2.5rem; }
  .intro-panel .rnd-dc { font-size: 1.7rem; }
  /* BJ normal play: wide + tall window has the room for the biggest cards. */
  .panel:has(#bj-player-hand) .card.lg { width: 132px; height: 186px; }
  .panel:has(#bj-player-hand) .card.lg .csuit { font-size: 5rem; }
  .panel:has(#bj-player-hand) .card.lg .ct-r { font-size: 2rem; }
  .panel:has(#bj-player-hand) .card.lg .ct-s { font-size: 1.6rem; }
  .panel:has(#bj-player-hand) .card.lg .ct-r[data-r="10"] { font-size: 1.55rem !important; }
  .panel:has(#bj-player-hand) .card.lg.back::before { font-size: 4.7rem; }
  .panel:has(#bj-player-hand) .hand-val { font-size: 3.3rem; }

  /* BJ win result: wide + tall: biggest cards */
  .panel > div[style*="gap:16px"] .card.sm { width: 112px; height: 156px; }
  .panel > div[style*="gap:16px"] .card.sm .csuit { font-size: 4.1rem; }
  .panel > div[style*="gap:16px"] .card.sm .ct-r { font-size: 1.65rem; }
  .panel > div[style*="gap:16px"] .card.sm .ct-s { font-size: 1.35rem; }
  .panel > div[style*="gap:16px"] .card.sm .ct-r[data-r="10"] { font-size: 1.25rem !important; }

  /* 2-/3-hand result splits: widest + tallest windows */
  .sr-2 .bj-sr-dealer .card.sm { width: 104px; height: 146px; }
  .sr-2 .bj-sr-hands .card.sm { width: 120px; height: 168px; }
  .sr-2 .card.sm .csuit { font-size: 2.9rem; }
  .sr-2 .hand-val { font-size: 2.3rem !important; }
  .sr-3 .bj-sr-dealer .card.sm { width: 90px; height: 126px; }
  .sr-3 .bj-sr-hands .card.sm { width: 100px; height: 140px; }
  .sr-3 .card.sm .csuit { font-size: 2.5rem; }
  .sr-3 .hand-val { font-size: 2rem !important; }

  .panel:has(#uth-summary) #uth-summary { font-size: 1.7rem; margin: 6px 0 !important; }
  .panel:has(#uth-summary) .chip-row { gap: 14px; margin: 4px 0 14px; }
  .panel:has(#uth-summary) .chbtn { width: 82px; height: 82px; }
  .panel:has(#uth-summary) .chbtn > span { font-size: 1.4rem; }
  .panel:has(#uth-summary) .bet-amt { padding: 8px 16px; }
  .panel:has(#uth-summary) .bet-amt span:last-child { font-size: 2rem; }
  .panel:has(#uth-summary) #db { padding: 12px 18px; font-size: 1.55rem; margin-top: 2px !important; }
  .panel:has(.bj-bet-table) #db,
  .panel:has(#r-bets-zone) #db { margin-top: 2px !important; }  /* match UTH bet's bet->Deal gap + the play box->button gap so the box Y matches */
  .panel:has(#uth-summary) > .divider { margin: 8px 0; }
  .panel:has(.bj-bet-table) > .dots-row + .divider { margin-top: 8px; }  /* match UTH bet's dots->divider gap */
  .panel:has(#uth-summary) .ptable { padding: 6px 16px; gap: 2px 20px; max-width: 360px; }
  .panel:has(#uth-summary) .pname { font-size: 1.1rem; }
  .panel:has(#uth-summary) .ppay  { font-size: 1.05rem; }
}

/* ── Large-display scaling ──────────────────────────────────────────────
   The window caps at ~880×960px, so on a 1440p/4K monitor it floats small
   on a sea of desktop. Zoom the whole app uniformly to fill more of the
   screen. `zoom` (unlike `transform: scale`) reflows cleanly and keeps
   fonts crisp + hit-areas correct. Gated on width AND height so a short-
   but-wide ultrawide (e.g. 3440×1440) can't zoom itself into vertical
   scroll: the capped 960px window × zoom must still fit the viewport.
   Note most 4K monitors run at 150% OS scaling → a 2560×1440 CSS viewport,
   which is exactly the first step. True 4K-at-100% hits the second.       */
@media (min-width: 2560px) and (min-height: 1400px) {
  .app { zoom: 1.25; }   /* 960px window → ~1200px, fits 1440px tall */
}
@media (min-width: 3840px) and (min-height: 2100px) {
  .app { zoom: 1.8; }    /* 960px window → ~1728px, fits 2160px tall */
}
