/* =============================================================================
   bust.fun — SLOTS styles  (games/slots/slots.css)
   -----------------------------------------------------------------------------
   Game-SPECIFIC styles for the Slots module. Synthwave tokens ONLY (tokens.css) —
   no hard-coded palette. The shared chrome (.panel / .preview / .preview .stat /
   .muted) is owned centrally in styles.css; this file only adds the slots-specific
   selectors (the reel stage, cells, win highlights, win-total, paytable).

   a11y: 0 horizontal overflow @360px (the 5-reel grid is fluid + min-width:0),
   reduced-motion-safe (the spin animation is gated off — reels resolve instantly).
   The interactive controls are the shared stake + Bet button (44px, owned centrally).
   ========================================================================== */

/* ---- The reel stage: 5 fluid reels, each a 3-row column. -------------------- */
.slots-stage {
  position: relative; /* anchor for the jackpot-burst reveal overlay */
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: var(--sp-2, 8px);
  /* FILL: the 5×3 reel grid grows with the viewport (square cells define the 5:3 height), centred. */
  width: min(100%, 920px, calc(64vh * 5 / 3));
  max-width: 100%;
  margin: var(--sp-3) auto;
  padding: var(--sp-3);
  background: linear-gradient(180deg, var(--surface-2), var(--bg-1));
  border: 1px solid var(--line-2);
  border-radius: var(--r-lg, 16px);
  box-shadow: inset 0 0 32px rgba(0, 0, 0, .5), 0 0 24px var(--brand-glow);
}

/* ---- Jackpot burst: a brief celebration graphic centered over the reels on a BIG/JACKPOT win
        (showLanding's jackpot path adds .show, then removes it). The supplied PNG has a near-black
        background, so screen-blend drops the dark and keeps the neon burst + JACKPOT text. Decorative,
        non-interactive, self-removing. Self-hosted (/img/selected/, CSP img-src 'self'). */
.slots-jackpot-burst {
  position: absolute;
  inset: 0;
  margin: auto;
  width: min(86%, 360px);
  aspect-ratio: 1 / 1;
  pointer-events: none;
  background: url("/img/selected/slot-jackpot-burst.png") center / contain no-repeat;
  mix-blend-mode: screen;
  opacity: 0;
  transform: scale(.6);
  z-index: 5;
}
.slots-jackpot-burst.show {
  animation: slots-jackpot-burst 1.6s var(--ease-out, cubic-bezier(.2,.8,.2,1)) both;
}
@keyframes slots-jackpot-burst {
  0%   { opacity: 0; transform: scale(.6) rotate(-6deg); }
  18%  { opacity: 1; transform: scale(1.04) rotate(0deg); }
  72%  { opacity: 1; transform: scale(1); }
  100% { opacity: 0; transform: scale(1.06); }
}
.slots-reel {
  position: relative;
  min-width: 0; /* allow shrink to avoid horizontal overflow at 360px */
  border-radius: var(--r-md, 12px);
}

/* ---- The clip WINDOW: the 3-row viewport that holds the static (settled) cells AND clips the
        spinning ribbon to exactly 3 rows. The static cells are the SETTLED face; the ribbon scrolls
        over them mid-spin, then hides at the landing so the visible face is the server outcome. ----- */
.slots-window {
  position: relative;
  display: flex;
  flex-direction: column;
  gap: var(--sp-2, 8px);
  min-width: 0;
  overflow: hidden;
  border-radius: var(--r-md, 12px);
}

/* ---- A symbol cell: a square-ish tile holding one glyph. ------------------- */
.slots-cell {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  aspect-ratio: 1 / 1;
  min-width: 0;
  background: var(--bg-1);
  border: 1px solid var(--line-2);
  border-radius: var(--r-sm, 8px);
  overflow: hidden;
  transition: box-shadow var(--dur-2), border-color var(--dur-2), opacity var(--dur-2),
    transform var(--dur-2);
}

/* ---- The spinning RIBBON: an absolutely-positioned column of symbol tiles that scrolls vertically
        past the clip window while a reel is in motion (JS drives translateY: a real decelerating reel
        that streams symbols in from above and settles on the result). Hidden (empty + no class) when a
        reel is idle/landed — the static cells show through. Sits OVER the static cells while spinning. */
