/* ibm-plex-sans-latin-400-normal */
@font-face {
  font-family: 'IBM Plex Sans';
  font-style: normal;
  font-display: swap;
  font-weight: 400;
  src: url(/_astro/ibm-plex-sans-latin-400-normal.CDDApCn2.woff2) format('woff2'), url(/_astro/ibm-plex-sans-latin-400-normal.CYLoc0-x.woff) format('woff');
}/* ibm-plex-sans-latin-600-normal */
@font-face {
  font-family: 'IBM Plex Sans';
  font-style: normal;
  font-display: swap;
  font-weight: 600;
  src: url(/_astro/ibm-plex-sans-latin-600-normal.CuJfVYMP.woff2) format('woff2'), url(/_astro/ibm-plex-sans-latin-600-normal.Cu4Hd6ag.woff) format('woff');
}/* ibm-plex-mono-latin-400-normal */
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-display: swap;
  font-weight: 400;
  src: url(/_astro/ibm-plex-mono-latin-400-normal.DMJ8VG8y.woff2) format('woff2'), url(/_astro/ibm-plex-mono-latin-400-normal.CvHOgSBP.woff) format('woff');
}/* ibm-plex-mono-latin-600-normal */
@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-display: swap;
  font-weight: 600;
  src: url(/_astro/ibm-plex-mono-latin-600-normal.BgSNZQsw.woff2) format('woff2'), url(/_astro/ibm-plex-mono-latin-600-normal.DWFSQ4vo.woff) format('woff');
}/* Axialy design tokens. One light theme by design (website plan, section 7). */
:root {
  --paper: #F7F5F0;
  --surface: #FFFFFF;
  --ink: #0C1524;
  --accent: #F2552C;
  --accent-hover: #FF6A3D;
  --accent-active: #E0461F;
  --blue: #1B4F72;
  --muted: #56606E;
  --rule: #D8D5CC;
  --field: #767C86;
  --sans: 'IBM Plex Sans', 'Helvetica Neue', Helvetica, Arial, sans-serif;
  --mono: 'IBM Plex Mono', 'SF Mono', Menlo, Consolas, monospace;
  --section-pad: clamp(56px, 7vw, 92px);
  --inset: clamp(22px, 4.2vw, 56px);
  color-scheme: light;
}

*, *::before, *::after { box-sizing: border-box; }

body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 18px;
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
}

a { color: var(--blue); }
a:hover { color: var(--ink); }
a:focus-visible { outline: 3px solid var(--blue); outline-offset: 3px; }

.skip {
  position: absolute; left: 16px; top: -72px; z-index: 2;
  padding: 12px 16px; background: var(--ink); color: var(--paper);
  font-weight: 600; text-decoration: none;
}
.skip:focus { top: 12px; color: var(--paper); }

.wrap { max-width: 1200px; margin: 0 auto; padding: 0 clamp(24px, 5vw, 56px); }

/* Header: the logo symbol sits centred on the page axis line. */
.site-header { position: relative; z-index: 20; }
.site-header-bar { background: var(--paper); }
.site-header-inner {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;
  gap: 4px 32px; padding-top: 19px; padding-bottom: 7px;
}
.logo-link { display: block; margin-left: -15px; padding: 7px 0; line-height: 0; }
.logo { display: block; height: 30px; width: auto; }
.site-nav { display: flex; flex-wrap: wrap; gap: 8px 28px; }
.site-nav a {
  display: block; padding: 12px 2px; font-size: 17px; line-height: 20px;
  font-weight: 600; color: var(--ink); text-decoration: none;
}
.site-nav a:hover, .site-nav a[aria-current='page'] { text-decoration: underline; text-underline-offset: 4px; }

/* The axis: a dash-dot centre line down the left edge of the content. */
.axis-frame { position: relative; }
.axis-line {
  position: absolute; left: 0; top: 0; bottom: 0; width: 1px;
  background-image: repeating-linear-gradient(
    to bottom,
    rgba(27, 79, 114, 0.7) 0px, rgba(27, 79, 114, 0.7) 16px,
    transparent 16px, transparent 20px,
    rgba(27, 79, 114, 0.7) 20px, rgba(27, 79, 114, 0.7) 22px,
    transparent 22px, transparent 26px
  );
}

