/* ==========================================================
   /build-before-you-buy (VLP-1528) : the Build Before You Buy page layer only.

   WHAT THIS FILE OWNS
   Everything that is this page and no other: the two-column hero with the
   intake form in the fold, the three-line proof strip, the console plane and
   its clip handoff, the offer stage and its five stacked sentences, the four
   boundaries laid out as a grid, the closer, this page's act seams by id, the
   one-shot arrival animations, and the no-JS, static and reduced-motion
   restatements for exactly those moves.

   WHAT IT DEPENDS ON
   /folio.css, loaded first: tokens, reset, base type, the section formula,
   buttons, the nav, frames and the window device, the grids, the FAQ, the
   footer, the field styles, the sticky CTA. This file adds to that layer and
   never restates it.

   LOAD ORDER
   critical fallback <style> -> /folio.css -> /build-before-you-buy-v2.css ->
   /scrollcraft.css. The engine sheet is last so the page can override its
   tokens; folio.css restates every engine base rule it changes at a higher
   specificity.
   ========================================================== */

/* ---------------- hero ----------------
   Flow, not a pinned act: the intake form lives here and a form that fades out under a cue is a
   form nobody can fill in. Ink only, lifted by one faint radial so the field is not a flat wall. */
.hero{position:relative;background:var(--ink);
  padding:calc(var(--nav-h) + var(--nav-inset) + 44px) 0 0}
.hero::before{content:"";position:absolute;inset:0;pointer-events:none;z-index:0;
  background:radial-gradient(ellipse at 28% 0%,rgba(244,241,234,.07),transparent 58%)}
.bb-hero-grid{position:relative;z-index:1;display:grid;
  grid-template-columns:minmax(0,1.08fr) minmax(360px,.92fr);gap:24px 56px;align-items:start}
.hero-in{min-width:0;display:flex;flex-direction:column;align-items:flex-start;text-align:left}
/* Line masks reserve descender room. Instrument Serif hangs its g, y and p a long way below the
   baseline, and the engine's default 0.14em shears them at this line-height. */
.hero h1 .sc-split--line{padding-bottom:.26em;margin-bottom:-.26em}
.hero h1{margin-top:20px;max-width:12ch}
.hero-lead{margin-top:22px;max-width:46ch;font-size:clamp(16px,1.4vw,18.5px);text-wrap:pretty}
/* The offer in three clauses, under the lead. Mono and lit: it is the terms line, and it is the
   one thing a reader who never scrolls must have read. */
.bb-terms{margin:24px 0 0;letter-spacing:.12em;text-transform:uppercase;font-size:12.5px;color:var(--text)}

/* --- the proof strip ---
   Three product boundaries, ruled off under the claim. On desktop it sits in the first column
   under the copy; on a phone it moves under the form so the first field stays in the fold. */
.bb-proofs{list-style:none;margin:8px 0 0;padding:26px 0 0;border-top:1px solid var(--line);
  display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:22px;grid-column:1}
.bb-proofs li{min-width:0;display:flex;flex-direction:column;gap:9px}
.bb-proofs .num{color:var(--blue)}
.bb-proofs p{color:var(--muted);font-size:14px;line-height:1.5;text-wrap:pretty}

/* --- the form card ---
   The page's one form, in the fold. folio.css owns .field, its label, its inputs and the
   invalid state; this card owns only its own frame, its head and the consent row. */
.bb-form-wrap{min-width:0;grid-row:1 / span 2;grid-column:2;
  scroll-margin-top:calc(var(--nav-h) + var(--nav-inset) + 24px)}
.bb-form{background:var(--surface);border:1px solid var(--line-2);border-radius:20px;
  padding:28px;display:flex;flex-direction:column;gap:15px;box-shadow:var(--shadow)}
.bb-form-head{display:flex;flex-direction:column;align-items:flex-start;gap:10px;
  padding-bottom:8px;border-bottom:1px solid var(--line);margin-bottom:4px}
.bb-form-head h2{font-family:var(--serif);font-weight:400;font-size:clamp(26px,2.3vw,32px);
  line-height:1.05;letter-spacing:-.005em;color:var(--text)}
.bb-form-head p{color:var(--muted);font-size:14.5px;line-height:1.55;text-wrap:pretty}
.bb-form .field input{min-height:48px}
.bb-form .err{margin-top:2px}
.bb-form .bb-submit{margin-top:6px;width:100%;justify-content:center;min-height:50px}
.bb-form .fine{text-align:center}
.consent{margin-top:4px;display:flex;gap:12px;align-items:flex-start;color:var(--muted);
  font-size:13px;line-height:1.55;cursor:pointer}
.consent input{flex:none;margin-top:2px;width:20px;height:20px;accent-color:var(--blue)}
.consent a{color:var(--text)}
@media(pointer:coarse),(max-width:760px){.consent{min-height:44px}}

