/* ==========================================================================
   VICE ROULETTE — styles
   Single-theme by design: a neon night in Leonida. Every colour is explicit.
   ========================================================================== */

:root {
  /* palette — lifted from the artwork */
  --ink: #0B0413;
  --ink-2: #160A24;
  --ink-3: #221238;
  --violet: #4A1C6E;
  --magenta: #FF2E9A;
  --sunset: #FF6A3D;
  --gold: #FFC857;
  --surf: #35E4D6;
  --paper: #FFF3F8;
  --muted: rgba(255, 243, 248, 0.64);
  --faint: rgba(255, 243, 248, 0.34);
  --line: rgba(255, 243, 248, 0.14);

  /* category hues — alternating warm / cool around the dial */
  --c-florida: #FF2E9A;
  --c-chaos: #FF5A3D;
  --c-roleplay: #35E4D6;
  --c-hustle: #FFB53D;
  --c-cops: #4C82FF;
  --c-viral: #F5E663;
  --c-wheels: #B04CFF;
  --c-wildlife: #4CE08A;

  /* type */
  --font-neon: 'Monoton', 'Bebas Neue', Impact, sans-serif;
  --font-head: 'Bebas Neue', 'Oswald', Impact, 'Arial Narrow', sans-serif;
  --font-body: 'Rubik', 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;

  /* motion */
  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
  --ease-slam: cubic-bezier(0.34, 1.56, 0.64, 1);

  /* the composition keeps the share card's proportions; the artwork still bleeds full-width */
  --frame: min(96vw, 2000px, 210vh);

  /* Ad slots. The rails flank the app column, the leaderboard takes its own row.
     Both feed the wheel sizing below, and both drop to 0 at the breakpoints that
     hide them, so the wheel takes the space straight back. */
  --ad-rail-w: 160px;
  --ad-rail-h: 600px;
  --ad-rail-pad: 12px;
  --ad-bottom-h: 90px;
  --ad-gap: 10px;
  --ad-reserve: calc(var(--ad-bottom-h) + 2 * var(--ad-gap));

  --wheel: min(
    calc((100vw - 2 * (var(--ad-rail-w) + var(--ad-rail-pad))) * 0.5),
    calc(100dvh - 240px - 4vh - var(--ad-reserve)),
    820px
  );
  --accent: var(--magenta);
}

*, *::before, *::after { box-sizing: border-box; }

html, body { height: 100%; }

body {
  margin: 0;
  background: var(--ink);
  color: var(--paper);
  font-family: var(--font-body);
  font-size: 16px;
  line-height: 1.45;
  overflow: hidden;
  -webkit-font-smoothing: antialiased;
}

[hidden] { display: none !important; }
button { font: inherit; color: inherit; cursor: pointer; }
button:focus-visible, a:focus-visible, [tabindex]:focus-visible {
  outline: 2px solid var(--surf);
  outline-offset: 3px;
}

/* --------------------------------------------------------------------------
   Background — three layers make the tilt-shift and the rack focus.
   sharp   : the artwork
   tilt    : the pre-blurred artwork, masked so only sky + foreground show
   rack    : the pre-blurred artwork, unmasked, faded in during a spin
   -------------------------------------------------------------------------- */
.bg {
  position: fixed;
  inset: -3%;
  z-index: 0;
  pointer-events: none;
  overflow: hidden;
}
.bg__layer {
  position: absolute;
  inset: 0;
  background-size: cover;
  background-position: center 60%;
  will-change: transform;
  transform: translate3d(var(--px, 0px), var(--py, 0px), 0);
  transition: opacity 0.55s ease;
}
/* The background-image for .bg__sharp / .bg__tilt / .bg__rack is set in an inline
   <style> in index.html (paths resolve relative to the document, which is reliable
   across browsers — url() inside CSS custom properties is not). */
.bg__tilt {
  -webkit-mask-image: linear-gradient(
    to bottom,
    rgba(0,0,0,1) 0%, rgba(0,0,0,1) 18%, rgba(0,0,0,0) 38%,
    rgba(0,0,0,0) 64%, rgba(0,0,0,1) 86%, rgba(0,0,0,1) 100%
  );
  mask-image: linear-gradient(
    to bottom,
    rgba(0,0,0,1) 0%, rgba(0,0,0,1) 18%, rgba(0,0,0,0) 38%,
    rgba(0,0,0,0) 64%, rgba(0,0,0,1) 86%, rgba(0,0,0,1) 100%
  );
}
.bg__rack { opacity: 0; }
body.is-spinning .bg__rack { opacity: 1; transition-duration: 0.7s; }
body.is-landing .bg__rack { opacity: 0; transition-duration: 0.22s; }

.bg__vignette {
  position: absolute; inset: 0;
  background:
    radial-gradient(120% 90% at 50% 45%, rgba(11,4,19,0) 40%, rgba(11,4,19,0.55) 78%, rgba(11,4,19,0.9) 100%),
    linear-gradient(to bottom, rgba(11,4,19,0.55) 0%, rgba(11,4,19,0) 22%, rgba(11,4,19,0) 70%, rgba(11,4,19,0.7) 100%);
}
/* Left-to-right scrim: the hero column reads on near-solid ink while the
   artwork stays bright behind the dial. Turns vertical when the layout stacks. */
.bg__scrim {
  position: absolute; inset: 0;
  /* Stops are anchored to the centred frame, not the viewport, so the hero
     column keeps its near-solid ink however wide the screen gets. */
  background: linear-gradient(90deg,
    rgba(11,4,19,0.94) 0%,
    rgba(11,4,19,0.90) calc(50% - var(--frame) / 2 + 700px),
    rgba(11,4,19,0.34) calc(50% + var(--frame) / 2 - 230px),
    rgba(11,4,19,0.12) 100%);
}
/* The accent band along the bottom edge. Fixed, not absolute: .bg is inset by
   -3% for the parallax overscan, so its own bottom sits below the viewport. */
