/* =============================================================================
   bust.fun - BLACKJACK styles  (games/blackjack)
   -----------------------------------------------------------------------------
   Felt-table UI: dealer hand on top, player seat(s) below, action buttons. Uses
   the synthwave design tokens ONLY (tokens.css) - never a hard-coded color.
   a11y bar: 44px+ touch targets, reduced-motion (instant reveal), no horizontal
   overflow at 360/390px. The dealer hole renders as a face-down card; it is only
   ever filled when the SERVER reveals the full hand (no client-side hidden state).
   ========================================================================== */

/* FILL: the felt is the hero — it grows to fill the tall display column (flex:1). The
   dealer + player card areas share the growing space (so the cards sit LARGE, centred
   vertically); the status / side-bets / controls keep their natural size at the bottom.
   Card geometry lives here as a var so the card + its rank/suit glyphs scale together. */
.bj-table {
  --bj-card-w: clamp(48px, 13vh, 150px);
  --bj-card-h: calc(var(--bj-card-w) * 64 / 44);
  display: flex;
  flex-direction: column;
  gap: clamp(var(--sp-2), 1.8vh, var(--sp-4));
  padding: clamp(var(--sp-3), 2vh, var(--sp-5));
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  background:
    radial-gradient(120% 90% at 50% -10%, var(--brand-soft), transparent 60%),
    linear-gradient(180deg, var(--surface-2), var(--bg-1));
  box-shadow: var(--shadow-2);
  width: 100%;
  max-width: min(820px, 96vh);
  margin: 0 auto;
  flex: 1 1 auto;
  min-height: 0;
}

/* the dealer + player areas grow to share the felt's height so the cards centre in the
   open space; the card row inside each area is vertically centred. */
.bj-area {
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
  flex: 1 1 auto;
  min-height: 0;
  justify-content: center;
}

.bj-area-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--sp-2);
}

.bj-area-label {
  font-family: var(--font-display);
  font-size: var(--fs-sm);
  letter-spacing: var(--tracking-cap);
  text-transform: uppercase;
  color: var(--muted);
}

/* The total is the key info at a glance (dealer + player) — render it large + legible. Scales with
   viewport height like the cards (floor → vh → cap) so it stays prominent on a tall felt and readable on a
   phone, between ~--fs-lg (17px) and ~--fs-xl (22px). Sits in the .bj-seat-meta row under the cards. */
.bj-total {
  font-variant-numeric: tabular-nums;
  font-weight: var(--fw-bold);
  color: var(--fg);
  font-size: clamp(var(--fs-lg), 2.4vh, var(--fs-xl));
  line-height: 1.1;
}

/* ---- card rows: min-height tracks the card so the row reserves the full card slot ----
   CLS FIX 2 — long hands no longer WRAP to a 2nd row (which grew the felt + re-centred
   the stack). The row is a single NON-WRAPPING line; from the 4th card on, cards OVERLAP
   (a fan) via a negative margin so a 5-6 card dealer/player hand never widens past the
   felt or spills to a second row. The min-height stays exactly one card tall — fixed. */
.bj-cards {
  display: flex;
  flex-wrap: nowrap;
  align-items: center;
  gap: clamp(var(--sp-2), 1.2vh, var(--sp-3));
  min-height: var(--bj-card-h);
}
/* Cards sit SIDE BY SIDE and SHRINK-TO-FIT their seat (see .bj-card's flex/aspect below) instead of the old
   fixed "fan": the fan overlapped every card from the 4th AND abruptly re-anchored the rank/suit from centre
   to top-left when the 4th landed — a jarring shift, and it fired even when the (wide) seat had ample room,
   and it couldn't tell a full seat from a narrow split column. Shrink-to-fit adapts to the ACTUAL seat width
   (full or split) with no overlap and no glyph reflow, so the rank/suit stay centred and put for every card
   count. (Owner: "numbers in weird spots… shifted from middle to top-left… the 4th card is over the 3rd.") */

