/* =============================================================================
   Blind Box — a straight replica of the Pop Mart "POP NOW" set page.

   Layout: step strip on top, product stage left, buy column right, line-up
   strip and spec table underneath. Everything is driven by the --pm-* tokens
   below, which are the reference page's own values in light mode and their
   dark-surface equivalents when the site theme is dark.
   ============================================================================= */

/* Barlow is the reference page's typeface, self-hosted so the page does not
   depend on a third-party CDN being reachable. Latin only — Chinese falls
   through to the theme stack, which Barlow could never have covered anyway. */
@font-face {
  font-family: "Barlow";
  font-style: normal;
  font-weight: 300;
  font-display: swap;
  src: url("../fonts/barlow-300.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Barlow";
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url("../fonts/barlow-400.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Barlow";
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url("../fonts/barlow-500.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Barlow";
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url("../fonts/barlow-600.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Barlow";
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url("../fonts/barlow-700.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

.ch-pm-shell {
  --pm-stage:   #f5f5f5;   /* the reference's product plate */
  --pm-riser:   #e6e2da;   /* paperboard the boxes stand in */
  --pm-riser-2: #d5d0c6;
  --pm-ink:     rgba(0, 0, 0, 0.85);
  --pm-ink-2:   #666;
  --pm-ink-3:   #999;
  --pm-line:    #e5e5e5;
  --pm-line-2:  #d4d4d4;
  --pm-red:     #d2001e;
  --pm-hl:      #ffe600;   /* the yellow marker under the active step */
  --pm-btn:     #000;
  --pm-btn-ink: #fff;
  --pm-surface: #fff;
  --pm-font:    "Barlow", "Inter", -apple-system, "Segoe UI", Roboto, sans-serif;

  /* The reference is a white product page end to end, so the section runs
     full-bleed rather than sitting on the site's page background. */
  padding: 26px 0 56px;
  background: var(--pm-surface);
}

.ch-pm-page {
  color: var(--pm-ink);
  font-family: var(--pm-font);
  font-size: 14px;
  line-height: 1.5;
}

/* One centred column for the whole set page: banner, case, buy bar, line-up
   and spec table all share the same edges, on every screen size. Two classes
   deep because reddit-theme.css loads last and widens .ch-container. */
.ch-pm-shell .ch-pm-page {
  max-width: 1180px;
  margin-inline: auto;
}

/* The theme sets its own family on h1–h6, and a direct rule outranks
   inheritance — so the headings have to be named again or the page ends up
   half Barlow, half Inter. */
.ch-pm-page :is(h1, h2, h3, h4) {
  font-family: var(--pm-font);
}

html[data-theme="dark"] .ch-pm-shell {
  --pm-stage:   #17181a;
  --pm-ink:     #e8eaec;
  --pm-ink-2:   #a4a9ad;
  --pm-ink-3:   #7c8185;
  --pm-line:    #2c2e30;
  --pm-line-2:  #3a3d40;
  --pm-red:     #ff5c72;
  --pm-hl:      #ffd400;
  --pm-btn:     #f2f3f4;
  --pm-btn-ink: #101113;
  --pm-surface: var(--color-bg);
}

/* Author-level `display` outranks the UA rule for the hidden attribute, so
   state-toggled elements need this to actually hide. */
.ch-pm-page [hidden] {
  display: none !important;
}

/* ============================================================================
   The type index — /blind-box/ with no set chosen.

   A player's first question is "which blind box?", and the set page has no
   room to ask it: it opens on one series with the others tucked into a
   thumbnail strip below the fold. So the bare URL is a grid of covers, one
   per configured series, and picking one walks into that series' case.
   ============================================================================ */
.ch-bbi-head {
  max-width: 640px;
  margin: 0 0 26px;
}

.ch-bbi-kicker {
  margin: 0 0 6px;
  color: var(--pm-red);
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.2em;
  text-transform: uppercase;
}

.ch-bbi-title {
  margin: 0;
  font-size: clamp(26px, 3vw, 38px);
  font-weight: 700;
  line-height: 1.1;
  letter-spacing: -0.01em;
}

.ch-bbi-sub {
  margin: 10px 0 0;
  color: var(--pm-ink-2);
  font-size: 14px;
}

/* auto-fill, not auto-fit: with two series configured the tiles stay their own
   size instead of stretching half a metre wide across a desktop. */
.ch-bbi-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(240px, 1fr));
  gap: 18px;
  margin: 0;
  padding: 0;
  list-style: none;
}

.ch-bbi-cell { display: flex; }

.ch-bbi-card {
  display: flex;
  flex-direction: column;
  width: 100%;
  border: 1px solid var(--pm-line);
  background: var(--pm-surface);
  color: var(--pm-ink);
  text-decoration: none;
  transition: border-color 0.15s ease, transform 0.15s ease;
}

.ch-bbi-card:hover {
  border-color: var(--pm-ink);
  color: var(--pm-ink);
  transform: translateY(-2px);
}

.ch-bbi-card:focus-visible {
  outline: 2px solid var(--pm-ink);
  outline-offset: 2px;
}

/* Always dark behind the cover: these key visuals are shot on black, and the
   carton fallback is a cut-out that needs a ground of its own. */
.ch-bbi-cover {
  position: relative;
  display: block;
  aspect-ratio: 16 / 9;
  background: #0d0f11;
  overflow: hidden;
}

.ch-bbi-cover.is-plain {
  background: linear-gradient(120deg, #15171a, #23272c 60%, #3a2018);
}

.ch-bbi-cover-img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center right;
}

/* The carton stand-in is a photographed box on transparency — contain it and
   let it stand in the middle rather than cropping it to a banner. */
.ch-bbi-cover-img.is-cutout {
  object-fit: contain;
  object-position: center;
  padding: 14px;
}

/* Shown only for a set that is nearly gone, so it has to read as urgency
   rather than as one more statistic. Fixed red in both themes — it sits on
   the cover, which is always a dark photograph. */
.ch-bbi-stock {
  position: absolute;
  right: 10px;
  bottom: 10px;
  padding: 3px 9px;
  border-radius: 999px;
  background: rgba(196, 0, 28, 0.92);
  color: #fff;
  font-size: 11px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  letter-spacing: 0.01em;
}

.ch-bbi-body {
  display: flex;
  flex: 1;
  flex-direction: column;
  gap: 4px;
  padding: 14px 16px 16px;
}

.ch-bbi-name {
  font-size: 17px;
  font-weight: 700;
  line-height: 1.2;
}

.ch-bbi-meta {
  color: var(--pm-ink-2);
  font-size: 12px;
  font-variant-numeric: tabular-nums;
}

.ch-bbi-foot {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 10px;
  margin-top: auto;
  padding-top: 12px;
}

.ch-bbi-price {
  color: var(--pm-red);
  font-size: 18px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

.ch-bbi-price em {
  color: var(--pm-ink-2);
  font-size: 12px;
  font-style: normal;
  font-weight: 400;
}

.ch-bbi-go {
  display: inline-flex;
  align-items: center;
  gap: 2px;
  font-size: 13px;
  font-weight: 700;
}

.ch-bbi-go .ch-icon { width: 15px; height: 15px; }

.ch-bbi-card:hover .ch-bbi-go .ch-icon { transform: translateX(2px); }

.ch-bbi-note {
  display: flex;
  align-items: center;
  gap: 6px;
  margin: 22px 0 0;
  color: var(--pm-ink-2);
  font-size: 12px;
}

.ch-bbi-note .ch-icon { width: 14px; height: 14px; flex: none; }

@media (prefers-reduced-motion: reduce) {
  .ch-bbi-card,
  .ch-bbi-go .ch-icon { transition: none; }
  .ch-bbi-card:hover { transform: none; }
  .ch-bbi-card:hover .ch-bbi-go .ch-icon { transform: none; }
}

/* ---------------------------------------------------------------- banner -- */
/* The series' key visual, running the full width of the page above the step
   strip: it names what the whole page is about, so it cannot sit inside the
   product column while the buy column starts level with it. The artwork is
   uploaded per series and keeps its subject on the right, so the scrim only
   has to darken the left where the name sits. Always dark, in both themes —
   the art is shot on black. */
.ch-pm-banner {
  position: relative;
  display: flex;
  align-items: center;
  min-height: clamp(120px, 13vw, 190px);
  margin: 0 0 22px;
  padding: 22px 26px;
  background-color: #0d0f11;
  background-position: center right;
  background-size: cover;
  background-repeat: no-repeat;
  overflow: hidden;
}

.ch-pm-banner::before {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(90deg,
              rgba(8, 9, 10, 0.94) 0%,
              rgba(8, 9, 10, 0.78) 30%,
              rgba(8, 9, 10, 0.25) 58%,
              rgba(8, 9, 10, 0) 76%);
}

/* No artwork uploaded yet: a plain title bar instead of an empty black band. */
.ch-pm-banner.is-plain {
  min-height: 0;
  padding: 20px 24px;
  background-image: linear-gradient(120deg, #15171a, #23272c 60%, #3a2018);
}

.ch-pm-banner-text {
  position: relative;
  z-index: 1;
  max-width: min(62%, 620px);
}

.ch-pm-banner-kicker {
  margin: 0 0 6px;
  color: #ff6a3d;
  font-size: 11px;
  font-weight: 700;
  letter-spacing: 0.2em;
  text-transform: uppercase;
}

.ch-pm-banner-title {
  margin: 0;
  color: #fff;
  font-size: clamp(24px, 2.3vw, 34px);
  font-weight: 700;
  line-height: 1.08;
  letter-spacing: -0.01em;
  text-shadow: 0 2px 18px rgba(0, 0, 0, 0.55);
}

.ch-pm-banner-meta {
  margin: 10px 0 0;
  color: rgba(255, 255, 255, 0.72);
  font-size: 13px;
  font-variant-numeric: tabular-nums;
}

/* ----------------------------------------------------------------- steps -- */
.ch-pm-steps {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 18px;
  margin: 0 0 26px;
  padding: 0;
  list-style: none;
}

.ch-pm-step {
  display: flex;
  align-items: center;
  gap: 8px;
  padding-bottom: 2px;
  color: var(--pm-ink-3);
  font-size: 14px;
  font-weight: 700;
  white-space: nowrap;
  transition: color 0.2s ease;
}

.ch-pm-step .ch-icon { width: 18px; height: 18px; }

.ch-pm-step.is-done { color: var(--pm-ink-2); }

.ch-pm-step.is-active {
  color: var(--pm-ink);
}

/* The reference marks the live step with a yellow highlighter stroke. */
.ch-pm-step.is-active .ch-pm-step-label {
  box-shadow: inset 0 -7px 0 var(--pm-hl);
}

html[data-theme="dark"] .ch-pm-step.is-active .ch-pm-step-label {
  box-shadow: inset 0 -2px 0 var(--pm-hl);
}

.ch-pm-step-arrow {
  width: 52px;
  height: 1px;
  background: var(--pm-line-2);
}

.ch-pm-step-arrow::after {
  content: "";
  display: block;
  width: 6px;
  height: 6px;
  margin: -3px 0 0 46px;
  border-top: 1px solid var(--pm-line-2);
  border-right: 1px solid var(--pm-line-2);
  transform: rotate(45deg);
}

/* ---------------------------------------------------------------- layout -- */
/* Case on the left, everything you can do with it on the right. Below 900px
   the two stack — case first, buy bar under it — so on a phone the thumb
   never has to travel back up past the shelf. */
.ch-pm-main {
  display: grid;
  grid-template-columns: minmax(0, 1fr);
  gap: 18px;
  align-items: start;
}

@media (min-width: 901px) {
  .ch-pm-main {
    grid-template-columns: minmax(0, 1.5fr) minmax(0, 1fr);
    gap: 36px;
  }
}

/* ------------------------------------------------------------- left side -- */
/* Back-link to the gallery. It belongs to the page, not to the product
   column, so both columns can start level with each other. */
.ch-pm-explore {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  margin-bottom: 14px;
  color: var(--pm-ink);
  font-size: 13px;
  text-decoration: underline;
  text-underline-offset: 3px;
}

.ch-pm-explore:hover { color: var(--pm-ink); opacity: 0.7; }
.ch-pm-explore .ch-icon { width: 14px; height: 14px; }

/* The product plate stays a light studio surface in both themes — that is what
   the reference is, and the cartons are photographed on white. It turns into a
   dark theatre for the unbox itself, where the light-on-black effect art has to
   read. Everything inside the stage colours off these tokens, not the page's. */
.ch-pm-stage {
  --stage-bg:      #f5f5f5;
  --stage-ink:     rgba(0, 0, 0, 0.85);
  --stage-ink-2:   #666;
  --stage-surface: #fff;

  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  /* Full column width now, so a wider plate — 4:3 at 880px would be a tower.
     (A max-height cannot do this job: with an aspect ratio the browser would
     shrink the width to match instead of stretching the plate.) */
  aspect-ratio: 16 / 10;
  background: var(--stage-bg);
  overflow: hidden;
  transition: background-color 0.4s ease;
}

.ch-pm-stage.is-dark {
  --stage-bg:      #131416;
  --stage-ink:     #eceef0;
  --stage-ink-2:   #9aa0a6;
  --stage-surface: rgba(255, 255, 255, 0.12);
}

/* The case view — the product shot, and the only place boxes are picked. */
.ch-pm-hero-view {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  height: 100%;
}

/* The live case: a backdrop board and the boxes still standing on its steps.
   A box that has been opened is not drawn at all, so the shot IS the
   remaining stock — one pull, one carton fewer. */
.ch-bb-display {
  position: relative;
  /* The case is the product shot, so it fills the plate the way the
     reference's photo does — the photo's own margin is the breathing room. */
  width: min(90%, 700px);
  aspect-ratio: 3 / 2;
}

/* The photographed empty case; white shot multiplied onto the light stage so
   only the cardboard and its shadow remain. */
.ch-bb-display-case {
  position: absolute;
  inset: 0;
  z-index: 1;
  width: 100%;
  height: 100%;
  object-fit: contain;
  mix-blend-mode: multiply;
}

/* Optional printed backdrop board (admin upload), standing behind the case
   like a Pop Mart counter display. Hidden entirely without art — the plain
   case matches the original product shot. */
.ch-bb-display-board {
  position: absolute;
  right: 13%;
  bottom: 62%;
  left: 13%;
  z-index: 0;
  display: none;
  height: 52%;
  background-size: cover;
  background-position: center;
  border-radius: 3px 3px 0 0;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.2);
}

.ch-bb-display-board.has-art { display: block; }

/* Flipping to another case: every case looks much like the last one, so the
   swap animates. Without it the only thing that changes is a digit, and the
   click reads as ignored. */
@keyframes ch-bb-swap-next {
  from { opacity: 0.15; transform: translateX(7%); }
  to   { opacity: 1;    transform: none; }
}

@keyframes ch-bb-swap-prev {
  from { opacity: 0.15; transform: translateX(-7%); }
  to   { opacity: 1;    transform: none; }
}

.ch-bb-display.is-swap-next { animation: ch-bb-swap-next 0.3s cubic-bezier(0.22, 0.61, 0.36, 1); }
.ch-bb-display.is-swap-prev { animation: ch-bb-swap-prev 0.3s cubic-bezier(0.22, 0.61, 0.36, 1); }

/* One composited carton standing on a photo step. */
.ch-bb-display-boxes {
  position: absolute;
  inset: 0;
  z-index: 2;
}

/* The carton photo is trimmed to its own silhouette, so the element's box IS
   the carton: its bottom edge is the line the carton stands on, which is what
   the step geometry in blind-box.js positions. Depth order comes in as
   --bb-z (back step behind front step) rather than a plain z-index, so a
   lifted carton can jump in front of the row standing before it. */
.ch-bb-dbox {
  position: absolute;
  z-index: var(--bb-z, 1);
  aspect-ratio: 480 / 755;
  padding: 0;
  border: 0;
  background-color: #efe9dd;
  background-size: cover;
  background-position: center;
  box-shadow: 0 2px 5px rgba(0, 0, 0, 0.28);
  cursor: pointer;
  transform-origin: 50% 100%;
  transition: transform 0.18s cubic-bezier(0.22, 0.61, 0.36, 1), filter 0.18s ease;
}

/* Stock carton photo: drop it in as-is, standing on its own silhouette. */
.ch-bb-display-boxes.is-photo .ch-bb-dbox {
  background-color: transparent;
  background-size: contain;
  background-repeat: no-repeat;
  background-position: bottom center;
  box-shadow: none;
  /* Contact shadow on the step it stands on, not a drop shadow behind it.
     --bb-hue is the series' colour, set once on the component root. */
  filter: hue-rotate(var(--bb-hue, 0deg)) drop-shadow(0 3px 3px rgba(0, 0, 0, 0.22));
}

/* Reaching for a box: it lifts off its step, out in front of everything —
   above every --bb-z the packing order hands out. */
.ch-bb-dbox:hover,
.ch-bb-dbox:focus-visible {
  z-index: 900;
  transform: translateY(-5%) scale(1.03);
}

.ch-bb-display-boxes.is-photo .ch-bb-dbox:hover,
.ch-bb-display-boxes.is-photo .ch-bb-dbox:focus-visible {
  filter: hue-rotate(var(--bb-hue, 0deg)) drop-shadow(0 10px 8px rgba(0, 0, 0, 0.28));
}

.ch-bb-dbox.is-selected {
  z-index: 999;
  transform: translateY(-9%) scale(1.05);
}

.ch-bb-display-boxes.is-photo .ch-bb-dbox.is-selected {
  filter:
    hue-rotate(var(--bb-hue, 0deg))
    drop-shadow(0 0 1px rgba(0, 0, 0, 0.85))
    drop-shadow(0 0 6px rgba(0, 0, 0, 0.35))
    drop-shadow(0 14px 10px rgba(0, 0, 0, 0.3));
}

/* Which box this is. The case is meant to read as a packed shelf, so the
   numbers only show up on the carton the user is actually reaching for. */
.ch-bb-dbox-no {
  position: absolute;
  top: -20px;
  left: 50%;
  padding: 2px 7px;
  transform: translateX(-50%);
  background: #101113;
  color: #fff;
  font-size: 11px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  border-radius: 999px;
  opacity: 0;
  transition: opacity 0.18s ease;
  pointer-events: none;
}

.ch-bb-dbox:hover .ch-bb-dbox-no,
.ch-bb-dbox:focus-visible .ch-bb-dbox-no,
.ch-bb-dbox.is-selected .ch-bb-dbox-no { opacity: 1; }

/* How much of this case is still unopened, right on the product shot. */
.ch-bb-display-count {
  position: absolute;
  top: 2%;
  right: 1%;
  z-index: 5;
  padding: 5px 11px;
  background: #101113;
  color: #fff;
  font-size: 12px;
  font-weight: 700;
  font-variant-numeric: tabular-nums;
  border-radius: 999px;
  box-shadow: 0 2px 6px rgba(0, 0, 0, 0.28);
  white-space: nowrap;
}

/* Standing instruction under the case: what to do, and what is picked. */
.ch-pm-hero-cue {
  position: absolute;
  bottom: 18px;
  left: 50%;
  z-index: 4;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  margin: 0;
  padding: 7px 14px;
  transform: translateX(-50%);
  background: #101113;
  color: #fff;
  font-size: 12px;
  font-weight: 600;
  white-space: nowrap;
  pointer-events: none;
}

.ch-pm-hero-cue .ch-icon { width: 14px; height: 14px; }

/* Stage furniture ---------------------------------------------------------- */
/* The case pager. It sits on the case because the case is what it moves —
   series are switched from the strip underneath — and it is big enough to
   find without hunting. */
.ch-pm-stage-nav {
  position: absolute;
  top: 50%;
  z-index: 3;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 46px;
  height: 46px;
  margin-top: -23px;
  padding: 0;
  border: 0;
  background: var(--stage-surface);
  color: var(--stage-ink);
  cursor: pointer;
  border-radius: 999px;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.18);
  transition: opacity 0.15s ease, transform 0.15s ease;
}

.ch-pm-stage-nav:hover { transform: scale(1.08); }

.ch-pm-stage-nav:hover { color: var(--stage-ink); opacity: 0.75; }

.ch-pm-stage-nav:disabled {
  opacity: 0.3;
  cursor: default;
}

.ch-pm-stage-nav:disabled:hover { opacity: 0.3; }
.ch-pm-stage-nav.is-prev { left: 14px; }
.ch-pm-stage-nav.is-next { right: 14px; }
.ch-pm-stage-nav .ch-icon { width: 22px; height: 22px; }

.ch-pm-stage-back {
  position: absolute;
  top: 14px;
  left: 14px;
  z-index: 4;
  display: inline-flex;
  align-items: center;
  gap: 3px;
  padding: 6px 11px 6px 7px;
  border: 0;
  background: var(--stage-surface);
  color: var(--stage-ink);
  font-family: inherit;
  font-size: 12px;
  font-weight: 600;
  cursor: pointer;
  box-shadow: 0 1px 4px rgba(0, 0, 0, 0.12);
}

.ch-pm-stage-back .ch-icon { width: 14px; height: 14px; }

.ch-pm-stage-tag {
  position: absolute;
  top: 16px;
  right: 16px;
  z-index: 3;
  color: var(--stage-ink-2);
  font-size: 12px;
  font-weight: 600;
  letter-spacing: 0.04em;
}

.ch-pm-code {
  margin: 12px 0 0;
  color: var(--pm-ink-2);
  font-size: 12px;
  font-variant-numeric: tabular-nums;
  text-align: center;
}

/* Gallery thumbnails under the stage, one per configured set — the only
   control that changes series, now that the stage arrows walk the cases. */
.ch-pm-thumbs {
  display: flex;
  flex-wrap: wrap;
  /* Sits on the right edge, under the wallet, so the column has one clean
     right-hand rail instead of two competing left starts. */
  align-items: center;
  justify-content: flex-end;
  gap: 10px;
  margin-top: 4px;
}

/* Says out loud what the strip does; without it the covers read as decoration
   and people hunt for the series switch on the arrows instead. */
.ch-pm-thumbs-label {
  margin-right: auto;
  color: var(--pm-ink-2);
  font-size: 12px;
  font-weight: 600;
}

.ch-pm-thumb {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 12px 6px 6px;
  border: 1px solid var(--pm-line);
  color: var(--pm-ink);
  font-size: 12px;
  font-weight: 600;
  text-decoration: none;
  transition: border-color 0.15s ease;
}

.ch-pm-thumb:hover { border-color: var(--pm-line-2); color: var(--pm-ink); }
.ch-pm-thumb.is-active { border-color: var(--pm-ink); }

/* A slice of the series' key visual — wide, because that art is a banner and
   a 34px square of it reads as a dark blob. `cover` keeps the subject, which
   sits right of centre in these shots. */
.ch-pm-thumb-art {
  width: 62px;
  height: 34px;
  background-color: var(--pm-stage);
  background-repeat: no-repeat;
  background-size: cover;
  background-position: center right;
}

/* ------------------------------------------------------------ right side -- */
/* The buy bar: what it costs on the left, what you can press on the right,
   the small print across the bottom. Collapses to one column on a phone. */
.ch-pm-buy {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.1fr);
  gap: 16px 28px;
  align-items: start;
}

.ch-pm-buy-info {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.ch-pm-buy-actions {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

/* Small print left, balance right. */
.ch-pm-buy-foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 10px 18px;
  grid-column: 1 / -1;
  padding-top: 14px;
  border-top: 1px solid var(--pm-line);
}

/* Sitting in the right-hand rail instead of under the case: too narrow to be
   a bar, so it goes back to being a column. */
@media (min-width: 901px) {
  .ch-pm-buy {
    grid-template-columns: minmax(0, 1fr);
    gap: 12px;
  }

  .ch-pm-buy-foot { gap: 8px 14px; }
  .ch-pm-buy-foot .ch-pm-wallet { flex-basis: 100%; margin-left: 0; }
}


.ch-pm-price {
  margin: 2px 0 0;
  color: var(--pm-red);
  font-size: 22px;
  font-weight: 600;
  font-variant-numeric: tabular-nums;
}

.ch-pm-price-unit {
  color: var(--pm-ink-2);
  font-size: 13px;
  font-weight: 400;
}

.ch-pm-promo {
  display: inline-flex;
  align-items: center;
  align-self: flex-start;
  gap: 5px;
  margin: 0;
  padding: 3px 9px;
  background: color-mix(in srgb, var(--pm-red) 10%, transparent);
  color: var(--pm-red);
  font-size: 12px;
  font-weight: 500;
}

.ch-pm-promo .ch-icon { width: 13px; height: 13px; }

@keyframes ch-bb-bump {
  0%   { background: color-mix(in srgb, var(--pm-hl) 55%, transparent); }
  100% { background: transparent; }
}

.ch-pm-ship.is-bumped { animation: ch-bb-bump 0.7s ease-out; }

.ch-pm-ship {
  margin: 0 0 8px;
  color: var(--pm-ink-2);
  font-size: 12px;
  font-variant-numeric: tabular-nums;
}

/* Buttons — square corners and full width, exactly like the reference. */
.ch-pm-btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  width: 100%;
  min-height: 46px;
  padding: 12px 18px;
  border: 1px solid transparent;
  border-radius: 0;
  font-family: inherit;
  font-size: 14px;
  font-weight: 700;
  text-align: center;
  text-decoration: none;
  cursor: pointer;
  transition: opacity 0.15s ease, background-color 0.15s ease, color 0.15s ease;
}

.ch-pm-btn .ch-icon { width: 16px; height: 16px; }

.ch-pm-btn-primary {
  background: var(--pm-btn);
  color: var(--pm-btn-ink);
}

.ch-pm-btn-primary:hover { color: var(--pm-btn-ink); opacity: 0.85; }

.ch-pm-btn-ghost {
  border-color: var(--pm-ink);
  background: transparent;
  color: var(--pm-ink);
}

.ch-pm-btn-ghost:hover { color: var(--pm-ink); background: color-mix(in srgb, var(--pm-ink) 6%, transparent); }

.ch-pm-btn:disabled,
.ch-pm-btn[disabled] {
  opacity: 0.35;
  cursor: not-allowed;
}

.ch-pm-bulk {
  display: flex;
  gap: 8px;
}

.ch-pm-bulk select {
  flex: 0 0 108px;
  padding: 0 8px;
  border: 1px solid var(--pm-ink);
  border-radius: 0;
  background: transparent;
  color: var(--pm-ink);
  font-family: inherit;
  font-size: 13px;
}

/* Kept in the foot row, so no bottom margin of its own. */
.ch-pm-note {
  margin: 4px 0 0;
  color: var(--pm-ink);
  font-size: 12px;
  font-weight: 300;
  text-align: center;
}

.ch-pm-howto {
  margin: 0 auto;
  padding: 0;
  border: 0;
  background: none;
  color: var(--pm-ink-2);
  font-family: inherit;
  font-size: 12px;
  font-weight: 500;
  text-decoration: underline;
  text-underline-offset: 3px;
  cursor: pointer;
}

.ch-pm-howto:hover { color: var(--pm-ink); }

/* The foot row draws the only divider now. */
.ch-pm-wallet {
  margin-left: auto;
  display: flex;
  gap: 18px;
  color: var(--pm-ink-2);
  font-size: 13px;
  font-variant-numeric: tabular-nums;
}

.ch-pm-wallet-item {
  display: inline-flex;
  align-items: center;
  gap: 5px;
}

.ch-pm-wallet .ch-icon { width: 15px; height: 15px; }

/* Every box of every case opened, and the stock is spent — said over the
   empty case, which by then is the whole picture anyway. */
.ch-bb-soldout {
  position: absolute;
  top: 50%;
  left: 50%;
  z-index: 6;
  margin: 0;
  padding: 12px 18px;
  transform: translate(-50%, -50%);
  background: rgba(255, 255, 255, 0.92);
  color: rgba(0, 0, 0, 0.7);
  font-size: 14px;
  text-align: center;
  box-shadow: 0 2px 10px rgba(0, 0, 0, 0.12);
}

/* =============================================================================
   Unbox animation

   Box dimensions drive every face transform, so resizing the box is a matter
   of changing --bb-w / --bb-h / --bb-d.
   ============================================================================= */
.ch-bb-scene {
  --bb-w: 150px;   /* width  */
  --bb-h: 200px;   /* height */
  --bb-d: 110px;   /* depth  */
  --bb-lid-h: 30px;
  --bb-over: 4px;  /* how far the lid overhangs the base on each side */
  --bb-lid-fly: 230px; /* how far the lid travels before it fades out */
  --bb-glow: var(--color-primary);
  /* Celebration strength, scaled by the drawn card's rarity tier. A common
     pull should not get the same fireworks as the chase card. */
  --bb-fx-op: 0.4;
  --bb-fx-scale: 0.85;

  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  perspective: 1100px;
  perspective-origin: 50% 42%;
}

/* ------------------------------------------------------------- box shell -- */
.ch-bb-float {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 0;
  height: 0;
  transform-style: preserve-3d;
  animation: ch-bb-hover 4s ease-in-out infinite;
}

.ch-bb-box {
  position: absolute;
  top: calc(var(--bb-h) / -2);
  left: calc(var(--bb-w) / -2);
  width: var(--bb-w);
  height: var(--bb-h);
  transform-style: preserve-3d;
  /* Three-quarter view so the lid lift and the depth both read. */
  transform: rotateX(-12deg) rotateY(-26deg);
  transition: transform 0.6s cubic-bezier(0.22, 0.61, 0.36, 1),
              opacity 0.5s ease 0.25s;
}

.ch-bb-f {
  position: absolute;
  inset: 0;
  background-color: #efe9dd;
  background-image: var(--bb-art, none);
  background-size: cover;
  background-position: center;
  backface-visibility: hidden;
  box-shadow: inset 0 0 0 1px rgba(0, 0, 0, 0.07);
}

.ch-bb-f-front  { transform: translateZ(calc(var(--bb-d) / 2)); }
.ch-bb-f-back   { transform: rotateY(180deg) translateZ(calc(var(--bb-d) / 2)); }

/* Sides carry the narrow side-panel print, not a squashed front panel. */
.ch-bb-f-left,
.ch-bb-f-right {
  width: var(--bb-d);
  left: calc((var(--bb-w) - var(--bb-d)) / 2);
  background-image: var(--bb-art-side, var(--bb-art, none));
}

.ch-bb-f-left   { transform: rotateY(-90deg) translateZ(calc(var(--bb-w) / 2)); }
.ch-bb-f-right  { transform: rotateY(90deg)  translateZ(calc(var(--bb-w) / 2)); }

/* Side faces read as shaded so the box has real volume. */
.ch-bb-f-left,
.ch-bb-f-back   { filter: brightness(0.74); }
.ch-bb-f-right  { filter: brightness(0.88); }

.ch-bb-f-bottom {
  height: var(--bb-d);
  top: calc((var(--bb-h) - var(--bb-d)) / 2);
  transform: rotateX(-90deg) translateZ(calc(var(--bb-h) / 2));
  filter: brightness(0.55);
}

/* The dark opening revealed once the lid is gone. */
.ch-bb-f-inner {
  height: var(--bb-d);
  top: calc((var(--bb-h) - var(--bb-d)) / 2);
  transform: rotateX(90deg) translateZ(calc(var(--bb-h) / 2 - 12px));
  background-image: none;
  background-color: #17140f;
  box-shadow: inset 0 0 26px rgba(0, 0, 0, 0.9);
}

/* -------------------------------------------------------------------- lid -- */
.ch-bb-lid {
  position: absolute;
  top: calc(var(--bb-lid-h) / -2);
  left: calc(var(--bb-over) * -1);
  width: calc(var(--bb-w) + var(--bb-over) * 2);
  height: var(--bb-lid-h);
  transform-style: preserve-3d;
}

.ch-bb-rim {
  background-image: var(--bb-art-side, var(--bb-art, none));
}

.ch-bb-rim-front { transform: translateZ(calc(var(--bb-d) / 2 + var(--bb-over))); }
.ch-bb-rim-back  { transform: rotateY(180deg) translateZ(calc(var(--bb-d) / 2 + var(--bb-over))); }

.ch-bb-rim-left,
.ch-bb-rim-right {
  width: calc(var(--bb-d) + var(--bb-over) * 2);
  left: calc((var(--bb-w) - var(--bb-d)) / 2);
}

.ch-bb-rim-left  { transform: rotateY(-90deg) translateZ(calc(var(--bb-w) / 2 + var(--bb-over))); }
.ch-bb-rim-right { transform: rotateY(90deg)  translateZ(calc(var(--bb-w) / 2 + var(--bb-over))); }

.ch-bb-rim-left,
.ch-bb-rim-back  { filter: brightness(0.74); }
.ch-bb-rim-right { filter: brightness(0.88); }

.ch-bb-f-top {
  width: calc(var(--bb-d) + var(--bb-over) * 2);
  height: calc(var(--bb-d) + var(--bb-over) * 2);
  left: calc((var(--bb-w) - var(--bb-d)) / 2);
  top: calc((var(--bb-lid-h) - var(--bb-d)) / 2 - var(--bb-over));
  transform: rotateX(90deg) translateZ(calc(var(--bb-lid-h) / 2));
  filter: brightness(1.06);
}

/* ------------------------------------------------------------ ground + fx -- */
.ch-bb-shadow {
  position: absolute;
  top: 78%;
  left: 50%;
  width: 180px;
  height: 24px;
  transform: translateX(-50%);
  border-radius: 50%;
  background: radial-gradient(ellipse at center, rgba(0, 0, 0, 0.28), transparent 70%);
  animation: ch-bb-shadow-pulse 4s ease-in-out infinite;
}

.ch-bb-fx {
  position: absolute;
  top: 50%;
  left: 50%;
  width: 460px;
  height: 460px;
  transform: translate(-50%, -50%) scale(0.35);
  background-position: center;
  background-size: contain;
  background-repeat: no-repeat;
  /* Assets are drawn on pure black, so screen blending keys the black out. */
  mix-blend-mode: screen;
  opacity: 0;
  pointer-events: none;
}

.ch-bb-fx-rays     { z-index: 1; }
.ch-bb-fx-sparkles { z-index: 3; }

/* The pop itself. Both layers are drawn in the pulled card's rarity colour, so
   an SSR does not just get *more* of the same gold burst as a common — it reads
   as a different colour of light before the card is even legible. */
.ch-bb-flash {
  position: absolute;
  inset: 0;
  z-index: 2;
  background: radial-gradient(circle at 50% 47%,
              #fff 0%,
              color-mix(in srgb, var(--bb-glow) 72%, transparent) 26%,
              transparent 60%);
  opacity: 0;
  pointer-events: none;
}

.ch-bb-ring {
  position: absolute;
  top: 50%;
  left: 50%;
  z-index: 2;
  width: 120px;
  height: 120px;
  margin: -60px 0 0 -60px;
  border: 2px solid var(--bb-glow);
  border-radius: 50%;
  opacity: 0;
  pointer-events: none;
}

.ch-bb-scene.is-opening .ch-bb-flash { animation: ch-bb-flash 0.5s ease-out both; }
.ch-bb-scene.is-opening .ch-bb-ring  { animation: ch-bb-ring 0.9s cubic-bezier(0.16, 0.72, 0.24, 1) both; }

@keyframes ch-bb-flash {
  0%   { opacity: 0;                                transform: scale(0.45); }
  12%  { opacity: calc(0.85 * var(--bb-fx-op));     transform: scale(1); }
  100% { opacity: 0;                                transform: scale(1.22); }
}

@keyframes ch-bb-ring {
  0%   { opacity: 0;                            transform: scale(0.3);  border-width: 3px; }
  14%  { opacity: calc(0.95 * var(--bb-fx-op)); }
  100% { opacity: 0;                            transform: scale(4.4);  border-width: 1px; }
}

/* Rarity wash behind the card — colour comes from the drawn card's tier. */
.ch-bb-scene::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: 340px;
  height: 340px;
  transform: translate(-50%, -50%) scale(0.4);
  border-radius: 50%;
  background: radial-gradient(circle, var(--bb-glow), transparent 62%);
  opacity: 0;
  pointer-events: none;
  transition: opacity 0.5s ease, transform 0.6s ease;
}

/* -------------------------------------------------------------- the card -- */
.ch-bb-card {
  position: absolute;
  top: 50%;
  left: 50%;
  /* Above both effect layers: the pull is the point, the fireworks are not. */
  z-index: 5;
  width: 148px;
  aspect-ratio: var(--ch-card-aspect, 9 / 16);
  /* Starts small, low and face-away: it is "inside" the box. */
  transform: translate(-50%, -34%) scale(0.34) rotateY(180deg);
  transform-style: preserve-3d;
  opacity: 0;
  pointer-events: none;
}

.ch-bb-card-side {
  position: absolute;
  inset: 0;
  border-radius: var(--radius-md);
  background-color: var(--color-card);
  background-size: cover;
  background-position: center;
  backface-visibility: hidden;
  overflow: hidden;
  box-shadow: 0 18px 38px rgba(0, 0, 0, 0.34);
}

.ch-bb-card-back {
  transform: rotateY(180deg);
  background-image: var(--ch-card-back);
}

.ch-bb-card-foil {
  position: absolute;
  inset: 0;
  background-position: center;
  background-size: cover;
  mix-blend-mode: screen;
  opacity: 0;
}

/* ------------------------------------------------------------- timeline --- */

/* 1. Anticipation — the box rattles, harder as it goes. */
.ch-bb-scene.is-shaking .ch-bb-float {
  animation: ch-bb-rattle 0.42s ease-in-out infinite;
}

.ch-bb-scene.is-shaking .ch-bb-shadow {
  animation: ch-bb-shadow-tense 0.42s ease-in-out infinite;
}

/* 2. Pop — lid tears off and spins away, light floods out. */
.ch-bb-scene.is-opening .ch-bb-float { animation: ch-bb-recoil 0.5s ease-out both; }
.ch-bb-scene.is-opening .ch-bb-lid   { animation: ch-bb-lid-off 0.85s cubic-bezier(0.2, 0.7, 0.3, 1) both; }
.ch-bb-scene.is-opening .ch-bb-fx-rays     { animation: ch-bb-rays 1.5s ease-out both; }
.ch-bb-scene.is-opening .ch-bb-fx-sparkles { animation: ch-bb-sparkles 1.5s ease-out both; }

/* 3. Rise — the card lifts out of the box and turns face-up. */
.ch-bb-scene.is-revealing .ch-bb-card {
  animation: ch-bb-card-rise 0.95s cubic-bezier(0.16, 0.72, 0.24, 1) both;
}

/* Once the card is out, the emptied carton drops away entirely — held at a
   low opacity it only read as a stray orange polygon under the card. */
.ch-bb-scene.is-revealing .ch-bb-box,
.ch-bb-scene.is-revealed  .ch-bb-box {
  transform: rotateX(-12deg) rotateY(-26deg) translateY(52px) scale(0.78);
  opacity: 0;
}

.ch-bb-scene.is-revealing::after,
.ch-bb-scene.is-revealed::after {
  opacity: calc(0.42 * var(--bb-fx-op));
  transform: translate(-50%, -50%) scale(1);
}

/* 4. Settle — card floats, foil sweeps across it. */
.ch-bb-scene.is-revealed .ch-bb-card {
  transform: translate(-50%, -62%) scale(1) rotateY(0deg);
  opacity: 1;
  animation: ch-bb-card-bob 3.6s ease-in-out infinite;
}

.ch-bb-scene.is-revealed .ch-bb-card-foil {
  animation: ch-bb-foil 2.6s ease-in-out 0.1s 2;
}

.ch-bb-scene.is-revealed .ch-bb-shadow,
.ch-bb-scene.is-revealed .ch-bb-float {
  /* An animation outranks a plain declaration, so the idle loops have to be
     switched off, not just overridden — otherwise the ground shadow keeps
     pulsing under a card that no longer has a box beneath it. */
  animation: none;
}

.ch-bb-scene.is-revealed .ch-bb-shadow { opacity: 0; }

/* Higher tiers get a louder celebration. */
.ch-bb-scene[data-tier="1"] { --bb-fx-op: 0.5;  --bb-fx-scale: 0.95; }
.ch-bb-scene[data-tier="2"] { --bb-fx-op: 0.62; --bb-fx-scale: 1.05; }
.ch-bb-scene[data-tier="3"] { --bb-fx-op: 0.74; --bb-fx-scale: 1.15; }
.ch-bb-scene[data-tier="4"] { --bb-fx-op: 0.86; --bb-fx-scale: 1.28; }

.ch-bb-scene[data-tier="3"] .ch-bb-fx-rays,
.ch-bb-scene[data-tier="4"] .ch-bb-fx-rays { filter: saturate(1.35) brightness(1.15); }
.ch-bb-scene[data-tier="4"].is-revealed .ch-bb-card-side { box-shadow: 0 18px 44px color-mix(in srgb, var(--bb-glow) 55%, transparent); }

/* ------------------------------------------------------------- keyframes --- */
@keyframes ch-bb-hover {
  0%, 100% { transform: translateY(0); }
  50%      { transform: translateY(-9px); }
}

@keyframes ch-bb-shadow-pulse {
  0%, 100% { opacity: 0.85; transform: translateX(-50%) scale(1); }
  50%      { opacity: 0.62; transform: translateX(-50%) scale(0.9); }
}

@keyframes ch-bb-rattle {
  0%, 100% { transform: translate3d(0, 0, 0) rotate(0deg); }
  20%      { transform: translate3d(-6px, 2px, 0) rotate(-2.4deg); }
  45%      { transform: translate3d(5px, -3px, 0) rotate(2deg); }
  70%      { transform: translate3d(-4px, 3px, 0) rotate(-1.6deg); }
}

@keyframes ch-bb-shadow-tense {
  0%, 100% { transform: translateX(-50%) scale(1);    opacity: 0.85; }
  50%      { transform: translateX(-52%) scale(1.08); opacity: 0.95; }
}

@keyframes ch-bb-recoil {
  0%   { transform: translateY(0) scale(1); }
  25%  { transform: translateY(6px) scale(1.06, 0.94); }
  100% { transform: translateY(0) scale(1); }
}

@keyframes ch-bb-lid-off {
  0% {
    transform: translateY(0) translateZ(0) rotateZ(0deg) rotateX(0deg);
    opacity: 1;
  }
  35% {
    transform: translateY(calc(var(--bb-lid-fly) * -0.39)) translateZ(30px) rotateZ(-9deg) rotateX(12deg);
    opacity: 1;
  }
  100% {
    transform: translateY(calc(var(--bb-lid-fly) * -1)) translateZ(150px) rotateZ(-46deg) rotateX(64deg);
    opacity: 0;
  }
}

@keyframes ch-bb-rays {
  0%   { opacity: 0;                            transform: translate(-50%, -50%) scale(calc(0.2  * var(--bb-fx-scale))) rotate(0deg); }
  18%  { opacity: calc(0.95 * var(--bb-fx-op)); transform: translate(-50%, -50%) scale(calc(1.05 * var(--bb-fx-scale))) rotate(9deg); }
  100% { opacity: 0;                            transform: translate(-50%, -50%) scale(calc(1.5  * var(--bb-fx-scale))) rotate(26deg); }
}

@keyframes ch-bb-sparkles {
  0%   { opacity: 0;                        transform: translate(-50%, -50%) scale(calc(0.3  * var(--bb-fx-scale))); }
  22%  { opacity: calc(1 * var(--bb-fx-op)); transform: translate(-50%, -50%) scale(calc(1    * var(--bb-fx-scale))); }
  100% { opacity: 0;                        transform: translate(-50%, -50%) scale(calc(1.45 * var(--bb-fx-scale))); }
}

@keyframes ch-bb-card-rise {
  0% {
    transform: translate(-50%, -34%) scale(0.34) rotateY(180deg);
    opacity: 0;
  }
  22% {
    opacity: 1;
  }
  62% {
    transform: translate(-50%, -78%) scale(1.06) rotateY(28deg);
    opacity: 1;
  }
  100% {
    transform: translate(-50%, -62%) scale(1) rotateY(0deg);
    opacity: 1;
  }
}

@keyframes ch-bb-card-bob {
  0%, 100% { transform: translate(-50%, -62%) scale(1) rotateY(0deg); }
  50%      { transform: translate(-50%, -66%) scale(1) rotateY(6deg); }
}

@keyframes ch-bb-foil {
  0%   { opacity: 0;    background-position: -60% center; }
  40%  { opacity: 0.55; }
  100% { opacity: 0;    background-position: 160% center; }
}

@keyframes ch-bb-pop {
  0%   { opacity: 0; transform: scale(0.8) translateY(10px); }
  100% { opacity: 1; transform: scale(1) translateY(0); }
}

/* ---------------------------------------------------------------- reveal -- */
.ch-pm-reveal {
  position: absolute;
  right: 0;
  bottom: 16px;
  left: 0;
  z-index: 5;
  text-align: center;
  animation: ch-bb-pop 0.45s cubic-bezier(0.18, 0.89, 0.32, 1.28) both;
}

.ch-pm-reveal-title {
  margin: 0 0 5px;
  color: var(--stage-ink);
  font-size: 16px;
  font-weight: 700;
  line-height: 1.3;
}

.ch-pm-reveal-rarity {
  display: inline-block;
  padding: 2px 10px;
  background: color-mix(in srgb, var(--bb-rarity, var(--color-primary)) 16%, transparent);
  color: var(--bb-rarity, var(--color-primary));
  font-size: 11px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
}

/* ------------------------------------------------------ bulk-open spread -- */
.ch-bb-haul {
  position: absolute;
  inset: 0;
  z-index: 3;
  display: flex;
  flex-wrap: wrap;
  align-content: center;
  justify-content: center;
  gap: 10px;
  padding: 24px;
  overflow-y: auto;
}

/* Shrink the spread as the haul grows so ten pulls still fit the stage
   without turning it into a scroll box. */
.ch-bb-haul { --bb-haul-w: 96px; }
.ch-bb-haul[data-n="5"],
.ch-bb-haul[data-n="6"] { --bb-haul-w: 72px; }
.ch-bb-haul[data-n="7"],
.ch-bb-haul[data-n="8"],
.ch-bb-haul[data-n="9"],
.ch-bb-haul[data-n="10"] { --bb-haul-w: 62px; }

.ch-bb-haul-item {
  width: var(--bb-haul-w);
  margin: 0;
  text-align: center;
  opacity: 0;
}

.ch-bb-scene.is-revealing .ch-bb-haul-item,
.ch-bb-scene.is-revealed .ch-bb-haul-item {
  /* Staggered so the haul lands card by card instead of all at once. The
     settled state is also declared statically: if the animation never runs —
     a throttled background tab, a dropped frame budget — the pulls still have
     to be on screen. */
  opacity: 1;
  animation: ch-bb-pop 0.42s cubic-bezier(0.18, 0.89, 0.32, 1.28) both;
  animation-delay: calc(var(--bb-i) * 70ms);
}

.ch-bb-haul-thumb {
  display: block;
  width: 100%;
  aspect-ratio: var(--ch-card-aspect, 9 / 16);
  border-radius: var(--radius-sm);
  background-color: var(--color-card);
  background-size: cover;
  background-position: center;
  box-shadow: 0 6px 16px rgba(0, 0, 0, 0.32);
}

.ch-bb-haul-name {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 2;
  margin-top: 5px;
  overflow: hidden;
  color: var(--stage-ink);
  font-size: 10px;
  font-weight: 600;
  line-height: 1.3;
}

.ch-bb-haul-rarity {
  display: block;
  color: var(--bb-glow, var(--stage-ink-2));
  font-size: 9px;
  font-weight: 700;
  text-transform: uppercase;
}

/* =============================================================================
   Line-up strip + spec table
   ============================================================================= */
.ch-pm-section-title {
  margin: 0;
  font-size: 15px;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
}

.ch-pm-lineup,
.ch-pm-detail {
  margin-top: 46px;
  padding-top: 18px;
  border-top: 1px solid var(--pm-line);
}

.ch-pm-lineup-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 12px;
  margin-bottom: 18px;
}

.ch-pm-collected {
  color: var(--pm-ink-2);
  font-size: 12px;
  font-variant-numeric: tabular-nums;
}

/* One row that scrolls sideways, the way the reference lists its figures. */
.ch-pm-lineup-row {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: 132px;
  gap: 16px;
  padding-bottom: 12px;
  overflow-x: auto;
  scrollbar-width: thin;
}

.ch-pm-lineup-item {
  margin: 0;
  text-align: center;
}

.ch-pm-lineup-thumb {
  position: relative;
  width: 100%;
  aspect-ratio: var(--ch-card-aspect, 9 / 16);
  background-color: var(--pm-stage);
  overflow: hidden;
}

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

.ch-pm-lineup-name {
  display: block;
  margin-top: 8px;
  color: var(--pm-ink);
  font-size: 12px;
  font-weight: 500;
  line-height: 1.35;
}

.ch-pm-lineup-name em {
  color: var(--pm-red);
  font-style: normal;
  font-weight: 600;
}

/* Not yet collected reads as a faded silhouette; collected pops. */
.ch-pm-lineup-item:not(.is-owned) .ch-pm-lineup-thumb {
  filter: grayscale(1);
  opacity: 0.4;
}

/* On a dark page 40% leaves nothing to look at. */
html[data-theme="dark"] .ch-pm-lineup-item:not(.is-owned) .ch-pm-lineup-thumb {
  opacity: 0.58;
}

.ch-pm-lineup-check {
  position: absolute;
  right: 5px;
  bottom: 5px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 19px;
  height: 19px;
  border-radius: 50%;
  background: var(--pm-ink);
  color: var(--pm-surface);
}

.ch-pm-lineup-check .ch-icon { width: 12px; height: 12px; }

.ch-pm-detail-list {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: 2px 40px;
  margin: 0;
}

.ch-pm-detail-list > div {
  display: flex;
  gap: 10px;
  padding: 9px 0;
  border-bottom: 1px solid var(--pm-line);
}

.ch-pm-detail-list dt {
  flex: 0 0 130px;
  color: var(--pm-ink-2);
  font-size: 12px;
  font-weight: 500;
  letter-spacing: 0.03em;
  text-transform: uppercase;
}

.ch-pm-detail-list dd {
  margin: 0;
  color: var(--pm-ink);
  font-size: 13px;
  font-weight: 300;
}

/* ----------------------------------------------------------- help modal -- */
.ch-pm-help-body ol {
  margin: 0;
  padding-left: 20px;
}

.ch-pm-help-body li {
  margin-bottom: 10px;
  color: var(--color-text-secondary);
  font-size: 13px;
  line-height: 1.6;
}

.ch-pm-help-body strong { color: var(--color-text-primary); }

.ch-pm-help-cost {
  margin: 14px 0 0;
  padding-top: 12px;
  border-top: 1px solid var(--color-border-light);
  color: var(--color-text-muted);
  font-size: 12px;
}

/* ------------------------------------------------------------ responsive -- */
@media (max-width: 760px) {
  /* One column all the way down, and the buy bar stops being a bar. */
  .ch-pm-buy {
    grid-template-columns: minmax(0, 1fr);
    gap: 14px;
  }

  .ch-pm-buy-foot {
    justify-content: center;
    text-align: center;
  }

  .ch-pm-buy-foot .ch-pm-note { flex: 1 0 100%; }
  .ch-pm-buy-foot .ch-pm-wallet { margin-left: 0; }
  .ch-pm-thumbs { justify-content: center; }
  /* Centred covers need the label on its own line, or `margin-right: auto`
     shoves the first one off to the right. */
  .ch-pm-thumbs-label { flex-basis: 100%; margin-right: 0; text-align: center; }

  .ch-pm-steps { gap: 10px; }
  .ch-pm-step-arrow { width: 28px; }
  .ch-pm-step-arrow::after { margin-left: 22px; }

  /* Thumb-sized targets for the two things you tap on the shelf. */
  .ch-pm-stage-nav {
    width: 40px;
    height: 40px;
    margin-top: -20px;
  }

  .ch-pm-stage-nav .ch-icon { width: 20px; height: 20px; }
}

@media (max-width: 520px) {
  .ch-pm-shell { padding-top: 16px; }

  /* Keep the three beats readable on a phone — the strip is the whole point
     of the page's top edge. Shrink it instead of dropping the labels. */
  .ch-pm-steps { gap: 4px; }
  .ch-pm-step { gap: 4px; font-size: 11px; }
  .ch-pm-step .ch-icon { width: 14px; height: 14px; }
  .ch-pm-step.is-active .ch-pm-step-label { box-shadow: inset 0 -5px 0 var(--pm-hl); }
  .ch-pm-step-arrow { width: 16px; }
  .ch-pm-step-arrow::after { width: 5px; height: 5px; margin: -3px 0 0 10px; }

  /* The shelf is the whole screen here, so give it more of the width and
     less air above and below. */
  .ch-pm-stage { aspect-ratio: 5 / 4; }
  .ch-bb-display { width: 96%; }
  .ch-pm-hero-cue { bottom: 10px; padding: 6px 12px; font-size: 11px; }
  .ch-bb-display-count { padding: 4px 9px; font-size: 11px; }
  .ch-pm-stage-tag { font-size: 11px; }

  /* Price stays the loudest thing in the buy bar on a small screen. */
  .ch-pm-price { font-size: 26px; }
  .ch-pm-ship { font-size: 12px; line-height: 1.6; }
  .ch-pm-wallet { gap: 14px; }

  /* On a phone the art has no room to breathe beside the name, so the scrim
     goes vertical and the title sits over the bottom of it. */
  .ch-pm-banner {
    align-items: flex-end;
    min-height: 150px;
    margin-bottom: 16px;
    padding: 18px;
    background-position: center;
  }

  .ch-pm-banner::before {
    background: linear-gradient(180deg,
                rgba(8, 9, 10, 0.25) 0%,
                rgba(8, 9, 10, 0.72) 55%,
                rgba(8, 9, 10, 0.94) 100%);
  }

  .ch-pm-banner-text { max-width: 100%; }
  .ch-pm-banner-meta { margin-top: 6px; font-size: 12px; }

  /* Thumb-sized cartons: the numbers stay on so a tap target is identifiable
     without the hover the phone never gets. */
  .ch-bb-dbox-no { top: -16px; padding: 1px 6px; font-size: 10px; opacity: 1; }

  .ch-bb-scene {
    --bb-w: 116px;
    --bb-h: 152px;
    --bb-d: 84px;
    --bb-lid-h: 24px;
    /* A square phone-sized stage clips anything past ~150px of travel. */
    --bb-lid-fly: 140px;
  }

  .ch-bb-card { width: 112px; }
  .ch-bb-haul { --bb-haul-w: 58px; }
  .ch-pm-lineup-row { grid-auto-columns: 108px; }
  .ch-pm-detail-list dt { flex-basis: 110px; }
}

/* The JS also short-circuits its timeline here; this is the CSS backstop so no
   looping idle animation survives. */
@media (prefers-reduced-motion: reduce) {
  .ch-bb-dbox { transition: none; }
  .ch-bb-haul-item { animation: none !important; opacity: 1; }

  .ch-bb-float,
  .ch-bb-shadow,
  .ch-bb-scene.is-shaking .ch-bb-float,
  .ch-bb-scene.is-shaking .ch-bb-shadow,
  .ch-bb-scene.is-opening .ch-bb-float,
  .ch-bb-scene.is-revealed .ch-bb-card,
  .ch-bb-scene.is-revealed .ch-bb-card-foil,
  .ch-pm-reveal {
    animation: none !important;
  }

  /* Lid and effects still need their end state, just without the travel. */
  .ch-bb-scene.is-opening .ch-bb-lid { opacity: 0; animation: none !important; }
  .ch-bb-scene.is-opening .ch-bb-fx  { animation: none !important; }
  .ch-bb-flash,
  .ch-bb-ring { display: none; }
  .ch-bb-scene.is-revealing .ch-bb-card,
  .ch-bb-scene.is-revealed .ch-bb-card {
    transform: translate(-50%, -62%) scale(1) rotateY(0deg);
    opacity: 1;
    animation: none !important;
  }
}
