/* =============================================================================
   bust.fun — COINFLIP styles  (games/coinflip)
   -----------------------------------------------------------------------------
   Game-SPECIFIC styles for this module (linked from index.html). Synthwave tokens
   only (tokens.css); no hard-coded palette outside metallic gradient stops (which
   read as gold/silver coin metal, not theme accents). The coin is the STAR: a
   believable 3D metallic neon coin with distinct heads/tails faces that spins (in
   coinflip.js) and lands on the SERVER's outcome — server-authoritative.

   Reduced-motion: ALL motion (spin/idle float/glow pulse) is no-op'd at the bottom;
   the coin still shows its face and the win/loss state colour, with zero movement.
   ========================================================================== */

/* The Heads/Tails picker is now a gv-controls segmented({variant:'chip'}) (.coin-pick keeps the class so it
   sits centered below the coin); it uses the shared .seg button.active chip chrome from styles.css — no
   bespoke .coin-pick .pick styling forked here any more. */
/* Cap the picker width + center it so the two Heads/Tails chips read as compact segmented chips, NOT
   two oversized full-bleed bars — including on the logged-out first paint, which has no post-login
   layout pass to narrow them (audit #7). .gv-seg forces width:100%; we override to a centered max-width. */
.coin-pick {
  justify-content: center; margin-top: var(--sp-2);
  width: 100%; max-width: 340px; margin-left: auto; margin-right: auto;
}

/* =============================================================================
   The 3D coin stage
   ========================================================================== */
.coin-stage {
  display: flex; justify-content: center; align-items: center;
  position: relative;
  /* FILL: the stage grows to consume the display column's spare height so the (now
     large) coin sits centered in the tall area. min-height:0 keeps it shrinkable on
     short screens; the shared styles.css supplies a min-height floor. A trimmer top/
     bottom pad lets the coin claim more of the tall column (less dead gutter beside
     the round coin on wide desktop — T3 board-fill) without overflowing the picker. */
  flex: 1; min-height: 0;
  padding: var(--sp-3) 0;
  perspective: 1200px;            /* deeper perspective → a stronger 3D tumble */
  perspective-origin: 50% 42%;
}
/* a soft elliptical floor shadow under the coin — anchors the toss so the coin reads as
   leaving and returning to a surface. The coin is now CENTERED, so the shadow sits just
   below the coin's center and its width scales with the coin diameter (≈0.6×). */
.coin-stage::after {
  content: ''; position: absolute; top: 50%; left: 50%;
  width: min(52vh * 0.6, 480px * 0.6, 288px); height: 16px;
  transform: translate(-50%, calc(min(52vh, 480px) * 0.5 + var(--sp-3)));
  border-radius: 50%;
  background: radial-gradient(ellipse at center, rgba(0,0,0,.55), rgba(0,0,0,0) 72%);
  filter: blur(1px); pointer-events: none; z-index: 0;
}

