/* MegaWheel body content (brief 18). Wheel art direction: design lead 2026-10-16 (ring,
   pointer and logo art in assets/wheel/). Everything else not in the reference is a placeholder
   (data-todo="design"). Face SVG constants live in js/games/wheel/wheel.js. */

.wh-title {
  width: 288px;
  margin: 0;
  font: 800 16px/32px 'Inter', sans-serif;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: #fff;
  text-align: center;
  /* One line always (long tier names, e.g. PLATINUM): wheel.js fitTitle() shrinks the font. */
  white-space: nowrap;
}

/* Fixed stage hosting the wheel or the result card, so the modal height never changes.
   Art direction 2026-10-16: code-rendered face under two static images (no frame, no pedestal)
   plus a code-drawn bulb layer:
   Lengths are in art units = px of the 1024 px / 299 x 400 originals in design-sources/wheel/
   (the shipped PNGs are 2x downscales, 614 px / 179 x 240, stretched into these same boxes; see
   js/games/wheel/layout.js SHIPPED_PX).
     assets/wheel/ring-sockets.png  1024 x 1024 ring units, gold ring with 17 light sockets whose
       interiors were baked royal blue offline (unlit state), transparent centre. Alpha-channel circle fits (alpha > 128, 720 rays): hole centre
       (510.3, 484.3), inner radius 349.6 (347.8..351.7 around the circle; 355.1 max at
       alpha > 250); outer edge centre (510.5, 491.3), radius 438.9. Socket centres:
       RING_SOCKETS in js/games/wheel/layout.js (dark hole about 38 px across).
     assets/wheel/pointer.png  299 x 400 pointer units, tip down. Opaque bbox x 86..202, y 72..291;
       axis x 143.5, tip (143, 290); ball centre about (143.5, 125).
   --wh-k scales ring units to CSS px, --wh-p pointer units, --wh-cy is the face centre
   from the stage top. The face (radius 356 ring units) runs a few px under the ring so no gap
   shows. The pointer tip sits 8px inside the face edge, on the face's vertical axis
   (POINTER_ANGLE stays 0). */
.wh-stage {
  --wh-k: 0.3;
  --wh-p: 0.3;
  --wh-cy: 164px;
  position: relative;
  flex-shrink: 0;
  width: 288px;
  height: 300px;
  /* Visible, so the sunburst fades out on its own mask instead of being cut at the stage box. */
  overflow: visible;
  margin-bottom: 12px; /* breathing room under the wheel (design lead, 2026-10-16) */
}

/* The shared modal body clips the oversized sunburst at the card edge (wheel-only rule, the
   modal itself stays game-agnostic). isolation: the body becomes the stacking context of the
   wheel content, so the sunbursts (z-index -1) paint above the body background but under every
   in-flow element (title, Spin CTA, availability); otherwise the absolutely positioned stage
   sunburst, which overflows the stage, painted over the non-positioned CTA. */
.sm-body:has(.wh-stage) { overflow: hidden; isolation: isolate; }


