/* ==================================================================
   LUCKY TURNTABLE — STYLESHEET
   Sections:
   1. Fonts / Reset          12. Spin Button
   2. Design Tokens          13. Control Deck
   3. Canvas / Scaling       14. Bottom Wallet
   4. Background             15. Result Modal
   5. Header / Title         16. Toasts
   6. Mode Tabs              17. Particle Effects
   7. Info Bar               18. States
   8. Turntable Machine      19. Animations
   9. Bulbs                  20. Performance Mode
   10. Prize Cards           21. Reduced Motion / Responsive
   11. (reserved)
   ================================================================== */

/* ------------------------------------------------------------------
   1. FONTS / RESET
   ------------------------------------------------------------------ */
*, *::before, *::after { box-sizing: border-box; }

html, body {
  margin: 0;
  padding: 0;
  width: 100%;
  height: 100%;
  background: #0a0420;
  overflow-x: hidden;
  /* Global default so EVERY element — including the result/history/rules
     modals and toasts, which live outside #luckyGame in the DOM and so
     don't inherit its font-family — gets our UI font, not the browser's
     serif default. Baloo 2 is opted into specifically where needed. */
  font-family: var(--font-ui);
}

button {
  font-family: inherit;
  border: none;
  background: none;
  cursor: pointer;
  -webkit-tap-highlight-color: transparent;
  user-select: none;
  -webkit-user-select: none;
}

img { -webkit-user-drag: none; user-select: none; }

/* ------------------------------------------------------------------
   2. DESIGN TOKENS
   ------------------------------------------------------------------ */
:root {
  --game-width: 375px;
  --game-height: 646px;
  --game-scale: 1;

  /* Core palette */
  --purple-950: #0d0432;
  --purple-900: #1a0a52;
  --purple-800: #2a1580;
  --purple-700: #3d1fa8;
  --purple-600: #5941dc;
  --purple-500: #7b5cf0;

  --pink: #ef65ff;
  --pink-soft: #ff9dfb;
  --cyan: #65e7ff;

  --gold: #ffd84d;
  --gold-light: #fff5a4;
  --gold-dark: #ee8c00;

  --text-main: #ffffff;
  --text-soft: #ddd8ff;
  --text-muted: #b3a8e8;

  --panel-dark: rgba(20, 8, 60, 0.72);
  --panel-light: rgba(255, 255, 255, 0.08);
  --card-face: linear-gradient(180deg, #fbf7ff 0%, #ece3ff 100%);
  --card-border: #7454d6;

  /* Typography — Baloo 2 for display/headline text (rounded, playful,
     high weight, reads as "game" at a glance), Nunito for UI/body copy
     (clean, rounded terminals so it pairs naturally with Baloo 2 without
     feeling like two unrelated typefaces). Both fall back gracefully to
     system fonts if the network font can't load. */
  --font-display: "Baloo 2", "Arial Rounded MT Bold", "Trebuchet MS", system-ui, sans-serif;
  --font-ui: "Nunito", "Trebuchet MS", system-ui, -apple-system, sans-serif;
  --font-number: "Nunito", "Trebuchet MS", system-ui, sans-serif;

  /* Shadows / radii */
  --radius-lg: 22px;
  --radius-md: 14px;
  --radius-sm: 8px;

  /* Motion — one small vocabulary of easing curves instead of plain
     "ease" scattered everywhere, so every interaction feels like it
     belongs to the same, deliberately-tuned system. */
  --ease-snappy: cubic-bezier(0.16, 1, 0.3, 1);   /* quick, confident settle — taps/presses */
  --ease-standard: cubic-bezier(0.4, 0, 0.2, 1);  /* smooth deceleration — fades/reveals */
  --ease-bounce: cubic-bezier(0.34, 1.56, 0.64, 1); /* playful overshoot — modals/winners */

  --safe-top: env(safe-area-inset-top, 0px);
  --safe-bottom: env(safe-area-inset-bottom, 0px);
}

/* ------------------------------------------------------------------
   3. CANVAS / RESPONSIVE SCALING
   ------------------------------------------------------------------ */
/* The game sits pinned to the bottom of the viewport so the top portion
   (reserved for a live-stream video behind it) stays empty — at every
   screen size, phone through desktop. */
.game-stage {
  position: relative;
  width: 100%;
  height: 100vh;
  height: 100dvh;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: flex-end;
  overflow: hidden;
  background: radial-gradient(circle at 50% 35%, rgba(90, 40, 160, 0.16), transparent 62%);
}

/* The OUTER shell (#luckyGame) is a plain, invisible positioning box —
   height locked to exactly 70% of the screen by script.js (the "30%
   blank top" guarantee), width 100% on phone / capped+centered on
   tablet+ (see .wide-mode below). It carries NO background or clipping
   of its own; that all lives on .lg-clip inside it (see below), so the
   title banner and close button — its OTHER children — can sit directly
   on top of its top edge, straddling it, without being cut off. */
.lucky-game {
  position: relative;
  isolation: isolate;
  width: 100%;
  height: 100%;
  color: var(--text-main);
  font-family: var(--font-ui);
  flex-shrink: 0;
}

/* Everything that must respect the panel's rounded top corners — the
   background, the machine, the wallet bar, all of it — is clipped here
   instead of on .lucky-game itself. */
.lg-clip {
  position: absolute;
  inset: 0;
  overflow: hidden;
  border-radius: 18px 18px 0 0;
  box-shadow: 0 20px 60px rgba(0, 0, 0, 0.55);
}

/* Optional embed states */
.lucky-game.is-embed .lg-clip { background: transparent; box-shadow: none; }
.lucky-game.is-fullscreen .lg-clip { border-radius: 0; }

/* Tablet/laptop/desktop: the panel is a centered floating card (side
   edges are now visible, not clipped by the screen edge), so round all
   four corners instead of just the top two. */
.game-stage.wide-mode .lg-clip {
  border-radius: 18px;
  box-shadow: 0 24px 70px rgba(0, 0, 0, 0.5), 0 0 0 1px rgba(255, 255, 255, 0.06);
}

/* The inner canvas fills the outer shell completely via plain fluid CSS
   (flex, %) — no fixed logical size, no transform-scale in the normal
   case, so every control genuinely reaches the outer's left/right edges
   on any phone or tablet shape. On unusually short screens script.js
   applies a one-off corrective transform:scale() here so the chrome
   (header/tabs/wallet bar) never overflows off-screen; top-center origin
   keeps that rare shrink anchored sensibly. */
.lg-canvas {
  position: relative;
  width: 100%;
  height: 100%;
  display: flex;
  flex-direction: column;
  transform-origin: top center;
}

/* ------------------------------------------------------------------
   4. BACKGROUND
   ------------------------------------------------------------------ */
.lg-clip {
  background:
    radial-gradient(circle at 50% 8%, rgba(239, 101, 255, 0.20), transparent 45%),
    radial-gradient(circle at 12% 30%, rgba(101, 231, 255, 0.14), transparent 40%),
    radial-gradient(circle at 88% 60%, rgba(255, 216, 77, 0.08), transparent 40%),
    linear-gradient(160deg, var(--purple-950) 0%, var(--purple-900) 45%, var(--purple-800) 78%, var(--purple-700) 100%);
}

.lg-clip::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  /* assets/background.webp: the space / candy-cloud artwork, shown at full strength
     (its centre is deliberately dark and calm so the machine stays readable). */
  background-image: url("assets/background.webp");
  background-size: cover;
  background-position: center bottom;
  background-repeat: no-repeat;
  pointer-events: none;
}

