* {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

:root {
  --ice-blue: #0b3d5c;
  --ice-blue-dark: #05202f;
  --ice-white: #eaf6ff;
  --rink-line: #d63447;
  --gold: #ffcf4a;
  --gold-dark: #b8860b;
  --panel-bg: #0e2a3d;
  --panel-border: #1c4a66;
  --win-glow: #4affc0;
}

html, body { height: 100%; overflow: hidden; }

body {
  font-family: 'Segoe UI', Arial, sans-serif;
  background: #04121e;
  color: var(--ice-white);
}

/* One arena scene. Its grid reserves room for controls at every viewport. */
.app {
  position: relative;
  isolation: isolate;
  width: 100%;
  height: 100vh;
  height: 100dvh;
  display: grid;
  grid-template-rows: 86px minmax(0, 1fr) 112px;
  padding: env(safe-area-inset-top, 0px) env(safe-area-inset-right, 0px)
    env(safe-area-inset-bottom, 0px) env(safe-area-inset-left, 0px);
  background: linear-gradient(180deg, rgba(3,15,28,.35), rgba(3,15,28,.08) 55%, rgba(3,15,28,.88)),
    url('assets/background/arena.png') center / cover no-repeat;
}

/* ---------- topbar ---------- */

.topbar {
  position: relative;
  padding: 14px 16px;
  text-align: center;
  border-bottom: 2px solid var(--panel-border);
  background: linear-gradient(180deg, rgba(255,255,255,0.05), transparent);
}

/* Info button ("?") — top corner of the game screen, never over the grid. */
.info-btn {
  position: absolute;
  top: 12px;
  right: 14px;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  border: 2px solid var(--gold);
  background: rgba(14, 42, 61, 0.85);
  color: var(--gold);
  font-weight: 800;
  font-size: 15px;
  line-height: 1;
  cursor: pointer;
  z-index: 3;
}

.info-btn:active {
  transform: scale(0.94);
}

.logo {
  font-size: clamp(28px, 4.5vw, 54px);
  font-weight: 900;
  letter-spacing: 2px;
  color: var(--gold);
  text-shadow:
    0 0 14px rgba(255, 207, 74, 0.65),
    0 0 32px rgba(255, 207, 74, 0.35),
    0 3px 8px rgba(0,0,0,0.6);
}

.logo span {
  color: var(--ice-white);
  font-weight: 700;
  text-shadow:
    0 0 12px rgba(234, 246, 255, 0.4),
    0 3px 8px rgba(0,0,0,0.6);
}

/* Studio/publisher credit — kept as its own line, never merged into the
   game title text itself (Caziki is the studio, Ice Rush is the game). */
.studio-byline {
  margin-top: 2px;
  font-size: 10px;
  font-weight: 600;
  letter-spacing: 2px;
  color: #7fb2cf;
  text-transform: uppercase;
}

/* ---------- stage ---------- */

.stage {
  position: relative;
  min-height: 0;
  min-width: 0;
  container-type: size;
  display: flex;
  align-items: center;
  justify-content: center;
  margin: 0 24px;
}

/* The playable field owns its dimensions; artwork never dictates cell placement. */
.frame-wrap {
  position: relative;
  width: min(100%, 1060px, calc((100cqh - 64px) * 5 / 3));
  aspect-ratio: 5 / 3;
  flex: none;
  margin-top: 34px;
  border: 6px solid #c0d1da;
  border-radius: 14px;
  background: linear-gradient(145deg, #effaff, #c2e0ed);
  box-shadow: 0 0 0 3px #263e51, 0 12px 30px #00111d99;
  overflow: hidden;
}

/* Free Spins visual theme — the frame art itself is untouched; a warm glow
   is layered on top via box-shadow (outer edge) and a ::after tint (matching
   the icy-screen percentages below) instead. */
.stage.free-spins-theme .frame-wrap {
  box-shadow: 0 0 28px 4px rgba(255, 159, 60, 0.45);
  border-radius: 6px;
}

.frame-wrap::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: 0;
  background: rgba(255, 178, 53, .12);
  transition: opacity .4s ease;
}
.stage.free-spins-theme .frame-wrap::after { opacity: 1; }

.reels-wrap { position: absolute; inset: 5px; }
.reels {
  position: relative;
  width: 100%;
  height: 100%;
  display: grid;
  grid-template-columns: repeat(5, minmax(0, 1fr));
  align-content: stretch;
  gap: 0;
  padding: 1px;
}

/* Each .reel is a fixed-height clipped window; its height is locked in px by
   game.js (lockReelHeights) right after layout, so inserting extra filler
   rows during a spin never expands the grid — they're just clipped. Grid
   items stretch to their row's cross-size by default, so with .reels'
   align-content:stretch above, .reel naturally fills the full grid height
   pre-lock (no explicit height needed here). */
.reel {
  position: relative;
  overflow: hidden;
}

/* Thin mechanical-reel seams between columns (not rows) — the columns sit
   flush (column-gap: 0 above) so this reads as one drum, not five separate
   strips with visible air between them. */
.reel:not(:last-child) {
  border-right: 1.5px solid rgba(0, 0, 0, 0.15);
}

.reel-strip {
  display: flex;
  flex-direction: column;
  height: 100%;
  gap: 1px;
  width: 100%;
}

/* transform/filter (blur) during a spin are both driven per-phase by inline
   styles set in game.js's spinOneReel (kickoff/cruise/brake) — see that
   function for why a single CSS transition can't express all three phases. */
.reel.spinning .reel-strip {
  will-change: transform, filter;
}

/* A sticky Jersey that already existed before this spin: game.js pins one
   of these over the reel-strip at the exact row it occupies (top/height set
   inline, matching the resting cell's real rect) for the whole spin — it
   never gets a transform of its own, so it visually stays put while the
   strip scrolls underneath and through the other rows normally. Removed
   again once the reel settles, since the resting strip shows the identical
   cell underneath by then. */
.cell.sticky-frozen-cell {
  /* Higher specificity than the base .cell rule (which sets position:relative
     and flex:1 1 0) — this must win regardless of source order, since it's
     not a flex item of .reel-strip at all, just a plain absolutely-positioned
     child of .reel. */
  position: absolute;
  left: 0;
  width: 100%;
  flex: none;
  z-index: 1;
}

.cell {
  /* Symbols share the ice surface; three equal cells fill each reel. */
  position: relative;
  flex: 1 1 0;
  min-height: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: clamp(22px, 6vw, 34px);
  font-weight: 800;
  color: var(--ice-white);
  transition: transform 0.15s ease;
  user-select: none;
}

.symbol-img {
  width: 96%;
  height: 96%;
  object-fit: contain;
  pointer-events: none;
  user-select: none;
  display: block;
  /* Stands in for the old card background — grounds the symbol against the
     light ice without boxing it in. */
  filter: drop-shadow(0 2px 4px rgba(0,0,0,0.25));
}

.symbol-glyph-fallback {
  /* Used only if a PNG fails to load — same size/weight as the old glyph-only cells. */
  font-size: inherit;
  font-weight: inherit;
  line-height: 1;
  text-shadow: 0 2px 4px rgba(0,0,0,0.35);
}

.cell.patch .symbol-glyph-fallback {
  font-family: 'Georgia', serif;
  color: var(--gold);
}

/* GOAL is the scatter/bonus-trigger symbol — standard slot convention is for
   it to visually dominate its cell so it reads as special at a glance. Pure
   transform (no layout impact), so it can overlap into neighboring cells'
   space without disturbing the grid — .cell has no overflow:hidden to clip it. */
.cell.sym-GOAL .symbol-img {
  transform: scale(1.2);
}

/* ZUBR is the top-paying symbol (CONFIG.TOP_SYMBOL) — sized up the same way
   as GOAL above so the grid reads a size hierarchy (premium > scatter-ish >
   base), not one flat symbol size regardless of tier. */
.cell.sym-ZUBR .symbol-img {
  transform: scale(1.15);
}

/* Every JERSEY on the grid during Free Spins is sticky (see engine.js's
   session.stickyJerseys) — a persistent gold glow marks it as locked in
   place for the rest of the bonus, distinct from the one-off pop-in
   animation (.symbol-img.jersey-scale-in, below) that plays only the spin
   it lands. */
.cell.sym-JERSEY .symbol-img {
  filter:
    drop-shadow(0 0 3px rgba(0,0,0,0.4))
    drop-shadow(0 0 8px var(--gold))
    drop-shadow(0 0 16px rgba(255, 207, 74, 0.55))
    drop-shadow(0 2px 4px rgba(0,0,0,0.25));
}

/* ---------- goal-trigger highlight ---------- */
/* No cell background to fill — the highlight is a glow hugging the symbol's
   own silhouette (filter: drop-shadow on the img/glyph) plus a gentle scale
   pulse on the cell. (Winning-line presentation used to share this same
   pulse+glow treatment — see the per-symbol win-anim-* keyframes below for
   what replaced it; GOAL never pays a line itself, so this stays the only
   thing using cell-pulse now.) */

.cell.goal-highlight {
  animation: cell-pulse 0.5s ease-in-out infinite;
  z-index: 2;
}

.cell.goal-highlight .symbol-img,
.cell.goal-highlight .symbol-glyph-fallback {
  filter:
    drop-shadow(0 0 2px rgba(0,0,0,0.45))
    drop-shadow(0 0 7px var(--rink-line))
    drop-shadow(0 0 18px var(--rink-line))
    drop-shadow(0 2px 4px rgba(0,0,0,0.25));
}

@keyframes cell-pulse {
  0%, 100% { transform: scale(1); }
  50% { transform: scale(1.08); }
}

/* ---------- winning-symbol animations ---------- */
/* Each symbol that actually took part in a winning line plays its own
   gesture (game.js playSymbolWinAnimation adds the class) instead of the
   line being outlined/filled. Low tier shares one simple bounce; each
   roster character gets a bespoke gesture. Every rule below loops
   (animation-iteration-count: infinite) — a short pattern repeating, not a
   long single playback — for as long as this spin's result is on screen;
   game.js's clearWinAnimations stops it exactly when the next spin starts,
   not the animation completing on its own (each keyframe's 0%/100% state
   already matches, so the loop point is seamless, no visible snap). */

@keyframes win-anim-jump {
  0% { transform: scale(1); }
  50% { transform: scale(1.09); }
  100% { transform: scale(1); }
}

.win-anim-jump {
  /* Softer than the roster gestures on purpose — a gentle pulse, not a
     snappy bounce: smaller amplitude, slower cycle, no overshoot easing. */
  animation: win-anim-jump 580ms cubic-bezier(.4, 0, .2, 1) infinite;
}

/* WOLF — a coach's nod. */
@keyframes win-anim-wolf {
  0% { transform: rotate(0deg); }
  33% { transform: rotate(-6deg); }
  66% { transform: rotate(4deg); }
  100% { transform: rotate(0deg); }
}

.win-anim-wolf {
  transform-origin: bottom center;
  animation: win-anim-wolf 400ms ease-in-out infinite;
}

/* BEAR — a heavy, goalie-stance stomp (vertical squash-and-stretch). */
@keyframes win-anim-bear {
  0% { transform: scaleY(1) scaleX(1); }
  30% { transform: scaleY(0.85) scaleX(1.1); }
  60% { transform: scaleY(1.05) scaleX(1); }
  100% { transform: scaleY(1) scaleX(1); }
}

.win-anim-bear {
  animation: win-anim-bear 350ms ease-in-out infinite;
}

/* TIGER — a fast, aggressive jitter: the 300ms shake pattern itself is
   unchanged, just repeated indefinitely instead of stopping after 2 reps. */
@keyframes win-anim-tiger {
  0% { transform: translateX(0) rotate(0deg); }
  25% { transform: translateX(-4px) rotate(-3deg); }
  50% { transform: translateX(4px) rotate(3deg); }
  75% { transform: translateX(-2px) rotate(0deg); }
  100% { transform: translateX(0) rotate(0deg); }
}

.win-anim-tiger {
  animation: win-anim-tiger 300ms ease-in-out infinite;
}

/* ZUBR — the most expressive of the four (it's the top symbol): a victory
   jump. Layered on top of its permanent scale(1.15) size-hierarchy bump
   (see .cell.sym-ZUBR .symbol-img above) rather than replacing it, so the
   animation doesn't visibly "shrink" ZUBR back to baseline for a frame. */
@keyframes win-anim-zubr {
  0% { transform: scale(1.15) translateY(0); }
  40% { transform: scale(1.4375) translateY(-8px); }
  70% { transform: scale(1.265) translateY(0); }
  100% { transform: scale(1.15) translateY(0); }
}

.win-anim-zubr {
  animation: win-anim-zubr 450ms cubic-bezier(.34, 1.56, .64, 1) infinite;
}

/* ---------- jersey landing pop ---------- */
/* The rolled multiplier is now baked directly into jersey_2x.png/jersey_3x.png
   (see config.js JERSEY_VALUE_IMAGES) — no more separate text overlay node.
   This just replays the same landing "pop" on the symbol image itself,
   centered via .cell's flex centering so no translate(-50%,-50%) hack is
   needed (unlike the old absolutely-positioned text overlay). */

.symbol-img.jersey-scale-in {
  animation: jersey-scale-in 0.45s cubic-bezier(0.34, 1.56, 0.64, 1) both;
}

@keyframes jersey-scale-in {
  0% { transform: scale(0); opacity: 0; }
  60% { transform: scale(1.15); opacity: 1; }
  100% { transform: scale(1); opacity: 1; }
}

/* ---------- win banner (normal win, small pill) ---------- */

.win-banner {
  position: absolute;
  top: 8px;
  left: 50%;
  transform: translate(-50%, -12px);
  display: flex;
  align-items: baseline;
  gap: 8px;
  padding: 8px 20px;
  background: linear-gradient(180deg, var(--gold), var(--gold-dark));
  color: #241800;
  font-weight: 800;
  border-radius: 999px;
  box-shadow: 0 6px 18px rgba(0,0,0,0.4);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.2s ease, transform 0.2s ease;
  z-index: 5;
  white-space: nowrap;
}

.win-banner.visible {
  opacity: 1;
  transform: translate(-50%, 0);
}

#winBannerLabel {
  font-size: 13px;
  letter-spacing: 2px;
}

