/* ══════════════════════════════════════════════════════════════════════════
   home.css — the welcome page at /rip/.

   Composes from rip-ui.css and adds nothing to its palette: cyan is still the
   only thing you click, amber is still only money, and the eight tier colours
   are still data. Everything here is layout and atmosphere.

   ── WHAT CHANGED, AND WHY ────────────────────────────────────────────────
   The previous version leaned on a hero photograph with a sheen sweeping
   across it. Both are gone, deliberately and permanently:

     · the photograph (images/rip/hero-mobile.webp) was 4.7 KB at 390x440 and
       rendered as a flat near-black wash carrying no information;
     · the sheen (.hm-pack::after) was a screen-blended white→cyan diagonal
       that flashed across it for 3.6 seconds of every 14. Aaron's verdict was
       "this image and the sheen overlay looks shit".

   Neither is replaced by a different gloss. The imagery on this page is now
   real product: card scans, slab photographs, prize photographs and screen
   recordings. Nothing sweeps across any of them.

   Loaded only by welcome.php. The pack app and the member pages never see it.
   ══════════════════════════════════════════════════════════════════════════ */

/* rip-ui.css sets no global box-sizing, and .rip-btn carries 30px of
   horizontal padding — so `width:100%` on a CTA overflows its column by 60px
   and any ancestor with overflow:hidden silently amputates its right edge.
   This one line is what keeps every full-width button on the page inside the
   viewport at 390px. */
*,*::before,*::after{box-sizing:border-box}

/* rip-ui.css paints a cyan bloom at the top of every page; each hero brings
   its own atmosphere, so the bloom would double up behind it. */
body.hm{background:var(--rip-bg)}

.hm-in{max-width:var(--rip-maxw);margin:0 auto;padding:0 18px}
.hm-in--narrow{max-width:760px}

/* ── section furniture ─────────────────────────────────────────────────────
   One idea per section: an eyebrow, a heading, a visual, and — at most — one
   line. If a section needed two sentences to justify itself it got a better
   visual instead.                                                           */
.hm-sec{padding:clamp(20px,5vw,70px) 0}
.hm-sec--tint{background:linear-gradient(180deg,transparent,rgba(17,23,33,.6) 22%,rgba(17,23,33,.6) 78%,transparent)}
.hm-sec__head{margin:0 0 clamp(12px,2.6vw,28px)}
/* ⚠ .hm-join RESTORES A SECTION BOUNDARY THAT MERGING REMOVED.
   Merging sections folds blocks into a neighbour, and each of those joints
   silently loses TWO lots of .hm-sec padding — up to 140px of separation —
   leaving the blocks flush against each other. This puts that gap back without
   reinstating the section header that was the point of merging. After the
   2026-08-10 rebuild there is exactly one: the leaderboard under the streak
   ladder in "Every day".
   ⚠ TWO CLASSES, NOT ONE. A bare .hm-join is (0,1,0) and loses to any component
   that sets its own margin shorthand later in this file — .hm-chase__box used to
   do exactly that with `margin:0 auto` and measured 0px of join gap while the
   other three got 30px. That block is gone, but .hm-lb is a bordered panel and
   the next one will be too, so the (0,2,0) form stays: it wins outright rather
   than on source order. */
.hm-in > .hm-join{margin-top:clamp(30px,6.4vw,74px)}
/* ⚠ THE MEASURE CAP BELONGS TO THE HEADING, NOT TO THE WRAPPER.
   `ch` resolves against the element's OWN font. On this wrapper that is the
   inherited body font (~10.2px/ch), so `max-width:22ch` here computed to
   223.95px at 390px AND at 1920px — it never changed, because the wrapper's
   font never changes. Meanwhile the h2 inside scales to 38px. The result was
   38px display type in a 224px box: five characters a line, four and five
   line headings on desktop, and 805px of pure heading overflow across the
   page. Invisible at 390px (two lines either way), which is why a phone-only
   review cannot catch it. The cap now sits on .hm-h2, where 22ch means 22 of
   ITS characters (~337px at 390px, ~582px from 768px up) — which is what a
   22-character measure was always meant to say.                             */
.hm-sec__head--mid{margin-left:auto;margin-right:auto;text-align:center}
/* 13px, not 11: these eleven kickers are the section nav of a ten-screen page,
   and they were the second-largest block of sub-13px text on it. The height the
   extra 2px costs is paid back by the tighter line-box and margin — the eyebrow
   BOX is smaller than it was at 11px, and the type is bigger. */
.hm-eyebrow{
    font-family:var(--rip-data);font-size:13px;font-weight:700;letter-spacing:.18em;
    text-transform:uppercase;color:var(--rip-act);margin:0 0 5px;line-height:1.2;
}
.hm-eyebrow--val{color:var(--rip-val)}                 /* the prize section only */
.hm-h2{font-family:var(--rip-display);font-weight:800;letter-spacing:-.028em;line-height:1.05;
    font-size:clamp(22px,5.5vw,38px);margin:0;color:var(--rip-fg);text-wrap:balance;
    max-width:22ch}
.hm-sec__head--mid .hm-h2{margin-left:auto;margin-right:auto}

/* ── the data line ─────────────────────────────────────────────────────────
   Where a sentence would have gone. Mono, tabular, centred under the visual:
   numbers are read at a glance and sentences are not.                       */
.hm-data{
    font-family:var(--rip-data);font-size:13px;font-weight:700;letter-spacing:.1em;
    text-transform:uppercase;color:var(--rip-fg-2);text-align:center;margin:14px 0 0;
    line-height:1.6;
}
/* .hm-data--left was the left-aligned variant for the data line inside a
   .hm-pair's side column. There are no side columns any more; every data line
   sits centred under the visual it describes. */

/* ── the fold-away ─────────────────────────────────────────────────────────
   Reference and edge-case detail is not deleted, it is folded. Closed by
   default, so the page is short; one tap and nothing has been lost.         */
.hm-det{
    max-width:62ch;margin:clamp(13px,2.4vw,22px) auto 0;
    border:1px solid var(--rip-line);border-radius:var(--rip-r);background:var(--rip-panel);
}
/* min-height is the tap target, not the padding: these summaries measured
   352x37 at 390px — seven pixels short of the 44px floor, on the only control
   that reveals the folded-away detail. 13px is also the readable floor; at
   11px the affordance was smaller than the text it opens.                   */
.hm-det>summary{
    cursor:pointer;list-style:none;padding:11px 15px;min-height:44px;
    font-family:var(--rip-data);font-size:13px;font-weight:700;letter-spacing:.1em;
    text-transform:uppercase;color:var(--rip-act);
    display:flex;align-items:center;justify-content:space-between;gap:12px;
}
.hm-det>summary::-webkit-details-marker{display:none}
.hm-det>summary::after{
    content:'';flex:none;width:8px;height:8px;border-right:2px solid currentColor;
    border-bottom:2px solid currentColor;transform:rotate(45deg) translateY(-2px);
    transition:transform .18s;
}
.hm-det[open]>summary::after{transform:rotate(-135deg) translateY(-2px)}
.hm-det p{margin:0;padding:0 16px 15px;color:var(--rip-fg-2);font-size:14px;line-height:1.6;text-wrap:pretty}

/* ── the FAQ variant ───────────────────────────────────────────────────────
   .hm-det's summary is uppercase mono with .1em tracking, which is right for a
   three-word label ("THE PRIZE, IN FULL") and wrong for a question. Measured at
   390px, "Is Pack Dojo affiliated with GameStop, Nintendo, PSA or PriceCharting?"
   set that way runs to four lines and reads as shouting; in sentence case at the
   body font it is two.

   ⚠ THE SUMMARY TEXT MUST STAY EXACTLY THE QUESTION IN THE FAQPage MARKUP.
   text-transform would not change the HTML, but a rewrite for length would —
   and the visible question and the marked-up one have to match. Style it, never
   abbreviate it.

   align-items:flex-start so the chevron sits on the first line of a wrapped
   question rather than floating at its vertical centre. */
/* ⚠ THE CRAWL ROW FOLLOWS ITS SECTION'S ALIGNMENT, AND IT CANNOT DO THAT ON
   ITS OWN. .rip-crawl is shared chrome: a flex row, so it takes flex-start
   whatever the parent's text-align says. On the pages that host it the copy
   around it is left-aligned and that is correct — but .hm-end is a centred
   section, and the row sat hard left directly above a centred disclaimer.
   Scoped here rather than changed in rip-ui.css, because left IS right on
   every other host. */