/* Gold / black sunburst rays behind the wheel, centred on the face. */
.wh-sunburst {
  position: absolute;
  left: 50%;
  top: var(--wh-cy);
  width: 460px;
  height: 460px;
  margin: -230px 0 0 -230px;
  pointer-events: none;
  z-index: -1; /* under the CTA / title, see .sm-body:has(.wh-stage) */
  /* Calm rays: a shade lighter than the modal, so they read as texture, not as a feature. */
  background: repeating-conic-gradient(rgba(255, 255, 255, 0.045) 0deg 10deg, transparent 10deg 20deg);
  /* Fades to fully transparent before its own edge, so no hard cut-off anywhere. */
  -webkit-mask-image: radial-gradient(circle closest-side, #000 60%, transparent 100%);
  mask-image: radial-gradient(circle closest-side, #000 60%, transparent 100%);
  animation: wh-spin-slow 60s linear infinite;
}

.wh-box {
  position: absolute;
  inset: 0;
  transition: filter 200ms ease-out;
}
.wh-box.is-dimmed { filter: brightness(0.35) saturate(0.6); }

.wh-ring,
.wh-pointer {
  position: absolute;
  pointer-events: none;
  user-select: none;
  -webkit-user-drag: none;
}
.wh-ring {
  left: calc(50% - 510.3px * var(--wh-k));
  top: calc(var(--wh-cy) - 484.3px * var(--wh-k));
  width: calc(1024px * var(--wh-k));
  height: calc(1024px * var(--wh-k));
}

/* Bulbs: same box as the ring image. The unlit state is baked into ring-sockets.png (blue
   socket glass); each .wh-bulb is the lit sprite assets/wheel/bulb-on.png (64 ring units:
   bulb disk 32 px over the ~38 px socket + its halo), centred on a socket (RING_SOCKETS, inline
   left/top %). No CSS glow (box-shadow / filter): only opacity animates, on the compositor.
   Patterns (class set by wheel.js setLights):
     --idle  odd / even alternate, 0.6 s per phase
     --spin  chase clockwise, 70 ms per step: two lit bulbs + a half-lit tail
     --win   all flash together 4 x 250 ms, then wheel.js switches back to --idle
   No class = steady on. prefers-reduced-motion: steady on. */
.wh-lights {
  --wh-step: 70ms;
  position: absolute;
  left: calc(50% - 510.3px * var(--wh-k));
  top: calc(var(--wh-cy) - 484.3px * var(--wh-k));
  width: calc(1024px * var(--wh-k));
  height: calc(1024px * var(--wh-k));
  pointer-events: none;
}
.wh-bulb {
  position: absolute;
  width: 6.25%;
  height: 6.25%;
  transform: translate(-50%, -50%);
  opacity: 1;
  will-change: opacity;
  user-select: none;
  -webkit-user-drag: none;
}
.wh-lights--idle .wh-bulb { animation: wh-bulb-blink 1.2s step-end infinite; }
.wh-lights--idle .wh-bulb:nth-child(even) { animation-delay: -0.6s; }
.wh-lights--spin .wh-bulb {
  animation: wh-bulb-chase calc(var(--n) * var(--wh-step)) step-end infinite;
  animation-delay: calc((var(--i) - var(--n)) * var(--wh-step));
}
.wh-lights--win .wh-bulb { animation: wh-bulb-blink 250ms step-end 4; }
@keyframes wh-bulb-blink { 0% { opacity: 1; } 50%, 100% { opacity: 0; } }
/* One step is 100% / n of the cycle (1/17 = 5.88% for the 17 sockets): the head and the bulb one
   step behind are lit (2/17 = 11.76%), the one two steps behind is half lit (3/17 = 17.65%).
   Update the breakpoints if RING_SOCKETS changes length. */
@keyframes wh-bulb-chase { 0% { opacity: 1; } 11.7% { opacity: 0.4; } 17.6%, 100% { opacity: 0; } }
/* Tip y = face centre - inner radius + 8px. Wiggle rotates around the ball. */
.wh-pointer {
  left: calc(50% - 143.5px * var(--wh-p));
  top: calc(var(--wh-cy) - 349.6px * var(--wh-k) + 8px - 290px * var(--wh-p));
  width: calc(299px * var(--wh-p));
  height: calc(400px * var(--wh-p));
  transform-origin: 48% 31.25%;
  filter: drop-shadow(0 2px 3px rgba(0, 0, 0, 0.5));
}

/* Face: circle of radius 356 ring units centred on the ring's hole. Only .wh-rotor rotates. */
.wh-face {
  position: absolute;
  left: calc(50% - 356px * var(--wh-k));
  top: calc(var(--wh-cy) - 356px * var(--wh-k));
  width: calc(712px * var(--wh-k));
  height: calc(712px * var(--wh-k));
}
.wh-rotor {
  position: absolute;
  inset: 0;
  border-radius: 50%;
  transform-origin: 50% 50%;
  will-change: transform;
}
.wh-rotor svg { display: block; width: 100%; height: 100%; overflow: visible; }
.wh-separator { stroke: #ffd463; stroke-width: 1.6; stroke-linecap: round; filter: drop-shadow(0 0 1px rgba(90, 50, 6, 0.9)); }
.wh-label text {
  font-family: 'Inter', sans-serif;
  font-weight: 900;
  paint-order: stroke;
  stroke: #5a3206;
  stroke-width: 3px;
  stroke-linejoin: round;
}
.wh-label { filter: drop-shadow(0 1.5px 1px rgba(0, 10, 50, 0.6)); }
/* Winning sector: pale blue glaze (brightens either blue without greying it) + gold edge. */
.wh-highlight { fill: #5fb0ff; fill-opacity: 0.75; stroke: #ffd463; stroke-width: 4; stroke-linejoin: round; opacity: 0; pointer-events: none; }
.wh-highlight.is-winner { animation: wh-winner 400ms ease-in-out 3 alternate both; }
@keyframes wh-winner { from { opacity: 0; } to { opacity: 1; } }
@keyframes wh-spin-slow { from { transform: rotate(0deg); } to { transform: rotate(360deg); } }

/* Centre hub (static, above the face, below the ring / bulbs / pointer): bezel outer radius 36 of
   the face's 118 SVG units (labels start at radius ~50). Layers, all baked PNGs (no CSS glow):
   assets/wheel/hub-bezel[-<tier>].png 240 x 240 units (shipped 156 px), bezel radius 100 at the centre, so it is drawn
   at 120% of the hub box (its baked drop shadow overhangs); the VIP icon fills ~78% of the
   recessed dish (dish radius 74 of 100); hub-gloss.png same 240 canvas, over the icon. */
.wh-hub {
  position: absolute;
  left: 50%;
  top: 50%;
  width: calc(100% * 72 / 236);
  height: calc(100% * 72 / 236);
  transform: translate(-50%, -50%);
}
.wh-hub__bezel,
.wh-hub__gloss {
  position: absolute;
  left: -10%;
  top: -10%;
  width: 120%;
  height: 120%;
  pointer-events: none;
}
.wh-hub__icon {
  position: absolute;
  left: 21%;
  top: 21%;
  width: 58%;
  height: 58%;
  object-fit: contain;
  pointer-events: none;
}
.wh-hub__logo { width: 100%; height: 100%; object-fit: contain; border-radius: 50%; }

/* No-attempts notice over the dimmed wheel (Smartico no_attempts_message popup). */
.wh-notice {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 24px;
}
.wh-notice[hidden] { display: none; }
.wh-notice__text {
  margin: 0;
  padding: 16px;
  border: 1px solid rgba(242, 193, 78, 0.5);
  border-radius: 14px;
  background: rgba(8, 12, 25, 0.88);
  font: 600 14px/20px 'Inter', sans-serif;
  color: #fff;
  text-align: center;
}

/* Spin CTA idle pulse: scale 1 +- 0.04, 1 s loop. */
.sm-cta.wh-cta--pulse { animation: wh-pulse 1s ease-in-out infinite; }
@keyframes wh-pulse { 0%, 100% { transform: scale(0.96); } 50% { transform: scale(1.04); } }

/* Result card (scratch result pattern): placeholder, data-todo="design". */
.wh-result {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 8px;
  width: 100%;
  height: 100%;
  padding: 0 24px;
}
/* Same stage size as the wheel (modal height never changes, design lead 2026-10-16); the 12px top
   padding offsets the stage's 12px margin-bottom, so the result sits centred between the title
   and the CTA (equal space above and below). */
.wh-stage--result .wh-result { padding-top: 12px; }
.wh-result__icon { width: 96px; height: 96px; object-fit: cover; }
.wh-result__badge {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  width: 104px;
  height: 104px;
  border-radius: 50%;
  background: radial-gradient(circle at 50% 40%, var(--wh-badge-light, #0a74f6) 0%, var(--wh-badge-dark, #0052d4) 100%);
  box-shadow: 0 0 0 3px #f2c14e, 0 0 0 5px #5a3a06;
  font: 900 22px/24px 'Inter', sans-serif;
  color: #ffd55a;
  text-shadow: 0 1px 0 #5a3206, 0 0 1px #5a3206, 0 2px 3px rgba(0, 10, 50, 0.6);
}
.wh-result__badge span + span { font-size: 13px; line-height: 16px; letter-spacing: 0.06em; }
.wh-result__title {
  margin: 0;
  max-width: 272px;
  font: 700 20px/24px 'Inter', sans-serif;
  color: #fff;
  text-align: center;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.wh-result__message {
  margin: 0;
  max-width: 272px;
  font: 400 14px/20px 'Inter', sans-serif;
  color: #c4c4c4;
  text-align: center;
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 3;
  line-clamp: 3;
  overflow: hidden;
}
/* Title -> message: 4px box gap (column gap 8 - 4; design lead 2026-10-16: was 8px + 28px line). */
.wh-result__title + .wh-result__message { margin-top: -4px; }
.wh-result__icon.is-entering,
.wh-result__badge.is-entering {
  transform-origin: 50% 50%;
  animation:
    wh-art-scale 400ms cubic-bezier(0.22, 1, 0.36, 1) both,
    wh-art-fade 150ms linear both;
}
@keyframes wh-art-scale { from { transform: scale(0); } to { transform: scale(1); } }
@keyframes wh-art-fade { from { opacity: 0; } to { opacity: 1; } }

/* Sunburst behind the win art: the shared .sm-sunburst (styles/modal.css). */

@media (prefers-reduced-motion: reduce) {
  .wh-sunburst,
  .sm-cta.wh-cta--pulse,
  .wh-result__icon.is-entering,
  .wh-result__badge.is-entering,
  .wh-lights .wh-bulb { animation: none; }
}