#winBannerAmount {
  font-size: 20px;
}

/* ---------- jersey landing popup ---------- */

.jersey-popup {
  position: absolute;
  top: 56px;
  left: 50%;
  transform: translate(-50%, -8px);
  padding: 6px 14px;
  background: var(--panel-bg);
  border: 1px solid var(--win-glow);
  color: var(--win-glow);
  font-weight: 800;
  font-size: 13px;
  letter-spacing: 0.5px;
  border-radius: 999px;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.2s ease, transform 0.2s ease;
  z-index: 7;
  white-space: nowrap;
  text-align: center;
}

.jersey-popup.visible {
  opacity: 1;
  transform: translate(-50%, 0);
}

/* ---------- free spins / multiplier badges ---------- */

.free-spins-info {
  display: none;
  gap: 8px;
  margin-bottom: 10px;
}

.free-spins-info.visible {
  display: flex;
}

.free-spins-badge,
.multiplier-badge {
  padding: 6px 14px;
  background: var(--panel-bg);
  border: 1px solid var(--gold);
  border-radius: 999px;
  color: var(--gold);
  font-weight: 700;
  font-size: 13px;
  letter-spacing: 0.5px;
  text-align: center;
}

.multiplier-badge {
  border-color: var(--win-glow);
  color: var(--win-glow);
  transition: transform 0.1s ease;
}