/* CLS FIX 1 — split seat: a split appends a 2nd seat. As a flex COLUMN that 2nd seat
   added a whole unreserved row (~150px) and re-centred the stack. Make .bj-seats a
   fixed 2-up GRID instead: a single hand spans BOTH columns (centred, full width); a
   split fills the empty 2nd cell side-by-side WITHOUT growing the area's height. The
   row height is the same for 1 seat or 2, so the split never shifts the felt. */
.bj-seats {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--sp-3);
  align-items: start;
}
/* a single (un-split) hand: span both columns so it stays centred + full-width, exactly
   as it looked before the split layout. A split paints a 2nd .bj-seat into cell 2, and
   the :only-child rule no longer applies, so each seat falls back to one column. */
.bj-seats > .bj-seat:only-child { grid-column: 1 / -1; }

.bj-seat {
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
  padding: var(--sp-2);
  border: 1px solid transparent;
  border-radius: var(--r-md);
  transition: border-color var(--dur-2) var(--ease-out), box-shadow var(--dur-2);
}
.bj-seat.active {
  border-color: var(--line-3);
  box-shadow: inset 0 0 0 1px var(--brand-glow), 0 0 14px var(--brand-glow);
}

/* CLS FIX 3 (M3) — the total + outcome chip render UNDER the cards at verdict. With no reserved
   height the meta row was 0px until the verdict, then grew (re-centring the stack) at the
   highest-stakes moment; on a narrow seat the chip also wrapped BELOW the total, growing it
   further. Reserve a fixed one-line slot that EXPLICITLY accounts for BOTH possible occupants
   and FORBID wrap so the chip always sits beside the total — the verdict swaps content into an
   already-sized row, never grows it. The reserve is the MAX of:
     • the total line: --fs-xl (22px) × 1.2 line-height ≈ 26.4px, and
     • one .bj-chip line: --fs-xs (11px) × 1.5 line-height + 2×2px padding + 2×1px border ≈ 22.5px
   (worst case, e.g. a split seat with count 0 that shows ONLY a chip at verdict). max() keeps the
   slot correct even if a token shifts. The dealer meta (.bj-dealer-meta) shares this via the
   .bj-seat-meta class. */
.bj-seat-meta {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  flex-wrap: nowrap;
  min-height: max(calc(var(--fs-xl) * 1.2), calc(var(--fs-xs) * 1.5 + 6px));
}

/* ---- a single card ----
   FILL: the card scales with viewport HEIGHT (var on .bj-table: floor→vh→cap) so it grows
   on a tall screen and caps on a phone; the height keeps the ~44:64 (0.6875) card aspect.
   The rank/suit glyphs are em-derived off the card width so the ink scales WITH the card. */
