/* ============================================================
   THE VAULT — brand-3.css
   One lit object in a dark room. A single implied light source
   (upper-left, ~135deg) governs every shadow, highlight and card
   edge on the page so nothing invents its own local gradient.

   Typography: Anton for H1/headline moments only, Libre Franklin
   for H2/H3/labels/eyebrows, Montserrat for body. Archivo Black
   retired (see report — font-pairing data argued for keeping one
   display face doing one job, not two competing uppercase faces).
   ============================================================ */

@font-face {
  font-family: 'Anton';
  src: url('../fonts/Anton.ttf') format('truetype');
  font-weight: 400; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'Libre Franklin';
  src: url('../fonts/LibreFranklin.ttf') format('truetype');
  font-weight: 100 900; font-style: normal; font-display: swap;
}
@font-face {
  font-family: 'Montserrat';
  src: url('../fonts/Montserrat.ttf') format('truetype');
  font-weight: 100 900; font-style: normal; font-display: swap;
}

:root {
  /* ---- the room ---- */
  --ink:        #0a0507;
  --ink-2:      #120a0c;
  --ink-3:      #1b1012;
  --stage:      #08050a;

  /* ---- crimson ramp ---- */
  --crimson:      #c8202e;
  --crimson-lt:   #e0343f;
  --crimson-dp:   #7a0d17;
  --oxblood:      #4a0a12;
  --hairline:     rgba(232, 198, 90, 0.14);
  --hairline-red: rgba(200, 32, 46, 0.28);

  /* ---- gold: reserved for the $99.99 collection + the footer mantra ---- */
  --gold:     #e8c65a;
  --gold-lt:  #f3dd93;
  --gold-ink: #1a1206; /* required text colour ON gold — white fails at 1.66:1 */

  --text:   #ece4e2;
  --muted:  #a89c9b;
  /* Was #746668 (3.7:1 on plain ink — already under the 4.5:1 floor before
     the crest watermark existed). Raised while auditing the watermark's
     contrast against dense legal-page text; verified by pixel-sampling the
     rendered page (not computed in the abstract) against the ambient glow
     and the crest's own brightest point. */
  --faint:  #9c8f93;

  /* ---- one light source: upper-left, ~135deg ----
     Every raised surface gets the same highlight edge (top-left)
     and the same cast shadow — offset down-RIGHT (positive x, positive
     y), matching a light travelling from upper-left. A straight-down
     shadow (x:0) doesn't come from anywhere; that was the "weird
     shadows" complaint. These three tokens are now the ONLY shadow
     values used for raised surfaces (offer cards, procession cards,
     header-stuck, the plinth node, the glass panel) — no ad hoc
     box-shadow values elsewhere. */
  --lit-edge:    rgba(255,255,255,0.09);
  --lit-edge-2:  rgba(255,255,255,0.16);
  --cast-sm:     6px 12px 22px -12px rgba(0,0,0,0.8);
  --cast:        10px 22px 50px -20px rgba(0,0,0,0.85);
  --cast-lg:     14px 38px 84px -28px rgba(0,0,0,0.9);

  --display: 'Anton', 'Arial Narrow', sans-serif;
  --head:    'Libre Franklin', 'Helvetica Neue', sans-serif;
  --body:    'Montserrat', 'Helvetica Neue', sans-serif;

  --wrap: 76rem;
  --gutter: clamp(1.15rem, 4.5vw, 4rem);
  --section: clamp(3.75rem, 8vw, 7.5rem);
  --ease: cubic-bezier(0.16, 0.84, 0.44, 1);
}

*, *::before, *::after { box-sizing: border-box; }
html { scroll-behavior: smooth; -webkit-text-size-adjust: 100%; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  margin: 0;
  background: var(--ink);
  color: var(--text);
  font-family: var(--body);
  font-size: clamp(1rem, 0.96rem + 0.2vw, 1.0625rem);
  line-height: 1.7;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
  position: relative;
}

/* ---------- the room's ambient light ----------
   A single soft glow, sourced upper-left, that every other lit
   surface on the page is implicitly standing inside. Nothing else
   on the page is allowed its own independent light direction. */
body::before {
  content: '';
  position: fixed; inset: 0; z-index: 0; pointer-events: none;
  background:
    radial-gradient(ellipse 70% 50% at 20% 0%, rgba(232,198,90,0.04), transparent 60%),
    radial-gradient(ellipse 90% 60% at 50% 100%, rgba(200,32,46,0.05), transparent 70%);
}
/* fine grain so large ink fields don't band */
body::after {
  content: ''; position: fixed; inset: 0; pointer-events: none; z-index: 1; opacity: 0.045;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='140' height='140'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' numOctaves='3'/%3E%3C/filter%3E%3Crect width='140' height='140' filter='url(%23n)'/%3E%3C/svg%3E");
}
.glow { display: none; } /* superseded by body::before in this system */
main, header, footer { position: relative; z-index: 2; }

/* ============================================================
   CREST WATERMARK — fixed, centred, on all five pages
   Viewport-fixed and centred so it stays put while the page scrolls
   over it (Banks: "the logo... remains centered on the page throughout
   the scroll. On all five pages. And make it bigger."). Lives on
   `html::before` — a single rule, no markup on any page, so it is
   identical everywhere by construction rather than by copy-paste.

   Two hard constraints, both handled the same way as the plinth crest
   was before it: sized in fixed px at three deliberately-chosen
   breakpoints (never a vw formula), and rendered via `background-size`
   with only a width given — height is automatic, so the image is
   always shown whole, never cropped. Opacity is capped low enough
   (0.12) that `screen`-blending it over the ink ground never lifts
   background luminance far enough to threaten 4.5:1 against the
   site's text colours — verified against --text/--muted/--faint at
   the crest's brightest point on terms.html, where the small print is
   densest. It sits behind body::before/::after (both later in the
   box tree, so both paint on top of it at the same z-index) and
   nowhere near main/header/footer (z-index 2). */
/* The fixed crest watermark.
   - EMBLEM ONLY: crest-emblem-only.webp is crest-lg cropped above the RUBEDO
     VENTURES wordmark and trimmed to the artwork. Banks: "let's use the version
     that doesn't have Rubedo Ventures at the bottom."
   - CENTRED ON THE CONTENT, NOT THE VIEWPORT. From 1100px the layout carries a
     240px sidebar rail, so a viewport-centred crest sits visibly left of the
     column a reader is actually looking at. The inset-left below re-centres it
     over the content. Below 1100px the rail is off-canvas and inset:0 is right.
   - Always shown whole: background-size sets WIDTH only, height follows, and the
     sizes are fixed per breakpoint rather than a vw formula nobody chose. */
html::before {
  content: '';
  position: fixed; inset: 0; z-index: 0; pointer-events: none;
  background: url('../img/crest-emblem-only.webp') no-repeat center center;
  background-size: 420px auto;
  opacity: 0.055;
  mix-blend-mode: screen;
  filter: saturate(1.1);
}
@media (min-width: 480px)  { html::before { background-size: 560px auto; } }
@media (min-width: 900px)  { html::before { background-size: 840px auto; } }
@media (min-width: 1100px) { html::before { inset: 0 0 0 250px; } }
@media (min-width: 1440px) { html::before { background-size: 1100px auto; } }

