/* ─── the sequence ───────────────────────────────────────────────────────
   Three sticky, scroll-scrubbed sections: the garage filling, one discipline
   duel, and the sealed sets. js/sequence.js publishes every stage as a 0→1
   custom property on the section; everything below just reads them. Nothing
   here runs on a clock, so scrubbing backwards is exact rather than an
   animation played in reverse.
   ───────────────────────────────────────────────────────────────────────── */

.seq {
  position: relative;
  /* ~400vh per beat, matching the blueprint section. The sticky stage inside
     is what you actually see; this height is only the scroll budget. */
  height: 400vh;
}

.seq__stage {
  position: sticky;
  top: 0;
  height: 100vh;
  display: flex;
  flex-direction: column;
  justify-content: center;
  gap: clamp(1.25rem, 2.5vw, 2.5rem);
  overflow: hidden;
  padding-block: clamp(1.5rem, 4vh, 3.5rem);
}

.seq__head {
  position: relative;
  z-index: 3;
  flex: none;
}

/* Same as the garage: no hairline above a sticky stage's own heading. */
.seq__head .sec-head {
  border-top: 0;
  padding-top: 0;
  margin-bottom: clamp(1rem, 2.5vw, 2rem);
}

.seq__head h2 {
  font-size: clamp(2.4rem, 7vw, 6.5rem);
  line-height: 0.86;
  margin: 0 0 0.75rem;
  /* wide enough that a desktop keeps it on two lines at most, and it breaks
     on its own measure rather than at a hard-coded <br> */
  max-width: 26ch;
}

.seq__head .copy {
  max-width: 46ch;
  font-size: 0.92rem;
}

/* ══ 05 · the garage fills ══════════════════════════════════════════════ */

.library__tally {
  margin-top: clamp(1.25rem, 2.5vw, 2rem);
  display: flex;
  align-items: baseline;
  gap: 0.75rem;
  color: var(--dim);
}

.library__tally b {
  font-family: var(--display);
  font-weight: 700;
  font-size: clamp(3rem, 7vw, 6rem);
  line-height: 0.8;
  color: var(--bone);
  /* tabular so the number does not jitter its own width as it climbs */
  font-variant-numeric: tabular-nums;
}

.shelf {
  position: relative;
  z-index: 1;
  flex: 1;
  min-height: 0;
  display: grid;
  grid-template-columns: repeat(9, 1fr);
  /* Rows share whatever height is left rather than each card claiming its
     own 5:7 — otherwise two rows of portrait cards overflow the sticky
     stage and the shelf gets cut off mid-card. */
  align-content: center;
  gap: clamp(0.4rem, 1vw, 0.9rem);
  padding-inline: var(--gut);
}

/* Each card lands when the fill sweep reaches its index. The 9 divisor is
   the stagger: card 0 is done by the time card 8 starts, so the shelf reads
   as filling steadily rather than 18 things appearing at once. */
.mini {
  --t: clamp(0, calc(var(--fill, 0) * 22 - var(--i)), 1);
  position: relative;
  min-height: 0;
  aspect-ratio: 5 / 7;
  border-radius: 10px;
  overflow: hidden;
  background: var(--panel);
  opacity: var(--t);
  transform: translate3d(0, calc((1 - var(--t)) * 42px), 0)
    scale(calc(0.86 + var(--t) * 0.14));
  /* the last few settle into a shelf rather than a grid */
  box-shadow: 0 10px 30px rgb(0 0 0 / calc(var(--t) * 0.55));
}

.mini__well {
  position: absolute;
  inset: 0;
}

.mini__well img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

.mini__tier {
  position: absolute;
  top: 5px;
  left: 5px;
  z-index: 2;
  font-size: 0.4rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  padding: 0.15rem 0.35rem;
  border-radius: 99px;
  color: var(--tier, var(--bone));
  background: rgb(0 0 0 / 0.55);
  backdrop-filter: blur(6px);
}

.mini__prov {
  position: absolute;
  inset: auto 0 0 0;
  z-index: 2;
  padding: 0.5rem 0.45rem 0.4rem;
  background: linear-gradient(transparent, rgb(0 0 0 / 0.86) 55%);
}

.mini__prov p {
  font-size: 0.36rem;
  letter-spacing: 0.1em;
  color: var(--dim);
  margin: 0 0 0.1rem;
}

.mini__prov h4 {
  font-family: var(--display);
  font-weight: 700;
  text-transform: uppercase;
  font-size: clamp(0.6rem, 1.1vw, 0.95rem);
  line-height: 0.9;
  margin: 0;
  color: var(--bone);
}