/* --- the console ---
   The proof under the claim. The stage is the folio figure; the plane is this page's, and it
   settles once on arrival rather than leaning with the pointer, because there is a form beside
   it and a picture that follows the hand next to a field that does not reads as a fault. */
.bb-console{max-width:1240px;margin-top:64px;padding-top:0;perspective:1500px}
.hero>.stage.wrap{width:100%}
.bb-plane{transform-origin:50% 100%}
.frame-hero{aspect-ratio:16/10}
.frame-hero .poster{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}
.frame-hero .clip{position:relative;z-index:1;width:100%;height:100%;object-fit:cover;
  opacity:0;transition:opacity 600ms var(--ease-out);background:var(--surface)}
.frame-hero .clip.is-playing,html.no-js .frame-hero .clip{opacity:1}
/* The hero and closer pictures are cut to their frame exactly, so the window has to be made: a
   small scale gives the picture room to travel without ever showing an edge. */
.frame-hero .media,.frame-still .media{position:absolute;inset:0;transform-origin:50% 50%;
  --w-s:1.05;--w-from:16px;--w-to:-16px;
  transform:translate3d(0,var(--w-y,0px),0) scale(var(--w-s,1))}
/* The hero console is the exception: any pan or scale cuts the application's own rail and header
   off the edge of the picture, and the rail is where the volumes are named. Scale 1 means no
   overflow, and a window with no overflow never pans; the closer's still keeps the pan. */
.frame-hero .media{--w-s:1;--w-from:0px;--w-to:0px}
.bb-console .cap{margin-top:18px}
/* The hero hands over to the pinned offer: its stage carries its own top pad, so the seam is the
   console's caption to the act's furniture, and it is one section pad, not two. */
.hero{padding-bottom:var(--sec-pad)}

/* --- the library crop ---
   The shared .shot-library shows the whole library screen, whose right half is empty ground at
   this capture's framing, so the card photographed as half nothing. This page crops to the rail
   and the first two volume tiles instead: the rail is where the volumes are named, with their
   kind and their online state, which is the sentence above the card. */
#get .shot-library{aspect-ratio:4/3;--zoom:250%;--sx:0;--sy:-4%;--w-from:0px;--w-to:-70px}

/* ---------------- this page's seams ----------------
   Stated by id so the value survives an act being demoted to flow on a phone or under reduce.
   #get's heading is what the emptied offer stage hands over to as it slides off, and the last
   question has to hand over to the close rather than to half a screen of ground. */
#get{padding-top:calc(var(--sec-pad) * .5)}
#faq{padding-bottom:calc(var(--sec-pad) * .62)}

/* ---------------- the four boundaries ----------------
   The shared .rules is a column, written for the text half of a pair. Four boundaries down one
   column is a screen and a half of list, so this page lays the same markup out as two columns of
   two under a centred statement. The list keeps its own top hairline, so the second cell, which
   is the top of the right-hand column, must not draw a second one under it. */
.bb-rules-2{display:grid;grid-template-columns:repeat(2,minmax(0,1fr));column-gap:56px;
  flex:none;max-width:1000px;margin:52px auto 0}
.bb-rules-2 li:nth-child(2){border-top:0}
.bb-rules-2 li:last-child{padding-bottom:22px}
.bb-rules-2 li p{max-width:44ch}

/* ---------------- the offer: the peak ---------------- */
/* Five sentences, centred in one column, each separated by a hairline that spans it. The column
   is narrower than the section so the lines break where the sentence breaks. */
.sec-offer .lines{margin-top:52px;max-width:860px;margin-left:auto;margin-right:auto}
.line{font-size:clamp(22px,2.9vw,40px);line-height:1.18;letter-spacing:-.025em;font-weight:500;
  color:var(--text);text-align:center;text-wrap:balance;padding:24px 0;
  border-top:1px solid var(--line)}
.line:first-child{border-top:0;padding-top:0}
.offer-stage{display:flex;flex-direction:column;justify-content:center;background:var(--ink);
  padding:calc(var(--nav-h) + var(--nav-inset) + 26px) 0 46px}
.offer-stage>.wrap{width:100%}
.offer-stage .act-mark{margin-bottom:20px}
.offer-stage .head .display{font-size:clamp(30px,3.6vw,50px)}
.offer-stage .lines{margin-top:34px}
.offer-stage .line{font-size:clamp(21px,2.5vw,34px)}
.offer-stage .inline-cta{margin-top:32px}
/* Stacked in one box, not down a column. Five sentences crossing over in the same place is the
   beat; five rows lit one at a time marches the reader's eye down the screen and leaves a hole
   above whichever one is lit. The hairline column is the static layout, and it comes back
   whenever the stage is not actually pinned (no script, ?static=1, a capture tool). */
