/* 00-tokens.css */
/* Self-hosted fonts — static per-weight woff2 files (Task 2). Unlike the
   retired variable-font era, each family ships one physical file per
   weight, so this is one @font-face rule per file (7 total), no shared
   file spanning a weight range. Big Shoulders 500 is deliberately NOT
   shipped: DESIGN.md's "weights 500-800" names the allowed range, not a
   shipping mandate, and nothing on the site uses it — never reference
   font-weight: 500 on the display family. */

@font-face {
  font-family: 'Big Shoulders';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('/fonts/big-shoulders-600.woff2') format('woff2');
}

@font-face {
  font-family: 'Big Shoulders';
  font-style: normal;
  font-weight: 700;
  font-display: swap;
  src: url('/fonts/big-shoulders-700.woff2') format('woff2');
}

@font-face {
  font-family: 'Big Shoulders';
  font-style: normal;
  font-weight: 800;
  font-display: swap;
  src: url('/fonts/big-shoulders-800.woff2') format('woff2');
}

@font-face {
  font-family: 'General Sans';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/fonts/general-sans-400.woff2') format('woff2');
}

@font-face {
  font-family: 'General Sans';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url('/fonts/general-sans-500.woff2') format('woff2');
}

@font-face {
  font-family: 'General Sans';
  font-style: normal;
  font-weight: 600;
  font-display: swap;
  src: url('/fonts/general-sans-600.woff2') format('woff2');
}

@font-face {
  font-family: 'Fragment Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url('/fonts/fragment-mono-400.woff2') format('woff2');
}

/* Machined Star — chrome x brass, dark-only. No theme toggle, no light
   overrides anywhere in this codebase (DESIGN.md S1/S3). Token names and
   hex values below are DESIGN.md S3 law, verbatim — do not rename or
   recolor without amending DESIGN.md first. The pre-v3 electric-blue
   accent is retired sitewide; never reintroduce it (see DESIGN.md S3). */
:root {
  color-scheme: dark;

  --surface: #151210;    /* page ground — warm charcoal, never pure black pages */
  --well: #0B0A08;        /* anodized black — recessed bands, hero wells, card interiors */
  --bone: #EFEAE2;        /* primary text */
  --bone-dim: #A99F92;    /* secondary text, captions */
  --brass: #B08D57;       /* THE accent — CTAs, links, active states, rules that matter */
  --brass-bright: #D9BC82; /* brass for small text on dark, hover glow, point-lights */
  --brass-deep: #8A6B3D;  /* pressed states, brass shadows, engraved strokes */
  --chrome-hi: #F2F4F7;   /* metal gradient family — logo, metallic details, divider highlights */
  --chrome: #C3C9D1;      /* not a text color */
  --chrome-lo: #98A1AB;
  --hairline: rgba(239, 234, 226, .12);

  --display: 'Big Shoulders', sans-serif;
  --body: 'General Sans', sans-serif;
  --mono: 'Fragment Mono', monospace;

  --dur-nav: .4s;
  --ease-nav: cubic-bezier(.4, 0, .2, 1);
}

/* 01-base.css */
/* Reset */
*, *::before, *::after { box-sizing: border-box; margin: 0; padding: 0; }
html { -webkit-text-size-adjust: 100%; text-size-adjust: 100%; -webkit-tap-highlight-color: transparent; }
/* Sitewide guard. A transformed or absolutely-positioned box that overhangs
   the viewport creates scrollable overflow the page never wants — the orbit's
   rotated arms shipped 93px of it to every phone before anyone noticed.
   `clip` rather than `hidden` so this cannot silently create a scroll
   container and break position:sticky on the nav. */
html, body { overflow-x: clip; }
img, picture, svg, video { display: block; max-width: 100%; }
ul, ol { list-style: none; }
a { color: inherit; text-decoration: none; }
button, input, textarea, select { font: inherit; color: inherit; }
button { cursor: pointer; background: none; border: none; }

/* Typography */
body {
  font-family: var(--body);
  font-weight: 400;
  color: var(--bone);
  background: var(--surface);
  line-height: 1.6;
}

h1, h2, h3, h4, h5, h6 {
  font-family: var(--display);
  line-height: 1;
  letter-spacing: .01em;
}

/* ---------- Layout ---------- */

/* The shared max-width rail every section sits inside (comp: .shell). */
.shell {
  max-width: 1360px;
  margin: 0 auto;
  padding: 0 clamp(20px, 4vw, 64px);
}

/* Fragment Mono serial-plate label — eyebrow chips, engraved-plate stamps
   (comp: .plate). */
.plate {
  display: inline-block;
  font: 12px/1 var(--mono);
  letter-spacing: .18em;
  color: var(--brass-bright);
  background: rgba(11, 10, 8, .5);
  border: 1px solid rgba(176, 141, 87, .4);
  border-radius: 2px;
  padding: 8px 14px;
}

/* ---------- Buttons ---------- */
/* The brass CTA pair (comp: .btn / .btn.ghost). .btn is the filled brass
   action; .btn-ghost is its bordered sibling — each works standalone or
   paired in a cta-row. */
.btn, .btn-ghost {
  display: inline-block;
  font-family: var(--body);
  font-weight: 600;
  font-size: 14.5px;
  letter-spacing: .01em;
  padding: 11px 22px;
  border-radius: 3px;
  transition:
    filter var(--dur-nav) var(--ease-nav),
    border-color var(--dur-nav) var(--ease-nav),
    color var(--dur-nav) var(--ease-nav);
}

.btn {
  color: var(--well);
  background: linear-gradient(180deg, var(--brass-bright), var(--brass));
}
.btn:hover, .btn:focus-visible { filter: brightness(1.08); }

.btn-ghost {
  background: none;
  color: var(--bone);
  border: 1px solid var(--hairline);
}
.btn-ghost:hover, .btn-ghost:focus-visible {
  border-color: var(--brass);
  color: var(--brass-bright);
}

/* Selection + scrollbar — themed so OS defaults don't break the surface */
::selection {
  background: var(--brass);
  color: var(--well);
}

html {
  scrollbar-color: var(--brass-deep) var(--surface);
}

::-webkit-scrollbar { width: 12px; }
::-webkit-scrollbar-track { background: var(--surface); }
::-webkit-scrollbar-thumb {
  background: var(--brass-deep);
  border-radius: 6px;
  border: 3px solid var(--surface);
}

@media (prefers-reduced-motion: no-preference) {
  html { scroll-behavior: smooth; }
}

/* Focus */
:focus-visible {
  outline: 2px solid var(--brass);
  outline-offset: 2px;
  border-radius: 2px;
}

/* Motion */
@media (prefers-reduced-motion: reduce) {
  *{animation:none!important;transition:none!important}
}

/* 02-nav.css */
/* Sitewide nav, mobile drawer, footer — dark-only, Machined Star identity.
   Nav starts transparent over the page top and solidifies to --surface on
   scroll (.nav--solid, toggled by src/js/nav.js watching the
   #nav-sentinel IntersectionObserver target). Drawer motion is transform
   + a delayed visibility flip only. Ported from the comps' shared <style>
   head (docs/research/2026-08-16-rebrand-v3/comps/home.html ~L10-150). */

:root {
  --nav-h: 4.5rem;
}

/* Sentinel: zero footprint, positioned against the document (not the
   fixed header) so scrolling the page moves it out of the viewport. */
#nav-sentinel {
  position: absolute;
  top: 0;
  left: 0;
  width: 1px;
  height: 1px;
  pointer-events: none;
}

/* Lock body scroll while the drawer is open (toggled via JS). */
html.scroll-locked,
body.scroll-locked {
  overflow: hidden;
  height: 100%;
}

/* ---------- Header bar ---------- */

.nav {
  position: fixed;
  inset-inline: 0;
  top: 0;
  z-index: 50;
  background: transparent;
  border-bottom: 1px solid transparent;
  transition:
    background-color var(--dur-nav) var(--ease-nav),
    border-color var(--dur-nav) var(--ease-nav);
}

.nav-bar {
  display: flex;
  align-items: center;
  gap: 16px;
  min-height: var(--nav-h);
  padding-block: 18px;
}

.nav-logo {
  display: inline-flex;
  align-items: center;
  gap: 12px;
}

.nav-logo-mark {
  width: 34px;
  height: 34px;
}

.word {
  font-family: var(--display);
  font-weight: 700;
  font-size: 19px;
  letter-spacing: .09em;
  color: var(--bone);
  transition: color var(--dur-nav) var(--ease-nav);
}

.word b {
  color: var(--brass);
  font-weight: 700;
}

.nav-links {
  margin-left: auto;
  display: flex;
  align-items: center;
  gap: 34px;
  font-size: 14.5px;
  font-weight: 500;
}

.nav-links a {
  color: var(--bone-dim);
  transition: color var(--dur-nav) var(--ease-nav);
}
.nav-links a:hover,
.nav-links a:focus-visible {
  color: var(--bone);
}
.nav-links a[aria-current='page'] {
  color: var(--brass);
}

.nav .btn.nav-cta {
  margin-left: 8px;
  padding: 9px 18px;
}

/* ---------- Burger ---------- */

.nav-burger {
  display: none;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 6px;
  width: 44px;
  height: 44px;
  margin-left: auto;
  border-radius: 3px;
  flex-shrink: 0;
}

.nav-burger-line {
  display: block;
  width: 22px;
  height: 2px;
  background: var(--bone);
  transition:
    transform var(--dur-nav) var(--ease-nav),
    background-color var(--dur-nav) var(--ease-nav);
}

.nav-burger[aria-expanded='true'] .nav-burger-line:first-child {
  transform: translateY(4px) rotate(45deg);
}
.nav-burger[aria-expanded='true'] .nav-burger-line:last-child {
  transform: translateY(-4px) rotate(-45deg);
}

/* ---------- Solid state (scrolled, or drawer forced open) ---------- */

.nav--solid,
.nav--drawer-open {
  background: var(--surface);
  border-bottom-color: var(--hairline);
}

/* Focus rings default to --brass (see 01-base.css), which reads fine on
   both the transparent and solid nav states here, so no override needed —
   kept as an explicit anchor point for the drawer surface below. */
.drawer :focus-visible {
  outline-color: var(--brass-bright);
}

/* ---------- Drawer ---------- */

.drawer-scrim {
  position: fixed;
  inset: 0;
  z-index: 44;
  background: var(--well);
  pointer-events: none;
  transition: opacity var(--dur-nav) var(--ease-nav);
}

/* No-JS visitors never get nav.js's class toggling (the burger/drawer do
   nothing without it), so the scrim has nothing to reveal it — removed
   outright rather than left as a permanently invisible opacity:0 layer.
   html.js is added synchronously at the very top of <head>, before the
   stylesheet link, so every JS-capable browser already carries it by the
   time this rule paints (fx-gate: opacity:0 must be scoped to html.js/fx). */
html:not(.js) .drawer-scrim { display: none; }
html.js .drawer-scrim { opacity: 0; }

.drawer-scrim--visible {
  opacity: .6;
  pointer-events: auto;
}

.drawer {
  position: fixed;
  inset-block: 0;
  right: 0;
  z-index: 45;
  width: min(100%, 420px);
  background: var(--surface);
  border-left: 1px solid var(--hairline);
  overflow-y: auto;
  transform: translateX(100%);
  visibility: hidden;
  transition:
    transform var(--dur-nav) var(--ease-nav),
    visibility 0s linear var(--dur-nav);
}

.drawer--open {
  transform: translateX(0);
  visibility: visible;
  transition:
    transform var(--dur-nav) var(--ease-nav),
    visibility 0s linear 0s;
}

.drawer-inner {
  display: flex;
  flex-direction: column;
  min-height: 100%;
  padding-top: calc(var(--nav-h) + 24px);
  padding-bottom: 48px;
  gap: 48px;
}

.drawer-nav {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.drawer-nav a {
  display: inline-flex;
  align-items: center;
  min-height: 44px;
  font-family: var(--display);
  font-weight: 700;
  text-transform: uppercase;
  font-size: clamp(1.75rem, 9vw, 2.5rem);
  line-height: 1.15;
  letter-spacing: .01em;
  color: var(--bone);
  transition: color var(--dur-nav) var(--ease-nav);
}

.drawer-nav a:hover,
.drawer-nav a:focus-visible,
.drawer-nav a[aria-current='page'] {
  color: var(--brass);
}

.drawer-start {
  width: 100%;
  text-align: center;
  margin-top: auto;
}

/* ---------- Footer ---------- */

.footer {
  border-top: 1px solid var(--hairline);
  background: var(--well);
  padding: 64px 0 40px;
}

.foot-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 40px;
  align-items: start;
}

.foot-brand img {
  width: 44px;
  opacity: .9;
}

.foot-brand p {
  color: var(--bone-dim);
  font-size: 14px;
  max-width: 340px;
  margin-top: 16px;
}

.foot-h {
  font: 11.5px/1 var(--mono);
  letter-spacing: .2em;
  text-transform: uppercase;
  color: var(--brass-bright);
  margin-bottom: 16px;
}

.foot-links {
  display: grid;
  gap: 10px;
  font-size: 14.5px;
}

.foot-links a {
  color: var(--bone-dim);
  transition: color var(--dur-nav) var(--ease-nav);
}
.foot-links a:hover,
.foot-links a:focus-visible {
  color: var(--bone);
}