.mini__frame {
  position: absolute;
  inset: 0;
  z-index: 3;
  border-radius: 10px;
  border: 1px solid var(--tier, var(--hair));
  opacity: 0.75;
  pointer-events: none;
}

.mini[data-tier="common"] { --tier: var(--t-common); }
.mini[data-tier="uncommon"] { --tier: var(--t-uncommon); }
.mini[data-tier="rare"] { --tier: var(--t-rare); }
.mini[data-tier="epic"] { --tier: var(--t-epic); }
.mini[data-tier="legendary"] { --tier: var(--t-legendary); }

/* ══ 06 · the duel ══════════════════════════════════════════════════════ */

/* The arena is its own row rather than a flex child: head, arena, closing
   line. Absolute children (the grid and the ring) overflowed a flex:1 box
   and landed on top of the closing line, so the row track is what actually
   bounds them. */
/* The duel is the one stage that must be a grid: its arena holds only
   absolutely-positioned children, which measure zero in a flex column and
   let the closing line ride up over the cars. Explicit rows bound it. The
   column has to be explicit too — the base justify-content: center would
   otherwise size an implicit column to content and collapse the arena. */
.seq--duel .seq__stage {
  display: grid;
  grid-template-columns: 100%;
  grid-template-rows: auto minmax(0, 1fr) auto;
  justify-content: stretch;
}

.duel {
  position: relative;
  z-index: 1;
  flex: 1;
  min-height: 0;
  padding-inline: var(--gut);
}

/* ── the grid you set before a bout ── */
.duel__grid {
  position: absolute;
  inset: 0;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  align-content: center;
  gap: clamp(0.6rem, 1.6vw, 1.6rem);
  padding-inline: var(--gut);
  /* holds while you set it, then clears out of the ring's way */
  opacity: calc(var(--grid, 0) * (1 - var(--clash, 0)));
  transform: translate3d(0, calc(var(--clash, 0) * -8vh), 0);
}

.slot {
  --tier: var(--hair);
  position: relative;
  border: 1px solid var(--hair);
  /* sharper corners: the struck-object register, per docs/design.md round 4 */
  border-radius: 10px;
  padding: clamp(0.5rem, 1.2vw, 0.9rem);
  background: color-mix(in srgb, var(--panel) 70%, transparent);
  display: flex;
  flex-direction: column;
  gap: 0.6rem;
  /* each slot arrives on its own beat */
  --t: clamp(0, calc(var(--grid, 0) * 5 - var(--n)), 1);
  opacity: var(--t);
  transform: translate3d(0, calc((1 - var(--t)) * 24px), 0);
}

.slot__label {
  font-size: 0.56rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--dim);
}

.slot__car {
  position: relative;
  aspect-ratio: 5 / 7;
  border-radius: 6px;
  overflow: hidden;
  background: #08090c;
  /* the car drops into its slot after the slot exists */
  --l: clamp(0, calc(var(--load, 0) * 5 - var(--n)), 1);
  opacity: var(--l);
  transform: translate3d(0, calc((1 - var(--l)) * -18px), 0);
}

.slot__car img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* the leg that actually gets contested lights up as the lineup commits */
.slot--live {
  border-color: color-mix(in srgb, var(--mint) calc(var(--lock, 0) * 70%), var(--hair));
  box-shadow: 0 0 calc(var(--lock, 0) * 26px)
    color-mix(in srgb, var(--mint) calc(var(--lock, 0) * 30%), transparent);
}

.slot--live .slot__label {
  color: color-mix(in srgb, var(--mint) calc(var(--lock, 0) * 100%), var(--dim));
}

/* ── the ring ── */
.duel__ring {
  position: absolute;
  inset: 0;
  display: grid;
  grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
  align-items: center;
  gap: clamp(0.75rem, 2vw, 2.5rem);
  padding-inline: var(--gut);
  opacity: var(--clash, 0);
  pointer-events: none;
}

.duel__disc {
  position: absolute;
  top: 6%;
  left: 50%;
  transform: translateX(-50%);
  font-size: 0.62rem;
  letter-spacing: 0.3em;
  text-transform: uppercase;
  color: var(--mint);
}

.fighter {
  --tier: var(--hair);
  position: relative;
  min-height: 0;
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  align-items: center;
  gap: clamp(0.6rem, 1.5vw, 1.25rem);
}

/* the challenger's block mirrors, so both read outward from the centre */
.fighter--them {
  grid-template-columns: minmax(0, 1fr) auto;
}

.fighter--them .fighter__well { order: 2; }
.fighter--them .fighter__meta { order: 1; text-align: right; }

/* Both sides close on the centre as --clash runs; the loser then falls back
   and dims while the winner is lifted. */
.fighter--you {
  transform: translate3d(calc((1 - var(--clash, 0)) * -26vw), 0, 0)
    scale(calc(1 + var(--win, 0) * 0.06));
}

