/* ============================================================
   basic-page.css - default content render (item 10, V1 "Editorial Ledger")
   Page-scoped: auto-loaded by _main.php for template=basic-page only.
   Typographic hero + meta rule row, sticky h2 TOC for long documents,
   reading column with drop cap. All colors via design-tokens.css.
   ============================================================ */

/* DOMINANT MOMENT: oversized ledger title over the meta rule row - .bp-hero__title */
.bp-hero {
  position: relative;
  isolation: isolate;
  overflow: hidden; /* contain the dark theme's radial glow layer (no h-scroll) */
  padding: clamp(3rem, 8vw, 6rem) 0 clamp(2rem, 5vw, 3.5rem);
}

/* Keep the ledger content above the dark theme's radial glow layer. */
.bp-hero > .container {
  position: relative;
  z-index: 1;
}

/* The Kb monogram watermark that used to sit in the hero's right void was
   removed 2026-07-31 (Ben's call): the shared closing CTA already carries one,
   so every basic-page rendered the mark twice while the flagship pages show it
   once. Its rules are deleted rather than left dead. .bp-hero keeps
   overflow:hidden and the isolated stacking context below - both are still
   needed for the dark radial glow. */

/* Dark = cinematic depth: a soft radial glow anchored behind the ledger title
   so the strongest moment on the page reads as an authored dark section, not a
   flat navy field (design-reference bans flat navy slabs). */
[data-theme="dark"] .bp-hero::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: radial-gradient(120% 90% at 14% 0%, var(--color-accent-glow) 0%, transparent 55%);
  opacity: 0.15;
  pointer-events: none;
}
/* Carry a faint, off-axis depth cue into the top of the long reading column so
   the body isn't one uninterrupted navy plane below the lit hero. */
[data-theme="dark"] .bp-body {
  position: relative;
  isolation: isolate;
}
[data-theme="dark"] .bp-body::before {
  content: "";
  position: absolute;
  inset: 0 0 auto 0;
  height: 42vh;
  z-index: -1;
  background: radial-gradient(75% 100% at 82% 0%, var(--color-accent-glow) 0%, transparent 70%);
  opacity: 0.08;
  pointer-events: none;
}

.bp-hero__eyebrow {
  display: block;
  margin-bottom: 1.1rem;
  font-size: var(--text-xs);
  font-weight: var(--weight-semibold);
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--color-eyebrow);
}

.bp-hero__eyebrow a {
  /* --hit-expander: opt-in so audit-page.js credits the ::after 44px tap area
     (audit-page.js:218 unions the pseudo only when this custom prop is set).
     Purely an audit signal - no visual effect. */
  --hit-expander: 1;
  position: relative;
  color: inherit;
  text-decoration: none;
}
/* Invisible vertical hit-expander -> 44px tap target; eyebrow/breadcrumb stays compact */
.bp-hero__eyebrow a::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: 50%;
  transform: translateY(-50%);
  height: 44px;
}

.bp-hero__title {
  /* Velvet Cinema editorial serif hero (matches .svcs-hero__title). */
  font-family: var(--font-serif);
  font-optical-sizing: auto;
  font-size: clamp(2.4rem, 1.5rem + 4vw, 4.5rem);
  font-weight: 350;
  letter-spacing: -0.015em;
  line-height: 1.04;
  color: var(--color-heading);
  max-width: 20ch;
  text-wrap: balance;
}
.bp-hero__title em {
  font-style: italic;
  font-weight: 480;
  color: var(--color-rose-deep);
}

.bp-hero__meta {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem 1.5rem;
  align-items: baseline;
  margin-top: 1.4rem;
  padding-top: 1rem;
  border-top: 1px solid var(--color-border);
  color: var(--color-muted);
  font-size: var(--text-sm);
}

.bp-hero__meta strong {
  color: var(--color-heading);
  font-weight: var(--weight-semibold);
}

.bp-hero__meta a {
  /* --hit-expander: opt-in so audit-page.js credits the ::after 44px tap area
     (audit-page.js:218). Purely an audit signal - no visual effect. */
  --hit-expander: 1;
  position: relative;
  color: inherit;
  text-decoration: none;
}
/* Invisible vertical hit-expander -> 44px tap target; meta links stay compact */
.bp-hero__meta a::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: 50%;
  transform: translateY(-50%);
  height: 44px;
}