.footer-socials {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 16px;
  margin-top: 14px;
}

.footer-socials a {
  color: var(--brass-bright);
  font-size: 14px;
  transition: color var(--dur-nav) var(--ease-nav);
}
.footer-socials a:hover,
.footer-socials a:focus-visible {
  color: var(--bone);
}

.serial {
  margin-top: 54px;
  padding-top: 22px;
  border-top: 1px solid var(--hairline);
  display: flex;
  justify-content: space-between;
  align-items: center;
  gap: 20px;
  flex-wrap: wrap;
  font: 11px/1.8 var(--mono);
  color: var(--bone-dim);
  letter-spacing: .12em;
}

/* ---------- Burger breakpoint (HARD INVARIANT) ----------
   The mobile burger shows at max-width: 900px; src/js/nav.js auto-closes
   the drawer at matchMedia('(min-width: 901px)') — one pixel above this
   query's ceiling, so there is no dead zone where the burger is hidden
   but the drawer has no way to self-close, or vice versa. Change one,
   change both (lesson recorded in .superpowers/sdd/progress.md, chrome-
   era task 3: a 768px-vs-900px mismatch once stranded the drawer open
   with no visible way to close it). */
@media (max-width: 900px) {
  .nav-links,
  .nav .btn.nav-cta {
    display: none;
  }

  .nav-burger {
    display: inline-flex;
  }
}

@media (min-width: 901px) {
  .foot-grid {
    grid-template-columns: 1.4fr 1fr 1fr;
  }
}

/* 03-home.css */
/* Homepage — preloader, hero, ghost-fill band, capabilities rail, case
   grid, numbers, process steps, pricing plates, plaque CTA. Ported from
   docs/research/2026-08-16-rebrand-v3/comps/home.html. Shared chrome
   (.shell, .plate, .btn/.btn-ghost, nav, footer) lives in 01-base.css /
   02-nav.css — this file is homepage-section-only. The comp itself carries
   no responsive breakpoints (desktop-only reference); mobile-first base
   rules + a 768px desktop lock-in were added here to match the sitewide
   convention (04-work.css / 05-pricing.css / 09-services.css). Font
   weights adapted from the comp's 650/750 (which need a variable font we no
   longer ship, see 00-tokens.css) to the nearest of the three shipped
   static weights (600/700/800) per the CSS weight-matching algorithm — see
   task-5-report.md. */

/* ---------- Preloader ----------
   M·01 scene target (Task 6, src/js/home-fx.js — scene spec already
   transcribed in docs/superpowers/plans/2026-08-17-rebrand-v3-phase4-
   build.md's Task 6 section per porting rule 3). Hidden by default; shown
   only once fx-core.js's double-rAF heartbeat adds html.fx, so a no-JS or
   pre-heartbeat visitor never sees it (fx-gate rule, DESIGN.md S6) — this
   is a display:none gate, not opacity, so the fx-gate opacity scanner
   doesn't even need to look at it. Paths are the a-mark.svg geometry
   inlined as real DOM nodes (not an <img> reference) so Task 6's JS can
   measure and animate their strokes. */
.preloader {
  display: none;
  position: fixed;
  inset: 0;
  z-index: 999;
  place-items: center;
  background: var(--well);
}
html.fx .preloader { display: grid; }
.preloader-mark { width: min(36vw, 200px); height: auto; }

/* ---------- 01 Hero ---------- */
.hero {
  position: relative;
  min-height: min(92svh, 860px);
  display: flex;
  align-items: center;
  overflow: hidden;
}
.hero-img { position: absolute; inset: 0; }
.hero-img video {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: 72% center;
  background: var(--well);
}
.hero-img::after {
  content: '';
  position: absolute;
  inset: 0;
  background:
    linear-gradient(90deg, var(--surface) 22%, rgba(21, 18, 16, .86) 40%, rgba(21, 18, 16, .25) 62%, rgba(21, 18, 16, .45) 100%),
    linear-gradient(0deg, var(--surface) 0%, transparent 26%);
}
.hero-in {
  position: relative;
  z-index: 2;
  padding-block: 64px;
  max-width: 880px;
}
.hero h1 {
  font-family: var(--display);
  font-weight: 800;
  font-size: clamp(48px, 12vw, 132px);
  line-height: .96;
  letter-spacing: .01em;
  text-transform: uppercase;
  margin: 24px 0 0;
}
.hero h1 .l2 { display: block; color: var(--brass); }
.hero p {
  color: var(--bone-dim);
  max-width: 560px;
  margin: 22px 0 32px;
  font-size: clamp(16px, 1.4vw, 19px);
}
.hero p b { color: var(--bone); font-weight: 600; }
.cta-row { display: flex; gap: 14px; align-items: center; flex-wrap: wrap; }
.scroll-cue {
  display: none;
  position: absolute;
  z-index: 2;
  left: 50%;
  bottom: 18px;
  transform: translateX(-50%);
  font: 11px/1 var(--mono);
  color: var(--bone-dim);
  letter-spacing: .22em;
}

@media (min-width: 768px) {
  .hero-in { padding-block: 96px; }
  .scroll-cue { display: block; }
}

/* ---------- 02 Ghost-fill ---------- */
.ghost-fill {
  position: relative;
  padding: 64px 0 72px;
  border-top: 1px solid var(--hairline);
  overflow: hidden;
}
.ghost-fill .line {
  font-family: var(--display);
  font-weight: 800;
  text-transform: uppercase;
  font-size: clamp(40px, 12vw, 118px);
  line-height: 1.02;
  letter-spacing: .01em;
}
.ghost-fill .ghost { color: transparent; -webkit-text-stroke: 1px rgba(239, 234, 226, .28); }
.ghost-fill .fill { color: var(--bone); }
.ghost-fill .fill .hot { color: var(--brass); }
.ghost-fill small {
  display: block;
  margin-top: 22px;
  font: 11px/1.6 var(--mono);
  color: var(--bone-dim);
  letter-spacing: .1em;
}

@media (min-width: 768px) {
  .ghost-fill { padding: 110px 0 118px; }
  .ghost-fill .line { white-space: nowrap; }
  .ghost-fill small { margin-top: 26px; font-size: 12px; letter-spacing: .14em; }
}

/* ---------- Shared section furniture (kicker / lede / section h2) ------
   Reused across svc-rail, case-grid, steps, plates — comp does the same
   (single .kicker/.lede/h2-combo rule spanning several sections). */
.kicker {
  font: 12px/1 var(--mono);
  letter-spacing: .22em;
  color: var(--brass-bright);
  text-transform: uppercase;
}
.svc-rail h2, .case-grid h2, .steps h2, .plates h2 {
  font-family: var(--display);
  font-weight: 700;
  text-transform: uppercase;
  font-size: clamp(34px, 8vw, 68px);
  line-height: 1;
  letter-spacing: .01em;
  margin: 14px 0 12px;
}
.lede { color: var(--bone-dim); max-width: 640px; font-size: 16px; }

@media (min-width: 768px) {
  .lede { font-size: 16.5px; }
}

/* ---------- 03 Capabilities rail ---------- */
.svc-rail { position: relative; padding: 72px 0 32px; border-top: 1px solid var(--hairline); }
.svc-rows { margin-top: 40px; border-top: 1px solid var(--hairline); }
.svc-row {
  display: grid;
  grid-template-columns: 1fr;
  gap: 6px;
  padding: 20px 6px;
  border-bottom: 1px solid var(--hairline);
}
.svc-row .idx { font: 14px/1 var(--mono); color: var(--brass); }
.svc-row .name {
  font-family: var(--display);
  font-weight: 700;
  font-size: 22px;
  text-transform: uppercase;
  letter-spacing: .02em;
  transition: transform .3s cubic-bezier(.4, 0, .2, 1);
}
.svc-row .desc { color: var(--bone-dim); font-size: 14.5px; }
.svc-row .price {
  font: 13px/1 var(--mono);
  color: var(--brass-bright);
  white-space: nowrap;
  text-transform: uppercase; /* comp shows "FROM $1,499"; {{PRICE_*}} tokens
    resolve lowercase ("from $1,499") to stay config-driven — this restores
    the comp's visual caps without duplicating the word "from". */
  transition: color .3s cubic-bezier(.4, 0, .2, 1);
}
.svc-row:hover .name { transform: translateX(8px); }
.svc-row:hover .price { color: var(--bone); }

@media (min-width: 768px) {
  .svc-rail { padding: 110px 0 40px; }
  .svc-rows { margin-top: 56px; }
  .svc-row {
    grid-template-columns: 90px 1fr 1.1fr auto;
    gap: 28px;
    align-items: baseline;
    padding: 26px 6px;
  }
  .svc-row .name { font-size: 27px; }
  .svc-row .desc { font-size: 15px; }
}

/* ---------- 04 Case grid ---------- */
.case-grid {
  position: relative;
  background: var(--well) url('/img/texture-widmanstatten.webp') center/cover;
  background-blend-mode: luminosity;
  border-top: 1px solid var(--hairline);
  padding: 72px 0 56px;
}
.case-grid::before { content: ''; position: absolute; inset: 0; background: rgba(11, 10, 8, .72); }
.case-grid .shell { position: relative; z-index: 2; }
.cases { display: grid; grid-template-columns: 1fr; gap: 20px; margin-top: 40px; }
.case-card {
  display: block;
  background: linear-gradient(180deg, rgba(239, 234, 226, .05), rgba(239, 234, 226, .015));
  border: 1px solid var(--hairline);
  border-radius: 6px;
  overflow: hidden;
  transition: border-color .3s cubic-bezier(.4, 0, .2, 1);
}
.case-card:hover, .case-card:focus-visible { border-color: rgba(176, 141, 87, .5); }
.case-card .shot { border-bottom: 1px solid var(--hairline); aspect-ratio: 16 / 10; overflow: hidden; }
.case-card .shot img { width: 100%; height: 100%; object-fit: cover; object-position: top; }
.case-card .meta { display: flex; align-items: baseline; gap: 14px; padding: 16px 20px; }
.case-card .meta h3 { font-family: var(--display); font-weight: 700; font-size: 19px; text-transform: uppercase; letter-spacing: .03em; }
.case-card .meta span { font: 11.5px/1.5 var(--mono); color: var(--bone-dim); }
.case-card .meta .tag { margin-left: auto; color: var(--brass-bright); }

@media (min-width: 768px) {
  .case-grid { padding: 118px 0 96px; }
  .cases { grid-template-columns: 1fr 1fr; gap: 26px; margin-top: 58px; }
  .case-card .meta h3 { font-size: 21px; }
}

/* ---------- 05 Numbers ---------- */
.numbers { border-top: 1px solid var(--hairline); background: var(--well); }
.num-grid { display: grid; grid-template-columns: 1fr 1fr; }
.num { padding: 34px 20px; border-right: 1px solid var(--hairline); border-bottom: 1px solid var(--hairline); }
.num:nth-child(2n) { border-right: none; }
.num:nth-last-child(-n+2) { border-bottom: none; }
.num .v { font-family: var(--display); font-weight: 800; font-size: clamp(38px, 8vw, 74px); line-height: 1; color: var(--brass); }
.num .k { font: 11px/1.5 var(--mono); letter-spacing: .12em; color: var(--bone-dim); text-transform: uppercase; margin-top: 10px; }

@media (min-width: 768px) {
  .num-grid { grid-template-columns: repeat(4, 1fr); }
  .num { padding: 54px 34px; border-bottom: none; }
  .num:nth-child(2n) { border-right: 1px solid var(--hairline); }
  .num:last-child { border-right: none; }
  .num .k { font-size: 11.5px; letter-spacing: .16em; margin-top: 12px; }
}

/* ---------- 06 Steps ---------- */
/* A pinned section is position:fixed while held. Without its own background
   whatever scrolls behind composites straight through the process copy —
   that is what turned the pin-offset bug into illegible stacked text rather
   than merely a wrong scroll position. Opaque by default so any future
   geometry error degrades to "shown at the wrong time" instead of "shown on
   top of the founder bio". */
.steps {
  background: var(--surface);
  position: relative;
  padding: 72px 0;
  border-top: 1px solid var(--hairline);
}
.steps-grid { display: grid; grid-template-columns: 1fr; gap: 32px; margin-top: 20px; }
/* aspect-ratio reserves the box's final height before the lazy-attached
   media (poster isn't fetched until near-viewport; the film itself only via
   attachVideos' IntersectionObserver) resolves — otherwise .steps-img
   collapses to 0 height, the section grows once media loads, and everything
   below (incl. the M·07 pinned plaque section) shifts: a real layout-shift/
   scroll-jump source under slow devices. 1376/768 matches the guilloché
   film's poster frame (and the old widmanstatten placeholder before it). */
.steps-img { border: 1px solid var(--hairline); border-radius: 6px; overflow: hidden; aspect-ratio: 1376 / 768; }
.steps-img img, .steps-img video { width: 100%; height: 100%; object-fit: cover; display: block; }
.step { display: grid; grid-template-columns: 56px 1fr; gap: 16px; padding: 18px 0; border-bottom: 1px solid var(--hairline); align-items: baseline; }
.step:first-child { border-top: 1px solid var(--hairline); }
.step .idx { font: 14px/1 var(--mono); color: var(--brass); }
.step h3 { font-family: var(--display); font-weight: 700; font-size: 20px; text-transform: uppercase; letter-spacing: .02em; }
.step p { color: var(--bone-dim); font-size: 14.5px; margin-top: 4px; }
.ethic { margin-top: 28px; font-family: var(--display); font-weight: 700; font-size: 22px; text-transform: uppercase; color: var(--brass); letter-spacing: .02em; }