.hm-end .rip-crawl{justify-content:center}
/* Same reason, same scope: rip_chrome_legal()'s 78ch box carries margin-left:0
   because that is right on the seven left-aligned pages that host it. Inside
   this centred section it left the disclaimer reading as a centred block that
   had slipped 244px off centre — measured 81→676 in an 81→1165 column.
   !important because that margin is an INLINE style on the <p>, and inline
   loses to nothing else. */
.hm-end .rip-legal{margin-left:auto !important;margin-right:auto !important}

/* ⚠ NO max-width HERE — each .hm-det inside already caps itself at 62ch, and
   `ch` resolves against the ELEMENT's own font-size. This wrapper's 62ch came
   out 595px while a standalone .hm-det's came out 631px, so the FAQ block sat
   18px inside every other folded panel on the page for no visible reason.
   One cap, on the component, and all of them share an edge. */
.hm-faq{margin-left:auto;margin-right:auto}
.hm-det--faq>summary{
    font-family:var(--rip-body);font-size:15px;font-weight:700;letter-spacing:0;
    text-transform:none;color:var(--rip-fg);align-items:flex-start;line-height:1.45;
}
.hm-det--faq>summary::after{margin-top:5px}
.hm-det--faq[open]>summary{color:var(--rip-act)}

/* .hm-lede is gone too (2026-08-10). It held the paragraph beside each paired
   visual — three of them in the binder section alone — and the rebuild's rule
   is that a section gets a heading, a visual and at most one .hm-data line. The
   copy those ledes carried is either folded into the section's <details> or
   said by the clip's own caption bar. Below the hero this page now has zero
   body paragraphs outside a fold, which is what "not a wall of text" means when
   it is measured rather than asserted. (.hm-chips went the same way on
   2026-08-08 — "random words inside pills that the user doesn't need to see".) */

/* ── the one button, and the line under it ────────────────────────────────
   Exactly one .rip-btn per screen. The second line is a text link on purpose:
   two equally weighted pills is two decisions, and only one is the offer.
   welcome.php swaps its content on the sim_signed_in hint cookie, so a member
   who is already signed in is never invited to sign in.                     */
.hm-cta{margin:20px 0 0;display:flex;flex-direction:column;align-items:center;gap:13px}
.hm-cta .rip-btn{width:100%;max-width:330px}
/* --rip-fg-2, not --rip-fg-3: this line sits on the bare page background where
   #66738a measures 4.04:1 — under AA, on the sentence that carries the hero's
   only alternative action. */
.hm-cta__alt{font-size:14.5px;color:var(--rip-fg-2)}
/* The link measured 49.5x16 — a third of the 44px floor, above the fold at
   390px. Padding grows the hit area and the matching negative margin puts the
   text back exactly where it was, so nothing moves on screen. */
.hm-cta__alt a{display:inline-block;padding:14px 12px;margin:-14px -12px}

/* ── the proof strip — four figures, one glance ───────────────────────────
   Shared by all three heroes rather than triplicated in each namespace: it is
   the same component doing the same job, and three near-identical copies is
   three places to fix a number.                                             */
.hm-proof{
    display:grid;grid-template-columns:repeat(4,minmax(0,1fr));gap:1px;
    background:var(--rip-line);border:1px solid var(--rip-line);
    border-radius:var(--rip-r);overflow:hidden;
    width:100%;max-width:560px;margin:22px auto 0;
}
.hm-proof__i{background:var(--rip-bg);padding:11px 5px 10px;min-width:0;text-align:center}
.hm-proof__v{
    font-family:var(--rip-data);font-weight:800;line-height:1.05;
    font-size:clamp(15px,4.2vw,21px);font-variant-numeric:tabular-nums;
    letter-spacing:-.025em;color:var(--rip-fg);
}
.hm-proof__v--val{color:var(--rip-val)}                /* amber = money, always */
/* ⚠ THE NOWRAP WAS A CLIP, NOT A GUARD. A 390px phone gives each of the four
   cells 87px, 77px of it content — and "Real cards" already needed 82px AT
   11px, so the label shipped with its right edge cut off. Measured at 13px:
   "Pack tiers" 90px, "Real cards" 97px, and dropping the tracking to 0 only
   reaches 85/92. Nothing fits on one line at any readable size, so the labels
   wrap instead: 0 clipped, 13px, at a cost of 23px of strip height. --rip-fg-2
   lifts these off 4.04:1. */
.hm-proof__l{
    font-size:13px;font-weight:700;letter-spacing:.04em;text-transform:uppercase;
    color:var(--rip-fg-2);margin-top:5px;line-height:1.25;
}

/* .hm-cd — the standalone card tile — is gone with the grail strip and the
   chase block that were its only two consumers (2026-08-10). The two card
   objects still on the page each need something it did not do: .hm-tier__art
   puts the tier's slab photograph behind the scan, and .hx3-tile crops to fill
   rather than contains. A third "generic" tile with no call site is a component
   waiting to be reintroduced by accident. */

/* ── the media box — real footage of the real product ─────────────────────
   The caption bar is load-bearing honesty: it says whether you are looking at
   a recording of the live product or at an illustration built from the
   product's own components. Never let the "live" badge ride on a fallback.  */
.hm-media{
    position:relative;border:1px solid var(--rip-line);border-radius:var(--rip-r);
    background:radial-gradient(120% 130% at 50% 0%,rgba(46,230,214,.06),transparent 58%),
               linear-gradient(180deg,var(--rip-panel-2),var(--rip-bg-2));
    padding:clamp(14px,2.6vw,22px);overflow:hidden;box-shadow:var(--rip-shadow);
}
.hm-media video{border-radius:var(--rip-r-sm)}
/* ⚠ THE CLIPS ARE WIDE NOW, SO THEY ARE SIZED BY WIDTH AND NOTHING ELSE.
   They were 780x1688 portrait phone captures, and this rule sized them by
   HEIGHT — clamp(440px,124vw,560px) — because at width:100% a full phone screen
   came out 727px tall and took the page from 8,266 to 10,090. Cropping them to
   fit was tried and rejected ("you've chopped them and made them square"), so
   height-driven sizing was the only thing left.
   Re-recorded 2026-08-10 as 1000x624 wide (Aaron: "make the clips shorter and
   wider to fit the page width"), which removes the whole problem: the natural
   thing — fill the column, keep the ratio — is now also the short thing. At a
   390px viewport the content box is 338px, so a clip is 211px tall against 484
   before.

   ⚠ NO aspect-ratio HERE, DELIBERATELY. The shape comes from hm_media()'s
   width/height attributes, which are ffprobe'd from the files themselves. Two
   declarations of the same ratio is two places to be wrong, and the CSS copy is
   the one nobody re-measures when the files change. If a clip ever letterboxes,
   the attributes are stale — fix them, not this. */