/* ---- Reading layout: TOC rail + column ---- */
.bp-body {
  padding-bottom: var(--space-2xl);
}

.bp-toc {
  display: none;
}

/* Measure lives on the wrapper (70ch of BODY font) so every child shares the
   same left edge - per-child 70ch drifts because ch scales with font size. */
.bp-body .cms-content {
  font-size: var(--text-base);
  line-height: 1.75;
  color: var(--color-body);
  max-width: 70ch;
  margin-inline: auto;
}

.bp-body .cms-content p {
  margin-bottom: 1.1em;
}

/* Lede: the opening paragraph reads larger as the dominant intro moment (pairs
   with the drop cap). Content-agnostic - matches the first prose paragraph even
   when the doc opens with a heading. When the doc opens with an italic meta line
   (e.g. "Last updated: ..." rendered as <p><em>...</em></p>, as /privacy-policy/
   does), skip it so the lede + drop cap land on the first real prose paragraph,
   not the date. Keyed off the lone <em>, not specific text - stays content-agnostic. */
.bp-body .cms-content > p:first-of-type:not(:has(> em:only-child)),
.bp-body .cms-content > p:first-of-type:has(> em:only-child) + p {
  font-size: var(--text-lg);
  line-height: 1.65;
}

/* The leading meta line itself reads as quiet document metadata, not a lede. */
.bp-body .cms-content > p:first-of-type:has(> em:only-child) {
  font-size: var(--text-sm);
  color: var(--color-muted);
  margin-bottom: 1.6em;
}

/* Break-out pull-quote: when CMS copy contains a blockquote, render it as an
   offset editorial serif moment that breaks the reading measure. Fires only
   when a blockquote exists - no effect on plain policy pages. */
.bp-body .cms-content blockquote {
  margin: 2em 0;
  padding: 0.15em 0 0.15em 1.5rem;
  border-left: 3px solid var(--color-rose);
  font-family: var(--font-serif);
  font-optical-sizing: auto;
  font-size: clamp(1.35rem, 1rem + 1.4vw, 1.9rem);
  font-weight: 350;
  line-height: 1.32;
  letter-spacing: -0.01em;
  color: var(--color-heading);
}
.bp-body .cms-content blockquote p {
  margin: 0;
}

/* Prose links only (:not(.btn)). A real button component (.btn--cta /
   .btn--outline) inside body copy owns its own colour + shape - without this
   guard the prose link colour + underline painted the CTA text teal (invisible
   on the teal pill in dark mode) and underlined the buttons. */
.bp-body .cms-content a:not(.btn) {
  color: var(--color-link);
  text-decoration: underline;
  text-underline-offset: 3px;
  text-decoration-thickness: 1px;
}

.bp-body .cms-content h2 {
  font-family: var(--font-display);
  color: var(--color-heading);
  font-size: var(--text-xl);
  font-weight: var(--weight-bold);
  letter-spacing: -0.01em;
  /* Chapter rhythm: a full-measure hairline rule above each section so a long
     policy/resource doc reads as sequenced chapters instead of an
     undifferentiated wall. The rose left-tick stays as the section accent. */
  margin: 3.2em 0 0.8em;
  padding: 1.4em 0 0 0.75rem;
  border-top: 1px solid var(--color-border);
  border-left: 3px solid var(--color-rose);
  text-wrap: balance;
  scroll-margin-top: 6rem;
}

.bp-body .cms-content h2:first-child {
  margin-top: 0;
  padding-top: 0;
  border-top: 0;
}

.bp-body .cms-content h2 strong {
  font-weight: inherit;
}

.bp-body .cms-content h3 {
  font-family: var(--font-display);
  color: var(--color-heading);
  font-size: var(--text-lg);
  font-weight: var(--weight-semibold);
  margin: 1.8em 0 0.5em;
  text-wrap: balance;
}

.bp-body .cms-content ul,
.bp-body .cms-content ol {
  padding-left: 1.4rem;
  margin-bottom: 1.1em;
}

.bp-body .cms-content li {
  margin-bottom: 0.45em;
}