.section {
  position: relative;
  padding: var(--section-pad) 0 var(--section-pad) var(--inset);
  border-top: 1px solid var(--rule);
}
.section-marker {
  position: absolute; left: -3px; top: calc(var(--section-pad) + 6px);
  width: 7px; height: 7px; background: var(--ink);
}
.eyebrow {
  margin: 0 0 20px; font-family: var(--mono); font-size: 13px; line-height: 20px;
  letter-spacing: 0.08em; text-transform: uppercase; color: var(--muted);
}
.section-title {
  margin: 0 0 28px; max-width: 780px; font-size: clamp(27px, 2.7vw, 38px);
  line-height: 1.18; font-weight: 600; letter-spacing: -0.012em; text-wrap: balance;
}
.section-title.tight { margin-bottom: 16px; }
.prose p { margin: 0 0 18px; max-width: 580px; }
.prose p:last-child { margin-bottom: 0; }
.intro { margin: 0 0 36px; max-width: 580px; }

/* Hero */
.hero {
  display: flex; flex-wrap: wrap; align-items: center; gap: 40px 56px;
  padding: clamp(36px, 5vw, 64px) 0 var(--section-pad) var(--inset);
}
.hero-text { flex: 1.5 1 520px; max-width: 640px; min-width: 0; }
.hero h1, .page-title {
  margin: 0 0 26px; font-size: clamp(32px, 3.4vw, 48px); line-height: 1.1;
  font-weight: 600; letter-spacing: -0.02em; text-wrap: balance;
}
.lede { margin: 0 0 34px; max-width: 560px; font-size: clamp(18px, 1.45vw, 20px); line-height: 1.6; }
.hero-figure { flex: 1 1 340px; max-width: 480px; min-width: 0; margin: 0; }
.hero-figure svg { display: block; width: 100%; height: auto; }
.caption { margin-top: 10px; font-size: 15px; line-height: 1.5; color: var(--muted); }

.btn {
  display: inline-flex; align-items: center; gap: 12px; padding: 16px 24px;
  background-color: var(--accent); color: var(--ink); font-size: 17px; line-height: 24px;
  font-weight: 600; text-decoration: none; overflow-wrap: anywhere;
  transition: background-color 0.15s ease-out;
}
.btn:hover { background-color: var(--accent-hover); color: var(--ink); }
.btn:active { background-color: var(--accent-active); }
.btn svg { display: block; flex: none; }
@media (prefers-reduced-motion: reduce) { .btn { transition: none; } }

/* Figure 1 labels */
.fig-label { font-family: var(--mono); font-size: 13px; letter-spacing: 0.5px; fill: var(--blue); }
.fig-label .strong { font-weight: 600; }

/* Services */
.svc-groups { display: grid; gap: 44px; }
.svc-compact { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(240px, 100%), 1fr)); gap: 28px 40px; }
.svc-col { min-width: 0; padding-top: 14px; border-top: 1px solid var(--ink); }
.svc-names { margin: 0; padding: 0; list-style: none; }
.svc-names li { padding: 11px 0; border-bottom: 1px solid var(--rule); font-size: 18px; line-height: 1.35; font-weight: 600; }
.more { margin: 28px 0 0; font-size: 17px; font-weight: 600; }
.more a { text-underline-offset: 4px; }
.svc-stage {
  margin: 0 0 10px; font-family: var(--mono); font-size: 13px; line-height: 20px; font-weight: 600;
  letter-spacing: 0.08em; text-transform: uppercase; color: var(--blue);
}
.svc { display: flex; flex-wrap: wrap; gap: 14px 40px; padding: 26px 0; border-top: 1px solid var(--rule); }
.svc:first-child { border-top-color: var(--ink); }
.svc:last-child { border-bottom: 1px solid var(--rule); }
.svc h3 { flex: 1 1 200px; min-width: 0; margin: 0; font-size: 20px; line-height: 1.3; font-weight: 600; }
.svc-main { flex: 2.2 1 300px; min-width: 0; }
.svc-side { flex: 1.3 1 220px; min-width: 0; }
.label {
  margin: 0 0 6px; font-family: var(--mono); font-size: 13px; line-height: 18px;
  letter-spacing: 0.08em; text-transform: uppercase; color: var(--muted);
}
.body-sm { margin: 0; font-size: 17px; line-height: 1.55; }
.muted { color: var(--muted); }
.note { margin: 22px 0 0; max-width: 500px; font-size: 15px; line-height: 1.55; color: var(--muted); }