.bg__band {
  position: fixed; left: 0; right: 0; bottom: 0;
  height: 10px;
  background: linear-gradient(90deg, var(--magenta), var(--sunset));
}
.bg__grain {
  position: absolute; inset: 0;
  opacity: 0.09;
  mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='220' height='220'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* --------------------------------------------------------------------------
   App shell
   -------------------------------------------------------------------------- */
.shell {
  position: relative;
  z-index: 1;
  height: 100dvh;
  display: grid;
  grid-template-columns: auto minmax(0, 1fr) auto;
  grid-template-rows: minmax(0, 1fr) auto;
  grid-template-areas:
    "rail-left app rail-right"
    "ad-bottom ad-bottom ad-bottom";
}
.app {
  grid-area: app;
  position: relative;
  min-height: 0;
  display: grid;
  grid-template-rows: auto 1fr auto;
}

/* --------------------------------------------------------------------------
   Ad slots — placeholders. Swap the .ad__box contents for the network's tag.
   -------------------------------------------------------------------------- */
.ad {
  display: grid;
  place-items: center;
  min-width: 0;
  min-height: 0;
  transition: opacity 0.4s, filter 0.5s;
}
.ad--left,
.ad--right { width: calc(var(--ad-rail-w) + var(--ad-rail-pad)); padding-block: 12px; }
.ad--left { grid-area: rail-left; padding-left: var(--ad-rail-pad); }
.ad--right { grid-area: rail-right; padding-right: var(--ad-rail-pad); }
.ad--bottom { grid-area: ad-bottom; padding: var(--ad-gap) 12px var(--ad-gap); }

.ad__box {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 5px;
  background: rgba(11, 4, 19, 0.55);
  border: 1px dashed rgba(255, 255, 255, 0.16);
  border-radius: 6px;
  font-family: var(--font-head);
  text-transform: uppercase;
  color: var(--faint);
  text-align: center;
}
.ad--rail .ad__box { width: 100%; height: min(var(--ad-rail-h), 100%); }
.ad--bottom .ad__box { width: min(728px, 100%); height: var(--ad-bottom-h); }
.ad__word { font-size: 11px; letter-spacing: 0.26em; }
.ad__size { font-size: 12px; letter-spacing: 0.14em; color: var(--muted); }

/* Header — a sign strip */
.top {
  width: min(100%, var(--frame));
  margin-inline: auto;
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: start;
  gap: 16px;
  padding: 14px 22px 8px;
  transition: opacity 0.4s, filter 0.5s;
}
.cd { grid-column: 2; }
.top__right { grid-column: 3; justify-self: end; }
.logo {
  display: flex;
  flex-direction: column;
  line-height: 0.9;
  text-decoration: none;
  color: inherit;
}
.logo__vice {
  font-family: var(--font-neon);
  font-size: clamp(46px, min(6.4vw, 13vh), 152px);
  letter-spacing: 0.02em;
  color: var(--magenta);
  text-shadow:
    0 0 10px rgba(255,46,154,0.9),
    0 0 30px rgba(255,46,154,0.6),
    0 0 70px rgba(255,46,154,0.35);
  transform-origin: left center;
  /* neon-on only: the heartbeat now belongs to the hub alone, so nothing on the
     page competes with SPIN for the eye. @keyframes vice-beat is kept below in
     case the logo wants it back. */
  animation: neon-on 1.4s steps(1, end) 1;
}
.logo__roulette {
  /* Bowlby One SC, matching the wheel labels and the SPIN button. It sets wider
     again than Anton, so the tracking comes in to keep ROULETTE the same width
     under VICE as it has always been. */
  font-family: 'Bowlby One SC', var(--font-head);
  font-size: clamp(21px, min(3.03vw, 6.15vh), 72px);
  letter-spacing: 0.16em;
  padding-left: 0.1em;
  color: var(--paper);
  opacity: 0.92;
}
/* lub-dub: two thumps, then rest */
@keyframes vice-beat {
  0%, 100% {
    transform: scale(1);
    text-shadow: 0 0 10px rgba(255,46,154,0.9), 0 0 30px rgba(255,46,154,0.6), 0 0 70px rgba(255,46,154,0.35);
  }
  9% {
    transform: scale(1.045);
    text-shadow: 0 0 14px rgba(255,46,154,1), 0 0 44px rgba(255,46,154,0.85), 0 0 100px rgba(255,46,154,0.55);
  }
  18% {
    transform: scale(1);
    text-shadow: 0 0 10px rgba(255,46,154,0.9), 0 0 30px rgba(255,46,154,0.6), 0 0 70px rgba(255,46,154,0.35);
  }
  27% {
    transform: scale(1.026);
    text-shadow: 0 0 12px rgba(255,46,154,0.95), 0 0 36px rgba(255,46,154,0.72), 0 0 84px rgba(255,46,154,0.45);
  }
  40% {
    transform: scale(1);
    text-shadow: 0 0 10px rgba(255,46,154,0.9), 0 0 30px rgba(255,46,154,0.6), 0 0 70px rgba(255,46,154,0.35);
  }
}
@keyframes neon-on {
  0%   { opacity: 0.15; text-shadow: none; }
  12%  { opacity: 1; }
  18%  { opacity: 0.2; text-shadow: none; }
  26%  { opacity: 1; }
  32%  { opacity: 0.55; }
  40%  { opacity: 1; }
  100% { opacity: 1; }
}
.top__right { display: flex; align-items: center; gap: 8px; }

.chip-btn {
  display: inline-flex; align-items: center; gap: 8px;
  height: 38px; padding: 0 14px;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: rgba(11,4,19,0.55);
  color: var(--paper);
  font-family: var(--font-head);
  font-size: 17px;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  backdrop-filter: blur(6px);
  transition: border-color 0.2s, background 0.2s, transform 0.15s;
}
.chip-btn:hover { border-color: var(--magenta); background: rgba(74,28,110,0.45); }
.chip-btn:active { transform: translateY(1px); }
.chip-btn svg { width: 16px; height: 16px; stroke: currentColor; fill: none; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.chip-btn--icon { width: 38px; padding: 0; justify-content: center; }
.chip-btn[aria-pressed="true"] { border-color: var(--surf); color: var(--surf); }
.chip-btn .streak { color: var(--gold); }

/* Countdown — one tinted card per digit, centred in the header */
.cd { display: flex; flex-direction: column; align-items: center; gap: 6px; }
.cd__cap {
  font-family: var(--font-head);
  font-size: clamp(10px, 0.85vw, 14px);
  letter-spacing: 0.28em;
  text-transform: uppercase;
  color: var(--muted);
}
.cd__row { display: flex; align-items: flex-start; gap: clamp(4px, 0.5vw, 9px); }
.cd__unit { display: flex; flex-direction: column; align-items: center; gap: 5px; }
.cd__digits { display: flex; gap: 3px; }
.cd__d {
  min-width: clamp(22px, 2.3vw, 38px);
  padding: clamp(3px, 0.4vw, 7px) clamp(3px, 0.35vw, 6px) clamp(1px, 0.25vw, 4px);
  background: rgba(11, 4, 19, 0.62);
  border: 1px solid var(--line);
  border-radius: 6px;
  font-family: var(--font-head);
  font-size: clamp(20px, 2.2vw, 40px);
  line-height: 1;
  text-align: center;
  color: var(--paper);
  backdrop-filter: blur(4px);
}
.cd__label {
  font-family: var(--font-head);
  font-size: clamp(8.5px, 0.72vw, 11px);
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: var(--faint);
}
.cd__sep {
  font-family: var(--font-head);
  font-size: clamp(16px, 1.5vw, 26px);
  line-height: 1;
  color: var(--faint);
  padding-top: clamp(3px, 0.4vw, 7px);
}
.cd--live .cd__cap { color: var(--gold); }
.cd--live .cd__d { border-color: rgba(255, 200, 87, 0.45); color: var(--gold); }
.cd--live .cd__sep { color: rgba(255, 200, 87, 0.5); }

/* --------------------------------------------------------------------------
   Stage — the dial
   -------------------------------------------------------------------------- */
.stage {
  width: min(100%, var(--frame));
  margin-inline: auto;
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto;
  align-items: center;
  gap: clamp(24px, 4vw, 72px);
  padding: 6px clamp(18px, 5vw, 76px) 10px;
  min-height: 0;
}

/* Hero — the reading column, sized from the share card */
.hero {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: clamp(11px, 1.7vh, 24px);
  max-width: min(100%, calc(var(--frame) * 0.46));
  transition: opacity 0.4s, filter 0.5s;
}
/* Game switch — the first thing above the wordmark, because it decides
   everything below it: the pool, the wheel art and the hero copy. */
.game-switch {
  display: inline-flex;
  align-self: flex-start;
  padding: 3px;
  margin-bottom: clamp(4px, 1vh, 12px);
  border: 1px solid var(--line);
  border-radius: 999px;
  background: rgba(11, 4, 19, 0.6);
  backdrop-filter: blur(6px);
}
.game-switch__btn {
  padding: 6px clamp(14px, 1.6vw, 24px) 4px;
  border: 0;
  border-radius: 999px;
  background: none;
  color: var(--faint);
  font-family: var(--font-head);
  font-size: clamp(15px, 1.5vw, 21px);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  transition: color 0.2s, background 0.25s var(--ease-out), box-shadow 0.25s;
}
.game-switch__btn:hover { color: var(--paper); }
.game-switch__btn[aria-pressed="true"] {
  background: linear-gradient(135deg, var(--magenta), var(--sunset));
  color: var(--paper);
  box-shadow: 0 0 18px rgba(255, 46, 154, 0.45);
}

.hero__eyebrow {
  margin: clamp(2px, 1.1vh, 14px) 0 0;
  font-family: var(--font-head);
  font-size: clamp(16px, min(1.8vw, 3.6vh), 40px);
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: var(--surf);
}
.hero__line {
  margin: 0;
  font-family: 'Anton', var(--font-body);
  font-weight: 400;
  font-size: clamp(20px, min(2.4vw, 4.9vh), 52px);
  line-height: 1.18;
  color: var(--paper);
  text-wrap: balance;
}
.hero__sub {
  margin: 0;
  font-size: clamp(13.5px, min(1.45vw, 3vh), 30px);
  line-height: 1.4;
  color: var(--muted);
}
/* While the dial is turning — and on through the card that lands after it — the page
   furniture pulls back with the backdrop, so only the wheel and the card stay sharp.
   Both states are listed because land() drops .is-spinning and adds .card-open in the
   same frame; keying off the spin alone would snap the header back for that frame. */
body.is-spinning .top, body.card-open .top,
body.is-spinning .hero, body.card-open .hero,
body.is-spinning .foot, body.card-open .foot,
body.is-spinning .stage__hint, body.card-open .stage__hint,
body.is-spinning .stage__stats, body.card-open .stage__stats,
body.is-spinning .ad, body.card-open .ad {
  opacity: 0.25;
  filter: blur(2px);
}

.stage__dial {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: clamp(6px, 1.1vh, 14px);
}
.stage__hint {
  margin: 0;
  font-family: var(--font-head);
  font-size: 18px;
  letter-spacing: 0.22em;
  color: var(--muted);
  text-align: center;
  transition: opacity 0.3s;
}
.stage__hint kbd {
  font: inherit;
  border: 1px solid var(--line);
  border-bottom-width: 2px;
  border-radius: 4px;
  padding: 1px 7px 0;
  color: var(--paper);
}
.stage__stats {
  font-family: var(--font-head);
  font-size: 16px;
  letter-spacing: 0.1em;
  color: var(--paper);
  opacity: 0.85;
  text-align: center;
  text-wrap: balance;
  transition: opacity 0.4s, filter 0.5s;
}
.stage__stats em { font-style: normal; color: var(--gold); }

.dial {
  position: relative;
  width: var(--wheel);
  height: var(--wheel);
  transition: transform 0.6s var(--ease-out), opacity 0.4s, filter 0.5s;
}
body.card-open .dial { transform: scale(0.82) translateY(10px); opacity: 0.35; filter: blur(2px); }

.dial__svg { width: 100%; height: 100%; overflow: visible; display: block; }
/* NB: the rotor is rotated via the SVG attribute rotate(a cx cy). Do not add a CSS
   transform-origin here — Chromium applies both and the dial orbits off-centre. */

.seg { transition: opacity 0.3s; }
.seg__art { transition: filter 0.3s; }
/* the artwork carries the segment; the scrim is its own colour, dialled right down,
   so white labels stay legible over the busy neon and the category still reads. */
.seg__scrim { fill-opacity: 0.14; transition: fill-opacity 0.25s; }
/* A game whose wedge artwork has not been dropped in yet still gets a readable
   wheel: the scrim goes solid so the wedge reads as a painted colour block. */
.seg__art.is-bare .seg__scrim { fill-opacity: 0.85; }
.seg.is-hot .seg__art.is-bare .seg__scrim { fill-opacity: 1; }
.seg__edge { fill: none; stroke-width: 1.5; stroke-opacity: 0.55; }
.seg__label {
  font-family: 'Bowlby One SC', var(--font-head);
  font-size: 16px;
  letter-spacing: 0.01em;
  fill: var(--paper);
  paint-order: stroke fill;
  stroke: rgba(6, 2, 12, 0.82);
  stroke-width: 5px;
  stroke-linejoin: round;
  filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.65));
}
.seg__label--long { font-size: 13px; letter-spacing: 0; }
.seg.is-off { opacity: 0.3; }
.seg.is-off .seg__art { filter: grayscale(1) brightness(0.5); }
.seg.is-hot .seg__scrim { fill-opacity: 0.3; }
.seg.is-hot .seg__art { filter: brightness(1.18) saturate(1.15); }
.seg.is-hot .seg__edge { stroke-opacity: 1; stroke-width: 2.5; }

