/* ==========================================================================================
   ND ABOUT PAGE — /about/   (enqueued only on is_page('about'); see functions.php)
   ------------------------------------------------------------------------------------------
   Approved direction (Nathan, 2026-08-06, from four mockups): the page TRAVELS white → black.
   Hero + manifesto + "what we do" sit on the studio off-white (#F2F2F2 — the exact Services
   ground); the founders + closing are BLACK and SWIPE UP OVER the held-still white.

   ⚠️ COMPONENT CSS IS RE-PROVIDED HERE ON PURPOSE. The per-character blur reveal (.nd-char /
   .nd-chars-in) and the Line CTA (.nd-hero__cta) are styled in nd-home.css, which functions.php
   enqueues FRONT-PAGE ONLY. Their JS (reveal + hover sweep) lives in nd-motion.js and is SITEWIDE,
   so the same class names work here — only the CSS was missing off the home page. It is reproduced
   below rather than moved out of the approved nd-home.css, to keep this change fully additive.
   The mechanic's tokens (--nd-char-blur/-dur, --nd-ease-out, --nd-dur-*, --nd-cta-*) are on :root
   already, so nothing here reaches across a component boundary without a value.
   TODO (low-risk follow-up): lift these primitives into a sitewide nd-components.css so home and
   about share one definition (the drift risk of the copy below is the reason).
   ========================================================================================== */

/* The page opens on white — so html's background must be paper, not the dark default (this file
   only loads on About, so overriding --nd-page-bg here is scoped to this page). Belt to the lvh
   braces the sections already carry. */
:root {
  --nd-page-bg: var(--nd-color-paper);
  /* The footer wipe's gaps show --nd-page-bg. The closing above the footer is now WHITE (Nathan,
     2026-08-10), so the wipe floor is paper — the gaps read white and the slats wipe cleanly to
     black, the same white→black transition home has. initFooter reads this via
     var(--nd-ftr-floor, paper) when it holds the page ground during the wipe. */
  --nd-ftr-floor: var(--nd-color-paper);
}

/* Grounds. The white is #F2F2F2 (--nd-color-paper), the same value the Services section reads out
   of the live site's --light. The black is #0D0D0D (--nd-color-ink). Each section also carries
   data-nd-theme so its type/rules/CTAs take the right tokens. */
.nd-about-page { background: var(--nd-color-paper); }
.ab-white { background: var(--nd-color-paper); }
.ab-black { background: var(--nd-color-ink); }

/* 🐛 RE-DECLARE color, not just the token. `color` is set ONCE on <html> (which is data-nd-theme
   ="dark" on this page), and CSS `color` inherits the COMPUTED value — so a section that swaps
   --nd-text via data-nd-theme="light" still inherits html's dark-theme CREAM unless it re-declares
   color. Without this, every display heading on the white sections (hero title, manifesto lines,
   "Eight ways…", the service names) rendered cream-on-white = invisible; only the explicitly-red
   accent words showed. The eyebrow/lead/intro were fine because they set an explicit color token.
   One line fixes all of it: each themed container declares its own theme's text colour. */
.nd-about-page [data-nd-theme] { color: var(--nd-text); }

/* Section rhythm. */
.ab-sec { position: relative; padding-block: var(--nd-section-y); }
.ab-wrap { max-inline-size: var(--nd-container-wide); margin-inline: auto; padding-inline: var(--nd-gutter); }

/* ══════════════════════════════════════════════════════════════════════ CHAR REVEAL (reused)
   Copied from nd-home.css 388-432 / 558-573. Tokens on :root. Driven by nd-motion.js (.is-in). */
.nd-word { display: inline-block; white-space: nowrap; }
.nd-char { display: inline-block; opacity: 0; filter: blur(var(--nd-char-blur)); }
.nd-chars-in.is-in:not(.is-settled) .nd-char { will-change: filter, opacity; }
.nd-chars-in.is-in .nd-char {
  animation: nd-char-in var(--nd-char-dur) var(--nd-ease-out) both;
  animation-delay: var(--nd-char-d, 0ms);
}
@keyframes nd-char-in {
  from { opacity: 0; filter: blur(var(--nd-char-blur)); }
  to   { opacity: 1; filter: blur(0); }
}
.nd-chars-in.is-settled .nd-char { opacity: 1; filter: none; animation: none; }
.no-js .nd-chars-in .nd-char { opacity: 1; filter: none; animation: none; }
@media (prefers-reduced-motion: reduce) { .nd-chars-in .nd-char { opacity: 1; filter: none; animation: none; } }