/* Method */
.steps {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(min(210px, 100%), 1fr));
  gap: 28px 32px; margin: 0 0 56px; padding: 0; list-style: none;
}
.steps li { padding-top: 16px; border-top: 1px solid var(--ink); }
.num { margin: 0 0 8px; font-family: var(--mono); font-size: 13px; line-height: 20px; color: var(--muted); }
.steps h3 { margin: 0 0 8px; font-size: 20px; line-height: 1.3; font-weight: 600; }
.trace { margin: 0; }
.trace-label {
  margin: 0 0 14px; font-family: var(--mono); font-size: 13px; line-height: 18px;
  letter-spacing: 0.08em; text-transform: uppercase; color: var(--blue);
}
.cards { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(260px, 100%), 1fr)); gap: 12px; }
.card { display: flex; flex-direction: column; padding: 20px 22px 22px; border: 1px solid var(--blue); background: var(--surface); }
.card-id { margin: 0 0 10px; font-family: var(--mono); font-size: 13px; line-height: 20px; color: var(--blue); }
.card-id strong { font-weight: 600; }
.card-text { margin: 0 0 14px; font-size: 17px; line-height: 1.5; }
.card-link { margin: auto 0 0; font-family: var(--mono); font-size: 13px; line-height: 18px; color: var(--muted); }

/* Track record and engagement */
.split { display: flex; flex-wrap: wrap; align-items: flex-start; gap: 36px 64px; }
.split-main { flex: 1 1 500px; max-width: 580px; min-width: 0; }
.split-side { flex: 1 1 240px; max-width: 320px; min-width: 0; display: flex; flex-direction: column; gap: 12px; }
.facts { margin: 0; }
.facts div { display: flex; flex-wrap: wrap; gap: 4px 28px; padding: 18px 0; border-top: 1px solid var(--rule); }
.facts div:last-child { border-bottom: 1px solid var(--rule); }
.facts dt { flex: 0 0 150px; font-weight: 600; }
.facts dd { flex: 1 1 300px; min-width: 0; margin: 0; }
.placeholder {
  margin: 0; padding: 14px 16px; border: 1px dashed var(--field);
  font-family: var(--mono); font-size: 13px; line-height: 1.5; color: var(--muted);
}
.engage { margin: 0; padding: 0; list-style: none; }
.engage li { display: flex; flex-wrap: wrap; gap: 4px 28px; padding: 20px 0; border-top: 1px solid var(--rule); }
.engage li:first-child { border-top-color: var(--ink); }
.engage li:last-child { border-bottom: 1px solid var(--rule); }
.engage .num { flex: 0 0 22px; margin: 0; line-height: 28px; }
.engage-body { flex: 1 1 300px; min-width: 0; }
.engage h3 { margin: 0 0 6px; font-size: 20px; line-height: 1.4; font-weight: 600; }
.engage-body p { margin: 0 0 8px; font-size: 17px; line-height: 1.55; }
.terms {
  font-family: var(--mono); font-size: 13px; line-height: 18px; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--muted);
}
.engage-body p.terms { margin: 0; font-size: 13px; line-height: 18px; }
.rules { flex: 1 1 240px; max-width: 320px; min-width: 0; display: flex; flex-direction: column; gap: 12px; }
.rule-box { padding: 20px 22px 22px; border: 1px solid var(--ink); }
.rule-box h3 { margin: 0 0 8px; font-size: 18px; line-height: 1.4; font-weight: 600; }
.rule-box p { margin: 0; font-size: 17px; line-height: 1.55; }

/* Contact */
.notes { margin: 30px 0 0; padding: 0; max-width: 580px; list-style: none; font-size: 17px; line-height: 1.55; color: var(--muted); }
.notes li { padding: 12px 0; border-top: 1px solid var(--rule); }
.notes li:last-child { border-bottom: 1px solid var(--rule); }
.address { margin: 18px 0 0; font-family: var(--mono); font-size: 15px; color: var(--muted); }