.bj-card {
  position: relative;
  container-type: inline-size;   /* rank/suit glyphs size off the card's RENDERED width (cqw), so they scale
                                    down WITH the card when a many-card / split hand makes it shrink */
  flex: 0 1 var(--bj-card-w);     /* at most one card wide; SHRINK to fit when the hand is wide or the seat is
                                    a narrow split column — replaces the old fixed-width + negative-margin fan */
  min-width: 0;
  max-width: var(--bj-card-w);
  aspect-ratio: 44 / 64;          /* height tracks the (possibly shrunk) width — keeps the card shape (was a
                                    fixed --bj-card-h; the row still reserves --bj-card-h via min-height) */
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: .08em;
  border-radius: clamp(var(--r-sm), 1.3vh, 13px);
  background: linear-gradient(180deg, #f7f6ff, #e9e7f6);
  color: #1a1033; /* card faces are light; dark ink reads on them (not a token - physical card) */
  border: 1px solid rgba(0, 0, 0, .18);
  box-shadow: var(--shadow-1);
  font-family: var(--font-display);
  font-weight: var(--fw-bold);
}
/* red suits (hearts/diamonds) → the theme's vivid red. NOT --accent-2: that token is a deep BLUE in this
   theme, so the red suits were rendering blue. --lose (#f43f5e) is red across themes (the negative token). */
.bj-card.red { color: var(--lose); }
/* glyphs in cqw (% of the card's OWN width) so they scale with a shrunk card — equals the old
   calc(--bj-card-w * 0.4/0.34) at full size, but tracks the card when a wide/split hand shrinks it. */
.bj-card-rank { font-size: 40cqw; line-height: 1; }
.bj-card-suit { font-size: 34cqw; line-height: 1; }

/* face-down dealer hole — neon-patterned back, NO value ever rendered here.
   P1 issue #5: the stripe alternated --brand-2 vs --brand which are BOTH green in neon-noir, so the
   "pattern" read as a flat green card. Alternate the brand green against the deep --bg-1 well instead so
   the diagonal stripes have real contrast (green-on-dark) and the face-down back is unmistakable in any
   theme. A subtle radial sheen + the inner highlight keep it reading as a printed card back, not a void. */
.bj-card.bj-hole {
  background:
    radial-gradient(120% 90% at 50% 0%, rgba(255, 255, 255, .10), transparent 55%),
    repeating-linear-gradient(45deg, var(--brand) 0 7px, var(--bg-1) 7px 14px);
  border-color: var(--line-3);
  box-shadow: inset 0 0 0 2px rgba(255, 255, 255, .14), var(--glow-brand);
}

/* ---- pre-deal placeholder (P1 issue #2) ----
   Ghost card OUTLINES + a payout-key hero fill the otherwise-blank pre-deal felt so it communicates the
   table instead of reading as broken/unloaded. Ghosts are dashed, low-fill card slots (same geometry as a
   real card via the shared --bj-card-w/h vars) carrying NO data. The hero teaches the 3:2 payout + the
   "deal" prompt. All presentation; wiped the instant a real deal lands. */
.bj-card.bj-ghost {
  background: none;
  border: 1.5px dashed var(--line-2);
  box-shadow: none;
  opacity: .55;
}
.bj-ghost-seat {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--sp-3);
  border-color: transparent;
}
.bj-ghost-seat .bj-cards { justify-content: center; }
.bj-empty-hero {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--sp-1);
  text-align: center;
}
.bj-empty-pays {
  font-family: var(--font-display);
  font-weight: var(--fw-bold);
  font-size: clamp(var(--fs-md), 2.2vh, var(--fs-lg));
  letter-spacing: var(--tracking-cap);
  text-transform: uppercase;
  /* contrast >= 3:1 on the felt — the brand green reads clearly against the dark surface (not muted grey) */
  color: var(--brand);
}
.bj-empty-sub {
  font-size: var(--fs-sm);
  color: var(--fg-dim);
}

/* card flip-in for cards drawn after the initial deal + the revealed hole. The reveal sequencing is in
   blackjack.js (cards flip in one-by-one; the hole stays face-down until the SERVER reveals it at
   terminal); this is the per-card 3D flip the JS triggers by adding .flip-in. */
.bj-cards { perspective: 600px; }
.bj-card.flip-in { animation: bj-flip var(--dur-3) var(--ease-out) both; transform-origin: center; }
@keyframes bj-flip {
  from { transform: rotateY(-90deg) translateY(-6px); opacity: 0; }
  40%  { opacity: 1; }
  to   { transform: rotateY(0)      translateY(0);    opacity: 1; }
}

/* a natural 21 gets a brief gold glow as it lands (its moment, before the dealer reveals) */
.bj-seat.bj-natural { animation: bj-natural-glow 900ms var(--ease-out) both; }
@keyframes bj-natural-glow {
  0%   { box-shadow: 0 0 0 0 transparent; }
  40%  { box-shadow: inset 0 0 0 1px var(--win), 0 0 18px var(--glow-win, var(--win)); }
  100% { box-shadow: inset 0 0 0 1px var(--win), 0 0 8px var(--win); }
}