.lg-clip::after {
  content: "";
  position: absolute;
  inset: -20%;
  z-index: 0;
  background:
    radial-gradient(circle at 20% 15%, rgba(255, 255, 255, 0.5) 0, transparent 1.4%),
    radial-gradient(circle at 70% 8%, rgba(255, 255, 255, 0.4) 0, transparent 1.2%),
    radial-gradient(circle at 85% 22%, rgba(255, 255, 255, 0.35) 0, transparent 1%),
    radial-gradient(circle at 40% 35%, rgba(255, 255, 255, 0.3) 0, transparent 1%),
    radial-gradient(circle at 10% 55%, rgba(255, 255, 255, 0.3) 0, transparent 1%),
    radial-gradient(circle at 92% 70%, rgba(255, 255, 255, 0.35) 0, transparent 1%),
    radial-gradient(circle at 60% 85%, rgba(255, 255, 255, 0.25) 0, transparent 1%);
  animation: starsDrift 26s linear infinite;
  pointer-events: none;
}

.lg-bg-stars { position: absolute; inset: 0; z-index: 0; pointer-events: none; }

/* ------------------------------------------------------------------
   5. HEADER / TITLE
   ------------------------------------------------------------------ */
/* The logo banner sits right ON the panel's top edge (top:0, then pulled up by its own height,
   tucked 1px under the panel so there is no gap), over the bottom of the blank live-stream area
   above. z-index puts it above .lg-clip (which has no explicit z-index of its own). */
.lg-header {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  transform: translateY(calc(-100% + 1px));
  z-index: 20;
  display: flex;
  align-items: flex-end;
  justify-content: center;
  padding: 0 58px;
  pointer-events: none;
}

.lg-banner {
  display: block;
  margin: 0 auto;            /* the <h1> around it is as wide as the header, so centre the image in it */
  width: min(230px, 100%);   /* assets/banner.webp is 1400x258 */
  height: auto;
  user-select: none;
}

.lg-title {
  margin: 0;
  text-align: center;
  font-family: var(--font-display);
  font-weight: 800;
  line-height: 1;
  letter-spacing: 0.5px;
  filter: drop-shadow(0 3px 4px rgba(0, 0, 0, 0.45));
  animation: titleBreath 3.6s ease-in-out infinite;
}

.lg-title-line {
  display: block;
  font-size: 25px;
  white-space: nowrap;
  background: linear-gradient(180deg, var(--gold-light) 0%, var(--gold) 55%, var(--gold-dark) 100%);
  -webkit-background-clip: text;
  background-clip: text;
  color: transparent;
  -webkit-text-stroke: 2px rgba(255, 255, 255, 0.95);
  paint-order: stroke fill;
  text-shadow:
    0 2px 0 var(--purple-900),
    0 4px 3px rgba(0, 0, 0, 0.4),
    0 0 20px rgba(255, 216, 77, 0.6);
}

.lg-planet {
  width: 20px;
  height: 20px;
  border-radius: 50%;
  flex-shrink: 0;
  filter: drop-shadow(0 0 6px rgba(101, 231, 255, 0.6));
}
.lg-planet--left { background: radial-gradient(circle at 30% 30%, var(--cyan), var(--purple-600) 70%); }
.lg-planet--right { background: radial-gradient(circle at 30% 30%, var(--pink-soft), var(--pink) 70%); }

/* ------------------------------------------------------------------
   CLOSE BUTTON
   ------------------------------------------------------------------ */
/* Lives inside .mode-tabs, on the same row as the Ordinary / Super tabs, at the right of
   "Super". It fills the row's own height (top/bottom match the tabs' box), so it is exactly
   as tall as the Super tab and centred on it, and stays a square via aspect-ratio. The icon
   (assets/cross.png) is a complete glossy badge with a little transparent padding, so it is
   scaled up 12% to make the badge itself the tab's height. The ::before makes the tap area
   a few pixels bigger than what is drawn. */