/* Inner pages */
.page-head { padding: clamp(36px, 5vw, 64px) 0 clamp(36px, 5vw, 56px) var(--inset); }
.page-lede { margin: 0; max-width: 620px; font-size: clamp(18px, 1.45vw, 20px); line-height: 1.6; }
.portrait-img { display: block; width: 220px; max-width: 100%; height: auto; aspect-ratio: 4 / 5; object-fit: cover; }
.list-plain { margin: 0; padding: 0; list-style: none; }
.list-plain li { padding: 10px 0; border-top: 1px solid var(--rule); }
.list-plain li:last-child { border-bottom: 1px solid var(--rule); }
.legal-section { max-width: 680px; }
.legal-section h2 { margin: 0 0 10px; font-size: 22px; line-height: 1.3; font-weight: 600; }
.legal-section + .legal-section { margin-top: 36px; }
.legal-section p { margin: 0 0 12px; }

/* Footer */
.site-footer {
  display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between;
  gap: 8px 32px; padding: 22px 0 30px; border-top: 1px solid var(--ink);
  font-size: 15px; line-height: 20px; color: var(--muted);
}
.site-footer p { margin: 0; }
.legal-nav { display: flex; flex-wrap: wrap; gap: 0 24px; }
.legal-nav a { display: block; padding: 12px 0; color: var(--ink); }

@media (max-width: 480px) {
  .logo-link { margin-left: 0; }
  .facts dt { flex-basis: 100%; }
}
/* ==========================================================================
   Axialy motion layer
   --------------------------------------------------------------------------
   Pure CSS. The site ships no JavaScript, so the CSP in vercel.json
   (script-src 'self'; style-src 'self') stays exactly as it is.

   The metaphor: the page is a technical sheet and the axis is a timeline.
   Lines are plotted as on a drawing, a red playhead rides the axis while you
   read, section markers flash as the playhead passes them, and pages change
   with a top-to-bottom scan, like a video frame refreshing.

   Rules (the motion-director agent enforces these):
   1. Everything that moves sits inside prefers-reduced-motion: no-preference.
      With reduced motion the site is complete and static.
   2. Content never depends on motion. Without support for a feature, the
      element simply appears in its final state.
   3. Animate opacity, translate, scale, filter, masks, stroke offsets and
      background-size only. Never layout properties on content. Nothing loops.
   4. Load intros use fill-mode backwards so hover and focus states win
      once the intro ends.
   5. Distances stay small: 22px for blocks, 0.4em for words.
   6. Timing: hover and focus 160ms; anything the user triggers (page change
      included) done within 400ms; hero copy settled within about 1.1s;
      stagger 30ms, capped at nine items.
   7. Never animate legal text, credentials, logos or the claims disclaimer.
   8. Scroll-driven shorthands carry a 1ms duration. Chrome scales it to the
      range; some Firefox builds apply nothing without a non-zero duration.

   Features used, newest first, each with a fallback:
   cross-document view transitions + speculation rules prerender (vercel.json),
   scroll-driven animations (scroll(), view(), named timelines, animation-range),
   scroll-state container queries, sibling-index(), text-box trim,
   @property-typed mask animation, :has() interaction, text-wrap pretty/balance.

   Support checked 8 Nov 2026 (MDN browser-compat-data 8.1.8, web-features 3.45.0):
   cross-document view transitions  Chrome/Edge 126, Safari 18.2, Firefox none
   scroll-driven animations          Chrome/Edge 115, Safari 26, Firefox 159 (not ESR 153)
   scroll-state container queries    Chrome/Edge 133 only
   sibling-index()                   Chrome/Edge 138, Safari 26.2, Firefox 154
   text-box trim (two keywords)      Chrome/Edge 133, Safari 18.2; Firefox fails the @supports test
   speculation rules prerender       Chrome/Edge only
   Firefox ESR, common on government desktops, gets the static site plus the
   load intros. Re-check with the platform-scout agent before relying on more.
   ========================================================================== */

:root {
  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
  --ease-in-out: cubic-bezier(0.65, 0, 0.35, 1);
  --ease-in: cubic-bezier(0.4, 0, 1, 1);
  --dur-micro: 160ms;
  --dur-small: 280ms;
  --dur-reveal: 520ms;
  --dur-draw: 900ms;
  --stagger: 30ms;
}

@property --ax-scan {
  syntax: '<percentage>';
  inherits: false;
  initial-value: 108%;
}

/* --------------------------------------------------------------------------
   Static craft: applies with or without motion
   -------------------------------------------------------------------------- */

html { scrollbar-gutter: stable; }
p, li, dd, figcaption { text-wrap: pretty; }
::selection { background: color-mix(in oklab, var(--accent) 28%, transparent); color: var(--ink); }