.dial__ring {
  fill: none;
  stroke: var(--magenta);
  stroke-width: 2;
  filter: url(#glow);
}
.dial__ring--outer { stroke: rgba(255,46,154,0.55); stroke-width: 1; filter: none; }
.dial__ticks { stroke: rgba(255,243,248,0.35); stroke-width: 1.5; }

/* the pointer — fixed, white-hot, sits at 12 o'clock */
.dial__pointer {
  position: absolute;
  top: -14px;
  left: 50%;
  width: 34px;
  height: 44px;
  transform: translateX(-50%);
  transform-origin: 50% 20%;
  filter: drop-shadow(0 0 6px rgba(255,46,154,0.9)) drop-shadow(0 0 16px rgba(255,46,154,0.5));
}
.dial__pointer svg { width: 100%; height: 100%; display: block; }
.dial__pointer.tick { animation: pointer-kick 90ms ease-out 1; }
@keyframes pointer-kick { 0% { transform: translateX(-50%) rotate(0); } 40% { transform: translateX(-50%) rotate(-14deg); } 100% { transform: translateX(-50%) rotate(0); } }

/* the hub — SPIN. The face is artwork (metal rim, neon ring, chrome SPIN), so the
   button carries no visible text: its name comes from aria-label. The background-image
   is set in the inline <style> in index.html, same as the backdrop layers. */
.hub {
  position: absolute;
  top: 50%; left: 50%;
  width: 31%; height: 31%;
  transform: translate(-50%, -50%);
  border: 0;
  border-radius: 50%;
  padding: 0 0 0.06em;
  display: grid;
  place-items: center;
  cursor: pointer;
  /* The bezel, the neon tube and the three bloom tiers are all sized from --wheel,
     so the ring reads the same on a 250px dial as on an 820px one. Fixed pixel
     radii wash out the whole wheel once the dial gets small. */
  --hub-bezel: max(3px, calc(var(--wheel) * 0.0115));
  --hub-tube: max(4.5px, calc(var(--wheel) * 0.0171));
  --glow-a: max(7px, calc(var(--wheel) * 0.023));
  --glow-b: max(18px, calc(var(--wheel) * 0.068));
  --glow-c: max(34px, calc(var(--wheel) * 0.16));
  /* luminous pink: bright at the top-left shoulder, deepening to the base */
  background:
    radial-gradient(circle at 32% 24%, rgba(255,255,255,0.30), rgba(255,255,255,0) 48%),
    linear-gradient(150deg, #FF63BE 0%, #FF2E9A 46%, #E30C79 100%);
  /* SPIN is set exactly like the wedge labels: same face, same dark outline
     carried under the fill, same drop shadow. */
  color: var(--paper);
  font-family: 'Bowlby One SC', var(--font-head);
  font-size: max(11px, calc(var(--wheel) * 0.066));
  letter-spacing: 0.01em;
  line-height: 1;
  text-indent: 0.01em;
  -webkit-text-stroke: 0.16em rgba(6, 2, 12, 0.82);
  paint-order: stroke fill;
  filter: drop-shadow(0 2px 4px rgba(0, 0, 0, 0.65));
  box-shadow:
    inset 0 -10px 26px rgba(150, 6, 78, 0.5),
    inset 0 3px 12px rgba(255, 255, 255, 0.26),
    0 0 0 var(--hub-bezel) rgba(11, 4, 19, 0.95),
    0 0 0 var(--hub-tube) rgba(255, 90, 190, 0.95),
    0 0 var(--glow-a) rgba(255, 46, 154, 0.9),
    0 0 var(--glow-b) rgba(255, 46, 154, 0.6),
    0 0 var(--glow-c) rgba(255, 46, 154, 0.35),
    0 14px 34px rgba(11, 4, 19, 0.65);
  transition: box-shadow 0.25s, filter 0.2s;
  /* same lub-dub cadence and period as the VICE logo, so the two beat together */
  animation: hub-beat 1.5s ease-in-out infinite;
}
.hub:hover { filter: drop-shadow(0 2px 4px rgba(0,0,0,0.65)) brightness(1.08) saturate(1.05); }
/* the press has to win over the animation, which would otherwise hold the scale */
.hub:active, .hub.is-down {
  animation: none;
  transform: translate(-50%, -50%) scale(0.94);
}
.hub:disabled {
  cursor: default;
  animation: none;
  /* dimmed enough to read as un-clickable, but still lit: the portal ring burns
     around it while the wheel turns and a heavy dim would smother SPIN inside it */
  filter: saturate(0.85) brightness(0.82);
}
@keyframes hub-beat {
  0%, 100% {
    transform: translate(-50%, -50%) scale(1);
    box-shadow:
      inset 0 -10px 26px rgba(150,6,78,0.5), inset 0 3px 12px rgba(255,255,255,0.26),
      0 0 0 var(--hub-bezel) rgba(11,4,19,0.95), 0 0 0 var(--hub-tube) rgba(255,90,190,0.95),
      0 0 var(--glow-a) rgba(255,46,154,0.9), 0 0 var(--glow-b) rgba(255,46,154,0.6),
      0 0 var(--glow-c) rgba(255,46,154,0.35), 0 14px 34px rgba(11,4,19,0.65);
  }
  9% {
    transform: translate(-50%, -50%) scale(1.055);
    box-shadow:
      inset 0 -10px 26px rgba(150,6,78,0.5), inset 0 3px 12px rgba(255,255,255,0.26),
      0 0 0 var(--hub-bezel) rgba(11,4,19,0.95), 0 0 0 calc(var(--hub-tube) * 1.12) rgba(255,140,215,1),
      0 0 calc(var(--glow-a) * 1.45) rgba(255,46,154,1), 0 0 calc(var(--glow-b) * 1.45) rgba(255,46,154,0.85),
      0 0 calc(var(--glow-c) * 1.45) rgba(255,46,154,0.55), 0 14px 34px rgba(11,4,19,0.65);
  }
  18% {
    transform: translate(-50%, -50%) scale(1);
    box-shadow:
      inset 0 -10px 26px rgba(150,6,78,0.5), inset 0 3px 12px rgba(255,255,255,0.26),
      0 0 0 var(--hub-bezel) rgba(11,4,19,0.95), 0 0 0 var(--hub-tube) rgba(255,90,190,0.95),
      0 0 var(--glow-a) rgba(255,46,154,0.9), 0 0 var(--glow-b) rgba(255,46,154,0.6),
      0 0 var(--glow-c) rgba(255,46,154,0.35), 0 14px 34px rgba(11,4,19,0.65);
  }
  27% {
    transform: translate(-50%, -50%) scale(1.03);
    box-shadow:
      inset 0 -10px 26px rgba(150,6,78,0.5), inset 0 3px 12px rgba(255,255,255,0.26),
      0 0 0 var(--hub-bezel) rgba(11,4,19,0.95), 0 0 0 var(--hub-tube) rgba(255,115,205,1),
      0 0 calc(var(--glow-a) * 1.22) rgba(255,46,154,0.95), 0 0 calc(var(--glow-b) * 1.22) rgba(255,46,154,0.72),
      0 0 calc(var(--glow-c) * 1.22) rgba(255,46,154,0.45), 0 14px 34px rgba(11,4,19,0.65);
  }
  40%, 100% {
    transform: translate(-50%, -50%) scale(1);
  }
}

/* --------------------------------------------------------------------------
   Footer — stats roast + disclaimer
   -------------------------------------------------------------------------- */
.foot {
  width: min(100%, var(--frame));
  margin-inline: auto;
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(auto, 76ch) minmax(0, 1fr);
  align-items: end;
  gap: 16px;
  padding: 8px 22px 14px;
  font-size: 12.5px;
  color: var(--muted);
  transition: opacity 0.4s, filter 0.5s;
}
.foot__legal { grid-column: 2; text-align: center; line-height: 1.35; color: var(--faint); text-wrap: balance; }
.foot__legal a { color: var(--muted); text-decoration: none; border-bottom: 1px solid var(--line); }
.foot__links { display: block; margin-top: 5px; font-size: 12px; letter-spacing: 0.06em; }
.foot__links a:hover { color: var(--paper); }
.foot__links span { padding: 0 7px; color: var(--line); border: 0; }

/* --------------------------------------------------------------------------
   The challenge card — a poster, not a glass panel
   -------------------------------------------------------------------------- */
.card-wrap {
  position: fixed;
  inset: 0;
  z-index: 20;
  display: grid;
  place-items: center;
  padding: 16px;
  pointer-events: none;
  visibility: hidden;
  transition: visibility 0s linear 0.3s;
}
.card-wrap.is-open {
  visibility: visible;
  transition-delay: 0s;
  /* the backdrop takes clicks only while the card is up, so a click outside can
     dismiss it. The tray (z 30) and share sheet (z 40) still sit above it. */
  pointer-events: auto;
}
.card {
  --accent: var(--magenta);
  position: relative;
  /* The poster scales with the viewport instead of sitting at one fixed width,
     so a big screen gets a big card. The floor keeps it readable on a laptop. */
  width: min(100%, clamp(600px, 56vw, 940px));
  max-height: min(90dvh, 900px);
  /* the legendary corner ribbon overhangs the right edge; clip it instead of
     letting it make the card scroll sideways */
  overflow-y: auto;
  overflow-x: hidden;
  padding: clamp(26px, 3vmin, 40px) clamp(30px, 3.4vmin, 48px) clamp(24px, 2.8vmin, 38px);
  background:
    linear-gradient(180deg, rgba(16,7,28,0.70), rgba(11,4,19,0.88) 58%, rgba(11,4,19,0.94)),
    var(--card-art, none) center / cover no-repeat,
    linear-gradient(180deg, rgba(22,10,36,0.975), rgba(11,4,19,0.985));
  color: var(--paper);
  border: 1px solid color-mix(in srgb, var(--accent) 70%, transparent);
  box-shadow:
    0 0 0 1px rgba(11,4,19,1),
    0 0 40px color-mix(in srgb, var(--accent) 35%, transparent),
    0 30px 80px rgba(0,0,0,0.6);
  clip-path: polygon(0 0, calc(100% - 22px) 0, 100% 22px, 100% 100%, 22px 100%, 0 calc(100% - 22px));
  pointer-events: auto;
  opacity: 0;
  transform: translateY(40px) scale(0.92);
  transition: opacity 0.25s, transform 0.25s;
}
.card-wrap.is-open .card {
  opacity: 1;
  transform: none;
  transition: opacity 0.3s, transform 0.55s var(--ease-slam);
}
.card::before {
  /* the accent bar along the top edge, clipped by the chamfer */
  content: "";
  position: absolute; top: 0; left: 0; right: 0; height: 4px;
  background: linear-gradient(90deg, var(--accent), transparent 80%);
}

.card__eyebrow {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  flex-wrap: wrap;
  margin-bottom: clamp(14px, 1.8vmin, 22px);
  padding-right: 52px; /* keeps the eyebrow clear of the close button */
}

/* Close — sits inside the chamfer, above the legendary ribbon */
.card__close {
  position: absolute;
  top: 12px; right: 12px;
  z-index: 4;
  width: 38px; height: 38px;
  display: grid; place-items: center;
  padding: 0;
  border: 1px solid var(--line);
  border-radius: 999px;
  background: rgba(11,4,19,0.82);
  color: var(--muted);
  transition: color 0.2s, border-color 0.2s, background 0.2s;
}
.card__close:hover { color: var(--paper); border-color: var(--accent); background: rgba(11,4,19,0.95); }
.card__close:active { transform: translateY(1px); }
.card__close svg {
  width: 17px; height: 17px;
  stroke: currentColor; fill: none; stroke-width: 2.2; stroke-linecap: round;
}
.tag {
  display: inline-flex; align-items: center; gap: 8px;
  font-family: var(--font-head);
  font-size: clamp(17px, 2vmin, 21px);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--accent);
}
.tag svg { width: 20px; height: 20px; stroke: currentColor; fill: none; stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round; }
.tag--players { color: var(--muted); }
.tag--daily { color: var(--gold); }

/* difficulty as wanted stars: 2 / 4 / 6 of six */
.stars { display: inline-flex; gap: 3px; align-items: center; }
.stars svg { width: clamp(15px, 1.8vmin, 19px); height: clamp(15px, 1.8vmin, 19px); }
.stars svg.on { fill: var(--accent); stroke: var(--accent); }
.stars svg.off { fill: none; stroke: var(--faint); stroke-width: 1.5; }
.stars__name { font-family: var(--font-head); font-size: clamp(16px, 1.9vmin, 20px); letter-spacing: 0.16em; color: var(--muted); margin-left: 6px; }

.card__title {
  font-family: var(--font-head);
  font-weight: 400;
  font-size: clamp(36px, 7.4vmin, 72px);
  line-height: 0.94;
  letter-spacing: 0.01em;
  margin: 0 0 clamp(14px, 1.8vmin, 20px);
  text-wrap: balance;
}
.card__text {
  font-size: clamp(17px, 2.6vmin, 23px);
  line-height: 1.5;
  max-width: 60ch;
  margin: 0 0 clamp(16px, 2vmin, 22px);
  color: var(--paper);
}
.card__fail {
  display: flex; gap: 10px; align-items: baseline;
  padding: clamp(10px, 1.3vmin, 15px) clamp(14px, 1.7vmin, 20px);
  margin: 4px 0 clamp(22px, 2.6vmin, 30px);
  border-left: 3px solid var(--accent);
  background: rgba(255,243,248,0.05);
  font-size: clamp(15px, 1.8vmin, 18px);
  color: var(--muted);
}
.card__fail b { font-family: var(--font-head); font-weight: 400; font-size: clamp(18px, 2.1vmin, 22px); letter-spacing: 0.16em; color: var(--accent); white-space: nowrap; }

.card__actions { display: flex; flex-wrap: wrap; gap: clamp(10px, 1.2vmin, 14px); align-items: center; }
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  height: clamp(48px, 5.6vmin, 60px); padding: 3px clamp(22px, 2.6vmin, 30px) 0;
  border: 1px solid transparent;
  border-radius: 6px;
  font-family: var(--font-head);
  font-size: clamp(22px, 2.6vmin, 27px);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  transition: transform 0.15s var(--ease-out), filter 0.2s, border-color 0.2s, background 0.2s, color 0.2s;
}
.btn:active { transform: translateY(1px) scale(0.98); }
.btn svg { width: clamp(18px, 2.1vmin, 22px); height: clamp(18px, 2.1vmin, 22px); stroke: currentColor; fill: none; stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round; margin-top: -3px; }
.btn--send {
  background: linear-gradient(135deg, var(--magenta), var(--sunset));
  color: var(--paper);
  box-shadow: 0 0 22px rgba(255,46,154,0.45);
}
.btn--send:hover { filter: brightness(1.1); }
.btn--ghost { background: transparent; border-color: var(--line); color: var(--muted); }
.btn--ghost:hover { border-color: var(--gold); color: var(--gold); }
.btn--icon { background: rgba(255,243,248,0.06); border-color: var(--line); color: var(--paper); }
.btn--icon:hover { border-color: var(--surf); color: var(--surf); }
.btn--text { height: auto; padding: 8px 6px; background: none; color: var(--muted); font-size: clamp(18px, 2.2vmin, 23px); margin-left: auto; }
.btn--text:hover { color: var(--paper); }

