/* Risk-free promo banner — "Open your first $25 pack"
   ---------------------------------------------------------------------------
   Composition from the 1720x780 design handoff, rebuilt fluid.

   The handoff scales a fixed 1720x780 artboard with transform. That can't work
   in this hero: `body.page-public .pv-hero .vbn` makes every banner full-bleed
   at height clamp(440px, 32vw, 520px), so the frame's aspect ratio runs from
   ~1.9:1 to ~3.7:1 depending on the window. A fixed artboard either overflows
   (width-scaled) or letterboxes (height-scaled). So the frame is `.vbn` itself,
   identical to every other slide, and the composition is expressed fluidly:

     - vertical rhythm and type in cqh, so everything tracks the frame height
     - the copy column in cqw, matching .vbn-inner's min(1680px, 100%)
     - the product group keeps its internal geometry in % of its own box, so
       pack and slab hold the handoff's relative positions and rotations at
       every size

   Every artboard number below is carried across as a fraction: 72px of 780 is
   9.23cqh, and so on. Landscape and portrait differ only in placement.

   Colour rules from the handoff, don't break these:
     --vb-emerald is ONLY the risk-free guarantee band. Never buttons.
     --vb-gold marks money and the CTA, nothing else.
     Everything else is the ink/paper ramp. No new hues. */

.vb-riskfree {
    /* palette */
    --vb-gold: #D4A017;
    --vb-gold-hover: #C98E08;
    --vb-emerald: #18745F;
    --vb-ink: #161B18;
    --vb-ink-2: #4B524D;
    --vb-muted: #69716C;
    --vb-faint: #8A918C;
    --vb-paper-0: #FBFCF9;
    --vb-paper-1: #F7F8F4;
    --vb-paper-2: #F2F4F0;
    --vb-paper-3: #EFF2EE;
    --vb-paper-4: #E7EBE6;

    /* same inset the other banners use */
    --vb-gutter: clamp(26px, 5%, 78px);

    /* type — cqh keeps the handoff's ratios; the clamps stop it collapsing on a
       short frame or running away on a tall one. The claim also caps against
       cqw because it is a nowrap line and the frame gets narrow before it gets
       short. */
    --vb-fs-eyebrow: clamp(15px, 5.64cqh, 44px);
    --vb-fs-headline: clamp(28px, 10.77cqh, 84px);
    --vb-fs-band: clamp(38px, 17.5cqh, 116px);
    --vb-fs-kicker: clamp(11px, min(4.3cqh, 1.9cqw), 30px);
    --vb-fs-claim: clamp(19px, min(7.7cqh, 3.2cqw), 54px);
    --vb-fs-cta: clamp(12px, 3.59cqh, 28px);
    /* bumped ~25% 2026-08-27 (founder: "slightly bigger") -- it is still legal
       fine print, so it stays well under --vb-fs-cta at every size. */
    --vb-fs-legal: clamp(7.5px, 1.85cqh, 14px);

    container-type: size;
    font-family: 'Space Grotesk', system-ui, sans-serif;
    color: var(--vb-ink);
    /* Cream on the left warming into gold on the right, over the handoff's
       paper ramp. Drawn from --vb-gold rather than a new hue. It stays clear
       behind the copy column and only comes up under the product art, so the
       ink keeps its contrast. */
    background:
        linear-gradient(95deg,
            rgba(212, 160, 23, 0) 0%,
            rgba(212, 160, 23, .07) 38%,
            rgba(212, 160, 23, .18) 68%,
            rgba(212, 160, 23, .31) 100%),
        radial-gradient(ellipse 92% 132% at 70% 36%,
            var(--vb-paper-0) 0%, var(--vb-paper-1) 40%, var(--vb-paper-2) 70%,
            var(--vb-paper-3) 88%, var(--vb-paper-4) 100%);
}

/* No border, no inner glow. The handoff's inset hairline + white glow both read
   as edge artefacts at this frame size (founder call) — the banner is a flat
   paper field. */

/* The handoff's ambient radials were authored as 520px/420px circles on a
   1720x780 board — broad and barely-there. At 214px tall they shrink to ~141px
   and land right on top of the pack and slab, reading as a blue field around
   the product rather than ambience. Removed (founder call). Kept as an empty
   layer so the markup and DOM order are unchanged. */