/* ---- outcome chips ---- */
.bj-chip {
  font-size: var(--fs-xs);
  font-weight: var(--fw-bold);
  letter-spacing: var(--tracking-cap);
  text-transform: uppercase;
  padding: 2px var(--sp-2);
  border-radius: var(--r-pill);
  border: 1px solid var(--line-2);
}
.bj-win  { color: var(--win);  background: var(--win-soft);  border-color: var(--win); box-shadow: var(--glow-win); }
.bj-lose { color: var(--lose); background: var(--lose-soft); border-color: var(--lose); }
.bj-push { color: var(--muted-2); background: var(--muted-surface); }
/* The payout figure (counts up via fx.numberRamp on a win). tabular-nums so the ramp doesn't jitter
   the chip width frame-to-frame. Inherits the chip color/weight. Tokens only. */
.bj-chip-pay { font-variant-numeric: tabular-nums; }
/* P1 issue #6: the outcome SHAPE glyph (✓/=/✕) so win/lose/push isn't colour-only. Inherits the chip
   hue + sits just before the label with a hair of trailing space. Decorative (aria-hidden in the JS). */
.bj-chip-mark { margin-right: .35em; font-weight: var(--fw-bold); }

/* ---- status line (aria-live) ---- */
.bj-status {
  min-height: 1.4em;
  font-size: var(--fs-sm);
  color: var(--fg-dim);
  padding: var(--sp-2) var(--sp-3);
  border-radius: var(--r-md);
  background: var(--surface-2);
  border: 1px solid var(--line);
}

/* ---- controls ----
   ACTION HIERARCHY (game-blackjack MAJOR): the controls stack as ROWS now, not one equal-weight flex wrap.
   Deal / Rebet sit at the top (pre-hand). In-hand, the PRIMARY pair (Hit + Stand) gets its own full-width
   row at a larger size + accent tint; the SECONDARY cluster (Double / Split / Surrender) sits below, smaller
   and de-emphasized, so the eye lands on Hit/Stand every decision. */
.bj-controls {
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
}
.bj-controls-primary { display: flex; gap: var(--sp-2); }
.bj-controls-primary .bj-btn { flex: 1 1 0; }
.bj-controls-secondary { display: flex; flex-wrap: wrap; gap: var(--sp-2); }
.bj-controls-secondary .bj-btn { flex: 1 1 auto; }
/* hide an empty row entirely so it reserves no space when its buttons are all .hidden (pre-hand). */
.bj-controls-primary:not(:has(.bj-btn:not(.hidden))),
.bj-controls-secondary:not(:has(.bj-btn:not(.hidden))) { display: none; }