/* The accent word inside a per-char line (hero + closing). Nathan, 2026-08-06: "not the correct
   orange" — he wants the BRAND orange (#F23207), not the deep --nd-accent-text used for small text
   on light grounds. Safe here because both the hero headline and the closing credo are LARGE display
   text (≥24px), where AA's floor is 3:1: #F23207 measures 3.58:1 on the paper hero and 4.84:1 on the
   dark closing — both clear it. Only ever used on these two big headlines. */
.ab-accent .nd-char { color: var(--nd-accent); }

/* ══════════════════════════════════════════════════════════════════════ LINE CTA (reused)
   Reproduced from nd-home.css 664-892 (the COMPONENT only — the hero's absolute placement and
   load-entrance stay in nd-home.css). Hover sweep is restarted by nd-motion.js (sitewide) via the
   .nd-cta-sweep class on any .nd-hero__cta. Depends on .nd-fill (nd-base.css, sitewide). */
.nd-hero__cta {
  --nd-cta-fs: clamp(11px, calc(6px + 0.4688vw), 24px);
  --nd-fill-inset: -0.85em -1.1em -0.15em;
  --nd-fill-radius: 0;
  --nd-cta-dur: 0.75s;
  --nd-cta-stagger: var(--nd-cta-stagger-base, 34ms);
  --nd-cta-travel: 4.5em;
  --nd-cta-rule-pad: 0.85em;

  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.5em;
  inline-size: 18em;
  max-inline-size: 100%;
  padding-block-end: 0.85em;
  min-block-size: 24px;                     /* WCAG 2.5.8 target size */

  font-family: var(--nd-typography-eyebrow-font-family);
  font-weight: 400;
  font-size: var(--nd-cta-fs);
  letter-spacing: 0.22em;
  line-height: 1;
  text-transform: uppercase;
  text-decoration: none;
  color: var(--nd-text);
  -webkit-tap-highlight-color: transparent;
}
/* the hairline rule under the whole thing (a pseudo, so it can sweep) */
.nd-hero__cta::after {
  content: "";
  position: absolute;
  inset-inline: 0;
  inset-block-end: 0;
  block-size: 1px;
  background: var(--nd-line-strong);
  transform-origin: left center;
  transition: background var(--nd-dur-fast) var(--nd-ease);
}
.nd-hero__cta:is(:hover, :focus-visible, .is-hover)::after { background: var(--nd-text); }
.nd-hero__cta.nd-cta-sweep::after { animation: nd-cta-underline var(--nd-dur-slower) var(--nd-ease); }
@keyframes nd-cta-underline {
  0%   { transform: scaleX(1); transform-origin: right center; }
  49%  { transform: scaleX(0); transform-origin: right center; }
  50%  { transform: scaleX(0); transform-origin: left center; }
  100% { transform: scaleX(1); transform-origin: left center; }
}
/* the right-hand arrow */
.nd-hero__cta-arrow {
  flex: none;
  inline-size: 1.2em;
  block-size: auto;
  overflow: visible;
  transition: transform var(--nd-cta-dur, 0.75s) var(--nd-ease), clip-path var(--nd-cta-dur, 0.75s) var(--nd-ease), opacity var(--nd-cta-dur, 0.75s) var(--nd-ease);
  transition-delay: 0.34s;
}
.nd-hero__cta:is(:hover, :focus-visible, .is-hover) .nd-hero__cta-arrow {
  transform: translateX(3.5em);
  clip-path: inset(0 0 0 100%);
  opacity: 0;
  transition-delay: 0s;
}
/* the letters pull right on hover, staggered, reassembling right-aligned */
.nd-hero__cta .nd-word { display: inline-block; white-space: nowrap; }
.nd-cta-char { display: inline-block; }
.nd-hero__cta .nd-cta-char {
  transition: transform var(--nd-cta-dur, 0.75s) var(--nd-ease);
  transition-delay: calc(var(--i, 0) * var(--nd-cta-stagger, 34ms));
}
.nd-hero__cta:is(:hover, :focus-visible, .is-hover) .nd-cta-char {
  transform: translateX(var(--nd-cta-travel, 4.5em));
  transition-delay: calc((var(--n, 13) - 1 - var(--i, 0)) * var(--nd-cta-stagger, 34ms));
}
/* the new left arrow fades in (a ::before masking currentColor) */
.nd-hero__cta::before {
  content: "";
  position: absolute;
  inset-inline-start: 0;
  inset-block-start: 0;
  inset-block-end: var(--nd-cta-rule-pad, 0.85em);
  margin-block: auto;
  inline-size: 1.2em;
  block-size: 0.8em;
  background: currentColor;
  -webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 16'%3E%3Cpath d='M0 8h21M15 1.5 21.5 8 15 14.5' fill='none' stroke='%23fff' stroke-width='1.6'/%3E%3C/svg%3E") left center / contain no-repeat;
          mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 16'%3E%3Cpath d='M0 8h21M15 1.5 21.5 8 15 14.5' fill='none' stroke='%23fff' stroke-width='1.6'/%3E%3C/svg%3E") left center / contain no-repeat;
  opacity: 0;
  transform: translateX(-2em);
  clip-path: inset(0 100% 0 0);
  transition: opacity var(--nd-cta-dur, 0.75s) var(--nd-ease), transform var(--nd-cta-dur, 0.75s) var(--nd-ease), clip-path var(--nd-cta-dur, 0.75s) var(--nd-ease);
  transition-delay: 0s;
  pointer-events: none;
}
.nd-hero__cta:is(:hover, :focus-visible, .is-hover)::before {
  opacity: 1;
  transform: translateX(0);
  clip-path: inset(0);
  transition-delay: 0.42s;
}
@media (prefers-reduced-motion: reduce) {
  .nd-cta-char, .nd-hero__cta-arrow, .nd-hero__cta::before { transition: none; }
  .nd-hero__cta:is(:hover, :focus-visible, .is-hover)::after { animation: none; }
}