.fighter--them {
  transform: translate3d(calc((1 - var(--clash, 0)) * 26vw), 0, 0)
    scale(calc(1 - var(--win, 0) * 0.08));
  opacity: calc(1 - var(--win, 0) * 0.55);
}

.fighter__well {
  position: relative;
  /* Width-capped, not height-driven. Letting the card fill the arena's
     height blew it up to fill the section and crushed the stat column into
     a one-word-per-line ribbon. */
  width: clamp(110px, 13vw, 210px);
  aspect-ratio: 5 / 7;
  border-radius: 12px;
  overflow: hidden;
  background: #08090c;
}

.fighter__well img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* the frame belongs to the photo, so it lives on the well rather than
   guessing at half the fighter's width */
.fighter__well::after {
  content: "";
  position: absolute;
  inset: 0;
  border-radius: 12px;
  border: 1px solid var(--tier);
  pointer-events: none;
  opacity: 0.8;
}

.fighter__frame {
  display: none;
}

.fighter--you .fighter__well {
  box-shadow: 0 0 calc(var(--win, 0) * 46px)
    color-mix(in srgb, var(--tier) calc(var(--win, 0) * 55%), transparent);
}

.fighter__meta p.mono {
  font-size: 0.56rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--dim);
  margin: 0 0 0.35rem;
}

.fighter__meta h4 {
  font-family: var(--display);
  font-weight: 700;
  text-transform: uppercase;
  font-size: clamp(1.1rem, 2.4vw, 2.1rem);
  line-height: 0.88;
  margin: 0 0 0.5rem;
  color: var(--bone);
}

.fighter__score {
  margin: 0 0 0.6rem;
}

.fighter__score b {
  font-family: var(--display);
  font-weight: 700;
  font-size: clamp(2.4rem, 6vw, 5rem);
  line-height: 0.78;
  color: var(--tier);
  font-variant-numeric: tabular-nums;
  /* the number resolves rather than being there from the start */
  opacity: var(--verdict, 0);
}

.fighter__why {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: 0.18rem;
  font-size: 0.54rem;
  letter-spacing: 0.1em;
  color: var(--dim);
  opacity: var(--verdict, 0);
}

.fighter__why b {
  color: var(--bone);
  font-weight: 400;
}

.fighter[data-tier="uncommon"] { --tier: var(--t-uncommon); }
.fighter[data-tier="rare"] { --tier: var(--t-rare); }
.fighter[data-tier="epic"] { --tier: var(--t-epic); }
.fighter[data-tier="legendary"] { --tier: var(--t-legendary); }

.duel__vs {
  font-size: 0.62rem;
  letter-spacing: 0.28em;
  text-transform: uppercase;
  color: var(--dimmer);
  text-align: center;
}

/* The verdict belongs in the centre column under the VS, not floating over
   the ring: absolute-positioning it landed the winner's name on top of the
   two cars it was announcing between. */
.duel__mid {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: clamp(0.6rem, 1.5vw, 1.25rem);
  text-align: center;
}

.duel__verdict {
  transform: translateY(calc((1 - var(--win, 0)) * 14px));
  opacity: var(--win, 0);
}

.duel__verdict .mono {
  font-size: 0.56rem;
  letter-spacing: 0.28em;
  text-transform: uppercase;
  color: var(--dim);
  margin: 0 0 0.3rem;
}

.duel__winner {
  font-family: var(--display);
  font-weight: 700;
  text-transform: uppercase;
  white-space: nowrap;
  font-size: clamp(1.5rem, 3.4vw, 3rem);
  line-height: 0.85;
  margin: 0;
  color: var(--bone);
}

.duel__foot {
  position: relative;
  z-index: 3;
  flex: none;
  max-width: 56ch;
  opacity: var(--verdict, 0);
}

/* ══ the sets ═══════════════════════════════════════════════════════════
   Pulled from the page for now, not deleted. These rules and the matching
   stage config in js/sequence.js are intact, so restoring the beat is a
   matter of putting its markup back — nothing here needs rebuilding. */

.packs {
  position: relative;
  z-index: 1;
  flex: 1;
  min-height: 0;
  display: grid;
  grid-template-columns: repeat(6, 1fr);
  /* The pack keeps its 5:7 and is centred in whatever height is left, capped
     at it. The stage clips anything over, so a short viewport trims the packs
     rather than losing them. */
  align-content: center;
  gap: clamp(0.5rem, 1.2vw, 1.1rem);
  padding-inline: var(--gut);
}

