/* rip/binder-chrome.css — THE BOOK.
 *
 * Every class rip/binder-engine.js emits for the BOOK itself: the shelf, the
 * cover, the contents sheet, the spread, the spine and its rings, a page, a
 * pocket and its caption, the pager, the gaps switch and the turn animation.
 *
 * ⚠⚠ WHY IT IS ITS OWN FILE. rip/account.css restyles bare `h1, h2, h3` and
 * `html, body` and carries a whole second token set, so it can NEVER be linked
 * on a universe page — and every class the binder paints was defined only in
 * there. A universe binder loading account.css would inherit the member area's
 * typography and grounds; a universe binder loading neither would mount into
 * undefined CSS. This sheet is the third answer: the book, and nothing but the
 * book.
 *
 * ⚠ ZERO BARE-ELEMENT SELECTORS, AND THAT IS ASSERTED, NOT INTENDED. Every
 * selector here starts with a class, an id, a pseudo or an attribute, so
 * dropping it onto a page that uses none of these class names repaints exactly
 * nothing — the same property that makes rip-ui.css safe to add anywhere.
 *
 * ⚠ EXTRACTED BY A PREDICATE OVER PARSED RULES, NEVER A LINE RANGE. The
 * selector-token test is the whole cut, so every at-rule arm containing a
 * binder rule came across by construction — including the @media(max-width:
 * 760px) block, which is Aaron's "make the 9 cards in the binder bigger" fix
 * and is exactly what a hand-typed range misses, and the reduced-motion arm's
 * .gapsw-knob{transition:none}. rip/CLAUDE.md already records what removing CSS
 * line-by-line costs: brace depth -4, and a rule silently swallowed.
 *
 * ⚠ LINKED IMMEDIATELY AFTER rip-ui.css AND BEFORE account.css, in all three
 * hosts that emit that pair (rip/lib/member-page.php, rip/u.php,
 * rip/account.php) — never through $opts['head'], which emits after
 * rip-a11y.css. Order is checked in the rendered HTML by
 * rip/admin/cli/binder-dom-check.js, not assumed.
 */

/* ── THE TOKENS THIS SHEET CONSUMES, ALIASED ONTO rip-ui.css ────────────────
   ⚠⚠ WITHOUT THIS THE SHEET IS NOT SELF-SUFFICIENT, AND S4 SHIPPED IT THAT WAY.
   The extraction asserted ZERO bare-element selectors — which is necessary and
   is NOT sufficient. Ten of the nineteen custom properties it reads (--text,
   --text-2, --text-3, --surface-2, --surface-3, --border, --border-soft,
   --accent, --accent-soft, --gold) were defined only in account.css's :root,
   and a universe page does not load account.css — that is the entire reason
   this file exists. Every measurement was green; the picture was not. A binder
   whose colours all resolve to nothing measures exactly like one that works.

   ⚠ IT CANNOT OVERRIDE THE MEMBER AREA. This sheet is linked BEFORE account.css
   on all three member hosts, so account.css's identical declarations win any
   tie there and the member binder is bit-for-bit unaffected (verified: 0 of
   10,988 computed-style rows). On a universe page these are the only ones.

   ⚠ THE VALUES ARE COPIED FROM account.css, NOT CHOSEN. Two sheets aliasing the
   same names onto different rip-ui tokens is worse than one sheet missing them.

   Not listed here on purpose: --tc and --bdc-c, which the ENGINE writes inline
   per pocket and per binder, and --pk-cap, which the pocket sizing sets. */