.close-btn {
  position: absolute;
  right: 8px;
  top: 18px;                 /* = .mode-tabs padding-top */
  bottom: 5px;               /* = .mode-tabs padding-bottom */
  width: auto;
  aspect-ratio: 1 / 1;
  padding: 0;
  border: none;
  background: none;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  z-index: 4;
  -webkit-tap-highlight-color: transparent;
  transition: transform 0.15s var(--ease-snappy), filter 0.15s var(--ease-snappy);
}
.close-btn::before {
  content: "";
  position: absolute;
  inset: -6px;
  border-radius: 50%;
}
.close-btn:hover { filter: brightness(1.1); }
.close-btn:active { transform: scale(0.9); }
.close-btn:disabled { opacity: 0.5; pointer-events: none; }

.close-btn-img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  transform: scale(1.12);
  pointer-events: none;
  filter: drop-shadow(0 2px 3px rgba(0, 0, 0, 0.35));
}

/* ------------------------------------------------------------------
   6. MODE TABS
   ------------------------------------------------------------------ */
.mode-tabs {
  position: relative;
  z-index: 3;
  flex-shrink: 0;
  display: flex;
  justify-content: center;
  gap: 10px;
  /* Top padding = breathing room under the logo banner. The side padding leaves room on the
     right for the close button (see .close-btn) and keeps the tabs centred. */
  padding: 18px 54px 5px;
}

.mode-tab {
  flex: 1;
  max-width: 130px;
  padding: 9px 0;
  border-radius: 999px;
  font-size: 14px;
  font-weight: 700;
  letter-spacing: 0.3px;
  color: var(--text-soft);
  background: linear-gradient(180deg, var(--purple-600), var(--purple-800));
  box-shadow:
    inset 0 1px 2px rgba(255, 255, 255, 0.25),
    inset 0 -3px 5px rgba(20, 5, 50, 0.4),
    0 2px 4px rgba(0, 0, 0, 0.3);
  transition: transform 0.18s var(--ease-snappy), background 0.25s var(--ease-standard), box-shadow 0.25s var(--ease-standard), color 0.2s var(--ease-standard);
  position: relative;
}

.mode-tab:not(.active):not(:disabled):hover { color: var(--text-main); filter: brightness(1.12); }

.mode-tab.active {
  color: var(--gold-light);
  background: linear-gradient(180deg, var(--purple-950), var(--purple-900));
  box-shadow:
    inset 0 0 0 1.5px rgba(255, 216, 77, 0.55),
    inset 0 2px 6px rgba(0, 0, 0, 0.55),
    0 0 14px rgba(120, 60, 220, 0.55);
  transform: translateY(1px) scale(1.03);
}

.mode-tab.active::after {
  content: "";
  position: absolute;
  bottom: -5px;
  left: 50%;
  width: 10px;
  height: 10px;
  background: var(--purple-950);
  transform: translateX(-50%) rotate(45deg);
  box-shadow: inset 0 0 0 1.5px rgba(255, 216, 77, 0.4);
}

.mode-tab:disabled { opacity: 0.6; pointer-events: none; }

/* ------------------------------------------------------------------
   7. INFO BAR
   ------------------------------------------------------------------ */
.info-bar {
  position: relative;
  z-index: 3;
  flex-shrink: 0;
  display: flex;
  justify-content: center;
  padding: 2px 20px 5px;
}

.info-bar span {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  padding: 6px 16px;
  border-radius: 999px;
  font-size: 12px;
  color: var(--text-soft);
  background: var(--panel-dark);
  border: 1px solid rgba(255, 255, 255, 0.12);
  box-shadow: inset 0 0 8px rgba(120, 70, 220, 0.35);
}

.info-bar b { color: var(--gold-light); font-variant-numeric: tabular-nums; }

.coin-icon-xs {
  width: 13px;
  height: 13px;
  object-fit: contain;
  vertical-align: -2px;
}

/* ------------------------------------------------------------------
   8. TURNTABLE MACHINE
   ------------------------------------------------------------------ */
.machine-frame {
  position: relative;
  z-index: 2;
  flex: 1;
  /* The floor below which the grid stops looking like a readable 3x3
     board. On tall-enough screens flex gives it more than this and it
     fills the space naturally; on short screens it holds here and
     script.js's corrective scale shrinks the WHOLE canvas uniformly
     around it instead, preserving proportions. */
  min-height: 220px;
  /* Width is DERIVED from the flex-computed height via aspect-ratio,
     instead of being sized independently from it — that mismatch was
     exactly what made the grid (and every card in it) come out as a
     stretched-wide rectangle rather than a proper square. align-self
     overrides the flex column's default stretch-to-full-width so the
     aspect-ratio's own computed width actually gets used. */
  aspect-ratio: 1 / 1;
  align-self: center;
  max-width: 460px;
  max-height: 460px;
  margin: 0 auto;
  border-radius: 26px;
  padding: 18px;
  background:
    repeating-linear-gradient(135deg, var(--purple-700) 0 14px, var(--purple-800) 14px 28px);
  box-shadow:
    inset 0 3px 6px rgba(255, 255, 255, 0.25),
    inset 0 -8px 14px rgba(10, 2, 30, 0.55),
    0 10px 22px rgba(0, 0, 0, 0.45),
    0 0 24px rgba(167, 82, 255, 0.35);
}

.machine-frame::before {
  content: "";
  position: absolute;
  inset: 6px;
  border-radius: 22px;
  background: linear-gradient(160deg, rgba(255, 255, 255, 0.18), transparent 40%);
  pointer-events: none;
}

