/* ============================================================
   SUSPENSE REEL — the rarity slot reel (site/suspense.js).

   blockrips' reel MECHANICS (spin, brake, ticks, thunk, hold, clear), in
   Slushy's own clothes. Every choice below is read off Slushy's live UI
   (slushygames.net and slushy.com, measured 9 Nov 2026), not invented:

   * THE FACE. Slushy's big moments are set in normalidad-ultraextended 900,
     uppercase, no tracking: "$75,000 GIVEAWAY" (24px) and "TRENDING GAMES" /
     "LIVE BETS" on slushygames.net/games, the "MY GOALS" kicker on the live
     page. Their UI never uses italics and never outlines type (the old reel's
     800 italic with a dark keyline was blockrips' sticker look, not theirs).
   * THE CARD. Their panels are flat #1F2123 surfaces with a hairline ring:
     the gems sheet (rgba(31,33,35,.75), radius 22), slushy.com's age gate
     (#1F2123, radius 22, a 1px rgba(255,255,255,.1) inner section). So the
     reel sits on one such card instead of floating over the pack art.
   * THE PAYLINE. Their tier cards on the gems sheet are "armed" by a 2px
     ring in the tier's colour: 20% at rest, full strength when chosen. The
     payline is that ring, white at 20% while it spins.
   * THE LANDING. Their result chips are SOLID colour with #1F2123 type: the
     green multiplier chips (3.08x), the magenta "% off" pill. The tier lands
     the same way: the payline fills with the tier's colours and the word
     turns #1F2123 — a chip, not a glow sticker.
   * THE KICKER. "MY GOALS": normalidad-ultraextended 10px / 900 / uppercase
     / #fff, no tracking.

   It lives inside the rip overlay (#rip), under the sealed pack (suspense.js
   sizes and centres the pack in the space above the card), and it never
   takes a pointer, so a tap still reaches #rip's tap-to-skip.

   LEGIBILITY (Luke: two half-cut words under a tiny label "reads as
   garbage"). A one-line window shows two half words whenever the strip is
   between rows, so this one is 2.2 rows tall: the centre row always sits
   whole inside the payline, and the half rows above and below it are the
   neighbours, faded by shades in the card's own colour. No mask-image on
   the moving strip (blockrips measured it as per-frame GPU work on phones);
   the shades are static layers. transform / opacity only while spinning.
   ============================================================ */
.suspense {
  position: absolute; inset: 0; z-index: 3; pointer-events: none;
  display: grid; grid-template-areas: "rarity"; justify-items: center; align-items: end;
  padding: 0 16px calc(76px + 3vh + env(safe-area-inset-bottom, 0px));
  opacity: 0; transition: opacity 300ms cubic-bezier(.22, .8, .36, 1);
}
.suspense[data-on="1"] { opacity: 1; }

/* ROOM FOR THE REEL. While the reel is up (suspense.js sets data-sus on #rip)
   the sealed still is scaled and moved with the individual `scale` /
   `translate` properties, which compose with its own transform animations
   (sealedIn, sealedPulse) and pivot about the pack's own centre (app.css
   centres its box by layout). suspense.js MEASURES the space above the card
   and writes --sus-s (scale) and --sus-x / --sus-y (px) so the pack is
   exactly centred, left to right, in that space at every viewport — the
   fallbacks below only apply if it could not measure. It eases back to its
   exact rest pose (rip.js frame 0, 1.1% left) during the reel's 320ms exit,
   before the 3D crossfades in over it, so the handover is unchanged. */
.rip__sealed { transition: opacity 180ms, translate 320ms cubic-bezier(.22, .8, .36, 1), scale 320ms cubic-bezier(.22, .8, .36, 1); }
[data-sus="1"] > .rip__sealed {
  translate: var(--sus-x, 0px) var(--sus-y, -14%); scale: var(--sus-s, .74);
  transition: opacity 180ms, translate 420ms cubic-bezier(.22, .8, .36, 1), scale 420ms cubic-bezier(.22, .8, .36, 1);
}