@media (min-width: 768px) {
  .steps { padding: 118px 0; }
  .steps-grid { grid-template-columns: 1.05fr 1fr; gap: 64px; align-items: center; margin-top: 26px; }
  .step { grid-template-columns: 70px 1fr; gap: 20px; padding: 22px 0; }
  .step h3 { font-size: 24px; }
  .step p { font-size: 15px; }
  .ethic { margin-top: 34px; font-size: 27px; }
}

/* ---------- 07 Pricing plates ---------- */
.plates { position: relative; padding: 72px 0; border-top: 1px solid var(--hairline); }
.plates-grid { display: grid; grid-template-columns: 1fr; gap: 20px; margin-top: 36px; }
.plate-card {
  position: relative;
  background: var(--well);
  border: 1px solid var(--hairline);
  border-radius: 6px;
  padding: 32px 26px 30px;
  /* M·06 (Task 6, home-fx.js) toggles .is-bloom once each plate settles. */
  transition: box-shadow .5s var(--ease-nav);
}
.plate-card--feat {
  border-color: rgba(176, 141, 87, .55);
  box-shadow: 0 0 0 1px rgba(176, 141, 87, .25), 0 24px 60px -30px rgba(0, 0, 0, .8);
}
.plate-card.is-bloom { box-shadow: 0 0 34px -8px rgba(176, 141, 87, .4); }
.plate-card--feat.is-bloom {
  box-shadow: 0 0 0 1px rgba(176, 141, 87, .55), 0 24px 60px -30px rgba(0, 0, 0, .8), 0 0 40px -6px rgba(217, 188, 130, .45);
}
.plate-tier { font: 12px/1 var(--mono); letter-spacing: .2em; color: var(--brass-bright); text-transform: uppercase; }
/* "Most Popular" stamp riveted over the featured plate's top edge — shared
   sitewide furniture like `.amt`/`.per` below (home's .plate-card--feat and
   pricing's .pcard.feat both sit position: relative, so the chip anchors the
   same way on either card). Mirrors 01-base.css's `.plate` serial-chip
   vocabulary at stamp scale. */
.feat-flag {
  position: absolute;
  top: 0;
  right: 22px;
  transform: translateY(-50%);
  font: 10.5px/1 var(--mono);
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--brass-bright);
  background: var(--well);
  border: 1px solid rgba(176, 141, 87, .55);
  border-radius: 2px;
  padding: 6px 10px;
  white-space: nowrap;
}
.amt { font-family: var(--display); font-weight: 800; font-size: 46px; line-height: 1; margin: 18px 0 4px; }
.amt small { font-size: 18px; font-weight: 700; color: var(--bone-dim); }
.per { font-size: 13px; color: var(--bone-dim); }
.plate-card ul { list-style: none; margin: 22px 0 26px; display: grid; gap: 10px; }
.plate-card li { font-size: 14px; color: var(--bone-dim); padding-left: 20px; position: relative; }
.plate-card li::before { content: ''; position: absolute; left: 0; top: 9px; width: 9px; height: 2px; background: var(--brass); }
.own-line { margin-top: 36px; text-align: center; font-size: 15px; color: var(--bone-dim); }
.own-line b { color: var(--bone); font-weight: 600; }
/* A second stacked own-line (the starting-points disclaimer) sits tight
   under the first and a step quieter. */
.own-line + .own-line { margin-top: 10px; font-size: 13.5px; }

@media (min-width: 768px) {
  .plates { padding: 118px 0; }
  .plates-grid { grid-template-columns: repeat(3, 1fr); gap: 26px; margin-top: 56px; }
  .plate-card { padding: 40px 34px 36px; }
  .amt { font-size: 62px; }
  .amt small { font-size: 22px; }
  .per { font-size: 13.5px; }
  .plate-card li { font-size: 14.5px; }
  .own-line { margin-top: 44px; font-size: 15.5px; }
}

/* ---------- 08 Plaque CTA ---------- */
.plaque-cta {
  position: relative;
  /* Opaque floor beneath .plaque-bg's lazy image — a pinned section must
     never be see-through, see the .steps note above. */
  background: var(--well);
  min-height: min(78svh, 700px);
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  overflow: hidden;
  border-top: 1px solid var(--hairline);
}
.plaque-bg { position: absolute; inset: 0; }
.plaque-bg img { width: 100%; height: 100%; object-fit: cover; }
.plaque-bg::after {
  content: '';
  position: absolute;
  inset: 0;
  background: radial-gradient(ellipse at center, rgba(11, 10, 8, .18), rgba(11, 10, 8, .78) 78%);
}
.plaque-in { position: relative; z-index: 2; padding: 80px 24px; }
.plaque-in h2 {
  position: relative;
  font-family: var(--display);
  font-weight: 800;
  text-transform: uppercase;
  font-size: clamp(36px, 10vw, 84px);
  line-height: .98;
  letter-spacing: .01em;
}
/* M·07 (Task 6, home-fx.js) light-engrave mask. Existence itself is
   html.fx-gated (not just its opacity) — under no-JS/pre-heartbeat this
   selector never matches, so the pseudo-element is never generated at all.
   GSAP can't tween a ::after directly, so home-fx.js drives it by tweening
   --sweep/--sweep-o (plain numbers) on the real h2 element; custom
   properties inherit into pseudo-elements, and the var() fallbacks below
   keep it fully inert (positioned off to the right, invisible) any moment
   the scene hasn't started its one-shot sweep yet. Purely decorative —
   never hides real heading content — so it's the one entry in this file's
   reduced-motion coverage that gets forced OFF rather than forced visible;
   see 08-motion.css. */
html.fx .plaque-in h2::after {
  content: '';
  position: absolute;
  inset: -20% -10%;
  pointer-events: none;
  background: linear-gradient(100deg, transparent 40%, rgba(217, 188, 130, .55) 50%, transparent 60%);
  background-size: 260% 100%;
  background-position: calc(var(--sweep, 130) * 1%) 0;
  mix-blend-mode: screen;
  opacity: var(--sweep-o, 0);
}
.plaque-in p { color: var(--bone); opacity: .85; max-width: 520px; margin: 20px auto 30px; font-size: 16px; }
.plaque-in .fineprint { margin-top: 16px; font: 11px/1.6 var(--mono); color: var(--bone-dim); letter-spacing: .08em; }

@media (min-width: 768px) {
  .plaque-in { padding: 120px 24px; }
  .plaque-in p { font-size: 16.5px; margin: 22px auto 34px; }
  .plaque-in .fineprint { margin-top: 18px; font-size: 11.5px; letter-spacing: .1em; }
}

/* 04-work.css */
/* Work page — case-study theater: page intro, four full-bleed case scenes
   (Funday Rentals, Rafael Sells, PrintingFunds, SDF Dirtworks & Utilities),
   a bench-sample strip, and a plaque CTA reused verbatim from Home (see
   03-home.css's .plaque-cta/.plaque-bg/.plaque-in — no new rules needed
   here for that section). Ported from
   docs/research/2026-08-16-rebrand-v3/comps/work.html.

   The comp is desktop-first but — unlike home.html's comp — DOES carry its
   own two breakpoints (880px scene-grid collapse, 700px bench-card
   collapse); both are kept at their exact comp values but flipped to
   mobile-first (min-width) here to match the sitewide convention
   (03-home.css), same as that file's own port note. Base rules below are
   the single-column/stacked mobile layout; the two @media blocks add the
   desktop two-up grids.

   Font-weight 750/650 mapped per the CSS weight-matching algorithm
   (task-5-report.md: target > 500 → nearest available at or above):
   750→800 (.intro h1, .scene-copy h2), 650→700 (.bench-card .meta h3).

   Full rewrite, not additive: the previous version of this file styled the
   pre-rebrand `.page-head`/`.container`/`.case-*`/`.btn-primary` markup
   this page no longer ships. Of those, `.container`/`.eyebrow` already have
   no working CSS anywhere in this codebase as of Task 3's 01-base.css
   rewrite (verified — `.container`/`.eyebrow` are undefined sitewide;
   `.btn-primary` has no bare styling rule, only page-scoped compounds in
   09-services.css). `.page-head`/`.page-head h1`/`.page-lede`/`.case-close`
   were kept through Tasks 8-9 (checkup.html, contact.html, privacy.html,
   and thanks.html still emitted that markup then) and are gone now: Task 10
   rewrote all four of those pages' markup wholesale (checkup.html retired
   outright, folded into a rewritten contact.html) the same way this task
   replaced work.html's, so nothing sitewide references those three classes
   any more — the shared block itself was deleted from this file in Task 10,
   not just its callers. */

/* ---------- Page intro ---------- */
.intro {
  position: relative;
  padding: 100px 0 56px;
}
.intro h1 {
  font-family: var(--display);
  font-weight: 800;
  text-transform: uppercase;
  font-size: clamp(44px, 12vw, 100px);
  line-height: .96;
  letter-spacing: .01em;
  margin: 16px 0 16px;
}
.intro .lede {
  color: var(--bone-dim);
  max-width: 640px;
  font-size: 16px;
}

@media (min-width: 768px) {
  .intro { padding: 128px 0 74px; }
  .intro .lede { font-size: 16.5px; }
}

/* ---------- Case scenes ---------- */
.scene {
  position: relative;
  min-height: min(96vh, 920px);
  display: flex;
  align-items: center;
  overflow: hidden;
  border-top: 1px solid var(--hairline);
  padding: 90px 0;
}
.scene-bg {
  position: absolute;
  inset: 0;
  background: var(--well) url('/img/texture-widmanstatten.webp') center/cover;
  background-blend-mode: luminosity;
}
/* Task 13 environment film — sits over the texture fallback, under the
   ::after scrim and the bolts (both later in paint order). */
.scene-bg video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}
.scene-bg::after {
  content: '';
  position: absolute;
  inset: 0;
  background: rgba(11, 10, 8, .76);
}
.scene-bg .bolt {
  position: absolute;
  width: 6px;
  height: 6px;
  border-radius: 50%;
  background: radial-gradient(circle at 35% 30%, var(--chrome-hi), var(--brass-deep) 70%);
  opacity: .55;
}
.scene-bg .bolt.tl { top: 22px; left: 22px; }
.scene-bg .bolt.br { bottom: 22px; right: 22px; }

.scene-in.shell {
  position: relative;
  z-index: 2;
  display: grid;
  grid-template-columns: 1fr;
  gap: 32px;
  width: 100%;
}

.scene-copy h2 {
  font-family: var(--display);
  font-weight: 800;
  text-transform: uppercase;
  font-size: clamp(38px, 11vw, 92px);
  line-height: .96;
  margin: 14px 0 14px;
  color: var(--bone);
}
.scene-copy .discipline {
  font-size: 15.5px;
  color: var(--bone-dim);
  max-width: 400px;
  margin-bottom: 20px;
}
.scene-copy .tag {
  display: inline-block;
  font: 11px/1 var(--mono);
  letter-spacing: .16em;
  color: var(--brass-bright);
  border: 1px solid rgba(176, 141, 87, .4);
  padding: 8px 13px;
  border-radius: 2px;
  background: rgba(11, 10, 8, .5);
  text-transform: uppercase;
}
.scene-copy .tag.preview {
  color: var(--bone);
  border-color: var(--hairline);
}

/* Live URL beside the status tag. Every case that IS live now links out —
   a page that says "Live" without a link is asking to be doubted, and the
   client footers carry a reciprocal dofollow link back here anyway. */
.scene-copy .tag-row { display: flex; gap: 10px; align-items: center; flex-wrap: wrap; }
.scene-copy .visit {
  display: inline-block;
  font: 11px/1 var(--mono);
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--well);
  background: linear-gradient(180deg, var(--brass-bright), var(--brass));
  border: 1px solid var(--brass);
  padding: 8px 13px;
  border-radius: 2px;
  transition: filter var(--dur-nav) var(--ease-nav);
}
.scene-copy .visit:hover, .scene-copy .visit:focus-visible { filter: brightness(1.08); }
.bench-card .meta .visit {
  display: inline-block;
  margin-top: 20px;
  margin-left: 8px;
  font: 10.5px/1 var(--mono);
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--brass-bright);
  border: 1px solid rgba(176, 141, 87, .4);
  padding: 7px 12px;
  border-radius: 2px;
}

/* device-stack: on mobile both bezels sit in normal flow, stacked — no
   overlap, so work-fx.js's desktop-only scrub (see that file) has nothing
   to do here; .bezel.mobile is simply the second block in a single column. */
.device-stack {
  position: relative;
  margin-top: 8px;
}
.bezel {
  border: 1px solid var(--hairline);
  border-radius: 6px;
  overflow: hidden;
  background: var(--well);
  box-shadow: 0 34px 76px -32px rgba(0, 0, 0, .8);
}
.bezel.desktop .bar {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 10px 14px;
  border-bottom: 1px solid var(--hairline);
  background: linear-gradient(180deg, rgba(239, 234, 226, .06), rgba(239, 234, 226, .02));
}
.bezel.desktop .bar .dot { width: 8px; height: 8px; border-radius: 50%; background: var(--brass-deep); }
.bezel.desktop .bar .fig { margin-left: auto; font: 10.5px/1 var(--mono); color: var(--bone-dim); letter-spacing: .12em; }
.bezel.desktop .shot { aspect-ratio: 16 / 10; overflow: hidden; }
.bezel.desktop .shot img { width: 100%; height: 100%; object-fit: cover; object-position: top; }