/* PRIMARY: Hit / Stand — larger, accent-tinted, the obvious read. */
.bj-btn.bj-primary {
  font-size: var(--fs-lg);
  font-weight: var(--fw-bold);
  min-height: calc(var(--touch) + 8px);
  border-color: color-mix(in oklab, var(--accent, #8b5cf6) 55%, var(--line-2));
  background: linear-gradient(180deg,
    color-mix(in oklab, var(--accent, #8b5cf6) 18%, var(--surface-3)),
    color-mix(in oklab, var(--accent, #8b5cf6) 8%, var(--surface-2)));
}
.bj-btn.bj-primary:hover:not(:disabled) { box-shadow: var(--glow-accent, var(--glow-brand)); border-color: var(--accent, #8b5cf6); }
/* SECONDARY: Double / Split — present but quieter. TERTIARY: Surrender — smallest, most muted. */
.bj-btn.bj-secondary { font-size: var(--fs-sm); min-height: var(--touch); opacity: .92; }
.bj-btn.bj-tertiary { font-size: var(--fs-xs); min-height: var(--touch); opacity: .8; flex: 0 1 auto; }
/* REBET & DEAL: a one-tap repeat after settle — accent-styled like Deal. */
.bj-btn.bj-rebet {
  background: linear-gradient(180deg, var(--surface-3), var(--surface-2));
  border-color: color-mix(in oklab, var(--accent, #8b5cf6) 45%, var(--line-2));
  color: var(--fg);
}
.bj-btn.bj-rebet:hover:not(:disabled) { box-shadow: var(--glow-accent, var(--glow-brand)); }

/* =============================================================================
   RAIL CONTENT (game-blackjack MAJOR: fill the under-used left rail)
   Session shoe (last-N hands + streak), a live basic-strategy hint, payout reference.
   ========================================================================== */
.bj-rail { display: flex; flex-direction: column; gap: var(--sp-3); margin-top: var(--sp-2); }
.bj-rail-block {
  padding: var(--sp-2) var(--sp-3);
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--surface-2);
}
.bj-rail-label {
  font-size: var(--fs-xs);
  text-transform: uppercase;
  letter-spacing: var(--tracking-cap);
  color: var(--muted);
  margin-bottom: 6px;
}
/* SHOE STRIP: colored W/L/P/BJ chips for the last ~12 hands. Reserved one-line height so it never pops in
   and shifts the rail (CLS-safe — empty state shows the streak placeholder line). */
.bj-shoe-strip {
  display: flex; flex-wrap: wrap; gap: 4px;
  min-height: calc(var(--fs-sm) + 10px);
  margin-bottom: 4px;
}
.bj-shoe-chip {
  display: inline-flex; align-items: center; justify-content: center;
  min-width: 20px; height: 20px; padding: 0 5px;
  border-radius: var(--r-sm);
  font-size: var(--fs-xs); font-weight: var(--fw-bold);
  font-variant-numeric: tabular-nums;
  border: 1px solid var(--line-2);
}
.bj-shoe-win { color: var(--win); background: var(--win-soft); border-color: var(--win); }
.bj-shoe-lose { color: var(--lose); background: var(--lose-soft); border-color: var(--lose); }
.bj-shoe-push { color: var(--muted-2); background: var(--muted-surface); }
.bj-shoe-streak { font-size: var(--fs-sm); min-height: 1.3em; }

/* BASIC-STRATEGY HINT: a single live suggestion. The "Tip" tag reads as guidance, not a command. */
.bj-rail-hint { display: flex; align-items: center; gap: var(--sp-2); }
.bj-hint-tag {
  flex: 0 0 auto;
  font-size: var(--fs-xs); font-weight: var(--fw-bold);
  letter-spacing: var(--tracking-cap); text-transform: uppercase;
  color: var(--accent, #8b5cf6);
  background: color-mix(in oklab, var(--accent, #8b5cf6) 16%, transparent);
  border: 1px solid color-mix(in oklab, var(--accent, #8b5cf6) 45%, transparent);
  border-radius: var(--r-pill);
  padding: 1px 7px;
}
.bj-hint-text { font-size: var(--fs-sm); color: var(--fg-2); min-height: 1.3em; }

/* PAYOUT REFERENCE: a small collapsible pay table (reuses the gv-collapsible caret chrome). */
.bj-rail-pays.gv-collapsible { background: var(--surface-2); }
.bj-pays-body { padding: 0 var(--sp-3) var(--sp-2); display: flex; flex-direction: column; gap: 4px; }
.bj-pay-row { display: flex; justify-content: space-between; gap: var(--sp-2); font-size: var(--fs-sm); }
.bj-pay-k { color: var(--fg-2); font-weight: var(--fw-semi); }
.bj-pay-v { color: var(--muted); font-variant-numeric: tabular-nums; }

.bj-btn {
  flex: 1 1 auto;
  min-width: 72px;
  min-height: var(--touch); /* >= 44px touch target */
  padding: var(--sp-2) var(--sp-3);
  border-radius: var(--r-md);
  border: 1px solid var(--line-2);
  background: linear-gradient(180deg, var(--surface-3), var(--surface-2));
  color: var(--fg);
  font-family: var(--font-display);
  font-weight: var(--fw-semi);
  font-size: var(--fs-md);
  cursor: pointer;
  transition: transform var(--dur-1) var(--ease-out), border-color var(--dur-2), box-shadow var(--dur-2);
}
.bj-btn:hover:not(:disabled) { border-color: var(--line-3); box-shadow: var(--glow-brand); transform: translateY(-1px); }
.bj-btn:active:not(:disabled) { transform: translateY(0); }
.bj-btn:focus-visible { outline: none; box-shadow: var(--ring); }
.bj-btn:disabled { opacity: .45; cursor: not-allowed; }
.bj-btn.loading { opacity: .6; cursor: progress; }
.bj-btn.hidden { display: none; }

/* the primary Deal CTA stands out (rose accent) */
.bj-btn.bj-deal {
  background: linear-gradient(180deg, var(--accent), var(--accent-2));
  color: var(--accent-ink);
  border-color: var(--accent-2);
}
.bj-btn.bj-deal:hover:not(:disabled) { box-shadow: var(--glow-accent); }

/* ===== side bets — a CLOSED-BY-DEFAULT disclosure (collapsed to one summary line) =====
   Most players never bet side bets, so the inputs stay hidden until the player expands the
   summary. Collapsed it is a single ~44px row; expanded it reveals the 21+3 / Perfect Pairs
   wagers, each with a "$" affordance + an "optional" hint so the 0.00 reads as an extra wager. */
/* The side-bets disclosure is now a gv-controls collapsible() (it supplies the .gv-collapsible container +
   the .gv-collapsible-sum summary with the shared caret). #bjSideBets stays on the <details> for the
   open-hand hide toggle. */
.bj-sidebets.hidden { display: none; }
.bj-sidebets-title { font-weight: var(--fw-semi); color: var(--fg-2); }
.bj-sidebets-opt {
  font-size: var(--fs-xs);
  text-transform: uppercase;
  letter-spacing: var(--tracking-cap);
  color: var(--muted);
  border: 1px solid var(--line-2);
  border-radius: var(--r-pill);
  padding: 1px var(--sp-2);
}
.bj-sidebets-body {
  display: flex;
  flex-direction: column;
  gap: var(--sp-2);
  padding: 0 var(--sp-3) var(--sp-3);
}
.bj-sidebet {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  flex-wrap: wrap;
}
.bj-sidebet-name {
  flex: 0 0 96px;
  font-size: var(--fs-sm);
  font-weight: var(--fw-semi);
  color: var(--fg-2);
}
/* the $-prefixed stake input is now a gv-controls stepper({prefix:'$'}) — it uses the shared
   .gv-stepper / .gv-affix / .gv-stepper-input chrome (no bespoke .bj-sidebet-field/.bj-sidebet-input). */
.bj-sidebet .gv-stepper { flex: 0 0 120px; }
.bj-sidebet-tip { font-size: var(--fs-xs); }

/* ===== insurance prompt (shown ONLY in the INSURANCE server state, before the hole peek) ===== */
.bj-insurance {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-2);
  padding: var(--sp-2) var(--sp-3);
  border: 1px solid var(--line-2);
  border-radius: var(--r-md);
  background: linear-gradient(180deg, var(--surface-2), var(--surface-1));
}
.bj-insurance.hidden { display: none; }
.bj-insurance-label {
  flex: 1 1 220px;
  color: var(--fg-2);
  font-size: var(--fs-sm);
}
.bj-btn.bj-insurance-yes {
  background: linear-gradient(180deg, var(--accent), var(--accent-2));
  color: var(--accent-ink);
  border-color: var(--accent-2);
}

/* ===== responsive: no horizontal overflow at 390 / 360 =====
   Shrink the card-WIDTH var (height + glyphs follow via calc) so a split player hand of
   several cards still fits a row without overflow at narrow widths. */
@media (max-width: 390px) {
  .bj-table { --bj-card-w: clamp(40px, 8.5vh, 58px); padding: var(--sp-3); }
  .bj-btn { min-width: 64px; font-size: var(--fs-sm); }
}
@media (max-width: 360px) {
  .bj-table { --bj-card-w: clamp(36px, 8vh, 52px); }
  .bj-cards { gap: var(--sp-1); }
  .bj-btn { min-width: 56px; padding: var(--sp-2); }
}

/* ===== reduced motion: instant, no flip/transition ===== */
@media (prefers-reduced-motion: reduce) {
  .bj-card.flip-in { animation: none !important; }
  .bj-seat.bj-natural { animation: none !important; }
  .bj-seat,
  .bj-btn { transition: none !important; }
  .bj-btn:hover:not(:disabled) { transform: none; }
}