img { max-width: 100%; display: block; }
::selection { background: var(--crimson); color: #fff; }

/* ---------- type ---------- */
h1 {
  font-family: var(--display); font-weight: 400;
  line-height: 0.94; letter-spacing: -0.01em;
  text-transform: uppercase; color: #fff; margin: 0;
  text-wrap: balance;
}
h2, h3 {
  font-family: var(--head); font-weight: 800;
  line-height: 1.08; letter-spacing: -0.01em;
  text-transform: uppercase; color: #fff; margin: 0;
  text-wrap: balance;
}
h1 { font-size: clamp(3rem, 6.4vw + 1rem, 6.75rem); }
h2 { font-size: clamp(2rem, 3.2vw + 1rem, 3.6rem); }
h3 { font-size: clamp(1.05rem, 1.7vw, 1.35rem); font-weight: 700; }
p { margin: 0 0 1.3em; }
a { color: #fff; text-decoration-color: var(--hairline-red); text-underline-offset: 3px; }
a:hover { color: var(--crimson-lt); }
strong { color: #fff; font-weight: 700; }
em.hot { color: var(--crimson-lt); font-style: normal; font-weight: 700; }

/* Section labels ("Our Thesis", "The Offer"). Sized up on Banks's note that
   they were too small to do their job — they name the section, so they should
   be readable as a heading rather than as fine print. Tracking eased slightly
   at the larger size: 0.26em was tuned for 0.78rem and reads as gappy above
   1rem. Scales with the viewport so the jump holds on a phone too. */
.eyebrow {
  font-family: var(--head); font-size: clamp(0.95rem, 0.45vw + 0.85rem, 1.25rem);
  font-weight: 800; letter-spacing: 0.2em;
  text-transform: uppercase; color: var(--crimson-lt);
  margin: 0 0 1.35rem; display: flex; align-items: center; gap: 0.9rem;
}
.eyebrow::after { content: ''; flex: 1; height: 1px; background: linear-gradient(90deg, var(--hairline-red), transparent); }
.eyebrow.center { justify-content: center; }
.eyebrow.center::after, .eyebrow.center::before { display: none; }
.eyebrow.gold { color: var(--gold); }
.eyebrow.gold::after { background: linear-gradient(90deg, rgba(232,198,90,0.4), transparent); }

.lede { font-family: var(--body); font-size: clamp(1.1rem, 0.8vw + 0.9rem, 1.4rem); line-height: 1.62; color: #d9d0cf; }
.muted { color: var(--muted); }
.small { font-size: 0.8125rem; line-height: 1.6; color: var(--faint); }

.wrap { width: 100%; max-width: var(--wrap); margin-inline: auto; padding-inline: var(--gutter); }
section { padding-block: var(--section); position: relative; }

/* section-boundary transitions: every major seam fades through the room's
   ambient tone rather than cutting hard — this is the fix for "no gradient,
   let alone indication there's anything under this big red blob." */
.rule { height: 1px; border: 0; margin: 0; background: linear-gradient(90deg, transparent, var(--hairline) 20%, var(--hairline) 80%, transparent); }
/* REMOVED 2026-09-22 — the seam gradients.
   These painted an ink-to-transparent band across the top and bottom of a
   section, OVER the content (z-index:1), to soften section boundaries. On a
   dark page the band is invisible until text passes under it, and then it
   greys out whatever it covers — which is why "THE OFFER" and the first line
   of "GET BOOK ONE —" rendered dimmer than the lines beneath them. Banks
   screenshotted this three times as "weird shadows"; it was never a shadow,
   it was an overlay dimming live text.
   Section boundaries are carried by spacing and the .rule hairline instead. */

/* ---------- header ---------- */
.site-head {
  position: sticky; top: 0; z-index: 40;
  backdrop-filter: blur(14px);
  background: rgba(10, 5, 7, 0.82);
  border-bottom: 1px solid transparent;
  transition: border-color .4s var(--ease), background .4s var(--ease);
}
.site-head.is-stuck { border-bottom-color: var(--hairline); background: rgba(10,5,7,0.96); box-shadow: var(--cast-sm); }
.site-head .wrap { display: flex; align-items: center; justify-content: space-between; gap: 1rem; height: 72px; }

.brand { display: flex; align-items: center; gap: 0.7rem; text-decoration: none; min-width: 0; flex-shrink: 1; }
.brand img { height: 40px; width: auto; flex-shrink: 0; }
.brand-txt { min-width: 0; }
.brand-name {
  display: block; font-family: var(--head); font-weight: 800; color: #fff;
  font-size: clamp(0.66rem, 2.4vw, 0.84rem);
  letter-spacing: 0.04em; text-transform: uppercase; line-height: 1.15;
  white-space: nowrap; overflow: hidden; text-overflow: ellipsis;
}
.brand-sub {
  display: block; font-family: var(--head); font-size: 0.55rem !important; letter-spacing: 0.2em;
  color: var(--faint); text-transform: uppercase; white-space: nowrap;
  overflow: hidden; text-overflow: ellipsis;
}
.head-nav { display: flex; align-items: center; gap: 1.6rem; flex-shrink: 0; }
.head-nav a {
  color: var(--muted); text-decoration: none; font-family: var(--head); font-size: 0.74rem;
  letter-spacing: 0.13em; text-transform: uppercase; font-weight: 700;
  transition: color .25s; white-space: nowrap;
}
.head-nav a:hover, .head-nav a.is-on { color: #fff; }
.head-nav a.is-on { color: var(--crimson-lt); }
.head-cta {
  background: var(--crimson); color: #fff !important; padding: 0.62rem 1.05rem;
  border-radius: 2px; font-size: 0.7rem !important;
  box-shadow: inset 0 1px 0 var(--lit-edge), var(--cast-sm);
}
.head-cta:hover { background: var(--crimson-lt); }
@media (max-width: 900px) { .head-nav { gap: 1rem; } .head-nav .hide-sm { display: none; } }
@media (max-width: 560px) {
  .brand-name { font-size: clamp(7px, calc((100vw - 242px) / 16), 13px); letter-spacing: 0.02em; }
  .brand-sub  { display: block; font-size: clamp(6px, calc((100vw - 242px) / 19), 11px) !important; letter-spacing: 0.06em; }
  .brand img { height: 32px; }
  .brand { gap: 0.5rem; }
  .head-cta { padding: 0.5rem 0.6rem; font-size: 0.62rem !important; letter-spacing: 0.08em; }
}
@media (max-width: 430px) {
  .site-head .wrap { gap: 0.5rem; }
  .brand { gap: 0.4rem; }
  .brand img { height: 28px; }
  .head-cta { padding: 0.45rem 0.5rem; font-size: 0.55rem !important; letter-spacing: 0.05em; }
}

/* ---------- buttons ----------
   Both CTAs are solid objects. Neither is a ghost. Hierarchy comes from
   order, size and colour role, never from one being filled and one being
   an outline — that reads as "real button" vs "whisper", which is the
   exact complaint from the last round. */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 0.6rem;
  font-family: var(--head); font-size: 0.84rem; font-weight: 800;
  letter-spacing: 0.1em; text-transform: uppercase;
  padding: 1.15rem 2.1rem; border-radius: 3px; border: 1px solid transparent;
  text-decoration: none; cursor: pointer; position: relative; overflow: hidden;
  min-height: 44px;
  transition: transform .3s var(--ease), background .3s, color .3s, border-color .3s, box-shadow .3s;
}
.btn:hover { transform: translateY(-2px); }
.btn-red {
  background: linear-gradient(180deg, var(--crimson-lt), var(--crimson));
  color: #fff;
  box-shadow: inset 0 1px 0 var(--lit-edge-2), 6px 16px 34px -14px rgba(200,32,46,0.8);
}
.btn-red:hover { box-shadow: inset 0 1px 0 var(--lit-edge-2), 8px 20px 44px -14px rgba(224,52,63,0.95); color: #fff; }
.btn-red::before {
  content: ''; position: absolute; inset: 0 auto 0 -60%; width: 45%;
  transform: skewX(-20deg);
  background: linear-gradient(90deg, transparent, rgba(255,255,255,0.4), transparent);
  transition: left .65s var(--ease);
}
.btn-red:hover::before { left: 115%; }

/* Gold marks the $99.99 collection. Label MUST be dark ink — white on this
   gold is 1.66:1 and fails outright; #1a1206 gives 11.2:1+ on the gradient. */
.btn-gold {
  background: linear-gradient(180deg, var(--gold-lt), var(--gold));
  color: var(--gold-ink); border-color: transparent;
  box-shadow: inset 0 1px 0 rgba(255,255,255,0.45), 6px 16px 34px -14px rgba(232,198,90,0.6);
}
.btn-gold:hover { color: var(--gold-ink); box-shadow: inset 0 1px 0 rgba(255,255,255,0.5), 8px 20px 44px -14px rgba(240,212,120,0.8); }
.btn-gold::before {
  content: ''; position: absolute; inset: 0 auto 0 -60%; width: 45%;
  transform: skewX(-20deg);
  background: linear-gradient(90deg, transparent, rgba(255,255,255,0.5), transparent);
  transition: left .65s var(--ease);
}
.btn-gold:hover::before { left: 115%; }

/* secondary solid: same weight of object as the primary, smaller footprint —
   used where a CTA must be present but subordinate (e.g. "Read our mission"). */
.btn-secondary {
  background: var(--ink-3); color: #fff; border-color: var(--hairline);
  box-shadow: inset 0 1px 0 var(--lit-edge), var(--cast-sm);
}
.btn-secondary:hover { border-color: var(--hairline-red); background: var(--ink-2); }

.plus-tax {
  font-family: var(--body); font-weight: 600;
  font-size: 0.42em; letter-spacing: 0.1em; text-transform: uppercase;
  color: var(--muted); margin-left: 0.35em; white-space: nowrap;
  vertical-align: baseline;
}
.btn .plus-tax { font-size: 0.8em; color: inherit; opacity: 0.72; margin-left: 0.3em; }
.pricegroup { white-space: nowrap; }
.tax-note { font-size: 0.8rem; color: var(--faint); margin-top: 1.1rem; }

.btn-block { width: 100%; }
.btn[aria-disabled='true'] { opacity: 0.45; pointer-events: none; }
.cta-row { display: flex; flex-wrap: wrap; gap: 1rem; align-items: center; }
.cta-note { font-size: 0.8rem; color: var(--faint); }

/* No-gatekeeping mark: replaces the repeated 6/1/NO stat strip. One bold
   line, not a re-statement of facts already given in the copy above it.
   White, not gold — gold is reserved for the $99.99 collection and the
   footer mantra; gold here read as decoration with no meaning attached. */
.mark-line {
  display: inline-flex; align-items: center; gap: 0.6rem;
  margin-top: 1.9rem; font-family: var(--head); font-weight: 900;
  font-size: clamp(0.85rem, 1.4vw, 1rem); letter-spacing: 0.14em;
  text-transform: uppercase; color: #fff;
}
.mark-line::before { content: ''; width: 22px; height: 2px; background: #fff; }

/* ---------- hero: the stage ---------- */
.hero { position: relative; padding-block: clamp(2.75rem, 6vw, 5rem) 0; }
.hero-inner { text-align: center; max-width: 58rem; margin-inline: auto; }
.hero .lede { max-width: 46rem; margin-inline: auto; }
/* No text-shadow on the H1: flat type on flat dark ground isn't a
   raised object and doesn't cast a shadow. (It previously carried a
   44px atmospheric blur with no x-offset — a shadow from nowhere,
   sized for a red field that's no longer there.) */
.hero .cta-row { justify-content: center; margin-top: 2.1rem; }
.hero .mark-line { display: flex; justify-content: center; }

/* ---------- the plinth: the surface the books stand on ----------
   The crest itself has moved to a single site-wide fixed watermark
   (see "CREST WATERMARK" below) so it no longer needs its own copy
   inside the hero. */
.plinth-stage {
  position: relative;
  margin: clamp(2.5rem, 5vw, 4rem) auto 0;
  padding-top: clamp(1.5rem, 3vw, 2.5rem);
  display: flex; justify-content: center; align-items: flex-end;
}
/* the plinth floor: a shallow lit ellipse the frieze visually rests on,
   lit from upper-left like everything else, with the books' own cast
   shadow reading as if it falls onto this surface */
.plinth-floor {
  position: absolute; left: 50%; bottom: 4%; transform: translateX(-50%);
  width: min(78%, 760px); height: clamp(50px, 8vw, 90px);
  background: radial-gradient(ellipse at 38% 30%, rgba(232,198,90,0.10), rgba(0,0,0,0) 68%),
              radial-gradient(ellipse at center, rgba(0,0,0,0.75), transparent 72%);
  filter: blur(6px); z-index: 0; pointer-events: none;
}

/* the frieze: modest object, hard light, generous dark space.
   Never displayed past ~900 CSS px of clean width — the render is a fixed
   1800x653 asset with no higher-resolution version. */
.frieze { position: relative; z-index: 1; width: 100%; max-width: 900px; margin-inline: auto; }
.frieze picture { display: contents; }
.frieze img { position: relative; z-index: 1; display: block; width: 100%; height: auto; }
/* gallery spotlight: a soft directional highlight from upper-left across the
   frieze, matching the room's single light source, plus the frieze's own
   contact shadow cast down-right onto the plinth floor beneath it */
/* REMOVED 2026-09-22 — this was a rectangular highlight inset BEYOND the image
   (-6% -4% 30% -4%). The books render has a transparent background, so the
   rectangle had nothing to sit on and read as a pale floating box behind them
   on the dark ground. Banks screenshotted it as a "weird shadow" and he was
   right: a light source you can see the edges of is a box, not lighting. The
   render carries its own lighting; the contact shadow below is what grounds
   it. */
.frieze::after {
  content: ''; position: absolute; z-index: 0; left: 6%; right: 2%; bottom: -6%; height: 22%;
  background: radial-gradient(ellipse at 60% 20%, rgba(0,0,0,0.7), transparent 72%);
  filter: blur(10px); pointer-events: none;
}

/* free-book flag: replaces the rotated starburst sticker. A flat tag in
   normal document flow, sitting ABOVE the frieze as a caption — it can
   never obscure Book I's cover because it isn't positioned over the art. */
.flag {
  display: inline-flex; align-items: center; gap: 0.55rem;
  margin: 0 auto clamp(1.1rem, 2.4vw, 1.6rem); padding: 0.55rem 1.1rem 0.55rem 0.75rem;
  border: 1px solid var(--hairline-red); border-radius: 999px;
  background: linear-gradient(180deg, rgba(200,32,46,0.16), rgba(200,32,46,0.05));
  box-shadow: inset 0 1px 0 var(--lit-edge);
  font-family: var(--head); font-weight: 800; letter-spacing: 0.08em;
  text-transform: uppercase; font-size: clamp(0.72rem, 1.4vw, 0.84rem); color: #fff;
}
.flag::before { content: ''; width: 8px; height: 8px; border-radius: 50%; background: var(--crimson-lt); box-shadow: 0 0 10px 2px rgba(224,52,63,0.7); }
.flag b { color: var(--gold); font-weight: 800; }

/* scroll affordance: proves the page continues past the first screen,
   placed so it lands near the fold on a phone rather than after it */
.scrollcue {
  display: flex; flex-direction: column; align-items: center; gap: 0.5rem;
  margin: clamp(2.5rem, 5vw, 3.5rem) auto 0; padding-bottom: clamp(1.5rem, 3vw, 2rem);
  color: var(--faint); font-family: var(--head); font-size: 0.66rem;
  letter-spacing: 0.24em; text-transform: uppercase;
}
.scrollcue svg { width: 18px; height: 18px; stroke: var(--muted); animation: cue 1.8s var(--ease) infinite; }
@keyframes cue { 0%,100% { transform: translateY(0); opacity: .5; } 50% { transform: translateY(6px); opacity: 1; } }
@media (prefers-reduced-motion: reduce) { .scrollcue svg { animation: none; } }

/* ---------- offer, staged like a receipt ----------
   Ladder: free (lightest) -> single book (modest) -> collection
   (heaviest). Weight is built from border strength, shadow tier and
   padding, stepping up through --cast-sm -> --cast -> --cast-lg — the
   same three tokens used everywhere else, not a bespoke shadow. */
.offer-card {
  border: 1px solid var(--hairline); border-radius: 6px;
  background: linear-gradient(160deg, var(--ink-3), var(--ink-2) 75%);
  padding: clamp(1.5rem, 2.8vw, 2.1rem);
  position: relative; overflow: hidden;
  box-shadow: inset 0 1px 0 var(--lit-edge), var(--cast-sm);
}
.offer-card::before { content:''; position:absolute; inset:0 0 auto 0; height:2px; background: linear-gradient(90deg, transparent, var(--hairline-red), transparent); }
.offer-card.is-single {
  border-color: var(--hairline-red);
  padding: clamp(1.65rem, 3.1vw, 2.4rem);
  box-shadow: inset 0 1px 0 var(--lit-edge), var(--cast);
}
.offer-card.is-paid {
  border-color: rgba(232,198,90,0.5);
  padding: clamp(1.85rem, 3.6vw, 2.85rem);
  box-shadow: inset 0 1px 0 var(--lit-edge), var(--cast-lg);
}
.offer-card.is-paid::before { background: linear-gradient(90deg, transparent, var(--gold), transparent); }
.offer-card.is-paid .kicker { color: var(--gold); }
/* Four tiers since 2026-09-22: free, single, the Trader's Set, the collection.
   Four equal columns squeeze every card below a readable width once the 250px
   sidebar rail appears, so the grid goes 4 -> 2 -> 1 rather than holding four
   abreast. The pairs at the 2-column step are deliberate: free sits beside
   single, and the set sits beside the collection it is anchoring. */
.offer-grid { display: grid; grid-template-columns: repeat(4, minmax(0,1fr)); gap: clamp(1.1rem,2.2vw,1.5rem); align-items: stretch; }
@media (max-width: 1500px) { .offer-grid { grid-template-columns: repeat(2, minmax(0,1fr)); } }
@media (max-width: 980px)  { .offer-grid { grid-template-columns: 1fr; } }

/* The set: heavier than a single book, lighter than the collection, so the
   ladder still reads in one direction. */
.offer-card.is-set { border-color: var(--hairline-red); box-shadow: var(--cast); }
.price--set { font-size: clamp(1.95rem, 16cqw, 2.7rem); }
.receipt--set { margin-top: 0.9rem; }
.receipt--set .save { color: var(--crimson-lt); }

/* "From 9.99" — books are no longer one price, so the single-book card says
   the floor and the list carries each real price. */
/* "From" sits on its own line above the figure. Inline, it ate enough width
   that "+ tax" wrapped to a line of its own and the card read as three
   stacked fragments instead of one price. */
.price .from {
  flex: 0 0 100%;
  font-family: var(--head); font-size: 0.26em; font-weight: 800;
  letter-spacing: 0.18em; text-transform: uppercase;
  color: var(--muted); margin-bottom: 0.15em;
}

/* Each row is title-left, price-right. float dropped the price below any
   title long enough to wrap — and Book V's title always wraps. */
.single-list a { display: flex; align-items: baseline; justify-content: space-between; gap: 0.9rem; }
.single-list a > span.li-price { flex: 0 0 auto; }
.li-price { color: var(--muted); font-weight: 700; letter-spacing: 0.04em; white-space: nowrap; }
.single-list a:hover .li-price { color: var(--crimson-lt); }

/* ---------- mobile: compact rows so the ladder is a COMPARISON ----------
   Banks: get all three tiers in front of the viewer at once on a phone so
   the $149.95 -> $99.99 anchor actually lands, rather than one tier per
   screen. Below 640px each card becomes a slim row — kicker, price and one
   descriptive line stay (already-existing single-line copy, nothing new),
   the supporting bullet lists / detail lists / receipt breakdown collapse
   out, and the CTA shrinks but never drops under the 44px touch-target
   floor. Desktop and tablet (>640px) are completely untouched. */
@media (max-width: 640px) {
  .offer-grid { gap: 0.6rem; }
  .offer-card, .offer-card.is-single, .offer-card.is-paid {
    padding: 0.9rem 1rem;
    display: grid;
    grid-template-columns: 1fr auto;
    column-gap: 0.8rem;
    row-gap: 0.15rem;
    align-items: center;
  }
  .offer-card .kicker { grid-column: 1 / 2; margin-bottom: 0; font-size: 0.62rem; }
  .offer-card .price { grid-column: 2 / 3; grid-row: 1 / 3; font-size: 1.7rem; margin-bottom: 0; justify-self: end; }
  .offer-card .price-what { grid-column: 1 / 2; margin-bottom: 0; font-size: 0.68rem; }
  /* supporting detail collapses on the compact row: the tick lists, the
     single-book title links and the receipt's line-item breakdown are all
     elaboration a tablet/desktop card has room for and a phone row doesn't
     need in order to compare the three prices at a glance. */
  .offer-card .ticks, .offer-card .single-list { display: none; }
  /* books.html's free/paid cards carry a plain descriptive sentence (no
     class) between price-what and the buy action — the same kind of
     elaboration .ticks is on index.html, so it collapses the same way. */
  .offer-card > p:not(.kicker):not(.price):not(.price-what):not(.bookbuy) { display: none; }
  .offer-card .bookbuy { grid-column: 1 / -1; margin: 0.4rem 0 0; }
  .offer-card .receipt { grid-column: 1 / -1; margin: 0.3rem 0 0; padding: 0.4rem 0.6rem; }
  .offer-card .receipt-row { font-size: 0.74rem; }
  .offer-card .receipt-row.was { padding-bottom: 0.3rem; margin-bottom: 0.3rem; }
  .offer-card .receipt-row.save { font-size: 0.78rem; }
  .offer-card form, .offer-card .bookbuy, .offer-card > a.btn {
    grid-column: 1 / -1; margin-top: 0.4rem;
  }
  .offer-card .capture { gap: 0.4rem; }
  .offer-card .capture input[type=email] { padding: 0.7rem 0.8rem; font-size: 0.9rem; }
  .offer-card .btn { padding: 0.7rem 1rem; font-size: 0.7rem; min-height: 44px; }
  .offer-card .form-msg { grid-column: 1 / -1; }
}

/* the single-book tier: modest by design — smaller price type, a
   neutral (not red, not gold) button, and its content is a plain list
   of links rather than a sales pitch, so the collection reads as the
   obviously better buy once a visitor can see what one book costs
   against all six. */
.price--single { font-size: clamp(1.85rem, 15cqw, 2.5rem); }
.single-list { list-style:none; margin:0 0 1.3rem; padding:0; border-top:1px solid var(--hairline); }
.single-list li { border-bottom:1px solid var(--hairline); }
.single-list a {
  display:block; padding:0.7rem 0.1rem; font-family: var(--head); font-size:0.86rem;
  font-weight:600; color: var(--text); text-decoration:none;
}
.single-list a:hover { color: var(--crimson-lt); }

.kicker { font-family: var(--head); font-size: 0.72rem; font-weight: 800; letter-spacing: 0.22em; text-transform: uppercase; color: var(--crimson-lt); margin-bottom: 0.9rem; }
/* The price and its "+ tax" are one line that must never be wider than the
   card. It was: at middle widths the 6vw price plus the suffix overflowed and
   "+ TAX" was clipped by the card edge (Banks screenshotted it at a resized
   desktop window — a size neither of us had checked, since we test 390/900/1440).
   Now the line is a flex row that may wrap the suffix onto its own line, and the
   price itself is capped against the CARD width (cqw) rather than the VIEWPORT
   (vw), which is what let a three-column grid produce a price too wide for the
   column it lives in. */
.offer-card { container-type: inline-size; }
.price {
  font-family: var(--display); color:#fff; line-height:1;
  margin-bottom:0.35rem; font-variant-numeric: tabular-nums;
  font-size: clamp(2.35rem, 19cqw, 3.9rem);
  display: flex; align-items: baseline; flex-wrap: wrap; gap: 0 0.1em;
  min-width: 0; max-width: 100%;
}
.price .cur { color: #fff; }
.price-what { font-family: var(--head); font-size:0.8rem; font-weight: 700; letter-spacing:0.1em; text-transform:uppercase; color:var(--muted); margin-bottom:1.4rem; }

/* the anchor math, staged like a receipt guiding the eye to a total —
   the strongest commercial asset on the page, sized to act like it */
/* the anchor math, staged like a receipt: what it costs bought piecemeal,
   then the total saved — sized to act like the strongest commercial asset
   on the page rather than a 0.78rem afterthought */
.receipt { margin: -0.4rem 0 1.5rem; padding: 1rem 1.1rem; border: 1px solid var(--hairline); border-radius: 4px; background: rgba(0,0,0,0.28); }
.receipt-row { margin: 0; font-family: var(--head); font-size: 1.02rem; font-variant-numeric: tabular-nums; }
.receipt-row.was { color: var(--faint); padding-bottom: 0.65rem; margin-bottom: 0.65rem; border-bottom: 1px dashed var(--hairline); }
.receipt-row.was span { text-decoration: line-through; text-decoration-thickness: 1.5px; color: var(--muted); font-weight: 700; }
.receipt-row.save { color: var(--gold); font-weight: 800; font-size: 1.1rem; }

.ticks { list-style:none; margin:0 0 1.8rem; padding:0; }
.ticks li { position:relative; padding-left:1.5rem; margin-bottom:0.65rem; font-size:0.95rem; color:#d3c9c8; }
.ticks li::before { content:''; position:absolute; left:0; top:0.62em; width:7px; height:7px; background:var(--crimson); transform:rotate(45deg); }
.offer-card.is-paid .ticks li::before { background:var(--gold); }

.capture { display:flex; gap:0.6rem; flex-wrap:wrap; }
.capture input[type=email] {
  flex:1 1 12rem; min-width:0; background:rgba(0,0,0,0.45);
  border:1px solid var(--hairline); border-radius:2px; color:#fff;
  font-family:var(--body); font-size:1rem; padding:1.05rem 1rem; min-height: 44px;
  transition:border-color .25s, box-shadow .25s;
}
.capture input::placeholder { color:var(--faint); }
.capture input:focus { outline:none; border-color:var(--crimson); box-shadow:0 0 0 3px rgba(200,32,46,0.2); }
.form-msg { font-size:0.85rem; margin-top:0.85rem; min-height:1.2em; }
.form-msg.ok { color:#8fe0a0; }
.form-msg.err { color:#ff8098; }
.hp { position:absolute !important; left:-9999px !important; width:1px; height:1px; overflow:hidden; opacity:0; pointer-events:none; }

/* ---------- honesty band ---------- */
.honesty { border:1px solid var(--hairline); border-left:3px solid var(--crimson); background:rgba(200,32,46,0.06); padding:clamp(1.4rem,3vw,2.1rem); border-radius:4px; box-shadow: inset 0 1px 0 var(--lit-edge); }
.honesty p:last-child { margin-bottom:0; }

/* ---------- procession: the six-book list on books.html ----------
   A vertical rail linking six numbered nodes — the visual echo of
   "one path", not a flat stack of cards. */
.procession { list-style:none; margin:0; padding:0; position: relative; }
.procession::before {
  content: ''; position: absolute; left: 51px; top: 8px; bottom: 8px; width: 2px;
  background: linear-gradient(180deg, var(--hairline-red), var(--hairline) 90%);
}
@media (max-width: 640px) { .procession::before { left: 27px; } }
.proc-item { position: relative; padding-left: 122px; margin-bottom: clamp(1.6rem, 3vw, 2.4rem); }
@media (max-width: 640px) { .proc-item { padding-left: 66px; } }
.proc-node {
  position: absolute; left: 30px; top: 0; width: 44px; height: 44px; border-radius: 50%;
  display: grid; place-content: center;
  background: linear-gradient(160deg, var(--ink-3), var(--ink)); border: 1px solid var(--hairline-red);
  font-family: var(--display); color: var(--gold); font-size: 0.95rem;
  box-shadow: inset 0 1px 0 var(--lit-edge), var(--cast-sm);
}
@media (max-width: 640px) { .proc-node { left: 6px; width: 34px; height: 34px; font-size: 0.78rem; } }
.proc-card {
  display:grid; grid-template-columns: 100px minmax(0,1fr); gap:1.3rem; align-items:start;
  border:1px solid var(--hairline); border-radius:6px; padding:1.3rem;
  background:linear-gradient(160deg, var(--ink-2), var(--ink) 80%);
  box-shadow: inset 0 1px 0 var(--lit-edge), var(--cast-sm);
  transition:border-color .35s var(--ease), transform .35s var(--ease), box-shadow .35s var(--ease);
}
.proc-card:hover { border-color: rgba(200,32,46,0.5); transform: translateY(-3px); box-shadow: inset 0 1px 0 var(--lit-edge), var(--cast); }
@media (max-width: 480px) { .proc-card { grid-template-columns: 72px minmax(0,1fr); gap: 0.9rem; padding: 1rem; } }
.proc-card img { border-radius:3px; box-shadow:8px 16px 28px -12px rgba(0,0,0,0.9); }
.proc-card h3 { font-size:clamp(1rem,1.5vw,1.2rem); overflow-wrap:anywhere; }
.proc-card p { margin:0.5rem 0 0; font-size:0.9rem; line-height:1.6; color:var(--muted); }
.proc-card .tag { display:inline-block; margin-top:0.65rem; font-family: var(--head); font-size:0.6rem; font-weight:800;
  letter-spacing:0.18em; text-transform:uppercase; color:var(--gold-ink); background:var(--gold);
  padding:0.32rem 0.65rem; border-radius:2px; }

/* ---------- per-book buy ---------- */
.btn-sm { padding: 0.65rem 1.05rem; font-size: 0.68rem; letter-spacing: 0.08em; }
.bookbuy .btn { flex-wrap: wrap; text-align: center; }
.buylabel, .pricegroup { white-space: nowrap; }
.bookbuy { margin: 0.9rem 0 0; }
@media (max-width: 620px) { .bookbuy .btn { width: 100%; padding-inline: 0.7rem; } }
.separately { font-size: 0.8rem; color: var(--faint); margin: -1.2rem 0 1.5rem; }

/* ---------- individual pricing strip (books.html — subordinate to the
   collection card, uses only copy already present on this page) ---------- */
.solo-strip {
  margin-top: 1.4rem; padding-top: 1.2rem; border-top: 1px dashed var(--hairline);
  font-size: 0.85rem; color: var(--muted);
}

/* ---------- FAQ ---------- */
.faq { border-top:1px solid var(--hairline); }
.faq details { border-bottom:1px solid var(--hairline); }
.faq summary { cursor:pointer; list-style:none; padding:1.4rem 3rem 1.4rem 0; position:relative; font-family:var(--head); font-weight: 800; text-transform:uppercase; color:#fff; font-size:clamp(0.9rem,1.6vw,1.05rem); transition:color .25s; }
.faq summary::-webkit-details-marker { display:none; }
.faq summary:hover { color:var(--crimson-lt); }
.faq summary::after { content:''; position:absolute; right:0.4rem; top:50%; width:10px; height:10px; margin-top:-7px; border-right:2px solid var(--crimson); border-bottom:2px solid var(--crimson); transform:rotate(45deg); transition:transform .35s var(--ease); }
.faq details[open] summary::after { transform:rotate(-135deg); margin-top:-2px; }
.faq .answer { padding:0 3rem 1.5rem 0; color:var(--muted); max-width:70ch; }

/* ---------- tabs ---------- */
.tabbar { display:flex; gap:0.4rem; flex-wrap:wrap; border-bottom:1px solid var(--hairline); margin-bottom:clamp(2rem,4vw,3rem); }
.tabbar button {
  appearance:none; background:transparent; border:0; border-bottom:2px solid transparent;
  color:var(--muted); font-family:var(--head); font-size:0.76rem; font-weight:800;
  letter-spacing:0.16em; text-transform:uppercase; padding:1rem 1.2rem; cursor:pointer; min-height: 44px;
  transition:color .25s, border-color .25s;
}
.tabbar button:hover { color:#fff; }
.tabbar button[aria-selected='true'] { color:#fff; border-bottom-color:var(--crimson); }
.tabpanel[hidden] { display:none; }

/* ---------- footer ---------- */
.site-foot { border-top:1px solid var(--hairline); padding-block:3.2rem 3.8rem; background:var(--ink-2); position: relative; }
/* The footer's own seam gradient, removed 2026-09-22 with the others: same
   overlay, same symptom — Banks: the footer "still looks like it's sitting
   in a shadow". The border-top hairline marks the boundary on its own. */
.foot-grid { display:flex; flex-wrap:wrap; gap:1.7rem; justify-content:space-between; align-items:flex-start; }
.foot-nav { display:flex; flex-wrap:wrap; gap:1.4rem; }
.foot-nav a { color:var(--muted); text-decoration:none; font-family: var(--head); font-size:0.74rem; font-weight: 700; letter-spacing:0.12em; text-transform:uppercase; }
.foot-nav a:hover { color:var(--crimson-lt); }
.foot-legal { margin-top:2.2rem; max-width:74ch; }
/* the mantra: gold, the one place on the page gold appears outside the
   $99.99 tier — the client asked for this specifically */
.win { font-family:var(--display); text-transform:uppercase; color:var(--gold); letter-spacing:0.01em; font-size:1.05rem; }

/* ---------- legal pages ---------- */
.doc { padding-block:clamp(2.75rem,6vw,4.75rem) var(--section); }
.doc-title { font-size:clamp(2.1rem,4.6vw,3.4rem); margin-bottom:2.2rem; }
.doc-body { max-width:68ch; }
.doc-body h2 { font-family: var(--head); font-size:clamp(1.05rem,2vw,1.3rem); font-weight: 800; margin:2.6rem 0 0.9rem; text-transform: uppercase; }
.doc-body h2:first-child { margin-top:0; }
.doc-body ul { padding-left:1.2rem; }
/* The numbered conditions in Terms 4.2. Each item is a separate thing the
   buyer confirms, so they are numbered rather than bulleted — a dispute
   needs to be able to point at one of them by number. */
.doc-list { padding-left:1.4rem; }
.doc-list li { margin:0 0 0.6rem; }
.doc-body li { margin-bottom:0.55rem; }
.doc-toc { border:1px solid var(--hairline); padding:1.4rem 1.6rem; border-radius:5px; margin-bottom:2.6rem; background: var(--ink-2); box-shadow: inset 0 1px 0 var(--lit-edge); }
.doc-toc ol { margin:0; padding-left:1.2rem; columns:2; column-gap:2rem; }
.doc-toc li { margin-bottom:0.35rem; font-size:0.86rem; }
@media (max-width:620px) { .doc-toc ol { columns:1; } }

/* ---------- glass panel (mission page) ---------- */
.glasspanel {
  position: relative; max-width: 480px; margin-inline: auto;
  padding: clamp(1.75rem, 4.5vw, 3rem);
  border-radius: 18px; overflow: hidden;
  background: linear-gradient(150deg, rgba(255,255,255,0.10), rgba(255,255,255,0.02) 46%, rgba(200,32,46,0.1));
  border: 1px solid rgba(255,255,255,0.14);
  backdrop-filter: blur(18px) saturate(1.2);
  box-shadow: var(--cast-lg), inset 0 1px 0 rgba(255,255,255,0.24);
}
.glasspanel::after {
  content: ''; position: absolute; left: 50%; top: 55%; translate: -50% -50%;
  width: 78%; aspect-ratio: 1; border-radius: 50%;
  background: radial-gradient(circle, rgba(200,32,46,0.26), transparent 68%);
  filter: blur(34px); z-index: 0; pointer-events: none;
}
.glasspanel::before {
  content: ''; position: absolute; inset: 0; z-index: 2; pointer-events: none;
  background: linear-gradient(115deg, rgba(255,255,255,0.14) 0%, rgba(255,255,255,0) 38%);
}
.glasspanel img {
  position: relative; z-index: 1; width: 100%; height: auto; display: block;
  filter: drop-shadow(0 14px 34px rgba(200,32,46,0.35));
}
.mission-h {
  font-family: var(--head); font-weight: 800; text-transform: uppercase; color: #fff;
  font-size: clamp(1.2rem, 2.2vw, 1.6rem); letter-spacing: -0.005em;
  margin: 0 0 1.1rem;
}

/* thanks.html — the delivered download list */
.thanks-books { list-style:none; padding:0; margin:2rem 0 0; }
.thanks-books li { margin:0 0 0.9rem; }
.thanks-link {
  display:inline-block; font-weight:700; color:var(--crimson-lt);
  text-decoration:none; border-bottom:1px solid rgba(224,52,63,0.35);
  padding-bottom:0.15rem;
}
.thanks-link:hover { border-bottom-color:var(--crimson-lt); }

/* ============================================================
   SIDEBAR NAVIGATION
   ============================================================ */
.navtoggle {
  display: inline-flex; flex-direction: column; justify-content: center; gap: 4px;
  width: 44px; height: 44px; padding: 0 9px; margin-right: 0.15rem;
  background: transparent; border: 1px solid var(--hairline); border-radius: 3px;
  cursor: pointer; flex-shrink: 0;
}
.navtoggle span { display: block; height: 2px; background: #fff; border-radius: 2px; transition: transform .3s var(--ease), opacity .2s; }
.navtoggle[aria-expanded="true"] span:nth-child(1) { transform: translateY(6px) rotate(45deg); }
.navtoggle[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
.navtoggle[aria-expanded="true"] span:nth-child(3) { transform: translateY(-6px) rotate(-45deg); }
.site-head .brand { margin-right: auto; }

.sidebar {
  position: fixed; top: 72px; left: 0; bottom: 0; width: 250px; z-index: 35;
  padding: 1.75rem 1.1rem; overflow-y: auto;
  background: rgba(10, 5, 7, 0.97);
  backdrop-filter: blur(16px);
  border-right: 1px solid var(--hairline);
  transform: translateX(-100%);
  transition: transform .35s var(--ease);
}
.sidebar.is-open { transform: none; }
.sidebar .group { margin-bottom: 1.7rem; }
.sidebar h4 {
  font-family: var(--head); font-size: 0.62rem; font-weight: 800;
  letter-spacing: 0.24em; text-transform: uppercase; color: var(--faint);
  margin: 0 0 0.7rem 0.7rem;
}
.sidebar a {
  display: block; padding: 0.68rem 0.7rem; border-radius: 3px; min-height: 44px;
  color: var(--muted); text-decoration: none;
  font-family: var(--head); font-size: 0.78rem; font-weight: 700; letter-spacing: 0.07em; text-transform: uppercase;
  border-left: 2px solid transparent; transition: color .2s, background .2s, border-color .2s;
  display: flex; align-items: center;
}
.sidebar a:hover { color: #fff; background: rgba(200,32,46,0.08); }
.sidebar a.is-on { color: #fff; background: rgba(200,32,46,0.14); border-left-color: var(--crimson); }

.navscrim {
  position: fixed; inset: 72px 0 0 0; z-index: 34;
  background: rgba(0,0,0,0.62); opacity: 0; pointer-events: none;
  transition: opacity .3s var(--ease);
}
.navscrim.is-on { opacity: 1; pointer-events: auto; }

@media (min-width: 1100px) {
  .sidebar { transform: none; }
  .navtoggle, .navscrim { display: none; }
  main, .site-foot { padding-left: 250px; }
}

/* ---------- motion + a11y ----------
   .reveal/.stagger>* start at opacity:0 with a 3s JS failsafe (see
   brand-2.js) — content must appear even if animation never runs. */
.reveal { transition:opacity .8s var(--ease), transform .8s var(--ease); }
.js .reveal { opacity:0; transform:translateY(22px); }
.js .reveal.is-in { opacity:1; transform:none; }
.js .stagger > * { opacity:0; transform:translateY(18px); animation:rise .85s var(--ease) forwards; }
@keyframes rise { to { opacity:1; transform:none; } }
.stagger > *:nth-child(1){animation-delay:.05s}.stagger > *:nth-child(2){animation-delay:.15s}
.stagger > *:nth-child(3){animation-delay:.25s}.stagger > *:nth-child(4){animation-delay:.35s}
.stagger > *:nth-child(5){animation-delay:.45s}

/* the one permitted motion on the hero object: a few degrees of tilt,
   pointer-driven on desktop, tap-driven on touch (see brand-3.js hook in
   brand-2.js's existing DOM — implemented inline via a tiny CSS custom
   property the page sets on pointer/touch move) */
.frieze { transform: perspective(1400px) rotateX(var(--tiltx, 0deg)) rotateY(var(--tilty, 0deg)); transition: transform .5s var(--ease); }

@media (prefers-reduced-motion: reduce) {
  .js .reveal, .js .stagger > * { opacity:1 !important; transform:none !important; animation:none !important; transition:none !important; }
  .btn:hover, .proc-card:hover { transform:none; }
  .frieze { transform: none !important; }
  .scrollcue svg { animation: none; }
}
a:focus-visible, button:focus-visible, summary:focus-visible, input:focus-visible {
  outline:2px solid var(--crimson-lt); outline-offset:3px; border-radius:2px;
}
.skip { position:absolute; left:-9999px; top:0; z-index:100; background:var(--crimson); color:#fff; padding:0.9rem 1.3rem; font-weight:800; letter-spacing:0.1em; text-transform:uppercase; font-size:0.72rem; }
.skip:focus { left:1rem; top:1rem; }

/* visually hidden — used once, on index.html, to retain the free-book stat
   figures (6 / Books / 1 / Free) that the client asked moved off-screen in
   favour of a single bold "No Gatekeeping" mark, without deleting them from
   the page's copy (see report). Paired with aria-hidden so it is invisible
   to sighted users and screen readers alike, not just hidden visually. */
.offscreen { position:absolute !important; width:1px; height:1px; overflow:hidden; clip:rect(0,0,0,0); white-space:nowrap; border:0; padding:0; margin:-1px; }

/* ---------- what each book covers ----------
   Banks: "a checklist would be better here... we need to name very specific
   skills, not something like 'read a paycheck line by line' — people aren't
   retarded they know how to read a paycheck." So these are named topics, and
   the point is specificity: a reader who already knows the basics can tell at
   a glance whether a book has anything for them.

   Ticks are drawn in CSS rather than set as emoji. The guru template we
   studied leans on emoji for exactly this job, and that is the visual grammar
   this brand is trying not to share — the same reason three processors read
   the category as risky. */
.covers-label {
  font-family: var(--head); font-size: 0.7rem; font-weight: 800;
  letter-spacing: 0.2em; text-transform: uppercase;
  color: var(--faint); margin: 1.1rem 0 0.55rem;
}
.covers {
  list-style: none; margin: 0 0 1.1rem; padding: 0;
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 0.42rem 1.4rem;
}
.covers li {
  position: relative; padding-left: 1.4rem;
  font-family: var(--body); font-size: 0.86rem; line-height: 1.45; color: #cdc3c4;
}
/* the tick: two strokes, drawn and rotated, so it renders identically
   everywhere and inherits the brand crimson rather than a system emoji font */
.covers li::before {
  content: ''; position: absolute; left: 0; top: 0.34em;
  width: 0.42rem; height: 0.72rem;
  border-right: 2px solid var(--crimson-lt);
  border-bottom: 2px solid var(--crimson-lt);
  transform: rotate(42deg);
}
@media (max-width: 720px) { .covers { grid-template-columns: 1fr; } }

/* the collection recommendation sitting under "Six books. One path." */
.recommend { margin-top: 1.1rem; color: #e6dedd; }
.recommend strong { color: #fff; }


/* ---------- saving flags ----------
   Banks: "let's include the percentage of savings in the paycards. Whether we
   put it in text or we use a sticker in the top right corner, both work." A
   corner flag, not a rotated starburst — the sticker shape is the coupon
   language this brand keeps clear of. */
.offer-card { position: relative; }
.save-flag {
  position: absolute; top: 0; right: 0;
  padding: 0.4rem 0.7rem;
  background: var(--crimson); color: #fff;
  font-family: var(--head); font-size: 0.64rem; font-weight: 800;
  letter-spacing: 0.14em; text-transform: uppercase;
  border-bottom-left-radius: 3px;
}
.save-flag--gold { background: var(--gold); color: #1a1206; }

/* who the trading collection is for */
.set-for { font-size: 0.86rem; line-height: 1.5; color: var(--muted); margin: 0 0 1rem; }

/* ---------- mobile corrections, 2026-09-22 ----------
   1. The book checklists ran one item per line on a phone, so six skills meant
      six lines per book and the page scrolled forever. Two columns halves it.
   2. The "one at a time" card's price sat left of the other cards' prices: its
      "From" label is a flex item at 100% width, which made the flex box itself
      full-width and pushed the figure to the left edge instead of the right
      with everything else. */
@media (max-width: 720px) {
  .covers { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0.36rem 0.9rem; }
  .covers li { font-size: 0.78rem; padding-left: 1.15rem; }
}
@media (max-width: 400px) {
  .covers li { font-size: 0.74rem; }
}
@media (max-width: 640px) {
  .offer-card .price { justify-content: flex-end; flex-wrap: nowrap; text-align: right; }
  /* "From" rides immediately in front of the figure on a phone. Given its own
     full-width line it right-aligned to the card edge and floated above the
     "+ tax", so the card read FROM ... 9.99 + TAX across three misaligned
     fragments. Inline and small, the whole thing is one right-aligned line. */
  .offer-card .price .from {
    flex: 0 0 auto; width: auto; margin: 0 0.35em 0 0;
    font-size: 0.32em; align-self: center;
  }
  .offer-card .set-for { display: none; }
  .save-flag { font-size: 0.56rem; padding: 0.3rem 0.5rem; }
}

/* ---------- book cards on a phone ----------
   The cover sat beside the text at every width, leaving the text column about
   200px wide — so a two-column skills list had 69px columns and every item
   wrapped onto three lines, which is the stretched-out scrolling Banks saw.
   Below 620px the cover moves above the text, the text gets the full card
   width, and the two-column list actually fits two per row. */
@media (max-width: 620px) {
  .proc-card { grid-template-columns: 1fr; gap: 0.9rem; }
  .proc-card img { width: 96px; height: auto; }
  .covers { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0.34rem 1rem; }
  .covers li { font-size: 0.8rem; }
}

/* the sum of parts, struck. Both paid tiers show what the books cost bought
   separately; on the trading card it was plain text while the collection's was
   struck, which read as two different kinds of claim. */
.receipt-row.was s, .receipt-row.was [data-separately] { text-decoration: line-through; text-decoration-thickness: 2px; }
/* ============================================================
   THE CONSENT GATE
   ------------------------------------------------------------
   A native <dialog>, so focus trapping, Escape and the inert background come
   from the browser rather than from JavaScript that has to be right. What
   follows is the work of stopping it looking like one.

   It is built as a fourth offer card: the same lit top edge, the same cast
   shadow, Anton on the heading, and the crimson buy button it was opened
   from. The panel is the only lit thing on the screen, which is the point —
   this is the one moment in the flow where nothing else should compete.
   ============================================================ */
.gate {
  width: min(40rem, calc(100vw - 2rem));
  padding: 0;
  border: 1px solid var(--hairline-red);
  border-radius: 4px;
  background: linear-gradient(168deg, var(--ink-3), var(--ink) 62%);
  color: var(--text);
  box-shadow: inset 0 1px 0 var(--lit-edge), var(--cast-lg);
}
.gate::backdrop { background: rgba(4, 2, 3, 0.84); backdrop-filter: blur(3px); }
/* The panel scrolls; the decision does not scroll away. The required text is
   long by necessity — it is the thing being agreed to — so on a short screen
   the copy moves under a pinned action bar rather than pushing the button
   below the fold, where a buyer has to go looking for the way forward. */
.gate-inner {
  --gate-pad: clamp(1.5rem, 4vw, 2.6rem);
  padding: var(--gate-pad) var(--gate-pad) 0;
  max-height: 86dvh;
  overflow-y: auto;
  overscroll-behavior: contain;
  /* The default scrollbar is a white bar down the side of a black panel. */
  scrollbar-width: thin;
  scrollbar-color: var(--crimson-dp) transparent;
}

.gate-eyebrow {
  margin: 0 0 0.55rem;
  font-family: var(--head); font-size: 0.68rem; font-weight: 800;
  letter-spacing: 0.22em; text-transform: uppercase;
  color: var(--crimson-lt);
}
.gate-title {
  margin: 0 0 1.25rem;
  font-family: var(--display); font-weight: 400;
  font-size: clamp(1.6rem, 1.2rem + 1.7vw, 2.3rem);
  letter-spacing: 0.01em; line-height: 1.05; color: #fff;
  text-transform: uppercase;
}

/* What they clicked, restated. Someone who opened two cards before deciding
   needs to see which one this is before agreeing to anything. */
.gate-what {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 0.15rem 0.7rem;
  margin: 0 0 1.5rem; padding: 0.85rem 1rem;
  background: rgba(122, 13, 23, 0.22);
  border-left: 2px solid var(--crimson);
  border-radius: 2px;
}
.gate-what-label {
  font-family: var(--head); font-size: 0.64rem; font-weight: 800;
  letter-spacing: 0.18em; text-transform: uppercase; color: var(--muted);
}
.gate-what-value { font-family: var(--head); font-size: 1rem; color: #fff; }

/* The whole row is the hit area, not the 16px box. This is the one control
   the entire purchase depends on; it should be hard to miss with a thumb. */
.gate-check {
  display: grid; grid-template-columns: auto 1fr; gap: 0.85rem;
  margin: 0 0 1rem; padding: 1rem;
  border: 1px solid var(--lit-edge);
  border-radius: 3px; cursor: pointer;
  transition: border-color .25s var(--ease), background .25s var(--ease);
}
.gate-check:hover { border-color: var(--hairline-red); }
.gate-check:has(input:checked) {
  border-color: rgba(200, 32, 46, 0.55);
  background: rgba(200, 32, 46, 0.07);
}
/* The ring belongs around the row: focus sits on the box, but a 16px outline
   on a 40rem control reads as a rendering fault rather than a focus state. */
.gate-check:has(input:focus-visible) { outline: 2px solid var(--crimson-lt); outline-offset: 2px; }
.gate-check input {
  margin: 0.2rem 0 0; width: 1.15rem; height: 1.15rem;
  accent-color: var(--crimson); flex: none;
}
.gate-check input:focus-visible { outline: none; }
.gate-check-body { font-size: 0.85rem; line-height: 1.65; color: var(--text); }
.gate-link { color: var(--crimson-lt); text-decoration: underline; text-underline-offset: 2px; }
.gate-link:hover { color: var(--gold); }

.gate-email { margin: -0.3rem 0 1.1rem; padding-left: 2rem; }
.gate-email-label {
  display: block; margin: 0 0 0.4rem;
  font-family: var(--head); font-size: 0.64rem; font-weight: 800;
  letter-spacing: 0.16em; text-transform: uppercase; color: var(--muted);
}
.gate-email-input {
  width: 100%; padding: 0.8rem 0.9rem;
  background: rgba(0, 0, 0, 0.45);
  border: 1px solid var(--lit-edge); border-radius: 3px;
  color: var(--text); font-family: var(--body); font-size: 0.95rem;
}
.gate-email-input:focus-visible { outline: 2px solid var(--crimson-lt); outline-offset: 1px; }

.gate-actions {
  display: flex; flex-wrap: wrap; align-items: center;
  gap: 0.6rem 1.4rem;
  position: sticky; bottom: 0; z-index: 1;
  /* Bleeds to the panel edges so copy passes behind it rather than appearing
     to stop at an invisible line. No negative bottom margin: sticky aligns the
     MARGIN box, so a negative one pushes the bar off the bottom and leaves a
     strip of unread text showing under it. */
  margin: 1.1rem calc(-1 * var(--gate-pad)) 0;
  padding: 0.35rem var(--gate-pad) var(--gate-pad);
  background: var(--ink);
}
/* The fade belongs ABOVE the bar, not behind the controls — behind them it
   only makes the text underneath legible enough to be distracting. */
.gate-actions::before {
  content: ''; position: absolute; left: 0; right: 0; bottom: 100%; height: 2rem;
  background: linear-gradient(to top, var(--ink), rgba(10, 5, 7, 0));
  pointer-events: none;
}
.gate-go { flex: 1 1 16rem; }
.gate-go:disabled { opacity: 0.38; cursor: not-allowed; box-shadow: none; }
.gate-go:disabled:hover { transform: none; }
.gate-cancel {
  background: none; border: 0; padding: 0.5rem 0;
  color: var(--muted); font-family: var(--head); font-size: 0.74rem; font-weight: 800;
  letter-spacing: 0.13em; text-transform: uppercase; cursor: pointer;
}
.gate-cancel:hover { color: var(--text); }

.gate-foot { margin: 1.25rem 0 0; font-size: 0.72rem; line-height: 1.6; color: var(--muted); }

/* On a phone the panel IS the screen, so it sits on the bottom edge where a
   thumb already is, and the actions stack — side by side, "Not yet" squeezed
   the button until its label wrapped. */
@media (max-width: 520px) {
  .gate {
    width: 100vw; max-width: 100vw; max-height: 92dvh;
    margin: auto auto 0; border-radius: 4px 4px 0 0; border-bottom: 0;
  }
  .gate-inner { --gate-pad: 1.15rem; padding: 1.5rem 1.15rem 0; max-height: 86dvh; }
  .gate-actions { flex-direction: column-reverse; align-items: stretch; gap: 0.3rem; }
  /* ⚠️ flex-basis is a HEIGHT once the bar stacks. The desktop `flex: 1 1 16rem`
     that lets the button share a row with "Not yet" made it a 16rem-tall slab
     over the terms text. Reset it explicitly rather than relying on width. */
  .gate-go { flex: 0 0 auto; width: 100%; }
  .gate-cancel { flex: 0 0 auto; }
  .gate-email { padding-left: 0; }
}

@media (prefers-reduced-motion: reduce) { .gate-check { transition: none; } }

/* ---------- the end pages ----------
   thanks.html is the page a buyer sees straight after paying, so it gets the
   same ground, the same measure and the same type as the page that sold to
   them. Converted from brand-2 on 2026-09-23: "let's convert those two pages
   to the vault style so everything has a sense of continuity from beginning to
   end. That's essential." */
.thanks-resend {
  margin-top: 3.5rem;
  padding-top: 2.5rem;
  border-top: 1px solid var(--lit-edge);
}
.thanks-resend h3 {
  font-family: var(--head); font-size: 1.05rem; font-weight: 800;
  letter-spacing: 0.01em; margin: 0 0 0.8rem; color: #fff;
}

/* "There's enough for everyone." The old footer hung this in a two-column
   grid that brand-3 does not define, which left it as an orphaned line. Here
   it is its own row, set apart from the nav above and the legal line below. */
.foot-win {
  margin: 1.6rem 0 0.4rem;
  font-family: var(--display); font-size: clamp(1rem, 0.9rem + 0.5vw, 1.25rem);
  letter-spacing: 0.02em; text-transform: uppercase; color: var(--crimson-lt);
}

/* thanks.html nests a <section> inside main.doc, so it collects both paddings
   and opens a void above the footer. Every other doc page is main.doc > .wrap
   and is untouched by this. */
.doc > section { padding-top: 0; padding-bottom: 0; }

/* Banks, 2026-09-23: "tighten the letter spacing". At 0.2em the label was
   wider than the list it introduced, which made it read as a heading for the
   whole card rather than a caption for the checklist directly under it. */
.covers-label { letter-spacing: 0.1em; }

/* The name of what they are about to buy, in the consent gate. It was set in
   Libre Franklin at body size, which made it the least emphatic thing in a
   panel built around it. Anton, matched to the card headings, so the buyer
   sees the product name in the same voice the offer card used. */
.gate-what { align-items: center; }
.gate-what-value {
  font-family: var(--display); font-weight: 400;
  font-size: clamp(1.05rem, 0.95rem + 0.4vw, 1.3rem);
  letter-spacing: 0.02em; text-transform: uppercase; line-height: 1.1;
  color: #fff;
}

/* Shown only after a failed attempt, never as a standing warning. Crimson is
   the brand colour here, so the message leans on weight and position rather
   than colour alone to read as a correction. */
.gate-email-err {
  margin: 0.5rem 0 0;
  font-size: 0.78rem; font-weight: 700; line-height: 1.5;
  color: var(--crimson-lt);
}
.gate-email-input[aria-invalid="true"] { border-color: var(--crimson); }