.offer-stage.sc-stage .lines{position:relative;min-height:clamp(112px,19vh,180px)}
/* Centred with the `translate` property, not with flex and not with `transform`. Flex turns each
   run of text either side of <b class="price"> or <span class="nb"> into its own anonymous item
   and the sentence comes apart; transform is what the engine writes on a cue element. */
.offer-stage.sc-stage .line{position:absolute;left:0;right:0;top:50%;translate:0 -50%;
  margin:0;padding:0;border-top:0}

/* ---------------- closer ----------------
   The hero's console again, held still, so the last screen repeats the first. */
/* clip, not hidden: an overflow:hidden ancestor turns into the scrollport a sticky stage
   measures itself against, and the pin stops engaging. */
.sec-closer{border-top:1px solid var(--line);padding-bottom:0;overflow:clip}
.closer-in{max-width:820px;margin:0 auto;text-align:center;display:flex;flex-direction:column;align-items:center}
.closer-in .display{margin-top:22px}
.closer-in .lead{margin-top:20px;text-align:center;margin-left:auto;margin-right:auto}
.closer-in .inline-cta{margin-top:32px}
.stage-closer{position:relative;perspective:1500px;max-width:900px;margin:64px auto 0}
/* The window's bottom edge is the page's edge: the footer's own hairline sits on it. The fade
   reaches solid ground well before the edge and holds it, so whatever the console is showing,
   the cut lands on ink. */
.stage-closer::after{content:"";position:absolute;left:0;right:0;bottom:0;height:38%;z-index:3;
  pointer-events:none;background:linear-gradient(180deg,transparent,rgba(11,15,20,.62) 42%,var(--ink) 91%,var(--ink))}
.closer-stage{display:flex;flex-direction:column;background:var(--ink);
  padding:calc(var(--nav-h) + var(--nav-inset) + 24px) 0 0}
.closer-stage>.wrap{width:100%}
.closer-stage .closer-in .display{font-size:clamp(30px,3.4vw,50px)}
.closer-stage .stage-closer{margin-top:auto;max-width:780px;padding-top:34px}
.closer-stage.sc-stage .stage-closer::after{display:none}
.closer-stage.sc-stage::after{content:"";position:absolute;left:0;right:0;bottom:0;height:20%;
  z-index:3;pointer-events:none;
  background:linear-gradient(180deg,transparent,rgba(11,15,20,.6) 30%,var(--ink) 56%,var(--ink))}
.closer-lift{
  --l:clamp(0,calc(var(--sc-p,1) / .6),1);
  transform-origin:50% 100%;
  transform:rotateX(calc((1 - var(--l)) * 9deg))
            scale(calc(.96 + .04 * var(--l)))
            translate3d(0,calc((1 - var(--l)) * 40px),0)}

/* ---------------- motion ----------------
   The hero is flow, so nothing here is driven from --sc-p. Its arrival is one set of CSS
   animations, played once; animation-fill-mode is backwards only, so the layout owns every
   element the instant they end. The console plane settles from a tilt to level. */
@keyframes bb-rise{from{opacity:0;transform:translate3d(0,112%,0)}}
@keyframes bb-greet{from{opacity:0;transform:translate3d(0,14px,0)}}
@keyframes bb-settle{from{opacity:0;transform:rotateX(7deg) translate3d(0,34px,0) scale(.985)}}
@media(prefers-reduced-motion:no-preference){
  .hero h1 .sc-split__i{animation:bb-rise 980ms var(--ease-out) backwards}
  .hero h1 .sc-split--line:nth-child(2) .sc-split__i{animation-delay:100ms}
  .hero-in>.chip,.hero-in>.hero-lead,.hero-in>.bb-terms,.bb-form-wrap,.bb-proofs{
    animation:bb-greet 720ms var(--ease-out) backwards}
  .hero-in>.chip{animation-delay:40ms}
  .hero-in>.hero-lead{animation-delay:420ms}
  .hero-in>.bb-terms{animation-delay:530ms}
  .bb-form-wrap{animation-delay:260ms}
  .bb-proofs{animation-delay:640ms}
  .bb-plane{animation:bb-settle 1100ms var(--ease-out) 380ms backwards}
}

/* If the script never runs, or a capture tool asks for the static page, nothing may stay
   invisible and nothing may sit mid-animation. folio.css covers the cues, reveals and staggers;
   these are this page's own moves. */