.bezel.mobile {
  position: relative;
  width: 190px;
  margin: 20px 0 0 auto;
  border-radius: 22px;
  padding: 8px 8px 14px;
  box-shadow: 0 26px 54px -20px rgba(0, 0, 0, .85);
}
.bezel.mobile .notch { width: 30%; height: 4px; background: rgba(239, 234, 226, .16); border-radius: 3px; margin: 0 auto 8px; }
.bezel.mobile .shot { aspect-ratio: 9 / 19.5; border-radius: 14px; overflow: hidden; }
.bezel.mobile .shot img { width: 100%; height: 100%; object-fit: cover; object-position: top; }

/* Comp breakpoint (880px), flipped to min-width. Above it: two-up grid,
   the mobile bezel overlaps the desktop bezel's bottom-right corner — a
   fixed side chosen because every real screenshot is left-aligned, so the
   overlap never crosses headline text regardless of which column the
   device-stack lands in (.scene.alt swaps column order via `order`, not
   the bezel's own side). work-fx.js's scrub morph (desktop bezel scales
   down/fades as the mobile bezel fades in) only runs at this same
   DESKTOP gate, so the static CSS end-state here already matches its
   resolved frame — a no-JS visitor at ≥880px sees the same finished
   layout a JS visitor lands on. */
@media (min-width: 880px) {
  .scene-in.shell {
    grid-template-columns: 1fr 1.05fr;
    gap: 60px;
    align-items: center;
  }
  .scene.alt .scene-copy { order: 2; }
  .scene.alt .device-stack { order: 1; }

  .device-stack { margin-top: 0; }
  .bezel.mobile {
    position: absolute;
    right: -7%;
    bottom: -14%;
    width: 32%;
    min-width: 148px;
    max-width: 210px;
    margin: 0;
  }
}

/* ---------- Bench sample ---------- */
.bench {
  position: relative;
  padding: 72px 0 30px;
  border-top: 1px solid var(--hairline);
}
.bench h2 {
  font-family: var(--display);
  font-weight: 700;
  text-transform: uppercase;
  font-size: clamp(34px, 8vw, 60px);
  line-height: 1;
  letter-spacing: .01em;
  margin: 14px 0 12px;
}
.bench .lede { color: var(--bone-dim); max-width: 600px; font-size: 15px; }
.bench-strip { margin-top: 36px; }
.bench-card {
  display: grid;
  grid-template-columns: 1fr;
  background: linear-gradient(180deg, rgba(239, 234, 226, .05), rgba(239, 234, 226, .015));
  border: 1px solid var(--hairline);
  border-radius: 6px;
  overflow: hidden;
}
.bench-card .shot { aspect-ratio: 16 / 10; overflow: hidden; filter: grayscale(.2) brightness(.82); }
.bench-card .shot img { width: 100%; height: 100%; object-fit: cover; object-position: top; }
.bench-card .meta {
  padding: 24px 22px 28px;
  display: flex;
  flex-direction: column;
  justify-content: center;
  border-top: 1px solid var(--hairline);
}
.bench-card .meta h3 {
  font-family: var(--display);
  font-weight: 700;
  font-size: clamp(22px, 5vw, 32px);
  text-transform: uppercase;
  letter-spacing: .02em;
  color: var(--bone);
}
.bench-card .meta p { font-size: 14.5px; color: var(--bone-dim); margin-top: 10px; }
.bench-card .meta .tag {
  display: inline-block;
  margin-top: 20px;
  font: 10.5px/1 var(--mono);
  color: var(--bone-dim);
  border: 1px solid var(--hairline);
  padding: 7px 12px;
  border-radius: 2px;
  letter-spacing: .14em;
  text-transform: uppercase;
  align-self: flex-start;
}

@media (min-width: 768px) {
  .bench { padding: 118px 0 30px; }
  .bench .lede { font-size: 15.5px; }
}

/* Comp breakpoint (700px), flipped to min-width. */
@media (min-width: 700px) {
  .bench-card {
    grid-template-columns: 1.35fr 1fr;
    align-items: stretch;
  }
  .bench-card .meta {
    padding: 34px 40px;
    border-top: none;
    border-left: 1px solid var(--hairline);
  }
}

/* 05-pricing.css */
/* Pricing page — hero, the four package plates (Launch/Business/Growth/
   Custom) plus the three monthly care plates (same .price-grid/.pcard
   component, `--care` grid modifier), the add-ons index (the comp's
   quoted-families .qf row component, re-pointed at published add-on
   prices), an ownership band, FAQ accordion, plaque CTA (aliased to Home's
   .plaque-cta — see pricing.html's own comment on that section). Ported from
   docs/research/2026-08-16-rebrand-v3/comps/pricing.html. Shared chrome
   (.shell, .kicker, .lede, .plate, .btn/.btn-ghost, .cta-row, nav, footer)
   lives in 01-base.css/02-nav.css/03-home.css — this file is pricing-page-
   only.

   Class-collision note (why several section wrappers are renamed from the
   comp's literal names): the comp is a standalone preview file with its own
   self-contained <style> block, so its class names were never checked
   against the OTHER four comps' class names. The shipped site concatenates
   every page's CSS into one bundle (build.mjs), so a bare selector defined
   on one page's file applies everywhere. `.hero` and `.plates` are already
   home.html's (03-home.css, both bare selectors) — reusing them here would
   let this file's rules silently override home's on every page, and vice
   versa. `.cta`/`.cta-in`/`.bg` are already services.html's (09-services.css,
   also bare) with deliberately different sizing (58vh/520px vs. this comp's
   78vh/700px) — same risk. Renamed: `.hero`→`.pricing-hero`, `.plates`→
   `.price-plates`; the CTA section is aliased into Home/Work's existing
   `.plaque-cta`/`.plaque-bg`/`.plaque-in` instead of getting a third `.cta`
   variant (see pricing.html's own comment + task-9-report.md for the M·06
   reading). `.quoted`/`.owned`/`.faq`/`.qf`/`.qf-rows`/`.price-grid`/`.pcard`/
   `.receipts`/`.receipt` are all comp-exclusive names, verified against
   every other src/css/*.css file — safe to ship bare.

   `.amt`/`.amt small`/`.per` are deliberately NOT redeclared here (see
   pricing.html's own comment on `.price-plates`) — reused as-is from
   03-home.css's existing bare rules. `.pcard` padding/`.price-grid` gaps
   mirror home's `.plate-card`/`.plates-grid` mobile→desktop scaling
   (32/26/30px → 40/34/36px; 20px/36px-gap → 26px/56px-gap) exactly, since
   comp's own desktop-only numbers for both match home's precisely — the
   same "price plate" component, re-skinned under different section names
   only because of the collision above.

   The comp is desktop-first and carries one breakpoint (900px, `.price-grid`/
   `.qf` collapse) — kept at its exact comp value but flipped to mobile-first
   (min-width) here, matching the sitewide convention (04-work.css/
   09-services.css). Base rules below are the single-column mobile layout;
   the 900px block adds the desktop grids. A separate 768px block (shared
   sitewide breakpoint) bumps section padding/type up to the comp's literal
   desktop figures, same two-tier pattern as 03-home.css/04-work.css/
   09-services.css.

   Font-weight 750/650 mapped per the CSS weight-matching algorithm
   (task-5-report.md: target > 500 → nearest available at or above):
   750→800 (`.pricing-hero h1`), 650→700 (`.faq-item summary`).
   `.price-plates h2, .quoted h2, .owned h2, .faq h2`'s comp weight 700 is an
   exact match to a shipped weight — no mapping needed. */

/* ---------- 01 Hero (M·01) ---------- */
.pricing-hero {
  position: relative;
  min-height: min(56vh, 480px);
  display: flex;
  align-items: center;
  overflow: hidden;
  background: var(--well) url('/img/texture-widmanstatten.webp') center/cover;
  background-blend-mode: luminosity;
  border-bottom: 1px solid var(--hairline);
}
.pricing-hero::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: 1;
  background:
    radial-gradient(ellipse at 26% 38%, rgba(176, 141, 87, .12), transparent 58%),
    linear-gradient(180deg, rgba(11, 10, 8, .58), rgba(11, 10, 8, .88));
}
.pricing-hero .hero-in {
  position: relative;
  z-index: 2;
  padding-block: 64px 56px;
  max-width: 760px;
}
.pricing-hero h1 {
  font-family: var(--display);
  font-weight: 800;
  font-size: clamp(46px, 6.2vw, 92px);
  line-height: .98;
  letter-spacing: .005em;
  text-transform: uppercase;
  margin: 22px 0 0;
}
.pricing-hero h1 .l2 { display: block; color: var(--brass); }
.pricing-hero p {
  font-size: clamp(15.5px, 1.3vw, 18px);
  color: var(--bone-dim);
  max-width: 540px;
  margin: 20px 0 28px;
  font-weight: 450;
}

@media (min-width: 768px) {
  .pricing-hero .hero-in { padding-block: 88px 74px; }
  .pricing-hero h1 { margin: 26px 0 0; }
  .pricing-hero p { margin: 24px 0 34px; }
}

/* ---------- Shared section furniture (h2) ----------
   Comp's own combined selector, ported 1:1 with `.plates`→`.price-plates`. */
.price-plates h2, .addons h2, .owned h2, .faq h2 {
  font-family: var(--display);
  font-weight: 700;
  text-transform: uppercase;
  font-size: clamp(40px, 4.6vw, 68px);
  line-height: 1;
  margin: 16px 0 12px;
}

/* ---------- 02 Plates: Rebuild / Build / Care (M·02) ---------- */
.price-plates { position: relative; padding: 72px 0; border-top: 1px solid var(--hairline); }
.price-grid { display: grid; grid-template-columns: 1fr; gap: 20px; margin-top: 36px; }
.pcard {
  position: relative;
  background: var(--well);
  border: 1px solid var(--hairline);
  border-radius: 6px;
  padding: 32px 26px 30px;
  display: flex;
  flex-direction: column;
  transition: box-shadow .5s var(--ease-nav);
}
.pcard.feat {
  border-color: rgba(176, 141, 87, .55);
  box-shadow: 0 0 0 1px rgba(176, 141, 87, .25), 0 24px 60px -30px rgba(0, 0, 0, .8);
}
/* M·02 (pricing-fx.js) toggles this once each pcard settles — same bloom
   mechanic as home's .plate-card.is-bloom (03-home.css). */
.pcard.is-bloom { box-shadow: 0 0 34px -8px rgba(176, 141, 87, .4); }
.pcard.feat.is-bloom {
  box-shadow: 0 0 0 1px rgba(176, 141, 87, .55), 0 24px 60px -30px rgba(0, 0, 0, .8), 0 0 40px -6px rgba(217, 188, 130, .45);
}
.pcard .tier { font: 12px/1 var(--mono); letter-spacing: .2em; color: var(--brass-bright); text-transform: uppercase; }
.pcard ul { margin: 22px 0 26px; display: grid; gap: 10px; flex: 1; }
.pcard li { font-size: 14px; color: var(--bone-dim); padding-left: 20px; position: relative; line-height: 1.45; }
.pcard li::before { content: ''; position: absolute; left: 0; top: 9px; width: 9px; height: 2px; background: var(--brass); }
.pcard .btn, .pcard .btn-ghost { text-align: center; margin-top: auto; }
/* Notes under the packages grid — the refresh/rebuild pointer and the
   starting-points disclaimer. Same quiet centered treatment as home's
   .own-line, a step smaller for the second (stacked) note. */
.plate-note { margin-top: 32px; text-align: center; font-size: 14.5px; color: var(--bone-dim); }
.plate-note b { color: var(--bone); font-weight: 600; }
.plate-note + .plate-note { margin-top: 10px; font-size: 13.5px; }

@media (min-width: 768px) {
  .price-plates { padding: 110px 0; }
  .pcard { padding: 40px 34px 36px; }
  .pcard li { font-size: 14.5px; }
  .plate-note { margin-top: 40px; }
}

/* Comp breakpoint (900px), flipped to min-width. Four package plates sit
   2×2 rather than 4-across — four bullet-heavy cards in one row would
   squeeze each below ~300px and wrap every line (the comp's 3-across value
   assumed three plates). The three care plates keep the comp's original
   one-row shape via the `--care` modifier. */
@media (min-width: 900px) {
  .price-grid { grid-template-columns: repeat(2, 1fr); gap: 26px; margin-top: 56px; }
  .price-grid--care { grid-template-columns: repeat(3, 1fr); }
}

/* ---------- 03 Add-ons index (M·03) ----------
   The comp's quoted-families row component (.qf/.qf-rows), re-pointed: the
   section now lists published add-on prices, with each row's tag slot
   carrying the starting price or range instead of the QUOTED stamp. */