/* Main navigation: the underline is a drawn line rather than a text decoration. */
.site-nav a,
.site-nav a:hover,
.site-nav a[aria-current='page'] { text-decoration: none; }
.site-nav a {
  background: linear-gradient(currentColor, currentColor) no-repeat 0 calc(100% - 10px) / 0% 1.5px;
}
.site-nav a:hover,
.site-nav a[aria-current='page'] { background-size: 100% 1.5px; }

/* Button label trimmed to cap height, so it sits optically centred on the arrow. */
@supports (text-box: trim-both cap alphabetic) {
  .btn { padding-block: 19px; }
  .btn-label { text-box: trim-both cap alphabetic; }
}

/* Header stays on screen from tablet width up, and draws a hairline once it is stuck. */
@media (min-width: 760px) {
  .site-header { position: sticky; top: 0; container-type: scroll-state; }
  .section, .hero, .page-head { scroll-margin-top: 80px; }
}
@container scroll-state(stuck: top) {
  .site-header-bar { box-shadow: 0 1px 0 var(--rule); }
}

/* Fig. 1: hover an area label to isolate the cameras that serve it. */
.hero-title .w { display: inline-block; }
.trace-num {
  background: linear-gradient(var(--accent), var(--accent)) no-repeat 0 100% / 100% 2px;
  padding-bottom: 1px;
}
.cards:has(.card:hover) .trace-num { background-color: color-mix(in oklab, var(--accent) 22%, transparent); }

.fig-cover .lbl { cursor: default; pointer-events: bounding-box; }
.fig-cover .lbl:hover { fill: var(--ink); }
.fig-cover:has(.lbl.a-perimeter:hover) :is(.fov, .cam):not(.a-perimeter),
.fig-cover:has(.lbl.a-gate:hover) :is(.fov, .cam):not(.a-gate),
.fig-cover:has(.lbl.a-entrance:hover) :is(.fov, .cam):not(.a-entrance),
.fig-cover:has(.lbl.a-room:hover) :is(.fov, .cam):not(.a-room) { opacity: 0.16; }
.fig-cover:has(.lbl.a-perimeter:hover) .fov.a-perimeter,
.fig-cover:has(.lbl.a-gate:hover) .fov.a-gate,
.fig-cover:has(.lbl.a-entrance:hover) .fov.a-entrance,
.fig-cover:has(.lbl.a-room:hover) .fov.a-room { fill-opacity: 0.22; stroke-opacity: 0.95; }

.axis-head { display: none; }