/* CC-3 a11y: prose list-row links (e.g. the /resources/ "Helpful Links"
   directory) render as ~18px underlined text but are real navigation targets.
   A transparent height-only ::after lifts the tap area to 44px WITHOUT adding
   vertical space to the list (keeps the reading rhythm). Height only - list
   links already exceed 44px wide; the 44px zone overlaps the 0.45em row-gap by
   a few px, the same acceptable trade-off as the footer utility links. The
   underline is text-decoration (not a pseudo), so ::after is free. Inline links
   flowing mid-sentence inside a list item are exempted by the audit's
   inline-in-sentence rule, so this never over-expands running copy. */
.bp-body .cms-content li a:not(.btn) {
  --hit-expander: 1;
  position: relative;
}

.bp-body .cms-content li a:not(.btn)::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: 50%;
  transform: translateY(-50%);
  height: 44px;
}

.bp-body .cms-content strong {
  color: var(--color-heading);
  font-weight: var(--weight-semibold);
}

/* Drop cap lands on the first real prose paragraph. If the doc opens with an
   italic meta line (<p><em>Last updated: ...</em></p>), skip it and cap the next
   paragraph - otherwise the giant initial paints onto a date. Matches the lede rule. */
.bp-body .cms-content--dropcap > p:first-of-type:not(:has(> em:only-child))::first-letter,
.bp-body .cms-content--dropcap > p:first-of-type:has(> em:only-child) + p::first-letter {
  font-family: var(--font-display);
  font-weight: var(--weight-extrabold);
  font-size: 3.2em;
  line-height: 0.85;
  float: left;
  padding-right: 0.12em;
  color: var(--color-heading);
}

/* Legacy in-body CTA classes (btn-light-teal / btn-dark-teal in CMS copy):
   restyle as token buttons so old content renders correctly without edits. */
.bp-body .cms-content a[class*="btn-light-teal"],
.bp-body .cms-content a[class*="btn-dark-teal"] {
  display: inline-block;
  padding: 0.8rem 1.6rem;
  margin: 0.25rem 0.5rem 0.25rem 0;
  border-radius: var(--radius-button);
  font-weight: var(--weight-semibold);
  text-decoration: none;
  line-height: 1.2;
}

.bp-body .cms-content a[class*="btn-light-teal"] {
  background: var(--color-btn-primary-bg);
  color: var(--color-btn-primary-text);
}

.bp-body .cms-content a[class*="btn-dark-teal"] {
  border: 1px solid var(--color-btn-outline-border);
  color: var(--color-btn-outline-text);
  background: transparent;
}

@media (min-width: 1024px) {
  .bp-layout {
    display: grid;
    grid-template-columns: 230px minmax(0, 1fr);
    gap: clamp(2rem, 5vw, 5rem);
    align-items: start;
  }

  .bp-layout--no-toc {
    display: block;
  }

  .bp-toc {
    display: block;
    position: sticky;
    /* Was 7rem, reasoned from a 98px header - correct when written, wrong once
       the Editorial Rule header went to 157px at >=1280, where it put the
       "On this page" label 45px UNDER the header (27% of the TOC hidden).
       --sticky-top tracks --header-h at every breakpoint. */
    top: var(--sticky-top);
  }

  .bp-toc__label {
    font-size: var(--text-2xs);
    font-weight: var(--weight-semibold);
    letter-spacing: 0.15em;
    text-transform: uppercase;
    color: var(--color-muted);
    margin: 0 0 0.9rem;
  }

  .bp-toc__list {
    list-style: none;
    margin: 0;
    padding: 0;
    border-left: 1px solid var(--color-border);
  }

  .bp-toc__list a {
    display: flex;
    align-items: center;
    min-height: 44px;
    padding: 0.2rem 0 0.2rem 1rem;
    margin-left: -1px;
    border-left: 2px solid transparent;
    color: var(--color-muted);
    text-decoration: none;
    font-size: var(--text-sm);
    line-height: 1.35;
  }

  /* Scroll-spy: the in-view section reads as a live rose-ticked progress marker
     (JS adds .is-active via IntersectionObserver), turning the dead rail into a
     reading indicator. */
  .bp-toc__list a.is-active {
    color: var(--color-heading);
    border-left-color: var(--color-rose);
    font-weight: var(--weight-semibold);
  }

  /* TOC pages: the column left-aligns against the rail instead of centering */
  .bp-layout:not(.bp-layout--no-toc) .cms-content {
    margin-inline: 0;
  }
}