.hm-clip{display:block;width:100%;height:auto;margin:0;background:#05070b}

/* ⚠ A LONE CLIP MUST NOT TAKE THE WHOLE DESKTOP COLUMN.
   "Full content width" is a phone instruction — at 390px that is 336px and the
   clip is 210px tall, which is the point. At 1280px the same rule made the
   single "How it works" clip 1038x648: taller than it was on the phone, blown
   up 4% past the files' native 1000px so it is also softer, and it pushed that
   section from 928 to 1,017 — the one place this rebuild made the page LONGER.
   Capped at 700px the clip is 654x408 and the section comes in under both.
   Scoped to `.hm-in > .hm-media` so it reaches exactly the one standalone clip:
   the binder section's three are inside .hm-clips, which is already narrower
   than this at every width that matters. */
/* ⚠ ONE CONTENT COLUMN AT DESKTOP FOR EVERYTHING THAT IS NOT A ROW OF CARDS.
   The wide things — the eight-tier ladder, the three clips — earn the full
   1,084px because they are eight and three things side by side. A single panel
   does not: measured at 1280px the streak ladder spanned 1,084px to put a 66px
   day chip at one end of the row and "+5" at the other, and the three-row board
   did the same. Sparse is its own kind of clunky. Everything in this list is one
   object, so it takes the same 700px column and centres in it. */
@media(min-width:760px){
    .hm-in > .hm-media,
    .hm-run,
    .hm-streak,
    /* .hm-prizes is deliberately NOT here — its 560 cap is an artwork-weight
       decision (two 4:5 portraits at 700 would be 344x430), and it is centred,
       so it reads as a smaller pair rather than a broken edge. */
    .hm-in--narrow,
    .hm-in > .hm-lb{max-width:700px;margin-left:auto;margin-right:auto}
    /* …and with the panel at 700 the six rungs go three to a row rather than
       two, so the ladder is two tidy rows instead of three long ones. */
    .hm-streak__rungs{grid-template-columns:repeat(3,minmax(0,1fr))}
}
/* Three of them, stacked on a phone and in a row from 900px. This is the whole
   of the binder section's layout now — it used to be three .hm-pair grids, each
   pairing a clip against a hand-drawn stat panel that illustrated what the clip
   beside it was already showing. */
.hm-clips{display:grid;gap:clamp(10px,2.4vw,16px)}
@media(min-width:900px){.hm-clips{grid-template-columns:repeat(3,minmax(0,1fr))}}
/* flex-wrap, because the pair narrows this box to ~180px on a phone and ~154px
   at 320: "OPENING A GOLD PACK" and "REAL PULL" stop fitting on one line, and
   .hm-media clips its overflow, so without the wrap the honesty half of the
   honesty bar is what disappears. */
.hm-media__cap{
    display:flex;align-items:center;justify-content:space-between;gap:4px 12px;flex-wrap:wrap;
    font-family:var(--rip-data);font-size:13px;font-weight:700;letter-spacing:.06em;
    text-transform:uppercase;color:var(--rip-fg-2);
    margin:0 0 7px;padding:0 0 6px;border-bottom:1px solid var(--rip-line);
}
/* NOT cyan. Cyan is the one colour that means "tap this", and the caption bar
   is a label on a video, not a control. */
.hm-media__cap b{color:var(--rip-fg);font-weight:800}

/* ⚠ .hm-pair IS GONE, AND THAT IS THE SHORTENING IN ONE LINE.
   It put a clip in one column and a hand-drawn panel in the other, five times
   over — binder, numbers, badges, every day, leaderboards. Every one of those
   right-hand columns was an ILLUSTRATION of the screen playing next to it: a
   completion figure and eight tier bars beside a recording of the binder, two
   spend-against-value panels beside a recording of the stats page, a paragraph
   beside a recording of the badge grid, an aria-hidden drawing of a tab bar
   beside the real leaderboard. That is the panel-on-panel rhythm Aaron
   objected to on 2026-08-10, and it is also why it never fitted: the .85fr
   column is ~145px on a 390px phone, so the sheet needed a stack-below-560,
   a stack-below-360, and six more guards further down just to stop the drawings
   overflowing the page.
   The clip is the visual now, full width, and what the panel was illustrating
   is either in the clip already or in one .hm-data line. If a pair is ever
   wanted back, it should be for a visual that is NOT a duplicate of its
   neighbour. */

/* ══════════════════════════════════════════════════════════════════════════
   THE THREE HEROES

   All three live in this sheet so Aaron can flip between them on his phone at
   /rip/?hero=1|2|3. welcome.php renders exactly one, and each keeps its own
   .hx1- / .hx2- / .hx3- namespace so they cannot collide. What they share —
   the button block and the proof strip — is the shared .hm- component above,
   because the same object doing the same job three times is three places to
   fix one number.

   None of them adds a colour to rip-ui.css. Cyan is only the button, amber is
   only money, and the one non-neutral hue in each atmosphere is a TIER
   colour, which is data: it is the tier the card on screen came out of.
   ══════════════════════════════════════════════════════════════════════════ */

/* ══ HERO 1 · "THE PULL" ═════════════════════════════════════════════════
   The product moment first: a real card, in a real PSA slab, with its real
   market price, on screen before any sentence.                             */
.hx1-hero{
    position:relative;overflow:hidden;
    padding:clamp(26px,5vw,64px) 0 clamp(34px,5vw,68px);
    border-bottom:1px solid var(--rip-line);
}
/* Atmosphere in the SLAB'S OWN TIER COLOUR, confined to the top so it never
   reaches the button. --hx1-tc is set inline by welcome.php from the record
   pull's tier, so re-pointing the hero at a different card changes nothing
   here. The rgba fallback is spelled out for old WebKit. */
.hx1-glow{
    position:absolute;z-index:0;pointer-events:none;
    left:50%;top:-6%;transform:translateX(-50%);
    width:min(780px,168vw);height:min(600px,66%);
    background:radial-gradient(closest-side,
        rgba(239,68,68,.17) 0%,rgba(239,68,68,.07) 46%,rgba(239,68,68,0) 76%);
}
.hx1-in{position:relative;z-index:1;max-width:var(--rip-maxw);margin:0 auto;padding:0 18px}

/* Phone order: eyebrow → SLAB → words. `display:contents` on .hx1-copy is
   what allows that without a second DOM: the copy box evaporates, its
   children become flex items of the stage, and `order` interleaves them with
   the slab. At ≥900px .hx1-copy becomes a real box again and the whole
   interleave collapses back to DOM order — copy left, slab right. */
.hx1-stage{display:flex;flex-direction:column;align-items:center;text-align:center}
.hx1-copy{display:contents}
.hx1-eyebrow{order:1}
.hx1-pull{order:2}
.hx1-h1{order:3}
.hx1-lede{order:4}
.hx1-stage .hm-cta{order:5}
.hx1-stage .hm-proof{order:6}

.hx1-eyebrow{
    display:inline-flex;align-items:center;gap:8px;
    font-family:var(--rip-data);font-size:13px;font-weight:700;
    letter-spacing:.1em;text-transform:uppercase;color:var(--rip-fg-2);
    border:1px solid var(--rip-line-2);background:rgba(255,255,255,.035);
    padding:6px 13px;border-radius:999px;margin:0 0 16px;
    -webkit-backdrop-filter:blur(6px);backdrop-filter:blur(6px);
}

/* ── the slab ──────────────────────────────────────────────────────────────
   Same construction and proportions as the live slab in packs.htm (300 × 530,
   115px label, 10px PSA-red border), rebuilt in em so it scales as one
   object: font-size is declared with the SAME fluid function as the width,
   divided by ten, so 1em is always width/10 and every internal measurement is
   the packs.htm pixel value ÷ 30.                                           */
.hx1-pull{margin:0;display:flex;flex-direction:column;align-items:center}
.hx1-slab{
    position:relative;
    /* 216 and not 232: with the real /rip/ header on top, the extra 28px of
       slab pushed the CTA to the very bottom edge of a 390x844 phone. */
    width:min(216px,59vw);
    font-size:min(21.6px,5.9vw);      /* = width / 10 */
    aspect-ratio:300/530;
    border-radius:.467em;
    border:1px solid #444;
    background:linear-gradient(135deg,#2a2a2a 0%,#0a0a0a 100%);
    padding:.333em;
    display:flex;flex-direction:column;
    box-shadow:0 .8em 2.4em rgba(0,0,0,.72),
               0 0 0 1px rgba(255,255,255,.04) inset,
               0 0 3.2em -0.6em rgba(239,68,68,.42);
}
.hx1-label{
    background:#fff;color:#111;
    border:.333em solid #e31b23;       /* --psa-red */
    border-radius:2px;
    padding:.267em;margin-bottom:.267em;height:3.833em;
    font-family:var(--rip-data);
    display:flex;flex-direction:column;justify-content:space-between;
}
.hx1-label__top{display:flex;justify-content:space-between;align-items:flex-start;gap:.2em}
.hx1-label__meta{font-weight:800;text-transform:uppercase;width:70%;text-align:left;word-break:break-word}
.hx1-label__set{display:block;font-size:.25em;line-height:1.35;color:#444;letter-spacing:.01em}
.hx1-label__name{display:block;font-size:.433em;line-height:1.12;margin-top:.06em;letter-spacing:-.02em}
.hx1-label__grade{text-align:right;line-height:1;flex-shrink:0;text-transform:uppercase}
.hx1-label__gem{display:block;font-size:.267em;font-weight:800}
.hx1-label__num{display:block;font-size:.533em;font-weight:800;margin-top:.03em}
.hx1-label__foot{
    display:flex;justify-content:space-between;align-items:center;
    height:.733em;border-top:1px solid #eee;padding-top:.133em;
}
.hx1-barcode{height:.533em;width:2.667em;
    background:repeating-linear-gradient(90deg,#111,#111 1px,#fff 1px,#fff 3px)}
.hx1-psa{height:.467em;width:auto;display:block}

/* the card window. NO sheen, no gloss, no sweep — the art is the art. */
.hx1-art{flex:1;min-height:0;background:#000;border:1px solid #222;
    border-radius:.133em;padding:.133em;overflow:hidden}
.hx1-art__in{width:100%;height:100%;border-radius:.133em;overflow:hidden;position:relative;
    background:linear-gradient(160deg,#12161d,#07090d)}
.hx1-art img{width:100%;height:100%;object-fit:contain;display:block}

/* The reveal happens ONCE, on load, and then the page holds still. Every
   animated element's resting state IS its final state, so killing the
   animation under reduced-motion leaves the hero fully composed. */
@keyframes hx1-land{from{opacity:0;transform:translateY(20px) scale(.962)}to{opacity:1;transform:none}}
@keyframes hx1-flash{0%{opacity:0}20%{opacity:.46}100%{opacity:0}}
.hx1-slab{animation:hx1-land .74s cubic-bezier(.16,1,.3,1) both}
.hx1-flash{
    position:absolute;inset:0;z-index:5;pointer-events:none;
    border-radius:.467em;background:#fff;opacity:0;
    animation:hx1-flash .6s ease-out .2s both;
}

/* the value plate — the pedestal, composed from rip-ui's own notched panel */
.hx1-plate{
    width:min(304px,90vw);margin:12px 0 0;padding:12px 14px 13px;
    text-align:left;animation:hx1-land .74s cubic-bezier(.16,1,.3,1) .12s both;
}
.hx1-plate__tags{font-family:var(--rip-data);font-size:13px;font-weight:700;
    letter-spacing:.07em;text-transform:uppercase;color:var(--rip-fg-2)}
/* tier colour = data. The raw hue measured 4.44:1 on the plate — under AA — so
   it takes the SAME lift .hm-tier__n and .hm-lb__meta i already use: mixed 58%
   toward white, which still reads as the tier and clears AA. Plain colour first
   as the fallback for anything without color-mix. */
.hx1-plate__tier{color:var(--hx1-tc,var(--rip-t-neutronium));
    color:color-mix(in srgb,var(--hx1-tc,var(--rip-t-neutronium)) 58%,#ffffff)}
.hx1-plate__name{display:block;font-family:var(--rip-body);font-size:15px;font-weight:800;
    color:var(--rip-fg);line-height:1.25;margin-top:5px;letter-spacing:-.012em}
.hx1-plate__row{display:flex;align-items:flex-end;justify-content:space-between;gap:10px;margin-top:6px}
/* the price: amber, mono, and the biggest thing in the block — this is the
   number the whole product rests on being real */
.hx1-plate__val{font-family:var(--rip-data);font-size:30px;font-weight:800;line-height:1;
    color:var(--rip-val);font-variant-numeric:tabular-nums;letter-spacing:-.02em}
/* 13px is the CEILING here, not a starting point: this is the only readable
   restatement of the set and the grade, so it is what makes the 5.4px slab
   label legitimate mimicry rather than the only place those facts live — and it
   is right-aligned against a 30px price inside a 304px plate. */
.hx1-plate__meta{font-family:var(--rip-data);font-size:13px;font-weight:700;letter-spacing:.03em;
    text-transform:uppercase;color:var(--rip-fg-2);text-align:right;line-height:1.35;padding-bottom:2px}

/* NO CYAN IN THE HEADLINE. Cyan is the one action colour, so a cyan phrase
   directly above a cyan button is a second thing that looks clickable. The
   hierarchy is carried by weight of ink — grey setup, white invitation — and
   the button ends up the only cyan object on the screen. */
.hx1-h1,.hx1-lede,.hx1-stage .hm-cta,.hx1-stage .hm-proof{width:100%;max-width:560px}
.hx1-h1{font-family:var(--rip-display);font-weight:800;letter-spacing:-.032em;
    line-height:1.03;font-size:clamp(29px,7.9vw,56px);margin:22px 0 0;
    color:var(--rip-fg-2);text-wrap:balance}
.hx1-h1 em{font-style:normal;color:var(--rip-fg)}
.hx1-lede{color:var(--rip-fg-2);font-size:clamp(14.5px,3.9vw,18px);line-height:1.45;
    margin:12px auto 0;max-width:40ch;text-wrap:balance}

@media(min-width:900px){
    .hx1-stage{flex-direction:row;align-items:center;gap:clamp(40px,5vw,72px);text-align:left}
    .hx1-copy{display:flex;flex-direction:column;align-items:flex-start;flex:1 1 auto;min-width:0}
    .hx1-pull{flex:0 0 auto}
    .hx1-eyebrow{margin:0 0 20px}
    .hx1-h1{margin:0;max-width:none}
    .hx1-slab{width:296px;font-size:29.6px}
    .hx1-plate{width:296px;margin:14px 0 0}
    .hx1-plate__val{font-size:34px}
    .hx1-lede{margin:14px 0 0;max-width:52ch}
    .hx1-stage .hm-cta{align-items:flex-start;margin-top:26px;width:auto}
    .hx1-stage .hm-cta .rip-btn{width:auto}
    .hx1-stage .hm-proof{margin:28px 0 0;max-width:520px}
    /* There was a `.hx1-proof__l{font-size:11px}` here. The class does not
       exist — the proof strip is the shared .hm-proof__l — so it painted
       nothing, and "fixing" the typo would have put the desktop label back
       under the 13px floor. Deleted rather than corrected. */
}
@media(prefers-reduced-motion:reduce){
    .hx1-slab,.hx1-plate{animation:none}
    .hx1-flash{display:none}
}

/* ══ HERO 2 · "THE LADDER" ═══════════════════════════════════════════════
   The hero IS the tier ladder: eight rungs, bottom-aligned, each wider and
   taller than the last, so the strip physically climbs from the $25 pack to
   the $5,000 one.                                                          */
.hx2{position:relative;padding:26px 0 34px;overflow:hidden}
.hx2::before{
  content:'';position:absolute;inset:0;pointer-events:none;
  background:
    radial-gradient(520px 300px at 84% 34%,rgba(239,68,68,.11),transparent 68%),
    radial-gradient(460px 300px at 6% 8%,rgba(46,230,214,.07),transparent 66%);
}
.hx2-in{position:relative;max-width:var(--rip-maxw);margin:0 auto;padding:0 16px}
.hx2-eyebrow{font-family:var(--rip-data);font-size:11.5px;font-weight:800;letter-spacing:.16em;
  text-transform:uppercase;color:var(--rip-act);margin:0 0 12px}
.hx2-h1{font-family:var(--rip-display);font-weight:800;letter-spacing:-.032em;line-height:1.02;
  font-size:clamp(33px,9.2vw,58px);margin:0;text-wrap:balance}
.hx2-h1 .hx2-money{color:var(--rip-val)}          /* amber, because it is money */
.hx2-h1 em{font-style:italic;color:var(--rip-fg)}
.hx2-lede{color:var(--rip-fg-2);font-size:15px;line-height:1.45;max-width:31ch;margin:11px 0 0}

.hx2-ladder{
  --w0:88px;--step:6px;
  margin:15px -16px 0;padding:6px 16px 2px;
  overflow-x:auto;overflow-y:hidden;
  scroll-snap-type:x proximity;-webkit-overflow-scrolling:touch;scrollbar-width:none;
  /* edge fade tells the thumb there is more to the right. A mask, not a light. */
  -webkit-mask-image:linear-gradient(90deg,#000 0,#000 88%,transparent 100%);
          mask-image:linear-gradient(90deg,#000 0,#000 88%,transparent 100%);
}
.hx2-ladder::-webkit-scrollbar{display:none}
.hx2-track{display:flex;align-items:flex-end;gap:9px;width:max-content;margin-inline:auto}
.hx2-rung{flex:0 0 auto;width:calc(var(--w0) + var(--i) * var(--step));
  scroll-snap-align:center;display:flex;flex-direction:column}
.hx2-rung__art{
  position:relative;width:100%;aspect-ratio:5/7;border-radius:10px;overflow:hidden;
  border:1px solid var(--tc);
  background:linear-gradient(180deg,rgba(255,255,255,.055),rgba(0,0,0,.34));
  box-shadow:0 12px 26px rgba(0,0,0,.5);
}
.hx2-rung__tex{position:absolute;inset:0;background-size:cover;background-position:center;
  opacity:.34;filter:saturate(.7)}
.hx2-rung__art img{position:absolute;inset:0;width:100%;height:100%;object-fit:contain;
  padding:7% 8% 11%;filter:drop-shadow(0 6px 12px rgba(0,0,0,.55))}
.hx2-rung__grade{position:absolute;top:5px;left:5px;z-index:2;
  font-family:var(--rip-data);font-size:11px;font-weight:800;letter-spacing:.03em;
  color:var(--rip-fg);background:rgba(4,7,12,.78);border:1px solid rgba(255,255,255,.14);
  border-radius:999px;padding:2px 6px}
/* the rung's own colour restated as a bar — what makes eight separate colours
   read as one ordered set */
.hx2-rung__bar{height:3px;border-radius:2px;background:var(--tc);margin-top:8px}
.hx2-rung__n{font-family:var(--rip-data);font-size:13px;font-weight:800;letter-spacing:.02em;
  text-transform:uppercase;color:var(--tc);margin-top:7px;white-space:nowrap}
.hx2-rung__p{font-family:var(--rip-data);font-size:clamp(16px,4.4vw,20px);font-weight:800;
  line-height:1.12;color:var(--rip-fg);margin-top:2px;
  font-variant-numeric:tabular-nums;white-space:nowrap}
.hx2-rung__c{font-family:var(--rip-data);font-size:13px;font-weight:700;
  color:var(--rip-val);margin-top:4px;white-space:nowrap}

/* the range rail — always fully visible, even before you scroll */
.hx2-rail{margin-top:16px}
.hx2-rail__bar{height:5px;border-radius:3px;
  background:linear-gradient(90deg,
    #7c3aed 0 12.5%,#94a3b8 12.5% 25%,#f59e0b 25% 37.5%,#e11d48 37.5% 50%,
    #c0ccd8 50% 62.5%,#38bdf8 62.5% 75%,#818cf8 75% 87.5%,#ef4444 87.5% 100%)}
.hx2-rail__ends{display:flex;justify-content:space-between;align-items:baseline;margin-top:6px;
  font-family:var(--rip-data);font-size:12px;font-weight:800;letter-spacing:.03em;color:var(--rip-fg-2)}
.hx2-rail__mid{font-size:11px;font-weight:800;letter-spacing:.1em;text-transform:uppercase;color:var(--rip-fg-2)}

/* This hero is left-aligned, so the shared centred CTA/proof are re-anchored
   rather than re-declared. */
.hx2 .hm-cta{align-items:flex-start}
.hx2 .hm-proof{margin-left:0;margin-right:0}

/* the rungs climb in on load. Motion is the only decoration here. */
.hx2-rung{animation:hx2-rise .52s cubic-bezier(.2,.8,.25,1) both;animation-delay:calc(var(--i) * 55ms)}
@keyframes hx2-rise{from{opacity:0;transform:translateY(16px)}to{opacity:1;transform:none}}
@media (prefers-reduced-motion:reduce){.hx2-rung{animation:none}}

@media (min-width:700px){
  .hx2{padding:44px 0 48px}
  /* w0 + step + gap are budgeted so all eight rungs fit inside --rip-maxw
     without scrolling: 8*94 + 28*8 + 7*12 = 1060 <= 1072 of content box. */
  .hx2-ladder{--w0:94px;--step:8px;margin-top:26px;-webkit-mask-image:none;mask-image:none}
  .hx2-track{gap:12px}
  .hx2-lede{font-size:17px;max-width:44ch}
  .hx2 .hm-cta .rip-btn{width:auto}
  .hx2-rung__n,.hx2-rung__c{font-size:13px}
}
@media (min-width:1000px){
  .hx2-in{padding:0 24px}
  .hx2-ladder{padding-left:24px;padding-right:24px;margin-left:-24px;margin-right:-24px}
}

/* ══ HERO 3 · "THE WALL" ═════════════════════════════════════════════════
   A drifting wall of real card art with the offer over it. The scrim is not a
   black box — three cooperating layers:
     1  .hx3-veil   ink gradient + vignette + the product's own cyan bloom;
     2  .hx3-focus  a masked backdrop-filter, so the imagery physically goes
                    OUT OF FOCUS under the type instead of being covered up;
     3  the type's own weight.
   No gloss. Nothing sweeps across the imagery, ever.                       */
.hx3{
  position:relative;overflow:hidden;isolation:isolate;
  background:var(--rip-bg-2);border-bottom:1px solid var(--rip-line);
  /* 772 and not 844: the real /rip/ header sits above this, and the proof row
     has to land inside a 390x844 phone WITH that header on top. */
  min-height:min(100svh,772px);
  display:flex;align-items:flex-end;
  padding:104px 0 28px;
}
.hx3-wall{position:absolute;inset:-7% -3% -3%;z-index:0;
  display:grid;grid-template-columns:repeat(5,1fr);gap:6px;pointer-events:none}
.hx3-col{
  display:grid;gap:6px;align-content:start;
  margin-top:var(--off,0);          /* stagger — not a transform, so the 50%
                                       animation loop stays exact */
  animation:hx3-drift var(--d,110s) linear infinite;
  animation-direction:var(--dir,normal);
  animation-delay:calc(var(--d,110s) * -0.41);
  will-change:transform;
}
/* Columns 6-10 are for wider viewports; hiding them holds the phone to five. */
.hx3-col--6,.hx3-col--7,.hx3-col--8,.hx3-col--9,.hx3-col--10{display:none}
@keyframes hx3-drift{
  from{transform:translate3d(0,0,0)}
  to  {transform:translate3d(0,calc(-50% - 3px),0)}
}
.hx3-tile{
  position:relative;display:block;aspect-ratio:5/7;border-radius:7px;overflow:hidden;
  background:linear-gradient(163deg,rgba(255,255,255,.07),rgba(255,255,255,.01) 46%,rgba(0,0,0,.34));
  box-shadow:inset 0 0 0 1px rgba(255,255,255,.07);
}
.hx3-tile img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;display:block}

.hx3-veil{
  position:absolute;inset:0;z-index:1;pointer-events:none;
  background:
    radial-gradient(900px 360px at 50% -8%,rgba(46,230,214,.11),transparent 62%),
    radial-gradient(122% 78% at 50% 26%,transparent 34%,rgba(4,6,11,.76) 100%),
    linear-gradient(180deg,rgba(7,10,16,.14) 0%,rgba(7,10,16,.34) 26%,rgba(7,10,16,.78) 55%,
      rgba(7,10,16,.88) 74%,rgba(7,10,16,.90) 90%,var(--rip-bg) 100%);
}
.hx3-focus{
  position:absolute;left:0;right:0;bottom:0;height:74%;z-index:2;pointer-events:none;
  -webkit-backdrop-filter:blur(17px) saturate(.66);backdrop-filter:blur(17px) saturate(.66);
  -webkit-mask-image:linear-gradient(180deg,transparent 0%,rgba(0,0,0,.55) 22%,#000 46%,#000 100%);
          mask-image:linear-gradient(180deg,transparent 0%,rgba(0,0,0,.55) 22%,#000 46%,#000 100%);
}
.hx3-in{position:relative;z-index:3;width:100%;max-width:var(--rip-maxw);margin:0 auto;
  padding:0 18px;text-align:center}
.hx3-eyebrow{
  display:inline-flex;align-items:center;gap:9px;
  font-family:var(--rip-data);font-size:11.5px;font-weight:700;letter-spacing:.1em;
  text-transform:uppercase;color:var(--rip-fg-2);
  border:1px solid var(--rip-line-2);background:rgba(7,10,16,.55);
  padding:6px 13px;border-radius:999px;margin:0 0 16px;
  /* ⚠ ONE LINE, ALWAYS. Wrapped, this reads as two unrelated fragments stacked
     inside a pill, and it is the first thing on the page. At 11.5px with .1em
     tracking, 36 characters plus the tick, the gap and the padding came to more
     than a 390px phone has, so it broke. The step below shaves tracking and size
     on narrow screens rather than letting it wrap. */
  white-space:nowrap;
  -webkit-backdrop-filter:blur(7px);backdrop-filter:blur(7px);
}
.hx3-eyebrow svg{width:11px;height:11px;flex:none;display:block}
/* 9.0vw + the tighter tracking is what keeps line one on ONE line at 390px.
   Three lines would push the button off the fold, which is the only thing
   this hero exists to deliver. */
.hx3-h1{font-family:var(--rip-display);font-weight:800;
  font-size:clamp(30px,9.0vw,74px);line-height:.98;letter-spacing:-.042em;
  margin:0;color:var(--rip-fg);text-shadow:0 2px 26px rgba(4,6,11,.92),0 1px 3px rgba(4,6,11,.8)}
.hx3-h1 em{font-style:italic;display:block;color:var(--rip-fg)}
.hx3-lede{margin:12px auto 0;max-width:44ch;font-size:15px;line-height:1.45;
  color:var(--rip-fg-2);text-shadow:0 1px 14px rgba(4,6,11,.9)}
.hx3 .hm-cta .rip-btn{box-shadow:0 8px 30px rgba(46,230,214,.30),0 2px 0 rgba(0,0,0,.3)}
/* 2x2 on a phone so nothing is squeezed, and the tiles sit on the wall rather
   than in a solid block. */
.hx3 .hm-proof{grid-template-columns:1fr 1fr;gap:8px;background:none;border:0;border-radius:0}
.hx3 .hm-proof__i{border-radius:var(--rip-r-sm);background:rgba(9,13,20,.62);
  border:1px solid var(--rip-line);-webkit-backdrop-filter:blur(9px);backdrop-filter:blur(9px)}

@media (min-width:600px){
  .hx3 .hm-proof{grid-template-columns:repeat(4,1fr);max-width:640px}
}
@media (min-width:760px){
  .hx3{min-height:min(96svh,720px);padding:132px 0 42px}
  .hx3-wall{grid-template-columns:repeat(7,1fr);gap:8px}
  .hx3-col--6,.hx3-col--7{display:grid}
  .hx3-col{gap:8px}
  .hx3-tile{border-radius:9px}
  @keyframes hx3-drift{
    from{transform:translate3d(0,0,0)}
    to  {transform:translate3d(0,calc(-50% - 4px),0)}
  }
  .hx3-lede{font-size:17px}
  .hx3-focus{height:64%}
}
@media (min-width:1080px){
  .hx3-wall{grid-template-columns:repeat(10,1fr)}
  .hx3-col--8,.hx3-col--9,.hx3-col--10{display:grid}
  .hx3 .hm-proof{max-width:760px}
}
@media (prefers-reduced-motion:reduce){.hx3-col{animation:none}}

/* ══════════════════════════════════════════════════════════════════════════
   THE PAGE BODY

   Every block below replaced a paragraph. Where the old page explained a
   feature in 30 words, this shows the feature and labels it in four.
   ══════════════════════════════════════════════════════════════════════════ */

/* ── how it works: one clip, three labels ──────────────────────────────────
   .hm-flow, .hm-swatches and .hm-pockets are gone (2026-08-10). They built
   three bordered step cards, two of which drew a small, worse copy of a block
   the page renders properly a screen or two later — eight colour swatches
   against the eight-tier ladder, four binder pockets against the binder
   recording. The rules they needed were the fiddliest in this sheet: a
   104px phone rail, a min-width:0 on both grid items because a <video> carries
   an intrinsic width attribute, an 820px breakpoint that switched the swatch
   grid from 8 columns to 4 and un-hid the prices, and a display:none on those
   prices that hid an AA contrast failure from every phone-width review.

   What replaced all of it: the clip at full width, and three labels in a row
   under it. Numbered because it genuinely is a sequence — you cannot keep a
   card you have not pulled. */
/* ⚠ `margin:13px auto 0`, NOT `13px 0 0`. The 700px column rule further up
   centres this row with margin-left/right:auto — and this shorthand, being
   later in the file at the same specificity, was resetting both back to 0.
   The clip above it centred, the steps under it did not: measured at 1245px
   the clip ran 273→973 and this row 81→781, a 192px offset between two things
   that are meant to be the same object. */
.hm-run{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:9px;
    margin:13px auto 0;padding:0;list-style:none}
.hm-run li{display:flex;align-items:baseline;gap:7px;min-width:0;
    font-family:var(--rip-display);font-weight:800;font-size:15px;letter-spacing:-.018em;
    line-height:1.25;color:var(--rip-fg)}
/* cyan on the ordinal only. It is the one place on this row that is not a word,
   so it can carry the accent without competing with the button. */
.hm-run b{flex:none;font-family:var(--rip-data);font-size:13px;font-weight:800;
    letter-spacing:.08em;color:var(--rip-act)}
/* ⚠ THE ORDINAL GOES ABOVE THE LABEL ON A PHONE, AND IT IS NOT A STYLE CHOICE.
   Three columns of a 354px row are 112px each. Inline, the ordinal and its gap
   take 29 of that and "Pick a pack" needs 88 — four pixels over, so step 01
   alone wrapped to two lines while 02 and 03 stayed on one, and the row read as
   a mistake. Stacked, the label gets the full 112px and fits, and all three
   items are the same shape. The row is the same height either way (~38px); this
   only decides whether it looks deliberate. */
@media(max-width:480px){
    .hm-run li{flex-direction:column;align-items:flex-start;gap:2px}
}

/* the stand-in when a clip is missing from disk — a labelled empty frame at the
   clip's own ratio, so the layout is identical with or without the file and it
   can never be mistaken for footage. Named .hm-ph, not .hm-flow__ph: the flow it
   was named after no longer exists, and this sheet has already been bitten once
   by rules that depended on an ancestor block that got folded away (see the
   note by .hm-chase__box's removal). A component's class travels with it. */
.hm-ph{
    aspect-ratio:1000/624;border-radius:var(--rip-r-sm);border:1px dashed var(--rip-line-2);
    display:flex;align-items:center;justify-content:center;
    font-family:var(--rip-data);font-size:12px;font-weight:800;letter-spacing:.2em;
    color:var(--rip-fg-3);background:var(--rip-bg-2);
}

/* ── the tier ladder ───────────────────────────────────────────────────────
   A rail on a phone, because eight of anything in a column is a scroll and
   not a comparison. The negative margin + matching padding keeps the rail
   bleeding to both screen edges WITHOUT the page itself gaining a horizontal
   scrollbar.                                                                */
.hm-ladder{
    display:grid;grid-auto-flow:column;grid-auto-columns:minmax(132px,1fr);gap:11px;
    overflow-x:auto;padding:2px 18px 14px;margin:0 -18px;
    scroll-snap-type:x proximity;-webkit-overflow-scrolling:touch;
    scrollbar-width:thin;scrollbar-color:var(--rip-panel-3) transparent;
}
/* ⚠ ALL EIGHT IN ONE ROW ONCE THERE IS ROOM, NOT TWO ROWS OF FOUR.
   Four-up made each card 260px wide, so eight 5:7 scans stacked to 899px — the
   ladder alone was two thirds of the packs section at 1280px, and a ladder
   split over two rows stops being a ladder: the whole point is that you read
   $25 → $5,000 in one sweep. Eight-up gives ~120px a column at 1100px, which is
   the same size the phone rail already uses (132px min), and the section drops
   from 1,259 to well under half that.
   1100 and not 900: at 900px eight columns are 96px and "NEUTRONIUM" at 13px
   needs ~90 — inside the column but with nothing left for the ceiling figure
   under it, so the four-up step stays for that band. */
@media(min-width:900px){
    .hm-ladder{grid-auto-flow:row;grid-template-columns:repeat(4,1fr);overflow:visible;
               padding:0;margin:0;gap:14px}
}
@media(min-width:1100px){
    .hm-ladder{grid-template-columns:repeat(8,minmax(0,1fr));gap:10px}
}
.hm-tier{scroll-snap-align:start;display:flex;flex-direction:column;min-width:0}
.hm-tier__art{
    position:relative;display:block;aspect-ratio:5/7;border-radius:10px;overflow:hidden;
    border:1px solid var(--tc);box-shadow:0 12px 26px rgba(0,0,0,.5);
    background:linear-gradient(180deg,rgba(255,255,255,.055),rgba(0,0,0,.34));
}
/* the tier's own slab photograph, behind its own record card */
.hm-tier__tex{position:absolute;inset:0;background-size:cover;background-position:center;
    opacity:.34;filter:saturate(.7)}
.hm-tier__art img{position:absolute;inset:0;width:100%;height:100%;object-fit:contain;
    padding:7% 8% 11%;filter:drop-shadow(0 6px 12px rgba(0,0,0,.55))}
.hm-tier__g{
    position:absolute;top:5px;left:5px;z-index:2;
    font-family:var(--rip-data);font-size:13px;font-weight:800;letter-spacing:.03em;
    color:var(--rip-fg);background:rgba(4,7,12,.78);border:1px solid rgba(255,255,255,.14);
    border-radius:999px;padding:2px 6px;
}
/* The tier's NAME and its CEILING are the core data of this page, and they
   shipped at 10px — smaller than the grade badge on the card above them. 13px
   is the floor; the tracking comes off to pay for the width inside a 132px
   rail column.
   The colour stays the tier's own, because it is data — but three of the eight
   (Starter #7c3aed at 3.39:1, Sensei #e11d48 at 4.11:1) fail AA as text on the
   dark canvas. color-mix lifts each one toward white by a fixed amount, so the
   hue still identifies the pack while the text clears AA. The plain
   `color:var(--tc)` above it is the fallback for anything without color-mix. */
.hm-tier__n{font-family:var(--rip-data);font-size:13px;font-weight:800;letter-spacing:.02em;
    text-transform:uppercase;color:var(--tc);
    color:color-mix(in srgb,var(--tc) 58%,#ffffff);margin-top:9px}
.hm-tier__p{font-family:var(--rip-data);font-size:20px;font-weight:800;line-height:1.12;
    color:var(--rip-fg);margin-top:2px;font-variant-numeric:tabular-nums}
.hm-tier__c{font-family:var(--rip-data);font-size:13px;font-weight:700;
    color:var(--rip-val);margin-top:4px}      /* amber, because it is money */

/* .hm-grails / .hm-grail — the six-card "real prices" strip — and the whole
   .hm-chase block (rays, the CHASE! word mark, its caption and its paragraph)
   were removed on 2026-08-10 with the sections that held them. Between them
   they were 606px of the packs section's 1,309, and both were second copies:
   the strip sat directly under a ladder already showing eight real cards, and
   the chase dramatised in CSS the exact moment the "How it works" clip shows
   happening for real. The top-card figure the strip existed to prove is now one
   computed number in that section's .hm-data line.

   Two rules that lived here are worth remembering rather than the components
   themselves. .hm-chase__rays was 564px wide and had to clip itself once its
   parent section was folded away — unclipped it pushed a 390px page to 477px of
   real horizontal scroll. And h2.hm-chase__cap needed its class doubled to beat
   rip-ui.css's `.rip-ui h2 {margin:0}` at (0,1,1), because the ancestor it had
   been borrowing specificity from no longer existed. Both are the same lesson:
   a rule that depends on an ancestor block breaks silently when the block moves.

   .hm-comp (the completion figure and its eight per-tier bars) and .hm-pl /
   .hm-pls (the two spend-against-value panels) went the same way and for the
   stated reason: each was a hand-drawn illustration of a screen that the clip
   beside it was playing for real. Only the caption survives, because a caption
   under a figure is still needed. */

/* the caption under a figure that is an example rather than live data.
   Sentence case, body face — these were two- and three-word labels ("Up, and
   down") where uppercase mono read as a data label; as sentences, 13px
   letter-spaced uppercase across two lines reads as shouting. */
.hm-comp__l{font-family:var(--rip-body);font-size:13px;font-weight:600;
    color:var(--rip-fg-3);margin:10px 0 0;line-height:1.5;text-wrap:pretty}

/* ── the daily allowance ───────────────────────────────────────────────────
   A ladder of numbers and nothing else. The flame is an inline SVG at a fixed
   pixel size and never an emoji: this row is width-budgeted, and an emoji
   measures ~1.25em on a real phone against ~0.6em in a headless check, so a
   break here cannot be caught before it ships.                              */
.hm-streak{border:1px solid var(--rip-line);border-radius:var(--rip-r);background:var(--rip-panel);padding:16px}
.hm-streak__base{display:flex;align-items:baseline;gap:8px;padding-bottom:10px;
    border-bottom:1px solid var(--rip-line);margin-bottom:10px}
.hm-streak__base b{font-family:var(--rip-data);font-size:34px;font-weight:800;line-height:1;
    color:var(--rip-fg);letter-spacing:-.03em}
.hm-streak__base span{font-family:var(--rip-data);font-size:13px;font-weight:700;
    letter-spacing:.07em;text-transform:uppercase;color:var(--rip-fg-2)}
/* ⚠ TWO RUNGS TO A ROW, NOT SIX STACKED. Six full-width rows put a 66px chip
   and a two-character bonus on a 322px line and spent 150px of a 390px phone on
   the whitespace between them. Paired, the same six numbers are three rows and
   ~75px, and each row still reads left-to-right as "day → bonus". The rungs
   also no longer carry an inline --w: the old ladder widened each chip by 13%
   per step to draw a staircase, which in two columns would just look ragged. */
.hm-streak__rungs{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:6px 12px}
.hm-streak__r{display:flex;align-items:center;justify-content:space-between;gap:10px;
    line-height:1;min-width:0}
.hm-streak__d{
    display:inline-flex;align-items:center;gap:5px;flex:none;
    font-family:var(--rip-data);font-size:13px;font-weight:800;letter-spacing:.03em;
    color:var(--rip-fg);background:var(--rip-panel-3);border-radius:5px;padding:4px 8px;
}
.hm-flame{width:11px;height:11px;flex:none;display:block;fill:var(--rip-val);stroke:none}
/* NOT cyan — an earned quantity is not a control. Amber is the value colour. */
.hm-streak__b{font-family:var(--rip-data);font-size:13px;font-weight:800;color:var(--rip-val)}

/* .hm-w2e — the watch-a-Short card — has had no markup since 2026-08-10
   ("it doesn't need to give every single tiny feature, like watching my shorts
   to get 2 more views"). Removed here too rather than left as an orphan. */

/* ── leaderboard rows ──────────────────────────────────────────────────── */
.hm-lb{border:1px solid var(--rip-line);border-radius:var(--rip-r);background:var(--rip-panel);overflow:hidden}
.hm-lb__head{display:flex;align-items:center;justify-content:space-between;gap:2px 12px;
    flex-wrap:wrap;                 /* same reason as .hm-media__cap */
    padding:11px 14px;border-bottom:1px solid var(--rip-line);
    font-family:var(--rip-data);font-size:13px;font-weight:800;letter-spacing:.06em;
    text-transform:uppercase;color:var(--rip-fg-2)}
.hm-lb__head b{color:var(--rip-val);font-weight:800}
.hm-lb__r{display:grid;grid-template-columns:18px 30px 1fr auto;align-items:center;gap:10px;
    padding:8px 12px;border-bottom:1px solid var(--rip-line)}
.hm-lb__r:last-child{border-bottom:0}
.hm-lb__rank{font-family:var(--rip-data);font-size:14px;font-weight:800;color:var(--rip-fg-2);text-align:center}
.hm-lb__art{position:relative;display:block;aspect-ratio:5/7;border-radius:5px;overflow:hidden;
    border:1px solid var(--tc);background:var(--rip-panel-3)}
.hm-lb__art img{position:absolute;inset:0;width:100%;height:100%;object-fit:contain}
.hm-lb__meta{min-width:0}
.hm-lb__meta b{display:block;font-size:13.5px;font-weight:800;color:var(--rip-fg);line-height:1.25;
    overflow:hidden;text-overflow:ellipsis;white-space:nowrap}
.hm-lb__meta i{display:block;font-style:normal;font-family:var(--rip-data);font-size:13px;
    font-weight:700;letter-spacing:.03em;text-transform:uppercase;color:var(--tc);
    color:color-mix(in srgb,var(--tc) 58%,#ffffff);margin-top:3px}
.hm-lb__v{font-family:var(--rip-data);font-size:14px;font-weight:800;color:var(--rip-val);
    font-variant-numeric:tabular-nums}

/* .hm-tabs / .hm-seg were an aria-hidden DRAWING of the leaderboard's tab bar
   and its day/month/all segment, sitting in the second column of a .hm-pair
   beside the real board. A picture of chrome is not a picture of the product,
   and it cost a phone-width guard of its own — the segment is inline-flex with
   overflow:hidden, so in a 145px column it silently ATE the word "All" rather
   than reporting an overflow. The nine words it was drawing ("A board for every
   pack · day, month and all-time") are the .hm-data line under the board now. */

/* ── the prize ─────────────────────────────────────────────────────────────
   The two prize cards' own artwork — the same art packs.htm puts on the face
   of PRIZE-STARTER and PRIZE-SILVER, so the thing you chase on the page is
   the thing you see in the app. (These are card art, NOT photographs of the
   physical pack; the alt text used to claim otherwise.)                     */
/* max-width, because two 4:5 portraits across a 1084px column are 536px wide
   and 670px tall — a full desktop screen of prize artwork for a section whose
   whole content is "you can win one of these". At 560px the pair is 274x342,
   which is the same weight it carries on the phone. */
.hm-prizes{display:grid;grid-template-columns:1fr 1fr;gap:12px;
    max-width:560px;margin-left:auto;margin-right:auto}
.hm-prize{margin:0;position:relative;border-radius:var(--rip-r);overflow:hidden;
    border:1px solid rgba(242,177,52,.36);background:var(--rip-bg-2)}
/* 4:5 rather than the file's 5:7 — portrait art with headroom, and cropping
   it saves 60px of scroll on a phone. */
.hm-prize img{display:block;width:100%;height:auto;aspect-ratio:4/5;object-fit:cover;object-position:center 38%}
.hm-prize figcaption{
    position:absolute;left:0;right:0;bottom:0;padding:26px 12px 11px;
    background:linear-gradient(transparent,rgba(4,6,11,.92));
}
.hm-prize figcaption b{display:block;font-family:var(--rip-data);font-size:14px;font-weight:800;color:var(--rip-val)}
.hm-prize figcaption span{display:block;font-size:13px;color:var(--rip-fg-2);margin-top:2px}

/* .hm-steps (three numbered prize chips) and .hm-two / .hm-meter (the two amber
   meters beside them) are gone — five panels under two card images, restating in
   fragments the four sentences inside the section's own "The prize, in full"
   fold, which is unchanged and still carries every fact.

   Worth keeping the reason .hm-steps__n took a --tc-ink variable, because the
   same trap is waiting for any chip painted in a tier colour: dark ink on Sensei
   red measured 4.14:1, under AA. The tier colour is data and must not move, so
   the INK moves — white cleared it at 4.70:1.

   .hm-bubble (the share card framed as a chat post) and .hm-more (the six
   link tiles) were already dead before this rebuild — zero uses in welcome.php
   at the time it started. Removed rather than carried. */

/* ── the honest bit — three six-word lines ─────────────────────────────── */
.hm-honest{display:grid;gap:7px;margin:0 0 clamp(22px,4vw,34px);padding:0;list-style:none;text-align:left}
@media(min-width:760px){.hm-honest{grid-template-columns:repeat(3,1fr)}}
.hm-honest li{border:1px solid var(--rip-line);border-radius:var(--rip-r-sm);background:var(--rip-panel);
    padding:10px 13px;color:var(--rip-fg-2);font-size:13.5px;line-height:1.4}
.hm-honest b{font-family:var(--rip-display);font-weight:800;color:var(--rip-fg);margin-right:5px}

/* ── the close ─────────────────────────────────────────────────────────── */
.hm-end{text-align:center;padding:clamp(36px,6vw,80px) 0 clamp(32px,5vw,58px);
    border-top:1px solid var(--rip-line)}
.hm-end__h{font-family:var(--rip-display);font-weight:800;letter-spacing:-.03em;line-height:1.04;
    font-size:clamp(28px,6.4vw,50px);margin:0;color:var(--rip-fg);text-wrap:balance}
.hm-end__b{margin:24px 0 0;display:flex;justify-content:center}
.hm-end__b .rip-btn{width:100%;max-width:330px}

/* ── the one guard that survives the pair ──────────────────────────────────
   Eight of the guards that used to live here existed only because .hm-pair
   squeezed a drawn panel into a ~145px column. The pair is gone, the panels are
   gone, and so are they. This one is about the leaderboard's own content and
   still bites: "Blastoise 1st Edition" needs 156px and gets 110 at 390px, so
   nowrap + text-overflow would print "Blastoise 1st E…" on every row of a
   three-row board. Two lines costs 54px at 390 and keeps every card's name. */
@media(max-width:820px){
    .hm-lb__meta b{white-space:normal;overflow:visible;text-overflow:clip}
}

/* ── phone ─────────────────────────────────────────────────────────────────
   The page carries every feature, so on a phone the AIR comes out, never the
   content.                                                                  */
@media(max-width:560px){
    /* ⚠ THESE WERE DELIBERATELY SQUEEZED AND THAT WAS THE WRONG CALL.
       The note here read "Every number below is AIR… the tint does the work" —
       the theory being that the alternating .hm-sec--tint band could separate
       one idea from the next instead of whitespace. It cannot. 8px of section
       padding put a heading almost against the panel above it, and the tint
       only marks ALTERNATE sections, so every untinted pair ran together with
       nothing between them at all. Roughly doubled throughout, 2026-08-08.
       ⚠ The tint alternation is now load-bearing again: after the 2026-08-10
       merge there are five body sections, and welcome.php stamps --tint on the
       1st, 3rd and 5th precisely so no two untinted ones ever touch. If a
       section is added or reordered, re-check that pattern. */
    .hm-sec{padding:30px 0}
    .hm-sec__head{margin-bottom:16px}
    .hm-end{padding:38px 0 30px}
    .hm-end__b{margin-top:22px}
    .hm-honest{margin-bottom:24px}
    /* 8px, so the clip inside gets 338px of a 390px phone — the number the
       .hm-clip note's 211px height is calculated from. */
    .hm-media{padding:8px}
    .hm-prizes{gap:12px}
    .hm-streak{padding:16px}
    /* the leaderboard row loses its fourth column rather than its card name:
       rank and art span both rows, the name gets the full remaining width, and
       the value sits under it instead of competing with it for 196px. */
    .hm-lb__r{grid-template-columns:16px 30px minmax(0,1fr);gap:2px 9px;padding:8px 10px}
    .hm-lb__rank,.hm-lb__art{grid-row:1/3}
    .hm-lb__v{grid-column:3}
    .hm-det{margin-top:11px}
}

/* ── reveal ────────────────────────────────────────────────────────────────
   Sections arrive as you reach them.

   The HIDDEN state is gated on html.hm-js, stamped by an inline head script.
   Hiding unconditionally in CSS would leave a visitor with JS disabled — or
   any visitor whose JS failed to run — looking at a blank page below the
   hero, because nothing would ever arrive to add .is-in. Gate the hiding,
   not the showing. */
html.hm-js .hm-rv{opacity:0;transform:translateY(16px);transition:opacity .6s ease,transform .6s cubic-bezier(.22,.72,.3,1)}
html.hm-js .hm-rv.is-in{opacity:1;transform:none}

@media(prefers-reduced-motion:reduce){
    html.hm-js .hm-rv,html.hm-js .hm-rv.is-in{opacity:1;transform:none;transition:none}
}


/* The pill's narrow-screen step. Measured, not guessed: see the note in
   .hx3-eyebrow. Tracking goes first because it is the cheapest character-width
   saving that does not touch legibility. */
@media(max-width:412px){.hx3-eyebrow{font-size:10.5px;letter-spacing:.055em;gap:7px;padding:6px 11px}}
@media(max-width:360px){.hx3-eyebrow{font-size:9.5px;letter-spacing:.03em;gap:6px;padding:5px 9px}}