.addons { position: relative; padding: 72px 0; border-top: 1px solid var(--hairline); }
/* Group label splitting the index into "Website add-ons" and "Other
   services" — the same mono serial vocabulary as .kicker/.plate, sized as
   a quiet divider rather than a section heading. */
.qf-sub {
  margin-top: 40px;
  font: 12px/1 var(--mono);
  letter-spacing: .18em;
  text-transform: uppercase;
  color: var(--brass);
}
.qf-sub + .qf-rows { margin-top: 14px; }
.qf-rows { margin-top: 36px; border-top: 1px solid var(--hairline); }
.qf {
  display: grid;
  grid-template-columns: 1fr;
  gap: 8px;
  align-items: baseline;
  padding: 18px 4px;
  border-bottom: 1px solid var(--hairline);
}
.qf .idx { order: -1; font: 15px/1 var(--mono); color: var(--brass); }
.qf .name { font-family: var(--display); font-weight: 700; font-size: 20px; text-transform: uppercase; letter-spacing: .02em; }
.qf .desc { color: var(--bone-dim); font-size: 14px; }
.qf .tag {
  justify-self: start;
  font: 12px/1 var(--mono);
  color: var(--brass-bright);
  letter-spacing: .12em;
  white-space: nowrap;
  transition: color .3s cubic-bezier(.4, 0, .2, 1);
}
.qf:hover .tag, .qf:focus-within .tag { color: var(--bone); }

@media (min-width: 768px) {
  .addons { padding: 110px 0; }
  .qf-rows { margin-top: 52px; }
}

/* Comp breakpoint (900px), flipped to min-width. */
@media (min-width: 900px) {
  .qf {
    grid-template-columns: 84px 1fr 1.5fr auto;
    gap: 26px;
    padding: 25px 6px;
  }
  .qf .idx { order: initial; }
  .qf .name { font-size: 24px; }
  .qf .desc { font-size: 14.5px; }
  .qf .tag { justify-self: auto; }
}

/* ---------- 04 Ownership band (M·04) ---------- */
.owned {
  position: relative;
  padding: 72px 0;
  border-top: 1px solid var(--hairline);
  background: var(--well);
  text-align: center;
}
.owned .kicker { display: block; }
.owned h2 { margin-left: auto; margin-right: auto; }
/* Rest state: a plain, fully-drawn brass rule — GSAP's own gsap.from() sets
   the transient scaleX:0 start state at runtime only (pricing-fx.js M·04),
   never via CSS, so no-JS/pre-heartbeat visitors see it fully drawn (fx-gate
   compliant by construction, same contract as every other reveal on site). */
.owned .rule {
  width: 72px;
  height: 2px;
  background: var(--brass);
  margin: 20px auto 0;
  transform-origin: left;
}
.owned p { color: var(--bone-dim); max-width: 600px; margin: 14px auto 0; font-size: 16.5px; }
.receipts { display: flex; justify-content: center; gap: 36px; margin-top: 40px; flex-wrap: wrap; }
.receipt b { display: block; font-family: var(--display); font-weight: 700; font-size: 22px; color: var(--brass); text-transform: uppercase; letter-spacing: .03em; margin-bottom: 8px; }
.receipt span { font: 11.5px/1.6 var(--mono); color: var(--bone-dim); letter-spacing: .1em; text-transform: uppercase; }

@media (min-width: 768px) {
  .owned { padding: 100px 0; }
  .receipts { margin-top: 50px; }
}

/* Comp breakpoint (900px), flipped to min-width. */
@media (min-width: 900px) {
  .receipts { gap: 60px; }
}

/* ---------- 05 FAQ accordion (M·05) ---------- */
.faq { position: relative; padding: 72px 0; border-top: 1px solid var(--hairline); }
.faq-list { margin-top: 36px; max-width: 820px; }
.faq-item { border-top: 1px solid var(--hairline); padding: 20px 0; }
.faq-list .faq-item:last-child { border-bottom: 1px solid var(--hairline); }
.faq-item summary {
  cursor: pointer;
  list-style: none;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 20px;
  font-family: var(--display);
  font-weight: 700;
  font-size: 18px;
  text-transform: uppercase;
  letter-spacing: .01em;
  color: var(--bone);
}
.faq-item summary::-webkit-details-marker { display: none; }
/* Comp authors no transition on the glyph — a plain content swap, kept
   verbatim rather than inventing a rotate/flip animation the comp doesn't
   specify (CSS-only per the brief; JS is reserved for the 18px/120ms slide
   below, which CSS alone can't do against native <details>). */
.faq-item summary::after { content: '+'; font-family: var(--mono); font-size: 20px; color: var(--brass); flex: none; }
.faq-item[open] summary::after { content: '\2013'; }
.faq-item p { color: var(--bone-dim); font-size: 15px; margin-top: 14px; max-width: 640px; }

@media (min-width: 768px) {
  .faq { padding: 110px 0; }
  .faq-list { margin-top: 48px; }
  .faq-item { padding: 22px 0; }
  .faq-item summary { font-size: 19px; }
}

/* 06-forms.css */
/* Contact page (checkup funnel — pitch column + form card) and the Thanks
   success state. Ported from
   docs/research/2026-08-16-rebrand-v3/comps/contact.html. Shared chrome
   (.shell, .kicker, .lede, .plate, .btn/.btn-ghost, nav, footer) lives in
   01-base.css / 02-nav.css / 03-home.css — this file is contact/thanks-only.
   .util-hero (thanks.html's base intro treatment) and .inline-link (the
   "call or text" link below) are shared primitives defined in 07-misc.css,
   also used by privacy.html — see that file's header comment.

   Class-collision note: `.field` supersedes the pre-rebrand rules this file
   used to carry for checkup.html/contact.html's old markup (both retired —
   checkup.html deleted, contact.html rewritten below) — full rewrite, no
   collision risk since this file owns `.field` outright. Every other class
   here (`.contact`, `.contact-grid`, `.pitch`, `.c-plate`, `.c-row`, `.c-k`,
   `.c-v`, `.form-wrap`, `.form-card`, `.f-label`, `.ts-note`) was grepped
   against every other src/css/*.css file and confirmed comp-exclusive.
   `.pitch .fineprint` is scoped (not a bare `.fineprint` rule) to match the
   two other existing usages sitewide (`.plaque-in .fineprint` in
   03-home.css, `.cta .fineprint` in 09-services.css — both scoped
   compounds, never bare).

   The comp is desktop-first and carries one breakpoint of its own (860px,
   `.contact-grid` column collapse) — kept at its exact comp value but
   flipped to mobile-first (min-width) here, matching the sitewide
   convention (04-work.css/05-pricing.css/09-services.css). A separate
   768px tier (same sitewide convention) bumps `.contact`/`.form-card`
   padding up to the comp's literal desktop figures; mobile-first base
   values below are a deliberate reduction, same adaptation those other
   files document for their own hero/card padding. */

/* ---------- 01 Contact hero + pitch column (M·01) ---------- */
.contact {
  position: relative;
  padding: 64px 0 48px;
  overflow: hidden;
}
.contact-grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: 54px;
  align-items: start;
}
.pitch h1 {
  font-family: var(--display);
  font-weight: 800;
  text-transform: uppercase;
  font-size: clamp(46px, 5.4vw, 76px);
  line-height: .98;
  margin: 16px 0 22px;
}
.pitch .lede { max-width: 480px; }
.pitch .sub { color: var(--bone-dim); font-size: 15px; max-width: 460px; margin-top: 18px; }
.pitch .fineprint { margin-top: 22px; font: 11.5px/1.6 var(--mono); color: var(--bone-dim); letter-spacing: .1em; }

.c-plate {
  margin-top: 44px;
  border: 1px solid var(--hairline);
  border-radius: 4px;
  background: rgba(239, 234, 226, .03);
  max-width: 420px;
}
.c-row {
  display: flex;
  justify-content: space-between;
  align-items: baseline;
  gap: 16px;
  padding: 17px 20px;
  border-bottom: 1px solid var(--hairline);
}
.c-row:last-child { border-bottom: none; }
.c-k { font: 10.5px/1 var(--mono); letter-spacing: .2em; text-transform: uppercase; color: var(--bone-dim); }
.c-v { font: 13.5px/1 var(--mono); letter-spacing: .03em; color: var(--brass-bright); }

/* ---------- 02 Form card (M·02) ---------- */
.form-wrap { position: relative; display: flex; flex-direction: column; gap: 14px; }
.form-card {
  position: relative;
  background: var(--well) url('/img/texture-widmanstatten.webp') center/cover;
  border: 1px solid var(--hairline);
  border-radius: 6px;
  padding: 28px 22px 26px;
  overflow: hidden;
}
.form-card::before { content: ''; position: absolute; inset: 0; background: rgba(11, 10, 8, .9); }
.form-card > * { position: relative; z-index: 1; }

.field { display: grid; gap: 9px; margin-bottom: 22px; }
.f-label { font: 11px/1 var(--mono); letter-spacing: .16em; text-transform: uppercase; color: var(--bone-dim); }
.field input, .field textarea {
  background: var(--well);
  border: 1px solid var(--hairline);
  border-radius: 3px;
  padding: 14px 16px;
  color: var(--bone);
  font-family: var(--body);
  font-size: 14.5px;
  width: 100%;
}
.field textarea { resize: none; line-height: 1.5; }
.field input::placeholder, .field textarea::placeholder { color: rgba(169, 159, 146, .55); }

/* Focus ring is a brass glow, never the default outline — but focus
   visibility itself is non-negotiable, so :focus-visible still gets a
   clearly visible replacement (border + glow), not a silent removal. */
.field input:focus-visible, .field textarea:focus-visible {
  outline: none;
  border-color: var(--brass);
  box-shadow: 0 0 0 3px rgba(176, 141, 87, .18);
}

/* Honeypot: visually removed, still in the accessibility-neutral DOM for
   bots (name="website" — kept distinct from the real name="site" field). */
.field-hp {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  overflow: hidden;
}

.ts-note {
  display: flex;
  align-items: center;
  gap: 10px;
  font: 11.5px/1.5 var(--mono);
  color: var(--bone-dim);
  letter-spacing: .04em;
  border: 1px solid var(--hairline);
  border-radius: 3px;
  padding: 12px 14px;
  margin: 4px 0 22px;
}
.ts-note .dot { width: 6px; height: 6px; border-radius: 50%; background: var(--brass); flex: none; }

.form-card .cf-turnstile { min-height: 65px; margin-bottom: 22px; }
.form-card .btn { width: 100%; text-align: center; padding: 14px 22px; font-size: 15px; }

/* ---------- Desktop ≥768px (sitewide padding tier) ---------- */
@media (min-width: 768px) {
  .contact { padding: min(15vh, 132px) 0 118px; }
  .form-card { padding: 38px 36px 34px; }
}

/* Comp's own breakpoint (860px), flipped to min-width. */
@media (min-width: 860px) {
  .contact-grid { grid-template-columns: .95fr 1.05fr; gap: 72px; }
}

/* ---------- Thanks ---------- */
/* .thanks-hero stacks on top of 07-misc.css's shared .util-hero base
   (kicker/h1/lede typography + top padding clearing the fixed nav) — this
   page-only modifier adds the taller, centered "success" treatment the
   pre-rebrand .thanks-head min-height gave it. No v3 comp exists for this
   route; copy is unchanged from the pre-rebrand page per the brief. */
.thanks-hero {
  min-height: min(58vh, 520px);
  display: flex;
  align-items: center;
  text-align: center;
}
.thanks-hero .lede { margin-left: auto; margin-right: auto; }
.thanks-hero .submission-ref { margin-top: 18px; }
.thanks-hero .btn-ghost { margin-top: 26px; }

.submission-ref {
  font-family: var(--mono);
  font-size: 12.5px;
  letter-spacing: .04em;
  color: var(--bone-dim);
}
.submission-ref strong { color: var(--bone); }

/* 07-misc.css */
/* Privacy prose, the shared small-page intro (.util-hero, also used by
   thanks.html — see 06-forms.css's .thanks-hero modifier), and 404. Shared
   chrome (.shell, .kicker, .lede, .plate, .btn/.btn-ghost, nav, footer)
   lives in 01-base.css / 02-nav.css / 03-home.css. `.accent` (404's "Lost
   the thread." span) is NOT redeclared here — reused bare, byte-identical,
   from 09-services.css (`.accent { color: var(--brass); }`), the same
   sitewide-shared-primitive pattern `.amt`/`.per`/`.kicker`/`.lede`/`.plate`
   already follow elsewhere.

   404 is ported from the comp's appended 404 section
   (docs/research/2026-08-16-rebrand-v3/comps/contact.html — see that page's
   own header comment). Privacy and Thanks have no v3 comp; `.util-hero` is
   this port's own small shared intro pattern (kicker/h1/lede, bottom
   hairline, top padding clearing the fixed nav), built from the same
   typographic/spacing vocabulary the four comp-backed pages already
   established (Big Shoulders 800 uppercase display headings, `.kicker`
   eyebrows, `.hairline` rules) rather than inventing a new idiom.

   `.page-dark` (the pre-rebrand body class this file used to carry, flipping
   nav text color for pages that opened directly on a dark hero) is dropped
   outright, not restyled: the whole site is dark-only now (DESIGN.md S3),
   so 02-nav.css's default nav-text colors already read correctly against
   every page's background with zero exceptions — verified no other v3 page
   (including home.html, whose hero is just as dark) uses it either. */

