/* ============================================================
   SLUSHY RIPS — shop styles.
   Brand values are measured from Slushy's own CSS (lead brief, 9 Nov):
   base #1F2123, page behind #121314, Slushy green #73FF00 for money and the
   primary action, pink #FF5380 -> magenta #E552C5 for brand moments, chips
   rgba(35,35,38,.5) with a 1px rgba(255,255,255,.28) ring.

   BRAND AUDIT, 9 Nov (measured off slushygames.net and slushy.com with
   getComputedStyle; see suspense.css for the reel): their UI type is never
   italic and never letter-spaced (every label, chip and button measured
   `letter-spacing: normal`); small labels are uppercase, but pill buttons are
   title case ("Login", "Sign up", "All bets", "Play Ski"); text is never a
   gradient (gradients are fills: the Play button, promo cards); "LIVE NOW" is
   flat #FF5380. So the tracking, the italics and the gradient text are gone
   below, and headings use their display faces (--display / --display-cond).

   LAYOUT: phone first (a column: top bar, page, rip dock, bottom nav). From
   1024px it is blockrips' desktop (without its strip): top bar + live ticker, left rail,
   stage, her card on the right — the grid at "DESKTOP" below.
   z-index scale: backdrop 0 · app 1 · fan slots 1–100 (own stacking context)
   · top 20 · rip overlay 100 · toast 200 · dialogs: top layer.
   ============================================================ */