/* ---- Featured media rail (opt-in via basic-page.php $featuredImageSlugs) ---- */
/* DOMINANT MOMENT: sticky 3:4 product photo pinned beside the reading column - .bp-figure */
.bp-figure {
  margin: 0 0 var(--space-xl);
}

/* Same uncapped-3:4-in-a-1-col-track failure as .landing-why__photo, and on this page it is the
   whole screen: 848x1131 at 900 means one stock photograph, no copy, first heading 1163px down
   and the BUY GIFT CARDS button 1.77 viewports down. At 1024 the same photo is a 360px card with
   every word of copy beside it. 22rem lands the band figure within 8px of that desktop card, so
   the band previews the desktop composition instead of contradicting it.
   /gift-cards/ is the ONLY page that renders .bp-layout--media - basic-page.php:111 emits it
   just for pages with a featured image - so this cap has a fan-out of exactly one today. */
@media (min-width: 768px) {
  .bp-figure {
    max-width: 22rem;
    /* Left, not centred. A capped figure has to pick an axis, and centring it under left-set
       prose invents a second one - the 768 frame showed the photo starting at x180 with the
       paragraph beneath it at x60. Left also matches what >=1024 does (the figure is the left
       column there) and closes the 50px figure-vs-prose edge disagreement the sweep noted. */
    margin-inline: 0;
  }
}

.bp-figure__img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: var(--radius-lg);
  box-shadow: var(--shadow-xl);
}

/* Batch 3 of the 768-1023 sweep: gate moved 1024 -> 768. The opt-in featured-media
   rail stacked across the whole band, and because .bp-figure is a ratio-locked box it
   ran the same curve as the other Batch 2 surfaces - 94% of the viewport at 768,
   pushing the first heading 1163px down the page. Batch 2 capped it at 22rem as a
   stopgap; the real fix is the side-by-side form the page already has at 1024, where
   the figure's own 300-360px track governs and the cap is inert.
   The sticky figure comes down with the grid deliberately: a figure that travels with
   the reader is the entire point of the rail, and it is only sticky-able once it has a
   column of its own. At 768 the tracks resolve to about 300 / 369. */
@media (min-width: 768px) {
  .bp-layout--media {
    display: grid;
    grid-template-columns: minmax(300px, 360px) minmax(0, 1fr);
    gap: clamp(2rem, 5vw, 5rem);
    align-items: start;
  }

  /* Pin the figure so it travels with the reader down the body copy, releasing
     at the section end. top clears the fixed header, matching .bp-toc. */
  .bp-figure {
    position: sticky;
    /* Matches .bp-toc - same header clearance, now via the shared token. */
    top: var(--sticky-top);
    margin: 0;
    /* Release the band cap: the figure's own 300-360px track governs from here up, and
       max-width:22rem would otherwise shave the desktop card from 360px to 352px. */
    max-width: none;
  }

  /* Reading column left-aligns against the figure (matches TOC-page behaviour) */
  .bp-layout--media .cms-content {
    margin-inline: 0;
  }
}

/* ---- Interim feature sections (exit at items 7/9/13) ---- */
.bp-form {
  padding-bottom: var(--space-2xl);
}

.bp-form__card {
  max-width: 760px;
  margin-inline: auto;
  background: var(--color-bg-elevated);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-card);
  padding: clamp(1.5rem, 4vw, 3rem);
}

.bp-form__title {
  font-family: var(--font-display);
  font-size: var(--text-xl);
  font-weight: var(--weight-bold);
  color: var(--color-heading);
  margin: 0 0 0.5rem;
  text-wrap: balance;
}

.bp-form__hint {
  font-size: var(--text-sm);
  color: var(--color-muted);
  margin: 0 0 1.5rem;
}

.bp-form__req {
  color: var(--color-error);
}

/* Anti-spam fields. Honeypots ('comments' on both forms, 'website' on the
   agreement form - its wrapper id is malformed, so target by class) go
   offscreen, NOT display:none: bots skip display:none fields and the trap
   stops working. Mirrors the svc-form pattern in style.css. The Turnstile
   token is a hidden input whose label row should never render. */