/* ---------- Shared small-page intro (privacy, thanks) ---------- */
.util-hero {
  position: relative;
  padding: calc(var(--nav-h) + 40px) 0 40px;
  border-bottom: 1px solid var(--hairline);
}
.util-hero h1 {
  font-family: var(--display);
  font-weight: 800;
  text-transform: uppercase;
  font-size: clamp(38px, 6vw, 60px);
  line-height: 1;
  margin: 14px 0 0;
}
.util-hero .lede { margin-top: 14px; }

@media (min-width: 768px) {
  .util-hero { padding: calc(var(--nav-h) + 64px) 0 56px; }
}

/* Inline prose link (Privacy's "Email ..." / Thanks' "call or text ...") —
   brass-bright with a bone hover, the same small-link formula
   02-nav.css's .footer-socials already uses sitewide. */
.inline-link {
  color: var(--brass-bright);
  text-decoration: underline;
  text-underline-offset: 3px;
  transition: color var(--dur-nav) var(--ease-nav);
}
.inline-link:hover, .inline-link:focus-visible { color: var(--bone); }

/* ---------- Privacy prose ---------- */
.prose-wrap { padding: 56px 0 96px; }
.prose { max-width: 640px; }
.prose h2 {
  font-family: var(--display);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: .01em;
  font-size: clamp(21px, 2.4vw, 27px);
  margin-top: 40px;
}
.prose h2:first-child { margin-top: 0; }
.prose p {
  margin-top: 12px;
  color: var(--bone-dim);
  font-size: 15.5px;
  line-height: 1.7;
}
/* Prose bold runs (the /services/<slug> pages' package leads) — same
   brightened-bone emphasis as .own-line b (03-home.css). */
.prose b { color: var(--bone); font-weight: 600; }
/* Prose lists (the /services/<slug> pages' "what's included" runs) — same
   brass-dash bullet the price plates use (03-home.css .plate-card li). */
.prose ul { margin-top: 14px; display: grid; gap: 10px; }
.prose li {
  font-size: 15px;
  color: var(--bone-dim);
  padding-left: 20px;
  position: relative;
  line-height: 1.55;
}
.prose li::before { content: ''; position: absolute; left: 0; top: 10px; width: 9px; height: 2px; background: var(--brass); }

/* ---------- 404 (M·01) ---------- */
.err404 {
  position: relative;
  min-height: min(84vh, 760px);
  background: var(--well);
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  overflow: hidden;
}
.err-mark {
  position: absolute;
  inset: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  opacity: .06;
  pointer-events: none;
}
.err-mark img { width: min(62vw, 760px); }
.err-in { position: relative; z-index: 2; padding: 90px 24px; }
.err-in .plate { margin-bottom: 10px; }
.err-in h2 {
  font-family: var(--display);
  font-weight: 800;
  text-transform: uppercase;
  font-size: clamp(52px, 6.6vw, 100px);
  line-height: .98;
  margin: 22px 0 20px;
}
.err-in p {
  color: var(--bone-dim);
  max-width: 440px;
  margin: 0 auto 34px;
  font-size: 16px;
}

/* 08-motion.css */
/* Shared machined-motion CSS contract, paired with src/js/fx-core.js.
   HARD RULE (fx-gate, structural + test-enforced): nothing ships hidden
   (opacity: 0) unless the selector is scoped to html.js or html.fx — a
   no-JS visitor, and any visitor before fx-core's double-rAF heartbeat
   proves the window paints, must see the complete static page. Page-specific
   `html.fx .selector { opacity: 0 }` hidden states land in the per-page CSS
   files (Tasks 5-10); every one of them must be added to the reduced-motion
   reveal block below (or an equivalent block in its own file) so reduced-
   motion visitors are never left with hidden content. */

/* ---------- Shared pre-reveal class ---------- */
/* .fx-hide is the one hidden-state class fx-core.js itself understands
   generically (scenes may still gate their own bespoke selectors instead). */
html.fx .fx-hide { opacity: 0; }

/* ---------- Brass light-sweep (FX.sweep helper) ---------- */
/* Runs once (no infinite/alternate), 600ms, machined easing. FX.sweep(el)
   toggles .is-sweep and removes it on 'animationend' (which bubbles up from
   the ::after pseudo-element that carries the actual animation, so el's own
   layout/transform animations are never touched). */
@keyframes fx-sweep {
  from { transform: translateX(-120%) skewX(-18deg); }
  to   { transform: translateX(220%) skewX(-18deg); }
}

.is-sweep { position: relative; overflow: hidden; }
.is-sweep::after {
  content: '';
  position: absolute;
  inset: 0;
  width: 40%;
  background: linear-gradient(100deg, transparent, rgba(217, 188, 130, .45), transparent);
  animation: fx-sweep .6s cubic-bezier(.4, 0, .2, 1);
  pointer-events: none;
}

/* ---------- Precision cursor (fine pointers only) ----------------------
   body.fx-cursor + .f-cursor are created by fx-core.js's cursor scene, in
   the same pass, so `cursor: none` never applies without a replacement
   visible. Reduced motion never reaches that scene (scenes don't run under
   REDUCED), so the native cursor stands there by construction. Ported from
   redesign/chrome's home-only version; generalized off body.home-cinema
   since fx-core is a shared, every-page engine here — see task-4-report.md
   self-review. */
@media (pointer: fine) {
  body.fx-cursor { cursor: none; }
  /* Text-entry fields keep their native caret. The replacement dot never
     becomes an I-beam, so hiding the system cursor inside an input removed
     the only affordance showing where text would land — on the contact form,
     which is the page's conversion point. Interactive-but-not-typed elements
     still hide it; the dot's ring state covers those. */
  body.fx-cursor :is(a, button, select, summary, [role="slider"]) { cursor: none; }
  body.fx-cursor :is(input, textarea) { cursor: auto; }

  .f-cursor {
    position: fixed;
    top: 0;
    left: 0;
    z-index: 999;
    pointer-events: none;
    width: 8px;
    height: 8px;
    border-radius: 50%;
    background: var(--brass-bright);
    translate: -50% -50%;
    transition:
      width .2s cubic-bezier(.4, 0, .2, 1),
      height .2s cubic-bezier(.4, 0, .2, 1),
      background .2s cubic-bezier(.4, 0, .2, 1),
      border-color .2s cubic-bezier(.4, 0, .2, 1);
  }

  html.fx .f-cursor::after {
    content: attr(data-label);
    position: absolute;
    inset: 0;
    display: grid;
    place-items: center;
    font: 500 .5625rem var(--mono);
    letter-spacing: .1em;
    color: var(--well);
    opacity: 0;
    transition: opacity .2s cubic-bezier(.4, 0, .2, 1);
  }

  .f-cursor.is-on { width: 56px; height: 56px; background: var(--bone); }
  .f-cursor.is-on::after { opacity: 1; }
  .f-cursor.is-link { width: 28px; height: 28px; background: transparent; border: 1px solid var(--brass-bright); }
}

/* ---------- Below-fold render skip: REMOVED 2026-08-24 ------------------
   This used to apply the CSS render-skipping property (with a 600px
   intrinsic-size placeholder) to every <main> section past the first, and
   carried a comment predicting that pinned sections might need an override
   "if size containment fights ScrollTrigger's pin spacer". That exclusion was
   never written, and the prediction was too narrow anyway.

   Size containment does not only affect the pinned section — it makes EVERY
   off-screen section report the 600px placeholder instead of its real
   height. Measured on the shipped homepage: the document measured 10404px
   against a real 12149px, `.numbers` reported 601px against a real 212px,
   `.faq` 785 against 1376. ScrollTrigger caches every pin's start against
   that fake document at init, so `.steps` pinned 1251px early and
   `.plaque-cta` 2051px early — the process section going position:fixed
   while the founder block was still on screen, painting over it.

   Excluding only the pinned sections cannot fix this: the sections ABOVE a
   pin are what displace its start. The rule and pinning are mutually
   exclusive on the same page, and every page here pins. Correct scroll
   geometry beats a marginal render saving on a nine-section static page, so
   the rule is gone rather than patched. build.test.mjs guards its absence.
   ------------------------------------------------------------------------ */

/* Reduced data: zero video bytes ever move. fx-core.js's attachVideos()
   already never sets a source under navigator.connection.saveData; this
   covers the CSS side for browsers that surface the OS/browser-level
   preference without exposing the Save-Data JS API. The poster <img> is
   always the markup fallback next to every data-video-src video (wired per
   page starting Task 5). */
@media (prefers-reduced-data: reduce) {
  /* Do NOT display:none the video — every film here carries its still on its
     own `poster=` ATTRIBUTE, and hiding the element hides the poster with it.
     The previous rule handed off to `img[data-poster]` siblings, a selector
     that matches zero elements anywhere in this repo, so a Data Saver visitor
     got an empty bordered box where the hero film should be while still
     downloading the preloaded poster they never saw.

     fx-core.js's attachVideos() already refuses to set a source under
     saveData, so the element never fetches video bytes. Left visible, it
     paints its poster attribute — which is exactly the "static poster frames"
     DESIGN.md S6 promises. */
  video[data-video-src] { display: block; }
}

/* Reduced motion: force every fx-hidden state back to fully visible, static,
   and unanimated — belt-and-suspenders alongside fx-core.js never running
   its scenes under REDUCED (root never even gets .fx class transitions
   beyond the base .fx-hide rule above, which this overrides outright). */
@media (prefers-reduced-motion: reduce) {
  html.fx .fx-hide {
    opacity: 1 !important;
    transform: none !important;
    animation: none !important;
  }
  .f-cursor { display: none; }
  /* M·07's light-engrave mask (03-home.css) is decorative-only, never
     real content, so it gets the opposite treatment from .fx-hide above:
     forced OFF instead of forced visible. html.fx is never added under
     reduced motion anyway (fx-core.js's REDUCED early-return), so this is
     belt-and-suspenders, matching the .fx-hide rule's own posture. */
  html.fx .plaque-in h2::after { opacity: 0 !important; }
}

/* 09-services.css */
/* Services page — capabilities index rail (M·01) + eight full chapters
   (M·02-M·09) + CTA (M·10). Ported from
   docs/research/2026-08-16-rebrand-v3/comps/services.html. Shared chrome
   (.shell, .kicker, .lede, .btn/.btn-ghost, nav, footer) lives in
   01-base.css / 02-nav.css / 03-home.css — this file is services-page-only.

   The comp is desktop-first and carries exactly one breakpoint (860px,
   `.chapter-grid`/`.toc-row` collapse for narrow viewports) — kept at its
   exact comp value but flipped to mobile-first (min-width) here, matching
   the sitewide convention (04-work.css/05-pricing.css). Base rules below
   are the single-column mobile layout; the @media block adds the two-column
   desktop grid. Mobile-only `.chapter-grid`/`.cta-in` gap/padding values are
   a deliberate reduction from the comp's desktop-only figures (same
   adaptation 04-work.css's `.scene-in.shell` documents for its own gap) —
   the @media block converges on the comp's literal desktop numbers.

   Font-weight 750/650 mapped per the CSS weight-matching algorithm
   (task-5-report.md: target > 500 → nearest available at or above):
   750→800 (.svc-hero h1, .cta h2), 650→700 (.toc-row .name). `.chapter h2`'s
   700 is an exact match, no mapping needed.

   `.toc-row .price`/`.price-line` render UPPERCASE via CSS even though their
   {{PRICE_BUILD}}/{{PRICE_CARE}} tokens resolve lowercase ("from $1,499") —
   same deliberate deviation 03-home.css documents for `.svc-row .price`:
   restores the comp's visual caps ("FROM $1,499") without a second
   hardcoded price literal that could desync from site.config.json. */

/* ---------- Intro + index rail (M·01) ---------- */
.svc-hero { position: relative; padding: 88px 0 56px; border-bottom: 1px solid var(--hairline); }
.accent { color: var(--brass); }
.svc-hero h1 {
  font-family: var(--display);
  font-weight: 800;
  text-transform: uppercase;
  font-size: clamp(44px, 12vw, 88px);
  line-height: .98;
  letter-spacing: .01em;
  margin: 16px 0 18px;
}

.toc { border-top: 1px solid var(--hairline); margin-top: 36px; }
.toc-row {
  display: grid;
  grid-template-columns: 40px 1fr;
  row-gap: 4px;
  gap: 4px 16px;
  align-items: baseline;
  padding: 16px 4px;
  border-bottom: 1px solid var(--hairline);
}
.toc-row .idx { font: 14px/1 var(--mono); color: var(--brass); }
.toc-row .name {
  font-family: var(--display);
  font-weight: 700;
  font-size: 17px;
  text-transform: uppercase;
  letter-spacing: .02em;
  text-decoration-line: underline;
  text-decoration-color: transparent;
  text-underline-offset: 6px;
  transition: color .3s cubic-bezier(.4, 0, .2, 1), text-decoration-color .3s cubic-bezier(.4, 0, .2, 1);
}
.toc-row .desc { grid-column: 2; color: var(--bone-dim); font-size: 13.5px; }
.toc-row .price {
  grid-column: 2;
  font: 11.5px/1 var(--mono);
  color: var(--brass-bright);
  text-transform: uppercase;
  white-space: nowrap;
}
.toc-row .go { grid-column: 2; font: 13px/1 var(--mono); color: var(--bone-dim); transition: color .3s cubic-bezier(.4, 0, .2, 1); }
.toc-row:hover .name, .toc-row:focus-visible .name { color: var(--brass-bright); text-decoration-color: var(--brass); }
.toc-row:hover .go, .toc-row:focus-visible .go { color: var(--brass-bright); }