.machine-inner {
  position: relative;
  width: 100%;
  height: 100%;
  border-radius: 18px;
  background: linear-gradient(160deg, var(--purple-950), var(--purple-900) 60%, var(--purple-950));
  box-shadow:
    inset 0 0 0 3px rgba(10, 4, 30, 0.8),
    inset 0 6px 16px rgba(0, 0, 0, 0.6);
  padding: 5px;
  /* Deliberately NOT clipped (no overflow:hidden): the active/winner
     prize-card glow (box-shadow blur up to ~40px) needs room well beyond
     a corner card's own edge to render fully. .machine-frame (this
     element's parent) has no clipping of its own either, so that glow
     can spill safely into the striped border band instead of being cut
     off — it fades out naturally well before reaching the panel's own
     outer edge. */
  overflow: visible;
}

/* ------------------------------------------------------------------
   9. BULBS
   ------------------------------------------------------------------ */
.bulb-ring {
  position: absolute;
  /* The frame's striped border band is its own 18px padding zone (see
     .machine-frame) — a NEGATIVE inset here pushed the bulbs past the
     frame's outer edge entirely, floating outside it. Pulling this
     inward instead seats them properly in the middle of that stripe
     band, matching the pattern instead of hovering off it. */
  inset: 9px;
  z-index: 1;
  pointer-events: none;
}

/* left/top are set per-bulb in script.js as percentages (of this ring's
   own, now-fluid, box) rather than a fixed-pixel radius, so the ring
   always tracks the machine-frame's actual size on any screen. */