.slots-strip {
  position: absolute;
  inset: 0 0 auto 0;
  display: flex;
  flex-direction: column;
  gap: var(--sp-2, 8px);
  will-change: transform;
  z-index: 3;
  pointer-events: none;
}
.slots-strip:empty { display: none; }
/* a strip tile is one cell tall (so 3 fill the window) — mirrors .slots-cell sizing exactly. */
.slots-strip-tile {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  aspect-ratio: 1 / 1;
  min-width: 0;
  flex: 0 0 auto;
  background: var(--bg-1);
  border: 1px solid var(--line-2);
  border-radius: var(--r-sm, 8px);
  overflow: hidden;
}
.slots-strip-tile img {
  width: 78%;
  height: 78%;
  object-fit: contain;
  -webkit-user-drag: none;
  user-select: none;
  filter:
    drop-shadow(0 1px 2px rgba(0, 0, 0, .55))
    drop-shadow(0 0 7px var(--sym-glow, var(--brand-glow)))
    drop-shadow(0 0 14px var(--sym-glow, var(--brand-glow)));
}
/* subtle motion blur on the moving ribbon (the JS handles the scroll; this just softens the streak). */
.slots-strip.spinning { filter: blur(0.5px); }
.slots-strip.spinning .slots-strip-tile img { filter:
    drop-shadow(0 0 6px var(--sym-glow, var(--brand-glow))); }
.slots-glyph {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
  line-height: 0;
}

/* ---- Per-symbol NEON GLOW tokens. -----------------------------------------
   Each symbol's themed glow colour (set per-img by slots.js as --sym-glow), used by the
   drop-shadow below. These are tokens.css derivatives ONLY (no hard-coded neon) so the whole
   set recolours with the theme. A reskin can re-point a symbol's glow by changing its `glow`
   in slots.js SYMBOL_IMG (the reskin hook). Scoped to the slots subtree so they don't leak. */
.slots-stage,
.slots-paytable {
  --sym-glow-cherry:  var(--accent-glow);            /* rose — low */
  --sym-glow-lemon:   var(--gold-glow);              /* gold — low */
  --sym-glow-plum:    var(--violet-glow);            /* violet — low */
  --sym-glow-bell:    var(--gold-glow);              /* gold — mid */
  --sym-glow-bar:     var(--brand-glow);             /* brand violet — high */
  --sym-glow-seven:   var(--accent-glow);            /* rose — higher */
  --sym-glow-diamond: var(--win-glow);               /* neon teal — TOP */
  --sym-glow-wild:    var(--brand-glow);             /* brand — WILD */
  --sym-glow-scatter: var(--gold-glow);              /* gold — SCATTER */
}

/* The raster symbol art fills the cell (fluid, transparent PNG on the dark well). The themed neon
   drop-shadow (per-symbol --sym-glow, set inline by slots.js) makes the symbol POP off the dark cell
   and RECOLOUR with the theme; a faint dark under-shadow keeps depth. Replaces the old SVG depth
   filter. --sym-glow falls back to --brand-glow if a reskin omits it. */
.slots-glyph img {
  width: 78%;
  height: 78%;
  object-fit: contain;
  -webkit-user-drag: none;
  user-select: none;
  filter:
    drop-shadow(0 1px 2px rgba(0, 0, 0, .55))
    drop-shadow(0 0 7px var(--sym-glow, var(--brand-glow)))
    drop-shadow(0 0 14px var(--sym-glow, var(--brand-glow)));
}

/* ---- Spinning: the REAL reel motion is the JS-driven .slots-strip ribbon (above). While a reel
        spins we just dim the static face slightly so the moving ribbon reads as the live layer. ----- */
.slots-reel.spinning .slots-window { box-shadow: inset 0 0 18px rgba(0, 0, 0, .45); }

/* ---- Anticipation: the LAST reel "teases" the verdict — a glowing pulse on the still-spinning
       reel after the others have stopped (suspense for a big win / scatters). ----------------- */
.slots-reel.anticipate {
  animation: slots-anticipate .5s var(--ease-out, cubic-bezier(.2,.8,.2,1)) infinite alternate;
}
@keyframes slots-anticipate {
  0%   { filter: none; }
  100% { filter: drop-shadow(0 0 12px var(--gold-glow, rgba(255,207,92,.6))); }
}
/* the moment a reel lands, give the column a brief settle pop. */
.slots-reel.landed { animation: slots-reel-land var(--dur-3, .36s) var(--ease-spring, cubic-bezier(.2,1.3,.3,1)) both; }
@keyframes slots-reel-land {
  0%   { transform: translateY(-6%); }
  60%  { transform: translateY(2%); }
  100% { transform: translateY(0); }
}