/* --------------------------------------------------------------------------
   Motion
   -------------------------------------------------------------------------- */

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

  /* Page change: the new page scans in from the top while the old one lifts away.
     Header is named so it holds still through the change. */
  @view-transition { navigation: auto; }
  .site-header { view-transition-name: ax-header; }
  ::view-transition-old(root),
  ::view-transition-new(root) { mix-blend-mode: normal; }
  ::view-transition-old(root) { animation: ax-sink 360ms var(--ease-in) both; }
  ::view-transition-new(root) {
    animation: ax-scan 400ms var(--ease-in-out) both;
    mask-image: linear-gradient(to bottom, #000 var(--ax-scan), transparent calc(var(--ax-scan) + 8%));
  }

  /* Micro-interactions */
  .site-nav a { transition: background-size var(--dur-micro) var(--ease-out); }
  .btn svg { transition: translate var(--dur-micro) var(--ease-out); }
  .btn:hover svg { translate: 3px 0; }
  .site-header-bar { transition: box-shadow var(--dur-small) var(--ease-out); }
  .trace-num { transition: background-color var(--dur-micro) var(--ease-out); }
  .fig-cover :is(.fov, .cam) {
    transition: opacity var(--dur-micro) var(--ease-out), fill-opacity var(--dur-micro) var(--ease-out),
      stroke-opacity var(--dur-micro) var(--ease-out);
  }

  /* Hero intro: words rise into focus, then the lede and the call to action. */
  .hero-title .w { animation: ax-word 640ms var(--ease-out) backwards; }
  .hero-title .w:nth-child(1) { animation-delay: 40ms; }
  .hero-title .w:nth-child(2) { animation-delay: 70ms; }
  .hero-title .w:nth-child(3) { animation-delay: 100ms; }
  .hero-title .w:nth-child(4) { animation-delay: 130ms; }
  .hero-title .w:nth-child(5) { animation-delay: 160ms; }
  .hero-title .w:nth-child(6) { animation-delay: 190ms; }
  .hero-title .w:nth-child(7) { animation-delay: 220ms; }
  .hero-title .w:nth-child(8) { animation-delay: 250ms; }
  .hero-title .w:nth-child(n + 9) { animation-delay: 280ms; }
  @supports (order: sibling-index()) {
    .hero-title .w { animation-delay: calc(10ms + min(sibling-index(), 9) * 30ms); }
  }
  .hero .lede { animation: ax-rise 740ms var(--ease-out) 260ms backwards; }
  .hero-text .btn { animation: ax-rise 700ms var(--ease-out) 340ms backwards; }
  .hero-figure .caption { animation: ax-fade 900ms var(--ease-out) 2000ms backwards; }

  /* Inner page heads */
  .page-head > * { animation: ax-rise 680ms var(--ease-out) backwards; }
  .page-head > :nth-child(2) { animation-delay: 70ms; }
  .page-head > :nth-child(3) { animation-delay: 140ms; }

  /* Fig. 1 plots itself: fence, building and room are drawn, then the cameras
     come on and their fields open from each lens, then the labels. About 2.3s. */
  .fig-cover .draw { stroke-dasharray: 1; }
  .fig-cover .fig-axis { animation: ax-fade 700ms var(--ease-out) 80ms backwards; }
  .fig-cover .fig-fence { animation: ax-draw 1200ms var(--ease-in-out) 150ms backwards; }
  .fig-cover .fig-building { animation: ax-draw 900ms var(--ease-in-out) 420ms backwards; }
  .fig-cover .fig-room { animation: ax-draw 700ms var(--ease-in-out) 720ms backwards; }
  .fig-cover .fig-posts { animation: ax-fade 500ms var(--ease-out) 1050ms backwards; }
  .fig-cover :is(.fig-gate, .fig-door) { animation: ax-fade 500ms var(--ease-out) 1100ms backwards; }
  .fig-cover :is(.fig-core, .cam) { transform-box: fill-box; transform-origin: center; }
  .fig-cover .fig-core { animation: ax-pop 500ms var(--ease-out) 1250ms backwards; }
  .fig-cover .cam { animation: ax-pop 420ms var(--ease-out) backwards; }
  .fig-cover .cam-1 { animation-delay: 1250ms; }
  .fig-cover .cam-2 { animation-delay: 1310ms; }
  .fig-cover .cam-3 { animation-delay: 1370ms; }
  .fig-cover .cam-4 { animation-delay: 1430ms; }
  .fig-cover .cam-5 { animation-delay: 1490ms; }
  .fig-cover .cam-6 { animation-delay: 1550ms; }
  .fig-cover .cam-7 { animation-delay: 1610ms; }
  .fig-cover .fov { transform-box: view-box; animation: ax-open 820ms var(--ease-out) backwards; }
  .fig-cover .fov-1 { transform-origin: 54px 56px; animation-delay: 1330ms; }
  .fig-cover .fov-2 { transform-origin: 432px 62px; animation-delay: 1400ms; }
  .fig-cover .fov-3 { transform-origin: 426px 340px; animation-delay: 1470ms; }
  .fig-cover .fov-4 { transform-origin: 48px 334px; animation-delay: 1540ms; }
  .fig-cover .fov-5 { transform-origin: 190px 304px; animation-delay: 1610ms; }
  .fig-cover .fov-6 { transform-origin: 300px 260px; animation-delay: 1680ms; }
  .fig-cover .fov-7 { transform-origin: 270px 150px; animation-delay: 1750ms; }
  .fig-cover .fig-reader { animation: ax-fade 400ms var(--ease-out) 1750ms backwards; }
  .fig-cover .fig-leader { animation: ax-fade 400ms var(--ease-out) 1900ms backwards; }
  .fig-cover .fig-label { animation: ax-rise-sm 520ms var(--ease-out) backwards; }
  .fig-cover .fig-label:nth-of-type(1) { animation-delay: 1820ms; }
  .fig-cover .fig-label:nth-of-type(2) { animation-delay: 1900ms; }
  .fig-cover .fig-label:nth-of-type(3) { animation-delay: 1980ms; }
  .fig-cover .fig-label:nth-of-type(4) { animation-delay: 2060ms; }
}