.bulb {
  position: absolute;
  width: 8px;
  height: 8px;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  background: radial-gradient(circle at 32% 28%, #fffbe0 0%, var(--gold) 45%, var(--gold-dark) 100%);
  box-shadow: 0 0 6px 2px rgba(255, 216, 77, 0.65);
}

.bulb-a { animation: bulbPulseA 750ms ease-in-out infinite; }
.bulb-b { animation: bulbPulseB 750ms ease-in-out infinite; }

/* ------------------------------------------------------------------
   10. PRIZE CARDS
   ------------------------------------------------------------------ */
.prize-grid {
  position: relative;
  z-index: 2;
  width: 100%;
  height: 100%;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  grid-template-rows: repeat(3, 1fr);
  grid-template-areas:
    "p0 p1 p2"
    "p7 sp p3"
    "p6 p5 p4";
  gap: 5px;
}

.prize-card {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  padding: 4px 2px;
  border-radius: var(--radius-sm);
  background: var(--card-face);
  box-shadow:
    inset 0 1px 2px rgba(255, 255, 255, 0.8),
    inset 0 -3px 5px rgba(120, 90, 200, 0.18),
    0 3px 6px rgba(10, 2, 30, 0.4);
  border: 1.5px solid var(--card-border);
  transition: transform 0.18s var(--ease-snappy), box-shadow 0.18s var(--ease-standard), filter 0.18s var(--ease-standard);
  overflow: hidden;
  color: var(--purple-900);
}

.prize-qty {
  position: absolute;
  top: 3px;
  right: 3px;
  z-index: 2;
  font-size: 9px;
  font-weight: 800;
  color: #8a1fb0;
  background: linear-gradient(180deg, var(--gold-light), var(--gold));
  padding: 1px 5px;
  border-radius: 999px;
  box-shadow: 0 1px 2px rgba(0, 0, 0, 0.3), inset 0 1px 1px rgba(255, 255, 255, 0.7);
  line-height: 1.4;
}

.prize-img-wrap {
  width: 100%;
  height: 66%;
  flex-shrink: 1;
  min-height: 0;
  display: flex;
  align-items: center;
  justify-content: center;
}

.prize-img {
  max-width: 98%;
  max-height: 100%;
  object-fit: contain;
  filter: drop-shadow(0 3px 3px rgba(80, 40, 140, 0.3));
}

.prize-img-fallback {
  width: 40px;
  height: 40px;
  border-radius: 50%;
  align-items: center;
  justify-content: center;
  color: #fff;
  font-weight: 800;
  font-size: 13px;
  letter-spacing: -0.2px;
  box-shadow: inset 0 2px 3px rgba(255, 255, 255, 0.5), 0 2px 4px rgba(0, 0, 0, 0.3);
}

.prize-name {
  font-size: 10.5px;
  line-height: 1.2;
  flex-shrink: 0;
  font-weight: 700;
  color: var(--purple-800);
  white-space: nowrap;
  max-width: 96%;
  overflow: hidden;
  text-overflow: ellipsis;
}

.prize-value {
  display: inline-flex;
  align-items: center;
  flex-shrink: 0;
  line-height: 1.2;
  gap: 2px;
  font-size: 9px;
  font-weight: 700;
  color: var(--gold-dark);
  font-variant-numeric: tabular-nums;
}

.prize-value.no-coin-icon::before {
  content: "";
  width: 8px;
  height: 8px;
  border-radius: 50%;
  background: radial-gradient(circle at 35% 30%, var(--gold-light), var(--gold-dark));
  display: inline-block;
}

/* Active spin highlight */
.prize-card.active {
  transform: scale(1.06);
  z-index: 3;
  filter: brightness(1.08);
  box-shadow:
    inset 0 0 0 2px rgba(255, 255, 255, 0.85),
    0 0 0 3px var(--gold),
    0 0 15px rgba(255, 221, 80, 0.9),
    0 0 30px rgba(235, 90, 255, 0.5);
  animation: activePrizeGlow 0.5s ease-in-out infinite;
}

/* Winner state */
.prize-card.winner {
  transform: scale(1.08);
  z-index: 4;
  filter: brightness(1.18);
  box-shadow:
    inset 0 0 0 2px #fff,
    0 0 0 4px var(--gold),
    0 0 22px rgba(255, 221, 80, 1),
    0 0 40px rgba(235, 90, 255, 0.65);
  animation: winnerPulse 1s ease-in-out infinite;
}

.prize-card.winner::before {
  content: "";
  position: absolute;
  inset: -40%;
  background: conic-gradient(from 0deg, transparent 0deg, rgba(255, 255, 255, 0.55) 12deg, transparent 30deg);
  animation: winnerShine 1.6s linear infinite;
  pointer-events: none;
}

.prize-card.winner .prize-img { filter: drop-shadow(0 0 6px rgba(255, 230, 130, 0.9)); }

/* ------------------------------------------------------------------
   12. SPIN BUTTON
   ------------------------------------------------------------------ */
.spin-slot {
  /* The fluid grid's own cell isn't reliably square (its shape depends on
     the responsive machine-frame's actual size on any given screen) — so
     .spin-button below sizes itself off whichever of THIS cell's own
     dimensions is smaller, via container query units, guaranteeing a
     true circle instead of an oval stretched to match the cell. */
  container-type: size;
  display: flex;
  align-items: center;
  justify-content: center;
}

.spin-button {
  position: relative;
  width: 85%;
  height: 85%;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  background: radial-gradient(circle at 32% 28%, var(--gold-dark), var(--purple-950) 78%);
  box-shadow:
    0 6px 12px rgba(0, 0, 0, 0.5),
    0 0 18px rgba(255, 216, 77, 0.35);
  transition: transform 0.12s var(--ease-snappy), filter 0.15s var(--ease-standard);
}

/* Modern browsers (any current mobile WebView included): lock to a true
   circle sized by the cell's smaller dimension, filling it generously.
   Where container query units aren't supported, this rule is simply
   skipped and the plain 85%/85% above still applies as a safe fallback. */
@supports (width: 1cqw) {
  .spin-button {
    width: min(85cqw, 85cqh);
    height: min(85cqw, 85cqh);
  }
}

.spin-button-ring {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  background: conic-gradient(var(--gold-light), var(--gold), var(--gold-dark), var(--gold), var(--gold-light));
  box-shadow: inset 0 0 0 3px rgba(255, 255, 255, 0.4);
  animation: spinButtonPulse 2.4s ease-in-out infinite;
}

.spin-button-core {
  position: relative;
  z-index: 2;
  flex-shrink: 0;
  width: 80%;
  height: 80%;
  border-radius: 50%;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  background: radial-gradient(circle at 35% 25%, var(--pink), var(--purple-600) 52%, var(--purple-900) 100%);
  box-shadow:
    inset 0 3px 5px rgba(255, 255, 255, 0.55),
    inset 0 -6px 10px rgba(20, 5, 50, 0.6),
    0 2px 4px rgba(0, 0, 0, 0.4);
}

/* Belt-and-suspenders: percentage sizing on this doubly-nested flex
   element (a flex item that's also itself a flex container with text
   content) can get thrown off by the browser's min-content/flex-basis
   resolution. Sizing it directly off the query container's own smaller
   dimension — same technique as .spin-button above — sidesteps that
   entirely and guarantees a true circle. */
@supports (width: 1cqw) {
  .spin-button-core {
    width: min(68cqw, 68cqh);
    height: min(68cqw, 68cqh);
  }
}

.spin-button-text {
  font-family: var(--font-display);
  font-size: 15px;
  font-weight: 800;
  color: #ffffff;
  text-shadow: 0 1px 3px rgba(60, 10, 90, 0.8), 0 0 8px rgba(255, 255, 255, 0.35);
  letter-spacing: 0.5px;
}

.spin-button-sub {
  font-size: 8px;
  font-weight: 600;
  color: #ffffff;
  margin-top: 1px;
}

/* Text scales WITH the button (see .spin-button above) instead of
   staying a fixed px size that could crowd a small button or look tiny
   on a large one. */
@supports (width: 1cqw) {
  .spin-button-text { font-size: min(16.4cqw, 16.4cqh); }
  .spin-button-sub { font-size: min(8.7cqw, 8.7cqh); }
}

.spin-button:hover { filter: brightness(1.08); }
.spin-button:active { transform: scale(0.95); }
.spin-button.is-spinning { pointer-events: none; }
.spin-button.is-spinning .spin-button-ring { animation-duration: 0.9s; }
.spin-button:disabled { cursor: default; }

/* ------------------------------------------------------------------
   13. CONTROL DECK
   ------------------------------------------------------------------ */
.control-deck {
  position: relative;
  z-index: 3;
  flex-shrink: 0;
  display: flex;
  gap: 10px;
  padding: 4px 20px 4px;
}

.deck-btn {
  position: relative;
  overflow: hidden;
  flex: 1;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1px;
  padding: 6px 4px 7px;
  border-radius: var(--radius-md);
  background: linear-gradient(180deg, var(--purple-500), var(--purple-700));
  box-shadow:
    inset 0 2px 3px rgba(255, 255, 255, 0.35),
    inset 0 -5px 8px rgba(45, 10, 110, 0.45),
    0 7px 15px rgba(18, 5, 80, 0.35),
    0 0 18px rgba(167, 82, 255, 0.25);
  transition: transform 0.12s var(--ease-snappy), filter 0.15s var(--ease-standard), box-shadow 0.2s var(--ease-standard);
}

/* Static glass-like top-cap highlight — the classic glossy-button look,
   distinct from the animated shine-sweep below. */
.deck-btn::before {
  content: "";
  position: absolute;
  top: 0;
  left: 4%;
  right: 4%;
  height: 46%;
  border-radius: 999px / 12px;
  background: linear-gradient(180deg, rgba(255, 255, 255, 0.5), rgba(255, 255, 255, 0) 100%);
  pointer-events: none;
}

/* Periodic shine sweep — a subtle premium "polish" cue rather than a
   constant animation; timed with a long pause so it reads as occasional
   glints, not restless motion. */
.deck-btn::after {
  content: "";
  position: absolute;
  top: 0;
  left: -60%;
  width: 40%;
  height: 100%;
  background: linear-gradient(115deg, transparent, rgba(255, 255, 255, 0.35), transparent);
  transform: skewX(-20deg);
  animation: buttonShine 4.5s ease-in-out infinite;
  pointer-events: none;
}

.deck-btn-cost {
  display: inline-flex;
  align-items: center;
  gap: 3px;
  font-size: 12px;
  color: var(--gold-light);
  font-weight: 700;
  font-variant-numeric: tabular-nums;
}

.deck-btn-label {
  font-size: 13px;
  font-weight: 800;
  color: #fff;
  letter-spacing: 0.4px;
}

.deck-btn--ten { background: linear-gradient(180deg, #ff9de0, var(--purple-700)); }

.deck-btn:hover { filter: brightness(1.06); }
.deck-btn:active { transform: scale(0.96); }
.deck-btn:disabled {
  opacity: 0.55;
  filter: grayscale(0.3);
  pointer-events: none;
}

/* ------------------------------------------------------------------
   14. BOTTOM WALLET
   ------------------------------------------------------------------ */
.wallet-bar {
  position: relative;
  z-index: 3;
  flex-shrink: 0;
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 16px calc(12px + var(--safe-bottom));
}

.wallet-balance {
  display: flex;
  align-items: center;
  gap: 5px;
  font-size: 12px;
  color: var(--text-soft);
  background: var(--panel-dark);
  border-radius: 999px;
  padding: 6px 12px;
  border: 1px solid rgba(255, 255, 255, 0.1);
}

.wallet-label { white-space: nowrap; }

.balance {
  font-weight: 800;
  color: var(--gold-light);
  font-variant-numeric: tabular-nums;
}

.balance.spend { animation: balanceSpend 0.4s ease; }
.balance.gain { animation: balanceGain 0.5s ease; }

.coin-icon-sm { width: 16px; height: 16px; object-fit: contain; }

.wallet-recharge {
  font-size: 11.5px;
  font-weight: 700;
  color: var(--purple-900);
  padding: 7px 12px;
  border-radius: 999px;
  background: linear-gradient(180deg, var(--gold-light), var(--gold));
  box-shadow: inset 0 1px 2px rgba(255, 255, 255, 0.7), 0 2px 4px rgba(0, 0, 0, 0.35);
  white-space: nowrap;
  transition: transform 0.12s var(--ease-snappy), filter 0.15s var(--ease-standard);
}
.wallet-recharge:hover { filter: brightness(1.08); }
.wallet-recharge:active { transform: scale(0.95); }

.wallet-icon-btn {
  position: relative;
  width: 32px;
  height: 32px;
  min-width: 32px;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  color: #ffffff;
  border: none;
  margin-left: auto;
  box-shadow:
    inset 0 2px 3px rgba(255, 255, 255, 0.55),
    inset 0 -3px 5px rgba(0, 0, 0, 0.25),
    0 3px 6px rgba(0, 0, 0, 0.35);
  transition: transform 0.12s var(--ease-snappy), filter 0.15s var(--ease-standard);
}
.wallet-icon-btn + .wallet-icon-btn { margin-left: 0; }
.wallet-icon-btn:hover { filter: brightness(1.1); }
.wallet-icon-btn:active { transform: scale(0.92); }

.wallet-icon-img {
  width: 22px;
  height: 22px;
  object-fit: contain;
  filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.3));
}

/* The history icon is a complete, pre-styled circular badge (its own
   gradient ring baked in) rather than a plain glyph — so it replaces the
   button's own background/shadow entirely instead of sitting redundantly
   inside another circle, and fills the button. */
#historyBtn {
  background: none;
  box-shadow: none;
}
#historyBtn .wallet-icon-img {
  /* clock-icon.png is 1141x928 with the round badge (842px wide) centred in transparent padding,
     so the image is drawn 32 * 1141 / 842 = 43.4px wide to make the badge itself exactly 32px,
     the same size as the rules button next to it. */
  width: 43.4px;
  height: auto;
  max-width: none;
  flex: none;
  filter: none;
}

