/* =============================================================================
   bust.fun — ROULETTE styles  (games/roulette/roulette.css) — the FEATURED table
   -----------------------------------------------------------------------------
   The featured multi-bet roulette: a real-felt board, a chip-denomination tray,
   magnetic chip stacks on board zones, the neon spin wheel, and a winning-number
   history strip. Synthwave tokens only (tokens.css) — no hard-coded palette except
   the few casino-chip accent colours (which are intentional product identity).
   a11y bar: 44px touch targets, 0 horizontal overflow at 360px, reduced-motion
   no-ops all motion. Responsive down to 1080×1920 portrait.
   ========================================================================== */

/* =============================================================================
   MODE TOGGLE — Solo | Live. The single, obvious switch between the two versions
   of the table. The selected pill glows; LIVE turns the felt accent warm so it is
   unmistakable which version you're in.
   ========================================================================== */
/* The Solo/Live mode toggle is now a gv-controls segmented({variant:'tab', twoLine}) tagged .roul-modebar.
   It uses the shared .gv-seg / .seg button.active chrome; this just keeps the framed-tray container + the
   distinctive GOLD Live tab (keyed off the active live option). */
.roul-modebar {
  margin-bottom: var(--sp-3); padding: 4px;
  background: var(--surface-2); border: 1px solid var(--line-2); border-radius: var(--r-lg);
}
.roul-modebar .gv-seg-btn[data-value="live"].active {
  color: var(--win-ink, #07130c);
  background: linear-gradient(180deg, var(--gold), var(--gold-grad-end));
  box-shadow: 0 0 18px var(--gold-glow);
}
/* Two-line Solo/Live sub-labels must NEVER clip in the narrow rail column ("our wheel, your pac").
   The shared .gv-seg-sub has no overflow handling; constrain it to the pill width and ellipsize as a
   belt-and-braces guard (the labels are also shortened in JS). max-width:100% + min-width:0 lets the
   flex pill shrink the text instead of letting it spill past the rounded edge. */
.roul-modebar .gv-seg-btn { min-width: 0; overflow: hidden; }
.roul-modebar .gv-seg-sub {
  max-width: 100%; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0;
}

/* ---- LIVE opt-in explainer (finding #3) ------------------------------------
   One line clarifying what Live means ("shared table, timed rounds"), shown ONLY when the Live tab is
   active. Solo is the default + self-paced, so it needs no caveat. The element stays in flow with the
   toggle in the rail; `.show` reveals it, the default state is collapsed so Solo shows no empty band. */
.roul-modenote {
  margin: 0 0 var(--sp-3); padding: 8px var(--sp-3);
  border: 1px solid rgba(255,216,107,.30); border-radius: var(--r-md);
  background: linear-gradient(180deg, rgba(255,216,107,.08), rgba(0,0,0,.14));
  color: var(--fg-dim); font-size: var(--fs-xs); line-height: 1.4;
}
.roul-modenote:not(.show) { display: none; }

/* ---- LIVE bar: connection + the betting-window countdown -------------------- */
/* CLS-STABLE: the bar's BOX is always reserved (fixed min-height, single row — no wrap), so toggling
   Solo↔Live never adds/removes a row that re-centres the wheel + felt. In Solo it's kept in flow but
   visually hidden (visibility:hidden), so the reserved height is identical whether it's shown or not. */
.roul-livebar {
  display: flex; align-items: center; gap: var(--sp-2); flex-wrap: nowrap;
  min-height: 42px; box-sizing: border-box;
  margin-bottom: var(--sp-3); padding: 8px var(--sp-3);
  background: linear-gradient(180deg, rgba(255,216,107,.10), rgba(0,0,0,.18));
  border: 1px solid rgba(255,216,107,.30); border-radius: var(--r-md);
}
/* Override the shared .hidden (display:none !important): keep the bar's BOX in flow (space reserved),
   but make its contents invisible + inert. The live tint stays so the reserved strip reads as part of
   the (idle, solo) chrome rather than an empty void. */
.roul-livebar.hidden { display: flex !important; visibility: hidden; pointer-events: none; }
.roul-conn { display: inline-flex; align-items: center; gap: 6px; font-size: var(--fs-xs); color: var(--fg-dim); }
.roul-conn-dot { width: 9px; height: 9px; border-radius: 50%; background: var(--fg-dim); box-shadow: 0 0 0 0 transparent; }
.roul-conn.online .roul-conn-dot { background: var(--win); box-shadow: 0 0 8px var(--win-glow); }
.roul-conn.connecting .roul-conn-dot { background: var(--gold); animation: roul-conn-pulse 1s var(--ease-out) infinite; }
.roul-conn.offline .roul-conn-dot { background: var(--lose, #ff6b6b); }
@keyframes roul-conn-pulse { 0%,100% { opacity: 1; } 50% { opacity: .35; } }
.roul-live-phase {
  flex: 1 1 auto; min-width: 0; font-family: var(--font-display); font-weight: var(--fw-semi);
  font-size: var(--fs-sm); color: var(--fg); letter-spacing: .02em;
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap;
}
/* DOUBLE-SECONDS FIX (baccarat report #4 pattern): the countdown seconds already render INSIDE the
   phase label ("Place your bets - 10.3s"); this separate gold figure showed the SAME "10.3" a second
   time in the same bar. The JS no longer writes the seconds here, and we hide the element so it reserves
   no width and the bar reads with the seconds exactly ONCE (in the labelled phase). */
.roul-live-count {
  display: none;
  font-family: var(--font-display); font-weight: var(--fw-bold); font-size: var(--fs-lg);
  font-variant-numeric: tabular-nums; color: var(--gold); min-width: 3ch; text-align: right;
}

/* ---- LIVE result banner (my settled outcome this round) --------------------- */
/* CLS FIX (baccarat report #5 pattern): the banner ("WIN · 1.95× · …" / "… You sat this one out.")
   used to be `display:none` when hidden and a flow block when shown, so every settle it APPEARED and
   shoved the live session stats below it DOWN ~46px (then the next round hid it and they jumped back UP).
   The banner sits at the TOP of the live panel, above the session block, so its appearance was that shift.
   Now we PRE-ALLOCATE a fixed slot: the box is ALWAYS in flow with a reserved min-height (one line of
   text), and `.hidden` only makes its CONTENT invisible + inert — the box (and the stats below it) never
   moves across idle → betting → result → idle. min-height = 1 line (fs-sm ≈ 1.5em) + 2×10px pad + 2×1px
   border, matching the shown one-line height exactly so show/hide never shifts the panel. */
.roul-live-banner {
  box-sizing: border-box; min-height: calc(1.5em + 20px + 2px);
  margin-bottom: var(--sp-3); padding: 10px var(--sp-3); border-radius: var(--r-md);
  font-family: var(--font-display); font-weight: var(--fw-semi); font-size: var(--fs-sm);
  border: 1px solid var(--line-2); background: var(--surface-2); color: var(--fg);
}
/* hidden = reserved-but-invisible: keep the box (and its reserved min-height) IN FLOW so the stats below
   never shift, but make it fully invisible + inert. The global `.hidden { display:none !important }`
   utility would otherwise pull the box out of flow — we override it with our own `!important` (same trick
   as .roul-livebar.hidden) so the slot stays reserved; `visibility:hidden` hides the content/tint/border. */
.roul-live-banner.hidden { display: block !important; visibility: hidden; pointer-events: none; }
.roul-live-banner.win { border-color: var(--win); background: linear-gradient(180deg, rgba(46,213,115,.18), rgba(0,0,0,.2)); box-shadow: inset 0 0 0 1px var(--win), 0 0 16px var(--win-glow); }
.roul-live-banner.loss { border-color: var(--lose, #ff6b6b); background: linear-gradient(180deg, rgba(255,107,107,.14), rgba(0,0,0,.2)); }
.roul-live-banner.flat { color: var(--fg-dim); }

/* the live "24/7" pill on the live stats title */
.roul-live-tag {
  display: inline-flex; align-items: center; padding: 2px 8px; border-radius: var(--r-pill);
  font-family: var(--font-display); font-weight: var(--fw-bold); font-size: 10px; letter-spacing: .08em;
  color: var(--win-ink, #07130c); background: linear-gradient(180deg, var(--gold), var(--gold-grad-end));
  box-shadow: 0 0 10px var(--gold-glow);
}
.roul-live.hidden { display: none; }
/* LIVE surface tint: warm the felt edge so the live version reads differently from solo */
.roul-is-live .roul-felt { box-shadow: var(--shadow-2), inset 0 0 60px rgba(0,0,0,.35), 0 0 0 1px rgba(255,216,107,.25); }

/* ---- winning-number history strip ------------------------------------------ */
/* CLS-STABLE: a SINGLE-ROW fixed-height band. Newest is prepended (stays at the left edge); the row
   never wraps to a 2nd line, so the wheel + felt below it never get re-centred on a spin. The oldest
   pills clip off the right end via overflow-x:hidden — a clean horizontal clip, no vertical growth ever.
   (Was flex-wrap:wrap + min-height:28px, which wrapped to a 2nd ~28px row almost every spin.) */
.roul-history {
  display: flex; flex-wrap: nowrap; gap: 6px; height: 28px; overflow-x: hidden;
  margin-bottom: var(--sp-3); justify-content: flex-start;
}
.roul-hist-pill {
  display: inline-flex; align-items: center; justify-content: center;
  flex: 0 0 auto;       /* keep full size in the nowrap row so it clips cleanly (never squished) */
  min-width: 26px; height: 26px; padding: 0 6px; border-radius: var(--r-pill);
  font-family: var(--font-display); font-weight: var(--fw-bold); font-size: var(--fs-xs);
  font-variant-numeric: tabular-nums; color: #fff; border: 1px solid var(--line-2);
  animation: roul-hist-in var(--dur-2) var(--ease-out);
}
@keyframes roul-hist-in { from { transform: scale(.4); opacity: 0; } to { transform: scale(1); opacity: 1; } }
.roul-h-red   { background: linear-gradient(180deg, #cc2030, #9e1822); }
.roul-h-black { background: linear-gradient(180deg, #24244a, #141428); }
.roul-h-green { background: linear-gradient(180deg, var(--win), var(--win-2)); color: var(--win-ink); }

/* ---- wheel stage (the centrepiece) ----------------------------------------- */
/* DESKTOP: a centred row — the wheel (left) sits beside the racetrack/call-bets strip (right).
   align-items:center (NOT the flex default `stretch`) is LOAD-BEARING: the wheel-wrap declares
   aspect-ratio:1/1 with a width but no explicit height; under `stretch` the taller racetrack gives
   the row a definite height that the wheel then stretches to fill, squashing it into a vertical
   ellipse (the 200×287 wheel the audit saw @360px). Centering lets aspect-ratio keep it a circle. */
.roul-stage { display: flex; align-items: center; justify-content: center; gap: var(--sp-4); padding: var(--sp-2) 0 var(--sp-6); }
/* Lift the shared styles.css `.gameview-display .roul-stage { max-width: 520px }` cap so the
   stage can be full column width (the WRAP below carries the real circle cap). Matches that
   rule's specificity and loads after it (game CSS is linked after styles.css), so it wins on
   source order — no styles.css edit. The stage stays centred; the wheel cap lives on .roul-wheel-wrap. */
.gameview-display .roul-stage { max-width: none; width: 100%; margin-inline: auto; }
/* SIZE-TO-FILL: the spin wheel is the centrepiece, so it grows to the BIGGEST centred
   circle that fits the room above the felt board. The square side = min(available width,
   a viewport-height budget) via `width: min(100%, <budget>)` + aspect-ratio 1/1 — driven
   by BOTH axes so it stays a true circle and never forces page scroll. Roulette (unlike
   the wheel game) has a full felt board + tray + actions below the wheel, so the height
   budget is larger (~520px reserves room for that chrome) and the wheel is width-bound on
   most laptops — but it now fills the column width instead of the old 300px cap. The
   canvas backing store re-measures this live box (roulette.fx.js sizeCanvas + ResizeObserver,
   DPR-aware) and redraws crisply at any size; an in-flight spin re-measures itself. */
.roul-wheel-wrap {
  position: relative; flex: 0 0 auto; align-self: center;
  width: min(100%, calc(100vh - 520px), 78vw);
  min-width: 200px; max-width: 560px; aspect-ratio: 1 / 1;
}
/* Narrow / portrait: STACK the wheel above the racetrack (a column) so the wheel owns the full
   column width and is never co-constrained by the taller call-bets strip in a row. Width-bound +
   aspect-ratio:1/1 + align-self:center keep it a TRUE circle (not the prior 200×287 ellipse), with
   0 horizontal overflow at 360px (capped at 78vw so it never bleeds edge-to-edge). */
@media (max-width: 760px) {
  .roul-stage { flex-direction: column; gap: var(--sp-3); }
  .roul-wheel-wrap { width: min(78vw, 100%); }
}
.roul-wheel-canvas { display: block; width: 100%; height: 100%; filter: drop-shadow(0 8px 28px rgba(0,0,0,.5)); }
.roul-wheel-wrap::before {
  content: ""; position: absolute; top: -2px; left: 50%; transform: translateX(-50%);
  width: 0; height: 0; z-index: var(--z-raised);
  border-left: 9px solid transparent; border-right: 9px solid transparent;
  border-top: 14px solid var(--gold);
  filter: drop-shadow(0 0 6px var(--gold-glow));
}
.roul-wheel-fallback {
  position: absolute; inset: 8%; z-index: -1; border-radius: 50%;
  border: 2px solid var(--line-2);
  background: radial-gradient(circle at 50% 38%, var(--surface-3), var(--surface) 70%);
}

/* the landed-pocket result chip (announced; revealed AFTER the ball lands) */
.roul-chip {
  position: absolute; left: 0; right: 0; bottom: -24px;
  margin-inline: auto; width: max-content;
  display: inline-flex; align-items: center; gap: var(--sp-2);
  padding: 8px 14px; border-radius: var(--r-pill);
  background: var(--surface-3); border: 1px solid var(--line-2);
  box-shadow: var(--shadow-2); z-index: var(--z-raised);
  max-width: 100%; box-sizing: border-box;
}
.roul-chip.hidden { display: none; }
.roul-chip-num {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 30px; height: 30px; padding: 0 8px; border-radius: var(--r-pill);
  font-family: var(--font-display); font-weight: var(--fw-bold); font-size: var(--fs-lg);
  font-variant-numeric: tabular-nums; color: #fff;
}
.roul-chip-text {
  font-size: var(--fs-xs); font-weight: var(--fw-semi); letter-spacing: .04em;
  text-transform: uppercase; color: var(--fg-dim);
  overflow: hidden; text-overflow: ellipsis; white-space: nowrap; min-width: 0;
}
/* The payout figure — its own span so it can COUNT UP (fx.numberRamp). tabular-nums keeps the ramp
   from jittering the chip width frame-to-frame. Tokens only. */
.roul-chip-pay {
  font-size: var(--fs-xs); font-weight: var(--fw-bold); letter-spacing: .04em;
  text-transform: uppercase; color: var(--fg-dim);
  font-variant-numeric: tabular-nums; white-space: nowrap; flex: 0 0 auto;
}
/* P14a — the chip figure is now the SIGNED PROFIT ("+$X" / "−$X"), so tint it by outcome via the persistent
   .roul-chip-win / .roul-chip-loss classes set in _commitVerdict (NOT the transient self-removing .fx-win
   pulse): a WIN reads green, a LOSS reads rose. A push keeps the neutral --fg-dim above. Tokens only. */
.roul-chip.roul-chip-win  .roul-chip-pay { color: var(--win); }
.roul-chip.roul-chip-loss .roul-chip-pay { color: var(--lose); }
.roul-chip-red   .roul-chip-num { background: #cc2030; box-shadow: 0 0 16px var(--lose-glow); }
.roul-chip-black .roul-chip-num { background: #15152b; box-shadow: inset 0 0 0 1px var(--line-2); }
.roul-chip-green .roul-chip-num { background: var(--win); color: var(--win-ink); box-shadow: 0 0 16px var(--win-glow); }

/* =============================================================================
   THE FELT BOARD — 0 + 3×12 grid + columns + dozens + even-money outside
   Grid layout: a CSS grid where the zero column, the 12 number columns, and the
   2:1 column share rows; dozens + outside rows span beneath.
   ========================================================================== */
.roul-felt {
  --felt-1: #0f5132; --felt-2: #0a3a24;        /* real casino felt green */
  background:
    radial-gradient(ellipse at 50% 0%, rgba(255,255,255,.06), transparent 60%),
    linear-gradient(160deg, var(--felt-1), var(--felt-2));
  border: 1px solid rgba(255,255,255,.10);
  border-radius: var(--r-lg);
  padding: var(--sp-2);
  box-shadow: var(--shadow-2), inset 0 0 60px rgba(0,0,0,.35);
  display: grid;
  grid-template-columns: 0.7fr repeat(12, 1fr) 0.7fr;
  grid-template-rows: repeat(3, 1fr) auto auto;
  gap: 4px;
  margin: var(--sp-2) 0 var(--sp-3);
  max-width: 100%;
  position: relative; /* anchors the first-run coachmark overlay (.roul-coach) without affecting the grid */
}

/* =============================================================================
   FIRST-RUN COACHMARK (finding #1) — "Pick a chip, then tap the board." Overlays the felt so it NEVER
   shifts the board (no CLS): position:absolute, out of grid flow, shown only via `.show`. The LAYER ignores
   pointer events so the very first tap-to-place falls THROUGH to the board underneath (and auto-dismisses
   it); only the "Got it" button takes a click. Tokens only; reduced-motion no-ops the entrance.
   ========================================================================== */
.roul-coach {
  position: absolute; inset: 0; z-index: 8;
  display: none; align-items: center; justify-content: center;
  padding: var(--sp-3); pointer-events: none;
  background: radial-gradient(ellipse at 50% 45%, rgba(0,0,0,.55), rgba(0,0,0,.32));
  border-radius: var(--r-lg);
}
.roul-coach.show { display: flex; animation: roul-coach-in var(--dur-2) var(--ease-out); }
.roul-coach-card {
  pointer-events: auto; max-width: 320px; box-sizing: border-box;
  display: flex; flex-direction: column; gap: var(--sp-2); text-align: center;
  padding: var(--sp-4); border-radius: var(--r-lg);
  background: var(--surface-3); border: 1px solid var(--gold);
  box-shadow: var(--shadow-2), 0 0 22px var(--gold-glow);
}
.roul-coach-title {
  font-family: var(--font-display); font-weight: var(--fw-bold); font-size: var(--fs-md);
  letter-spacing: .02em; color: var(--gold);
}
.roul-coach-body { font-size: var(--fs-sm); line-height: 1.45; color: var(--fg); }
.roul-coach-dismiss {
  align-self: center; appearance: none; cursor: pointer; min-height: var(--touch);
  margin-top: var(--sp-1); padding: 8px 22px; border-radius: var(--r-pill);
  color: var(--brand-ink); background: var(--brand); border: 1px solid transparent;
  font-family: var(--font-display); font-weight: var(--fw-semi); font-size: var(--fs-sm);
  box-shadow: var(--glow-brand);
  transition: filter var(--dur-1) var(--ease-out), transform var(--dur-1);
}
.roul-coach-dismiss:hover { filter: brightness(1.08); }
.roul-coach-dismiss:active { transform: scale(.97); }
.roul-coach-dismiss:focus-visible { outline: 2px solid var(--violet); outline-offset: 2px; box-shadow: var(--ring); }
@keyframes roul-coach-in { from { opacity: 0; } to { opacity: 1; } }
/* zero spans all 3 number rows in the first column */
.roul-zero { grid-column: 1; grid-row: 1 / 4; }
/* the 3×12 number grid occupies columns 2..13, rows 1..3 */
.roul-grid {
  grid-column: 2 / 14; grid-row: 1 / 4;
  display: grid; grid-template-columns: repeat(12, 1fr); grid-template-rows: repeat(3, 1fr); gap: 4px;
  position: relative; /* anchors the absolutely-positioned INSIDE-bet overlay (.roul-inside) */
}
/* the 2:1 column zones in the last column */
.roul-cols { grid-column: 14; grid-row: 1 / 4; display: grid; grid-template-rows: repeat(3, 1fr); gap: 4px; }
/* dozens span the number columns beneath the grid */
.roul-dozens { grid-column: 2 / 14; grid-row: 4; display: grid; grid-template-columns: repeat(3, 1fr); gap: 4px; }
/* even-money outside row spans the same width */
.roul-outs { grid-column: 2 / 14; grid-row: 5; display: grid; grid-template-columns: repeat(6, 1fr); gap: 4px; }

/* a board zone (chip target) */
.roul-cell {
  position: relative; appearance: none; cursor: pointer;
  display: flex; align-items: center; justify-content: center;
  min-height: 38px; padding: 2px; border-radius: var(--r-sm);
  border: 1px solid rgba(255,255,255,.16);
  color: #fff; font-family: var(--font-display); font-weight: var(--fw-bold);
  font-variant-numeric: tabular-nums;
  transition: transform var(--dur-1) var(--ease-out), box-shadow var(--dur-2), filter var(--dur-1);
}
.roul-cell-label { font-size: var(--fs-sm); line-height: 1; pointer-events: none; }
.roul-cell:hover { transform: translateY(-1px); filter: brightness(1.14); box-shadow: 0 0 0 1px rgba(255,255,255,.35); z-index: 2; }
.roul-cell:active { transform: scale(.97); }
.roul-cell:focus-visible { outline: 2px solid var(--violet); outline-offset: 1px; box-shadow: var(--ring); z-index: 3; }

/* number colours (deepened red so white labels clear AA) */
.roul-c-red   { background: linear-gradient(180deg, #cc2030, #a8121f); }
.roul-c-black { background: linear-gradient(180deg, #1d1d3a, #101024); }
.roul-c-green { background: linear-gradient(180deg, var(--win), var(--win-2)); color: var(--win-ink); }
.roul-zero .roul-cell-label { font-size: var(--fs-lg); }

/* outside / column / dozen zones share a felt-tinted look */
.roul-outside, .roul-side {
  background: linear-gradient(180deg, rgba(255,255,255,.10), rgba(0,0,0,.18));
  min-height: 40px; letter-spacing: .03em; font-size: var(--fs-xs); text-transform: uppercase;
}
.roul-side .roul-cell-label { font-size: var(--fs-sm); }
.roul-sw-red   { background: linear-gradient(180deg, #cc2030, #a8121f); }
.roul-sw-black { background: linear-gradient(180deg, #20203f, #101024); }

/* a zone carrying chips gets a subtle gold inset ring */
.roul-cell.has-chips { box-shadow: inset 0 0 0 2px var(--gold), 0 0 14px rgba(0,0,0,.4); }

/* the winning-pocket flash + winning-bet zones (revealed on settle, server-authoritative) */
.roul-cell.win-pocket { box-shadow: 0 0 0 3px var(--gold), 0 0 22px var(--gold-glow); z-index: 4; animation: roul-winpulse 1.2s var(--ease-out) 2; }
.roul-cell.win-flash  { box-shadow: inset 0 0 0 2px var(--win), 0 0 18px var(--win-glow); z-index: 3; }
@keyframes roul-winpulse { 0%,100% { filter: brightness(1.1); } 50% { filter: brightness(1.6); } }

/* =============================================================================
   INSIDE-bet hit-zones — split / street / corner / six-line, overlaid on the grid
   on the TRUE shared line/intersection (positioned by JS from the cell rects). The
   layer itself ignores pointer events; only the zone buttons take taps, so a tap on
   a cell CENTRE still places the straight underneath.
   ========================================================================== */
.roul-inside { position: absolute; inset: 0; pointer-events: none; z-index: 6; }
.roul-ins {
  position: absolute; appearance: none; cursor: pointer; pointer-events: auto;
  /* override the global button baseline (min-height 44 / padding / brand bg) — JS sets exact w/h */
  min-height: 0; padding: 0; border: 0; overflow: visible;
  background: transparent; border-radius: var(--r-pill); box-shadow: none;
  transition: box-shadow var(--dur-1) var(--ease-out), background var(--dur-1);
}
.roul-ins:hover { filter: none; box-shadow: none; }
.roul-ins:active { transform: none; }
.roul-ins::before {
  content: ""; position: absolute; inset: 35%; border-radius: var(--r-pill);
  background: rgba(255,255,255,.0); transition: background var(--dur-1), inset var(--dur-1);
}
.roul-ins:hover::before { inset: 18%; background: rgba(255,255,255,.30); box-shadow: 0 0 8px rgba(255,255,255,.35); }
.roul-ins:focus-visible { outline: 2px solid var(--violet); outline-offset: 1px; box-shadow: var(--ring); z-index: 12; }
/* z-order: corners (points) sit ABOVE line bets, so any residual overlap resolves to the more specific bet */
.roul-ins-split, .roul-ins-street, .roul-ins-sixline { z-index: 1; }
.roul-ins-corner { z-index: 3; }
.roul-ins.has-chips { z-index: 10; }
.roul-ins.has-chips::before { background: transparent; }
/* the inside chip stack centres on the line/point */
.roul-ins .roul-stack { z-index: 9; }
.roul-ins.has-chips .roul-stack-disc { box-shadow: 0 3px 7px rgba(0,0,0,.6), inset 0 0 0 2px rgba(0,0,0,.2); }
/* inside winners flash like cells */
.roul-ins.win-flash::before { inset: 18%; background: var(--win); box-shadow: 0 0 16px var(--win-glow); }

/* ---- the magnetic chip stack on a zone -------------------------------------- */
.roul-stack {
  position: absolute; inset: 0; display: none; align-items: center; justify-content: center;
  pointer-events: none; z-index: 5;
}
.roul-stack.show { display: flex; }
.roul-stack-disc {
  position: relative; display: inline-flex; align-items: center; justify-content: center;
  /* TRUE CIRCLE: a FIXED square (not min-width + horizontal padding). Previously the disc grew in WIDTH to fit
     the amount text while the height stayed fixed, so a longer value (esp. after the 2-decimal money change:
     "$1" -> "$1.00") turned the 50%-radius box into a stretched OVAL. Fixed w==h + aspect-ratio + overflow keep
     it a circle for any value; the compact chip label (chipDenom, JS) keeps the figure fitting inside. */
  width: 30px; height: 30px; flex: none; aspect-ratio: 1 / 1; padding: 0; overflow: hidden; border-radius: 50%;
  border: 2px dashed rgba(255,255,255,.85);
  font-family: var(--font-display); font-weight: var(--fw-bold); font-size: 9px;
  color: #fff; text-shadow: 0 1px 2px rgba(0,0,0,.6);
  box-shadow: 0 3px 6px rgba(0,0,0,.5), inset 0 0 0 2px rgba(0,0,0,.18),
              /* the "neat offset stack" look — a couple of discs underneath */
              0 2px 0 -1px rgba(0,0,0,.4), 2px 4px 0 -2px rgba(255,255,255,.25);
}
.roul-stack-amt { white-space: nowrap; font-variant-numeric: tabular-nums; }
/* magnetic drop: snap in from above + settle */
.roul-stack-disc.drop { animation: roul-chip-drop 320ms var(--ease-out); }
@keyframes roul-chip-drop {
  0% { transform: translateY(-22px) scale(1.25); opacity: 0; }
  60% { transform: translateY(2px) scale(.94); opacity: 1; }
  100% { transform: translateY(0) scale(1); opacity: 1; }
}

/* chip denomination colours (shared by tray + stack discs) */
.c-5c   { background: radial-gradient(circle at 38% 32%, #f4f4f4, #c9ccd2); color: #1a1a1a; text-shadow: none; }
.c-25c  { background: radial-gradient(circle at 38% 32%, #5bd6a0, #189c66); }
.c-1    { background: radial-gradient(circle at 38% 32%, #6aa6ff, #2563c9); }
.c-5    { background: radial-gradient(circle at 38% 32%, #ff6b6b, #c0222f); }
.c-25   { background: radial-gradient(circle at 38% 32%, #b78bff, #7a3ce0); }
.c-100  { background: radial-gradient(circle at 38% 32%, #ffd86b, var(--gold-grad-end)); color: #2a1c00; text-shadow: none; }
.c-500  { background: radial-gradient(circle at 38% 32%, #ff7ad9, #b81f96); }                              /* magenta */
.c-1000 { background: radial-gradient(circle at 38% 32%, #4a4a68, #131320); color: #ffd86b; }             /* black + gold, high-roller */

/* ---- the chip tray --------------------------------------------------------- */
.roul-tray {
  display: flex; flex-wrap: wrap; gap: var(--sp-2); justify-content: center;
  margin: var(--sp-2) 0;
}
.roul-trchip {
  appearance: none; cursor: pointer; position: relative;
  width: 52px; height: 52px; border-radius: 50%;
  border: 3px dashed rgba(255,255,255,.85);
  display: inline-flex; align-items: center; justify-content: center;
  font-family: var(--font-display); font-weight: var(--fw-bold); font-size: var(--fs-sm);
  color: #fff; text-shadow: 0 1px 2px rgba(0,0,0,.5);
  box-shadow: 0 4px 10px rgba(0,0,0,.45), inset 0 0 0 2px rgba(0,0,0,.18);
  transition: transform var(--dur-1) var(--ease-out), box-shadow var(--dur-2), filter var(--dur-1);
}
.roul-trchip-face { pointer-events: none; }
.roul-trchip:hover { transform: translateY(-2px); filter: brightness(1.08); }
.roul-trchip:active { transform: scale(.94); }
.roul-trchip:focus-visible { outline: 2px solid var(--violet); outline-offset: 3px; box-shadow: var(--ring); }
.roul-trchip.sel { transform: translateY(-3px) scale(1.06); box-shadow: 0 0 0 3px var(--gold), 0 0 18px var(--gold-glow); }

/* ---- action buttons (Spin / 2× / ½ / Undo / Clear / Replay) ----------------- */
.roul-actions {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: var(--sp-2);
  margin: var(--sp-2) 0 var(--sp-3);
  /* P2-01 (a11y): the action row is now placed BEFORE the felt board in the DOM so #roulSpin leads the tab
     order (reachable within a few Tabs instead of behind the 0-36 grid + 100+ inside-bet cells). `order:10`
     keeps it rendered LAST in the display flex column — visual layout unchanged, tab order fixed. */
  order: 10;
}

/* PROMINENT, CO-VISIBLE total readout (findings #1 + #2): roulette has no typed stake — the summed Total IS
   the headline number — so it sits full-width directly above Spin. On mobile this row is the sticky action
   cluster, so Total + Spin stay together under the thumb. The figure lifts (brand-ink) once chips are down. */
.roul-totalbar {
  grid-column: 1 / -1;
  display: flex; align-items: baseline; justify-content: space-between; gap: var(--sp-2);
  padding: 8px var(--sp-3); border-radius: var(--r-md);
  background: linear-gradient(180deg, rgba(255,255,255,.05), rgba(0,0,0,.16));
  border: 1px solid var(--line-2);
}
.roul-totalbar-k {
  font-size: 10px; letter-spacing: .08em; text-transform: uppercase; color: var(--fg-dim);
}
.roul-totalbar-v {
  font-family: var(--font-display); font-weight: var(--fw-bold); font-size: var(--fs-xl);
  font-variant-numeric: tabular-nums; color: var(--fg-dim); letter-spacing: .01em;
}
.roul-totalbar-v.is-set { color: var(--gold); text-shadow: 0 0 12px var(--gold-glow); }

/* Rail "Total bet" prominence (finding #1): in the gv-controls preview the typed-stake games show a small
   pair of stats; for roulette the Total bet is the primary readout, so step its figure up to match Max win. */
.roul-preview #roulTotal { font-size: var(--fs-lg); color: var(--fg); }
.roul-act {
  appearance: none; cursor: pointer; min-height: var(--touch);
  padding: 10px 12px; border-radius: var(--r-md);
  background: var(--surface-2); border: 1px solid var(--line-2);
  color: var(--fg); font-family: var(--font-display); font-weight: var(--fw-semi); font-size: var(--fs-sm);
  transition: color var(--dur-1), background var(--dur-1), border-color var(--dur-1), box-shadow var(--dur-2), transform var(--dur-1);
}
.roul-act:hover:not(:disabled) { background: var(--surface-3); border-color: var(--line-3); }
.roul-act:active:not(:disabled) { transform: scale(.97); }
.roul-act:focus-visible { outline: 2px solid var(--violet); outline-offset: 2px; box-shadow: var(--ring); }
.roul-act:disabled { opacity: .45; cursor: not-allowed; }
/* Spin is the headline action — span the full row, brand-glowing */
.roul-act-spin {
  grid-column: 1 / -1; min-height: 52px; font-size: var(--fs-md);
  color: var(--brand-ink); background: var(--brand); border-color: transparent;
  box-shadow: var(--glow-brand);
}
.roul-act-spin:hover:not(:disabled) { filter: brightness(1.08); background: var(--brand); }
.roul-act-spin.loading { opacity: .7; cursor: progress; }
/* LIVE-bet CANCEL — full-row, destructive tone; shown only after a live bet is in (toggled by JS). */
.roul-act-cancel { grid-column: 1 / -1; color: var(--lose, #ff6b6b); border-color: var(--lose, #ff6b6b); }
.roul-act-cancel:hover:not(:disabled) { filter: brightness(1.12); }
.roul-act-cancel.loading { opacity: .7; cursor: progress; }
/* SOLO (default): the Cancel never applies, so it's fully out of flow — no reserved void in the
   common mode. */
.roul-act-cancel.hidden { display: none; }
/* LIVE: reserve the Cancel's full-width grid cell PERMANENTLY (it's in flow, occupying its row) and
   only toggle its visibility. So when a live bet goes in / the window locks, the Cancel appears/clears
   WITHOUT adding or removing an action-grid row — the wheel + felt above never get re-centred. The
   reserved cell is keyed to live mode (.roul-is-live) so solo stays void-free. */
.roul-is-live .roul-act-cancel.hidden { display: block !important; visibility: hidden; pointer-events: none; }

/* =============================================================================
   SOLO SESSION STATS — scoped to THIS session (not a 24/7 live feed). Display-only
   history: counts, recent strip, even-money split bars, hot/cold, + the session net.
   ========================================================================== */
.roul-session {
  margin: var(--sp-3) 0 var(--sp-2);
  background: linear-gradient(180deg, rgba(255,255,255,.04), rgba(0,0,0,.18));
  border: 1px solid var(--line-2); border-radius: var(--r-lg);
  padding: var(--sp-3); box-shadow: var(--shadow-1), inset 0 0 30px rgba(0,0,0,.2);
}
.roul-sess-head { display: flex; align-items: center; justify-content: space-between; gap: var(--sp-2); margin-bottom: var(--sp-2); }
.roul-sess-title {
  margin: 0; font-family: var(--font-display); font-weight: var(--fw-bold); font-size: var(--fs-md);
  letter-spacing: .02em; color: var(--fg);
}
.roul-sess-new { min-height: 38px; padding: 8px 14px; }
.roul-sess-sublabel {
  display: block; font-size: 10px; letter-spacing: .08em; text-transform: uppercase;
  color: var(--fg-dim); margin-bottom: 4px;
}

/* top stats: spins + net */
.roul-sess-top { display: grid; grid-template-columns: 1fr 1fr; gap: var(--sp-2); margin-bottom: var(--sp-3); }
.roul-sess-stat {
  background: var(--surface-2); border: 1px solid var(--line-2); border-radius: var(--r-md);
  padding: var(--sp-2) var(--sp-3);
}
.roul-sess-stat .k { display: block; font-size: 10px; letter-spacing: .08em; text-transform: uppercase; color: var(--fg-dim); }
.roul-sess-stat b { font-family: var(--font-display); font-size: var(--fs-lg); font-variant-numeric: tabular-nums; color: var(--fg); }
.roul-sess-net.is-pos { color: var(--win); }
.roul-sess-net.is-neg { color: var(--lose, #ff6b6b); }

/* recent strip */
.roul-sess-stripwrap { margin-bottom: var(--sp-3); }
.roul-sess-strip { display: flex; flex-wrap: wrap; gap: 5px; min-height: 24px; }
.roul-sess-pill {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 22px; height: 22px; padding: 0 5px; border-radius: var(--r-pill);
  font-family: var(--font-display); font-weight: var(--fw-bold); font-size: 10px;
  font-variant-numeric: tabular-nums; color: #fff; border: 1px solid var(--line-2);
}
.roul-sess-empty { color: var(--fg-dim); font-size: var(--fs-xs); }

/* even-money split bars */
.roul-sess-bars { display: grid; gap: var(--sp-2); margin-bottom: var(--sp-3); }
.roul-sess-track {
  display: flex; height: 22px; border-radius: var(--r-pill); overflow: hidden;
  border: 1px solid var(--line-2); background: var(--surface-2);
}
.roul-sess-seg {
  display: flex; align-items: center; justify-content: center; min-width: 0;
  transition: width var(--dur-3) var(--ease-out);
}
.roul-sess-segtxt {
  font-size: 10px; font-weight: var(--fw-bold); letter-spacing: .03em; color: #fff;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis; padding: 0 4px;
  text-shadow: 0 1px 2px rgba(0,0,0,.6);
}
.roul-sess-seg.sg-red   { background: linear-gradient(180deg, #cc2030, #9e1822); }
.roul-sess-seg.sg-black { background: linear-gradient(180deg, #2a2a52, #16162c); }
.roul-sess-seg.sg-neutral  { background: linear-gradient(180deg, #4f7cff, #2d4fc0); }
.roul-sess-seg.sg-neutral2 { background: linear-gradient(180deg, #b78bff, #7a3ce0); }

/* hot / cold */
.roul-sess-hotcold { display: grid; grid-template-columns: 1fr 1fr; gap: var(--sp-2); margin-bottom: var(--sp-2); }
.roul-sess-hc { background: var(--surface-2); border: 1px solid var(--line-2); border-radius: var(--r-md); padding: var(--sp-2); }
.roul-sess-hc.is-hot  { box-shadow: inset 0 0 0 1px rgba(255,120,60,.35); }
.roul-sess-hc.is-cold { box-shadow: inset 0 0 0 1px rgba(90,160,255,.30); }
.roul-sess-hcnums { display: flex; flex-wrap: wrap; gap: 4px; color: var(--fg-dim); font-size: var(--fs-xs); }
.roul-sess-hcpill {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 20px; height: 20px; padding: 0 4px; border-radius: var(--r-pill);
  font-family: var(--font-display); font-weight: var(--fw-bold); font-size: 9px;
  font-variant-numeric: tabular-nums; color: #fff; border: 1px solid var(--line-2);
}

.roul-sess-commit {
  margin: 0 0 var(--sp-1); font-size: var(--fs-xs); color: var(--gold);
  font-variant-numeric: tabular-nums; word-break: break-all; min-height: 1em;
}
.roul-sess-disc { margin: 0; font-size: 10px; line-height: 1.4; color: var(--fg-dim); }

/* ---- portrait / narrow viewports ------------------------------------------- */
@media (max-width: 560px) {
  .roul-cell-label { font-size: var(--fs-xs); }
  .roul-cell { min-height: 32px; }
  .roul-outside, .roul-side { min-height: 34px; font-size: 9px; }
  .roul-stack-disc { width: 26px; height: 26px; font-size: 8px; }
  .roul-trchip { width: 46px; height: 46px; font-size: var(--fs-xs); }
  .roul-sess-top, .roul-sess-hotcold { grid-template-columns: 1fr; }
  /* Call-bet zones: smaller label + tighter padding so the French names fit (2 lines) without overflow. */
  .roul-racetrack { padding: var(--sp-2); max-width: 100%; box-sizing: border-box; }
  .roul-rt-zones { gap: 6px; }
  .roul-rt-zone { padding: 6px 4px; }
  .roul-rt-zone-t { font-size: var(--fs-xs); }
  .roul-rt-zone-s { font-size: 9px; }
  .roul-rt-neigh { gap: 6px; }
}

/* =============================================================================
   MOBILE IA (finding #2): the surface is tall + control-dense. Within roulette's OWN classes (no shell or
   12-gameview.css edits), we (a) pin the Total-bet + Spin action cluster to the bottom of the scrollable
   board area so they stay CO-VISIBLE under the thumb while the felt scrolls, (b) compact the session/live
   stats so they don't dominate the rail, and (c) grow the inside-bet hit-zones' TOUCH area to ~44px on a
   coarse pointer without changing the visible thin line. Phone-only query — desktop layout untouched.
   ========================================================================== */
@media (max-width: 760px) {
  /* (a) STICKY ACTION CLUSTER: the action row (Total bet + Spin + transforms) renders last (order:10) inside
     the scrollable .gameview-display; pin it to the bottom of that scrollport so a player never has to scroll
     past the felt to find Spin. A felt-toned backing keeps it legible over the board as it scrolls beneath.
     Scoped to roulette's own .roul-actions — no shell edit. */
  .roul-actions {
    position: sticky; bottom: 0; z-index: 9;
    margin-bottom: 0; padding: var(--sp-2) var(--sp-1) calc(var(--sp-2) + var(--safe-bottom, 0px));
    background: linear-gradient(180deg, rgba(8,20,14,0), rgba(8,20,14,.92) 28%);
    backdrop-filter: blur(3px);
  }
  /* keep the prominent total tight in the sticky cluster */
  .roul-totalbar { padding: 6px var(--sp-2); }
  .roul-totalbar-v { font-size: var(--fs-lg); }

  /* (b) COMPACT STATS: the session + live panels are full reference blocks (bars, hot/cold, disclaimer) that
     swamp the short phone rail. Trim them to the at-a-glance summary — title, the top stats (spins / net /
     round) and the recent-results strip — and collapse the heavy sub-blocks (even-money bars, hot/cold,
     commitment, disclaimer). The full breakdown stays on desktop; mobile keeps the IA light. */
  .roul-session .roul-sess-bars,
  .roul-session .roul-sess-hotcold,
  .roul-session .roul-sess-commit,
  .roul-session .roul-sess-disc,
  .roul-live .roul-sess-bars,
  .roul-live .roul-sess-hotcold,
  .roul-live .roul-sess-disc { display: none; }
  .roul-session, .roul-live { padding: var(--sp-2) var(--sp-3); }

  /* (c) 44px INSIDE-BET TOUCH TARGETS: the visible split/street/corner/six-line zones are intentionally thin
     lines on the cell edges (≤16px) so they don't cover the number cells. On a COARSE pointer we extend the
     TOUCHABLE area to ~44px with a transparent ::after that overhangs the line symmetrically, without moving
     or resizing the visible hit-zone — the finger target meets the bar, the felt still reads clean. */
  @media (pointer: coarse) {
    .roul-ins::after {
      content: ""; position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);
      min-width: 44px; min-height: 44px; width: 100%; height: 100%;
    }
  }
}

/* =============================================================================
   RACETRACK / CALL BETS — the oval call-bet strip under the wheel. One tap composes
   a FIXED multi-chip pattern (Voisins / Tiers / Orphelins, or Neighbours of X) onto
   the felt. Styled as a tactile "oval track" header + zone buttons; same synthwave
   tokens. Works identically in solo + live (both submit the composed felt placement).
   ========================================================================== */
.roul-racetrack {
  margin: var(--sp-3) auto 0; padding: var(--sp-3);
  background: linear-gradient(180deg, rgba(0,0,0,.22), rgba(0,0,0,.10));
  border: 1px solid var(--line-2); border-radius: 999px / 28px; /* oval-track feel */
  box-shadow: inset 0 0 30px rgba(0,0,0,.35);
}
.roul-rt-head { display: flex; align-items: baseline; justify-content: center; gap: var(--sp-2); flex-wrap: wrap; margin-bottom: var(--sp-2); }
.roul-rt-title { font-family: var(--font-display); font-weight: var(--fw-bold); font-size: var(--fs-sm); letter-spacing: .06em; text-transform: uppercase; color: var(--fg); }
.roul-rt-hint { font-size: 10px; color: var(--fg-dim); letter-spacing: .02em; }
.roul-rt-zones { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: var(--sp-2); }
.roul-rt-zone {
  appearance: none; cursor: pointer; min-height: 48px; min-width: 0; max-width: 100%;
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px;
  padding: 6px 8px; border-radius: var(--r-md);
  background: var(--surface-2); border: 1px solid var(--line-2); color: var(--fg);
  font-family: var(--font-display);
  transition: color var(--dur-1), background var(--dur-1), box-shadow var(--dur-2), transform var(--dur-1);
}
.roul-rt-zone:hover { background: var(--surface-3); box-shadow: var(--glow-brand); }
.roul-rt-zone:active { transform: scale(.98); }
.roul-rt-zone:focus-visible { outline: 2px solid var(--violet); outline-offset: 2px; box-shadow: var(--ring); }
/* The call-bet NAME (e.g. "Voisins du Zéro") must wrap to 2 lines inside its column rather than spill
   past the panel's right edge on narrow screens (the 360px Call-Bets clipping in the audit). min-width:0
   lets the flex column shrink; the title centres + wraps cleanly. */
.roul-rt-zone-t {
  font-weight: var(--fw-bold); font-size: var(--fs-sm); letter-spacing: .02em;
  min-width: 0; max-width: 100%; text-align: center; line-height: 1.15;
  overflow-wrap: break-word; word-break: normal; hyphens: auto;
}
.roul-rt-zone-s { font-size: 10px; letter-spacing: .04em; text-transform: uppercase; opacity: .8; font-variant-numeric: tabular-nums; }
/* Neighbours-of-X row: label + number select + place button */
.roul-rt-neigh { display: flex; align-items: center; gap: var(--sp-2); margin-top: var(--sp-2); flex-wrap: wrap; justify-content: center; }
.roul-rt-neigh-lab { font-size: var(--fs-xs); color: var(--fg-dim); letter-spacing: .02em; }
.roul-rt-neigh-sel {
  min-height: 40px; padding: 4px 10px; border-radius: var(--r-md);
  background: var(--surface-2); border: 1px solid var(--line-2); color: var(--fg);
  font-family: var(--font-display); font-weight: var(--fw-bold); font-variant-numeric: tabular-nums;
}
.roul-rt-neigh-sel:focus-visible { outline: 2px solid var(--violet); outline-offset: 2px; }
.roul-rt-neigh-btn { flex: 0 0 auto; min-height: 40px; }
/* live surface tint: warm the racetrack edge like the felt so the live version reads distinctly */
.roul-is-live .roul-racetrack { border-color: rgba(255,216,107,.25); }

/* ---- reduced-motion: no transforms/transitions/animations ------------------- */
@media (prefers-reduced-motion: reduce) {
  .roul-cell, .roul-trchip, .roul-act, .roul-ins, .roul-ins::before, .roul-sess-seg, .roul-rt-zone,
  .roul-coach-dismiss { transition: none; }
  .roul-cell:hover, .roul-cell:active, .roul-trchip:hover, .roul-trchip:active, .roul-act:active,
  .roul-rt-zone:active, .roul-coach-dismiss:active { transform: none; }
  .roul-stack-disc.drop, .roul-hist-pill, .roul-cell.win-pocket, .roul-conn.connecting .roul-conn-dot,
  .roul-coach.show { animation: none; }
  .roul-wheel-canvas { filter: none; }
}