/* Reduced motion: page changes become a plain 150ms crossfade. Nothing moves. */
@media (prefers-reduced-motion: reduce) {
  @view-transition { navigation: auto; }
  ::view-transition-group(*),
  ::view-transition-old(*),
  ::view-transition-new(*) { animation-duration: 150ms; }
}

/* Scroll-driven: only where the browser runs animations on a scroll timeline. */
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    /* The playhead: a red square that holds at 45% of the viewport on the axis
       and fades in once reading starts. Section markers flash as it passes. */
    .axis-head {
      display: block; position: sticky; top: 45vh; z-index: 3; height: 0; pointer-events: none;
      animation: ax-fade 1ms linear both; animation-timeline: scroll(root); animation-range: 0px 160px;
    }
    .axis-head::before {
      content: ''; position: absolute; left: -3px; top: -3px; width: 7px; height: 7px; background: var(--accent);
    }
    .axis-head::after {
      content: ''; position: absolute; left: 0; bottom: 4px; width: 1px; height: 96px;
      background: linear-gradient(to top, var(--accent), transparent); opacity: 0.6;
    }
    .section-marker {
      animation: ax-mark 1ms linear both; animation-timeline: view(); animation-range: cover 48% cover 62%;
    }

    /* Blocks rise into place over the first 180px of scroll after they appear. */
    .section > :is(.eyebrow, .section-title, .intro, .btn, .more),
    .section :is(.prose > p, .svc-col, .steps > li, .card, .trace-label, .caption, .facts > div,
      .engage > li, .rule-box, .notes > li, .svc, .split-side > *) {
      animation: ax-rise 1ms var(--ease-out) both;
      animation-timeline: view();
      animation-range: cover 0px cover 180px;
    }
    /* Items that sit side by side cascade left to right. */
    @supports (order: sibling-index()) {
      .section :is(.svc-col, .steps > li, .card) {
        animation-range: cover calc(sibling-index() * 28px - 28px) cover calc(152px + sibling-index() * 28px);
      }
    }

    /* Rules above columns and steps are drawn from the left, like lines on a sheet. */
    .section :is(.steps > li, .svc-col) { position: relative; border-top-color: transparent; view-timeline: --ax-row; }
    .section :is(.steps > li, .svc-col)::before {
      content: ''; position: absolute; left: 0; right: 0; top: -1px; height: 1px; background: var(--ink);
      transform-origin: 0 50%;
      animation: ax-line-x 1ms var(--ease-out) both; animation-timeline: --ax-row; animation-range: cover 40px cover 320px;
    }

    /* Fig. 2: the shared number is underlined in turn, card by card. */
    .card { view-timeline: --ax-card; }
    .trace-num {
      animation: ax-underline 1ms var(--ease-out) both; animation-timeline: --ax-card; animation-range: cover 150px cover 260px;
    }
    .card:nth-child(2) .trace-num { animation-range: cover 210px cover 320px; }
    .card:nth-child(3) .trace-num { animation-range: cover 270px cover 380px; }
  }
}

/* --------------------------------------------------------------------------
   Keyframes
   -------------------------------------------------------------------------- */

@keyframes ax-fade { from { opacity: 0; } }
@keyframes ax-rise { from { opacity: 0; translate: 0 22px; } }
@keyframes ax-rise-sm { from { opacity: 0; translate: 0 6px; } }
@keyframes ax-word { from { opacity: 0; translate: 0 0.4em; filter: blur(6px); } }
@keyframes ax-draw { from { stroke-dashoffset: 1; } to { stroke-dashoffset: 0; } }
@keyframes ax-open { from { opacity: 0; scale: 0.12; } }
@keyframes ax-pop { from { opacity: 0; scale: 0.3; } }
@keyframes ax-line-x { from { scale: 0 1; } }
@keyframes ax-underline { from { background-size: 0% 2px; } to { background-size: 100% 2px; } }
@keyframes ax-mark {
  0%, 100% { scale: 1; background-color: var(--ink); }
  45% { scale: 1.9; background-color: var(--accent); }
}
@keyframes ax-scan { from { --ax-scan: -8%; } to { --ax-scan: 108%; } }
@keyframes ax-sink { to { opacity: 0; translate: 0 -12px; } }

@media print {
  *, *::before, *::after { animation: none !important; transition: none !important; }
  .axis-head { display: none !important; }
  .site-header { position: static !important; }
}