/* ACCEPTED stamp */
.card__stamp {
  position: absolute;
  right: clamp(26px, 3vmin, 40px); top: clamp(64px, 8vmin, 92px);
  padding: 6px 14px 2px;
  border: 3px solid var(--surf);
  border-radius: 6px;
  font-family: var(--font-head);
  font-size: clamp(34px, 4.4vmin, 46px);
  letter-spacing: 0.2em;
  color: var(--surf);
  transform: rotate(-12deg) scale(2.4);
  opacity: 0;
  pointer-events: none;
  mix-blend-mode: screen;
}
.card.is-accepted .card__stamp { animation: stamp-in 0.35s var(--ease-slam) forwards; }
@keyframes stamp-in { to { transform: rotate(-12deg) scale(1); opacity: 0.95; } }
.card.is-shaking { animation: card-shake 0.4s ease-in-out 1; }
@keyframes card-shake { 0%,100% { transform: translateX(0);} 20% { transform: translateX(-10px) rotate(-1deg);} 40% { transform: translateX(9px) rotate(1deg);} 60% { transform: translateX(-6px);} 80% { transform: translateX(5px);} }

/* Legendary — gold treatment */
.card.is-legendary {
  --accent: var(--gold);
  /* This rule replaces the whole background stack, so the category artwork has to
     be carried through here too or a legendary lands on a flat card. Order:
     gold sweep, scrim, artwork, base gradient. */
  background:
    linear-gradient(120deg, rgba(255,200,87,0) 30%, rgba(255,200,87,0.16) 50%, rgba(255,200,87,0) 70%) 0 0 / 200% 100%,
    linear-gradient(180deg, rgba(26,15,38,0.70), rgba(13,5,22,0.88) 58%, rgba(11,4,19,0.94)),
    var(--card-art, none) center / cover no-repeat,
    linear-gradient(180deg, rgba(28,16,40,0.97), rgba(11,4,19,0.98));
  animation: shimmer 2.8s linear infinite;
}
/* one position per layer, or the sweep resets the artwork's placement too */
@keyframes shimmer {
  from { background-position: 200% 0, 0 0, center, 0 0; }
  to   { background-position: -200% 0, 0 0, center, 0 0; }
}
/* The gold corner banner. The card clips its own overflow because it scrolls,
   so a band that hangs past the card's edge gets cut off mid-word. Instead the
   .ribbon is a square at the corner that does the clipping itself, and the band
   inside it is cut flush with the card's top and left edges. */