/* ---- Win highlight: a glowing ring on each winning cell; non-winners dim. --- */
.slots-cell.win {
  border-color: var(--win);
  box-shadow: 0 0 0 1px var(--win), 0 0 18px var(--win-glow);
  z-index: 2;
  animation: slots-cell-pulse 1s var(--ease-out, cubic-bezier(.2,.8,.2,1)) both;
}
.slots-cell.scatter-win {
  border-color: var(--gold);
  box-shadow: 0 0 0 1px var(--gold), 0 0 18px var(--gold-glow, rgba(255,207,92,.5));
  z-index: 2;
  animation: slots-cell-pulse 1s var(--ease-out, cubic-bezier(.2,.8,.2,1)) both;
}
.slots-cell.dim { opacity: .42; }

/* ---- "Matched but under 1×" cell: a spin that hit a line yet returned LESS than the stake (a net
        loss) must NOT wear the green "you won" ring. Give the matched cells a neutral AMBER ring (no
        green glow, no celebratory win-glow PNG, no scale-pop) so the player reads "matched, but under
        1×" at a glance instead of a fake win. Amber `--warn` is 10.6:1 on the dark well. --------- */
.slots-cell.matched-noprofit {
  border-color: var(--warn, #ffb84d);
  box-shadow: 0 0 0 1px var(--warn, #ffb84d), 0 0 12px var(--warn-glow, rgba(255,184,77,.42));
  z-index: 2;
}

/* Winning-cell ART overlay: the supplied win-line glow PNG laid over a winning/scatter cell to
   reinforce the highlight (on top of the box-shadow ring). Decorative + non-interactive. Self-hosted
   (/img/selected/, CSP img-src 'self'). Sits under the symbol's z-index so the symbol stays readable. */
.slots-cell.win::after,
.slots-cell.scatter-win::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: url("/img/selected/slot-win-line-glow.png") center / cover no-repeat;
  mix-blend-mode: screen;
  opacity: .85;
  z-index: 1;
  animation: slots-winglow-in var(--dur-3, .36s) var(--ease-out, cubic-bezier(.2,.8,.2,1)) both;
}
.slots-cell.win > .slots-glyph,
.slots-cell.scatter-win > .slots-glyph { position: relative; z-index: 2; }
@keyframes slots-winglow-in {
  0%   { opacity: 0; transform: scale(1.12); }
  100% { opacity: .85; transform: scale(1); }
}
@keyframes slots-cell-pulse {
  0%   { transform: scale(1.06); }
  60%  { transform: scale(.99); }
  100% { transform: scale(1); }
}

/* ---- Win-total readout under the reels. ------------------------------------ */
.slots-total {
  min-height: 1.6em;
  margin: var(--sp-2) auto var(--sp-1);
  text-align: center;
  font-family: var(--font-display);
  font-weight: var(--fw-bold);
  font-size: clamp(var(--fs-md, 16px), 5vw, var(--fs-xl, 28px));
  font-variant-numeric: tabular-nums;
  letter-spacing: .04em;
  color: var(--muted);
  opacity: 0;
  transition: opacity var(--dur-2);
  /* CLS hardening: the win readout is opacity-toggled (NOT display:none — the 1.6em line
     stays reserved when idle, which is correct), but a longer future string could wrap to
     a 2nd line and grow the box below the reserved 1.6em, nudging the centered .panel stack.
     nowrap pins it to one line so the bottom edge is invariant. KEEP the opacity toggle. */
  white-space: nowrap;
}
.slots-total.show { opacity: 1; }
.slots-total.win {
  color: var(--win);
  text-shadow: 0 0 18px var(--win-glow);
  animation: slots-total-pop var(--dur-3, .4s) var(--ease-spring, cubic-bezier(.2,1.3,.3,1)) both;
}
/* LOSS readout — a matched-but-under-1× spin is a NET LOSS. Make it visually LOUD (the destructive red
   `--lose`, 5:1 on bg, with the same spring-pop the win gets) so it can never be mistaken for the green
   win above it. The grey default `--muted` was too quiet under a vivid matched line (the headline bug). */
.slots-total.loss {
  color: var(--lose, #ef4444);
  text-shadow: 0 0 16px var(--lose-glow, rgba(239,68,68,.42));
  animation: slots-total-pop var(--dur-3, .4s) var(--ease-spring, cubic-bezier(.2,1.3,.3,1)) both;
}
@keyframes slots-total-pop {
  0%   { transform: scale(.8); }
  100% { transform: scale(1); }
}

/* ---- Visually-hidden live region (announces result/payout to screen readers). */
.slots-sr-status {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0;
}

/* ---- Collapsible paytable. ------------------------------------------------- */
.slots-paytable {
  margin: var(--sp-3) 0 var(--sp-2);
  border: 1px solid var(--line-2);
  border-radius: var(--r-md, 12px);
  background: var(--surface-2);
  padding: var(--sp-2) var(--sp-3);
}
.slots-paytable > summary {
  cursor: pointer;
  min-height: var(--touch, 44px);
  display: flex;
  align-items: center;
  font-family: var(--font-display);
  font-weight: var(--fw-semi);
  font-size: var(--fs-sm);
  color: var(--fg-dim);
}
.slots-paytable > summary:focus-visible { outline: 2px solid var(--violet); outline-offset: 2px; }
.slots-paytable-grid {
  display: grid;
  grid-template-columns: 1.4fr 1fr 1fr 1fr;
  gap: 4px 8px;
  margin: var(--sp-2) 0;
  align-items: center;
}
.slots-pt-h {
  font-size: var(--fs-xs); text-transform: uppercase; letter-spacing: .05em;
  color: var(--muted); font-weight: var(--fw-semi);
}
.slots-pt-sym {
  display: inline-flex; align-items: center; justify-content: center;
  line-height: 0;
}
/* Paytable symbol art — same per-symbol themed glow as the reels, a touch softer (it's a quiet key). */
.slots-pt-sym img {
  width: 28px; height: 28px; object-fit: contain;
  filter:
    drop-shadow(0 1px 1px rgba(0, 0, 0, .5))
    drop-shadow(0 0 5px var(--sym-glow, var(--brand-glow)));
}
.slots-pt-v {
  font-variant-numeric: tabular-nums; font-size: var(--fs-sm); color: var(--fg-dim);
}
.slots-pt-note { margin: var(--sp-1) 0 0; font-size: var(--fs-xs); }
/* inline role note for the wild/scatter paytable rows (spans the 3 multiplier columns). */
.slots-pt-note-inline {
  font-size: var(--fs-xs); color: var(--muted); align-self: center;
}

/* ---- WINNING-PAYLINE overlay: an SVG sized to the live stage box (viewBox === its px box, set by JS),
        so the polylines hit the exact cell centres at any grid size. Non-interactive; above the cells'
        win glow but below the jackpot burst. Each winning line = a soft halo under a crisp neon stroke,
        animated in with a stroke-dash "draw". Token-derived colours (set per-path by slots.js). ------ */
.slots-lines {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  z-index: 4;
  overflow: visible;
}
.slots-line-halo {
  fill: none;
  stroke-width: 7;
  stroke-linecap: round;
  stroke-linejoin: round;
  opacity: .28;
  filter: blur(2px);
}
.slots-line {
  fill: none;
  stroke-width: 2.5;
  stroke-linecap: round;
  stroke-linejoin: round;
  opacity: .95;
  filter: drop-shadow(0 0 4px currentColor);
}
/* the "draw" reveal: trace the line on landing. (pathLength normalises so one dash spans any length.) */
.slots-line.draw {
  pathLength: 1;
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
  animation: slots-line-draw .5s var(--ease-out, cubic-bezier(.2,.8,.2,1)) both,
    slots-line-pulse 1.6s var(--ease-out, cubic-bezier(.2,.8,.2,1)) .5s infinite;
}
@keyframes slots-line-draw { to { stroke-dashoffset: 0; } }
@keyframes slots-line-pulse { 0%,100% { opacity: .95; } 50% { opacity: .55; } }
/* a "matched but under 1×" (non-profit) line: trace it in once, but DON'T loop-pulse + sit a touch
   calmer than a real win line — it's a neutral amber, not a celebration. */
.slots-line.draw.noprofit {
  animation: slots-line-draw .5s var(--ease-out, cubic-bezier(.2,.8,.2,1)) both;
  opacity: .72;
}
.slots-line.noprofit { opacity: .72; }
/* the legend's hover/focus PREVIEW trace — faint + dashed, clearly distinct from a real win line. */
.slots-line.preview {
  stroke-width: 2;
  opacity: .5;
  stroke-dasharray: 5 6;
  filter: drop-shadow(0 0 3px currentColor);
}

/* ---- ACTIVE PAYLINES legend: the 20 lines the player is playing, as mini line-shape diagrams. ----- */
.slots-active-lines {
  margin: var(--sp-2) 0;
  border: 1px solid var(--line-2);
  border-radius: var(--r-md, 12px);
  background: var(--surface-2);
  padding: var(--sp-2) var(--sp-3);
}
.slots-active-lines > summary {
  cursor: pointer;
  min-height: var(--touch, 44px);
  display: flex;
  align-items: center;
  font-family: var(--font-display);
  font-weight: var(--fw-semi);
  font-size: var(--fs-sm);
  color: var(--fg-dim);
}
.slots-active-lines > summary:focus-visible { outline: 2px solid var(--violet); outline-offset: 2px; }
.slots-al-note { margin: var(--sp-1) 0 var(--sp-2); font-size: var(--fs-xs); }
.slots-active-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(64px, 1fr));
  gap: var(--sp-2, 8px);
}
.slots-al-chip {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 3px;
  padding: 5px 4px;
  background: var(--bg-1);
  border: 1px solid var(--line-2);
  border-radius: var(--r-sm, 8px);
  cursor: pointer;
  min-height: var(--touch, 44px);
  transition: border-color var(--dur-2), box-shadow var(--dur-2), transform var(--dur-2);
}
.slots-al-chip:hover,
.slots-al-chip:focus-visible {
  border-color: var(--al-color, var(--violet));
  box-shadow: 0 0 0 1px var(--al-color, var(--violet)), 0 0 12px color-mix(in srgb, var(--al-color, var(--violet)) 45%, transparent);
  transform: translateY(-1px);
  outline: none;
}
.slots-al-badge {
  font-size: var(--fs-xs);
  font-variant-numeric: tabular-nums;
  font-weight: var(--fw-semi);
  color: var(--al-color, var(--fg-dim));
}
.slots-al-diagram { width: 100%; height: auto; display: block; }
.slots-al-dot { fill: var(--line-2); }
.slots-al-dot.on { fill: var(--al-color, var(--violet)); }
.slots-al-path { fill: none; stroke-width: 1.4; stroke-linecap: round; stroke-linejoin: round; opacity: .9; }