/* ---------- the card ---------- */
.sus {
  --card: 31, 33, 35;                 /* #1F2123, Slushy's base */
  --t1: #fff; --t2: #fff;             /* the landed tier's colours (suspense.js) */
  grid-area: rarity; position: relative; max-width: 100%;
  display: flex; flex-direction: column; align-items: center; gap: 8px;
  padding: 12px 12px 12px; border-radius: 22px;
  background: rgba(var(--card), .94);
  box-shadow: inset 0 0 0 1px rgba(255, 255, 255, .10), 0 24px 60px -20px rgba(0, 0, 0, .85);
  opacity: 0; transform: translateY(14px);
  transition: opacity 320ms cubic-bezier(.22, .8, .36, 1), transform 320ms cubic-bezier(.22, .8, .36, 1), box-shadow 260ms ease-out;
}
.sus--in { opacity: 1; transform: none; }
.sus[data-set="1"] { box-shadow: inset 0 0 0 1px color-mix(in srgb, var(--t1) 45%, transparent), 0 24px 60px -20px rgba(0, 0, 0, .85), 0 0 70px -24px var(--t2); }

/* the kicker: their "MY GOALS" spec */
.sus__label {
  font-family: 'normalidad-ultraextended', 'Archivo', system-ui, sans-serif; font-stretch: 125%;
  font-size: 10px; line-height: 12.5px; font-weight: 900; letter-spacing: 0; text-transform: uppercase;
  color: #fff; white-space: nowrap;
}

/* ---------- the reel ---------- */
.sus__reel {
  --row: 1.36em;
  position: relative; overflow: hidden; contain: paint;
  height: calc(var(--row) * 2.2); border-radius: calc(var(--row) * .5);
  font-family: 'normalidad-ultraextended', 'Archivo', system-ui, sans-serif; font-stretch: 125%;
  font-weight: 900; font-style: normal; letter-spacing: 0; text-transform: uppercase;
  font-size: clamp(26px, 4vh, 40px); line-height: 1;
}
/* the payline: one row, centred, the gems sheet's armed-tier ring at rest (20%) */
.sus__win {
  position: absolute; z-index: 0; left: 0; right: 0; top: calc(var(--row) * .6); height: var(--row);
  border-radius: 999px; background: rgba(255, 255, 255, .06); box-shadow: inset 0 0 0 2px rgba(255, 255, 255, .2);
  transition: box-shadow 200ms ease-out, background-color 200ms ease-out;
}
.sus__win::before { /* the landed fill, the tier's own two colours */
  content: ''; position: absolute; inset: 0; border-radius: inherit; opacity: 0;
  background: linear-gradient(90deg, var(--t1), var(--t2));
}
/* Slushy's feed arrows are tailless triangles (their micro-solid icon set);
   two of them mark the payline */
.sus__chev {
  position: absolute; top: 50%; width: .3em; height: .36em; margin-top: -.18em;
  background: rgba(255, 255, 255, .55); transition: background-color 200ms ease-out;
}
.sus__chev:first-child { left: .28em; clip-path: polygon(0 0, 100% 50%, 0 100%); }
.sus__chev:last-of-type { right: .28em; clip-path: polygon(100% 0, 0 50%, 100% 100%); }
/* one light pass over a Legendary or Mythic landing */
.sus__shine {
  position: absolute; inset: 0; border-radius: inherit; overflow: hidden; opacity: 0;
}
.sus__shine::before {
  content: ''; position: absolute; top: 0; bottom: 0; left: -40%; width: 40%;
  background: linear-gradient(100deg, transparent, rgba(255, 255, 255, .55), transparent);
  transform: translateX(0);
}