.ribbon {
  display: none;
  /* top-left: the close button owns the top-right corner */
  position: absolute; top: 0; left: 0;
  width: 150px; height: 150px;
  overflow: hidden;
  pointer-events: none;
  z-index: 3;
}
.ribbon span {
  position: absolute;
  top: 34px; left: -56px;
  width: 210px;
  padding: 5px 0 3px;
  transform: rotate(-45deg);
  background: var(--gold);
  color: var(--ink);
  font-family: var(--font-head);
  font-size: 15px;
  letter-spacing: 0.24em;
  text-align: center;
  box-shadow: 0 3px 12px rgba(11, 4, 19, 0.55);
}
.card.is-legendary .ribbon { display: block; }
.card.is-legendary .card__eyebrow { padding-left: 58px; }

/* --------------------------------------------------------------------------
   Tune the chaos — the filter tray
   -------------------------------------------------------------------------- */
.tray {
  position: fixed;
  top: 70px; right: calc(var(--ad-rail-w) + var(--ad-rail-pad) + 22px);
  z-index: 30;
  width: min(380px, calc(100vw - 32px));
  padding: 18px 18px 16px;
  background: rgba(16,8,28,0.96);
  border: 1px solid var(--line);
  border-radius: 8px;
  box-shadow: 0 24px 60px rgba(0,0,0,0.6);
  transform-origin: top right;
  opacity: 0; transform: scale(0.96) translateY(-6px);
  pointer-events: none;
  /* visibility is toggled with the fade so the closed tray leaves the tab order */
  visibility: hidden;
  transition: opacity 0.2s, transform 0.25s var(--ease-out), visibility 0s linear 0.25s;
}
.tray.is-open { opacity: 1; transform: none; pointer-events: auto; visibility: visible; transition-delay: 0s; }
.tray__head { display: flex; justify-content: space-between; align-items: baseline; margin-bottom: 12px; }
.tray h2 { font-family: var(--font-head); font-weight: 400; font-size: 24px; letter-spacing: 0.12em; margin: 0; }
.tray__sub { font-size: 12.5px; color: var(--muted); }
.tray__label { font-family: var(--font-head); font-size: 15px; letter-spacing: 0.2em; color: var(--muted); margin: 14px 0 8px; }
.tray__cats { display: grid; grid-template-columns: repeat(2, 1fr); gap: 6px; }