:root {
    --text: var(--rip-fg);
    --text-2: var(--rip-fg-2);
    --text-3: var(--rip-fg-3);
    --surface-2: var(--rip-panel-2);
    --surface-3: var(--rip-panel-3);
    --border: var(--rip-line-2);
    --border-soft: var(--rip-line);
    --accent: var(--rip-act);
    --accent-soft: var(--rip-act-soft);
    --gold: var(--rip-val);
}
.gapsw {display:inline-flex;align-items:center;gap:9px;padding:6px 14px 6px 8px;min-height:44px;border-radius:999px;
        background:var(--surface-2);border:1px solid var(--border-soft);cursor:pointer;
        font-family:var(--rip-body);transition:border-color .15s,background .15s
}
.gapsw:hover {border-color:var(--text-3)}
.gapsw:focus-visible {outline:2px solid var(--rip-act);outline-offset:2px}
.gapsw-track {position:relative;width:34px;height:20px;border-radius:999px;background:var(--surface-3);
        box-shadow:inset 0 0 0 1px rgba(255,255,255,.08);transition:background .18s;flex:0 0 auto
}
.gapsw-knob {position:absolute;top:2px;left:2px;width:16px;height:16px;border-radius:50%;background:#8b93a7;
        transition:transform .18s cubic-bezier(.4,1.4,.5,1),background .18s
}
.gapsw.on .gapsw-track {background:var(--accent-soft);box-shadow:inset 0 0 0 1px rgba(46,230,214,.55)}
.gapsw.on .gapsw-knob {transform:translateX(14px);background:var(--accent)}
.gapsw-lab {font-size:12.5px;font-weight:800;color:var(--text-3);transition:color .15s;white-space:nowrap}
.gapsw.on .gapsw-lab {color:var(--text)}
/* ══ BINDER ══ */
.binder {position:relative;border-radius:16px;padding:14px 14px 12px;
        background:linear-gradient(160deg,#241017,#14070c 60%),
                   repeating-linear-gradient(45deg,rgba(255,255,255,.014) 0 2px,transparent 2px 5px);
        border:1px solid #3d1a24;
        box-shadow:0 30px 70px rgba(0,0,0,.72),inset 0 1px 0 rgba(255,255,255,.07),inset 0 -2px 14px rgba(0,0,0,.6)
}
.binder::before {content:'';position:absolute;inset:6px;border-radius:11px;pointer-events:none;border:1px dashed rgba(255,255,255,.07)}
.binder-stage {position:relative;perspective:5200px;perspective-origin:50% 50%}
.spread {display:flex;align-items:stretch;justify-content:center;position:relative}
.spine {flex:0 0 30px;align-self:stretch;position:relative;border-radius:3px;
        background:linear-gradient(90deg,rgba(0,0,0,.85),rgba(0,0,0,.35) 40%,rgba(0,0,0,.85));
        display:flex;flex-direction:column;justify-content:space-evenly;align-items:center;padding:22px 0;z-index:6
}
.ring {width:24px;height:24px;border-radius:50%;border:3px solid #b9c2cf;border-right-color:#5c6675;
        border-bottom-color:#79828f;box-shadow:0 1px 3px rgba(0,0,0,.8),inset 0 0 4px rgba(0,0,0,.5);background:transparent
}
.slot-page {flex:1 1 0;min-width:0;display:flex}
.slot-page.mobile-hidden {display:none}
.page {flex:1 1 0;min-width:0;position:relative;padding:12px;border-radius:6px;
        background:linear-gradient(180deg,#161c29,#0e131d);box-shadow:inset 0 0 0 1px rgba(255,255,255,.045);
        backface-visibility:hidden;-webkit-backface-visibility:hidden;contain:layout paint style
}
.page.left {border-radius:6px 2px 2px 6px;box-shadow:inset 0 0 0 1px rgba(255,255,255,.045),inset -22px 0 34px -22px rgba(0,0,0,.95)}
.page.right {border-radius:2px 6px 6px 2px;box-shadow:inset 0 0 0 1px rgba(255,255,255,.045),inset 22px 0 34px -22px rgba(0,0,0,.95)}
.page-grid {display:grid;grid-template-columns:repeat(3,1fr);gap:8px}
.page-no {position:absolute;bottom:-2px;left:0;right:0;text-align:center;font-family:var(--rip-data);font-size:9px;color:var(--text-3);letter-spacing:.06em}
.page-head {display:flex;align-items:center;gap:7px;margin-bottom:9px;min-height:16px}
.page-head .ph-tier {font-family:var(--rip-data);font-size:9px;padding:3px 7px;border-radius:4px;color:#0b0d12;white-space:nowrap}
.page-head .ph-sub {font-size:10px;color:var(--text-3);font-weight:700;letter-spacing:.05em;text-transform:uppercase;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
/* pocket */
    /* ⚠ The pocket is now TWO parts: .pk-art (the sleeve, which owns the 5:7
       ratio and every absolute child) and .pk-meta (the caption, underneath).
       They used to be one box with the caption absolutely positioned over the
       card — three nowrap items in a ~94px pocket, so the value clipped
       mid-figure and the stack buried the art. Anything absolutely positioned
       inside a pocket belongs to .pk-art; .pocket itself is now a plain flex
       column and positions nothing. */
.pocket {position:relative;display:flex;flex-direction:column;min-width:0}
.pk-art {position:relative;aspect-ratio:5/7;border-radius:7px;overflow:hidden;
        background:linear-gradient(155deg,rgba(255,255,255,.055),rgba(255,255,255,.012) 45%,rgba(0,0,0,.28));
        box-shadow:inset 0 0 0 1px rgba(255,255,255,.10),inset 0 2px 6px rgba(0,0,0,.5)
}
.pk-art::after {content:'';position:absolute;inset:0;pointer-events:none;z-index:4;border-radius:7px;
        background:linear-gradient(118deg,rgba(255,255,255,.20) 0%,rgba(255,255,255,.05) 16%,transparent 34%,transparent 72%,rgba(255,255,255,.07) 100%);
        mix-blend-mode:screen;opacity:.75
}
.pocket .card {position:absolute;inset:3px;border-radius:5px;overflow:hidden;border:1.5px solid var(--tc,#333);background:var(--surface-2)}
.pocket.owned {cursor:pointer;transition:transform .14s}
.pocket.owned:hover {transform:translateY(-2px)}
.pocket.owned:hover .card {filter:brightness(1.12)}
.pocket.owned:focus-visible {outline:3px solid var(--accent);outline-offset:2px;transform:translateY(-2px)}
.pocket .card img {width:100%;height:100%;object-fit:cover;display:block}
/* Only things that CANNOT grow are allowed on the art: a grade is one or
       two digits, a duplicate count three characters at most. */
.pk-badge {position:absolute;z-index:5;pointer-events:none;
        font-family:var(--rip-data);font-weight:800;line-height:1;white-space:nowrap;
        border-radius:4px;padding:3px 4px;font-size:8.5px
}
.pk-grade {left:5px;bottom:5px;color:#111}
.pk-count {right:5px;top:5px;color:#fff;background:rgba(7,10,16,.86);
        box-shadow:inset 0 0 0 1px rgba(255,255,255,.18)
}
.pk-off {left:5px;top:5px;font-size:7px;letter-spacing:.06em;color:#0b0d12;background:#8b93a7}
/* Moved tier is good news — it is worth more than it was. Amber is the
       money colour everywhere else in rip-ui, and this is a value story. */
.pk-moved {left:5px;top:5px;font-size:7px;letter-spacing:.06em;color:#0b0d12;background:var(--gold)}
/* ── The Post Office's two pocket states ──────────────────────────────
       ⚠ BOTH SIT BOTTOM-RIGHT, WHICH IS THE ONLY FREE CORNER. .pk-off and
       .pk-moved own top-left, .pk-count top-right, .pk-grade bottom-left. A
       card that is simultaneously MOVED and picked would otherwise stack two
       badges in one corner. They are mutually exclusive with each other, and
       neither can grow: one is a tick, the other a padlock, both 11px. */
.pk-picked {right:5px;bottom:5px;width:16px;height:16px;padding:0;display:grid;place-items:center;
        color:#04121a;background:var(--accent)
}
.pk-lock {right:5px;bottom:5px;width:16px;height:16px;padding:0;display:grid;place-items:center;
        color:var(--text-3);background:rgba(7,10,16,.86);
        box-shadow:inset 0 0 0 1px rgba(255,255,255,.14)
}
/* The picked pocket reads as picked from across the room: the sleeve takes
       the action colour, not a subtle tint. One glance, no counting. */
.pocket.is-picked .pk-art {box-shadow:inset 0 0 0 2px var(--accent),0 0 18px rgba(45,212,191,.32)}
.pocket.is-lock {opacity:.42;cursor:default}
.pocket.is-lock:hover {transform:none}
/* Why a card cannot be sent goes in the CAPTION, never on the art — at
       8.5px on a 112px pocket a reason is unreadable and a wall of text. */
.pk-why {flex:0 0 auto;font-family:var(--rip-data);font-size:9px;font-weight:700;
        color:var(--text-3);white-space:nowrap
}
/* The caption, with the whole pocket width to itself. It ellipsises now
       instead of being clipped by the sleeve's overflow:hidden. */
    /* ⚠ EVERY POCKET RESERVES THE CAPTION ROW, FILLED OR NOT, OR THE BINDER
       CHANGES HEIGHT AS YOU TURN THE PAGE. Aaron, 2026-08-25: "it adds a new
       line of text when a Pokémon has been caught, meaning the binder height
       changes size on each page. not good." Only `.pocket.owned` rendered a
       .pk-meta, so a caught card was 17.9px taller than an empty or filler
       pocket and each sheet was as tall as its tallest ROW. Measured at 390px
       before this: owned 187.8px vs empty 169.9px, and four sheets of 9 pockets
       came out 573.4 / 555.5 / 537.6 / 519.6px depending only on how many cards
       you had caught.

       ⚠ ONE NUMBER, ONE PLACE. --pk-cap is the caption's font size; the
       reserved height is derived from it, so the two cannot drift the way two
       hand-tuned pixel values would. Change the size and the reservation
       follows. */
.pocket {--pk-cap:9.5px}
.pk-meta {display:flex;align-items:baseline;gap:5px;margin-top:4px;min-width:0;
        min-height:calc(var(--pk-cap) * 1.25)
}
.pk-name {flex:1;min-width:0;font-size:var(--pk-cap);font-weight:700;color:var(--text-2);
        line-height:1.25;overflow:hidden;text-overflow:ellipsis;white-space:nowrap
}
.pk-val {flex:0 0 auto;font-family:var(--rip-data);font-size:var(--pk-cap);font-weight:800;
        color:var(--gold);white-space:nowrap;font-variant-numeric:tabular-nums
}
/* ⚠⚠ THE VALUE-FREE TWIN, AND IT MUST NOT INHERIT .pk-val's FLEX. The Pokemon
   pocket reserves that slot for a PRICE — six or seven characters — so
   `flex:0 0 auto; nowrap` with no min-width is safe there. A universe pocket
   fills it with `#<num> · <pack>`, which on Marvel is things like "The Galaxy's
   Most Wanted": at that treatment the item takes whatever width it wants,
   crushes `.pk-name` (which is `flex:1; min-width:0`) to nothing and spills past
   the pocket. rip/fun-pack.css:841-856 already records paying for exactly this
   and already contains the fix — `flex:0 1 auto` with a min-width and a
   max-width, so the card's NAME wins the space it needs and the pack still
   identifies itself. This is that rule, not a second attempt at it.
   ⚠ It also drops the gold and the tabular-nums: neither is about a number any
   more, and gold on this site means "prize / premium". */
.pk-cap2 {flex:0 1 auto;min-width:0;max-width:55%;
        color:var(--text-3);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
        font-variant-numeric:normal
}
/* ⚠ THE CAPTION ROW CLIPS, so nothing added to it next month can escape either —
   but ONLY where the long caption exists. `.pocket, .pk-meta {overflow:hidden}`
   unscoped was written first and is wrong twice over: `.pocket` carries a hover
   lift (translateY(-2px)) and a focus outline with a 2px OFFSET, both of which a
   clip would eat, and either form changes a computed property on the LIVE
   Pokemon binder to buy a universe-only safety net. `:has()` keeps it exactly
   where it belongs, and a browser without it simply keeps today's behaviour. */
.pk-meta:has(.pk-cap2) {overflow:hidden}
.pocket.empty .pk-art {background:linear-gradient(155deg,rgba(255,255,255,.035),rgba(0,0,0,.35));cursor:default}
.pocket.empty .pslot {position:absolute;inset:3px;border-radius:5px;border:1px dashed rgba(255,255,255,.10);
        background:repeating-linear-gradient(135deg,rgba(255,255,255,.018) 0 6px,transparent 6px 12px);
        display:flex;align-items:center;justify-content:center;flex-direction:column;gap:5px
}
.pocket.empty .pslot .q {font-size:26px;font-weight:900;color:rgba(255,255,255,.13);line-height:1}
.pocket.empty .pslot .tag {font-family:var(--rip-data);font-size:7.5px;padding:2px 5px;border-radius:3px;opacity:.55;color:#0b0d12}
.pocket.filler {opacity:.28}
.pocket.filler .pslot {position:absolute;inset:3px;border-radius:5px;border:1px solid rgba(255,255,255,.05)}
/* turning leaf */
.leaf {position:absolute;top:0;z-index:20;transform-style:preserve-3d;will-change:transform;pointer-events:none}
.leaf .face {position:absolute;inset:0;backface-visibility:hidden;-webkit-backface-visibility:hidden;overflow:hidden;border-radius:6px}
.leaf .face.back {transform:rotateY(180deg)}
.leaf .face .page {height:100%}
.leaf .shade {position:absolute;inset:0;pointer-events:none;background:#000;opacity:0;border-radius:6px;z-index:9}
.leaf .gloss {position:absolute;inset:0;pointer-events:none;z-index:8;opacity:0;border-radius:6px;background:linear-gradient(90deg,rgba(255,255,255,.13),rgba(255,255,255,0) 45%)}
.leaf .face.back .gloss {background:linear-gradient(270deg,rgba(255,255,255,.10),rgba(255,255,255,0) 45%)}
.sheet-back {height:100%;border-radius:6px;padding:12px;background:linear-gradient(180deg,#131926,#0c111a);box-shadow:inset 0 0 0 1px rgba(255,255,255,.045)}
.sheet-back .sbg {display:grid;grid-template-columns:repeat(3,1fr);gap:8px;height:100%}
.sheet-back .sbg i {display:block;border-radius:7px;background:linear-gradient(155deg,rgba(255,255,255,.045),rgba(0,0,0,.3));box-shadow:inset 0 0 0 1px rgba(255,255,255,.06)}
.reveal-shade {position:absolute;top:0;bottom:0;z-index:15;pointer-events:none;opacity:0;border-radius:6px}
/* contents sheet */
.contents-title {font-family:var(--rip-data);font-size:10.5px;color:var(--rip-act);letter-spacing:.04em;margin:2px 0 4px}
.contents-sub {font-size:11px;color:var(--text-3);line-height:1.5;margin-bottom:12px}
.toc {display:flex;flex-direction:column;gap:7px}
/* ⚠ EIGHT OF THESE ARE THE ONLY WAY TO REACH A SECTION OF THE BINDER, and
       they were 36px in a list of eight — the row above and the row below are
       both live targets, so a miss goes to the wrong pack. 44px, with the
       padding unchanged so a row with a longer label still fits its content. */
.toc-row {display:flex;align-items:center;gap:9px;padding:8px 10px;min-height:44px;border-radius:9px;cursor:pointer;text-align:left;
        background:rgba(255,255,255,.028);border:1px solid rgba(255,255,255,.06);transition:.14s;font-family:var(--rip-body)
}
.toc-row:hover {background:rgba(255,255,255,.07);border-color:rgba(255,255,255,.16)}
.toc-row:focus-visible {outline:3px solid var(--accent);outline-offset:2px}
.toc-chip {font-family:var(--rip-data);font-size:8.5px;padding:4px 6px;border-radius:4px;color:#0b0d12;flex:0 0 auto;min-width:56px;text-align:center}
.toc-bar {flex:1;height:6px;border-radius:3px;background:rgba(255,255,255,.08);overflow:hidden;min-width:40px}
.toc-bar i {display:block;height:100%;border-radius:3px}
.toc-num {font-family:var(--rip-data);font-size:10.5px;font-weight:800;color:var(--text-2);flex:0 0 auto;white-space:nowrap}
.toc-pg {font-size:9px;color:var(--text-3);flex:0 0 auto;white-space:nowrap;font-weight:700}
.toc-empty {opacity:.42;cursor:default}
/* binder nav */
.bd-nav {display:flex;align-items:center;justify-content:center;gap:12px;margin-top:14px;flex-wrap:wrap}
.bd-arrow {appearance:none;width:44px;height:44px;border-radius:50%;cursor:pointer;background:var(--surface-2);
        border:1px solid var(--border);color:var(--text);font-size:18px;line-height:1;display:flex;align-items:center;justify-content:center;transition:.15s
}
.bd-arrow:hover:not(:disabled) {background:var(--accent);border-color:var(--accent);color:#fff}
.bd-arrow:disabled {opacity:.3;cursor:default}
.bd-counter {font-family:var(--rip-data);font-size:13px;font-weight:800;color:var(--text-2);min-width:120px;text-align:center}
.bd-counter small {display:block;font-family:var(--rip-body);font-size:9.5px;color:var(--text-3);font-weight:700;letter-spacing:.09em;text-transform:uppercase;margin-top:2px}
/* ⚠ THE SLIDER'S BOX IS THE GRAB AREA, AND IT WAS 16px TALL. A range input
       is only as tall as its track unless it is told otherwise, so skimming 449
       pages meant landing on a 16px line while holding the phone one-handed.
       44px box, same 8px track — the thumb stays centred in it and nothing
       about the control's behaviour or its value changes. */
.bd-jump {width:100%;max-width:420px;height:44px;margin:0;accent-color:var(--accent);cursor:pointer}
.bd-hint {text-align:center;font-size:11px;color:var(--text-3);margin-top:8px}
.bd-share {display:inline-flex;align-items:center;gap:8px;padding:11px 22px;min-height:44px;border-radius:999px;cursor:pointer;
        background:rgba(46,230,214,0.16);border:1px solid rgba(46,230,214,0.5);color:var(--rip-act);
        font-family:var(--rip-body);font-size:13px;font-weight:800;transition:.15s;min-width:210px;justify-content:center
}
.bd-share:hover {background:rgba(46,230,214,0.28);color:#fff;border-color:var(--accent)}
.bd-share:focus-visible {outline:2px solid var(--rip-act);outline-offset:2px}
.sr-only {position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}
@media(max-width:760px) {
/* Aaron, 2026-08-07: "make the 9 cards in the binder bigger if
           possible." Nothing here changes the layout — it takes the padding out
           from between the viewport edge and the card. At 390px the chain was
           16 wrap + 10 binder + 20 spine + 12 page + 2x6 gaps, leaving 94px a
           pocket; this recovers ~14 of that (a ~15% larger card) by bleeding
           the binder past the wrap's gutter and trimming each cushion. */
.binder {padding:8px 8px 7px;border-radius:13px;margin-inline:-12px}
.spine {flex:0 0 16px;padding:14px 0;order:-1}
.ring {width:13px;height:13px;border-width:2.5px}
.page {padding:8px}
.page.left {border-radius:2px 6px 6px 2px;box-shadow:inset 0 0 0 1px rgba(255,255,255,.045),inset 22px 0 30px -22px rgba(0,0,0,.95)}
.page-grid {gap:5px}
/* One token, so the reserved row shrinks with the text it reserves. */
.pocket {--pk-cap:9px}
.bd-counter {min-width:96px;font-size:12px}
}
@media (prefers-reduced-motion: reduce) {
.pocket.owned, .pocket.owned:hover {transition:none;transform:none}
.gapsw-knob {transition:none}
}
/* ══ THE SHELF: ONE BINDER PER SET ════════════════════════════════════════
   Aaron, on the first attempt (a set index inside one book): "it can't be one
   binder. the user is scrolling forever… I thought you were going to create a
   separate binder for each set… the gifting system is beautiful. something
   beautiful like that."

   So the motion is borrowed from rip/trades.css rather than invented: 220ms on
   cubic-bezier(.2,1.05,.4,1), the same curve the gift sheet rises on. And the
   same discipline — prefers-reduced-motion gets a DIFFERENT path, not a slower
   one: no transform, no transition, the binder is simply there. */
.bd-shelf {outline:none}
.bd-shelf__head {display:flex;align-items:baseline;gap:10px;margin:0 0 12px}
.bd-shelf__n {font-family:var(--rip-display,inherit);font-weight:800;font-size:15px;color:var(--text)}
.bd-shelf__hint {font-size:12px;color:var(--text-3)}
.bd-shelf__empty, .bd-shelf__rest {font-size:12.5px;color:var(--text-3);margin:14px 2px 0;line-height:1.5}
/* auto-fill, so the shelf is two covers wide on a phone and as many as fit on a
   desktop without a breakpoint per size. */
.bd-shelf__grid {display:grid;gap:12px;grid-template-columns:repeat(auto-fill,minmax(148px,1fr))}
/* ⚠ THE COVER IS THE WHOLE TILE, THE PACK IS NEVER CROPPED, AND THE CAPTION
   NEVER SITS ON IT.

   Three rounds of Aaron on this tile, and the third one undoes half of the
   second, so all three are here:

   1. "make the pack image fit properly on the shelf and binder. consider making
      it the entire background image of the binder and how to do that whilst
      keeping the text readable" — the pack was a 5:8.8 shot inside a 1:1 box at
      74% width, so a third of every tile was gutter.
   2. "make each set selection taller so that the image fills on the width too."
   3. "you can't see the full pack because the text is covering it, and the name
      of the pack usually sits at the bottom of the image/pack."

   (3) is the cost of (1) coming due, and he is right: a booster pack prints its
   set name across its FOOT, so a caption overlaid on the bottom strip hides the
   one thing that identifies the pack. "Over the logo band, never the art" was
   wrong — on a pack the logo band IS the identifying part.

   So the layers split by job rather than by position:

     .bdc__bg    object-fit:COVER, blurred — fills the whole tile, caption band
                 included, so there is still no dead space anywhere.
     .bdc__art   its own row, sized so a width-filling pack fits inside it. The
                 pack is CONTAIN and untouched: cropping it was rejected once
                 already on the clips.
     .bdc__body  a row BELOW the art, over the blur. Nothing is covered.

   ⚠ THE ART ROW'S ASPECT IS DERIVED FROM THE PACK, NOT PICKED. A trimmed pack
   is ~0.57 wide-to-tall, so filling the tile's width needs (width − insets) /
   0.57 of height; at a 173px tile that is 275px of pack in a 288px row. 3/5 is
   that number. Retune it with pack-trim.php, never alone — a looser trim leaves
   border in the image and the pack stops filling the width at the same ratio.

   ⚠ THE NAME RESERVES TWO LINES WHETHER IT USES THEM OR NOT. Grid rows size to
   their tallest tile, so a one-line name beside a two-line one ("Japanese
   Terastal Festival") makes a ragged shelf and moves every tile below it. Same
   discipline as the binder pocket's caption row. */
.bdc {position:relative;display:flex;flex-direction:column;text-align:left;padding:0;
  background:var(--panel-2,#141a24);border:1px solid var(--line,#243044);border-radius:12px;
  overflow:hidden;cursor:pointer;color:inherit;font:inherit;
  transition:transform 220ms cubic-bezier(.2,1.05,.4,1),border-color 150ms,box-shadow 220ms
}
.bdc:hover, .bdc:focus-visible {transform:translateY(-3px);border-color:var(--bdc-c);
  box-shadow:0 10px 26px -12px var(--bdc-c)
}
/* the spine: the tier colour, down the hinge edge, so a shelf reads as a shelf */
.bdc__spine {position:absolute;left:0;top:0;bottom:0;width:6px;z-index:3;background:var(--bdc-c);
  box-shadow:inset -1px 0 0 rgba(0,0,0,.35)
}
/* The backdrop is on the TILE, not the art row, so the caption band sits on the
   pack's own colours instead of a flat panel. */
.bdc__bg {position:absolute;inset:0;width:100%;height:100%;z-index:0;object-fit:cover;
  transform:scale(1.18);filter:blur(16px) saturate(1.25) brightness(.5);opacity:.85
}
.bdc__art {position:relative;z-index:1;flex:0 0 auto;aspect-ratio:3/5;
  display:grid;place-items:center;overflow:hidden
}
/* Insets kept tight — 5px, and 11px on the hinge side to clear the spine — so
   "fills the width" is true rather than nearly true. */
.bdc__fg {position:absolute;inset:5px 5px 5px 11px;width:auto;height:auto;
  max-width:calc(100% - 16px);max-height:calc(100% - 10px);margin:auto;
  object-fit:contain;filter:drop-shadow(0 8px 20px rgba(0,0,0,.6))
}
/* A card nobody owns yet is the thing to go and get, so it is present but dimmed
   rather than absent — an empty cover says nothing about the set. */
.bdc__art img.is-missing {filter:grayscale(1) brightness(.55);opacity:.75}
.bdc__noart {font-family:var(--rip-display,inherit);font-size:30px;font-weight:800;color:#fff;opacity:.35}
.bdc__body {position:relative;z-index:2;flex:1 1 auto;
  padding:8px 10px 10px 14px;display:flex;flex-direction:column;justify-content:center;gap:5px;
  background:rgba(4,7,11,.88);box-shadow:inset 0 1px 0 rgba(255,255,255,.06)
}
.bdc__name {font-family:var(--rip-display,inherit);font-weight:800;font-size:12.5px;line-height:1.25;
  min-height:2.5em;color:#fff;
  display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden
}
/* Count and bar share one row: two stacked rows of chrome under every tile is
   ~13px per tile that the pack could have had instead. */
.bdc__prog {display:flex;align-items:center;gap:8px}
.bdc__num {flex:0 0 auto;font-family:var(--rip-data,inherit);font-variant-numeric:tabular-nums;
  font-weight:800;font-size:13px;color:var(--bdc-c)
}
.bdc__num span {color:rgba(255,255,255,.55);font-weight:400}
.bdc__bar {flex:1 1 auto;min-width:0;height:3px;border-radius:2px;
  background:rgba(255,255,255,.16);overflow:hidden
}
.bdc__bar i {display:block;height:100%;background:var(--bdc-c);border-radius:2px}
/* the way back out of an open binder */
.bd-back {display:inline-flex;align-items:center;gap:6px;margin:0 0 12px;padding:7px 12px;
  background:var(--panel-2,#141a24);border:1px solid var(--line,#243044);border-radius:999px;
  color:var(--text-2);font:inherit;font-size:12.5px;font-weight:700;cursor:pointer;
  transition:border-color 150ms,color 150ms
}
.bd-back:hover, .bd-back:focus-visible {color:var(--text);border-color:var(--rip-act,#22d3ee)}
/* the binder flowing in as it opens — the gift sheet's curve, on the stage */
.binder-stage.bd-in {animation:bdFlowIn 220ms cubic-bezier(.2,1.05,.4,1) both}
/* ── the inside front cover ──────────────────────────────────────────────
   ⚠ PAGE 1 IS EXACTLY AS TALL AS EVERY OTHER PAGE, AND IT IS MEASURED, NOT
   GUESSED (Aaron, 2026-08-28: "I've told you many times to not have any binder
   pages at different heights. make the first page of the binder the same height
   as the other pages." — the third time this class of bug has reached him;
   the .pk-meta rule above is the first two).

   The height of a sheet is 3 pocket rows + 2 gaps, and a pocket is 5:7 art plus
   a reserved caption row — a number that changes with the column width, the
   font and any future pocket change. Recomputing it here in a min-height would
   be a SECOND copy of that arithmetic, silently wrong the next time a pocket
   changes. So the cover renders a REAL .page-grid of nine real filler pockets,
   hidden, and the cover art is laid over it. The page is then the same height
   as a sheet by construction, at every viewport, forever — and if a pocket ever
   changes height the cover follows it without anyone remembering to. */
.bdcov-wrap {position:relative}
.bdcov-ghost {visibility:hidden;pointer-events:none}
/* ⚠ THE ART IS A FLEX ROW, NOT AN ABSOLUTE BOX WITH A GUESSED BOTTOM INSET.
   It was `inset:10px 10px 92px` — 92px reserved for the caption — while the
   caption's own box measured ~142px, so the pack ran 50px underneath it and the
   binder's name printed across the pack's name. A reserved constant cannot
   track a block whose height comes from its content; `flex:1` and `flex:0 0
   auto` cannot disagree. Same fault, same fix, as the shelf tile above. */
.bdcov {position:absolute;inset:0;overflow:hidden;border-radius:6px;
  display:flex;flex-direction:column;text-align:center
}
/* Same two layers as the shelf tile: a blurred COVER backdrop fills the page in
   the pack's own colours, the real pack sits over it CONTAINED and uncropped. */
.bdcov__bg {position:absolute;inset:0;width:100%;height:100%;z-index:0;object-fit:cover;
  transform:scale(1.2);filter:blur(22px) saturate(1.25) brightness(.42)
}
/* ⚠ THE IMAGE IS ABSOLUTELY POSITIONED, AND A PERCENTAGE HEIGHT HERE IS NOT.
   `max-height:100%` on a child of a `flex:1` item resolves against an
   INDEFINITE height, so the browser is entitled to ignore it and paint the
   image at its natural size — which it did: measured at 390px the pack ran
   59.5px past the caption's top edge, i.e. exactly the bug this round is
   fixing, reintroduced one element lower down. Absolute insets against a
   positioned parent always resolve, at any viewport. Measured after: −16.6px
   at 390, −75.6 at 1280 (negative = clear). */
.bdcov__art {position:relative;z-index:1;flex:1 1 auto;min-height:0;display:grid;place-items:center}
.bdcov__art img {position:absolute;inset:10px 10px 6px;width:auto;height:auto;margin:auto;
  max-width:calc(100% - 20px);max-height:calc(100% - 16px);object-fit:contain;
  filter:drop-shadow(0 12px 26px rgba(0,0,0,.65))
}
.bdcov__art img.is-missing {filter:grayscale(1) brightness(.55);opacity:.75}
.bdcov__noart {font-family:var(--rip-display,inherit);font-size:38px;font-weight:800;color:#fff;opacity:.35}
.bdcov__meta {position:relative;z-index:2;flex:0 0 auto;
  display:flex;flex-direction:column;align-items:center;gap:6px;
  padding:12px 14px 14px;background:rgba(4,7,11,.9);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.07)
}
.bdcov__name {font-family:var(--rip-display,inherit);font-weight:800;font-size:17px;line-height:1.2;
  color:#fff
}
.bdcov__num {font-family:var(--rip-data,inherit);font-variant-numeric:tabular-nums;
  font-weight:800;font-size:20px;color:var(--bdc-c)
}
.bdcov__num span {color:rgba(255,255,255,.62);font-weight:400;font-size:15px}
.bdcov__bar {width:min(76%,220px);height:4px;border-radius:2px;background:rgba(255,255,255,.18);overflow:hidden}
.bdcov__bar i {display:block;height:100%;background:var(--bdc-c);border-radius:2px}
.bdcov__sub {font-size:11.5px;color:rgba(255,255,255,.68);line-height:1.45}
@media (prefers-reduced-motion:reduce) {
.bdc, .bd-back {transition:none}
.bdc:hover, .bdc:focus-visible {transform:none}
.binder-stage.bd-in {animation:none}
}