@media (min-width: 768px) {
  .svc-hero { padding: 128px 0 64px; }
}

/* Comp breakpoint (860px), flipped to min-width. */
@media (min-width: 860px) {
  .toc-row {
    grid-template-columns: 60px 220px 1fr auto auto;
    gap: 22px;
    row-gap: 22px;
    padding: 18px 4px;
  }
  .toc-row .name { font-size: 18.5px; }
  .toc-row .desc, .toc-row .price, .toc-row .go { grid-column: auto; }
  .toc-row .desc { font-size: 14px; }
}

/* ---------- Chapters (M·02-M·09) ---------- */
.chapter { position: relative; padding: 64px 0; border-bottom: 1px solid var(--hairline); overflow: hidden; }
.chapter.alt { background: var(--well); }
.chapter-num {
  position: absolute;
  top: -.12em;
  left: clamp(20px, 4vw, 64px);
  font-family: var(--display);
  font-weight: 800;
  font-size: clamp(100px, 34vw, 240px);
  line-height: 1;
  color: transparent;
  -webkit-text-stroke: 1px rgba(239, 234, 226, .08);
  z-index: 0;
  user-select: none;
  pointer-events: none;
}
.chapter.rev .chapter-num { left: auto; right: clamp(20px, 4vw, 64px); }

.chapter-grid { position: relative; z-index: 1; display: grid; grid-template-columns: 1fr; gap: 32px; }
.chapter-grid .copy { order: 1; }
.chapter-grid .visual { order: 2; }
.chapter.rev .chapter-grid .copy, .chapter.rev .chapter-grid .visual { order: initial; }

.chapter .idx-line { font: 13px/1 var(--mono); color: var(--brass); letter-spacing: .18em; }
.chapter h2 {
  font-family: var(--display);
  font-weight: 700;
  text-transform: uppercase;
  font-size: clamp(34px, 9vw, 62px);
  line-height: 1;
  letter-spacing: .01em;
  margin: 12px 0 16px;
}
.chapter p { color: var(--bone-dim); font-size: 15.5px; max-width: 480px; }
.chapter p + p { margin-top: 12px; }
.price-line {
  display: inline-block;
  margin-top: 22px;
  font: 12px/1 var(--mono);
  letter-spacing: .16em;
  color: var(--brass-bright);
  text-transform: uppercase;
  border: 1px solid rgba(176, 141, 87, .35);
  padding: 8px 14px;
  border-radius: 2px;
  background: rgba(11, 10, 8, .4);
}
/* Per-chapter jump to the discipline's own indexable page (/services/<slug>)
   — quiet mono link under the price plate, brass-brightening on hover like
   the .qf tag treatment. */
.chapter-link {
  display: block;
  margin-top: 16px;
  font: 12px/1 var(--mono);
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--brass);
  text-decoration: none;
  transition: color .3s cubic-bezier(.4, 0, .2, 1);
}
.chapter-link:hover, .chapter-link:focus-visible { color: var(--brass-bright); }

.frame { border: 1px solid var(--hairline); border-radius: 6px; overflow: hidden; background: var(--well); }
.frame img { width: 100%; height: 100%; object-fit: cover; }
.frame.r-16-10 { aspect-ratio: 16 / 10; }
.frame.r-4-3 { aspect-ratio: 4 / 3; }
.frame.r-1-1 { aspect-ratio: 1 / 1; }
.frame.r-3-2 { aspect-ratio: 3 / 2; }
.frame.r-16-9 { aspect-ratio: 16 / 9; }
.frame.r-9-16 { aspect-ratio: 9 / 16; max-width: 280px; margin: 0 auto; }
/* M·04's "heavy drop-shadow bloom" (src/js/services-fx.js toggles this once
   the frame settles) — same bloom mechanic as home's .plate-card.is-bloom
   (03-home.css), reused here on a .frame instead of a .plate-card. */
.frame.is-bloom { box-shadow: 0 0 34px -6px rgba(176, 141, 87, .45); }


.visual-duo { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }

@media (min-width: 768px) {
  .chapter { padding: 104px 0; }
  .chapter p { font-size: 16px; }
  .visual-duo { gap: 16px; }
}

/* Comp breakpoint (860px), flipped to min-width. */
@media (min-width: 860px) {
  .chapter-grid { grid-template-columns: 1fr 1fr; gap: 64px; align-items: center; }
  .chapter.rev .chapter-grid .copy { order: 2; }
  .chapter.rev .chapter-grid .visual { order: 1; }
}

/* ---------- CTA (M·10) ----------
   Comp's own `.cta`/`.cta-in` block — deliberately NOT aliased to Home's
   `.plaque-cta`/`.plaque-in` (contrast work.html's M·06, whose comp defined
   no CSS at all for the section and so fully inherited Home's classnames).
   This comp authors its own distinct sizing (shorter band: 58vh/520px vs
   Home's 78svh/700px; its own h2 clamp), so it keeps its own classnames and
   this small CSS block, while sharing Home's FX.plaqueScene JS mechanic
   (fx-core.js, called with `engrave: false` + a custom `headingSelector`)
   for the pin/hold behavior — see services-fx.js's M·10 scene. */
.cta {
  position: relative;
  /* Opaque floor — this section is pinned by FX.plaqueScene and must not
     composite over the page behind it (see 03-home.css's .steps note). */
  background: var(--well);
  min-height: min(58vh, 520px);
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  overflow: hidden;
}
.cta .bg { position: absolute; inset: 0; }
.cta .bg img { width: 100%; height: 100%; object-fit: cover; }
.cta .bg::after {
  content: '';
  position: absolute;
  inset: 0;
  background: radial-gradient(ellipse at center, rgba(11, 10, 8, .18), rgba(11, 10, 8, .82) 78%);
}
.cta-in { position: relative; z-index: 2; padding: 72px 24px; }
.cta h2 {
  font-family: var(--display);
  font-weight: 800;
  text-transform: uppercase;
  font-size: clamp(34px, 9vw, 64px);
  line-height: .98;
  letter-spacing: .01em;
}
.cta p { color: var(--bone); opacity: .85; max-width: 480px; margin: 18px auto 26px; font-size: 15.5px; }
.cta .fineprint { margin-top: 16px; font: 11px/1.6 var(--mono); color: var(--bone-dim); letter-spacing: .08em; }

@media (min-width: 768px) {
  .cta-in { padding: 96px 24px; }
  .cta p { font-size: 16px; margin: 20px auto 30px; }
  .cta .fineprint { font-size: 11.5px; letter-spacing: .1em; margin-top: 18px; }
}

/* 10-orbit.css */
/* ---------- Orbit — "Everything turns on your website" ----------
   Home M·09. The docmo-inspired node diagram, rebuilt in Machined Star
   vocabulary: six engraved bolt-heads seated on a guilloche bearing race
   around a brass hub. Clicking a node seats it (brass ring lights) and
   opens its reason in the hub.

   Degradation contract (DESIGN.md S6 / fx-gate): the RING LAYOUT is pure
   CSS and needs no JS — but every reason panel is readable in the static
   DOM by default, stacked under the race. JS only ever *collapses* that
   stack into the hub, which is safe because JS running is proof JS is
   alive. Nothing here ships at opacity:0. A no-JS, pre-heartbeat, or
   post-degrade visitor gets the race plus all six reasons in plain text. */

.orbit {
  position: relative;
  padding: 88px 0 96px;
  border-top: 1px solid var(--hairline);
  background:
    radial-gradient(120% 80% at 50% 0%, rgba(176, 141, 87, .07), transparent 60%),
    var(--surface);
}
.orbit .shell { text-align: center; }
.orbit h2 {
  font-family: var(--display);
  font-weight: 700;
  text-transform: uppercase;
  font-size: clamp(34px, 8vw, 68px);
  line-height: 1;
  letter-spacing: .01em;
  margin: 14px 0 12px;
}
.orbit h2 .hot { color: var(--brass); }
.orbit .lede { margin: 0 auto; }

/* ---- the race ---- */
.orbit-race {
  position: relative;
  /* Each .orbit-node is a full-size absolutely-positioned box rotated up to
     60deg. A square rotated 60deg has a bounding box ~1.366x wider, and a
     transformed box contributes to SCROLLABLE overflow even where it paints
     nothing — measured at a 486px viewport: scrollWidth 579 vs clientWidth
     486, i.e. 93px of sideways pan on every phone. Clipping here contains the
     arms without affecting the heads, which sit well inside the circle. */
  overflow: hidden;
  width: min(88vw, 560px);
  aspect-ratio: 1;
  margin: 48px auto 0;
  display: grid;
  place-items: center;
}
/* Two concentric engraved rings — the bearing race. Pure decoration. */
.orbit-race::before,
.orbit-race::after {
  content: '';
  position: absolute;
  border-radius: 50%;
  border: 1px solid var(--hairline);
}
.orbit-race::before { inset: 0; }
.orbit-race::after {
  inset: 13%;
  border-color: rgba(176, 141, 87, .22);
  box-shadow: inset 0 0 60px rgba(176, 141, 87, .06);
}

/* ---- hub ---- */
.orbit-hub {
  position: relative;
  z-index: 3;
  width: 54%;
  aspect-ratio: 1;
  border-radius: 50%;
  display: grid;
  place-items: center;
  text-align: center;
  padding: 8%;
  background:
    radial-gradient(circle at 38% 30%, rgba(217, 188, 130, .16), transparent 62%),
    var(--well);
  border: 1px solid rgba(176, 141, 87, .3);
  box-shadow: 0 0 0 1px rgba(11, 10, 8, .8), 0 24px 60px rgba(0, 0, 0, .5);
}
.orbit-hub-mark { width: 44%; max-width: 96px; opacity: .9; }
.orbit-hub-label {
  font: 11px/1.5 var(--mono);
  letter-spacing: .2em;
  text-transform: uppercase;
  color: var(--bone-dim);
  margin-top: 12px;
}

/* Hub readout — only ever populated by JS (empty + display:none until
   then), so it cannot strand a blank circle on a no-JS visitor. */
.orbit-readout { display: none; }
.orbit-race.is-live .orbit-readout { display: block; }
.orbit-race.is-live .orbit-hub-mark,
.orbit-race.is-live .orbit-hub-label { display: none; }
.orbit-readout h3 {
  font-family: var(--display);
  font-weight: 700;
  font-size: clamp(20px, 4.4vw, 30px);
  text-transform: uppercase;
  letter-spacing: .02em;
  color: var(--brass-bright);
}
.orbit-readout p {
  color: var(--bone-dim);
  font-size: clamp(13px, 2.6vw, 15px);
  line-height: 1.55;
  margin-top: 10px;
}

/* ---- nodes ---- */
/* Seated on the race by rotating a full-height arm then counter-rotating
   the head so type stays upright. --i is the node index (0-5). */
.orbit-node {
  position: absolute;
  inset: 0;
  z-index: 2;
  display: grid;
  justify-items: center;
  align-items: start;
  transform: rotate(calc(var(--i) * 60deg));
  pointer-events: none;             /* only the head is clickable */
}
.orbit-node-head {
  pointer-events: auto;
  transform: rotate(calc(var(--i) * -60deg)) translateY(-4%);
  width: clamp(66px, 15vw, 92px);
  aspect-ratio: 1;
  border-radius: 50%;
  display: grid;
  place-items: center;
  gap: 3px;
  background:
    radial-gradient(circle at 40% 32%, rgba(239, 234, 226, .1), transparent 60%),
    var(--well);
  border: 1px solid rgba(176, 141, 87, .32);
  color: var(--bone-dim);
  transition:
    border-color var(--dur-nav) var(--ease-nav),
    color var(--dur-nav) var(--ease-nav),
    box-shadow var(--dur-nav) var(--ease-nav);
}
.orbit-node-head svg { width: 22px; height: 22px; stroke: var(--brass); fill: none; stroke-width: 1.5; }
.orbit-node-head span {
  font: 10px/1 var(--mono);
  letter-spacing: .12em;
  text-transform: uppercase;
}
.orbit-node-head:hover,
.orbit-node-head:focus-visible {
  border-color: var(--brass);
  color: var(--bone);
  box-shadow: 0 0 24px rgba(176, 141, 87, .28);
}
.orbit-node-head[aria-expanded='true'] {
  border-color: var(--brass-bright);
  color: var(--bone);
  box-shadow: 0 0 30px rgba(176, 141, 87, .42), inset 0 0 20px rgba(176, 141, 87, .12);
}

/* ---- static reason stack (the no-JS / degraded state) ---- */
.orbit-reasons {
  display: grid;
  gap: 2px;
  margin: 40px auto 0;
  max-width: 720px;
  text-align: left;
  border-top: 1px solid var(--hairline);
}
/* Scoped to html.fx so the static stack RETURNS when the engine degrades.
   Unscoped, this hid five of the six reasons permanently: degrade() drops
   .fx but never removes the .is-live class showcase-fx.js added, leaving
   only the one reason seated in a readout the engine just declared unsafe to
   animate. Compare 11-reel.css's .reel-stage, which is fx-scoped and
   self-heals. Note the fx-gate test scans opacity/visibility only, so a
   display:none regression here is invisible to it — hence this comment. */