/* The rules icon, unlike the clock one, is a plain flat glyph with no
   circular badge of its own — give it the same rich glossy circle
   treatment as every other control so the two buttons match. */
#rulesBtn { background: radial-gradient(circle at 32% 28%, #ffc86b, #ee8c00 85%); }
#rulesBtn .wallet-icon-img { width: 20px; height: 20px; }

/* ------------------------------------------------------------------
   15. RESULT / MINI MODALS
   ------------------------------------------------------------------ */
.modal-overlay {
  position: fixed;
  inset: 0;
  z-index: 100;
  display: flex;
  align-items: center;
  justify-content: center;
  background: rgba(6, 2, 20, 0);
  backdrop-filter: blur(0px);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.22s var(--ease-standard), background 0.22s var(--ease-standard), backdrop-filter 0.22s var(--ease-standard);
  padding: 20px;
}

.modal-overlay[hidden] { display: none; }

.modal-overlay.is-open {
  opacity: 1;
  pointer-events: auto;
  background: rgba(6, 2, 20, 0.62);
  backdrop-filter: blur(4px);
}

.result-modal, .mini-modal {
  position: relative;
  width: min(300px, 100%);
  max-height: 85vh;
  overflow-y: auto;
  border-radius: var(--radius-lg);
  padding: 26px 22px 20px;
  text-align: center;
  background: linear-gradient(160deg, var(--purple-800), var(--purple-950));
  box-shadow:
    inset 0 0 0 2px rgba(255, 216, 77, 0.55),
    inset 0 2px 12px rgba(255, 255, 255, 0.08),
    0 20px 40px rgba(0, 0, 0, 0.55),
    0 0 30px rgba(255, 216, 77, 0.25);
  transform: scale(0.8) translateY(10px);
  opacity: 0;
  transition: transform 0.28s var(--ease-bounce), opacity 0.22s var(--ease-standard);
}