.vb-wash {
    position: absolute;
    inset: 0;
    z-index: 0;
    pointer-events: none;
}

/* ---- copy column: mirrors .vbn-inner so the text lines up with the other
       banners' text at every width ---- */
.vb-inner {
    position: absolute;
    top: 0;
    left: 50%;
    z-index: 3;
    width: min(1680px, 100cqw);
    height: 100%;
    transform: translateX(-50%);
}

/* Children are absolutely positioned, so they inset themselves with
   --vb-gutter; padding on .vb-inner would not reach them. */

/* ---- headline: OPEN YOUR FIRST $25 PACK ---- */
.vb-headline {
    position: absolute;
    left: var(--vb-gutter);
    top: 9.23cqh;
    margin: 0;
    display: flex;
    align-items: baseline;
    gap: .21em;
    line-height: 1;
    white-space: nowrap;
}

.vb-headline__lede {
    font-size: var(--vb-fs-eyebrow);
    font-weight: 600;
    letter-spacing: .005em;
    color: var(--vb-ink-2);
    /* Cap-align with "$25 PACK" instead of sharing its baseline. The row is
       baseline-aligned, so the smaller lede sits low; lift it by the cap-height
       difference. Space Grotesk cap height is ~0.70em, so the gap between the two
       cap tops is 0.70 x (headline size - eyebrow size). Expressed against the
       two variables so it stays right as both scale with the frame. */
    position: relative;
    top: calc((var(--vb-fs-eyebrow) - var(--vb-fs-headline)) * 0.74);
}

.vb-headline__price,
.vb-headline__noun {
    font-size: var(--vb-fs-headline);
    font-weight: 700;
    letter-spacing: .02em;
}

.vb-headline__price { color: var(--vb-gold); }
.vb-headline__noun { color: var(--vb-ink); }

/* ---- guarantee band: rotated bar bleeding off both edges, high left / low
       right. Sits outside .vb-inner because it spans the full frame, not the
       copy column; the label inside re-centres on the copy column. ---- */
.vb-band {
    position: absolute;
    left: -50%;
    top: 35.6cqh;
    z-index: 1;
    width: 200%;
    height: 31cqh;
    transform: rotate(4.5deg);
    background: var(--vb-emerald);
    box-shadow: 0 36px 76px rgba(24, 116, 95, .22);
}

.vb-band__row {
    position: absolute;
    left: 50%;
    top: 0;
    display: flex;
    align-items: center;
    width: min(1680px, 100cqw);
    height: 100%;
    padding-inline: var(--vb-gutter);
    transform: translateX(-50%);
}

.vb-band__label {
    font-size: var(--vb-fs-band);
    font-weight: 700;
    letter-spacing: .06em;
    line-height: 1.086;
    color: var(--vb-paper-1);
    white-space: nowrap;
    /* Space Grotesk tops out at 700 and the site only loads 400-700, so there is
       no heavier face to jump to. Thicken the strokes optically instead, in the
       fill colour so the weight changes and nothing else. */
    -webkit-text-stroke: .022em var(--vb-paper-1);
    paint-order: stroke fill;
}

/* ---- product: pack + graded slab. The group holds the handoff's internal
       geometry (x 1074-1532, y 82-697 on the artboard) in its own %, so the two
       pieces keep their overlap and rotations at any size. Slab is later in DOM
       so it overlaps the pack — keep that order. ---- */
.vb-product {
    position: absolute;
    right: var(--vb-gutter);
    top: 6.5cqh;
    z-index: 2;
    height: 85cqh;          /* up from 78.85 — reads too small in this short frame.
                               Sits high so the -6deg slab and its shadow clear
                               the bottom edge. */
    aspect-ratio: 458 / 615;
}

.vb-pack {
    position: absolute;
    left: 0;
    top: 0;
    width: 74.24%;
    height: 78.05%;
}

.vb-pack img {
    width: 100%;
    height: 100%;
    object-fit: contain;
    display: block;
    transform: rotate(11deg);
    filter: drop-shadow(0 34px 56px rgba(22, 27, 24, .3));
}