/* Recent dares — same popover shell as the tray, a list instead of controls */
.tray--recent { width: min(400px, calc(100vw - 32px)); }
.recent__list { display: grid; gap: 6px; }
.recent__item {
  display: grid;
  grid-template-columns: auto 1fr;
  align-items: baseline;
  gap: 4px 10px;
  width: 100%;
  padding: 9px 11px 8px;
  text-align: left;
  background: rgba(255,243,248,0.04);
  border: 1px solid var(--line);
  border-left: 3px solid var(--accent, var(--magenta));
  border-radius: 6px;
  color: var(--paper);
  cursor: pointer;
  transition: background 0.15s, border-color 0.15s;
}
.recent__item:hover { background: rgba(255,243,248,0.09); }
.recent__cat {
  grid-column: 1;
  font-family: var(--font-head);
  font-size: 12px;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--accent, var(--magenta));
}
.recent__title { grid-column: 2; font-size: 13.5px; line-height: 1.3; }
.recent__empty { font-size: 12.5px; color: var(--muted); padding: 4px 2px; }
.cat-toggle {
  --accent: var(--magenta);
  display: flex; align-items: center; gap: 8px;
  height: 36px; padding: 0 10px;
  border: 1px solid var(--line);
  border-radius: 6px;
  background: rgba(255,243,248,0.04);
  font-family: var(--font-head);
  font-size: 16px;
  letter-spacing: 0.14em;
  color: var(--paper);
  transition: background 0.2s, border-color 0.2s, opacity 0.2s;
}
.cat-toggle svg { width: 16px; height: 16px; stroke: var(--accent); fill: none; stroke-width: 2.2; stroke-linecap: round; stroke-linejoin: round; }
.cat-toggle[aria-pressed="true"] { border-color: color-mix(in srgb, var(--accent) 60%, transparent); background: color-mix(in srgb, var(--accent) 14%, transparent); }
.cat-toggle[aria-pressed="false"] { opacity: 0.45; }
.seg-ctl { display: flex; border: 1px solid var(--line); border-radius: 6px; overflow: hidden; }
.seg-ctl button {
  flex: 1; height: 36px; border: 0; background: transparent; color: var(--muted);
  font-family: var(--font-head); font-size: 16px; letter-spacing: 0.14em;
}
.seg-ctl button + button { border-left: 1px solid var(--line); }
.seg-ctl button[aria-pressed="true"] { background: rgba(255,46,154,0.22); color: var(--paper); }
.tray__count { margin-top: 12px; font-size: 12.5px; color: var(--muted); }
.tray__count b { color: var(--paper); font-weight: 500; }