.modal-overlay.is-open .result-modal,
.modal-overlay.is-open .mini-modal {
  transform: scale(1) translateY(0);
  opacity: 1;
  animation: modalEnter 0.32s cubic-bezier(.34,1.56,.64,1);
}

.result-modal-glow {
  position: absolute;
  inset: -30%;
  background: radial-gradient(circle at 50% 20%, rgba(255, 216, 77, 0.35), transparent 60%);
  pointer-events: none;
}

.result-title {
  position: relative;
  margin: 0 0 12px;
  font-family: var(--font-display);
  font-size: 19px;
  font-weight: 800;
  color: var(--gold-light);
  text-shadow: 0 2px 3px rgba(0, 0, 0, 0.5), 0 0 14px rgba(255, 216, 77, 0.5);
}

.result-img-wrap {
  position: relative;
  width: 84px;
  height: 84px;
  margin: 0 auto 10px;
  display: flex;
  align-items: center;
  justify-content: center;
}

.result-img { max-width: 100%; max-height: 100%; object-fit: contain; filter: drop-shadow(0 4px 8px rgba(0,0,0,0.4)); }

.result-img-fallback {
  width: 64px;
  height: 64px;
  border-radius: 50%;
  display: none;
  align-items: center;
  justify-content: center;
  color: #fff;
  font-weight: 800;
  font-size: 24px;
}

.result-name {
  position: relative;
  margin: 0 0 4px;
  font-size: 16px;
  font-weight: 800;
  color: #fff;
}

.result-value {
  position: relative;
  margin: 0 0 16px;
  font-size: 13px;
  color: var(--text-soft);
}
.result-value b { color: var(--gold-light); font-variant-numeric: tabular-nums; }

.bulk-result-heading { font-size: 13px; color: var(--text-soft); margin: 0 0 10px; }

.bulk-result-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
  margin-bottom: 16px;
  max-height: 220px;
  overflow-y: auto;
}

.bulk-result-row {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 10px;
  border-radius: var(--radius-sm);
  background: rgba(255, 255, 255, 0.06);
  border: 1px solid rgba(255, 255, 255, 0.1);
}