/* ══════════════════════════════════════════════════════════════════════ HEADER on About
   The page starts on white, so the fixed header needs its INK (light-ground) look at the top and
   flips to its white (dark-ground) look once the black block is under it. The site solves the
   "half a letterform" colour change with the sweep TWIN (a second, ink-coloured copy of the header,
   including the ink logo artwork). header.php now renders it on About (nd_needs_sweep()).

   The twin's default mask is TRANSPARENT (nd-header.css) = twin hidden = white header. That is
   wrong for the white top, so we make it OPAQUE here = twin shown = ink header on white. nd-about-
   page.js then cuts the twin away below the rising black edge, revealing the real white header
   over black. No-JS / reduced-motion: the opaque default leaves a readable ink header over the
   whole page (which starts and mostly reads white until the black arrives). */
.nd-site-header { --nd-sweep-mask: linear-gradient(#000, #000); }

/* ══════════════════════════════════════════════════════════════════════ HERO */
.ab-hero {
  min-block-size: 100svh;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;                 /* centre the block horizontally (Nathan, 2026-08-06) */
  text-align: center;                  /* and read centre-aligned */
  padding-block: calc(var(--nd-section-y) * 0.55) var(--nd-section-y);
  padding-inline: var(--nd-gutter);
  overflow: hidden;
}
.ab-hero__inner { position: relative; z-index: 1; max-inline-size: var(--nd-container-wide); margin-inline: auto; inline-size: 100%; }

/* the prism video ground (added 2026-08-12) — near-black loop with a centred veil so the white
   headline + orange accent read over any frame. Mirrors the Case Studies / Services landings. */
.ab-hero--video { background: var(--nd-color-ink); }
.ab-hero__bg { position: absolute; inset: 0; z-index: 0; overflow: hidden; }
/* prism video treated EXACTLY like the home hero (Nathan, 2026-08-13: "look the same as the hero").
   The hero plays the raw nd-prism-1920.mp4 at full opacity with NO scrim, NO filter, NO veil. So no
   brightness() here either — the earlier filter/veil made the landings brighter than the hero.
   Same treatment on Services / Case Studies. */
.ab-hero__bg video { inline-size: 100%; block-size: 100%; object-fit: cover; }
.ab-hero__title {
  font-family: var(--nd-typography-display-font-family);
  font-weight: var(--nd-typography-display-font-weight);
  letter-spacing: -0.045em;
  line-height: 0.92;
  font-size: clamp(2.9rem, calc(1rem + 8.5vw), 9rem);
  max-inline-size: 15ch;
  margin-block-start: 0.35em;
  margin-inline: auto;                 /* centre the capped headline block */
}
.ab-hero__lead {
  margin-block-start: clamp(24px, 3vw, 48px);
  max-inline-size: 46ch;
  margin-inline: auto;                 /* centre the capped lead block */
  font-family: var(--nd-typography-lead-font-family);
  font-size: clamp(1.15rem, calc(0.9rem + 1vw), 1.6rem);
  line-height: 1.5;
  color: var(--nd-text-soft);
}
/* the wide-tracked mono word centred on the hero's lower edge (mirrors .nd-hero__rail) */
.ab-rail {
  display: block;
  margin-block-start: clamp(40px, 6vw, 96px);
  font-family: var(--nd-typography-eyebrow-font-family);
  font-weight: 400;
  font-size: clamp(14px, calc(8px + 0.7292vw), 36px);
  letter-spacing: 0.45em;
  line-height: 1;
  text-transform: uppercase;
  white-space: nowrap;
  color: var(--nd-text-muted);
}

.ab-eyebrow {
  font-family: var(--nd-typography-eyebrow-font-family);
  font-weight: var(--nd-typography-eyebrow-font-weight);
  font-size: var(--nd-typography-eyebrow-font-size);
  letter-spacing: var(--nd-typography-eyebrow-letter-spacing);
  text-transform: uppercase;
  color: var(--nd-text-muted);
}

/* ══════════════════════════════════════════════════════════════════════ MANIFESTO  (DARK)
   Nathan, 2026-08-06: the four lines must SWEEP in from a side, through the centre, and out the
   other side — one by one as you scroll — like the home "OUR SERVICES" text, on a DARK ground.
   This IS the .nd-svc__big mechanic (nd-services.css): the two-phase smoothstep translateX, driven
   here per line by --ab-p (the line's crossing of the viewport centre, set by nd-about-page.js).
   Alternating sides (--l / --r) so successive lines read as having passed each other. */
.ab-mani { overflow-x: clip; padding-block: var(--nd-section-y); }
.ab-mani__inner { max-inline-size: var(--nd-container-wide); margin-inline: auto; padding-inline: var(--nd-gutter); }
.ab-mani__line {
  --nd-mani-travel: 82vw;                     /* how far each line travels across the screen */
  /* two phases, each smoothstepped, overlapping through the middle — copied from .nd-svc__big so the
     line is fastest off-screen and slowest (a real hold) at the centre where it reads. */
  --p1: clamp(0, calc(var(--ab-p, 0.5) / 0.55), 1);
  --p2: clamp(0, calc((var(--ab-p, 0.5) - 0.45) / 0.55), 1);
  --e1: calc(var(--p1) * var(--p1) * (3 - (2 * var(--p1))));
  --e2: calc(var(--p2) * var(--p2) * (3 - (2 * var(--p2))));
  transform: translateX(calc(var(--s, 1) * var(--nd-mani-travel) * ((1 - var(--e1)) - var(--e2))));
  will-change: transform;
  margin-block: clamp(28px, 9vh, 120px);      /* stacked tighter (Nathan, 2026-08-06) — was 26vh */
  font-family: var(--nd-typography-display-font-family);
  font-weight: 900;                           /* bolder (Nathan, 2026-08-06) — Archivo 900 */
  letter-spacing: -0.045em;
  line-height: 0.98;
  font-size: clamp(2.6rem, calc(1rem + 6.4vw), 7rem);   /* larger, to stand out */
  max-inline-size: 18ch;                      /* punchier wrap at the bigger size */
}
.ab-mani__line--l { --s: -1; }                                   /* arrives from the left  */
.ab-mani__line--r { --s:  1; margin-inline-start: auto; text-align: end; }   /* from the right */
.ab-mani__i {
  display: block;
  margin-block-end: 0.5em;
  font-family: var(--nd-typography-eyebrow-font-family);
  font-size: 0.72rem;
  letter-spacing: 0.18em;
  color: var(--nd-text-muted);
}
.ab-accent-word { color: var(--nd-accent-text); }
@media (prefers-reduced-motion: reduce) { .ab-mani__line { transform: none; } }

/* ══════════════════════════════════════════════════════════════════════ THE "+" PAGE BREAK
   Nathan, 2026-08-06: "copy it from the 'Work that outlives the campaign' page on home." So this is
   the SAME construction as the home case-studies page break (.nd-cs__break + .nd-cs__mark), not a
   lookalike: a full-width 1px rule with a "+" at its centre; on reveal the rule draws OUTWARD from
   the "+" (a centred background that widens, so the mark is never scaled) and the cross turns a HALF
   turn, + → × → +. Home drives it continuously by scroll; About plays it once on nd-motion's .is-in.
   The wrapper is data-nd-theme="dark" (the landing above + the manifesto below are both dark now),
   so --nd-line / --nd-line-strong resolve to the light values and the "+" reads on the ink ground.
   display:flow-root — the break's margin-block would otherwise COLLAPSE THROUGH this wrapper (leaving
   it 1px tall, so its ink ground covered only the line and the page's white showed in the margin gaps
   = the "white banner"). A flow-root contains those margins, so the ink ground fills the whole band. */
.ab-break-wrap { background: var(--nd-color-ink); display: flow-root; }
.ab-break {
  position: relative;
  block-size: 1px;
  margin-block: clamp(48px, 8vh, 150px);
  margin-inline: var(--nd-gutter);
  /* ⚠️ THE DRAW IS .nd-lineart's NOW (nd-base.css), 2026-08-15. This used to grow from `center` as
     ONE background widening in both directions — visually close, but a different construction from
     the ledger rule Nathan picked as the reference. He asked not to rebuild lookalikes: "copy the
     one we want and remove the old one and paste the working correct one." So the single-background
     rule below was deleted and this now uses the shared two-half component, split at the cross.
     ⚠️ THE RULE IS --nd-line (LIGHTER), THE MARK IS --nd-line-strong (STRONGER) — exactly like the
     home .nd-cs__break / .nd-cs__mark. Using the strong token for both is what made the "+" merge
     into the rule and read flat. Still driven by --nd-cs-in going 0 → 1
     (set per break by nd-about-page.js, the same driver the home page break uses). Fallback 1 =
     drawn, which is the no-JS / reduced-motion rest. */
  --nd-lineart-p: var(--nd-cs-in, 1);
}
/* the shared mark — the SAME construction as .nd-cs__mark: two centred gradients (a "+") in the
   strong line colour, turning a half turn (+ → × → +) as the break crosses the screen, so it is
   always in motion and never rests as a flat line on the rule. */
.ab-break__mark {
  --nd-mark-turn: 180deg;
  position: absolute;
  inset-block-start: 50%;
  inset-inline-start: 50%;
  inline-size: clamp(14px, calc(4px + 0.625vw), 28px);
  block-size: clamp(14px, calc(4px + 0.625vw), 28px);
  transform: translate(-50%, -50%) rotate(calc(var(--nd-cs-in, 1) * var(--nd-mark-turn)));
  background:
    linear-gradient(var(--nd-line-strong), var(--nd-line-strong)) center / 100% 2px no-repeat,
    linear-gradient(var(--nd-line-strong), var(--nd-line-strong)) center / 2px 100% no-repeat;
}

/* ══════════════════════════════════════════════════════════════════════ WHAT WE DO */
/* Trim the section's bottom padding so the founders heading follows closely — the big white gap
   between "All services" and the heading was this + the pinned-floor centring (Nathan, 2026-08-10). */
.ab-svc { padding-block-end: clamp(24px, 4vh, 72px); }
.ab-svc__head { display: flex; align-items: flex-end; justify-content: space-between; gap: 2em; flex-wrap: wrap; margin-block-end: clamp(28px, 3vw, 56px); }
.ab-svc__h { font-family: var(--nd-typography-display-font-family); font-weight: 800; letter-spacing: -0.03em; line-height: 1.05; font-size: clamp(1.6rem, calc(1rem + 2.4vw), 3rem); margin-block-start: 0.3em; }
.ab-svc__intro { max-inline-size: 34ch; color: var(--nd-text-soft); }
/* THE FLIP-BOARD — the 8 services as cards that flip down into place one by one as you scroll
   (Nathan chose Build B). The flip is scroll-position-linked: nd-about-page.js sets --card-p (0 =
   folded edge-on / hidden, 1 = flat / shown) per card from its viewport position every frame, so it
   is deterministic (holds exactly where you stop, never oscillates) AND reversible — the cards fold
   back on scroll-up (Nathan, 2026-08-10). The parent carries the 3-D perspective. */
.ab-flip { perspective: 1500px; }
.ab-flip__card {
  display: grid;
  grid-template-columns: 3.4em minmax(0, 1.1fr) minmax(0, 1fr);
  align-items: center;
  gap: clamp(16px, 3vw, 64px);
  padding: clamp(22px, 3.2vw, 46px) clamp(20px, 2.4vw, 44px);
  margin-block: clamp(8px, 1vw, 14px);
  border-radius: var(--nd-radius-panel);
  background: var(--nd-color-panel);
  box-shadow: 0 18px 44px -30px rgba(13, 13, 13, .55);
  transform-origin: top center;
  transform: rotateX(calc((1 - var(--card-p, 1)) * -92deg));
  opacity: var(--card-p, 1);
  backface-visibility: hidden;
  will-change: transform;
}
.ab-flip__idx  { font-family: var(--nd-typography-eyebrow-font-family); font-size: 0.72rem; letter-spacing: 0.12em; color: var(--nd-text-muted); }
.ab-flip__name { font-family: var(--nd-typography-display-font-family); font-weight: 800; letter-spacing: -0.025em; line-height: 1.02; font-size: clamp(1.7rem, calc(1rem + 2.4vw), 3.2rem); color: var(--nd-text); }
.ab-flip__desc { font-family: var(--nd-typography-body-font-family); font-size: clamp(0.95rem, calc(0.9rem + 0.35vw), 1.2rem); line-height: 1.45; color: var(--nd-text-soft); max-inline-size: 34ch; }
@media (max-width: 720px) {
  .ab-flip__card { grid-template-columns: 2.4em 1fr; gap: 8px 14px; }
  .ab-flip__desc { grid-column: 2; }
}
@media (prefers-reduced-motion: reduce) { .ab-flip__card { transform: none; opacity: 1; } }

/* The "All services" CTA, right under the last flip card (Nathan, 2026-08-10 — no separate hold). */
.ab-svc__cta { margin-block-start: clamp(36px, 5vw, 88px); }

/* ══════════════════════════════════════════════════════════════════════ THE SWIPE
   The BLACK block (founders + closing) swipes up over a held-still WHITE floor. Same "sticky +
   negative margin" shape the Services ground uses (nd-services.css:123-132) — but a SOLID white
   floor (no slat bands), so the black covers it as you scroll. lvh, not svh, so a phone's shrinking
   toolbar never opens a gap (nd-services.css:107-122).
   ⚠️ NEVER PIN ON TOUCH (BUILD-FRAMEWORK §4). On coarse pointers / narrow screens the floor is
   removed and the sections simply stack white-then-black — no hold. */
.ab-swipe { position: relative; }
/* THE HELD-STILL WHITE — the "What we do" section itself (Nathan, 2026-08-06: "it must swipe over
   the 8 services", and "remove the beat"). It is sized to one screen and pinned; the black panel
   rises up over it. Sized to 100lvh with the content centred so nothing is clipped when it pins
   (a sticky section taller than the viewport would lose its lower rows behind the fold). */
.ab-swipe__under {
  position: sticky;
  inset-block-start: 0;
  z-index: 0;
  min-block-size: 100lvh;
  display: flex;
  flex-direction: column;
  /* Heading sits in the UPPER part so it follows "All services" closely (Nathan, 2026-08-10 — the
     big white gap was the centring); the empty below is where the black images sweep up over it. */
  justify-content: flex-start;
  padding-block-start: clamp(72px, 15vh, 190px);
  overflow: hidden;
  background: var(--nd-color-paper);
}
.ab-swipe__under .ab-svc { padding-block: clamp(40px, 6vh, 96px); }   /* fit the one screen */
.ab-swipe__panel { position: relative; z-index: 1; background: var(--nd-color-ink); }

/* ⚠️ NEVER PIN ON TOUCH (BUILD-FRAMEWORK §4) — and reduced-motion. The section drops back to normal
   flow and the black simply follows it in a clean stack. */
@media (max-width: 759px), (pointer: coarse) {
  .ab-swipe__under { position: static; min-block-size: 0; display: block; }
}
@media (prefers-reduced-motion: reduce) {
  .ab-swipe__under { position: static; min-block-size: 0; display: block; }
}

/* ══════════════════════════════════════════════════════════════════════ FOUNDERS
   A standalone CENTRED heading (the white swipe floor the black images rise over), then the
   full-page SPLIT IMAGES with the name/role/bio laid over each (Nathan, 2026-08-10). */
/* ⚠️ The measure goes on the HEADING (large font), NOT the container. `ch` is relative to the
   element's own font-size, so 32ch on the 16px container was ~256px and wrapped the big heading to
   one word a line (Nathan, 2026-08-10). The container is wide; the heading caps at 20ch of ITS font
   so several words read per line. */
.ab-founders__intro { text-align: center; max-inline-size: min(1200px, 92vw); margin-inline: auto; }
.ab-founders__intro .ab-eyebrow { display: block; margin-block-end: 1.2em; }
/* Big enough to hold the full screen (Nathan, 2026-08-10 — it read small). ~18ch of ITS own large
   font keeps several words per line. */
.ab-founders__intro-h { font-family: var(--nd-typography-display-font-family); font-weight: 800; letter-spacing: -0.03em; line-height: 1.04; font-size: clamp(2.4rem, calc(1rem + 4.6vw), 5.4rem); max-inline-size: 18ch; margin-inline: auto; }
/* "proud" in brand orange (#F23207), not the small-text dark orange .ab-accent-word defaults to —
   safe here because this is large display text (Nathan, 2026-08-15). One orange word, one view. */
.ab-founders__intro-h .ab-accent-word { color: var(--nd-accent); }
.ab-founders__intro .ab-note { margin-block-start: 1.6em; }
.ab-note { margin-block-start: 1em; font-family: var(--nd-typography-eyebrow-font-family); font-size: 0.66rem; letter-spacing: 0.06em; color: var(--nd-accent-text); }

/* THE FULL-PAGE SPLIT IMAGES — two images, left + right, filling the screen; text laid over each. */
.ab-images { display: grid; grid-template-columns: 1fr 1fr; min-block-size: 100lvh; }
.ab-image { position: relative; overflow: hidden; isolation: isolate; }
.ab-image__ph {
  position: absolute; inset: 0;
  display: grid; place-items: center;
  background:
    linear-gradient(135deg, rgba(255,255,255,0.05), rgba(255,255,255,0) 60%),
    repeating-linear-gradient(45deg, rgba(255,255,255,0.035) 0 26px, transparent 26px 52px),
    var(--nd-color-dark-charcoal-deep);
}
.ab-image__ph img { position: absolute; inset: 0; inline-size: 100%; block-size: 100%; object-fit: cover; }
.ab-image__ph-label { font-family: var(--nd-typography-eyebrow-font-family); font-size: 0.72rem; letter-spacing: 0.16em; text-transform: uppercase; color: var(--nd-color-dark-muted); border: 1px dashed var(--nd-color-dark-border); padding: 0.6em 1em; border-radius: 6px; }
/* The scrim keeps overlaid text legible. STRONG at the bottom (name / role / quote live there over
   the shirt), plus a MILDER darkening at the very top so the top-right bio reads over the brighter
   top of the orange ground. Two stacked gradients, one element. */
.ab-image__scrim {
  position: absolute; inset: 0; z-index: 1;
  background:
    linear-gradient(to top, rgba(0,0,0,0.80) 0%, rgba(0,0,0,0.16) 48%, transparent 68%),
    linear-gradient(to bottom, rgba(0,0,0,0.42) 0%, transparent 26%);
}
/* THE BIO — small, top-RIGHT (Nathan, 2026-08-15). Right-aligned so it hangs off the far edge; a
   soft shadow braces it against the lighter top of the photo. */
.ab-image__bio {
  position: absolute; z-index: 2;
  /* ⚠️ CLEARS THE FIXED HEADER. The founders section runs under the transparent site header, and the
     RIGHT panel's top-right bio landed right on top of LET'S TALK / MENU. Start it below the header
     band (~88px) so it never collides, on either panel (Nathan, 2026-08-15). */
  inset-block-start: clamp(88px, 11vh, 132px);
  inset-inline-end: clamp(24px, 3vw, 60px);
  max-inline-size: 24ch;
  text-align: right;
  color: var(--nd-color-dark-body);
  text-shadow: 0 1px 14px rgba(0,0,0,0.45);
  font-size: clamp(0.9rem, calc(0.72rem + 0.4vw), 1.06rem);
  line-height: 1.5;
}
/* NAME + role + QUOTE — the bottom cluster, over the shirt. */
.ab-image__text { position: absolute; inset-block-end: clamp(28px, 5vh, 84px); inset-inline: clamp(24px, 3vw, 60px); z-index: 2; }
/* Big name, now with the surname (Nathan, 2026-08-15 — "our names BIG with surnames"). */
.ab-image__name { display: block; font-family: var(--nd-typography-display-font-family); font-weight: 800; letter-spacing: -0.03em; line-height: 1.02; font-size: clamp(2rem, calc(1rem + 2.7vw), 3.9rem); color: var(--nd-color-dark-heading); }
.ab-image__role { display: block; margin-block-start: 0.5em; font-family: var(--nd-typography-eyebrow-font-family); font-size: 0.72rem; letter-spacing: 0.14em; text-transform: uppercase; color: var(--nd-color-dark-muted); }
/* The personal QUOTE — large, in quotation marks (from CSS, so the text stays plain), filling the
   lower half over the shirt. */
.ab-image__quote {
  margin: clamp(14px, 2.6vh, 32px) 0 0;
  max-inline-size: 30ch;
  quotes: "\201C" "\201D";
  font-family: var(--nd-typography-display-font-family);
  font-weight: 500; font-style: italic; letter-spacing: -0.01em;
  font-size: clamp(1.1rem, calc(0.7rem + 1.35vw), 2rem);
  line-height: 1.4;
  color: var(--nd-color-dark-heading);
  text-wrap: balance;
}
.ab-image__quote::before { content: open-quote; }
.ab-image__quote::after  { content: close-quote; }
@media (max-width: 760px) {
  .ab-images { grid-template-columns: 1fr; min-block-size: 0; }
  .ab-image { min-block-size: 72vh; }
  /* 🐛 ON MOBILE EACH BIO HUGS THE CORNER AWAY FROM ITS FACE — and the two faces are on OPPOSITE
     sides once Nathan's photo is flipped, so the bios go opposite ways too (Nathan, 2026-08-16: the
     first pass moved BOTH left, which then overlapped Nathan's head).
       · Donavon (first, face centre-RIGHT)          → bio TOP-LEFT
       · Nathan  (second, flipped, head centre-LEFT)  → bio stays TOP-RIGHT (the base position)
     Tighter width cap on both so neither reaches the centred face. */
  .ab-image__bio { max-inline-size: min(22ch, 56vw); }
  .ab-image:first-child .ab-image__bio {
    inset-inline-end: auto;
    inset-inline-start: clamp(20px, 5vw, 40px);
    text-align: left;
  }
}

/* ══════════════════════════════════════════════════════════════════════ CLOSING
   A full-screen WHITE page (Nathan, 2026-08-10: "white page must be extended") so the footer's
   rising-slat wipe has a full white ground to rise over — a clean white → black page-turn. */
.ab-close { text-align: center; min-block-size: 100lvh; display: flex; flex-direction: column; justify-content: center; }
.ab-close__credo { font-family: var(--nd-typography-display-font-family); font-weight: 800; letter-spacing: -0.03em; line-height: 1.02; font-size: clamp(2rem, calc(1rem + 4.4vw), 5rem); max-inline-size: 16ch; margin-inline: auto; margin-block-end: clamp(32px, 4vw, 64px); }
.ab-close__cta { display: flex; gap: clamp(16px, 2vw, 32px); justify-content: center; align-items: center; flex-wrap: wrap; }

/* ══════════════════════════════════════════════════════════════════════ HERO RAIL placement
   Absolute on the hero's lower edge, centred (mirrors .nd-hero__rail). The .ab-rail base (used on
   the swipe floor) stays in normal flow; only the hero copy is pinned. */
.ab-hero { position: relative; }
.ab-rail--hero {
  position: absolute;
  z-index: 1;                          /* above the prism video ground */
  inset-block-end: clamp(20px, 2vh, 40px);
  inset-inline-start: 50%;
  transform: translateX(-50%);
  margin: 0;
}