/* The scan is cropped tight to the slab, so the plastic's rounded corners are
   not in the file and it reads as a hard rectangle. The radius is restored here
   as a PERCENTAGE pair, not a fixed px: a real PSA slab's corner is ~4.5% of its
   width, and the two values (4.5% horizontal / 2.65% vertical) keep the corner
   circular on a 182x310 box instead of elliptical. Being a % it holds at every
   size, which a fixed 9px could not — that was the original problem. */
.vb-slab {
    position: absolute;
    left: 48.47%;
    top: 34.80%;
    width: 51.53%;
    height: 65.20%;
    border-radius: 4.5% / 2.65%;
    overflow: hidden;
    transform: rotate(-6deg);
    box-shadow: 0 30px 60px rgba(22, 27, 24, .3), 0 5px 14px rgba(22, 27, 24, .16), 0 0 0 1px rgba(22, 27, 24, .08);
}

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

/* ---- buyback claim ---- */
.vb-claim {
    position: absolute;
    left: var(--vb-gutter);
    top: 69cqh;
    display: flex;
    flex-direction: column;
    align-items: flex-start;
}

.vb-claim__kicker {
    font-size: var(--vb-fs-kicker);
    font-weight: 600;
    letter-spacing: .02em;
    line-height: 1.2;
    color: var(--vb-muted);
    white-space: nowrap;
}

.vb-claim__line {
    display: flex;
    align-items: baseline;
    gap: .33em;
    margin-top: 1.03cqh;
    font-size: var(--vb-fs-claim);
    font-weight: 700;
    line-height: 1.148;
    letter-spacing: -.02em;
    white-space: nowrap;
}

.vb-claim__text { color: var(--vb-ink); }
.vb-claim__amount { color: var(--vb-gold); }

/* ---- CTA + legal: one row, legal to the right of the pill ---- */
.vb-actions {
    position: absolute;
    left: var(--vb-gutter);
    top: 86.3cqh;
    display: flex;
    align-items: center;
    gap: clamp(12px, 2.2cqh, 30px);
}

.vb-cta {
    display: flex;
    align-items: center;
    justify-content: center;
    height: 11.03cqh;
    min-height: 34px;
    padding-inline: 1.9em;
    border-radius: 999px;
    background: var(--vb-gold);
    font-size: var(--vb-fs-cta);
    font-weight: 700;
    letter-spacing: .12em;
    color: #FFFFFF;
    white-space: nowrap;
    text-decoration: none;
}