@property --c-acc { syntax: '<color>'; inherits: true; initial-value: #FF5380; }
@property --c-acc2 { syntax: '<color>'; inherits: true; initial-value: #E552C5; }

:root {
  --bg: #1F2123;
  --bg-deep: #121314;
  --surface: #26282B;
  --surface-2: #2F3135;
  --text: #FFFFFF;
  --muted: rgba(255, 255, 255, .66);
  --faint: rgba(255, 255, 255, .42);
  --line: rgba(255, 255, 255, .10);
  --green: #73FF00;
  --green-rgb: 115, 255, 0;
  --pink: #FF5380;
  --magenta: #E552C5;
  --brand-grad: linear-gradient(135deg, var(--pink), var(--magenta));
  --chip-bg: rgba(35, 35, 38, .5);
  --chip-ring: rgba(255, 255, 255, .28);
  --c-acc: var(--pink);            /* the girl in focus, set per page / per centred pack */
  --c-acc2: var(--magenta);

  --radius: 18px;
  --pill: 999px;
  --ease-out: cubic-bezier(.2, .9, .25, 1);
  --ease-spring: cubic-bezier(.34, 1.4, .5, 1);
  --shadow-1: 0 1px 0 rgba(255, 255, 255, .04) inset, 0 10px 30px -12px rgba(0, 0, 0, .6);

  --font: 'acumin-pro-wide', 'Archivo', system-ui, -apple-system, 'Segoe UI', sans-serif;
  /* Slushy's two display faces, both in the Adobe kit lez7jmz (index.html), both
     loading on slushy-packs.vercel.app (checked 9 Nov). normalidad-ultraextended
     900 is how slushygames.net sets its big moments ("$75,000 GIVEAWAY", "TRENDING
     GAMES", "LIVE BETS"); rift 700 is slushy.com's age gate title. Uppercase,
     never italic, never tracked. */
  --display: 'normalidad-ultraextended', 'Archivo', system-ui, sans-serif;
  --display-cond: 'rift', 'Archivo', system-ui, sans-serif;

  /* hold.js ring vars (blockrips names) */
  --acc: var(--green);
  --acc-rgb: var(--green-rgb);
  --rip-skew: 0deg;
  --slant: none;
  --ring-out-w: 0px;
  --ring-out: transparent;

  color-scheme: dark;
  transition: --c-acc 600ms ease-out, --c-acc2 600ms ease-out;
}

*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; background: var(--bg-deep); }
html:has(dialog[open]), html.no-scroll { overflow: hidden; }
body {
  margin: 0; min-height: 100dvh; background: var(--bg-deep); color: var(--text);
  font-family: var(--font); font-stretch: 125%; font-size: 15px; line-height: 1.45;
  -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale;
  overflow: hidden;
}
img, video, canvas { display: block; max-width: 100%; }
button { font: inherit; color: inherit; cursor: pointer; -webkit-tap-highlight-color: transparent; touch-action: manipulation; }
button:disabled { cursor: not-allowed; }
a { color: inherit; -webkit-tap-highlight-color: transparent; }
h1, h2, h3, p, ul, dl, dd { margin: 0; }
ul { padding: 0; list-style: none; }
h1, h2 { text-wrap: balance; }
:focus-visible { outline: 2px solid var(--green); outline-offset: 3px; border-radius: 10px; }
.sr-only { position: absolute !important; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); clip-path: inset(50%); white-space: nowrap; border: 0; }
[hidden] { display: none !important; }
.tnum { font-variant-numeric: tabular-nums; }
.skip { position: fixed; z-index: 300; left: 12px; top: -60px; padding: 10px 16px; border-radius: var(--pill); background: #fff; color: #111; font-weight: 800; text-decoration: none; }
.skip:focus { top: 12px; }

/* ── page backdrop: Slushy dark, her colour, a halftone and a little grain ── */
.backdrop {
  position: fixed; inset: 0; z-index: 0; pointer-events: none;
  background:
    radial-gradient(70vmax 50vmax at 50% 46%, color-mix(in srgb, var(--c-acc) 18%, transparent), transparent 62%),
    radial-gradient(60vmax 50vmax at 0% 0%, rgba(255, 83, 128, .10), transparent 60%),
    radial-gradient(60vmax 50vmax at 100% 100%, rgba(229, 82, 197, .10), transparent 60%),
    var(--bg-deep);
}
.backdrop::before { /* halftone dots, strongest at the edges */
  content: ''; position: absolute; inset: 0; opacity: .5;
  background-image: radial-gradient(rgba(255, 255, 255, .09) 1px, transparent 1.6px);
  background-size: 14px 14px;
  -webkit-mask-image: radial-gradient(closest-side at 50% 46%, transparent 35%, #000 120%);
  mask-image: radial-gradient(closest-side at 50% 46%, transparent 35%, #000 120%);
}
.backdrop::after { /* grain */
  content: ''; position: absolute; inset: 0; opacity: .07; mix-blend-mode: overlay;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.9' numOctaves='2' stitchTiles='stitch'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* ============================================================
   THE SHELL — phone
   ============================================================ */
.app {
  position: relative; z-index: 1; height: 100dvh; min-height: 0;
  display: grid; grid-template-columns: minmax(0, 1fr);
  grid-template-rows: auto minmax(0, 1fr) auto auto;
  grid-template-areas: "top" "main" "cta" "bnav";
  padding-left: env(safe-area-inset-left); padding-right: env(safe-area-inset-right);
}
.rail, .side, .live, #sndTop { display: none; }

/* ── top bar ── */
.top {
  grid-area: top; position: relative; z-index: 20; display: flex; align-items: center; justify-content: space-between;
  gap: 12px; padding: calc(6px + env(safe-area-inset-top)) 12px 6px 16px; min-height: 58px;
  background: rgba(31, 33, 35, .82); backdrop-filter: blur(14px); -webkit-backdrop-filter: blur(14px);
  border-bottom: 1px solid var(--line);
}
/* TEMPORARY wordmark: swap this element's content for <img> when the logo lands */
.wordmark {
  font-family: var(--font); font-stretch: 125%; font-weight: 800; font-style: italic;
  font-size: 21px; line-height: 1; letter-spacing: -.02em; text-transform: lowercase;
  color: #fff; text-decoration: none; white-space: nowrap; padding: 10px 2px; min-height: 44px;
  display: inline-flex; align-items: center; flex: 0 0 auto;
}
.wordmark img { height: 26px; width: auto; }
.top__end { display: flex; align-items: center; gap: 8px; }
.bal { display: flex; align-items: center; gap: 6px; }
/* the USDC chip is a button (it opens the wallet sheet): 40px tall, its hit
   area grown to 44 by the ::after; Sign in is the brand pill beside nothing */
.bal__chip {
  position: relative; display: inline-flex; gap: 6px; height: 40px; padding: 0 14px 0 12px; align-items: center;
  border: 0; border-radius: var(--pill); background: var(--chip-bg); box-shadow: inset 0 0 0 1px var(--chip-ring);
  color: #fff; font: inherit; cursor: pointer;
  transition: background-color 150ms, transform 150ms var(--ease-out);
}
.bal__chip::after { content: ''; position: absolute; inset: -2px; }
.bal__chip:hover { background: rgba(255, 255, 255, .1); }
.bal__chip:active { transform: scale(.96); }
.bal__chip:focus-visible, .bal__in:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }
.bal__ico { color: var(--muted); flex: 0 0 auto; }
.bal__in { min-height: 40px; padding: 0 18px; font-size: 14px; cursor: pointer; }
.bal__amt { color: var(--green); font-weight: 800; font-size: 15px; font-variant-numeric: tabular-nums; }
.bal__tag { font-size: 10px; font-weight: 800; letter-spacing: 0; text-transform: uppercase; color: var(--muted); }
.bal__net { font-size: 9px; font-weight: 800; text-transform: uppercase; color: var(--pink); padding: 2px 6px; border-radius: var(--pill); box-shadow: inset 0 0 0 1px rgba(255, 83, 128, .5); }
@media (max-width: 380px) { .bal__ico { display: none; } .bal__chip { padding: 0 12px; } }
.bal__chip.is-bump .bal__amt { animation: balBump 420ms var(--ease-out); }
@keyframes balBump { 0% { color: #fff; transform: translateY(-2px); } 100% { color: var(--green); transform: none; } }

.iconbtn {
  width: 44px; height: 44px; flex: 0 0 auto; display: inline-grid; place-items: center; padding: 0; border: 0;
  border-radius: 50%; background: var(--chip-bg); box-shadow: inset 0 0 0 1px var(--chip-ring); color: #fff;
  transition: background-color 150ms, transform 150ms var(--ease-out), opacity 150ms;
}
.iconbtn:hover { background: rgba(255, 255, 255, .1); }
.iconbtn:active { transform: scale(.96); }
.iconbtn:disabled { opacity: .35; }

/* the sound toggle: one icon each way, crossfaded */
.sndbtn { position: relative; }
.sndbtn .snd-on, .sndbtn .snd-off { transition: opacity 200ms cubic-bezier(.2, 0, 0, 1), transform 200ms cubic-bezier(.2, 0, 0, 1), filter 200ms; }
.sndbtn[aria-pressed="true"] .snd-off, .sndbtn[aria-pressed="false"] .snd-on { opacity: 0; transform: scale(.25); filter: blur(4px); position: absolute; }
.sndbtn.iconbtn .snd-on, .sndbtn.iconbtn .snd-off { grid-area: 1 / 1; }
.chipbtn.sndbtn .snd-on, .chipbtn.sndbtn .snd-off { position: absolute; left: 15px; top: 50%; margin-top: -9px; }
.sndbtn[aria-pressed="false"] { color: var(--muted); }

/* ── the page ── */
.view { grid-area: main; min-height: 0; overflow-y: auto; overflow-x: hidden; outline: none; overscroll-behavior: contain; }
.loading { display: grid; place-items: center; min-height: 60vh; }
.spinner { width: 32px; height: 32px; border-radius: 50%; border: 3px solid rgba(255, 255, 255, .15);
  border-top-color: var(--pink); animation: spin 800ms linear infinite; }
@keyframes spin { to { transform: rotate(360deg); } }

.label { font-size: 11px; font-weight: 800; letter-spacing: 0; text-transform: uppercase; color: var(--muted); }
.tag18 {
  font-size: 10px; font-weight: 800; letter-spacing: 0; padding: 3px 8px; border-radius: var(--pill);
  background: var(--chip-bg); box-shadow: inset 0 0 0 1px var(--chip-ring); color: #fff; line-height: 1.2;
}
.avatar {
  --s: 76px; width: var(--s); height: var(--s); flex: 0 0 auto; border-radius: 50%; padding: 3px; display: block;
  background: var(--brand-grad); box-shadow: 0 6px 24px rgba(255, 83, 128, .35);
}
.avatar img { width: 100%; height: 100%; border-radius: 50%; object-fit: cover; border: 3px solid var(--bg); background: var(--surface); }
.avatar--sm { --s: 34px; padding: 2px; box-shadow: none; }
.avatar--sm img { border-width: 2px; }

/* ============================================================
   THE STAGE (home + her page)
   ============================================================ */
.stage { height: 100%; min-height: 0; display: flex; flex-direction: column; }

/* her row on the phone (desktop: her card is in the right column) */
.mhead { display: flex; align-items: center; gap: 12px; padding: 10px 12px 4px 16px; position: relative; z-index: 3; }
.mhead .avatar { --s: 50px; padding: 2px; box-shadow: 0 4px 16px rgba(255, 83, 128, .3); }
.mhead .avatar img { border-width: 2px; }
.mhead__txt { flex: 1; min-width: 0; }
.mhead__name { font-size: 18px; font-weight: 800; line-height: 1.15; text-transform: uppercase; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.mhead__sub { display: flex; align-items: center; gap: 8px; margin-top: 4px; color: var(--muted); font-size: 13px; }

/* the stage title: her name (or "Today's mix") in Slushy's display face,
   white, lit by her colour; the handle small beneath. Type only, no box. On her page on the
   phone her row (.mhead) already says it, so it is hidden there. */
.shead { position: relative; z-index: 3; padding: 12px 16px 0; text-align: center; }
[data-page="creator"] .shead { display: none; }
.shead__t {
  display: inline-block; max-width: 100%;
  font-family: var(--display); font-size: 18px; font-weight: 900; line-height: 1.1; letter-spacing: 0; text-transform: uppercase;
  overflow-wrap: anywhere; color: #fff; text-shadow: 0 4px 30px color-mix(in srgb, var(--c-acc) 60%, transparent);
}
.shead__sub { display: none; align-items: center; justify-content: center; gap: 8px; margin-top: 6px; font-size: 13px; color: var(--muted); }
.shead__dot { width: 3px; height: 3px; border-radius: 50%; background: var(--faint); }

/* ── the fan ── */
.fan {
  position: relative; flex: 1 1 auto; min-height: 0; overflow: visible; isolation: isolate; z-index: 1;
  touch-action: none; cursor: grab; -webkit-user-select: none; user-select: none;
}
.fan.is-drag { cursor: grabbing; }
.fan__glow { /* her colour, big and soft, behind the centre pack; it fades out
  inside its own box (closest-side), so the page's overflow edge never cuts it */
  position: absolute; inset: -12% 0; pointer-events: none; z-index: -1;
  background:
    radial-gradient(closest-side, color-mix(in srgb, var(--c-acc) 40%, transparent), color-mix(in srgb, var(--c-acc2) 14%, transparent) 55%, transparent 100%);
}
.fslot {
  position: absolute; top: 50%; left: 50%; width: 0; height: 0; padding: 0; border: 0; background: none;
  display: flex; align-items: center; justify-content: center; will-change: transform; outline: none; cursor: inherit;
}
.fpack { /* a 3D still of the pack (site/packstill.js): transparent round its
  silhouette, so no frame, no rounded corners and no rect effects on it */
  --pw: 170px; --sheen: 0;
  position: relative; display: block; flex: 0 0 auto; width: var(--pw); aspect-ratio: 569 / 1000;
  transform-origin: 50% 50%;
}
.fpack::before { /* skeleton shimmer, roughly the pack's body, until the still paints */
  content: ''; position: absolute; inset: 2.5% 1.5%; border-radius: calc(var(--pw) * .03);
  background:
    linear-gradient(100deg, transparent 30%, rgba(255, 255, 255, .14) 50%, transparent 70%) 0 0 / 250% 100%,
    linear-gradient(160deg, var(--surface-2), var(--surface));
  animation: shimmer 1.3s linear infinite;
}
.fpack.is-ready::before { display: none; }
@keyframes shimmer { from { background-position: 150% 0; } to { background-position: -100% 0; } }
.fpack__sh { /* the shadow under the pack, by opacity only (paint() fades it). blockrips
  does the same (stage.css .sl-shadow): a box behind the still rather than a
  filter: drop-shadow, which would re-rasterise every frame the fan moves */
  position: absolute; inset: 3% 4%; border-radius: calc(var(--pw) * .03); opacity: 0; pointer-events: none;
  box-shadow: 0 24px 34px -6px rgba(0, 0, 0, .7), 0 30px 70px -24px color-mix(in srgb, var(--c-acc) 70%, transparent);
}
.fpack__img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: contain; pointer-events: none;
  opacity: 0; transition: opacity 260ms; }
.fpack.is-ready .fpack__img { opacity: 1; }
.fpack__dim { /* the still again, blacked out once (static filter), so only its opacity moves */
  position: absolute; inset: 0; width: 100%; height: 100%; object-fit: contain; pointer-events: none;
  opacity: 0; filter: brightness(0); will-change: opacity; }
.fpack:not(.is-ready) .fpack__dim { visibility: hidden; }
.fpack__sheen { /* foil sheen that follows the mouse on the centre pack, masked to the still */
  position: absolute; inset: 0; pointer-events: none; mix-blend-mode: overlay;
  -webkit-mask: var(--still, none) center / contain no-repeat; mask: var(--still, none) center / contain no-repeat;
  opacity: calc(.9 * var(--sheen)); transition: opacity 240ms;
  background:
    radial-gradient(circle at var(--mx, 50%) var(--my, 50%), rgba(255, 255, 255, .55), transparent 45%),
    linear-gradient(115deg, transparent 20%, rgba(255, 255, 255, .28) calc(var(--mx, 50%) - 10%), rgba(115, 255, 0, .12) var(--mx, 50%), rgba(229, 82, 197, .22) calc(var(--mx, 50%) + 10%), transparent 80%);
}
.fslot:not(.is-hero) .fpack__sheen { opacity: 0; }
.fslot:focus-visible .fpack { outline: 2px solid var(--green); outline-offset: 6px; }
.fpack__img.is-bounce { animation: fanBounce 520ms cubic-bezier(.34, 1.2, .44, 1) both; }
@keyframes fanBounce { 0% { transform: scale(1); } 28% { transform: scale(1.06) translateY(-2%); } 55% { transform: scale(.975); } 78% { transform: scale(1.015); } 100% { transform: scale(1); } }

/* ── under the fan: name, arrows, what is in it, dots ── */
.fmeta { flex: 0 0 auto; display: flex; flex-direction: column; align-items: center; gap: 6px; padding: 4px 12px 6px; position: relative; z-index: 3; }
.fmeta__row { display: flex; align-items: center; justify-content: center; gap: 10px; width: 100%; }
.fmeta__title {
  min-width: 0; flex: 0 1 auto; display: flex; align-items: center; justify-content: center; gap: 10px;
  font-family: var(--display); font-size: 18px; font-weight: 900; line-height: 1.1; letter-spacing: 0; text-transform: uppercase; min-height: 40px;
}
.fmeta__name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.fmeta__price { color: var(--green); }
.fmeta__arrow { width: 40px; height: 40px; }
.fmeta__arrow::after { content: ''; position: absolute; inset: -4px; }
.fmeta__arrow { position: relative; }
.fmeta__sub { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; justify-content: center;
  font-size: 11px; font-weight: 800; letter-spacing: 0; text-transform: uppercase; color: var(--muted); min-height: 22px; }
.fmeta__odds { color: var(--faint); }
.dots { display: flex; justify-content: center; }
.dots button { width: 18px; height: 24px; padding: 0; border: 0; background: none; display: grid; place-items: center; border-radius: 6px; }
.dots button::before { content: ''; width: 6px; height: 6px; border-radius: 3px; background: rgba(255, 255, 255, .24); transition: width 240ms var(--ease-out), background-color 240ms; }
.dots button:hover::before { background: rgba(255, 255, 255, .5); }
.dots button[aria-current="true"] { width: 30px; }
.dots button[aria-current="true"]::before { width: 20px; background: var(--brand-grad); }

/* ============================================================
   THE RIP DOCK
   ============================================================ */
.cta { grid-area: cta; display: flex; flex-direction: column; align-items: stretch; gap: 14px;
  padding: 6px 16px 8px; position: relative; z-index: 5; }
.cta .hring { order: 1; }
.cta__more { order: 0; display: flex; justify-content: center; gap: 8px; }
.cta__hint { order: 2; min-height: 16px; text-align: center; font-size: 12px; color: var(--muted); }
.cta .cta__pulls { display: none; }
/* THE RIP BUTTON — blockrips' RIP PACK sticker (eval/style.css .stick / .rip,
   read 9 Nov; Luke: "make the button a bit cooler like this … without the
   Apple Pay"), in Slushy's colours: their CTA gradient (#FF5380 -> #E552C5,
   slushygames.net "Play" button) lit lighter at the top and deeper at the
   foot, a gloss across the top half, a thick #1F2123 rim (Slushy's base as
   the keyline), a cream outer ring and a hard drop under it. The type is
   Acumin Pro Wide 800, their UI face, set big and white with a keyline
   shadow. No skew (Slushy never slants), no pay marks. */
.cta__btn {
  --ring-out: #FFF6EA; --ring-out-w: 4px;
  position: relative; overflow: hidden; display: block; width: 100%; min-height: 58px; padding: 0 20px;
  border: 3.5px solid #1F2123; border-radius: var(--pill);
  background:
    linear-gradient(180deg, rgba(255, 255, 255, .16) 0%, transparent 46%, rgba(80, 0, 40, .22) 100%),
    linear-gradient(90deg, var(--pink), var(--magenta));
  color: #fff; font-size: 18px; line-height: 1; font-weight: 800; letter-spacing: 0; text-transform: uppercase;
  text-shadow: 0 2px 0 rgba(31, 33, 35, .55);
  box-shadow: 0 0 0 var(--ring-out-w) var(--ring-out), 0 6px 0 calc(var(--ring-out-w) - 1px) rgba(0, 0, 0, .38);
  transition: transform 140ms cubic-bezier(.22, .8, .36, 1), opacity 150ms, filter 150ms;
}
.cta__btn::before { /* the gloss: a soft white band across the top half */
  content: ''; position: absolute; left: 14px; right: 14px; top: 3px; height: 42%; pointer-events: none;
  border-radius: 999px 999px 40px 40px / 999px 999px 14px 14px;
  background: linear-gradient(180deg, rgba(255, 255, 255, .55), rgba(255, 255, 255, .14) 70%, transparent);
}
.cta__btn > * { position: relative; z-index: 1; }
.cta__btn:disabled {
  --ring-out: rgba(255, 255, 255, .22);
  background: var(--surface-2); color: var(--faint); text-shadow: none;
}
.cta__btn:disabled::before { display: none; }
.cta__btn:focus-visible { outline-offset: 3px; border-radius: var(--pill); }
/* the hold buttons: the keyboard ring IS the hold ring's own track (6px out,
   inside the 8–10px gap to its neighbours), so the focus ring and the progress
   ring are one shape and never stack */
.hring > .cta__btn:focus-visible { outline: none; }
.hring:has(> .cta__btn:focus-visible):not(.is-holding) .hring__ring { opacity: 1; }
.hring:has(> .cta__btn:focus-visible):not(.is-holding) .hring__track { stroke: #fff; }
.sheet__in:focus, .viewer__in:focus { outline: none; }
.cta__hint button { border: 0; background: none; padding: 13px 6px; margin: -13px 0; color: var(--green); font-weight: 800; text-decoration: underline; text-underline-offset: 3px; font-size: 12px; }

.chipbtn {
  position: relative; display: inline-flex; align-items: center; gap: 8px; min-height: 44px; padding: 0 16px; border: 0;
  border-radius: var(--pill); background: var(--chip-bg); box-shadow: inset 0 0 0 1px var(--chip-ring);
  font-size: 13px; font-weight: 800; letter-spacing: 0; text-transform: none; color: #fff; text-decoration: none; white-space: nowrap;
  transition: background-color 150ms, transform 150ms var(--ease-out), box-shadow 150ms;
}
.chipbtn:hover { background: rgba(255, 255, 255, .1); }
.chipbtn:active { transform: scale(.96); }
.chipbtn svg { flex: 0 0 auto; }
.chipbtn .count { color: var(--green); font-variant-numeric: tabular-nums; }
.chipbtn .count:empty { display: none; }
.chipbtn.sndbtn { padding-left: 42px; }
.chipbtn--brand { background: linear-gradient(90deg, var(--pink), var(--magenta)); box-shadow: none; justify-content: center; }   /* their Play button: flat, no glow */
.chipbtn--brand:hover { background: linear-gradient(90deg, var(--pink), var(--magenta)); filter: brightness(1.08); }

/* ── HOLD RING — ported from blockrips eval/style.css 1441–1500 (hold.js's
   own CSS), restyled to Slushy: green line, no skew, no sticker ring. The
   wrapper carries any transform; the traced path is measured off the
   button's offset box, so the button itself must stay untransformed. ── */
.hring { --hring-gap: 10px; --p: 0; --e: 0; --glow-rgb: 255, 83, 128; position: relative; display: block;
  transform: skewX(var(--rip-skew)) scale(calc(1 - .03 * var(--e))); }
.hring > .cta__btn { display: block; transform: none; margin-top: 0; width: 100%; }
.hring__btn { touch-action: none; -webkit-user-select: none; user-select: none; -webkit-touch-callout: none; position: relative; z-index: 1; }
/* AT REST this is exactly the sticker's own shadow (rings + drop); the
   pink glow is a HOLD state, drawn only by --e (blockrips' rule) */
.hring > .cta__btn {
  box-shadow: 0 0 0 var(--ring-out-w) var(--ring-out), 0 6px 0 calc(var(--ring-out-w) - 1px) rgba(0, 0, 0, .38),
              0 14px 40px -12px rgba(var(--glow-rgb), calc(.9 * var(--e))),
              0 0 calc(8px + 40px * var(--e)) rgba(var(--glow-rgb), calc(.5 * var(--e)));
}
@media (hover: hover) { .hring > .cta__btn:not(:disabled):hover { transform: translateY(-2px); } }
.hring > .cta__btn:not(:disabled):active { transform: translateY(2px); }
.hring > .cta__btn:disabled { box-shadow: 0 0 0 var(--ring-out-w) var(--ring-out); }
.hring__ring { position: absolute; left: calc(-1 * var(--hring-gap)); top: calc(-1 * var(--hring-gap));
  width: calc(100% + 2 * var(--hring-gap)); height: calc(100% + 2 * var(--hring-gap));
  overflow: visible; pointer-events: none; transform-origin: 50% 50%;
  opacity: 0; transition: opacity 140ms ease-out; z-index: 2; }
.hring.is-holding .hring__ring { opacity: 1; }
.hring__track { fill: none; stroke: rgba(255, 255, 255, .16); stroke-width: 2.5; }
.hring__line { fill: none; stroke: var(--acc); stroke-width: 2.5; stroke-linecap: round;
  filter: drop-shadow(0 0 6px rgba(var(--acc-rgb), .9)); }
.hring .hring__labels { display: grid; place-items: center; transform: var(--slant); }
.hring__labels .hring__label { grid-area: 1 / 1; white-space: nowrap; display: block; opacity: 0; transform: translateY(3px);
  transition: opacity 130ms ease-out, transform 130ms ease-out; }
.hring__labels .hring__label.is-on { opacity: 1; transform: none; }
.hring__labels .hring__label[data-l="hold"], .hring__labels .hring__label[data-l="tap"] { letter-spacing: 0; }
@keyframes hringBloom { 0% { transform: scale(1); opacity: 1; } 100% { transform: scale(1.12); opacity: 0; } }
@keyframes hringFlash { 0% { filter: brightness(1); } 26% { filter: brightness(1.3); } 100% { filter: brightness(1); } }
.hring.is-done .hring__ring { opacity: 1; animation: hringBloom 420ms ease-out forwards; }
.hring.is-done .hring__line { stroke: #FFF; filter: drop-shadow(0 0 14px rgba(var(--acc-rgb), .95)); }
.hring.is-done .hring__btn { animation: hringFlash 380ms ease-out; }

/* ── phone bottom nav ── */
.bnav {
  grid-area: bnav; display: grid; grid-template-columns: repeat(4, 1fr); position: relative; z-index: 10;
  padding: 4px 6px calc(4px + env(safe-area-inset-bottom));
  background: rgba(24, 25, 27, .92); backdrop-filter: blur(14px); -webkit-backdrop-filter: blur(14px);
  border-top: 1px solid var(--line);
}
.bnav__item {
  position: relative; display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 3px;
  min-height: 52px; padding: 4px 2px; border: 0; background: none; border-radius: 14px; color: var(--faint); text-decoration: none;
  font-size: 10px; font-weight: 800; letter-spacing: 0; text-transform: uppercase; transition: color 150ms;
}
.bnav__item:hover { color: var(--muted); }
.bnav__item[aria-current="page"] { color: #fff; }
.bnav__item[aria-current="page"]::before { content: ''; position: absolute; top: -5px; left: 50%; width: 24px; height: 3px; margin-left: -12px; border-radius: 0 0 3px 3px; background: var(--brand-grad); }
.bnav__item:active svg { transform: scale(.92); }
.bnav__item svg { transition: transform 150ms var(--ease-out); }
.bnav__badge { position: absolute; top: 4px; left: calc(50% + 6px); min-width: 18px; height: 18px; padding: 0 5px; border-radius: 9px;
  background: var(--pink); color: #fff; font-size: 10px; line-height: 18px; text-align: center; font-variant-numeric: tabular-nums; letter-spacing: 0; }

/* ============================================================
   MY GIRLS (rail list on desktop, sheet on the phone)
   ============================================================ */
.pins { display: flex; flex-direction: column; gap: 2px; }
.pin { position: relative; max-height: 64px; transition: opacity 160ms ease-out, transform 180ms var(--ease-out), max-height 180ms ease-out; }
.pin.is-leaving { opacity: 0; transform: translateX(-12px); max-height: 0; }
.pin__link {
  display: flex; align-items: center; gap: 10px; min-height: 48px; padding: 6px 38px 6px 8px; border-radius: 14px;
  text-decoration: none; color: rgba(255, 255, 255, .86); transition: background-color 150ms, color 150ms;
}
.pin__link:hover { background: rgba(255, 255, 255, .06); color: #fff; }
.pin__link[aria-current="page"] { background: rgba(255, 255, 255, .09); color: #fff; box-shadow: inset 3px 0 0 var(--pink); }
.pin__av { width: 34px; height: 34px; flex: 0 0 auto; border-radius: 50%; padding: 2px; background: var(--brand-grad); }
.pin__av img { width: 100%; height: 100%; border-radius: 50%; object-fit: cover; border: 2px solid var(--bg); }
.pin--visiting .pin__av { background: rgba(255, 255, 255, .3); }
.pin__txt { flex: 1; min-width: 0; display: flex; flex-direction: column; line-height: 1.2; }
.pin__name { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; font-size: 14px; font-weight: 700; }
.pin__tag { font-size: 9px; font-weight: 800; letter-spacing: 0; text-transform: uppercase; color: var(--faint); }
.pin__x {
  position: absolute; right: 6px; top: 50%; width: 32px; height: 32px; margin-top: -16px; padding: 0; border: 0; border-radius: 50%;
  display: grid; place-items: center; background: rgba(255, 255, 255, .1); color: #fff;
  opacity: 0; transform: scale(.7); transition: opacity 150ms ease-out, transform 150ms var(--ease-out), background-color 150ms;
}
.pin__x::after { content: ''; position: absolute; inset: -6px; }
.pin__x:hover { background: var(--pink); }
.pin__x:active { transform: scale(.96); }
.pin:hover .pin__x, .pin:focus-within .pin__x { opacity: 1; transform: none; }
@media (hover: none) { .pin__x { opacity: 1; transform: none; } }
.pins--sheet .pin__link { min-height: 56px; }
.pin--sugg .pin__link { padding-right: 8px; }   /* no X to make room for */
.sheet__sub { margin: 18px 0 6px; padding: 0 8px; font-size: 11px; font-weight: 800; letter-spacing: 0; text-transform: uppercase; color: var(--faint); }
.pins--sheet .pin__x { opacity: 1; transform: none; width: 40px; height: 40px; margin-top: -20px; }

/* ============================================================
   PROFILE CARD (her page's right column; the home's centred girl)
   ============================================================ */
.pcard {
  position: relative; overflow: hidden; border-radius: 24px; padding: 0 14px 14px; text-align: center;
  background: linear-gradient(180deg, rgba(38, 40, 43, .92), rgba(31, 33, 35, .96));
  box-shadow: inset 0 0 0 1px var(--line), 0 30px 60px -30px rgba(0, 0, 0, .8);
}
.pcard.is-swap { animation: cardSwap 260ms var(--ease-out); }
@keyframes cardSwap { from { opacity: .3; transform: translateY(6px); } }
.pcard__banner { display: block; height: 92px; margin: 0 -14px; position: relative; overflow: hidden; background: linear-gradient(135deg, var(--p1), var(--p2)); }
.pcard__banner img { width: 100%; height: 100%; object-fit: cover; object-position: center 30%; opacity: .85; }
.pcard__banner::after { content: ''; position: absolute; inset: 0; background: linear-gradient(180deg, transparent 30%, rgba(38, 40, 43, .95)); }
.pcard__av { --s: 84px; margin: -48px auto 0; position: relative; }
.pcard__kicker { margin-top: 8px; font-size: 10px; font-weight: 800; letter-spacing: 0; text-transform: uppercase; color: var(--faint); }
/* names are Acumin Black uppercase: Slushy's creator-name spec (feed card, 12px/900/uppercase), set larger.
   normalidad is too wide for a 16-letter handle in a 232px card */
.pcard__name { margin-top: 8px; font-size: 20px; font-weight: 800; line-height: 1.15; text-transform: uppercase; overflow-wrap: anywhere; }
.pcard__kicker + .pcard__name { margin-top: 2px; }
.pcard__sub { display: flex; align-items: center; justify-content: center; gap: 8px; margin-top: 6px; color: var(--muted); font-size: 13px; }
.pcard__pitch { margin-top: 10px; font-size: 13px; line-height: 1.4; color: rgba(255, 255, 255, .8); text-wrap: pretty; }
.pcard__pitch b { color: var(--pink); font-weight: 800; }
.pcard__stats { display: grid; grid-template-columns: 1fr 1fr; gap: 6px; margin-top: 12px; }
.pcard__stats > div { display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 2px; min-height: 50px; padding: 6px 4px; border-radius: 14px; background: rgba(255, 255, 255, .04); box-shadow: inset 0 0 0 1px var(--line); }
.pcard__stats dt { font-size: 9px; font-weight: 800; letter-spacing: 0; text-transform: uppercase; color: var(--faint); }
.pcard__stats dd { font-size: 15px; font-weight: 800; line-height: 1.2; white-space: nowrap; }
/* her profile photos (Skip in the sorter), three across */
.pcard__photos { display: grid; grid-template-columns: repeat(3, 1fr); gap: 6px; margin-top: 12px; }
.pcard__ph { padding: 0; border: 0; border-radius: 10px; overflow: hidden; aspect-ratio: 3 / 4; background: var(--surface); cursor: pointer; }
.pcard__ph img { width: 100%; height: 100%; object-fit: cover; display: block; transition: transform 200ms var(--ease-out); }
.pcard__ph:hover img { transform: scale(1.04); }
.pcard__ph:focus-visible { outline: 2px solid var(--green); outline-offset: 2px; }
@media (prefers-reduced-motion: reduce) { .pcard__ph img { transition: none; } }
.pcard__acts { margin-top: 12px; display: grid; }
.pcard__acts .chipbtn { width: 100%; }


/* ============================================================
   ALL GIRLS + 404
   ============================================================ */
.page { padding: 18px 16px 28px; }
.page-head { padding: 4px 0 16px; }
.page-head h1 { font-family: var(--display); font-size: 24px; font-weight: 900; line-height: 1.1; text-transform: uppercase; }
.page-head h1 em { font-style: normal; color: var(--pink); }
.page-head p { margin-top: 8px; color: var(--muted); max-width: 60ch; text-wrap: pretty; }
.nf-art { display: grid; place-items: center; width: 64px; height: 64px; border-radius: 50%; background: var(--surface); box-shadow: inset 0 0 0 1px var(--line); margin-bottom: 14px; }

.girls { display: grid; grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); gap: 10px; }
.gcard {
  position: relative; display: flex; flex-direction: column; align-items: center; height: 100%;
  padding: 0 10px 12px; border-radius: 22px; overflow: hidden; text-decoration: none; text-align: center;
  background: linear-gradient(180deg, rgba(38, 40, 43, .95), rgba(31, 33, 35, .98));
  box-shadow: inset 0 0 0 1px var(--line), 0 20px 40px -24px rgba(0, 0, 0, .8);
  transition: transform 220ms var(--ease-out), box-shadow 220ms;
  animation: cardIn 420ms var(--ease-out) both; animation-delay: calc(var(--i, 0) * 40ms);
}
@keyframes cardIn { from { opacity: 0; transform: translateY(10px); } }
.gcard:hover { transform: translateY(-3px); box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--p1) 70%, transparent), 0 26px 50px -24px color-mix(in srgb, var(--p1) 60%, transparent); }
.gcard:active { transform: scale(.98); }
.gcard:focus-visible { outline-offset: 3px; border-radius: 22px; }
.gcard__banner { display: block; width: calc(100% + 20px); height: 84px; margin: 0 -10px; position: relative; overflow: hidden; background: linear-gradient(135deg, var(--p1), var(--p2)); }
.gcard__banner img { width: 100%; height: 100%; object-fit: cover; object-position: center 30%; opacity: .85; transition: transform 400ms var(--ease-out); }
.gcard:hover .gcard__banner img { transform: scale(1.05); }
.gcard__banner::after { content: ''; position: absolute; inset: 0; background: linear-gradient(180deg, transparent 25%, rgba(38, 40, 43, .95)); }
.gcard__av { --s: 72px; margin-top: -40px; position: relative; }
.gcard__pin { position: absolute; right: -2px; bottom: -2px; z-index: 2; display: none; place-items: center; width: 24px; height: 24px;
  border-radius: 50%; background: var(--green); color: #0B0C0D; box-shadow: 0 0 0 3px var(--bg); }
.gcard.is-pinned .gcard__pin { display: grid; }
.gcard__her { display: none; }
.gcard__name { display: block; max-width: 100%; margin-top: 8px; font-size: 16px; font-weight: 800; line-height: 1.2; text-transform: uppercase; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.gcard__sub { display: flex; align-items: center; justify-content: center; gap: 6px; margin-top: 4px; color: var(--muted); font-size: 12px; max-width: 100%; }
.gcard__sub > span:first-child { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.gcard__stats { display: grid; grid-template-columns: repeat(3, 1fr); gap: 4px; width: 100%; margin-top: 10px; }
.gcard__stats > span { display: flex; flex-direction: column; align-items: center; gap: 1px; padding: 6px 2px; border-radius: 12px; background: rgba(255, 255, 255, .04);
  font-size: 8px; font-weight: 800; letter-spacing: 0; text-transform: uppercase; color: var(--faint); }
.gcard__stats b { font-size: 12px; letter-spacing: 0; color: #fff; white-space: nowrap; }
.gcard__foot { display: flex; width: 100%; margin-top: auto; padding-top: 10px; }
.gcard__rare { position: absolute; top: 10px; left: 10px; z-index: 2; }
.gcard__rare .tchip { height: 20px; padding: 0 8px; font-size: 9px; box-shadow: 0 4px 12px -4px rgba(0, 0, 0, .6); }
.gcard__go { display: inline-flex; align-items: center; justify-content: center; gap: 6px; width: 100%; min-height: 40px; border-radius: var(--pill);
  background: var(--chip-bg); box-shadow: inset 0 0 0 1px var(--chip-ring); font-size: 12px; font-weight: 800; letter-spacing: 0; text-transform: none; color: var(--green);
  transition: background-color 150ms, color 150ms; }
.gcard:hover .gcard__go { background: var(--green); color: #1F2123; box-shadow: none; }

/* ============================================================
   RIP OVERLAY
   ============================================================ */
.rip {
  position: fixed; inset: 0; z-index: 100; overflow: hidden; cursor: pointer; touch-action: none;
  background:
    radial-gradient(70% 55% at 50% 45%, color-mix(in srgb, var(--c-acc) 22%, transparent), transparent 70%),
    radial-gradient(90% 70% at 50% 110%, rgba(229, 82, 197, .18), transparent 70%),
    var(--bg-deep);
  animation: fadeIn 200ms ease-out;
}
/* THE FOOT. The bottom band of the overlay is kept for the end-of-pull actions
   (Save / Rip again) from the first frame, so the stage never has to move or
   re-frame when they appear. The canvas still covers the whole overlay, but
   rip.js FRAMES the pack and the content in the box above the band (its
   frameBottom: the #ripEnd box's height, which is this variable), so the halo
   and the falling wrapper carry on underneath instead of being cut off at a
   line. The sealed still sits in that same box. During the rip the band holds
   "Tap to skip" and the rarity reel. On a phone the content is width-bound,
   so the band costs it nothing. */
.rip { --rip-foot: calc(196px + env(safe-area-inset-bottom)); }
.rip__canvas { position: absolute; inset: 0; width: 100%; height: 100%; opacity: 0; transition: opacity 200ms; }
.rip.is-playing .rip__canvas { opacity: 1; }
.rip__sealed {
  /* a 3D still of the pack in rip.js's frame-0 pose (site/packstill.js), placed where rip.js's own
     frame 0 draws it, so the 3D fades in on top of it. MEASURED (9 Nov, the wrapper's projected
     silhouette at frame 0, 1440x900 / 1024x768 / 375x812): 80.6% of the binding dimension
     (rip.js FIT asks .84/.88 of the world box; the silhouette comes out smaller), centred 1.1% of
     its own width left of the middle. --a is the still's aspect, set on load.
     CENTRED BY LAYOUT, NOT BY A TRANSFORM (fix, 9 Nov): it used to sit at left/top 50% and pull
     itself back with transform: translate(-50%, -50%). transform-origin is the UNtransformed box's
     centre, which that left half a pack right of and below the drawn pack, so anything that
     scaled it (the reel's `scale`, the pulse) pivoted about the drawn pack's bottom-right quarter
     and slid it right and down: at scale .76 the pack moved 12% of its width right of centre
     (43px at 1440x900; Luke's "why isn't this central?"). Now the box itself is where the pack
     is drawn (inset 0 + auto margins; an image's height comes from its ratio), so the origin is
     the pack's own centre and every scale is about it. `right` carries the 1.1% offset: auto
     margins centre the box between left 0 and right .022w, i.e. .011w left of the middle. */
  --sw: min(80.6vw, (100dvh - var(--rip-foot)) * .806 * var(--a, .549));   /* the canvas's box: above the foot */
  position: absolute; inset: 0 calc(var(--sw) * .022) var(--rip-foot) 0; margin: auto; width: var(--sw); height: auto;
  /* no shadow: the 3D frame it hands over to has none */
  animation: sealedIn 420ms var(--ease-spring) both, sealedPulse 1.2s ease-in-out 420ms infinite;
  transition: opacity 180ms;
}
.rip__sealed:not([src]), .rip__sealed[src=""] { visibility: hidden; }
.rip.is-playing .rip__sealed { opacity: 0; animation: none; transform: none; }
@keyframes sealedIn { from { transform: translateY(12%) scale(.82); opacity: 0; } to { transform: none; opacity: 1; } }
@keyframes sealedPulse { 0%, 100% { transform: none; } 50% { transform: scale(1.015) rotate(-.4deg); } }
.rip__status { position: absolute; left: 0; right: 0; bottom: calc(86px + env(safe-area-inset-bottom)); text-align: center;
  font-size: 12px; font-weight: 800; letter-spacing: 0; text-transform: uppercase; color: var(--muted); }
.rip__skip {
  position: absolute; left: 50%; bottom: calc(22px + env(safe-area-inset-bottom)); transform: translateX(-50%);
  min-height: 44px; padding: 0 18px; border: 0; border-radius: var(--pill); background: var(--chip-bg);
  box-shadow: inset 0 0 0 1px var(--chip-ring); font-size: 12px; font-weight: 800; letter-spacing: 0; text-transform: none; color: var(--muted);
}
@keyframes fadeIn { from { opacity: 0; } }

/* ── the end of a pull: My pulls / Rip again under the content ──
   (it was "Save"; since payments every pull is already kept, Luke 11 Nov)
   My pulls is slushy.com's gate primary (a WHITE pill, #1F2123 type, title case,
   .age__yes); Rip again is the shop's own sticker CTA (.cta__btn in its hold
   ring), so spending looks and feels the same everywhere. Phone: stacked,
   Rip again at the bottom where the shop's HOLD TO RIP sits. Desktop: a row. */
.rip.is-end { cursor: default; }
.rip.is-end .rip__skip, .rip.is-end .rip__status { display: none; }
.rip__end {
  position: absolute; left: 0; right: 0; bottom: 0; z-index: 4; height: var(--rip-foot);
  display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 12px;
  padding: 0 16px calc(16px + env(safe-area-inset-bottom)); cursor: default;
  visibility: hidden; opacity: 0; transform: translateY(10px);
  transition: opacity 260ms var(--ease-out), transform 260ms var(--ease-out), visibility 0s linear 260ms;
}
.rip.is-end .rip__end { visibility: visible; opacity: 1; transform: none; transition-delay: 120ms, 120ms, 0s; }
.rip__note { margin: 0; min-height: 16px; text-align: center; font-size: 12px; font-weight: 800; line-height: 16px; color: var(--muted); }
.rip__note button { border: 0; background: none; padding: 13px 6px; margin: -13px 0; color: var(--green); font-weight: 800; text-decoration: underline; text-underline-offset: 3px; font-size: 12px; }
.rip__acts { display: flex; flex-direction: column; gap: 16px; width: min(420px, 100%); }
.rip__save {
  display: flex; align-items: center; justify-content: center; width: 100%; min-height: 48px; padding: 0 20px;
  border: 0; border-radius: var(--pill); background: #fff; color: #1F2123;
  font-size: 15px; font-weight: 800; letter-spacing: 0; text-transform: none; -webkit-tap-highlight-color: transparent;
  box-shadow: 0 12px 30px -16px rgba(255, 255, 255, .5);
  transition: background-color 160ms ease-out, transform 160ms var(--ease-out);
}
.rip__save:hover { background: #F1F1F1; }
.rip__save:active { transform: scale(.96); }
.rip__save:focus-visible { outline: 2px solid #fff; outline-offset: 3px; border-radius: var(--pill); }
.rip__x {
  position: absolute; z-index: 4; top: calc(14px + env(safe-area-inset-top)); right: 14px;
  visibility: hidden; opacity: 0; transition: opacity 200ms, visibility 0s linear 200ms;
}
.rip.is-end .rip__x { visibility: visible; opacity: 1; transition-delay: 120ms, 0s; }
/* the pull's <video>: its frames are drawn on the 3D card; the element only has
   to be IN the page and rendered, which is what lets iOS play a muted video
   from script (WebKit's policy: a video outside the DOM, display:none or
   visibility:hidden needs a gesture). 2px, all but transparent, untouchable. */
.rip__vid { position: absolute; left: 0; bottom: 0; width: 2px; height: 2px; opacity: .01; pointer-events: none; }

/* ── THE EXTRAS: the pack's other items, fanned out from BEHIND the hero ──
   (app.js THE HERO AND THE EXTRAS). The layer is the overlay's first child,
   so it paints under the 3D canvas — transparent off the card, so the cards
   are really behind the hero and its halo washes over them. On the end
   screen the canvas lets taps through to them; .rip__herohit (the hero's own
   rect, on top) keeps a tap on the hero from reaching a card under it.
   app.js sets each card's box, rotation and travel; this is the look: the
   hero's thin tier frame (rip.js drawFrame: a tier gradient ring with the
   card's rounded corner) at card size, a rarer card keeps a glow. */
.rip__xtras { position: absolute; inset: 0; z-index: 0; pointer-events: none; visibility: hidden; }
.rip__xtras.is-on { visibility: visible; }
.rip.is-end .rip__canvas, .rip.is-end .rip__sealed { pointer-events: none; }
.rip__herohit { position: absolute; pointer-events: auto; z-index: 1; }
/* the hero's scrub bar (app.js heroScrub): over the bottom of the main card,
   shown on hover (always on touch screens) */
.rip__scrub { position: absolute; z-index: 3; height: 32px; display: flex; align-items: center; padding: 0 12px;
  border-radius: 99px; background: rgba(12, 13, 14, .62); backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px);
  opacity: 0; pointer-events: none; transform: translateY(6px); transition: opacity .18s ease-out, transform .18s ease-out; }
.rip__scrub.is-on { opacity: 1; pointer-events: auto; transform: none; }
.rip__scrub input { width: 100%; margin: 0; height: 32px; accent-color: var(--c-acc, #FF5380); cursor: pointer; background: transparent; }
.rip__scrub input:focus-visible { outline: 2px solid #fff; outline-offset: 2px; border-radius: 99px; }
.rip:not(.is-end) .rip__scrub { display: none; }
/* the main card's mute button (app.js heroControls), its top-right corner */
.rip__mute { position: absolute; z-index: 3; width: 40px; height: 40px; border-radius: 50%; border: 0; padding: 0;
  display: grid; place-items: center; color: #fff; cursor: pointer;
  background: rgba(12, 13, 14, .62); backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px);
  transition: background .15s ease-out, transform .15s ease-out; }
.rip__mute::before { content: ''; position: absolute; inset: -4px; }          /* 48px to tap */
.rip__mute:hover { background: rgba(12, 13, 14, .82); }
.rip__mute:active { transform: scale(.94); }
.rip__mute:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }
.rip__mute svg { grid-area: 1 / 1; transition: opacity .18s, transform .18s; }
.rip__mute[aria-pressed="true"] .snd-off, .rip__mute[aria-pressed="false"] .snd-on { opacity: 0; transform: scale(.4); }
.rip__mute[hidden], .rip:not(.is-end) .rip__mute { display: none; }
/* a card swapped into the middle: no pointer cursor, it is the main card */
.xcard--hero { cursor: default; z-index: 1; }
@media (hover: hover) { .xcard--hero:hover { filter: none; } }
@media (prefers-reduced-motion: reduce) { .rip__scrub { transition: none; } }
/* the hero's tier glow once the fan is out (stands in for rip.js's halo, which
   is turned down then: see app.js buildExtras). Under the cards. */
.rip__heroglow { position: absolute; pointer-events: none; border-radius: 4%;
  background: color-mix(in srgb, var(--t1) calc(var(--ha, .2) * 60%), transparent);
  box-shadow: 0 0 60px 18px color-mix(in srgb, var(--t1) calc(var(--ha, .2) * 100%), transparent),
              0 0 150px 50px color-mix(in srgb, var(--t2) calc(var(--ha, .2) * 55%), transparent); }
.rip__heroglow.is-breathing { animation: heroBreathe 2.6s ease-in-out infinite; }
@keyframes heroBreathe { 50% { opacity: .78; } }
.xcard {
  --bw: 3px;
  position: absolute; display: block; padding: var(--bw); border: 0; margin: 0;
  border-radius: 3.6% / 2.6%;                         /* rip.js: 27px corner on a 750x1050 face */
  background: linear-gradient(135deg, var(--t1), var(--t2));
  box-shadow: 0 18px 34px -14px rgba(0, 0, 0, .8), 0 0 0 1px rgba(0, 0, 0, .35);
  pointer-events: auto; cursor: pointer; -webkit-tap-highlight-color: transparent;
  transform-origin: 50% 50%; will-change: transform;
  transition: box-shadow 400ms ease-out, filter 150ms;
}
.xcard__in { position: relative; display: block; width: 100%; height: 100%; overflow: hidden; border-radius: 2.8% / 2%;
  background: var(--surface); box-shadow: inset 0 0 0 1px rgba(0, 0, 0, .35); }
.xcard__in img, .xcard__in video { display: block; width: 100%; height: 100%; object-fit: cover; pointer-events: none; }
/* the landing burst of a rarer card (Epic and up): its tier colour, out past its edge */
.xcard__glow { position: absolute; inset: -16%; z-index: -1; border-radius: 22%; pointer-events: none; opacity: 0;
  background: radial-gradient(closest-side, color-mix(in srgb, var(--t1) 85%, transparent), color-mix(in srgb, var(--t2) 45%, transparent) 55%, transparent);
  filter: blur(6px); }
.xcard.is-landed {
  box-shadow: 0 18px 34px -14px rgba(0, 0, 0, .8), 0 0 0 1px rgba(0, 0, 0, .35),
              0 0 calc(30px * var(--g, 0)) calc(3px * var(--g, 0)) color-mix(in srgb, var(--t1) 60%, transparent);
}
@media (hover: hover) { .xcard:hover { filter: brightness(1.08); } }
.xcard:active { filter: brightness(.94); }
.xcard:focus-visible { outline: 2px solid #fff; outline-offset: 3px; }
@media (min-width: 1024px) {
  .rip { --rip-foot: 136px; }
  .rip__acts { flex-direction: row; align-items: center; justify-content: center; gap: 22px; width: auto; }
  .rip__save { width: auto; min-width: 168px; min-height: 58px; padding: 0 34px; font-size: 17px; }
  .rip__acts .hring { width: 360px; }
  .rip__x { top: 20px; right: 20px; }
}

/* ============================================================
   SHEETS (dialog) — bottom sheets on the phone, centred modals on desktop
   ============================================================ */
dialog { color: var(--text); border: 0; padding: 0; background: transparent; max-width: none; max-height: none; }
dialog::backdrop { background: rgba(8, 9, 10, .66); backdrop-filter: blur(4px); -webkit-backdrop-filter: blur(4px); }
.sheet {
  position: fixed; inset: auto 0 0 0; margin: 0 auto; width: 100%; max-width: 560px;
  max-height: min(88dvh, 860px); overflow: hidden;
}
.sheet--tall { max-height: 94dvh; }
.sheet[open] { animation: sheetUp 300ms var(--ease-out); }
.sheet[open]::backdrop { animation: fadeIn 220ms ease-out; }
@keyframes sheetUp { from { transform: translateY(100%); } }
.sheet__in {
  display: flex; flex-direction: column; max-height: inherit; background: var(--bg);
  border-radius: 24px 24px 0 0; box-shadow: 0 -1px 0 var(--line), 0 -20px 60px rgba(0, 0, 0, .5);
}
.sheet--tall .sheet__in { height: 94dvh; }
.sheet--tall:has(.empty) .sheet__in { height: auto; }   /* an empty list does not need a full-height sheet */
.sheet__head { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 14px 12px 10px 20px; position: relative; }
.sheet__head::before { content: ''; position: absolute; top: 6px; left: 50%; width: 36px; height: 4px; margin-left: -18px; border-radius: 2px; background: rgba(255, 255, 255, .2); }
.sheet__head h2 { font-family: var(--display); font-size: 13px; font-weight: 900; line-height: 1.25; text-transform: uppercase; flex: 1; min-width: 0; text-wrap: balance; }
.sheet__head .chipbtn { min-height: 40px; padding: 0 14px; }
.sheet__head .chipbtn--ico { width: 44px; min-height: 44px; padding: 0; justify-content: center; }
.chipbtn--ico .chipbtn__lbl { display: none; }
@media (min-width: 1024px) {
  .sheet__head .chipbtn--ico { width: auto; min-height: 40px; padding: 0 14px; }
  .chipbtn--ico .chipbtn__lbl { display: inline; }
}
.sheet__body { overflow-y: auto; overscroll-behavior: contain; padding: 4px 16px 20px; flex: 1; }
.sheet__foot { display: grid; gap: 8px; padding: 16px 16px calc(12px + env(safe-area-inset-bottom)); border-top: 1px solid var(--line); background: var(--bg); }
.ghost {
  display: flex; align-items: center; justify-content: center; min-height: 48px; padding: 0 18px; border: 0;
  border-radius: var(--pill); background: var(--chip-bg); box-shadow: inset 0 0 0 1px var(--chip-ring);
  font-size: 13px; font-weight: 800; letter-spacing: 0; text-transform: none; color: #fff; text-decoration: none;
}
.ghost:hover { background: rgba(255, 255, 255, .08); }

/* odds */
.seg { display: flex; gap: 6px; overflow-x: auto; scrollbar-width: none; margin: 0 -16px; padding: 2px 16px 12px; }
.seg::-webkit-scrollbar { display: none; }
.seg button {
  flex: 0 0 auto; min-height: 40px; min-width: 56px; padding: 0 14px; border: 0; border-radius: var(--pill);
  background: var(--chip-bg); box-shadow: inset 0 0 0 1px var(--chip-ring); font-weight: 800; font-size: 14px; font-variant-numeric: tabular-nums;
  transition: background-color 150ms, color 150ms;
}
.seg button:hover { background: rgba(255, 255, 255, .1); }
.seg button[aria-pressed="true"] { background: #fff; color: #1F2123; box-shadow: none; }   /* their white pill (OPT IN / Continue) */
/* the pack line: "$100 pack · 8 items [Legendary+ guaranteed]" */
.odds-intro { display: flex; flex-wrap: wrap; align-items: center; gap: 6px 10px; min-height: 26px; color: var(--muted); font-size: 15px; }
.odds-intro b { color: #fff; font-size: 17px; font-weight: 800; font-variant-numeric: tabular-nums; }
.odds-intro__dot { width: 4px; height: 4px; border-radius: 50%; background: var(--faint); }
.odds-cap { margin: 18px 0 6px; font-size: 12px; font-weight: 700; color: var(--faint); }
/* one row per tier: swatch + name, a bar on the true 0–100% scale, the number */
.olist { display: grid; gap: 4px; }
.orow {
  --w: 0; display: grid; grid-template-columns: 7.5em minmax(0, 1fr) 4.2em; align-items: center; gap: 14px;
  min-height: 48px; padding: 0 14px; border-radius: 14px; background: rgba(255, 255, 255, .035);
  transition: opacity 200ms ease-out;
}
.orow__name { display: flex; align-items: center; gap: 10px; font-size: 14px; font-weight: 800; white-space: nowrap; }
.swatch { width: 12px; height: 12px; flex: 0 0 auto; border-radius: 4px; background: linear-gradient(135deg, var(--t1), var(--t2)); box-shadow: 0 0 10px -2px var(--t1); }
.orow__bar { position: relative; height: 8px; border-radius: 4px; background: rgba(255, 255, 255, .07); overflow: hidden; }
.orow__bar i { position: absolute; inset: 0; border-radius: inherit; background: linear-gradient(90deg, var(--t2), var(--t1));
  transform-origin: 0 50%; transform: scaleX(var(--w)); transition: transform 420ms cubic-bezier(.16, 1, .3, 1); }
.orow__pct { text-align: right; font-size: 16px; font-weight: 800; font-variant-numeric: tabular-nums; color: #fff; }
.orow.is-zero { opacity: .38; }
.orow.is-zero .swatch { box-shadow: none; }
.odds-notes { margin-top: 18px; padding: 14px 16px; border-radius: 14px; background: var(--surface); color: var(--muted); font-size: 13px; line-height: 1.4; display: grid; gap: 6px; }
.odds-notes p { display: flex; gap: 10px; }
.odds-notes p::before { content: ''; flex: 0 0 auto; width: 5px; height: 5px; margin-top: .5em; border-radius: 50%; background: var(--pink); }

/* tiles */
.tchip {
  display: inline-flex; align-items: center; height: 22px; padding: 0 9px; border-radius: var(--pill);
  font-size: 10px; font-weight: 800; letter-spacing: 0; text-transform: uppercase; color: #111; font-style: normal;
  background: linear-gradient(135deg, var(--t1, #fff), var(--t2, #ccc)); white-space: nowrap;
}
.tile {
  position: relative; display: block; width: 100%; padding: 0; border: 2px solid var(--t1); border-radius: 14px; overflow: hidden;
  background: var(--surface); aspect-ratio: 3 / 4; box-shadow: 0 0 22px -8px var(--t1);
  transition: transform 180ms var(--ease-out), filter 150ms;
}
.tile img, .tile video { width: 100%; height: 100%; object-fit: cover; }
.tile .tchip { position: absolute; left: 6px; bottom: 6px; max-width: calc(100% - 12px); }
.grid .tile .tchip { height: 20px; padding: 0 7px; font-size: 9px; letter-spacing: 0; }
.tile .play { position: absolute; right: 6px; top: 6px; width: 28px; height: 28px; border-radius: 50%; display: grid; place-items: center;
  background: rgba(0, 0, 0, .55); box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .3); }
.tile .count { position: absolute; left: 6px; top: 6px; font-size: 11px; font-weight: 800; padding: 2px 7px; border-radius: var(--pill); background: rgba(0, 0, 0, .6); font-variant-numeric: tabular-nums; }
.tile__who { position: absolute; left: 0; right: 0; bottom: 0; padding: 18px 6px 30px; font-size: 10px; font-weight: 800; text-align: left; background: linear-gradient(transparent, rgba(0, 0, 0, .7)); overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.tile:hover { filter: brightness(1.06); }
.tile:active { transform: scale(.96); }
.tile--mythic { border-color: transparent; background: linear-gradient(var(--surface), var(--surface)) padding-box, var(--brand-grad) border-box; }
.grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 10px; margin-top: 12px; }
.flip { animation: flipIn 520ms var(--ease-out) both; animation-delay: calc(240ms + var(--i, 0) * 40ms); }
@keyframes flipIn { from { transform: perspective(700px) rotateY(-95deg) scale(.9); opacity: 0; } 60% { opacity: 1; } to { transform: none; opacity: 1; } }

.best { position: relative; }
.best__label { display: flex; align-items: center; justify-content: space-between; margin: 4px 0 10px; }
.best .tile { aspect-ratio: 4 / 5; width: min(100%, 38dvh); margin-inline: auto; border-width: 3px; box-shadow: 0 0 46px -10px var(--t1); }
.best .tile .tchip { left: 12px; bottom: 12px; height: 26px; font-size: 11px; }
.best__what { margin: 10px 0 0; text-align: center; color: var(--muted); font-size: 14px; }
.best__what b { color: #fff; }
.best .flip { animation-name: bestIn; animation-delay: 60ms; animation-duration: 560ms; }
@keyframes bestIn { from { transform: scale(.86) translateY(16px); opacity: 0; } to { transform: none; opacity: 1; } }

.empty { text-align: center; padding: 40px 16px 48px; color: var(--muted); text-wrap: balance; }
.empty__art { display: block; width: 64px; height: auto; margin: 0 auto 16px; transform: rotate(-6deg); filter: drop-shadow(0 10px 18px rgba(255, 83, 128, .35)); }
.empty b { display: block; color: #fff; font-size: 18px; margin-bottom: 6px; }
.pulls-meta { color: var(--muted); font-size: 13px; margin-bottom: 4px; }

/* ── viewer ── */
.viewer { position: fixed; inset: 0; width: 100%; height: 100%; margin: 0; }
.viewer::backdrop { background: rgba(5, 5, 6, .98); backdrop-filter: none; }
.viewer[open] { animation: fadeIn 180ms ease-out; }
.viewer__in { display: flex; flex-direction: column; height: 100%; max-width: 980px; margin: 0 auto;
  padding: env(safe-area-inset-top) env(safe-area-inset-right) env(safe-area-inset-bottom) env(safe-area-inset-left); }
.viewer__head { display: flex; align-items: center; justify-content: space-between; gap: 12px; padding: 10px 12px 10px 16px; }
.viewer__meta { display: flex; align-items: center; gap: 10px; min-width: 0; }
.viewer__meta h2 { font-size: 16px; font-weight: 800; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.viewer__media { flex: 1; min-height: 0; display: grid; place-items: center; padding: 0 12px 16px;
  grid-template: minmax(0, 1fr) / minmax(0, 1fr); }   /* a definite cell, so a tall video's max-height: 100% fits the screen */
.viewer__media img, .viewer__media video { max-width: 100%; max-height: 100%; border-radius: 14px; object-fit: contain; background: #000; outline: 1px solid oklch(1 0 0 / .1); outline-offset: -1px; }
/* a whole video plays in Google's player (api/open.js `full`) */
.viewer__frame { width: 100%; height: 100%; min-height: 60vh; border: 0; border-radius: 14px; background: #000; }
#viewerChip[hidden] { display: none; }

/* ── age gate ──
   The packs stay visible behind it, blurred and dimmed (the backdrop), with
   her colour glowing under the card. The card: the Slushy lockup with the
   mascot on its native #1F2123, then the question and two clearly separate
   answers. FOCUS: the card takes focus on open (autofocus, tabindex=-1), so
   nothing is ringed on load; a keyboard ring is 2px at a 3px offset = 5px,
   inside half of the 12px gap between the answers, so it never overlaps. */
.age {
  position: fixed; inset: 0; width: 100%; height: 100%; margin: 0; display: grid; place-items: center; overflow-y: auto;
  padding: max(20px, env(safe-area-inset-top)) 16px max(20px, env(safe-area-inset-bottom));
  background: radial-gradient(closest-side at 50% 46%, color-mix(in srgb, var(--c-acc) 26%, transparent), color-mix(in srgb, var(--c-acc2) 9%, transparent) 60%, transparent);
  background-size: min(760px, 160vw) min(760px, 130dvh); background-position: center; background-repeat: no-repeat;
}
.age:not([open]) { display: none; }
.age::backdrop { background: rgba(14, 15, 16, .56); backdrop-filter: blur(20px) saturate(1.3); -webkit-backdrop-filter: blur(20px) saturate(1.3); }
.age[open] { animation: fadeIn 240ms ease-out; }
.age[open]::backdrop { animation: fadeIn 240ms ease-out; }
.age[open] .age__in { animation: ageIn 460ms cubic-bezier(.16, 1, .3, 1) both; }
@keyframes ageIn { from { opacity: 0; transform: translateY(16px) scale(.96); } }

.age__in {
  position: relative; width: min(100%, 392px); border-radius: 22px; background: var(--bg); text-align: center; outline: none;   /* slushy.com's gate: #1F2123, radius 22 */
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .08), inset 0 1px 0 rgba(255, 255, 255, .06),
              0 2px 6px rgba(0, 0, 0, .3), 0 40px 90px -28px rgba(0, 0, 0, .9);
}
/* the lockup on its own lit patch of Slushy dark */
.age__art {
  position: relative; display: grid; place-items: center; padding: 40px 24px 14px; border-radius: 22px 22px 0 0; overflow: hidden;
}
.age__art::before { /* a soft pink-magenta light behind the mascot */
  content: ''; position: absolute; left: 50%; top: 54%; width: 360px; height: 150px; transform: translate(-50%, -50%); pointer-events: none;
  background: radial-gradient(closest-side, rgba(255, 83, 128, .30), rgba(229, 82, 197, .10) 55%, transparent 100%);
}
.age__art::after { /* halftone, as on the page backdrop, fading to nothing */
  content: ''; position: absolute; inset: 0; pointer-events: none; opacity: .7;
  background-image: radial-gradient(rgba(255, 255, 255, .12) 1px, transparent 1.6px); background-size: 12px 12px;
  -webkit-mask-image: radial-gradient(closest-side at 50% 55%, #000, transparent); mask-image: radial-gradient(closest-side at 50% 55%, #000, transparent);
}
.age__lockup { position: relative; z-index: 1; display: flex; align-items: center; gap: 16px; margin: 0; }
.age__words {
  display: flex; flex-direction: column; align-items: flex-start; padding-right: .1em;
  font-family: var(--font); font-stretch: 125%; font-weight: 800; font-style: italic; font-size: 46px; line-height: .84;
  letter-spacing: -.035em; text-transform: lowercase; color: #fff; white-space: nowrap; text-align: left;
}
.age__words span:last-child { margin-top: .02em; }
.age__blob { position: relative; display: block; flex: 0 0 auto; width: 74px; }
.age__mascot { width: 100%; height: auto; filter: drop-shadow(0 10px 14px rgba(0, 0, 0, .45)); transform: rotate(-6deg); }
.age__sticker { /* a sticker on the blob's head, cut out of the card colour */
  position: absolute; left: -14px; top: -6px; display: grid; place-items: center; height: 24px; padding: 0 8px 0 7px;
  border-radius: var(--pill); background: var(--brand-grad); box-shadow: 0 0 0 3px var(--bg), 0 6px 14px -4px rgba(255, 83, 128, .7);
  font-size: 12px; font-weight: 800; font-style: italic; letter-spacing: 0; line-height: 1; color: #fff; transform: rotate(-12deg);
}
.age__body { padding: 18px 28px 26px; }
/* slushy.com's own gate (measured 9 Nov): the title in rift, uppercase; the
   copy in Acumin Regular at 60% white; a WHITE pill with #1F2123 type in title
   case; "leave" as a plain underlined line, not a second button */
.age h2 { font-family: var(--display-cond); font-size: 32px; font-weight: 700; line-height: 1; text-transform: uppercase; }
.age__text { margin: 10px auto 0; max-width: 30ch; color: rgba(255, 255, 255, .6); font-size: 14px; font-weight: 400; line-height: 1.45; text-wrap: pretty; }
.age__acts { display: grid; gap: 6px; margin-top: 22px; }
.age__yes, .age__no {
  display: flex; align-items: center; justify-content: center; width: 100%; border: 0; border-radius: var(--pill);
  font-weight: 800; text-transform: none; text-decoration: none; -webkit-tap-highlight-color: transparent;
  transition: background-color 160ms ease-out, color 160ms ease-out, box-shadow 160ms ease-out, transform 160ms var(--ease-out);
}
.age__yes {
  min-height: 48px; padding: 0 20px; background: #fff; color: #1F2123; font-size: 14px; letter-spacing: 0;
  box-shadow: 0 12px 30px -16px rgba(255, 255, 255, .5);
}
.age__yes:hover { background: #F1F1F1; }
.age__no {
  min-height: 44px; padding: 0 18px; background: transparent; color: rgba(255, 255, 255, .6); font-size: 12px; font-weight: 400; letter-spacing: 0;
  text-decoration: underline; text-underline-offset: 3px;
}
.age__no:hover { color: #fff; }
.age__yes:active, .age__no:active { transform: scale(.96); }
.age__yes:focus-visible, .age__no:focus-visible { outline: 2px solid #fff; outline-offset: 3px; border-radius: var(--pill); }
.age__fine { margin-top: 14px; font-size: 12px; color: var(--faint); }
@media (max-width: 380px) {
  .age__words { font-size: 40px; }
  .age__blob { width: 64px; }
  .age__body { padding: 16px 20px 22px; }
}
@media (max-height: 620px) {
  .age__art { padding-top: 26px; }
  .age__fine { display: none; }
}

/* ── SIGN-UP (username, 18+, Terms): the age gate's card and buttons, with a
   form in it. Left-aligned fields, 16px input text (no iOS zoom on focus),
   44px+ rows for every tick, errors under the field they are about, in pink
   with an icon-free but worded message (never colour alone). ── */
.signup__in { text-align: left; }
.signup__body { padding: 26px 24px 22px; }
.signup h2 { text-align: center; }
.signup__text { text-align: center; margin-bottom: 18px; }
.signup__field { margin: 0 0 6px; }
.signup__label { display: block; margin: 0 0 6px; font-size: 13px; font-weight: 800; color: #fff; }
.signup__input {
  display: block; width: 100%; min-height: 48px; padding: 0 16px; border: 0; border-radius: 14px;
  background: var(--bg-deep); box-shadow: inset 0 0 0 1px var(--chip-ring); color: #fff;
  font: 600 16px/1.2 var(--font); font-stretch: 112%; letter-spacing: 0;
  transition: box-shadow 150ms ease-out;
}
.signup__input:focus { outline: none; box-shadow: inset 0 0 0 2px #fff; }
.signup__field.is-bad .signup__input { box-shadow: inset 0 0 0 2px var(--pink); }
.signup__help { margin: 6px 2px 0; font-size: 12px; line-height: 1.4; color: rgba(255, 255, 255, .6); }
.signup__msg { margin: 4px 2px 0; min-height: 18px; font-size: 13px; line-height: 1.4; font-weight: 700; color: #FF7FA0; }
.signup__msg:empty { min-height: 0; margin: 0; }
.signup__current { margin: 0 0 8px; text-align: center; font-size: 14px; color: var(--muted); }
.signup__current b { color: #fff; }
.signup__checks { display: grid; gap: 4px; margin: 10px 0 0; }
.signup__check {
  display: flex; align-items: center; gap: 12px; min-height: 48px; padding: 6px 12px; border-radius: 14px; cursor: pointer;
  font-size: 14px; line-height: 1.35; color: #fff; -webkit-tap-highlight-color: transparent;
  transition: background-color 150ms;
}
.signup__check:hover { background: rgba(255, 255, 255, .05); }
.signup__check input {
  flex: 0 0 auto; width: 22px; height: 22px; margin: 0; accent-color: var(--green); cursor: pointer;
}
.signup__check input:focus-visible { outline: 2px solid #fff; outline-offset: 3px; border-radius: 4px; }
.signup__check a { color: var(--green); font-weight: 800; text-underline-offset: 3px; padding: 6px 0; }
.signup__err { margin: 8px 2px 0; font-size: 13px; line-height: 1.4; font-weight: 700; color: #FF7FA0; text-align: center; }
.signup__err:empty { margin: 0; }
.signup .age__acts { margin-top: 16px; }
.signup__go:disabled { background: rgba(255, 255, 255, .14); color: rgba(255, 255, 255, .5); box-shadow: none; cursor: not-allowed; }
.signup__go:disabled:active { transform: none; }
@media (max-width: 380px) { .signup__body { padding: 22px 16px 18px; } }

/* the Terms / Privacy links: the rail's foot (desktop), the wallet sheet, the age gate */
.rail__legal { display: none; }
.fund__legal { display: flex; gap: 16px; margin: 18px 0 0; font-size: 12px; }
.fund__legal a, .rail__legal a, .age__fine a { color: var(--faint); text-underline-offset: 3px; }
.fund__legal a:hover, .rail__legal a:hover, .age__fine a:hover { color: #fff; }
.fund__legal a { display: inline-flex; align-items: center; min-height: 44px; }
.fund__user { margin: 0 0 6px; font-size: 14px; font-weight: 800; color: #fff; }
.bal__user { display: none; font-size: 13px; font-weight: 800; color: #fff; max-width: 16ch; overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }

/* ── toast ── */
.toast {
  position: fixed; z-index: 200; left: 50%; bottom: calc(196px + env(safe-area-inset-bottom)); transform: translate(-50%, 20px);
  display: flex; align-items: center; gap: 14px;
  max-width: min(92vw, 440px); padding: 12px 18px; border-radius: 14px; background: #fff; color: #1F2123; font-size: 14px; font-weight: 700;
  box-shadow: 0 10px 30px rgba(0, 0, 0, .4); opacity: 0; pointer-events: none; transition: opacity 200ms, transform 240ms var(--ease-out);
}
.toast.is-on { opacity: 1; transform: translate(-50%, 0); pointer-events: auto; }
.toast button { flex: 0 0 auto; min-height: 36px; margin: -8px -8px -8px 0; padding: 0 12px; border: 0; border-radius: var(--pill); background: #1F2123; color: var(--green);
  font-size: 12px; font-weight: 800; letter-spacing: 0; text-transform: uppercase; }
[data-page="girls"] .toast, [data-page="notfound"] .toast { bottom: calc(80px + env(safe-area-inset-bottom)); }
/* money and error lines: a pink edge and an icon (not colour alone) */
/* left:50% leaves a fixed box only half the screen to shrink-fit into: size it
   to its text instead, capped by max-width, so a long line wraps across the width */
.toast { width: max-content; }
.toast > span { flex: 1 1 auto; min-width: 0; }
.toast--warn { box-shadow: inset 4px 0 0 var(--pink), 0 10px 30px rgba(0, 0, 0, .4); padding-left: 16px; line-height: 1.35; }
.toast__ico { flex: 0 0 auto; color: #D61F55; }

/* ============================================================
   YOUR WALLET (the funding sheet) and the vault's small lines
   ============================================================ */
.fund { padding-top: 8px; }
.fund__bal { display: flex; align-items: baseline; gap: 8px; margin: 0; }
.fund__amt { font-family: var(--display); font-weight: 900; font-size: 34px; line-height: 1.05; color: var(--green); }
.fund__unit { font-size: 13px; font-weight: 800; color: var(--muted); text-transform: uppercase; }
.fund__h { margin: 22px 0 4px; font-family: var(--display); font-size: 12px; font-weight: 900; text-transform: uppercase; }
.fund__p { margin: 0 0 10px; font-size: 14px; color: var(--muted); }
.fund__addr { display: flex; align-items: center; gap: 8px; padding: 6px 6px 6px 14px; border-radius: 16px;
  background: var(--surface); box-shadow: inset 0 0 0 1px var(--line); }
.fund__addr code { flex: 1; min-width: 0; font: 600 13px/1.4 ui-monospace, SFMono-Regular, Menlo, monospace; color: #fff;
  overflow-wrap: anywhere; user-select: all; -webkit-user-select: all; }
.fund__addr .chipbtn { flex: 0 0 auto; min-width: 76px; justify-content: center; cursor: pointer; }
.fund__addr .chipbtn:disabled { opacity: .4; cursor: default; }
.fund__fine { margin: 8px 0 0; font-size: 12px; color: var(--faint); }
#fundNet { margin-top: 20px; padding-top: 16px; border-top: 1px solid var(--line); }
.fund__badge { display: inline-block; margin-right: 4px; padding: 1px 7px; border-radius: var(--pill); font-size: 10px; font-weight: 800;
  text-transform: uppercase; color: var(--pink); box-shadow: inset 0 0 0 1px rgba(255, 83, 128, .5); vertical-align: 1px; }
.fund__links { display: flex; flex-wrap: wrap; gap: 8px; }
.fund__links .chipbtn { flex: 1 1 140px; justify-content: center; }
.fund__foot { grid-template-columns: 1fr 1fr; }
.fund__foot .ghost { cursor: pointer; }
.fund__foot .ghost:disabled { opacity: .5; cursor: default; }
.fund__out { color: var(--muted); }
.ghost:focus-visible, .fund__links .chipbtn:focus-visible, .fund__addr .chipbtn:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }

/* a card picture that will not load (app.js MEDIA_HOSTS), or a card with
   nothing to show: a neutral block in the pull's colour, never a broken icon */
.is-broken { visibility: hidden; }
.has-broken, .nomedia {
  background: radial-gradient(120% 90% at 50% 30%, color-mix(in srgb, var(--t1, #AEB7C2) 30%, var(--surface)), var(--bg) 75%);
}
.nomedia { display: block; width: 100%; height: 100%; min-height: 120px; border-radius: inherit; }

/* the summary's "In My pulls" note (a note, not a button) */
.res__kept { display: inline-flex; align-items: center; gap: 5px; flex: 0 0 auto; margin-right: 4px;
  font-size: 12px; font-weight: 800; color: var(--green); white-space: nowrap; }
#resPulls { cursor: pointer; }
#resPulls:focus-visible { outline: 2px solid #fff; outline-offset: 2px; }

.pulls-pending { display: flex; align-items: center; gap: 10px; margin: 6px 0 12px; padding: 10px 12px; border-radius: 12px;
  background: var(--surface); font-size: 13px; color: var(--muted); }
.spinner--sm { width: 16px; height: 16px; border-width: 2px; flex: 0 0 auto; }
.empty .spinner { display: block; margin: 0 auto 14px; }
.empty__act { margin: 18px 0 0; }
.empty__act .chipbtn { cursor: pointer; }
.best__tx { color: var(--muted); text-decoration: underline; text-underline-offset: 3px; display: inline-flex; align-items: center; gap: 3px; }
.best__tx:hover { color: #fff; }

/* ============================================================
   DESKTOP — blockrips' layout, from 1024px
   ============================================================ */
@media (min-width: 1024px) {
  .app {
    --side: clamp(212px, 18vw, 290px);
    grid-template-columns: var(--side) minmax(0, 1fr) var(--side);
    grid-template-rows: 68px minmax(0, 1fr) auto;
    grid-template-areas:
      "top  top  top"
      "rail main side"
      "rail cta  side";
  }
  .app[data-page="girls"], .app[data-page="notfound"], .app[data-page="error"], .app[data-page="loading"] {
    grid-template-areas:
      "top  top  top"
      "rail main main"
      "rail main main";
  }
  [data-page="girls"] .side, [data-page="notfound"] .side, [data-page="error"] .side, [data-page="loading"] .side { display: none; }
  .bnav, .mhead { display: none; }

  /* the top bar + the live ticker */
  .top { gap: 20px; padding: 0 20px; min-height: 0; background: rgba(22, 23, 25, .72); }
  .wordmark { font-size: 25px; }
  .live { display: flex; align-items: center; gap: 14px; flex: 1 1 auto; min-width: 0; height: 100%; }
  /* LIVE PULLS: Slushy's "LIVE NOW" — flat #FF5380, no shimmer, no glow
     (measured on slushygames.net's feed card) — on one of their pills */
  .live__pill {
    flex: 0 0 auto; display: inline-flex; align-items: center; gap: 7px; height: 32px; padding: 0 14px 0 12px; border-radius: var(--pill);
    background: rgba(255, 255, 255, .1);
    color: var(--pink); font-size: 11px; line-height: 1; letter-spacing: 0; text-transform: uppercase; white-space: nowrap;
  }
  .live__pill b { font-weight: 800; }
  .live__sub { font-weight: 800; color: rgba(255, 255, 255, .6); }
  .live__dot { position: relative; display: grid; place-items: center; width: 8px; height: 8px; }
  .live__dot i { width: 8px; height: 8px; border-radius: 50%; background: var(--pink); }
  .live__list { display: flex; gap: 8px; min-width: 0; flex: 1; overflow: hidden; padding: 4px 0;
    -webkit-mask-image: linear-gradient(90deg, #000 82%, transparent); mask-image: linear-gradient(90deg, #000 82%, transparent); }
  .tick { flex: 0 0 auto; overflow: hidden; max-width: 260px; }
  .tick.is-new { animation: tickIn 480ms var(--ease-out) both; }
  @keyframes tickIn { from { max-width: 0; opacity: 0; } }
  .tick > a, .tick > button {
    display: flex; align-items: center; gap: 9px; height: 46px; padding: 4px 14px 4px 4px; border: 0; border-radius: 12px; text-decoration: none; text-align: left;
    background: var(--chip-bg); box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .14); transition: background-color 150ms, box-shadow 150ms;
  }
  .tick > a:hover, .tick > button:hover { background: rgba(255, 255, 255, .08); box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .26); }
  .tick--own > button { box-shadow: inset 0 0 0 1px rgba(115, 255, 0, .45); }
  .tick__th { width: 29px; height: 38px; flex: 0 0 auto; border-radius: 6px; overflow: hidden; box-shadow: 0 0 0 2px var(--t1), 0 0 12px -2px var(--t1); background: var(--surface); }
  .tick__th img { width: 100%; height: 100%; object-fit: cover; filter: blur(3px) saturate(1.2); transform: scale(1.25); }
  .tick__tx { display: flex; flex-direction: column; line-height: 1.15; white-space: nowrap; }
  .tick__tx b { font-size: 11px; font-weight: 800; letter-spacing: 0; text-transform: uppercase; color: var(--t1); }
  .tick__tx small { font-size: 11px; color: var(--muted); font-variant-numeric: tabular-nums; }
  #sndTop { display: inline-grid; }

  /* the left rail */
  .rail { display: flex; flex-direction: column; gap: 4px; grid-area: rail; min-height: 0; padding: 18px 12px 16px 16px; position: relative; z-index: 6; }
  /* Hug the label, not the whole rail: a full-width 48px pill read as a huge
     hover box (Luke, 9 Nov). */
  .rail__link {
    display: flex; align-items: center; gap: 12px; width: fit-content; max-width: 100%; min-height: 44px; padding: 0 18px 0 14px; border: 0; border-radius: var(--pill);
    background: none; color: rgba(255, 255, 255, .72); text-decoration: none; text-align: left;
    font-size: 15px; font-weight: 800; letter-spacing: 0; text-transform: none;
    transition: background-color 150ms, color 150ms, transform 150ms var(--ease-out);
  }
  .rail__link svg { flex: 0 0 auto; }
  .rail__link:hover { background: rgba(255, 255, 255, .07); color: #fff; }
  .rail__link:active { transform: scale(.96); }
  /* slushygames.net's tab pills: active #fff on rgba(255,255,255,.1), inactive dimmed on nothing */
  .rail__link[aria-current="page"] { background: rgba(255, 255, 255, .1); color: #fff; }
  /* the count sits right after the label, as a small green badge */
  .rail__count { margin-left: -4px; padding: 2px 8px; border-radius: var(--pill); background: rgba(115, 255, 0, .12); color: var(--green); font-size: 12px; line-height: 1.3; font-variant-numeric: tabular-nums; }
  .rail__count:empty { display: none; }
  .rail__link.sndbtn { position: relative; padding-left: 46px; }
  .rail__link.sndbtn .snd-on, .rail__link.sndbtn .snd-off { position: absolute; left: 14px; top: 50%; margin-top: -10px; }
  /* My girls + Suggested girls scroll together as one list */
  .rail__sec {
    display: flex; flex-direction: column; flex: 1 1 auto; min-height: 0; margin-top: 14px; padding-top: 14px; border-top: 1px solid var(--line);
    overflow-y: auto; margin-right: -4px; padding-right: 4px; scrollbar-width: thin; scrollbar-color: rgba(255, 255, 255, .2) transparent;
  }
  .rail__h { padding: 0 16px 8px; font-size: 11px; font-weight: 800; letter-spacing: 0; text-transform: uppercase; color: var(--faint); }
  .rail__h:not([hidden]) ~ .rail__h { margin-top: 18px; }
  .rail .pins { flex: 0 0 auto; margin: 0 -4px; padding: 0 4px; }
  .rail__foot { display: flex; flex-direction: column; gap: 2px; padding-top: 10px; border-top: 1px solid var(--line); }
  .rail__legal { display: flex; gap: 14px; padding: 8px 16px 0; font-size: 12px; }
  .rail__legal a { display: inline-flex; align-items: center; min-height: 32px; }
  /* the username beside the balance, desktop only (the phone's top bar has no room) */
  .bal__user:not([hidden]) { display: inline; padding-right: 8px; margin-right: 2px; border-right: 1px solid rgba(255, 255, 255, .2); }

  /* her card, right column */
  .side { display: block; grid-area: side; min-height: 0; overflow-y: auto; scrollbar-width: none; padding: 18px 16px 16px 4px; position: relative; z-index: 6; }
  .side::-webkit-scrollbar { display: none; }

  /* the stage */
  .shead { padding: 22px 0 0; }
  [data-page="creator"] .shead { display: block; }
  .shead__t { font-size: clamp(24px, 2.3vw, 34px); }
  .shead__sub { display: flex; margin-top: 8px; }
  .fan { touch-action: pan-y; }
  .pcard__acts .chipbtn { padding: 0 12px; text-align: center; line-height: 1.15; }
  .fmeta { gap: 4px; padding: 2px 0 4px; }
  .fmeta__row { gap: 18px; }
  .fmeta__title { font-size: clamp(18px, 1.7vw, 26px); min-width: clamp(220px, 22vw, 360px); min-height: 48px; }
  /* slushygames.net's feed prev/next: dark round chips with a light ring, white tailless arrow */
  .fmeta__arrow { width: 44px; height: 44px; }
  .fmeta__arrow:hover { background: rgba(255, 255, 255, .14); }
  .avatar--sm { --s: 40px; }

  /* the dock under the stage */
  .cta { align-items: center; gap: 16px; padding: 12px 0 18px; }
  .cta .hring { order: 0; width: min(400px, 100%); }
  /* See odds / My pulls / Sound live in the left rail on desktop (Luke, 9 Nov) */
  .cta__more { display: none; }
  .cta__hint { order: 2; }
  .cta__btn { min-height: 64px; font-size: 21px; }

  /* pages that scroll (all girls, 404) */
  .page { padding: 28px 28px 40px 8px; }
  .page-head h1 { font-size: 32px; }
  .page-head p { font-size: 16px; }
  .girls { grid-template-columns: repeat(auto-fill, minmax(232px, 1fr)); gap: 16px; }
  .gcard { padding: 0 14px 14px; }
  .gcard__banner { width: calc(100% + 28px); margin: 0 -14px; height: 104px; }
  .gcard__av { --s: 88px; margin-top: -50px; }
  .gcard__name { font-size: 18px; }
  .gcard__sub { font-size: 13px; }
  .gcard__stats { gap: 6px; }
  .gcard__stats > span { font-size: 9px; padding: 8px 2px; }
  .gcard__stats b { font-size: 14px; }
  .gcard__go { min-height: 44px; }
  .gcard__her { display: inline; }

  /* sheets become centred modals */
  .sheet { inset: 0; margin: auto; width: min(560px, calc(100vw - 48px)); max-width: none; height: fit-content; max-height: min(86dvh, 820px); }
  .sheet--tall { max-height: min(88dvh, 860px); }
  .sheet[open] { animation: popIn 240ms var(--ease-out); }
  @keyframes popIn { from { opacity: 0; transform: translateY(8px) scale(.97); } }
  .sheet__in { border-radius: 24px; box-shadow: 0 0 0 1px var(--line), 0 40px 100px -20px rgba(0, 0, 0, .8); }
  .sheet--tall .sheet__in { height: auto; }
  .sheet__head { padding: 18px 16px 12px 24px; }
  .sheet__head::before { display: none; }
  .sheet__body { padding: 4px 24px 24px; }
  .sheet__foot { padding: 16px 24px 20px; border-radius: 0 0 24px 24px; }
  .sheet--res { width: min(920px, calc(100vw - 64px)); }
  .sheet--res .sheet__body { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr); gap: 28px; align-items: start; }
  .sheet--res.is-single .sheet__body { grid-template-columns: minmax(0, 1fr); }
  .sheet--res .best .tile { width: min(100%, 42dvh); }   /* the best pull, its chip and its line all fit above the footer */
  .sheet--res .grid { margin-top: 32px; }
  .sheet--res .sheet__foot { display: flex; justify-content: center; }
  .sheet--res .sheet__foot .hring { width: min(420px, 100%); }
  .sheet--wide { width: min(980px, calc(100vw - 64px)); }
  .sheet--wide .grid { grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); }
  .seg { margin: 0; padding: 2px 0 14px; }

  /* top right, under the balance it usually reports on, clear of the stage title */
  .toast { bottom: auto; top: 80px; left: auto; right: 20px; transform: translateY(-12px); }
  .toast.is-on { transform: none; }
  [data-page="girls"] .toast, [data-page="notfound"] .toast { bottom: auto; }
}

/* narrow desktops */
@media (min-width: 1024px) and (max-width: 1279px) {
  .pcard { padding: 0 12px 12px; }
  .pcard__banner { margin: 0 -12px; }
  .pcard__acts .chipbtn { font-size: 11px; letter-spacing: 0; gap: 6px; padding: 0 10px; }   /* one line, never two */
  .pcard__stats dd { font-size: 14px; }
}

/* short desktops (1280×720 and friends): tighten the vertical rhythm */
@media (min-width: 1024px) and (max-height: 800px) {
  .app { grid-template-rows: 60px minmax(0, 1fr) auto; }
  .toast { top: 76px; }
  .shead { padding-top: 14px; }
  .shead__t { font-size: clamp(22px, 2vw, 30px); }
  .shead__sub { margin-top: 6px; }
  .fmeta__title { min-height: 42px; }
  .cta { gap: 14px; padding-bottom: 12px; }
  .cta__btn { min-height: 58px; font-size: 19px; }
  .cta__hint { display: none; }
  .cta__hint:has(button) { display: block; }
  .tick > a, .tick > button { height: 42px; }
  .tick__th { width: 26px; height: 34px; }
  .pcard__banner { height: 76px; }
  .pcard__pitch { display: none; }
  .rail__link { min-height: 44px; }
}

/* short phones (SE-size): give the fan the hint's line, unless the hint is the reset link */
@media (max-width: 1023px) and (max-height: 700px) {
  .cta__hint { display: none; }
  .cta__hint:has(button) { display: block; }
  .mhead { padding-top: 6px; }
}

/* ── reduced motion: keep every state change, drop the travel ── */
@media (prefers-reduced-motion: reduce) {
  :root { transition: none; }
  *, *::before, *::after { animation-duration: 1ms !important; animation-delay: 0ms !important; animation-iteration-count: 1 !important; transition-duration: 1ms !important; scroll-behavior: auto !important; }
  .age__in { animation: none !important; }
  .orow__bar i { transition: none; }
  .fpack::before { animation: none; }
}