/* ---- Reduced motion: no spin/draw/pulse/pop — reels + lines resolve instantly + legibly. ---------- */
@media (prefers-reduced-motion: reduce) {
  .slots-reel.spinning .slots-window,
  .slots-reel.landed,
  .slots-reel.anticipate,
  .slots-cell.win,
  .slots-cell.scatter-win,
  .slots-cell.win::after,
  .slots-cell.scatter-win::after,
  .slots-line.draw,
  .slots-total.win,
  .slots-total.loss { animation: none !important; }
  .slots-reel.anticipate { filter: none; }
  /* lines appear fully drawn (no trace animation) under reduced motion. */
  .slots-line.draw { stroke-dashoffset: 0; }
  /* no celebratory burst flash under reduced motion */
  .slots-jackpot-burst, .slots-jackpot-burst.show { display: none; }
}

/* ---- Narrow viewport: keep glyphs legible + the stage edge-to-edge @360px. -- */
@media (max-width: 400px) {
  /* On a phone the reels should fill the available WIDTH, not be height-capped to a small band: drop the
     `64vh*5/3` cap (which on a tall phone shrinks the reels into a sea of empty space — report #2) so the
     stage is the full column width. Trim the vertical margin so the reels + win-total + the Bet CTA pack
     into the viewport with less dead space above/below. The remaining centered dead-band is the shared
     display box (12-gameview.css min-height + justify-content:center) — flagged for the lead. */
  .slots-stage { width: 100%; max-width: 100%; margin: var(--sp-1) auto; padding: var(--sp-2); gap: 5px; }
  .slots-window { gap: 5px; }
  .slots-strip { gap: 5px; }
  .slots-active-grid { grid-template-columns: repeat(auto-fill, minmax(54px, 1fr)); }
}