.sus__strip {
  position: relative; z-index: 1; top: calc(var(--row) * .6);
  display: flex; flex-direction: column; will-change: transform;
}
.sus__item {
  height: var(--row); display: flex; align-items: center; justify-content: center;
  white-space: nowrap; padding: .06em .7em 0;   /* the caps sit a hair high in the row; .06em centres them optically */
  color: var(--t1, #fff);
  transition: opacity 160ms ease-out, color 140ms ease-out;
}
/* the neighbours fade out above and below the payline: static shades in the
   card's own colour, never a mask on the moving strip */
.sus__reel::before, .sus__reel::after {
  content: ''; position: absolute; z-index: 2; left: 0; right: 0; height: calc(var(--row) * .62); pointer-events: none;
}
.sus__reel::before { top: 0; background: linear-gradient(rgba(var(--card), .96), rgba(var(--card), .35) 70%, rgba(var(--card), 0)); }
.sus__reel::after { bottom: 0; background: linear-gradient(0deg, rgba(var(--card), .96), rgba(var(--card), .35) 70%, rgba(var(--card), 0)); }

/* blind spin: the strip holds 4 copies; the loop runs from the 2nd copy to
   the 3rd (one cycle, --cyc = rows x row height), so there is always a row
   above and below the payline. The rarity spins DOWN like a real slot. */
@keyframes sus-spin { from { transform: translateY(calc(var(--cyc) * -1)); } to { transform: translateY(calc(var(--cyc) * -2)); } }
.sus__strip[data-spin="1"] { animation: sus-spin var(--sus-dur, 1.125s) linear infinite; }
.sus__strip[data-dir="down"][data-spin="1"] { animation-direction: reverse; }

/* ---------- the lock ----------
   The neighbours go, the payline fills with the tier, the word turns
   #1F2123 on it and pops: a Slushy result chip. */
.sus__reel[data-set="1"] .sus__strip { will-change: auto; }
.sus__reel[data-set="1"] .sus__item:not([data-hit="1"]) { opacity: 0; }
.sus__reel[data-set="1"] .sus__item[data-hit="1"] { color: #1F2123; animation: sus-lock 260ms cubic-bezier(.22, .8, .36, 1); }
.sus__reel[data-set="1"] .sus__win { box-shadow: inset 0 0 0 2px var(--t1), 0 0 0 4px color-mix(in srgb, var(--t1) 22%, transparent), 0 10px 40px -8px var(--t2); animation: sus-lock 260ms cubic-bezier(.22, .8, .36, 1); }
.sus__reel[data-set="1"] .sus__win::before { opacity: 1; transition: opacity 120ms ease-out; }
.sus__reel[data-set="1"] .sus__chev { background: #1F2123; }
.sus__reel[data-set="1"][data-tier="legendary"] .sus__shine,
.sus__reel[data-set="1"][data-tier="mythic"] .sus__shine { opacity: 1; }
.sus__reel[data-set="1"][data-tier="legendary"] .sus__shine::before,
.sus__reel[data-set="1"][data-tier="mythic"] .sus__shine::before { animation: sus-shine 720ms cubic-bezier(.3, .7, .3, 1) 120ms both; }
@keyframes sus-lock { 0% { transform: scale(1); } 45% { transform: scale(1.06); } 100% { transform: scale(1); } }
@keyframes sus-shine { from { transform: translateX(0); } to { transform: translateX(350%); } }

/* ---------- the phone ---------- */
@media (max-width: 1023px) {
  .suspense { padding-bottom: calc(84px + 4vh + env(safe-area-inset-bottom, 0px)); }
  .sus { padding: 10px 10px 10px; border-radius: 20px; gap: 6px; }
  .sus__reel { font-size: min(7.4vw, 28px); }
}

/* ---------- reduced motion: no spin, the result fades in ---------- */
.suspense[data-rm="1"] .sus { transform: none; transition: opacity 200ms ease-out; }
.suspense[data-rm="1"] .sus__strip { animation: none; }
.suspense[data-rm="1"] .sus__reel[data-set="1"] .sus__item[data-hit="1"],
.suspense[data-rm="1"] .sus__reel[data-set="1"] .sus__win,
.suspense[data-rm="1"] .sus__shine::before { animation: none; }
@media (prefers-reduced-motion: reduce) {
  .rip__sealed, [data-sus="1"] > .rip__sealed { transition: opacity 180ms; }   /* no travel: the pack just sits higher */
  .sus__strip[data-spin="1"] { animation: none; }
  .sus__reel[data-set="1"] .sus__item[data-hit="1"], .sus__reel[data-set="1"] .sus__win, .sus__shine::before { animation: none; }
  .sus { transform: none; transition: opacity 200ms ease-out; }
}