.bulk-result-img-wrap { width: 26px; height: 26px; flex-shrink: 0; display: flex; align-items: center; justify-content: center; }
.bulk-result-img { max-width: 100%; max-height: 100%; object-fit: contain; }
.bulk-result-fallback { width: 22px; height: 22px; border-radius: 50%; align-items: center; justify-content: center; color: #fff; font-size: 10px; font-weight: 800; }
.bulk-result-name { flex: 1; text-align: left; font-size: 12.5px; color: #fff; }
.bulk-result-value { font-size: 12px; color: var(--gold-light); font-weight: 700; font-variant-numeric: tabular-nums; }

.result-claim-btn, .mini-modal-close {
  position: relative;
  width: 100%;
  padding: 12px 0;
  border-radius: 999px;
  font-size: 15px;
  font-weight: 800;
  color: var(--purple-900);
  background: linear-gradient(180deg, var(--gold-light), var(--gold) 60%, var(--gold-dark));
  box-shadow: inset 0 2px 3px rgba(255,255,255,0.6), 0 4px 10px rgba(0,0,0,0.35);
  transition: transform 0.12s var(--ease-snappy), filter 0.15s var(--ease-standard);
}
.result-claim-btn:hover, .mini-modal-close:hover { filter: brightness(1.06); }
.result-claim-btn:active, .mini-modal-close:active { transform: scale(0.97); }

.mini-modal-title { margin: 0 0 14px; font-family: var(--font-display); font-size: 17px; font-weight: 800; color: var(--gold-light); }

.history-list, .rules-list { list-style: none; margin: 0 0 16px; padding: 0; text-align: left; }

.history-row {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 4px;
  border-bottom: 1px solid rgba(255,255,255,0.08);
  font-size: 13px;
}
.history-dot { width: 10px; height: 10px; border-radius: 50%; flex-shrink: 0; }
.history-name { flex: 1; color: #fff; }
.history-value { color: var(--gold-light); font-weight: 700; font-variant-numeric: tabular-nums; }
.history-empty { padding: 10px 0; color: var(--text-muted); font-size: 13px; text-align: center; }

.rules-list li {
  font-size: 12.5px;
  color: var(--text-soft);
  padding: 6px 0 6px 16px;
  position: relative;
  line-height: 1.4;
}
.rules-list li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 12px;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: var(--gold);
}

/* ------------------------------------------------------------------
   16. TOASTS
   ------------------------------------------------------------------ */
.toast-stack {
  position: fixed;
  top: calc(16px + var(--safe-top));
  left: 0;
  right: 0;
  z-index: 200;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 8px;
  pointer-events: none;
}

.toast {
  padding: 10px 18px;
  border-radius: 999px;
  font-size: 13px;
  font-weight: 600;
  color: #fff;
  background: rgba(30, 12, 70, 0.92);
  border: 1px solid rgba(255, 255, 255, 0.15);
  box-shadow: 0 6px 16px rgba(0,0,0,0.4);
  opacity: 0;
  transform: translateY(-10px);
  transition: opacity 0.24s var(--ease-standard), transform 0.24s var(--ease-snappy);
}
.toast.is-visible { opacity: 1; transform: translateY(0); }

.toast-success { border-color: rgba(120, 230, 160, 0.5); }
.toast-error { border-color: rgba(255, 110, 110, 0.55); }
.toast-warning { border-color: rgba(255, 200, 90, 0.55); }
.toast-info { border-color: rgba(150, 190, 255, 0.5); }

/* ------------------------------------------------------------------
   17. PARTICLE EFFECTS
   ------------------------------------------------------------------ */
.winner-particle {
  position: absolute;
  z-index: 50;
  color: var(--gold-light);
  font-size: 12px;
  pointer-events: none;
  will-change: transform, opacity;
  animation: particleBurst 0.85s ease-out forwards;
}

/* ------------------------------------------------------------------
   18. STATES
   ------------------------------------------------------------------ */
.lucky-game[data-state="spinning"] .wallet-recharge,
.lucky-game[data-state="spinning"] .mode-tab:not(.active) {
  opacity: 0.7;
}

.lucky-game[data-mode="super"] .machine-frame {
  box-shadow:
    inset 0 3px 6px rgba(255, 255, 255, 0.25),
    inset 0 -8px 14px rgba(10, 2, 30, 0.55),
    0 10px 22px rgba(0, 0, 0, 0.45),
    0 0 30px rgba(101, 231, 255, 0.55);
}

.lucky-game[data-mode="super"] .mode-tab.active {
  box-shadow:
    inset 0 0 0 1.5px rgba(101, 231, 255, 0.6),
    inset 0 2px 6px rgba(0, 0, 0, 0.55),
    0 0 14px rgba(101, 231, 255, 0.55);
}

/* ------------------------------------------------------------------
   19. ANIMATIONS
   ------------------------------------------------------------------ */
@keyframes titleBreath {
  0%, 100% { transform: scale(1); }
  50% { transform: scale(1.015); }
}

@keyframes bulbPulseA {
  0%, 100% { opacity: 0.65; }
  50% { opacity: 1; }
}
@keyframes bulbPulseB {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.65; }
}

@keyframes starsDrift {
  0% { transform: translate(0, 0); }
  100% { transform: translate(-2%, -2%); }
}

@keyframes activePrizeGlow {
  0%, 100% { filter: brightness(1.08); }
  50% { filter: brightness(1.22); }
}

@keyframes winnerPulse {
  0%, 100% { filter: brightness(1.18); transform: scale(1.08); }
  50% { filter: brightness(1.35); transform: scale(1.11); }
}

@keyframes winnerShine {
  0% { transform: rotate(0deg); }
  100% { transform: rotate(360deg); }
}

@keyframes winnerPop {
  0% { transform: scale(1); }
  40% { transform: scale(1.18); }
  100% { transform: scale(1.08); }
}

@keyframes spinButtonPulse {
  0%, 100% { filter: brightness(1); }
  50% { filter: brightness(1.15); }
}

@keyframes particleBurst {
  0% { opacity: 1; transform: translate(-50%, -50%) translate(0, 0) rotate(0deg) scale(1); }
  100% { opacity: 0; transform: translate(-50%, -50%) translate(var(--dx), var(--dy)) rotate(var(--rot)) scale(0.4); }
}

@keyframes modalEnter {
  0% { transform: scale(0.8) translateY(10px); }
  60% { transform: scale(1.03) translateY(-2px); }
  100% { transform: scale(1) translateY(0); }
}

@keyframes toastEnter {
  0% { opacity: 0; transform: translateY(-10px); }
  100% { opacity: 1; transform: translateY(0); }
}

@keyframes balanceSpend {
  0% { transform: scale(1); color: var(--gold-light); }
  40% { transform: scale(0.85) translateY(2px); color: #ff8a8a; }
  100% { transform: scale(1); color: var(--gold-light); }
}

@keyframes balanceGain {
  0% { transform: scale(1); }
  40% { transform: scale(1.25) translateY(-2px); text-shadow: 0 0 10px rgba(255,216,77,0.9); }
  100% { transform: scale(1); }
}

@keyframes buttonShine {
  0%, 15% { left: -60%; }
  35%, 100% { left: 130%; }
}

/* ------------------------------------------------------------------
   20. PERFORMANCE MODE
   ------------------------------------------------------------------ */
.lucky-game.perf-mode .bulb { animation: none; opacity: 0.85; }
.lucky-game.perf-mode .lg-clip::after { animation: none; }
.lucky-game.perf-mode .lg-title { animation: none; }
.lucky-game.perf-mode .spin-button-ring { animation: none; }
.lucky-game.perf-mode .deck-btn::after { display: none; }
.lucky-game.perf-mode .prize-card.winner::before { display: none; }
.lucky-game.perf-mode .prize-card,
.lucky-game.perf-mode .mode-tab,
.lucky-game.perf-mode .deck-btn {
  box-shadow: 0 2px 4px rgba(0,0,0,0.3);
}

/* ------------------------------------------------------------------
   21. REDUCED MOTION / RESPONSIVE
   ------------------------------------------------------------------ */
@media (prefers-reduced-motion: reduce) {
  .lg-title,
  .bulb-a, .bulb-b,
  .lg-clip::after,
  .spin-button-ring,
  .prize-card.active,
  .prize-card.winner,
  .prize-card.winner::before,
  .deck-btn::after {
    animation: none !important;
  }
  .modal-overlay, .result-modal, .mini-modal, .toast {
    transition-duration: 0.05s !important;
  }
}

@media (max-width: 340px) {
  .lg-title-line { font-size: 22px; }
  .lg-title-line:last-child { font-size: 24px; }
  .prize-name { font-size: 9.5px; }
}


.prize-card, .mode-tab, .deck-btn, .spin-button, .wallet-icon-btn, .close-btn {
  will-change: transform;
}
