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

   blockrips' reel MECHANICS (spin, brake, ticks, thunk, hold, clear), in the
   shop's own clothes:

   * THE FACE. Big moments are set in Rubik 900,
     uppercase, no tracking. No italics, no outlined type.
   * THE CARD. Panels are flat #1F2123 surfaces with a hairline ring
     (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. Tier cards 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. Result chips are SOLID colour with #1F2123 type. 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. Rubik 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, and
   the strip is its own compositor layer (will-change) inside a paint-contained
   window.
   ============================================================ */
.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 reel: blockrips' look, the shop's display type (Luke, 12 Nov: "no box. just
   do it like blockrips but in our font") ----------
   blockrips (eval/style.css:1580-1673): no card, no frame, no payline. The tier words ride
   a masked band under the pack, each in its own tier colour with a dark halo; on the lock
   the losing rows go, the mask comes off and the winner pops and blooms in its colour.
   The face: Rubik 900, uppercase, upright, no tracking. */
.sus {
  grid-area: rarity; position: relative; max-width: 100%;
  display: flex; flex-direction: column; align-items: center; gap: 22px;
  opacity: 0; transform: translateY(14px);
  transition: opacity 320ms cubic-bezier(.22, .8, .36, 1), transform 320ms cubic-bezier(.22, .8, .36, 1);
}
.sus--in { opacity: 1; transform: none; }

/* the kicker */
.sus__label {
  font-family: 'Rubik', system-ui, sans-serif;
  font-size: 11px; line-height: 1; font-weight: 900; letter-spacing: 0; text-transform: uppercase;
  color: rgba(255, 255, 255, .7); white-space: nowrap; text-shadow: 0 2px 8px #000;
}

/* the band (13 Nov: each row is a rating badge, site/rating-badge.css): 1.7 rows,
   so the centre badge is always whole and a third of each neighbour shows above
   and below, faded through a mask on the (static) band, never on the moving strip.
   (A word row was 1.2em and the band 2.2 rows; a badge is 1.165 x its width, so
   2.2 badge rows would push the pack half off a phone.) */
.sus__reel {
  --rb-w: clamp(92px, 14vh, 128px);
  --row: calc(var(--rb-w) * 1.165 + 16px);
  position: relative; overflow: hidden;
  height: calc(var(--row) * 1.7);
  font-family: 'Rubik', system-ui, sans-serif;
  font-weight: 900; font-style: normal; letter-spacing: 0; text-transform: uppercase;
  font-size: clamp(44px, 7.6vh, 88px); line-height: 1;
  -webkit-mask-image: linear-gradient(180deg, transparent, #000 22%, #000 78%, transparent);
  mask-image: linear-gradient(180deg, transparent, #000 22%, #000 78%, transparent);
}
.sus__win { display: none; }   /* no payline box (the markup stays for suspense.js) */

.sus__strip {
  position: relative; z-index: 1; top: calc(var(--row) * .35);
  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 .3em 0;
  line-height: 0;   /* the badge image sits in the row with no text strut under it */
  color: var(--t1, #fff);
  /* blockrips: the dark halo separates the type from the lit pack behind it */
  text-shadow: 0 2px 6px rgba(0, 0, 0, .92), 0 0 26px rgba(0, 0, 0, .75);
  /* NO opacity transition (13 Nov, Luke: "when the spinner lands on the rarity, it like flashes
     all the rarities on the screen for a split sec"). The lock below takes the clip and the mask
     off in one frame, so the losing rows must go in that SAME frame, as blockrips' do (its
     .sus__item has no transition). The 160ms fade left by the 9 Nov boxed look showed all ~29
     losing words, unclipped, for 9 frames. */
}

/* THE MOTION is not here. Since 12 Nov the spin and the brake are ONE Web
   Animation on the strip's transform, solved up front by suspense.js
   (reelPlan) and run by the compositor, so the 3D stage building on the main
   thread behind the reel cannot stall it. The strip holds enough copies of the
   tiers for the whole run, so it never wraps; it spins DOWN like a slot. */

/* ---------- the lock (blockrips): the window stops being a window ---------- */
.sus__reel[data-set="1"] { overflow: visible; -webkit-mask-image: none; mask-image: none; }
.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"] {
  text-shadow: 0 0 18px var(--t1), 0 2px 10px rgba(0, 0, 0, .9);
  filter: drop-shadow(0 0 26px var(--t1));
  animation: sus-lock 260ms cubic-bezier(.22, .8, .36, 1);
}
/* R (Legendary and Mythic, merged 13 Nov) lands harder: a bigger pop and a bloom that breathes once */
.sus__reel[data-set="1"][data-tier="r"] .sus__item[data-hit="1"] {
  animation: sus-lock-big 420ms cubic-bezier(.22, .8, .36, 1), sus-bloom 1100ms ease-out 120ms both;
}
@keyframes sus-lock { 0% { transform: scale(1); } 45% { transform: scale(1.08); } 100% { transform: scale(1); } }
@keyframes sus-lock-big { 0% { transform: scale(.92); } 40% { transform: scale(1.16); } 100% { transform: scale(1); } }
@keyframes sus-bloom { 0% { filter: drop-shadow(0 0 26px var(--t1)); } 35% { filter: drop-shadow(0 0 64px var(--t1)) brightness(1.18); } 100% { filter: drop-shadow(0 0 26px var(--t1)); } }

/* ---------- the phone ---------- */
@media (max-width: 1023px) {
  .suspense { padding-bottom: calc(84px + 4vh + env(safe-area-inset-bottom, 0px)); }
  .sus { gap: 16px; }
  .sus__reel { font-size: min(9.4vw, 46px); --rb-w: clamp(84px, 12vh, 108px); }
}

/* ---------- 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__reel[data-set="1"] .sus__item[data-hit="1"] { 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__reel[data-set="1"] .sus__item[data-hit="1"] { animation: none; }
  .sus { transform: none; transition: opacity 200ms ease-out; }
}
