  @font-face {
    font-family: 'Armenian';
    src: url('fonts/armenian.921771ed3f.woff2') format('woff2');
    font-weight: 400 800; font-style: normal; font-display: swap;
  }
  @font-face {
    font-family: 'Display';
    src: url('fonts/display.706eccad0d.woff2') format('woff2');
    font-weight: 700 900; font-style: normal; font-display: swap;
  }

  :root {
    /* ---- design tokens (spec §4; values eyedropped from the reference render,
       TODO: confirm against asset spec) ---- */
    --c-night-deep:      #14082A;
    --c-night:           #2A0F4A;
    --c-night-lift:      #4A1B72;
    --c-wedge-purple:    #6B2A9C;
    --c-wedge-purple-in: #4E1A78;
    --c-gold-100: #FFF3C4;  --c-gold-200: #FFE08A;  --c-gold-300: #FFC94A;
    --c-gold-400: #F0A81E;  --c-gold-500: #D2860B;  --c-gold-600: #9C5E06;
    --c-neon-magenta:    #FF2D95;
    --c-neon-magenta-hi: #FF74BC;
    --c-ink-on-gold:     #3B1160;
    --c-ink-on-purple:   #FFE9A8;
    --c-ink-outline:     #2A0A46;
    --glow-cta:  0 0 24px rgba(255,45,149,.65), 0 0 64px rgba(255,45,149,.35);
    --glow-rim:  0 0 40px rgba(255,201,74,.45);
    --glow-bulb: 0 0 8px rgba(255,243,196,.95), 0 0 18px rgba(255,201,74,.7);
    --g-gold-face: linear-gradient(180deg, var(--c-gold-200) 0%, var(--c-gold-300) 45%, var(--c-gold-500) 100%);
    --g-gold-rim:  linear-gradient(135deg, var(--c-gold-600) 0%, var(--c-gold-100) 22%, var(--c-gold-400) 55%, var(--c-gold-600) 78%, var(--c-gold-200) 100%);
    --g-cta:       linear-gradient(180deg, var(--c-gold-200), var(--c-gold-400));

    /* legacy aliases still used below */
    --gold-1:  var(--c-gold-200);
    --gold-2:  var(--c-gold-400);
    --gold-3:  var(--c-gold-500);
    --seg-violet-a: #5a1cb8;
    --seg-violet-b: #4c17b8;
    --seg-gold-a:   #ffd34a;
    --seg-gold-b:   #eda300;
    --neon:         #ff3cbe;   /* magenta neon — button halo, bear rim light, sign glow */
    --ink-on-gold:  #240a45;
    --ink-on-violet:#ffeeb4;
    --text:    #f6ecff;
    --muted:   #c3addf;

    /* The wheel is the hero and takes every pixel the layout can spare. Three
       limits at once: the column's usable width, the height left over once
       the subheadline, badge, button and the compliance fine print have their
       space (that line must stay on the first screen, so the wheel yields to
       it), and a hard cap. On a phone width binds first — a circle 60% of an
       820px viewport simply cannot fit across 380px, so full width is the
       ceiling. */
    --wheel: min(138vw, calc(100vh - 40px), 1960px);
  }

  * { box-sizing: border-box; -webkit-tap-highlight-color: transparent; }
  html, body {
    margin: 0; padding: 0; width: 100%; height: 100%;
    overflow: hidden;
  }
  body {
    font-family: 'Armenian', system-ui, sans-serif;
    color: var(--text);
    /* Night-neon ground, built from gradients so there is no image to download.
       TODO(asset): drop a night-city photo in as an <picture> layer behind
       .stage (AVIF + WebP) if art supplies one; the vignette below is already
       sized to sit on top of it. */
    background:
      radial-gradient(90% 55% at 18% 6%,  rgba(126,44,214,0.45), transparent 60%),
      radial-gradient(80% 50% at 84% 12%, rgba(214,44,160,0.38), transparent 62%),
      radial-gradient(70% 45% at 50% 104%,rgba(255,150,40,0.20), transparent 60%),
      linear-gradient(178deg, #1b0833 0%, #240a45 42%, #360f5e 74%, #1d0838 100%);
    background-attachment: fixed;
    background-color: #1b0833;
  }

  .stage {
    position: relative;
    width: 100%; height: 100dvh; max-height: 100dvh;
    min-height: 100dvh;
    display: flex; align-items: flex-start; justify-content: center;
    /* Clip light effects without creating a scroll container: focusing the
       spin button must never scroll the header and mascots above the viewport. */
    overflow: clip;
  }
  /* Optional art background. Drop apps/wonder/bg.jpg (or .webp, adjust the url)
     art background; the gradients underneath stay as the fallback. */
  :root { --px: 0px; --py: 0px; }        /* parallax offset, set by wheel.33cd4456c2.js */
  .bg-photo {
    position: fixed; inset: -14px; z-index: 0; pointer-events: none;
    background-image: url('bg.06124dba5a.webp');
    background-size: cover; background-position: center;
    /* the whole scene sits a stop and a half down with more chroma: the art
       was lighter than the wheel, and the wheel stopped reading as the hero */
    filter: brightness(0.66) saturate(1.42) contrast(1.06);
    transform: translate(calc(var(--px) * -0.33), calc(var(--py) * -0.33));   /* far */
    will-change: transform;
  }
  .glow, canvas.ambient { transform: translate(calc(var(--px) * -0.66), calc(var(--py) * -0.66)); } /* mid */
  .deco, .bear { transform: translate(var(--px), var(--py)); }                                       /* near */

  /* Ambient glow layers over the photo — slow, large and cheap: only opacity
     and transform animate, so they stay off the main thread. */
  .glow {
    position: fixed; z-index: 0; pointer-events: none;
    border-radius: 50%; filter: blur(46px);
    will-change: transform, opacity;
  }
  .glow.g1 {
    left: -16%; top: -18%; width: 80vw; height: 80vw; max-width: 1150px; max-height: 1150px;
    background: radial-gradient(circle, rgba(255,20,180,0.58), rgba(255,20,180,0.20) 40%, rgba(255,20,180,0) 68%);
    animation: none;
  }
  .glow.g2 {
    right: -18%; top: -14%; width: 74vw; height: 74vw; max-width: 1050px; max-height: 1050px;
    background: radial-gradient(circle, rgba(96,24,205,0.54), rgba(96,24,205,0.20) 42%, rgba(96,24,205,0) 68%);
    animation: none;
  }
  .glow.g3 {
    left: 22%; bottom: -26%; width: 90vw; height: 62vw; max-width: 1300px; max-height: 900px;
    background: radial-gradient(circle, rgba(255,150,0,0.42), rgba(255,96,0,0.15) 45%, rgba(255,150,0,0) 70%);
    animation: none;
  }
  /* Gold pool directly behind the wheel — the light the wheel would throw on
     the scene if it were real. Breathes slowly, never drifts. */
  .glow.g4 {
    left: 50%; top: 46%; width: 76vw; height: 76vw; max-width: 1100px; max-height: 1100px;
    margin: -38vw 0 0 -38vw;
    background: radial-gradient(circle, rgba(255,205,70,0.34), rgba(255,160,40,0.12) 38%, rgba(255,160,40,0) 62%);
    animation: none;
  }
  @media (min-width: 1447px) { .glow.g4 { margin: -550px 0 0 -550px; } }
  @keyframes breathe4 { from { transform: scale(0.94); opacity: 0.7; } to { transform: scale(1.08); opacity: 1; } }
  @keyframes drift1 { from { transform: translate(0,0) scale(1);        opacity: 0.75; }
                      to   { transform: translate(6vw,4vh) scale(1.18); opacity: 1; } }
  @keyframes drift2 { from { transform: translate(0,0) scale(1.12);     opacity: 1; }
                      to   { transform: translate(-5vw,5vh) scale(1);   opacity: 0.7; } }
  @keyframes drift3 { from { transform: translate(0,0) scale(1);        opacity: 0.65; }
                      to   { transform: translate(-7vw,-3vh) scale(1.2);opacity: 1; } }

  /* Floating gold bokeh and twinkles. Screen-blended so they read as light on
     the scene, and z-indexed under the column so they never sit on the copy. */
  canvas.ambient { position: fixed; inset: 0; z-index: 1; pointer-events: none; mix-blend-mode: screen; }

  /* ---------- top-right decoration ---------- */
  /* Palm fronds with the Vegas sign in front. The sign is two stacked frames —
     the lit one over the dim one — cropped to a shared bounding box so they are
     pixel-aligned; only the lit frame's opacity animates, which reads as bulbs
     switching rather than a fade. Boxes carry the art's own aspect ratios so
     nothing letterboxes. */
  .deco {
    filter: brightness(0.78) saturate(1.25);
    position: fixed; top: 0; right: 0; z-index: 1; pointer-events: none;
    width: min(50vw, 210px); aspect-ratio: 434 / 570;
    opacity: 0.85;
  }
  .deco .palm {
    position: absolute; inset: 0;
    background: url('palm.0a9952b82b.webp') no-repeat right top / contain;
  }
  /* Phone: the subheadline owns the top centre, so the sign hangs small and
     hard right, below the mute button and clear of its longest line. It grows
     and slides in front of the fronds once there is room (760px+). */
  .deco .vegas {
    position: absolute; right: 0; top: 30%;
    width: 52%; aspect-ratio: 444 / 258;
    filter: drop-shadow(0 6px 18px rgba(0,0,0,0.55));
  }
  .deco .vegas span {
    position: absolute; inset: 0;
    background-repeat: no-repeat; background-position: center; background-size: contain;
  }
  .deco .vegas .off { background-image: url('vegas-off.6cf7b13f58.webp'); }
  .deco .vegas .on  {
    background-image: url('vegas-on.b28626d57c.webp'); animation: none;
    filter: drop-shadow(0 0 10px rgba(255,90,210,0.75)) drop-shadow(0 0 26px rgba(255,60,190,0.45));
  }
  /* Irregular on/off, not a sine fade — a bulb sign never breathes evenly. */
  @keyframes vegasBlink {
    0%, 30%   { opacity: 1; }
    32%, 36%  { opacity: 0; }
    38%, 62%  { opacity: 1; }
    64%, 66%  { opacity: 0; }
    68%, 88%  { opacity: 1; }
    90%, 93%  { opacity: 0; }
    95%, 100% { opacity: 1; }
  }

  @media (min-width: 760px) {
    .deco { width: min(30vw, 330px); opacity: 1; }
    .deco .vegas { right: 42%; top: 3%; width: 96%; }
  }
  @media (min-width: 1180px) {
    .deco { width: min(26vw, 400px); }
  }

  /* Vignette — darkens the corners so the eye lands on the wheel and the
     background never competes with it. */
  .stage::before {
    content: ""; position: fixed; inset: 0; z-index: 0; pointer-events: none;
    background: radial-gradient(ellipse 74% 58% at 50% 46%, transparent 30%, rgba(6,1,14,0.88) 100%);
  }

  .app {
    position: relative; z-index: 2;
    width: 100%; max-width: 680px; height: 100%; max-height: 100%; min-height: 0;
    flex: 0 0 100%; overflow: visible;
    display: flex; flex-direction: column; align-items: center; justify-content: flex-start;
    gap: clamp(4px, 0.8vh, 9px);
    padding: max(env(safe-area-inset-top), 8px) 4px max(env(safe-area-inset-bottom), 6px);
    text-align: center;
  }

  /* ---------- header ----------
     The headline wordmark was removed at the owner's request; the subtitle
     and the free-spin badge are what is left, small, at the top of the
     column's flow. */
  .subheadline {
    margin: 0; position: relative; top: 24px; color: var(--c-gold-200);
    font-size: clamp(22px, 2.5vw, 32px); font-weight: 800;
    line-height: 1.25; letter-spacing: 0.06em; text-transform: uppercase;
    display: flex; align-items: center; justify-content: center; gap: 12px;
    width: min(100%, 900px); max-width: calc(100vw - 64px); white-space: normal; text-align: center;
    text-shadow: 0 1px 8px rgba(10,2,24,0.9);
  }
  .subheadline::before, .subheadline::after {
    content: ""; flex: 0 1 64px; min-width: 0; height: 1px;
    background: linear-gradient(90deg, transparent, var(--c-gold-200));
  }
  .subheadline::after { background: linear-gradient(90deg, var(--c-gold-200), transparent); }
  .badge {
    display: inline-block;
    top: 16px;
    font-size: clamp(11px, 1.05vw, 14px); font-weight: 700; letter-spacing: 0.14em;
    color: var(--c-gold-200); text-transform: uppercase;
    background: var(--c-night-lift); border: 1.5px solid var(--c-gold-400); border-radius: 999px;
    padding: 4px 14px 3px;
    box-shadow: 0 4px 16px rgba(10,2,24,0.45), inset 0 1px 0 rgba(255,255,255,0.08);
    position: relative;
  }
  .badge::before {
    content: ""; position: absolute; inset: -3px; border-radius: 999px; z-index: -1;
    box-shadow: 0 0 14px 2px rgba(245,197,66,0.55), 0 0 30px 6px rgba(255,59,212,0.22);
    animation: chipGlow 2.6s ease-in-out infinite alternate;
  }
  @keyframes chipGlow { from { opacity: 0.35; } to { opacity: 1; } }

  /* ---------- three-attempt promo state ---------- */
  .attempts {
    position: relative; z-index: 3; flex: none;
    display: flex; align-items: center; justify-content: center; gap: 10px;
    min-height: 56px; margin: clamp(20px, 2.5vh, 28px) 0 0; padding: 0 12px;
  }
  .attempt {
    position: relative; display: block; width: clamp(48px, 6vw, 56px); height: clamp(48px, 6vw, 56px); flex: none;
    transform-origin: 50% 90%;
  }
  .attempt::before, .attempt::after {
    content: ''; position: absolute; inset: 0;
    background-position: center; background-size: contain; background-repeat: no-repeat;
    background-image: var(--promo-bear-image, none);
    filter: drop-shadow(0 5px 8px rgba(12, 1, 25, .55));
    transition: opacity .42s ease, filter .65s ease;
  }
  .attempt::after { opacity: 0; }
  .attempt.failed::before { opacity: 0; }
  .attempt.failed::after {
    opacity: 1;
    filter: brightness(.62) saturate(.45) drop-shadow(0 5px 8px rgba(12, 1, 25, .65));
  }
  .attempt.active { animation: bearBreathe 3.4s ease-in-out infinite; }
  .attempt.active::before, .attempt.won::before { filter: drop-shadow(0 0 9px rgba(255, 207, 115, .55)); }
  @keyframes bearBreathe { 0%, 100% { transform: translateY(0) rotate(-2deg); } 50% { transform: translateY(-5px) rotate(2deg); } }
  .flow-message {
    position: relative; z-index: 3; min-height: 22px; max-width: min(92vw, 620px);
    margin: 3px 12px 0; color: var(--c-gold-100); font-size: clamp(12px, 1.25vw, 16px);
    line-height: 1.3; font-weight: 700; text-align: center;
    text-shadow: 0 2px 9px rgba(12, 1, 25, .9); transition: color .3s ease, text-shadow .3s ease;
  }
  .flow-message.dramatic { color: #fff1a8; text-shadow: 0 0 14px rgba(255, 209, 80, .45), 0 2px 10px rgba(15, 2, 28, .95); }
  @keyframes flowPulse { 50% { transform: scale(1.03); } }

  /* ---------- corner controls ---------- */
  .badge-18 {
    position: fixed; top: max(env(safe-area-inset-top), 10px); left: 10px; z-index: 6;
    font-family: 'Display', Georgia, serif; font-weight: 900; font-size: 12.5px;
    letter-spacing: 0.04em;
    color: var(--gold-1);
    border: 1.5px solid rgba(255,190,18,0.6); border-radius: 999px;
    background: rgba(20,6,38,0.62); backdrop-filter: blur(4px);
    padding: 5px 11px;
  }
  .mute {
    position: fixed; top: max(env(safe-area-inset-top), 10px); right: 10px; z-index: 6;
    width: 38px; height: 38px; padding: 0;
    display: flex; align-items: center; justify-content: center;
    color: var(--gold-1); cursor: pointer;
    background: rgba(20,6,38,0.62); backdrop-filter: blur(4px);
    border: 1.5px solid rgba(255,190,18,0.45); border-radius: 50%;
  }
  .mute svg { width: 19px; height: 19px; }
  .mute .off { display: none; }
  .mute[aria-pressed="true"] .on  { display: none; }
  .mute[aria-pressed="true"] .off { display: block; }

  /* ---------- wheel ---------- */
  /* The wheel claims whatever vertical space the column has left after the
     subheadline, badge, button and fine print, and is capped by its own
     width. Sizing it from the leftover box rather than from a guessed
     reserve is what keeps the compliance fine print on the first screen at
     every window height. */
  /* basis 0, not auto: with an auto basis the wrap's height would depend on the
     wheel while the wheel depends on the wrap, and the pair collapses to zero. */
  .wheel-wrap {
    flex: 1 1 0; min-height: 0; width: 100%;
    /* bottom-aligned rather than centred: the wheel sits low in its box
       instead of floating centred with empty space underneath. The height
       ceilings below deliberately stop short of 100cqh (see the comment
       there), so that empty space always exists above the wheel, not just
       when the box happens to be taller than the disc needs — otherwise a
       wheel that fills its whole column loses the "sitting low" read
       entirely and just looks vertically centred again. */
    display: flex; align-items: flex-end; justify-content: center;
  }
  @supports (container-type: size) {
    .wheel-wrap { container-type: size; }
    /* 96cqh, not 100cqh: capping a little short of the box's full height is
       what keeps a visible gap above the wheel at every width, so it reads
       as sitting low rather than centred — a wheel allowed to fill 100% of
       a tall, narrow column has nowhere left to sit "low" into. */
    .wheel-area { width: min(100cqw, 96cqh, 146vw) !important; height: min(100cqw, 96cqh, 146vw) !important; }
    @media (min-width: 700px) {
      .wheel-area { width: min(100cqw, 96cqh, 148vmin) !important; height: min(100cqw, 96cqh, 148vmin) !important; }
    }
    @media (min-width: 1024px) {
      .wheel-area { width: min(100cqw, 96cqh, 178vh, 100vw, 1960px) !important; height: min(100cqw, 96cqh, 178vh, 100vw, 1960px) !important; }
    }
  }
  /* The wheel stays frontal, with a light horizontal stretch and vertical
     squash so it reads as a larger, slightly oval casino wheel without the
     distracting depth distortion of a perspective tilt. */
  .wheel-area {
    position: relative; flex: none;
    width: var(--wheel); height: var(--wheel);   /* fallback where cq units are unsupported */
    display: flex; align-items: center; justify-content: center;
    transform: scaleX(1.04) scaleY(.95);
    transform-origin: center bottom;
  }
  /* Its own container, not just a sized box: the spin button (and anything
     else added later) sizes itself off the wheel's own rendered box via cq
     units, whichever of the width/height ceilings above actually won —
     `.wheel-wrap`'s container queries above size `.wheel-area` itself, this
     one is for `.wheel-area`'s children. */
  @supports (container-type: size) {
    .wheel-area { container-type: size; }
  }

  /* outer glow — separates the wheel from the background */
  .wheel-area::before {
    content: ""; position: absolute; inset: -6%;
    border-radius: 50%;
    background: radial-gradient(circle, rgba(255,200,40,0.55), rgba(255,120,220,0.18) 52%, transparent 68%);
    filter: blur(18px);
    transition: opacity 0.3s ease;
  }
  /* God rays behind the disc: a repeating conic gradient turning once a minute,
     masked so it fades out well before the column edges. Brightens while the
     wheel spins. */
  .rays {
    position: absolute; inset: -24%; z-index: 0; pointer-events: none; border-radius: 50%;
    background: repeating-conic-gradient(from 0deg,
      rgba(255,214,90,0) 0deg 10deg, rgba(255,222,120,0.36) 14deg 18deg, rgba(255,214,90,0) 23deg 32deg);
    -webkit-mask: radial-gradient(circle closest-side, transparent 18%, #000 28%, rgba(0,0,0,0.82) 62%, transparent 96%);
            mask: radial-gradient(circle closest-side, transparent 18%, #000 28%, rgba(0,0,0,0.82) 62%, transparent 96%);
    opacity: 0.42; filter: blur(2.5px); mix-blend-mode: screen;
    animation: raysSpin 64s linear infinite;
    transition: opacity 0.6s ease;
  }
  .stage.spinning .rays { opacity: .68; }
  @keyframes raysSpin { to { transform: rotate(360deg); } }
  /* The rim is the supplied ring art. Its hole measures 0.761 of its outer
     diameter, so the disc underneath is sized to exactly that and the wedges
     meet the inside of the gold without a seam. */
  .wheel-ring {
    position: absolute; inset: 0; width: 100%; height: 100%;
    z-index: 4; pointer-events: none;
    filter: drop-shadow(0 0 22px rgba(255,190,18,0.5)) drop-shadow(0 16px 40px rgba(0,0,0,0.6));
    animation: none;
  }
  @keyframes ringPulse {
    from { filter: drop-shadow(0 0 16px rgba(255,190,18,0.38)) drop-shadow(0 16px 40px rgba(0,0,0,0.6)); }
    to   { filter: drop-shadow(0 0 40px rgba(255,205,60,0.95)) drop-shadow(0 16px 40px rgba(0,0,0,0.6)); }
  }
  /* A highlight that travels around the gold band, as a light source moving
     past polished metal would. Masked to the band only: 0.76-1.0 of the radius. */
  .rim-shine {
    position: absolute; inset: 0; z-index: 4; pointer-events: none; border-radius: 50%;
    background: conic-gradient(from 0deg,
      rgba(255,255,255,0) 0deg, rgba(255,255,255,0) 38deg, rgba(255,250,225,0.70) 52deg, rgba(255,255,255,0) 66deg,
      rgba(255,255,255,0) 190deg, rgba(255,250,225,0.40) 214deg, rgba(255,255,255,0) 232deg, rgba(255,255,255,0) 360deg);
    -webkit-mask: radial-gradient(circle closest-side, transparent 75%, #000 78%, #000 97%, transparent 100%);
            mask: radial-gradient(circle closest-side, transparent 75%, #000 78%, #000 97%, transparent 100%);
    mix-blend-mode: screen; opacity: 0.85;
    animation: rimShine 7s linear infinite; will-change: transform;
  }
  @keyframes rimShine { to { transform: rotate(360deg); } }
  /* Bulb states, spec §5. The 39 bulbs are painted into the rim art; each gets
     a screen-blended warm halo at its measured centre and only the halo's
     opacity animates.
       idle:  a chase — every third bulb at full, .45 → 1 over 1.2s,
              delay (i % 3) * .4s
       spin:  all bulbs pulse together at 220ms
       win:   three fast full-ring flashes, then back to the idle chase */
  .bulbs {
    position: absolute; inset: 0; width: 100%; height: 100%;
    z-index: 4; pointer-events: none; overflow: visible; mix-blend-mode: screen;
    --bulb-dur: 1.2s;
  }
  .bulb {
    opacity: 0.45;
    animation: bulbChase var(--bulb-dur) ease-in-out infinite;
    animation-delay: calc(var(--ph) * -0.4s);
  }
  @keyframes bulbChase { 0% { opacity: 0.45; } 28% { opacity: 1; } 58%, 100% { opacity: 0.45; } }
  .stage.spinning .bulb {
    animation: bulbChase 900ms ease-in-out infinite;
    animation-delay: calc(var(--ph) * -.3s);
  }
  @keyframes bulbPulse { from { opacity: 0.4; } to { opacity: 1; } }
  .stage.won .bulb {
    animation: bulbChase 2.4s ease-in-out infinite;
    animation-delay: calc(var(--ph) * -.4s);
  }
  @keyframes bulbFlash { 0%, 55% { opacity: 1; } 56%, 100% { opacity: 0.25; } }
  /* Halo behind the rim, breathing out of sync with the pulse so the bulbs
     never look like they blink on a single beat. */
  .wheel-halo {
    position: absolute; inset: -14%; z-index: 0; pointer-events: none; border-radius: 50%;
    background: radial-gradient(circle, rgba(255,196,40,0.5) 30%, rgba(255,120,220,0.22) 52%, rgba(255,196,40,0) 72%);
    filter: blur(26px);
    animation: haloPulse 3.7s ease-in-out infinite alternate;
    will-change: transform, opacity;
  }
  @keyframes haloPulse {
    from { transform: scale(0.94); opacity: 0.6; }
    to   { transform: scale(1.09); opacity: 1; }
  }
  .wheel-svg-wrap {
    position: absolute; top: 50%; left: 50%;
    width: 76.1%; height: 76.1%;
    transform: translate(-50%, -50%);
    border-radius: 50%; overflow: hidden; background: transparent;
  }
  svg.wheel { width: 100%; height: 100%; display: block; will-change: transform; backface-visibility: hidden; }
  .stage.spinning .wheel-rays,
  .stage.spinning .wheel-halo,
  .stage.spinning .attempt.active,
  .stage.spinning .badge::before { animation-play-state: paused; }
  /* rim light */
  .wheel-svg-wrap::after {
    content: ""; position: absolute; inset: 0; border-radius: 50%; pointer-events: none;
    background: linear-gradient(155deg, rgba(255,255,255,0.18) 0%, transparent 34%, transparent 70%, rgba(0,0,0,0.12) 100%);
  }

  /* pointer — pivots from its own top anchor, driven by JS */
  /* spec §6: tip at R_rim_inner + 6, i.e. the chevron overlaps the rim and
     bites into the wedge area. The rim's inner edge is at 0.76 of the radius,
     12% down from the top of the box; a 9.2%-tall chevron whose top sits at
     3.8% puts the tip at 13%. */
  .pointer {
    position: absolute; top: 3.8%; left: 50%;
    width: 8.2%; height: 9.2%;
    margin-left: -4.1%;
    transform-origin: 50% 6%;
    z-index: 5;
    filter: drop-shadow(0 4px 6px rgba(0,0,0,0.65)) drop-shadow(0 0 24px rgba(255,201,74,0.27));
    will-change: transform;
  }
  .pointer svg { width: 100%; height: 100%; display: block; }

  .hub {
    position: absolute; top: 50%; left: 50%;
    width: 23%; height: 23%;
    transform: translate(-50%, -50%);
    border-radius: 50%; padding: 0; overflow: hidden;
    /* spec §5: --c-night-lift disc, 6-unit gold-400 ring (1% of the wheel),
       faint radiating spokes at 12% gold */
    background:
      repeating-conic-gradient(from 0deg, rgba(255,255,255,0.16) 0deg 1.2deg, transparent 1.2deg 15deg),
      radial-gradient(circle at 38% 28%, #fff0a0, #f5b51b 56%, #b86b00 100%);
    border: clamp(4px, 1vw, 7px) solid #F0A81E;
    box-shadow: 0 6px 22px rgba(0,0,0,0.65), 0 0 0 3px rgba(120,72,0,0.75), 0 0 26px rgba(255,190,18,0.4);
    z-index: 6; cursor: pointer;
    display: flex; align-items: center; justify-content: center;
    animation: none;
  }
  @keyframes hubGlow {
    from { box-shadow: 0 6px 22px rgba(0,0,0,0.65), 0 0 0 3px rgba(120,72,0,0.75), 0 0 22px rgba(255,190,18,0.35); }
    to   { box-shadow: 0 6px 22px rgba(0,0,0,0.65), 0 0 0 3px rgba(120,72,0,0.75), 0 0 46px rgba(255,205,60,0.85); }
  }
  .hub::after {
    content: ""; position: absolute; inset: 0; border-radius: 50%; pointer-events: none;
    background: radial-gradient(ellipse 70% 45% at 50% 22%, rgba(255,255,255,0.32), rgba(255,255,255,0) 70%);
  }
  .hub-mark { width: 82%; height: 82%; display: block; }
  .hub-mark text { fill: #3b1160; }
  .hub:disabled { cursor: default; }

  /* ---------- spin CTA (spec §8) ----------
     Pill, --g-cta fill, 3px gold-600 border, --glow-cta outside. Idle: a 2.4s
     breath — scale 1 → 1.02 on the button, glow intensity on the halo layer.
     States: ready / hover+focus / pressed / spinning / used. */
  .btn-spin {
    /* On the wheel, literally: absolutely positioned inside .wheel-area's
       own box (it is a DOM child of it now, not a flow sibling below it),
       low on the disc, between the hub and the rim — not touching the rim
       from outside, sitting on the wedges themselves. Centred without
       `transform`, because `transform` is already spoken for by the
       breathe/hover/press states below and the two would fight over a
       single property. Sized off the wheel's own rendered box (cqw/cqh, via
       .wheel-area's own container-type: size) rather than the viewport, so
       it scales with the disc at every breakpoint automatically. */
    position: absolute; left: 50%; bottom: 9%; margin-left: -130px;
    width: 260px; height: 72px; min-height: 72px;
    z-index: 5;
    border: 3px solid #6d3f02; border-radius: 999px;
    /* deeper than the token ramp: the scene sits lower now, and the old
       --g-cta glowed brighter than the wheel it sits under */
    background: linear-gradient(180deg, #FFD34A 0%, #E7A912 44%, #B87404 100%);
    color: #1a0430;
    display: flex; align-items: center; justify-content: center;
    /* TODO: confirm against asset spec — the label is Armenian and the only
       display face supplied is Latin, so it is set in the text face */
    font-family: 'Armenian', system-ui, sans-serif; font-weight: 800;
    font-size: 28px; letter-spacing: 0.06em;
    cursor: pointer;
    box-shadow: var(--glow-cta), inset 0 1px 0 var(--c-gold-100), inset 0 -2px 0 var(--c-gold-600);
    transition: filter 0.2s ease, box-shadow 0.2s ease, opacity 0.3s ease;
    overflow: hidden; isolation: isolate;
    animation: ctaBreathe 2.4s ease-in-out infinite;
  }
  @keyframes ctaBreathe { 0%, 100% { transform: scale(1); } 50% { transform: scale(1.02); } }
  /* glow intensity breathes on a pseudo-element's opacity, in step with the
     scale, rather than by animating box-shadow */
  .btn-spin::before {
    content: ""; position: absolute; inset: -2px; border-radius: 999px; z-index: -1; pointer-events: none;
    box-shadow: 0 0 30px 6px rgba(255,45,149,0.65), 0 0 70px 14px rgba(255,45,149,0.30);
    animation: neonBreath 2.4s ease-in-out infinite;
  }
  @keyframes neonBreath { 0%, 100% { opacity: 0.35; } 50% { opacity: 1; } }
  .btn-spin::after {
    content: ""; position: absolute; inset: 0; pointer-events: none; z-index: 0;
    border-radius: inherit;
    border: 3px solid transparent;
    background:
      linear-gradient(transparent, transparent) padding-box,
      linear-gradient(105deg,
        rgba(255,255,255,0) 0 30%,
        rgba(255,249,198,.45) 42%,
        #fff5b0 50%,
        rgba(255,194,24,.92) 58%,
        rgba(255,255,255,0) 70%) border-box;
    background-clip: padding-box, border-box;
    -webkit-background-clip: padding-box, border-box;
    background-size: 100% 100%, 300% 100%;
    background-position: 0 0, 100% 0;
    box-shadow: 0 0 9px rgba(255,220,82,.75), inset 0 0 5px rgba(255,247,190,.32);
    animation: edgeShimmer 2.15s ease-in-out infinite;
  }
  @keyframes edgeShimmer {
    0%, 15% { background-position: 0 0, 100% 0; }
    72%, 100% { background-position: 0 0, 0 0; }
  }
  /* hover / focus: glow to 100%, scale 1.03 */
  .btn-spin:hover:not(:disabled):not(.used), .btn-spin:focus-visible:not(:disabled):not(.used) { transform: scale(1.03); animation: none; }
  .btn-spin:hover:not(:disabled):not(.used)::before, .btn-spin:focus-visible:not(:disabled):not(.used)::before { opacity: 1; animation: none; }
  /* pressed */
  .btn-spin:active:not(:disabled):not(.used) {
    transform: scale(0.97) translateY(2px); animation: none;
    box-shadow: var(--glow-cta), inset 0 3px 8px rgba(60,20,0,0.45);
  }
  /* spinning: desaturated 40%, glow off */
  .btn-spin:disabled {
    cursor: default; animation: none;
    filter: saturate(0.6) brightness(0.86);
    box-shadow: inset 0 1px 0 rgba(255,243,196,0.4), inset 0 -2px 0 var(--c-gold-600);
  }
  .btn-spin:disabled::before, .btn-spin:disabled::after,
  .btn-spin.used::before, .btn-spin.used::after { animation: none; opacity: 0; }
  /* used: the one spin is spent */
  /* the used label is four times longer than ՊՏՏԵԼ, so it steps down a size
     rather than wrapping inside the pill */
  /* used is focusable — focus returns to the CTA when the modal closes — but
     inert: aria-disabled plus the `done` guard in the handler */
  .btn-spin.used {
    opacity: 0.55; filter: none; cursor: not-allowed; animation: none; box-shadow: none;
    font-size: clamp(13px, 1.7vw, 22px); letter-spacing: 0.06em; white-space: nowrap;
  }
  .btn-spin:focus-visible, .hub:focus-visible, .mute:focus-visible,
  .btn-claim:focus-visible, .modal-x:focus-visible {
    outline: 3px solid var(--c-gold-100); outline-offset: 4px;
  }

  .action-panel {
    position: fixed; right: clamp(18px, 4.5vw, 72px); bottom: max(env(safe-area-inset-bottom), 22px);
    z-index: 8; width: 280px; display: flex; flex-direction: column; align-items: center;
    gap: 8px; text-align: center;
  }
  .fineprint, .rg { content-visibility: auto; contain-intrinsic-size: auto 40px; }
  .fineprint {
    color: var(--muted); font-size: clamp(9.5px, 2.5vw, 11px);
    line-height: 1.38; letter-spacing: 0.02em; max-width: 44ch;
    text-shadow: 0 1px 6px rgba(10,2,24,0.95);
  }
  .rg { color: rgba(195,173,223,0.72); font-size: clamp(9px, 2.3vw, 10.5px); }
  .rg a { color: inherit; text-underline-offset: 2px; }

  .sr-only { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }

  .error {
    display: none;
    color: #ffc9c9; font-size: 12px; line-height: 1.45; max-width: 34ch;
    border: 1px solid rgba(255,120,120,0.45); border-radius: 12px;
    background: rgba(70,10,20,0.55); padding: 9px 12px;
  }
  .error.show { display: block; }

  /* ---------- win modal ---------- */
  /* Deliberately NOT a dim overlay: the celebration continues on the same
     bright stage, so this only adds a soft warm wash. */
  .overlay {
    position: fixed; inset: 0; z-index: 30;
    display: flex; align-items: center; justify-content: center; padding: 16px;
    /* Dim and soften the scene during the result state so the win card owns
       the visual focus while the celebration remains barely visible behind it. */
    background: rgba(7, 2, 20, .78);
    -webkit-backdrop-filter: blur(8px); backdrop-filter: blur(8px);
    opacity: 0; pointer-events: none; transition: opacity 0.3s ease;
  }
  .overlay.show { opacity: 1; pointer-events: auto; }
  .reward-choices { display: flex; flex-wrap: wrap; justify-content: center; gap: 8px; margin-top: 14px; }
  .reward-choices button, .btn-continue { border: 1px solid #ffd773; border-radius: 12px; padding: 10px; color: #fff3ce; background: #32105d; font: inherit; cursor: pointer; }
  .reward-choices button[aria-pressed='true'] { background: #ffcf58; color: #32105d; box-shadow: 0 0 12px #ffd77366; }
  .btn-continue { width: 100%; margin-top: 14px; }
  .btn-continue[hidden] { display: none; }
  .grand-prize-label text { fill: #fff3b0; stroke: #613612; }
  .overlay.loss .win-prize { font-size: clamp(24px, 6vw, 30px); line-height: 1.25; }
  .overlay.loss .win-desc { font-size: 16px; line-height: 1.5; }
  .loss-bear { display: block; width: 100px; height: 100px; margin: auto; background: var(--promo-bear-image, none) center / contain no-repeat; }
  .win-card {
    position: relative; z-index: 1; width: min(92vw, 330px);
    border-radius: 24px; padding: 30px 24px 24px; overflow: hidden;
    text-align: center;
    background: linear-gradient(180deg, rgba(70,24,124,0.97), rgba(35,11,68,0.97));
    border: 1.5px solid var(--gold-2);
    background:
      radial-gradient(ellipse at 50% 0%, rgba(255,220,112,.16), transparent 58%),
      linear-gradient(180deg, rgba(76,24,132,.99), rgba(24,7,52,.99));
    box-shadow:
      0 26px 64px rgba(0,0,0,.82),
      0 0 0 5px rgba(255,190,18,.2),
      0 0 34px rgba(255,198,42,.5),
      0 0 90px rgba(255,45,149,.24);
    transform: translateY(16px) scale(0.94);
    transition: transform 0.45s cubic-bezier(0.2,0.9,0.25,1.2);
  }
  .overlay.show .win-card { transform: translateY(0) scale(1); }
  .modal-x {
    position: absolute; top: 8px; right: 8px; width: 30px; height: 30px; padding: 0;
    display: flex; align-items: center; justify-content: center;
    border: none; background: none; cursor: pointer;
    color: rgba(246,236,255,0.42); font-size: 19px; line-height: 1;
  }
  .modal-x:hover { color: rgba(246,236,255,0.8); }
  .win-kicker {
    color: var(--gold-1); letter-spacing: 0.22em; font-size: 11.5px; font-weight: 700;
    display: flex; align-items: center; justify-content: center; gap: 10px;
  }
  .win-kicker::before, .win-kicker::after { content:""; width:18px; height:1px; background:linear-gradient(90deg,transparent,var(--gold-2)); }
  .win-kicker::after { background:linear-gradient(90deg,var(--gold-2),transparent); }
  .win-medal { margin: 16px auto 10px; width: 88px; height: 88px; }
  /* The prize name is the largest thing on the screen. */
  .win-prize {
    font-family: 'Display', Georgia, serif; font-weight: 900;
    font-size: clamp(26px, 8vw, 40px); line-height: 1.06; letter-spacing: 0.02em;
    background: linear-gradient(180deg, #fff6d4, #ffc21a 56%, #d68c00);
    -webkit-background-clip: text; background-clip: text; -webkit-text-fill-color: transparent;
    filter: drop-shadow(0 3px 16px rgba(255,190,18,0.4));
  }
  /* Armenian prize names render in the Armenian face, not the Latin display one. */
  .win-prize.hy { font-family: 'Armenian', system-ui, sans-serif; font-weight: 800; letter-spacing: 0.01em; }
  .win-desc { margin-top: 12px; color: var(--muted); font-size: 12.5px; line-height: 1.5; }
  .btn-claim, .btn-continue {
    position: relative; isolation: isolate; overflow: hidden;
    margin-top: 20px; width: 100%; min-height: 52px; padding: 8px 10px;
    border: 2px solid #ffe071; border-radius: 14px;
    background: linear-gradient(180deg, #ffe89a, #ffbe12 50%, #cf8a00);
    color: #2a0b04; font-family: 'Armenian', system-ui, sans-serif;
    font-weight: 800; font-size: 16px; letter-spacing: 0.04em;
    cursor: pointer;
    box-shadow:
      0 0 0 1px rgba(255,246,180,.95),
      0 0 12px rgba(255,224,86,.95),
      0 0 30px rgba(255,177,18,.72),
      0 12px 28px rgba(255,190,18,.42),
      inset 0 2px 0 rgba(255,255,255,0.72),
      inset 0 -3px 0 rgba(180,93,0,.35);
  }
  .btn-claim::after, .btn-continue::after {
    content: ""; position: absolute; z-index: -1; inset: -40% auto -40% -35%; width: 24%;
    background: linear-gradient(90deg, transparent, rgba(255,255,255,.82), transparent);
    transform: skewX(-20deg) translateX(-420%);
    animation: claimShine 2.6s ease-in-out infinite;
    pointer-events: none;
  }
  @keyframes claimShine {
    0%, 42% { transform: skewX(-20deg) translateX(-420%); }
    72%, 100% { transform: skewX(-20deg) translateX(720%); }
  }
  .btn-claim:active, .btn-continue:active { transform: translateY(2px); }
  .btn-continue:focus-visible { outline: 2px solid #fff3c4; outline-offset: 4px; }
  /* While another spin is available, it is the primary action. Once hidden,
     the claim button automatically regains its original gold treatment. */
  .btn-continue:not([hidden]) ~ .btn-claim {
    background: #32105d;
    color: #fff3ce;
    border: 1px solid #bfa064;
    box-shadow: none;
    font-weight: 600;
    margin-top: 14px;
  }
  .btn-continue:not([hidden]) ~ .btn-claim::after { display: none; animation: none; }

  .overlay.show .win-medal { animation: medalpop 820ms cubic-bezier(0.2,0.9,0.25,1.3) both; }
  @keyframes medalpop {
    0%   { transform: scale(0.25) rotate(-30deg); opacity: 0; }
    55%  { transform: scale(1.14) rotate(6deg);   opacity: 1; }
    100% { transform: scale(1)    rotate(0);      opacity: 1; }
  }
  .overlay.show .win-prize { animation: prizein 760ms cubic-bezier(0.2,0.9,0.25,1.25) both; }
  @keyframes prizein {
    0%   { transform: scale(0.55); opacity: 0; filter: drop-shadow(0 0 0 rgba(255,190,18,0)); }
    60%  { transform: scale(1.1);  opacity: 1; filter: drop-shadow(0 0 36px rgba(255,226,140,0.95)); }
    100% { transform: scale(1);    opacity: 1; filter: drop-shadow(0 3px 16px rgba(255,190,18,0.4)); }
  }
  .win-card::after {
    content: ""; position: absolute; inset: 0; pointer-events: none;
    background: linear-gradient(104deg, transparent 36%, rgba(255,255,255,0.3) 48%, transparent 61%);
    transform: translateX(-130%);
  }
  .overlay.show .win-card::after { animation: shine 1.15s 0.4s ease-out; }
  @keyframes shine { to { transform: translateX(130%); } }

  /* Choreography: a quiet idle, a travelling light during the spin, then a
     readable landing. Individual translate/scale leave wheel transforms intact. */
  .spin-aura {
    position: absolute; inset: -3%; border-radius: 50%; z-index: 3;
    pointer-events: none; opacity: 0;
    background: conic-gradient(from 20deg, transparent 0 200deg, rgba(255,97,192,.15) 258deg,
      rgba(255,215,131,.65) 294deg, #fff6d8 302deg, transparent 308deg);
    -webkit-mask: radial-gradient(closest-side, transparent 94%, #000 96%, transparent 100%);
    mask: radial-gradient(closest-side, transparent 94%, #000 96%, transparent 100%);
    animation: raysSpin 1.6s linear infinite; animation-play-state: paused;
    transition: opacity .7s ease;
  }
  .stage.spinning .spin-aura { opacity: .9; animation-play-state: running; }
  .stage[data-motion='settling'] .spin-aura { opacity: .3; }
  .stage[data-motion='settling'] .rays { opacity: .82; }
  .stage.spinning .attempt.active { animation: bearBreathe 1.6s ease-in-out infinite; }
  .stage[data-motion='winning'] .wheel-halo { animation: winningHalo 1s ease-out both; }
  @keyframes winningHalo { from { opacity: .6; scale: 1; } to { opacity: 1; scale: 1.18; } }
  .bomb-mark { transform-box: fill-box; transform-origin: center; }
  .bomb-mark.fuse-lit { animation: fuseAnticipation .44s ease-in forwards; }
  @keyframes fuseAnticipation {
    0% { scale: 1; filter: brightness(1); }
    60% { scale: 1.12; filter: brightness(1.3) drop-shadow(0 0 3px #ffa343); }
    100% { scale: 1.22; filter: brightness(1.6) drop-shadow(0 0 5px #ffc66b); }
  }
  .wheel-svg-wrap { z-index: 1; }
  svg.wheel { will-change: transform; }
  .btn-spin { transition: transform .2s ease, filter .2s ease, opacity .3s ease; }
  .stage[data-motion='ready'] .btn-spin { animation-duration: 3.6s; }
  .intro-overlay.show .attempt-bear { animation: introBear .8s cubic-bezier(.2,.8,.2,1) both; }
  .intro-overlay.show .attempt-bear:nth-child(2) { animation-delay: .12s; }
  .intro-overlay.show .attempt-bear:nth-child(3) { animation-delay: .24s; }
  @keyframes introBear {
    0% { opacity: 0; transform: translateY(16px) scale(.65) rotate(-9deg); }
    65% { opacity: 1; transform: translateY(-5px) scale(1.06) rotate(3deg); }
    100% { opacity: 1; transform: translateY(0) scale(1) rotate(0); }
  }
  .stage.motion-paused *, .stage.motion-paused *::before, .stage.motion-paused *::after { animation-play-state: paused !important; }

  /* ---------- intro modal ---------- */
  .intro-overlay {
    position: fixed; inset: 0; z-index: 40; display: flex; align-items: center; justify-content: center;
    padding: 18px; background: rgba(5, 0, 15, .64); backdrop-filter: blur(4px);
    opacity: 0; pointer-events: none; transition: opacity .28s ease;
  }
  .intro-overlay.show { opacity: 1; pointer-events: auto; }
  .intro-card {
    width: min(92vw, 360px); padding: 26px 24px 24px; border-radius: 24px; text-align: center;
    background: radial-gradient(ellipse at 50% 0%, rgba(255, 220, 112, .18), transparent 58%), linear-gradient(180deg, rgba(76,24,132,.98), rgba(24,7,52,.99));
    border: 1.5px solid var(--gold-2); box-shadow: 0 24px 64px rgba(0,0,0,.8), 0 0 36px rgba(255, 198, 42, .42);
    transform: translateY(12px) scale(.95); transition: transform .42s cubic-bezier(.2,.9,.25,1.2);
  }
  .intro-overlay.show .intro-card { transform: translateY(0) scale(1); }
  .intro-kicker { color: var(--gold-1); font-size: 11px; font-weight: 800; letter-spacing: .22em; }
  .intro-bears { display: flex; justify-content: center; gap: 12px; margin: 18px 0 12px; }
  .attempt-bear { width: 58px; height: 58px; background: var(--promo-bear-image, none) center / contain no-repeat; filter: drop-shadow(0 0 12px rgba(255, 78, 185, .5)); }
  .intro-card h2 { margin: 7px 0 10px; color: #fff4c2; font: 800 clamp(22px, 6vw, 30px)/1.12 'Armenian', system-ui, sans-serif; }
  .intro-card p { margin: 0; color: var(--muted); font-size: 13px; line-height: 1.55; }
  .btn-intro { width: 100%; margin-top: 20px; min-height: 50px; border: 2px solid #ffe071; border-radius: 14px; background: linear-gradient(180deg, #ffe89a, #ffbe12 50%, #cf8a00); color: #2a0b04; font: 800 16px 'Armenian', system-ui, sans-serif; cursor: pointer; box-shadow: 0 0 16px rgba(255, 213, 63, .72), inset 0 2px 0 rgba(255,255,255,.7); }
  .btn-intro:active { transform: translateY(2px); }

  /* Fireworks and confetti stay below the modal so the win card is always
     readable while the celebration remains visible behind it. */
  canvas.motion-fx { position: fixed; inset: 0; width: 100%; height: 100%; z-index: 25; pointer-events: none; }
  canvas.fx { position: fixed; inset: 0; z-index: 21; pointer-events: none; }
  canvas.confetti { position: fixed; inset: 0; z-index: 22; pointer-events: none; }
  .wheel-area { scale: 1; transition: scale 650ms cubic-bezier(.22,1,.36,1); transform-origin: center bottom; }
  .stage.spinning .wheel-area { scale: 1.045; }
  .motion-reduced .stage.spinning .wheel-area { scale: 1; }
  @media (max-width: 700px) { .stage.spinning .wheel-area { scale: 1.025; } }
  .overlay > canvas.motion-fx { z-index: 0; }

  /* ---------- mascot ---------- */
  /* Single bear at the bottom-left, as in the reference art. Its backdrop was
     feathered to transparent rather than keyed — the original sits on a soft
     dark gradient that no flat key can lift without eating the black suit. */
  .bear {
    /* Sits below the fold so the bear reads lower in frame. Less on a phone,
       where it is only ~400px tall and 100px would crop a quarter of it. */
    position: fixed; left: 0; bottom: -48px; z-index: 1; pointer-events: none;
    width: min(64vw, 340px); height: min(56vh, 480px);
    background: url('bear.df183e002c.webp') no-repeat left bottom / contain;
    opacity: 0.6;
    /* rim light from the magenta side of the scene; a static filter, so it is
       rasterised once and never repainted */
    filter: brightness(0.74) saturate(1.3)
            drop-shadow(0 0 28px rgba(255,60,190,0.42)) drop-shadow(0 0 6px rgba(255,200,80,0.28));
    transform-origin: 30% 100%;
    animation: none;
  }
  /* breathing rides on top of the parallax translate */
  @keyframes bearBreathe {
    0%, 100% { transform: translate(var(--px), var(--py)) scale(1); }
    50%      { transform: translate(var(--px), var(--py)) scale(1.015); }
  }
  /* an eye glint on the lens every ~6s. The bear's glasses sit at about
     57% / 23% of its box in bear.df183e002c.webp — move these two numbers if the art
     changes (README: "swap the bear"). */
  .bear::after {
    content: ""; position: absolute; left: 57%; top: 23%; width: 22px; height: 22px;
    margin: -11px 0 0 -11px; pointer-events: none; opacity: 0;
    background:
      radial-gradient(circle, rgba(255,255,255,1) 0 14%, rgba(255,255,255,0) 40%),
      linear-gradient(rgba(255,255,255,0.95), rgba(255,255,255,0.95)) 50% 50% / 100% 2px no-repeat,
      linear-gradient(rgba(255,255,255,0.95), rgba(255,255,255,0.95)) 50% 50% / 2px 100% no-repeat;
    animation: none;
  }
  @keyframes glint {
    0%, 88%, 100% { opacity: 0; transform: scale(0.3) rotate(0deg); }
    91% { opacity: 1; transform: scale(1) rotate(20deg); }
    95% { opacity: 0; transform: scale(0.4) rotate(45deg); }
  }
  @media (min-width: 760px) {
    .bear { width: min(38vw, 540px); height: min(82vh, 780px); bottom: -86px; opacity: 0.95; }
  }
  @media (min-width: 1180px) {
    .bear { width: min(35vw, 660px); height: min(88vh, 940px); bottom: -86px; opacity: 1; }
  }

  /* Wide screens: the column opens up, which widens the wheel's box. */
  @media (min-width: 760px) {
    .subheadline::before, .subheadline::after { flex-basis: 110px; }
    .wheel-area { transform: scaleX(1.08) scaleY(.92); }
  }
  @media (min-width: 1000px) {
    .app { max-width: 1080px; }
    .subheadline::before, .subheadline::after { flex-basis: 150px; }
  }

  /* Medium desktop/tablet Preview windows have enough width for the full
     composition, but not enough height for the wide-screen wheel ceiling. */
  @media (min-width: 900px) and (max-width: 1100px) {
    .wheel-area {
      width: min(78vw, 64vh, 720px) !important;
      height: min(78vw, 64vh, 720px) !important;
      margin-bottom: clamp(24px, 4vh, 40px);
    }
  }

  /* Short windows: tighten everything around the wheel so it keeps as much of
     the remaining height as possible without pushing the fine print off. */
  @media (max-height: 800px) {
    .app { gap: clamp(4px, 0.8vh, 8px); }
    .brand-lockup { margin-top: 0; }
    .brand-logo { width: 52px; }
    .brand-lockup h1 { font-size: clamp(24px, 3.3vw, 40px); }
    .fineprint { font-size: clamp(8.5px, 2vw, 9.5px); }
  }

  /* ---------- portrait (spec §7) ----------
     Under 768px the mascot and the Vegas sign go (the bear was under the
     wheel there anyway), the fronds with the sign, the scene re-crops to
     50% 30%, and the CTA is full width minus 32px gutters. The wheel keeps
     the full width rather than the spec's min(86vw, 52vh) — on a phone
     width is the only ceiling and the owner wants it at the ceiling. The
     mascot is also hidden below 900px wide (§7 desktop). */
  @media (max-width: 899px) {
    .bear { display: none; }
    /* Keep the Vegas sign as part of the top composition on tablets and
       phones, but scale and move it away from the live header copy. */
    .deco { display: block; width: min(34vw, 230px); opacity: .92; }
    .deco .vegas { right: -4%; top: 7%; width: 106%; }
    .subheadline { top: clamp(52px, 8vh, 78px); }
    .badge { top: clamp(56px, 8vh, 82px); }
    .action-panel {
      right: 50%; transform: translateX(50%); bottom: max(env(safe-area-inset-bottom), 12px);
      width: 280px;
    }
    .wheel-wrap { align-items: center; }
    .wheel-area {
      width: min(86cqw, 90cqh, 142vw) !important;
      height: min(86cqw, 90cqh, 142vw) !important;
      margin-bottom: 0;
      transform: scaleX(1.03) scaleY(.94);
    }
  }
  @media (max-width: 767px) {
    .bg-photo { background-position: 50% 30%; }
    .action-panel { right: 50%; transform: translateX(50%); bottom: max(env(safe-area-inset-bottom), 12px); width: 280px; }
    .btn-spin { width: 240px; height: 64px; min-height: 64px; margin-left: -120px; font-size: 25px; }
    .subheadline { top: clamp(36px, 6vh, 56px); font-size: clamp(20px, 4.5vw, 26px); letter-spacing: .035em; gap: 6px; }
    .badge { top: clamp(40px, 6vh, 60px); }
    .deco { width: min(42vw, 190px); opacity: .82; }
    .deco .palm { opacity: .72; }
    .deco .vegas { right: -10%; top: 9%; width: 114%; }
    /* Center the wheel in the usable phone stage instead of bottom-aligning it
       and applying a viewport-specific offset. This keeps it stable across
       different phone heights and browser chrome sizes. */
    .wheel-wrap { align-items: center; }
    .wheel-area {
      width: min(94cqw, 96cqh, 142vw) !important;
      height: min(94cqw, 96cqh, 142vw) !important;
      margin-bottom: 0;
      transform: scaleX(1.02) scaleY(.94);
    }
    .action-panel { gap: 4px; }
    .fineprint { max-width: 260px; margin: 0; }
    .rg { margin: 0; }
  }
  @media (max-width: 480px) {
    .subheadline::before, .subheadline::after { display: none; }
    .subheadline { max-width: calc(100vw - 48px); font-size: 20px; letter-spacing: .025em; }
    .deco { width: 178px; right: -18px; }
    .deco .vegas { top: 10%; width: 118%; }
  }

  /* Keep header elements in normal flow: visual top offsets used to put the
     badge over the bears on phones. Reserve space for fixed utility buttons. */
  .app { padding-top: max(calc(env(safe-area-inset-top) + 48px), 48px); }
  .subheadline, .badge { top: auto; flex-shrink: 0; }
  .attempts { margin-top: 14px; }
  .flow-message { flex-shrink: 0; }
  .subheadline { text-wrap: balance; }
  .intro-card, .win-card { max-height: calc(100dvh - 32px); overflow-y: auto; }
  @media (max-width: 899px) {
    .app { padding-bottom: max(calc(env(safe-area-inset-bottom) + 72px), 72px); }
    .subheadline { max-width: calc(100vw - 32px); }
    .subheadline::before, .subheadline::after { display: none; }
    .deco { opacity: .55; }
    .attempts { margin-top: 16px; }
    .btn-spin { width: min(72cqw, 280px); margin-left: 0; translate: -50% 0; font-size: clamp(17px, 5cqw, 25px); height: clamp(44px, 12cqw, 64px); min-height: 44px; }
  }
  @media (max-height: 600px) {
    .app { gap: 3px; }
    .subheadline { font-size: clamp(17px, 2.5vw, 24px); }
    .attempts { margin-top: 8px; min-height: 40px; }
    .attempt { width: 40px; height: 40px; }
  }
  @media (max-height: 480px) and (orientation: landscape) {
    .stage { overflow-y: auto; }
    .app { min-height: 560px; flex-shrink: 0; }
    .action-panel { position: absolute; }
  }

  /* Maximize the disc in the remaining layout space. Include the horizontal
     stretch and spin enlargement in the width limit to keep the rim visible. */
  @supports (container-type: size) {
    .app { max-width: 100%; }
    .wheel-wrap { align-items: flex-start; padding-top: 4px; }
    .wheel-area {
      width: min(91cqw, 104cqh) !important;
      height: min(91cqw, 104cqh) !important;
      transform: scaleX(1.04) scaleY(.92);
      transform-origin: center top;
      margin-bottom: 0;
    }
    @media (max-width: 759px) {
      .wheel-area {
        width: min(95cqw, 104cqh) !important;
        height: min(95cqw, 104cqh) !important;
        transform: scaleX(1.02) scaleY(.92);
      }
    }
  }

  .motion-reduced .stage *, .motion-reduced .stage *::before, .motion-reduced .stage *::after {
    animation: none !important; transition-duration: .1s !important;
  }
  .motion-reduced .spin-aura, .motion-reduced .motion-fx { display: none; }
  @media (prefers-reduced-motion: reduce) {
    :root:not(.motion-full) .stage *, :root:not(.motion-full) .stage *::before, :root:not(.motion-full) .stage *::after {
      animation: none !important;
      transition-duration: .1s !important;
    }
    :root:not(.motion-full) .spin-aura, :root:not(.motion-full) .motion-fx { display: none; }
  }