.pack {
  --tier: var(--t-rare);
  --t: clamp(0, calc(var(--deal, 0) * 8 - var(--i)), 1);
  position: relative;
  min-height: 0;
  aspect-ratio: 5 / 7;
  border-radius: 12px;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  padding: clamp(0.6rem, 1.2vw, 1rem);
  /* dark foil pack: near-black with the set colour as an edge bloom, never a
     bright pastel fill (docs/design.md round 3) */
  background: radial-gradient(
      120% 80% at 50% 100%,
      color-mix(in srgb, var(--tier) 22%, transparent),
      transparent 70%
    ),
    #08090c;
  border: 1px solid color-mix(in srgb, var(--tier) 40%, var(--hair));
  opacity: var(--t);
  transform: translate3d(0, calc((1 - var(--t)) * 40px), 0)
    rotate(calc((1 - var(--t)) * -3deg));
}

.pack__wm {
  position: absolute;
  right: -0.12em;
  top: -0.22em;
  font-family: var(--display);
  font-weight: 700;
  font-size: clamp(5rem, 12vh, 11rem);
  line-height: 1;
  color: color-mix(in srgb, var(--tier) 12%, transparent);
  pointer-events: none;
}

.pack__body {
  position: relative;
  z-index: 2;
}

.pack__kicker {
  font-size: 0.44rem;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  color: var(--dimmer);
  margin: 0 0 0.4rem;
}

.pack__title {
  font-family: var(--display);
  font-weight: 700;
  text-transform: uppercase;
  font-size: clamp(1rem, 2vw, 1.8rem);
  line-height: 0.88;
  margin: 0 0 0.35rem;
  color: var(--bone);
}

.pack__blurb {
  font-size: 0.4rem;
  letter-spacing: 0.12em;
  line-height: 1.5;
  color: var(--dim);
  margin: 0;
}

.pack__count {
  position: relative;
  z-index: 2;
  margin: 0.7rem 0 0;
  font-size: 0.5rem;
  letter-spacing: 0.16em;
  color: var(--dimmer);
}

.pack__count b {
  color: var(--tier);
  font-weight: 400;
}

/* the faint iridescent band that says "sealed", raised as --seal resolves */
.pack__foil {
  position: absolute;
  inset: 0;
  z-index: 1;
  pointer-events: none;
  opacity: calc(0.25 + var(--seal, 0) * 0.55);
  background: linear-gradient(
    114deg,
    transparent 32%,
    color-mix(in srgb, var(--mint) 16%, transparent) 44%,
    color-mix(in srgb, #dfe7ff 18%, transparent) 50%,
    color-mix(in srgb, var(--violet) 16%, transparent) 57%,
    transparent 68%
  );
  transform: translate3d(calc(-24% + var(--seal, 0) * 34%), 0, 0);
}

.pack[data-tier="uncommon"] { --tier: var(--t-uncommon); }
.pack[data-tier="rare"] { --tier: var(--t-rare); }
.pack[data-tier="epic"] { --tier: var(--t-epic); }
.pack[data-tier="legendary"] { --tier: var(--t-legendary); }

/* ══ narrow ═════════════════════════════════════════════════════════════ */

@media (max-width: 900px) {
  .shelf {
    grid-template-columns: repeat(6, 1fr);
  }
  .packs {
    grid-template-columns: repeat(3, 1fr);
  }
  .duel__grid {
    grid-template-columns: repeat(2, 1fr);
  }
  .fighter {
    grid-template-columns: 1fr;
    gap: 0.5rem;
  }
  .fighter__frame {
    width: 100%;
    height: auto;
    aspect-ratio: 5 / 7;
  }
}

@media (max-width: 620px) {
  .seq {
    height: 320vh;
  }
  .shelf {
    grid-template-columns: repeat(4, 1fr);
  }
  .packs {
    grid-template-columns: repeat(2, 1fr);
  }
  /* the duel's two sides stack, so they meet vertically instead of laterally */
  .duel__ring {
    grid-template-columns: 1fr;
    gap: 0.4rem;
  }
  .fighter--you {
    transform: translate3d(0, calc((1 - var(--clash, 0)) * -18vh), 0);
  }
  .fighter--them {
    transform: translate3d(0, calc((1 - var(--clash, 0)) * 18vh), 0);
    opacity: calc(1 - var(--win, 0) * 0.55);
  }
  .fighter__why {
    display: none;
  }
}

/* Reduced motion: js/sequence.js pins every stage at 1, so each section is
   its own finished frame. Nothing below needs to move for it to make sense. */
@media (prefers-reduced-motion: reduce) {
  .seq {
    height: auto;
  }
  .seq__stage {
    position: relative;
    height: auto;
    padding-block: clamp(3rem, 8vw, 7rem);
  }
  .duel {
    min-height: 70vh;
  }
}