.multiplier-badge.pulse {
  animation: multiplier-pulse 0.5s ease-out;
}

@keyframes multiplier-pulse {
  0% { transform: scale(1); box-shadow: 0 0 0 rgba(74,255,192,0); }
  40% { transform: scale(1.2); box-shadow: 0 0 16px var(--win-glow); }
  100% { transform: scale(1); box-shadow: 0 0 0 rgba(74,255,192,0); }
}

/* ---------- free spins summary plaque ---------- */

.summary-banner {
  position: absolute;
  top: 8px;
  left: 50%;
  transform: translate(-50%, -12px);
  max-width: 92%;
  padding: 10px 18px;
  background: linear-gradient(180deg, var(--win-glow), #0b8f6a);
  color: #012019;
  font-weight: 800;
  font-size: 13px;
  letter-spacing: 0.3px;
  border-radius: 999px;
  box-shadow: 0 6px 18px rgba(0,0,0,0.4);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.2s ease, transform 0.2s ease;
  z-index: 6;
  text-align: center;
}

.summary-banner.visible {
  opacity: 1;
  transform: translate(-50%, 0);
}

/* ---------- full-screen presentation overlays ---------- */

.fullscreen-overlay {
  position: fixed;
  inset: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  z-index: 200;
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.3s ease;
  text-align: center;
  padding: 24px;
  background: rgba(2, 8, 14, 0.88);
}

.fullscreen-overlay.visible {
  opacity: 1;
}

@keyframes overlay-text-pop-in {
  0% { transform: scale(0.4); opacity: 0; }
  100% { transform: scale(1); opacity: 1; }
}

.pop-in {
  animation: overlay-text-pop-in 0.35s cubic-bezier(0.34, 1.56, 0.64, 1) both;
}

/* Bonus transition: "GOAL! GOAL! GOAL!" -> "N FREE SPINS" */

.bonus-transition-text {
  font-family: Impact, 'Arial Narrow Bold', 'Franklin Gothic Bold', sans-serif;
  font-weight: 900;
  font-size: clamp(24px, 9vw, 46px);
  color: var(--ice-white);
  -webkit-text-stroke: 2px var(--rink-line);
  text-shadow: 0 0 26px var(--rink-line), 0 4px 10px rgba(0,0,0,0.6);
  max-width: 90vw;
}

/* Bonus Buy confirmation modal — unlike the other fullscreen overlays above
   (auto-timed, purely presentational), this one has real buttons, so it
   needs pointer-events restored when visible (the base .fullscreen-overlay
   rule sets pointer-events:none so a fading-out overlay can't eat clicks). */

.buy-bonus-modal.visible {
  pointer-events: auto;
}

.buy-bonus-modal-box {
  background: var(--panel-bg);
  border: 2px solid var(--gold);
  border-radius: 14px;
  padding: 24px 22px;
  max-width: 340px;
  width: 100%;
  box-shadow: 0 12px 40px rgba(0,0,0,0.6);
}

.buy-bonus-modal-title {
  font-family: Impact, 'Arial Narrow Bold', 'Franklin Gothic Bold', sans-serif;
  font-weight: 900;
  font-size: clamp(20px, 6vw, 28px);
  letter-spacing: 1px;
  color: var(--gold);
  text-shadow: 0 0 16px rgba(255, 207, 74, 0.5);
  margin-bottom: 12px;
}

.buy-bonus-modal-body {
  font-size: 14px;
  color: var(--ice-white);
  line-height: 1.5;
  margin-bottom: 20px;
}

.buy-bonus-modal-actions {
  display: flex;
  gap: 10px;
  justify-content: center;
}

.modal-btn {
  flex: 1;
  padding: 12px 10px;
  border-radius: 8px;
  border: none;
  font-weight: 800;
  font-size: 13px;
  letter-spacing: 0.5px;
  cursor: pointer;
}

.modal-btn:active {
  transform: scale(0.96);
}

.modal-btn-cancel {
  background: var(--panel-border);
  color: var(--ice-white);
}

.modal-btn-confirm {
  background: linear-gradient(180deg, var(--gold), var(--gold-dark));
  color: #241800;
}

/* ---------- info modal (paytable + how to play) ---------- */

.info-modal.visible {
  pointer-events: auto;
}

.info-modal-box {
  position: relative;
  background: var(--panel-bg);
  border: 2px solid var(--gold);
  border-radius: 14px;
  padding: 22px 18px 18px;
  max-width: 460px;
  width: 100%;
  max-height: 82vh;
  box-shadow: 0 12px 40px rgba(0,0,0,0.6);
  display: flex;
  flex-direction: column;
}

.info-modal-close {
  position: absolute;
  top: 10px;
  right: 10px;
  width: 28px;
  height: 28px;
  border-radius: 50%;
  border: none;
  background: rgba(255,255,255,0.08);
  color: var(--ice-white);
  font-size: 14px;
  cursor: pointer;
}

.info-modal-close:active {
  transform: scale(0.94);
}

.info-modal-scroll {
  overflow-y: auto;
  padding-right: 4px;
}

.info-section {
  margin-bottom: 22px;
}

.info-section:last-child {
  margin-bottom: 0;
}

.info-section-title {
  font-family: Impact, 'Arial Narrow Bold', 'Franklin Gothic Bold', sans-serif;
  font-weight: 900;
  font-size: 20px;
  letter-spacing: 1px;
  color: var(--gold);
  text-shadow: 0 0 14px rgba(255, 207, 74, 0.4);
  margin-bottom: 12px;
  padding-top: 8px;
}

/* Paytable rows */

.info-paytable-row {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 8px 0;
  border-bottom: 1px solid rgba(255,255,255,0.08);
}

.info-paytable-row:last-child {
  border-bottom: none;
}

.info-symbol-icon {
  width: 40px;
  height: 40px;
  flex: none;
  object-fit: contain;
  filter: drop-shadow(0 2px 4px rgba(0,0,0,0.4));
}

.info-symbol-glyph-fallback {
  width: 40px;
  height: 40px;
  flex: none;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 22px;
  font-weight: 800;
  font-family: 'Georgia', serif;
  color: var(--gold);
}

.info-paytable-main {
  flex: 1;
  min-width: 0;
}

.info-symbol-label {
  font-size: 13px;
  font-weight: 700;
  color: var(--ice-white);
}

.info-symbol-payouts {
  font-size: 12px;
  color: #9fc7de;
  font-variant-numeric: tabular-nums;
  margin-top: 2px;
}

.info-symbol-special-desc {
  font-size: 12px;
  color: #9fc7de;
  line-height: 1.4;
  margin-top: 2px;
}

/* How-to-play prose */

.info-howto p {
  font-size: 13px;
  line-height: 1.55;
  color: var(--ice-white);
  margin-bottom: 12px;
}

.info-howto p:last-child {
  margin-bottom: 0;
}

.info-howto strong {
  color: var(--gold);
}

/* Win-tier overlay: shared by BIG / MEGA / MAX, styled per tier below */

.win-tier-overlay {
  position: fixed;
}

.win-tier-flash {
  position: absolute;
  inset: 0;
  background: radial-gradient(circle, #fff 0%, var(--gold) 45%, transparent 75%);
  opacity: 0;
  pointer-events: none;
}

.win-tier-flash.flash {
  animation: win-tier-flash-anim 0.3s ease-out;
}

@keyframes win-tier-flash-anim {
  0% { opacity: 0; }
  15% { opacity: 0.95; }
  100% { opacity: 0; }
}

.win-tier-label {
  font-family: Impact, 'Arial Narrow Bold', 'Franklin Gothic Bold', sans-serif;
  font-weight: 900;
  font-size: clamp(26px, 10vw, 50px);
  letter-spacing: 1px;
  color: #fff;
  -webkit-text-stroke: 2px var(--gold-dark);
  text-shadow: 0 0 24px var(--gold), 0 4px 10px rgba(0,0,0,0.6);
  margin-bottom: 10px;
  max-width: 90vw;
}

.win-tier-amount {
  font-family: Impact, 'Arial Narrow Bold', 'Franklin Gothic Bold', sans-serif;
  font-weight: 900;
  font-size: clamp(34px, 13vw, 64px);
  color: var(--gold);
  -webkit-text-stroke: 1.5px #4a2f00;
  text-shadow: 0 4px 14px rgba(0,0,0,0.6);
  font-variant-numeric: tabular-nums;
}

.win-tier-overlay.tier-mega .win-tier-label,
.win-tier-overlay.tier-mega .win-tier-amount {
  color: #ff9a3c;
}

.win-tier-overlay.tier-mega .win-tier-label {
  text-shadow: 0 0 30px #ff6a00, 0 4px 10px rgba(0,0,0,0.6);
}

.win-tier-overlay.tier-max .win-tier-label,
.win-tier-overlay.tier-max .win-tier-amount {
  color: var(--win-glow);
}

.win-tier-overlay.tier-max .win-tier-label {
  text-shadow: 0 0 34px var(--win-glow), 0 4px 10px rgba(0,0,0,0.6);
}

/* ---------- confetti ---------- */

.confetti-layer {
  position: absolute;
  inset: 0;
  overflow: hidden;
  pointer-events: none;
}

.confetti-piece {
  position: absolute;
  top: -12px;
  width: 8px;
  height: 14px;
  border-radius: 2px;
  animation-name: confetti-fall;
  animation-timing-function: ease-in;
  animation-fill-mode: forwards;
  will-change: transform, opacity;
}

@keyframes confetti-fall {
  0% {
    transform: translateY(0) translateX(0) rotate(0deg);
    opacity: 1;
  }
  100% {
    transform: translateY(85vh) translateX(var(--drift, 0px)) rotate(var(--rot, 180deg));
    opacity: 0;
  }
}

/* ---------- dev-only test helpers (Step 2/3/5 QA, remove before ship) ---------- */

.dev-tools {
  /* Anchored below the topbar (not the HUD) so it can never overlap the bet
     controls or spin button at narrow/short viewports — confirmed via
     Step 6 QA that a bottom-anchored panel collided with the bet "+" button
     at 375px width. */
  position: fixed;
  right: 8px;
  top: 64px;
  z-index: 250;
  display: flex;
  flex-direction: column;
  gap: 4px;
  align-items: flex-end;
  max-width: 46vw;
}

.dev-tool {
  padding: 6px 10px;
  background: rgba(20, 10, 10, 0.85);
  color: #ff9a9a;
  border: 1px dashed #ff5f5f;
  border-radius: 6px;
  font-size: 11px;
  cursor: pointer;
}

.dev-tool:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

/* ---------- hud ---------- */

.hud {
  display: grid;
  grid-template-columns: 1fr 1fr auto auto 1fr;
  grid-template-areas: "balance bet spin buy win";
  align-items: center;
  gap: 10px;
  padding: 14px 12px 20px;
  border-top: 2px solid var(--panel-border);
  background: linear-gradient(0deg, rgba(0,0,0,0.35), transparent);
}

.balance-panel { grid-area: balance; }
.bet-panel { grid-area: bet; }
.spin-btn { grid-area: spin; }
.buy-bonus-btn { grid-area: buy; }
.win-panel { grid-area: win; }

.hud-panel {
  background: var(--panel-bg);
  border: 1px solid var(--panel-border);
  border-radius: 10px;
  padding: 8px 10px;
  text-align: center;
}

.hud-label {
  font-size: 10px;
  text-transform: uppercase;
  letter-spacing: 1px;
  color: #7fb2cf;
  margin-bottom: 2px;
}

.hud-value {
  font-size: 16px;
  font-weight: 700;
  color: var(--ice-white);
  font-variant-numeric: tabular-nums;
}

.bet-control {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 6px;
}

.bet-btn {
  /* >=44px touch target per mobile guidelines (was 26px). */
  width: 44px;
  height: 44px;
  flex: none;
  border: none;
  border-radius: 8px;
  background: var(--panel-border);
  color: var(--ice-white);
  font-size: 18px;
  font-weight: 700;
  cursor: pointer;
  line-height: 1;
}

.bet-btn:active {
  transform: scale(0.92);
}

.bet-btn:disabled {
  opacity: 0.4;
  cursor: not-allowed;
}

.spin-btn {
  width: 68px;
  height: 68px;
  border-radius: 50%;
  border: 4px solid var(--gold-dark);
  background: radial-gradient(circle at 35% 30%, #ff5f6d, var(--rink-line) 70%);
  color: #fff;
  font-weight: 800;
  font-size: 14px;
  letter-spacing: 1px;
  cursor: pointer;
  box-shadow: 0 6px 16px rgba(0,0,0,0.5);
}

.spin-btn:active {
  transform: scale(0.96);
}

.spin-btn:disabled {
  opacity: 0.55;
  cursor: not-allowed;
  filter: grayscale(0.3);
}

.buy-bonus-btn {
  padding: 10px 14px;
  border-radius: 10px;
  border: 2px solid var(--gold-dark);
  background: linear-gradient(180deg, var(--gold), var(--gold-dark));
  color: #241800;
  font-weight: 800;
  font-size: 12px;
  letter-spacing: 0.5px;
  cursor: pointer;
  white-space: nowrap;
}

.buy-bonus-btn:active {
  transform: scale(0.96);
}

.buy-bonus-btn:disabled {
  opacity: 0.4;
  cursor: not-allowed;
  filter: grayscale(0.4);
}

/* Scene chrome shares the arena instead of separate page sections. */
.topbar {
  align-self: center;
  width: 100%;
  padding: 8px 64px;
  background: none;
  border: 0;
}
.logo {
  font-family: Impact, 'Arial Narrow', sans-serif;
  font-size: 42px;
  font-style: italic;
  letter-spacing: 2px;
  text-shadow: 0 3px 0 #102332, 0 5px 12px #00101c;
}
.logo span { text-shadow: inherit; }
.studio-byline { color: #d0e7f4; font-size: 9px; letter-spacing: 4px; }
.info-btn {
  top: 50%; right: 24px; transform: translateY(-50%);
  width: 44px; height: 44px; border: 1px solid #8399aa;
  background: #071c2ddd; color: white;
}
.info-btn:active { transform: translateY(-50%) scale(.95); }
.hud {
  width: min(100% - 48px, 1060px);
  justify-self: center;
  align-self: center;
  grid-template-columns: 1fr 1.35fr 1fr auto auto;
  grid-template-areas: 'balance bet win buy spin';
  gap: 18px;
  padding: 10px 20px;
  border: 1px solid #7596ac66;
  border-radius: 16px;
  background: #061b2deb;
}
.hud-panel { min-width: 0; background: none; border: 0; padding: 0; }
.hud-label { color: #abc2d2; font-size: 10px; }
.hud-value { font-size: 20px; }
.bet-control { justify-content: center; gap: 12px; }
.bet-btn { background: #203e53; border-radius: 50%; }
.spin-btn {
  width: 76px; height: 76px; border: 3px solid #f5d289;
  background: #ca3047; box-shadow: 0 4px 0 #701b2d;
}
.buy-bonus-btn {
  min-height: 44px; background: #f2c66c; border: 0; border-radius: 8px;
}
.free-spins-info { position: absolute; top: 0; margin: 0; z-index: 6; }
.free-spins-badge, .multiplier-badge { font-size: 11px; padding: 7px 12px; }
.win-banner, .summary-banner { top: 0; }
.stage.free-spins-theme .win-banner { top: 34px; }
.jersey-popup { top: 36px; }
button { touch-action: manipulation; }
button:focus-visible { outline: 3px solid white; outline-offset: 3px; }

@media (max-aspect-ratio: 4/5), (max-width: 680px) and (min-height: 541px) {
  .app { grid-template-rows: 90px minmax(0, 1fr) 188px; }
  .stage { margin: 0 10px; }
  .frame-wrap { border-width: 4px; border-radius: 10px; }
  .reels-wrap { inset: 2px; }
  .logo { font-size: 36px; }
  .info-btn { right: 12px; }
  .hud {
    width: calc(100% - 20px);
    grid-template-columns: 1fr 1.2fr 1fr;
    grid-template-areas: 'balance bet win' 'buy spin .';
    gap: 10px 8px;
    padding: 12px;
  }
  .hud-value { font-size: 16px; }
  .hud-label { font-size: 9px; }
  .bet-control { gap: 4px; }
  .bet-btn { width: 44px; height: 44px; }
  .spin-btn { justify-self: center; width: 72px; height: 72px; }
  .buy-bonus-btn { padding: 8px; font-size: 10px; white-space: normal; }
  .free-spins-info { gap: 4px; }
  .free-spins-badge, .multiplier-badge { font-size: 9px; padding: 6px 8px; }
}

@media (max-height: 540px) and (min-aspect-ratio: 4/5) {
  .app { grid-template-rows: 48px minmax(0, 1fr) 76px; }
  .topbar { padding: 2px 60px; }
  .logo { font-size: 25px; }
  .studio-byline { font-size: 7px; }
  .stage { margin: 0 12px; }
  .frame-wrap { width: min(100%, calc((100cqh - 38px) * 5 / 3)); margin-top: 28px; border-width: 4px; }
  .hud { width: calc(100% - 24px); padding: 5px 12px; gap: 10px; border-radius: 12px; }
  .hud-value { font-size: 16px; }
  .spin-btn { width: 56px; height: 56px; font-size: 11px; }
  .buy-bonus-btn { font-size: 10px; }
  .free-spins-badge, .multiplier-badge { font-size: 9px; padding: 5px 8px; }
}