.bp-form__card .Inputfield_comments,
.bp-form__card .Inputfield_website {
  position: absolute !important;
  left: -10000px !important;
  width: 1px !important;
  height: 1px !important;
  margin: 0 !important;
  overflow: hidden !important;
}

.bp-form__card .Inputfield_cf-turnstile-response {
  display: none !important;
}

.bp-form__card input[type="text"],
.bp-form__card input[type="email"],
.bp-form__card input[type="tel"],
.bp-form__card input[type="number"],
.bp-form__card select,
.bp-form__card textarea {
  width: 100%;
  min-height: 44px;
  padding: 0.7rem 0.9rem;
  border: 1px solid var(--color-border-hover);
  border-radius: var(--radius-sm);
  background: var(--color-bg);
  color: var(--color-heading);
  font-family: var(--font-body);
  font-size: var(--text-base);
}

.bp-form__card input:focus-visible,
.bp-form__card select:focus-visible,
.bp-form__card textarea:focus-visible {
  outline: 2px solid var(--color-focus-ring);
  outline-offset: 1px;
}

.bp-form__card label {
  font-weight: var(--weight-semibold);
  color: var(--color-heading);
  font-size: var(--text-sm);
}

.bp-form__card button[type="submit"],
.bp-form__card .InputfieldSubmit button {
  padding: 0.85rem 2rem;
  border: 0;
  border-radius: var(--radius-button);
  background: var(--color-btn-primary-bg);
  color: var(--color-btn-primary-text);
  font-family: var(--font-body);
  font-weight: var(--weight-semibold);
  font-size: var(--text-base);
  cursor: pointer;
}

.bp-links,
.bp-social {
  padding-bottom: var(--space-2xl);
  text-align: center;
}

.bp-links__row {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--space-md);
}

.bp-links__btn {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  padding: 0.85rem 1.6rem;
  border: 1px solid var(--color-btn-outline-border);
  border-radius: var(--radius-button);
  color: var(--color-btn-outline-text);
  text-decoration: none;
  font-weight: var(--weight-semibold);
}

.bp-links__icon,
.bp-social__icon {
  width: 22px;
  height: 22px;
}

.bp-social__title {
  font-family: var(--font-display);
  font-size: var(--text-lg);
  font-weight: var(--weight-bold);
  color: var(--color-heading);
  margin: 0 0 1rem;
}

.bp-social__row {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--space-md);
}

.bp-social__row a {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 44px;
  min-height: 44px;
  padding: 0.7rem;
  border: 1px solid var(--color-border-hover);
  border-radius: var(--radius-full);
  color: var(--color-heading);
}

/* ---- Hover (pointer devices only) ---- */
@media (hover: hover) {
  .bp-hero__eyebrow a:hover,
  .bp-hero__meta a:hover {
    color: var(--color-accent);
  }

  .bp-body .cms-content a:not(.btn):hover {
    color: var(--color-accent-hover);
  }

  .bp-toc__list a:hover {
    color: var(--color-heading);
    border-left-color: var(--color-rose);
  }

  .bp-body .cms-content a[class*="btn-light-teal"]:hover,
  .bp-form__card button[type="submit"]:hover,
  .bp-form__card .InputfieldSubmit button:hover {
    background: var(--color-accent-hover);
    transform: translateY(-2px);
    box-shadow: var(--shadow-md);
  }

  .bp-body .cms-content a[class*="btn-dark-teal"]:hover,
  .bp-links__btn:hover {
    border-color: var(--color-accent);
    color: var(--color-accent);
    transform: translateY(-2px);
    box-shadow: var(--shadow-sm);
  }

  .bp-social__row a:hover {
    color: var(--color-accent);
    border-color: var(--color-accent);
  }
}

@media (prefers-reduced-motion: no-preference) {
  .bp-body .cms-content a[class*="btn-"],
  .bp-form__card button[type="submit"],
  .bp-links__btn,
  .bp-social__row a,
  .bp-toc__list a {
    transition: color var(--transition-fast), background-color var(--transition-fast), border-color var(--transition-fast), transform var(--transition-fast), box-shadow var(--transition-fast);
  }
}