html.no-js .hero h1 .sc-split__i,html.hv-static .hero h1 .sc-split__i,
html.no-js .hero-in>.chip,html.hv-static .hero-in>.chip,
html.no-js .hero-in>.hero-lead,html.hv-static .hero-in>.hero-lead,
html.no-js .hero-in>.bb-terms,html.hv-static .hero-in>.bb-terms,
html.no-js .bb-form-wrap,html.hv-static .bb-form-wrap,
html.no-js .bb-proofs,html.hv-static .bb-proofs,
html.no-js .bb-plane,html.hv-static .bb-plane{animation:none}
html.no-js .closer-lift,html.hv-static .closer-lift{transform:none;transition:none}
html.no-js .frame-hero .media,html.hv-static .frame-hero .media,
html.no-js .frame-still .media,html.hv-static .frame-still .media{transform:none}

/* ---------------- reduced motion ----------------
   Everything renders in its finished state and the clip holds on its poster. */
@media(prefers-reduced-motion:reduce){
  .frame-hero .clip{opacity:1;transition:none}
  .closer-lift{transform:none;transition:none}
  .frame-hero .media,.frame-still .media{transform:none}
  .hero h1 .sc-split__i{animation:none}
}
@media(max-width:760px) and (prefers-reduced-motion:reduce){
  .frame-hero .media,.frame-still .media{transform:scale(var(--w-s,1))}
}

/* --- the seam when nothing is pinned ---
   A pinned section takes padding:0 and its stage carries a top pad whose only job is to clear
   the fixed nav pill while the stage is stuck under it. With nothing stuck that is a leftover,
   not a seam. In the static state the stage takes the page's own section rhythm instead. */
html.hv-static .offer-stage{padding:var(--sec-pad) 0}

/* ---------------- responsive ---------------- */
@media(max-width:1120px){
  .bb-hero-grid{gap:24px 36px;grid-template-columns:minmax(0,1fr) minmax(340px,.9fr)}
  .bb-proofs{gap:18px}
}
@media(max-width:900px){
  /* The close is flow here, so its progress is not a pin's progress and the lift would arrive
     half-resolved. The window still pans. */
  .closer-lift{transform:none}
  .bb-hero-grid{grid-template-columns:1fr;gap:28px}
  /* One column: the claim, then the form, then the proof strip under it. The form takes its own
     row rather than spanning two, and the strip drops to the third. */
  .bb-form-wrap{grid-row:auto;grid-column:1}
  .bb-proofs{grid-column:1;grid-template-columns:1fr;gap:16px;padding-top:22px}
  .bb-proofs li{flex-direction:row;align-items:baseline;gap:14px}
  .bb-proofs .num{flex:none;width:22px}
  .bb-rules-2{grid-template-columns:1fr;column-gap:0;margin-top:44px}
  .bb-rules-2 li:nth-child(2){border-top:1px solid var(--line)}
  .bb-console{margin-top:48px}
}
@media(max-width:760px){
  .hero{padding-top:calc(var(--nav-h) + var(--nav-inset) + 30px)}
  .hero h1{margin-top:16px;max-width:none}
  .hero-lead{margin-top:14px;font-size:15.5px}
  .bb-terms{margin-top:16px;font-size:11px;letter-spacing:.08em}
  .bb-form{padding:22px;border-radius:16px}
  .bb-form-head h2{font-size:26px}
  .consent{font-size:15.5px}
  .bb-proofs p{font-size:15.5px}
  .bb-console{margin-top:40px}
  .stage-closer{margin-top:36px}
  /* On a phone a whole 1600px console is unreadable at 335px: the frame crops to the result
     column and the picture inside it is magnified about the results, so the quote, the timecode
     and the Open moment control are the picture. The scale rides .media, which the poster, the
     clip and the still all share, so the crossfade still lines up frame for frame. */
  .frame-hero,.frame-still{aspect-ratio:4/5}
  .frame-hero .media,.frame-still .media{--w-s:2.2;transform-origin:6% 31%}
  /* transform:none cancels the pan under no-JS and ?static=1. On a phone it would cancel the
     crop with it, and the crop is legibility rather than motion, so the scale comes back here
     without the pan. */
  html.no-js .frame-hero .media,html.hv-static .frame-hero .media,
  html.no-js .frame-still .media,html.hv-static .frame-still .media{transform:scale(var(--w-s,1))}
  .frame-hero .poster,.frame-hero .clip,.frame-still img{object-position:50% 0}
  .frame-hero{border-radius:12px}
  .offer-stage{padding:calc(var(--nav-h) + var(--nav-inset) + 16px) 0 30px}
  .offer-stage .lines{margin-top:26px}
  .offer-stage .line{padding:13px 0}
  .sec-offer .lines{margin-top:34px}
  .line{padding:16px 0;max-width:none;font-size:clamp(21px,5.4vw,26px)}
  .closer-stage{padding:calc(var(--nav-h) + var(--nav-inset) + 20px) 0 0}
  .closer-in .inline-cta{margin-top:28px}
  #get .shot-library{--w-to:-48px}
}