/* --------------------------------------------------------------------------
   Share sheet
   -------------------------------------------------------------------------- */
.sheet-wrap {
  position: fixed; inset: 0; z-index: 40;
  display: grid; place-items: end center;
  background: rgba(11,4,19,0.6);
  opacity: 0; pointer-events: none;
  /* visibility is toggled with the fade so the closed sheet leaves the tab order */
  visibility: hidden;
  transition: opacity 0.2s, visibility 0s linear 0.3s;
}
.sheet-wrap.is-open { opacity: 1; pointer-events: auto; visibility: visible; transition-delay: 0s; }
.sheet {
  width: min(560px, 100%);
  padding: 18px 18px 22px;
  background: rgba(16,8,28,0.98);
  border: 1px solid var(--line);
  border-bottom: 0;
  border-radius: 12px 12px 0 0;
  transform: translateY(30px);
  transition: transform 0.3s var(--ease-out);
}
.sheet-wrap.is-open .sheet { transform: none; }
.sheet__head { display: flex; justify-content: space-between; align-items: center; margin-bottom: 12px; }
.sheet h2 { font-family: var(--font-head); font-weight: 400; font-size: 24px; letter-spacing: 0.12em; margin: 0; }
.sheet__preview { width: 100%; aspect-ratio: 1 / 1; max-height: 42vh; object-fit: contain; display: block; margin: 0 auto 14px; border-radius: 6px; background: var(--ink-2); }
.sheet__actions { display: grid; grid-template-columns: repeat(3, 1fr); gap: 8px; }
.sheet__actions .btn { height: 44px; font-size: 18px; padding-inline: 10px; }
.sheet__link { margin-top: 12px; display: flex; gap: 8px; align-items: center; }
.sheet__link input {
  flex: 1; height: 38px; padding: 0 12px;
  border: 1px solid var(--line); border-radius: 6px;
  background: rgba(255,243,248,0.05); color: var(--paper);
  font: 500 14px var(--font-body); letter-spacing: 0.02em;
}

/* --------------------------------------------------------------------------
   Toast
   -------------------------------------------------------------------------- */
.toast {
  position: fixed; left: 50%; bottom: calc(var(--ad-reserve) + 76px); z-index: 50;
  transform: translate(-50%, 12px);
  padding: 10px 18px 8px;
  background: rgba(16,8,28,0.96);
  border: 1px solid var(--line);
  border-left: 3px solid var(--gold);
  border-radius: 6px;
  font-family: var(--font-head);
  font-size: 19px;
  letter-spacing: 0.1em;
  color: var(--paper);
  opacity: 0; pointer-events: none;
  transition: opacity 0.2s, transform 0.25s var(--ease-out);
}
.toast.is-on { opacity: 1; transform: translate(-50%, 0); }

/* the portal ring burns over the wheel but under the card that lands on top of it */
.portal {
  position: fixed;
  inset: 0;
  /* a canvas is a replaced element: inset alone leaves it at its intrinsic
     (device-pixel) size, so it must be told to fill the viewport explicitly */
  width: 100%;
  height: 100%;
  z-index: 15;
  pointer-events: none;
}