html.fx .orbit-race.is-live ~ .orbit-reasons { display: none; }
.orbit-reasons li { padding: 16px 4px; border-bottom: 1px solid var(--hairline); }
.orbit-reasons h3 {
  font-family: var(--display);
  font-weight: 700;
  font-size: 19px;
  text-transform: uppercase;
  letter-spacing: .02em;
  color: var(--brass-bright);
}
.orbit-reasons p { color: var(--bone-dim); font-size: 14.5px; margin-top: 4px; }

.orbit-foot {
  margin: 40px auto 0;
  font: 11px/1.6 var(--mono);
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--bone-dim);
}

/* Small screens: the race gets tight — shrink heads and drop the hub mark
   so six 66px heads never collide on a 320px viewport. */
@media (max-width: 560px) {
  .orbit-race { width: 92vw; }
  .orbit-hub { width: 58%; }
  .orbit-hub-label { display: none; }
}

/* 11-reel.css */
/* ---------- Reel — the industry showcase ----------
   Home M·10 + /showcase. Astrion's answer to a portfolio problem every
   young shop has: more industries than shipped clients. Each entry is a
   complete, hand-built demo site for an industry we want, living at
   /demos/<slug>/ — a real page, not a mockup image.

   Degradation contract: every card is a plain <a> straight to the demo, so
   the section is fully functional with zero JS. The in-page preview bezel
   is pure enhancement — JS reveals it and lazily points an iframe at the
   already-linked URL. Nothing ships hidden. */

.reel {
  position: relative;
  padding: 88px 0 96px;
  border-top: 1px solid var(--hairline);
  background: var(--well);
}
.reel h2 {
  font-family: var(--display);
  font-weight: 700;
  text-transform: uppercase;
  font-size: clamp(34px, 8vw, 68px);
  line-height: 1;
  letter-spacing: .01em;
  margin: 14px 0 12px;
}
.reel h2 .hot { color: var(--brass); }
.reel-head { display: grid; gap: 8px; }

/* Honest labelling is a hard guard: these are demonstrations, not clients.
   DESIGN.md S7 verified-claims — never let a demo read as a case study. */
.reel-disclaimer {
  margin-top: 18px;
  font: 11px/1.6 var(--mono);
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--brass-bright);
  border-left: 2px solid var(--brass-deep);
  padding-left: 12px;
}

/* ---- card grid ---- */
.reel-grid {
  margin-top: 44px;
  display: grid;
  grid-template-columns: 1fr;
  gap: 18px;
}
@media (min-width: 640px) { .reel-grid { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1080px) { .reel-grid { grid-template-columns: repeat(4, 1fr); } }

.reel-card {
  position: relative;
  display: grid;
  grid-template-rows: auto 1fr;
  background: var(--surface);
  border: 1px solid var(--hairline);
  border-radius: 3px;
  overflow: hidden;
  transition:
    border-color var(--dur-nav) var(--ease-nav),
    transform var(--dur-nav) var(--ease-nav);
}
.reel-card:hover, .reel-card:focus-visible {
  border-color: var(--brass);
  transform: translateY(-3px);
}
.reel-shot {
  position: relative;
  aspect-ratio: 4 / 3;
  overflow: hidden;
  background: var(--well);
}
.reel-shot img { width: 100%; height: 100%; object-fit: cover; object-position: top center; }
.reel-shot::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(0deg, rgba(11, 10, 8, .55), transparent 55%);
}
.reel-meta { padding: 16px 16px 18px; display: grid; gap: 5px; align-content: start; }
.reel-meta h3 {
  font-family: var(--display);
  font-weight: 700;
  font-size: 21px;
  text-transform: uppercase;
  letter-spacing: .02em;
}
.reel-tag {
  font: 10.5px/1.4 var(--mono);
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--bone-dim);
}
.reel-live {
  margin-top: 6px;
  font: 11px/1 var(--mono);
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--brass-bright);
}

/* Corner stamp marking every card as a demonstration build. */
.reel-stamp {
  position: absolute;
  top: 10px;
  right: 10px;
  z-index: 2;
  font: 9.5px/1 var(--mono);
  letter-spacing: .16em;
  color: var(--brass-bright);
  background: rgba(11, 10, 8, .78);
  border: 1px solid rgba(176, 141, 87, .4);
  border-radius: 2px;
  padding: 6px 8px;
}

/* ---- preview bezel (JS enhancement only) ---- */
.reel-stage { display: none; }
html.fx .reel-stage.is-armed { display: block; margin-top: 40px; }
.reel-bezel {
  border: 1px solid var(--hairline);
  border-radius: 4px;
  overflow: hidden;
  background: var(--surface);
  box-shadow: 0 30px 80px rgba(0, 0, 0, .55);
}
.reel-bar {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 10px 14px;
  border-bottom: 1px solid var(--hairline);
  background: var(--well);
}
.reel-dots { display: flex; gap: 6px; }
.reel-dots i { width: 8px; height: 8px; border-radius: 50%; background: var(--brass-deep); }
.reel-url {
  flex: 1;
  font: 11px/1 var(--mono);
  letter-spacing: .06em;
  color: var(--bone-dim);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.reel-close {
  font: 11px/1 var(--mono);
  letter-spacing: .14em;
  text-transform: uppercase;
  color: var(--brass-bright);
}
.reel-frame { width: 100%; height: min(72vh, 680px); border: 0; background: var(--well); display: block; }

.reel-foot { margin-top: 34px; display: flex; gap: 14px; flex-wrap: wrap; align-items: center; }

/* 12-faq.css */
/* ---------- FAQ ----------
   Home M·11. Built on native <details>/<summary>: open/close costs zero JS,
   works before the heartbeat, survives degrade, and is keyboard- and
   screen-reader-correct for free. JS only adds the accordion behaviour
   (opening one closes its siblings) and the brass sweep — both pure
   enhancement. The answers are always in the DOM, so the crawler that
   reads the page for the FAQPage JSON-LD sees exactly what a visitor
   does (build.mjs derives that JSON-LD from this markup — see faq()). */

.faq {
  padding: 88px 0 96px;
  border-top: 1px solid var(--hairline);
  background: var(--surface);
}
.faq h2 {
  font-family: var(--display);
  font-weight: 700;
  text-transform: uppercase;
  font-size: clamp(34px, 8vw, 68px);
  line-height: 1;
  letter-spacing: .01em;
  margin: 14px 0 12px;
}
.faq h2 .hot { color: var(--brass); }

.faq-list { margin-top: 40px; border-top: 1px solid var(--hairline); }
.faq-item { border-bottom: 1px solid var(--hairline); }

.faq-item summary {
  display: flex;
  align-items: flex-start;
  gap: 16px;
  padding: 22px 4px;
  cursor: pointer;
  list-style: none;
  font-family: var(--display);
  font-weight: 700;
  font-size: clamp(18px, 3.4vw, 24px);
  text-transform: uppercase;
  letter-spacing: .02em;
  transition: color var(--dur-nav) var(--ease-nav);
}
.faq-item summary::-webkit-details-marker { display: none; }
.faq-item summary:hover, .faq-item summary:focus-visible { color: var(--brass-bright); }

.faq-idx { font: 12px/1.9 var(--mono); color: var(--brass); flex: none; }
.faq-q { flex: 1; }

/* Machined +/- : two chrome bars, the vertical one retracts on open. */
.faq-sign { position: relative; flex: none; width: 16px; height: 16px; margin-top: 7px; }
.faq-sign::before,
.faq-sign::after {
  content: '';
  position: absolute;
  inset: 50% 0 auto;
  height: 1.5px;
  background: var(--brass);
  transition: transform var(--dur-nav) var(--ease-nav);
}
.faq-sign::after { transform: rotate(90deg); }
.faq-item[open] .faq-sign::after { transform: rotate(90deg) scaleX(0); }

.faq-a {
  padding: 0 4px 26px 44px;
  color: var(--bone-dim);
  font-size: clamp(14.5px, 2.6vw, 16px);
  line-height: 1.65;
  max-width: 760px;
}
.faq-a b { color: var(--bone); font-weight: 600; }
.faq-a a { color: var(--brass-bright); text-decoration: underline; text-underline-offset: 3px; }

.faq-foot {
  margin-top: 36px;
  display: flex;
  gap: 14px;
  flex-wrap: wrap;
  align-items: center;
}
.faq-foot span {
  font: 11px/1.6 var(--mono);
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--bone-dim);
}

/* 13-about.css */
/* ---------- About — the founder block ----------
   Home M·12. This section is a deliberate, Drew-authorised exception to
   DESIGN.md S7's "no personal photos, bios, or founder-forward presence"
   rule — see DESIGN.md S7's own amendment note, dated 2026-08-24. It is
   ALSO the only place on the site that speaks in first person; every other
   section stays in agency voice. Keep that boundary: the moment "I" leaks
   into the capabilities rail or the pricing plates, the site starts sounding
   like a freelancer's and the positioning goes with it.

   Structurally this is docmo's `ueber` block re-cut in Machined Star: a
   portrait held in an engraved plate, a two-sides credibility claim, and
   two oversized stat cards. Nothing here ships hidden. */

.about {
  position: relative;
  padding: 88px 0 96px;
  border-top: 1px solid var(--hairline);
  background:
    radial-gradient(90% 70% at 78% 12%, rgba(176, 141, 87, .08), transparent 62%),
    var(--well);
}
.about-grid { display: grid; gap: clamp(32px, 5vw, 68px); align-items: start; }
@media (min-width: 900px) { .about-grid { grid-template-columns: .82fr 1.18fr; } }

/* ---- portrait, seated in an engraved plate ---- */
.about-plate { position: relative; }
.about-portrait {
  position: relative;
  aspect-ratio: 4 / 5;
  overflow: hidden;
  border: 1px solid rgba(176, 141, 87, .3);
  border-radius: 2px;
  background: var(--surface);
}
.about-portrait img {
  width: 100%; height: 100%; object-fit: cover; object-position: center 22%;
  /* Barely-there grade. The studio backdrop is a cool grey and the page is
     warm charcoal, so untouched it reads as a bright rectangle pasted on.
     Kept deliberately light — enough to seat it in the world, not enough to
     change how the subject actually looks. */
  filter: contrast(1.04) saturate(.94) brightness(.97);
}
/* Vignette plus a floor gradient: the edges fall off into the page instead of
   ending on a hard bright border, and the stamp gets a dark bed to sit on. */
.about-portrait::after {
  content: '';
  position: absolute;
  inset: 0;
  background:
    radial-gradient(120% 85% at 50% 38%, transparent 40%, rgba(11, 10, 8, .5) 100%),
    linear-gradient(0deg, rgba(11, 10, 8, .78), transparent 46%);
}
/* Chamfered brass corner brackets — the serial-plate language. */
.about-plate::before,
.about-plate::after {
  content: '';
  position: absolute;
  width: 26px; height: 26px;
  border: 1px solid var(--brass);
  pointer-events: none;
}
.about-plate::before { top: -6px; left: -6px; border-right: 0; border-bottom: 0; }
.about-plate::after { bottom: -6px; right: -6px; border-left: 0; border-top: 0; }

.about-stamp {
  position: absolute;
  z-index: 2;
  bottom: 14px; left: 14px; right: 14px;
  display: flex; gap: 10px; align-items: baseline; flex-wrap: wrap;
  font: 11px/1.5 var(--mono);
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--brass-bright);
}
.about-stamp b { color: var(--bone); font-weight: 400; letter-spacing: .1em; }

/* ---- copy ---- */
.about h2 {
  font-family: var(--display);
  font-weight: 700;
  text-transform: uppercase;
  font-size: clamp(32px, 7vw, 62px);
  line-height: 1;
  letter-spacing: .01em;
  margin: 14px 0 18px;
}
.about h2 .hot { color: var(--brass); }
.about p { color: var(--bone-dim); font-size: clamp(15.5px, 1.5vw, 17.5px); margin-bottom: 16px; }
.about p b { color: var(--bone); font-weight: 600; }
.about p:last-of-type { margin-bottom: 0; }

.about-sign {
  margin-top: 26px;
  padding-top: 20px;
  border-top: 1px solid var(--hairline);
  display: flex; gap: 14px; align-items: baseline; flex-wrap: wrap;
  font: 11.5px/1.6 var(--mono);
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--bone-dim);
}
.about-sign b { color: var(--brass-bright); font-weight: 400; }

/* ---- stat cards ---- */
.about-stats {
  display: grid;
  gap: 1px;
  margin-top: 34px;
  background: var(--hairline);
  border: 1px solid var(--hairline);
}
@media (min-width: 560px) { .about-stats { grid-template-columns: repeat(2, 1fr); } }
.about-stat { background: var(--well); padding: clamp(22px, 3vw, 30px); }
.about-stat .v {
  font-family: var(--display);
  font-weight: 800;
  font-size: clamp(40px, 7vw, 66px);
  line-height: 1;
  color: var(--brass);
}
.about-stat .k {
  font: 11.5px/1.5 var(--mono);
  letter-spacing: .16em;
  text-transform: uppercase;
  color: var(--bone-dim);
  margin-top: 10px;
}