a.vb-cta:hover,
a.vb-cta:focus-visible { background: var(--vb-gold-hover); color: #FFFFFF; }

.vb-legal {
    position: absolute;
    /* sits tighter to the corner than the copy gutter */
    right: clamp(7px, 2.4%, 26px);
    bottom: 3.4cqh;
    z-index: 6;
    font-size: var(--vb-fs-legal);
    font-weight: 500;
    letter-spacing: .06em;
    line-height: 1.33;
    color: var(--vb-faint);
    white-space: nowrap;
    /* not interactive -- see index.html. pointer-events:none so it can never
       swallow a tap meant for the banner's own hit target underneath it. */
    pointer-events: none;
}

/* the two-line claim break is portrait-only; wide keeps the words inline */
.vb-claim__break { display: none; }
.vb-claim__lead { display: inline; }

/* ===========================================================================
   `square` artboard — 1200 x 840 (1.43:1), <=820px

   This is the handoff's second shipped shape, carried across verbatim in
   proportion. It is the right one for this hero's mobile frame: the shared
   banner rules make every campaign banner a short wide strip here, not a
   portrait card —

     <=820px  .pv-hero padding 8px; .vbn-campaign min-height 500px, radius 16px
     <=520px  .vbn-campaign height 214px !important

   so a 390px phone frame is 374x214 (1.75:1) and a 780px tablet is 764x500
   (1.53:1). `square` at 1.43:1 sits right in that band; the `wide` 2.21:1
   composition would not fit, which is why the handoff ships two.

   Geometry below is the README's `square` table, each value carried across as
   value/840*100 cqh (vertical) or value/1200*100 % (horizontal).
   =========================================================================== */
@media (max-width: 820px) {
    .vb-riskfree {
        /* square type scale: 34 / 64 / 90 / 25 / 48 / 24 / 16 on an 840 board */
        --vb-fs-eyebrow: clamp(11px, 4.05cqh, 34px);
        --vb-fs-headline: clamp(19px, 7.62cqh, 64px);
        --vb-fs-band: clamp(24px, 15cqh, 90px);
        --vb-fs-kicker: clamp(9px, min(3.4cqh, 2.2cqw), 25px);
        --vb-fs-claim: clamp(11px, min(6.4cqh, 2.6cqw), 48px);
        --vb-fs-cta: clamp(10px, 2.86cqh, 24px);
        --vb-fs-legal: clamp(7px, 1.5cqh, 12px);
        /* square insets at 80/1200 = 6.67% */
        --vb-gutter: clamp(14px, 6.67%, 80px);
    }

    /* headline: top 132, gap 14 */
    .vb-headline {
        top: 12.8cqh;
        gap: .17em;
    }

    /* band: top 268, height 158, 2.6deg — a gentler angle than wide's 4.5 */
    .vb-band {
        top: 31.3cqh;
        height: 27cqh;
        transform: rotate(2.6deg);
    }

    /* product: pack 714,132 262x370 · slab 886,398 182x310 -> group 354x576 */
    .vb-product {
        top: 9.5cqh;
        height: 76cqh;      /* up from 68.57; high enough that the rotated slab
                               and its drop-shadow clear the bottom edge */
        aspect-ratio: 354 / 576;
    }

    .vb-pack { width: 82.9%; height: 72%; }

    .vb-slab {
        left: 37%;
        top: 41.5%;
        width: 59.4%;
        height: 62%;
    }

    /* claim: top 452, and it breaks across two lines at this shape */
    .vb-claim { top: 62cqh; }

    /* One line at every size (founder call). The string is long, so the width
       cap below is what actually sets the size on a phone, not cqh. */
    .vb-claim__break { display: none; }
    .vb-claim__lead { display: inline; }
    .vb-claim__line { margin-top: .95cqh; line-height: 1.15; }

    /* CTA 80,648 322x76 · legal 428,674 -> 26px to the right of the pill */
    .vb-actions {
        top: 80.5cqh;
        gap: clamp(8px, 2.17cqh, 26px);
    }

    .vb-cta {
        height: 9.05cqh;
        min-height: 26px;
        padding-inline: 1.7em;
    }
}

/* ===========================================================================
   phone — the 214px frame (<=520px)

   Below 520px the shared chrome pins the banner to a hard `height: 214px`
   (banner-showroom.css), so on a 390pt phone the frame is 374x214 and 1cqh is
   2.14px. Every `square` clamp above bottoms out there — 7.62cqh headline is
   16px, so the 19px floor is what actually renders — and the composition ends
   up sized by its floors rather than by the frame. Result: a headline reading
   at 19px with ~26px of dead paper above it (founder catch on mobile).

   Two things set the ceiling here, and they're the reason for every number
   below:

     - the band. It's rotated 2.6deg about the frame centre, so its top edge
       rises toward the left: 67px at centre, ~59px under the copy column.
       That's the floor the headline has to stay off.
     - the product. The pack box starts ~249px in from the left, and the slab's
       swung-out bottom-left corner ~281px. Those cap the copy's line lengths.

   The headline stays ONE line (founder call — a stacked "OPEN YOUR FIRST" over
   a 31px "$25 PACK" shipped first and read too big). So the pack, not the band,
   is what sizes it: the whole string has to land left of ~237px, which puts the
   ceiling at ~26px on this frame.

   Sizes here are cqw, not cqh. Height is PINNED at 214px below this breakpoint,
   so cqh is a constant and tells you nothing about the phone; width is the only
   thing that still varies (359px on an SE, 414px on a Max), and every line in
   the copy column is nowrap and width-bound. cqw tracks the one axis that moves:
   6.9cqw is 26px on a 374px frame and eases off to 25px / 28.6px at those two
   ends, which is the shape of the space the pack leaves. The eyebrow rides the
   headline at .46 so the cap-align lift above stays correct as both move.

   The claim keeps its one-line rule too, at 13px against a ~215px line — the
   slab's swung-out corner is the wall there, not the pack.
   =========================================================================== */
@media (max-width: 520px) {
    .vb-riskfree {
        --vb-fs-headline: clamp(19px, 6.9cqw, 30px);
        --vb-fs-eyebrow: calc(var(--vb-fs-headline) * .46);
        --vb-fs-kicker: clamp(9px, 2.94cqw, 13px);
        --vb-fs-claim: clamp(11px, 3.48cqw, 15px);
    }

    /* 12.8cqh was authored for a 19px line and left ~26px of dead paper above
       it. At 26px the line wants to sit a touch below centre in the run up to
       the band: caps land 22-40px against a band edge that starts at ~60px
       under this column and slopes away to the right, so the room below the
       line is really more than the number suggests. */
    .vb-headline { top: 9cqh; }

    /* More rake on the guarantee band (founder call). `square` authored 2.6deg
       against `wide`'s 4.5 because a steep bar eats vertical room in a short
       frame — at 4deg the left edge rides 13px above centre instead of 8.5, and
       that is the edge the copy has to clear. It still fits: ~16px under the
       headline caps and ~18px over the kicker at the left gutter, where the two
       gaps are tightest. The label rotates with the bar, no separate rule. */
    .vb-band { transform: rotate(4deg); }

    /* Kicker and line tighten to ~3.4px apart — the .95cqh above collapses to
       1.9px, which reads as one block, and 6px read as two unrelated ones.
       62cqh centres the pair in the ~50px between the band's underside and the
       CTA rather than hanging it off the band. */
    .vb-claim { top: 62cqh; }
    .vb-claim__line { margin-top: 1.6cqh; }

    /* the taller claim eats into the CTA's clearance — give the row back 1.5cqh
       (still 12px of paper under the pill) */
    .vb-actions { top: 82cqh; }
}

/* ---- whole-banner hit target ---- */
.vb-hit {
    position: absolute;
    inset: 0;
    z-index: 4;
    text-decoration: none;
}

/* CTA + terms sit above the hit target so they keep their own destinations */
.vb-actions { z-index: 6; }

/* ===========================================================================
   Mobile takes this static banner INSTEAD of the risk-free film banner
   (#heroSlide12). One risk-free slot, two treatments: the HTML film on
   desktop, this static composition on phones and tablets. Both stay in the
   DOM; the rotator's slide list drops whichever one is hidden (see index.html)
   so it can never land on an invisible slide.
   =========================================================================== */
@media (max-width: 820px) {
    body.page-public .pv-hero #heroSlide12 { display: none !important; }
}

@media (min-width: 821px) {
    body.page-public .pv-hero #heroSlide11 { display: none !important; }
}

/* No border. Something in the shared banner chrome puts a
   1px solid rgba(255,255,255,.12) on .vbn — invisible on the dark banners it
   was written for, but a white hairline down the edge of this light one
   (founder catch on prod, 2026-08-18). Same specificity as the hero's own
   .vbn rules and this sheet loads after them, so it wins without !important. */
body.page-public .pv-hero .vb-riskfree {
    border: 0;
}

/* ---- idle bob on the product art ----
   Two slightly different periods so the pack and slab drift out of phase
   rather than moving as one block. translateY comes BEFORE rotate so they lift
   straight up rather than along their own tilted axis, and the rotation is
   restated in every keyframe because animating transform replaces it whole.
   Offsets are in cqh, so the travel scales with the banner like everything else.

   Gated on .hero-slide-active: hero slides sit at opacity:0 rather than
   display:none, so an ungated animation would keep four off-screen banners
   compositing forever — the exact pile-up the hero JS already guards against on
   iOS Safari. */
@keyframes vb-bob-pack {
    0%, 100% { transform: translateY(0) rotate(11deg); }
    50%      { transform: translateY(-2.1cqh) rotate(11deg); }
}

@keyframes vb-bob-slab {
    0%, 100% { transform: translateY(0) rotate(-6deg); }
    50%      { transform: translateY(-1.4cqh) rotate(-6deg); }
}

#heroSlide11.hero-slide-active .vb-pack img {
    animation: vb-bob-pack 4.6s ease-in-out infinite;
    will-change: transform;
}

#heroSlide11.hero-slide-active .vb-slab {
    animation: vb-bob-slab 5.7s ease-in-out -1.4s infinite;
    will-change: transform;
}

@media (prefers-reduced-motion: reduce) {
    #heroSlide11.hero-slide-active .vb-pack img,
    #heroSlide11.hero-slide-active .vb-slab { animation: none; }
}