/* legacy / un-enhanced fallback (core builds .coin3d; this keeps SSR markup legible) */
.coin {
  width: 96px; height: 96px; border-radius: 50%; position: relative;
  display: flex; align-items: center; justify-content: center;
  font-size: 30px; font-weight: var(--fw-black); color: #4a3500;
  background: radial-gradient(circle at 35% 30%, #ffe9a8, var(--gold) 55%, #c79622);
  box-shadow: inset 0 0 0 4px rgba(255,255,255,.25), 0 8px 24px rgba(0,0,0,.5);
}

/* enhanced 3D coin — the host gets .coin3d; inner holds the two faces + the rim.
   FILL: the coin is the STAR — size it off the viewport height (a big square that caps
   on tall monitors and floors so it never gets tiny). --coin-size drives the face mark
   and the toss-arc height so the whole coin scales as one unit. */
.coin.coin3d {
  /* size off viewport height (round coin → height is the binding dimension), capped so it
     never gets gaudy on tall monitors. Bumped from 46vh/440 → 52vh/480 so the coin claims
     more of the wide desktop board column, shrinking the dead horizontal gutter beside it
     (T3 board-fill) while still flooring/capping cleanly. Mobile keeps its tighter cap below. */
  --coin-size: min(52vh, 480px);
  width: var(--coin-size); height: var(--coin-size); background: none; box-shadow: none;
  position: relative; z-index: 1;
  transform-style: preserve-3d; overflow: visible;
}
.coin3d .coin-inner {
  position: absolute; inset: 0;
  transform-style: preserve-3d;
  will-change: transform;
}
/* gentle idle bob — applied to the HOST (translateY) so it never fights the inner's
   rotateY (the spin transform). Different element = different transform, no conflict. */
.coin3d:not(.is-spinning) { animation: coin-bob 3.6s var(--ease-in-out) infinite; }

/* TOSS arc — while spinning the host "tosses" up and settles back down, synced to the spin
   duration the core sets via --coin-toss-dur (default 1.2s). It's translateY-only on the HOST,
   so it never fights the inner's rotateY/rotateX. Overshoot-ease for a springy launch + settle. */
.coin3d.is-tossing {
  animation: coin-toss var(--coin-toss-dur, 1.2s) var(--ease-out) both;
}
/* the launch height scales with the coin (≈35% of its size) so a big coin tosses with
   proportional travel rather than a tiny fixed 46px hop. */
@keyframes coin-toss {
  0%   { transform: translateY(0) scale(1); }
  30%  { transform: translateY(calc(var(--coin-size, 132px) * -0.35)) scale(1.06); }   /* launch — up + slightly nearer */
  62%  { transform: translateY(calc(var(--coin-size, 132px) * -0.23)) scale(1.05); }
  100% { transform: translateY(0) scale(1); }           /* settle back to the floor */
}

.coin3d .coin-face {
  position: absolute; inset: 0; border-radius: 50%;
  display: flex; align-items: center; justify-content: center;
  backface-visibility: hidden;
  box-shadow:
    inset 0 0 0 5px rgba(255,255,255,.22),
    inset 0 -8px 16px rgba(0,0,0,.35),
    0 10px 28px rgba(0,0,0,.55);
}
.coin3d .coin-mark {
  font-family: var(--font-display, inherit);
  /* scale the H/T glyph with the coin (≈35% of its diameter), capped for huge coins */
  font-size: clamp(46px, calc(var(--coin-size, 132px) * 0.35), 168px); font-weight: var(--fw-black);
  line-height: 1; text-shadow: 0 2px 3px rgba(0,0,0,.35), 0 0 14px rgba(255,255,255,.25);
  position: relative; z-index: 1; /* sit above the milled inner ring (::before below) */
}
/* MINTED-RIM relief on the PAINTED fallback face (NOT .has-art, which carries its own rim): a concentric
   inner ring drawn with two thin ring-shadows so the coin reads as a STRUCK disc — a real coin face — rather
   than a flat letter on a circle (audit #1 "placeholder" read). Pure inset shadow on a positioned pseudo, no
   extra DOM, no motion. Suppressed when real art loads. */
.coin3d .coin-face:not(.has-art)::before {
  content: ''; position: absolute; inset: 11%; border-radius: 50%; pointer-events: none; z-index: 0;
  box-shadow:
    inset 0 0 0 2px rgba(255,255,255,.16),
    inset 0 0 0 3px rgba(0,0,0,.18),
    inset 0 3px 8px rgba(0,0,0,.22);
}

/* HEADS — warm gold metal (CSS FALLBACK; real art overrides via `.has-art` below) */
.coin3d .coin-heads {
  background:
    radial-gradient(circle at 34% 28%, #fff3c4, var(--gold) 46%, #c79622 86%, #8f6c12);
  transform: rotateY(0deg);
}
.coin3d .coin-heads .coin-mark { color: #4a3500; }

/* TAILS — cool violet/cyan metal (the synthwave twin; CSS FALLBACK) */
.coin3d .coin-tails {
  background:
    radial-gradient(circle at 34% 28%, #e7e0ff, var(--violet) 46%, var(--brand) 86%, #3b1d77);
  transform: rotateY(180deg);
}
.coin3d .coin-tails .coin-mark { color: #f4efff; text-shadow: 0 2px 3px rgba(0,0,0,.45), 0 0 16px var(--violet-glow); }

/* REAL COIN ART (Gemini illustration, loaded by coinflip.js when /img/selected/coin-*.png is present).
   The face gets `.has-art` + an inline background-image; we then drop the painted gradient + inset
   metal rings and hide the letter glyph (the art carries its own H/T), keeping just a soft contact
   shadow so the disc still reads as a 3D coin. A 404 leaves the CSS fallback above untouched. */
.coin3d .coin-face.has-art {
  background-color: transparent;
  background-repeat: no-repeat;
  background-position: center;
  background-size: cover;          /* the disc was tight-cropped → fill the round face edge-to-edge */
  box-shadow: 0 10px 28px rgba(0,0,0,.5); /* drop the inset metal rings; keep the cast shadow */
}
.coin3d .coin-face.has-art .coin-mark { display: none; } /* the art has its own embossed letter */

/* the coin's edge/rim — RETIRED. A single opaque disc at translateZ(-Npx) flips to +Npx under the
   inner's rotateY(180deg) and renders IN FRONT of the tails face, covering it (a latent z-order bug
   in BOTH the art and painted-fallback paths). The 3D thickness is sold instead by the face inset
   metal rings (.coin-face box-shadow) + the host drop-shadow + the real art's own milled rim. We keep
   the element in the DOM (harmless, aria-hidden) but never paint it. */
.coin3d .coin-edge { display: none; }

/* outcome state glow on the host (added by the core on landing). The landing PULSE is on
   `filter` only (a glow ramp) — NOT transform — so it never fights the host's coin-bob
   translateY. */
.coin3d.is-win  { filter: drop-shadow(0 0 18px var(--win-glow));  animation: coin-bob 3.6s var(--ease-in-out) infinite, coin-land-win .9s var(--ease-out); }
.coin3d.is-loss { filter: drop-shadow(0 0 12px var(--lose-glow)); animation: coin-bob 3.6s var(--ease-in-out) infinite, coin-land-loss .6s var(--ease-out); }
.coin3d.is-spinning { filter: drop-shadow(0 0 14px var(--brand-glow)); }

@keyframes coin-land-win {
  0%   { filter: drop-shadow(0 0 4px var(--win-glow)) brightness(1); }
  35%  { filter: drop-shadow(0 0 34px var(--win-glow)) brightness(1.25); }
  100% { filter: drop-shadow(0 0 18px var(--win-glow)) brightness(1); }
}
@keyframes coin-land-loss {
  0%   { filter: drop-shadow(0 0 4px var(--lose-glow)) saturate(.7); }
  100% { filter: drop-shadow(0 0 12px var(--lose-glow)) saturate(1); }
}

@keyframes coin-bob {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(-6px); }
}

/* on phones the column is shorter and the coin shares it with the Heads/Tails picks +
   the odds chip — cap the coin a little lower so the whole panel fits with no page scroll. */
@media (max-width: 480px) {
  .coin.coin3d { --coin-size: min(44vh, 300px); }
  .coin-stage::after {
    width: min(44vh * 0.6, 300px * 0.6, 180px);
    transform: translate(-50%, calc(min(44vh, 300px) * 0.5 + var(--sp-2)));
  }
}

/* The Win-pays preview is now a gv-controls preview() in the LEFT rail (#gameControlsSlot) and uses the
   shared .preview .stat.accent chrome from styles.css — no bespoke gold .coin-preview chip styling forked
   here any more (the live per-stake figure is rendered straight onto the preview's #coinPays node). */

/* the visually-hidden aria-live announcer (e.g. "Heads — you won"). Belt-and-suspenders with the
   global .visually-hidden so the SR-only region NEVER affects layout / horizontal overflow. */
.coin-announce {
  position: absolute !important; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0;
}

/* =============================================================================
   Reduced motion — no spin, no bob, no glow pulse. The face + state colour remain.
   (The core also snaps straight to the outcome face when reduced-motion is set.)
   ========================================================================== */
@media (prefers-reduced-motion: reduce) {
  .coin3d,
  .coin3d.is-win,
  .coin3d.is-loss,
  .coin3d.is-tossing,
  .coin3d:not(.is-spinning) { animation: none !important; transform: none !important; }
  .coin3d .coin-inner { transition: none !important; }
  /* keep the resting state-glow (no movement, no pulse) so win/loss is still legible */
  .coin3d.is-win  { filter: drop-shadow(0 0 12px var(--win-glow)); }
  .coin3d.is-loss { filter: drop-shadow(0 0 10px var(--lose-glow)); }
}

/* =============================================================================
   STREAK mode (Stake "Flip" parity) — the in-panel mode toggle + the stateful
   cash-out HUD/controls injected by coinflip.js (buildStreakUI). All structural
   classes (.pick, .btn, .row, .muted) are shared utilities; these rules only add
   the streak-specific layout/colour. Mirrors the hilo cashbar treatment.
   ========================================================================== */
/* the mode toggle is now a gv-controls segmented({variant:'tab'}) tagged .coin-mode — it uses the shared
   .seg button.active chrome; this just adds the panel-top spacing. */
.panel[data-panel="coinflip"] .coin-mode { margin-bottom: var(--sp-2, .5rem); }

.panel[data-panel="coinflip"] .coin-streak { margin-top: var(--sp-3, .75rem); }
/* CLS FIX — the streak chrome stays IN FLOW in BOTH modes (no display:none). In Instant
   mode .is-instant collapses ONLY the help copy (whose multi-line height would be an ugly
   void) and hides the Flip button via visibility, while the controls ROW keeps its reserved
   44px height (below). Switching Instant→Streak then only fades the button + help in — it no
   longer inserts an unreserved row that pushes the Heads/Tails picker up. */
.panel[data-panel="coinflip"] .coin-streak.is-instant .coin-streak-help { display: none; }
.panel[data-panel="coinflip"] .coin-streak.is-instant .coin-streak-flip { visibility: hidden; }
/* reserve the Flip-control row height in BOTH modes so the slot never grows on the switch
   (the button itself is [hidden] in instant; the row holds the space regardless). */
.panel[data-panel="coinflip"] .coin-streak-controls { min-height: 44px; }

/* VISIBLE streak verdict line (audit #1) — a sighted result for every money-changing streak outcome
   (win / cash-out / bust), not just an SR-only span. It's also role=status + aria-live=polite (set in
   coinflip.js) so SR users still hear it. Mirrors the .hilo-streak treatment: a single centered line
   that stays IN FLOW (reserved min-height) and just fades out when empty — no layout shift. Neutral by
   default; .is-win = gold glow, .is-loss = muted/red so the outcome reads at a glance. */
.panel[data-panel="coinflip"] .coin-streak-verdict {
  margin: var(--sp-2, .5rem) 0 0; text-align: center;
  font-size: var(--fs-sm, .82rem); font-weight: var(--fw-bold, 700); line-height: 1.25;
  min-height: calc(var(--fs-sm, .82rem) * 1.25);
  color: var(--fg, #fff); font-variant-numeric: tabular-nums;
  transition: opacity var(--dur-2, .2s) var(--ease-out, ease);
}
.panel[data-panel="coinflip"] .coin-streak-verdict.is-empty { visibility: hidden; opacity: 0; }
.panel[data-panel="coinflip"] .coin-streak-verdict.is-win {
  color: var(--gold); text-shadow: 0 0 10px var(--gold-glow);
}
.panel[data-panel="coinflip"] .coin-streak-verdict.is-loss { color: var(--muted, #9aa); }
/* Instant mode hides the streak chrome entirely — keep the verdict out of flow there too. */
.panel[data-panel="coinflip"] .coin-streak.is-instant .coin-streak-verdict { display: none; }

.panel[data-panel="coinflip"] .coin-streak-controls { gap: var(--sp-2, .5rem); }
.panel[data-panel="coinflip"] .coin-streak-controls .btn { flex: 1 1 0; min-height: 44px; }
.panel[data-panel="coinflip"] .coin-streak-controls .btn[hidden] { display: none; }
.panel[data-panel="coinflip"] .coin-streak-help { margin-top: var(--sp-2, .5rem); }

/* =============================================================================
   STREAK-LADDER TEASER (audit #2 retention) — the Instant-view chase preview.
   -----------------------------------------------------------------------------
   A focusable one-line strip below the Heads/Tails picker that surfaces the first
   few streak rungs (1.96× → 3.84× → 7.53× → …) so the compounding Streak mode is
   DISCOVERABLE from the default Instant view, and switches into it on click. It is
   ONLY shown in Instant mode (display:none under .is-streak — same pattern as the
   streak-help collapse), so within Instant it is ALWAYS present (never pops in mid
   round) and the idle→play→result flow stays shift-free. The real ladder HUD owns
   the chase once in streak mode, so the teaser would be redundant there.
   ========================================================================== */
.panel[data-panel="coinflip"] .coin-teaser {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: center;
  gap: var(--sp-1, 4px) var(--sp-2, 8px);
  width: 100%; max-width: 360px; margin: var(--sp-2, 8px) auto 0;
  padding: var(--sp-2, 8px) var(--sp-3, 12px);
  text-align: center; cursor: pointer;
  /* a subtle gold-tinted surface chip so it reads as a reward affordance, not a control. Token-only. */
  background: var(--surface-2, #15152b);
  border: 1px solid var(--line-2, #3a2d6e);
  border-radius: var(--r-md, 10px);
  color: var(--fg, #fff);
  font-size: var(--fs-sm, 13px); line-height: 1.2;
  transition: border-color var(--dur-2, .2s) var(--ease-out, ease),
              box-shadow var(--dur-2, .2s) var(--ease-out, ease),
              background-color var(--dur-2, .2s) var(--ease-out, ease);
}
/* hidden in streak mode (the real ladder HUD takes over). Same collapse pattern as .coin-streak-help. */
.panel[data-panel="coinflip"] .coin-teaser.is-streak { display: none; }
.panel[data-panel="coinflip"] .coin-teaser:hover,
.panel[data-panel="coinflip"] .coin-teaser:focus-visible {
  border-color: var(--gold, #ffcf5c);
  box-shadow: 0 0 0 1px var(--gold-glow, rgba(255,207,92,.38)), 0 4px 18px var(--gold-glow, rgba(255,207,92,.38));
  background: var(--surface-3, #222244);
}
.panel[data-panel="coinflip"] .coin-teaser:focus-visible { outline: none; } /* the glow ring above IS the focus affordance */

.panel[data-panel="coinflip"] .coin-teaser-lead {
  color: var(--muted, #9aa); font-weight: var(--fw-bold, 700);
  font-size: var(--fs-xs, 11px); text-transform: uppercase; letter-spacing: .04em;
}
.panel[data-panel="coinflip"] .coin-teaser-rungs {
  display: inline-flex; align-items: center; gap: var(--sp-1, 4px);
  flex-wrap: wrap; justify-content: center;
}
/* each rung chip — gold, tabular so the figures line up; the compounding reads at a glance. */
.panel[data-panel="coinflip"] .coin-teaser-rung {
  color: var(--gold, #ffcf5c); font-weight: var(--fw-black, 700);
  font-variant-numeric: tabular-nums; text-shadow: 0 0 8px var(--gold-glow, rgba(255,207,92,.38));
}
.panel[data-panel="coinflip"] .coin-teaser-arrow,
.panel[data-panel="coinflip"] .coin-teaser-more { color: var(--muted, #9aa); }
/* the call-to-action tail — a brand-tinted "Chase the streak" cue that the strip is clickable. */
.panel[data-panel="coinflip"] .coin-teaser-cta {
  color: var(--violet, #a78bfa); font-weight: var(--fw-bold, 700);
  font-size: var(--fs-xs, 11px); white-space: nowrap;
}
.panel[data-panel="coinflip"] .coin-teaser-cta::after { content: ' →'; }
/* reduced motion — the teaser has no looping motion; only neutralise the hover/focus transitions. */
@media (prefers-reduced-motion: reduce) {
  .panel[data-panel="coinflip"] .coin-teaser { transition: none; }
}