/* confetti canvas */
.confetti { position: fixed; inset: 0; z-index: 25; pointer-events: none; }

/* --------------------------------------------------------------------------
   Small screens
   -------------------------------------------------------------------------- */
/* Below the two-column threshold the hero stacks above the dial and the
   left-to-right scrim becomes top-to-bottom. */
/* Rails need 320px of width and ~630px of height to be worth showing. Below either,
   retire them and zero the token so the wheel takes the space straight back. */
@media (max-width: 1280px) {
  :root { --ad-rail-w: 0px; }
  .ad--rail { display: none; }
}
@media (max-height: 640px) {
  .stage__hint { display: none; }
}

@media (max-height: 700px) {
  :root { --ad-rail-w: 0px; }
  .ad--rail { display: none; }
}
/* Phones get the 320x50 mobile banner instead of the leaderboard. */
@media (max-width: 640px) {
  :root { --ad-bottom-h: 50px; }
  .ad--bottom .ad__box { width: min(320px, 100%); }
  .ad__word { font-size: 10px; letter-spacing: 0.2em; }
  .ad__size { font-size: 11px; }
  /* the slot is a mobile banner here, so the placeholder should say so */
  .ad--bottom .ad__size { font-size: 0; }
  .ad--bottom .ad__size::after { content: "320 \00D7 50"; font-size: 11px; }
}

@media (max-width: 900px) {
  :root { --wheel: min(78vw, calc(46vh - var(--ad-reserve) - 30px), 400px); }
  .foot { grid-template-columns: minmax(0, 1fr); }
  .foot__legal { grid-column: 1; }
  .stage {
    grid-template-columns: 1fr;
    align-content: center;
    justify-items: center;
    gap: clamp(14px, 2.4vh, 30px);
    padding: 4px 20px 20px;
  }
  .hero {
    align-items: center;
    text-align: center;
    max-width: 36ch;
    gap: clamp(8px, 1.2vh, 16px);
  }
  .logo__vice { transform-origin: center; }
  .game-switch { align-self: center; }
  .bg__scrim {
    background: linear-gradient(180deg,
      rgba(11,4,19,0.9) 0%, rgba(11,4,19,0.6) 40%,
      rgba(11,4,19,0.4) 66%, rgba(11,4,19,0.86) 100%);
  }
}

@media (max-width: 640px) {
  :root { --wheel: min(80vw, calc(42vh - var(--ad-reserve) - 40px), 400px); }
  .top { padding: 12px 14px 6px; }
  .logo__vice { font-size: 40px; }
  .logo__roulette { font-size: 16px; letter-spacing: 0.16em; }
  .hero__eyebrow { font-size: 15px; letter-spacing: 0.2em; }
  .hero__line { font-size: 19px; }
  .hero__sub { font-size: 13px; }
  .game-switch__btn { font-size: 15px; padding: 5px 16px 3px; }
  .chip-btn { height: 36px; padding: 0 12px; font-size: 15px; }
  .chip-btn .chip-btn__text { display: none; }
  .top { grid-template-columns: 1fr auto; row-gap: 8px; }
  .top__right { grid-column: 2; grid-row: 1; }
  .cd { grid-column: 1 / -1; grid-row: 2; }
  .cd__cap { font-size: 10px; letter-spacing: 0.24em; }
  .cd__d { min-width: 24px; font-size: 22px; padding: 4px 4px 2px; border-radius: 5px; }
  .cd__label { font-size: 8.5px; letter-spacing: 0.14em; }
  .cd__sep { font-size: 17px; }
  .stage { padding-bottom: 18px; }
  .stage__hint { font-size: 15px; }
  .foot { gap: 4px; padding: 6px 14px 12px; }
  .foot__legal { max-width: none; }
  .card-wrap { place-items: end center; padding: 0; }
  .card {
    width: 100%; max-height: 88dvh;
    padding: 54px 18px 20px;
    clip-path: polygon(0 0, calc(100% - 18px) 0, 100% 18px, 100% 100%, 0 100%);
    border-bottom: 0;
  }
  .card__stamp { right: 16px; top: 54px; font-size: 26px; }
  /* the chip row cannot share a line with the close button at this width, so
     the button and the ribbon get their own band above it */
  .card__close { top: 8px; right: 8px; width: 32px; height: 32px; }
  .card__eyebrow { padding-right: 0; }
  .ribbon { width: 104px; height: 104px; }
  .ribbon span { top: 24px; left: -46px; width: 160px; padding: 3px 0 1px; font-size: 11px; letter-spacing: 0.16em; }
  .card.is-legendary .card__eyebrow { padding-left: 0; }
  .btn { height: 46px; font-size: 20px; padding-inline: 16px; flex: 1 1 auto; }
  .btn--text { flex: 1 1 100%; margin-left: 0; }
  .tray { top: auto; bottom: 0; right: 0; left: 0; width: 100%; border-radius: 12px 12px 0 0; transform-origin: bottom center; }
}
@media (max-height: 700px) and (max-width: 900px) {
  .hero__sub { display: none; }
}
@media (max-height: 560px) {
  :root { --wheel: min(calc(58vh - var(--ad-reserve) - 30px), 70vw, 420px); }
  .cd__cap { display: none; }
  .hero__sub { display: none; }
  /* landscape phones have almost no height to spare; claw some back. The
     leaderboard alone would eat a third of the viewport, so it goes too. */
  :root { --ad-bottom-h: 0px; --ad-gap: 0px; }
  .ad--bottom { display: none; }
  .top { padding: 8px 16px 4px; }
  .cd { gap: 3px; }
  .cd__unit { gap: 2px; }
  .cd__d { font-size: 20px; min-width: 22px; padding: 2px 3px 1px; }
  .cd__label { font-size: 8px; }
  .cd__sep { font-size: 14px; padding-top: 2px; }
  .foot { padding-bottom: 8px; }
  /* no physical keyboard on a landscape phone, and the hub says SPIN already */
  .stage__hint { display: none; }
}

/* The smallest landscape phones: the logotype and the dial are the whole page */
@media (max-height: 400px) {
  .hero__eyebrow { display: none; }
}

/* --------------------------------------------------------------------------
   Reduced motion — the spin becomes a cut, nothing floats
   -------------------------------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
  .logo__vice { animation: none; }
  .hub { animation: none; }
  .card, .card-wrap.is-open .card, .tray, .sheet, .toast { transition-duration: 0.01s; }
  .card.is-legendary { animation: none; }
  .bg__layer { transition: none; }
}
