/* ==================================================================================================
   Libertas AI Solutions — direction v11 · OPERATOR
   The machine's control surface. Instrument plates, mono readouts, a schematic security page.

   Everything the site shows now sits on a *plate*: squared 2px, a 1px mist rule at .10, a mono label
   in its top-left, and bracket marks in the corners. Nothing floats; everything is mounted. The page
   is calm and ordered, but it is a live machine — beacons emit, plates draw their own strokes, and the
   public/private schematic on security.html is the centrepiece.

   This sheet loads AFTER assets/site-tech.css (the shared technical layer) and AFTER
   assets/base-landing.css. base-landing.css lives in @layer (reset, tokens, base, layout, components,
   utilities, responsive, legacy); this file is deliberately UNLAYERED, so it wins on cascade origin
   without a specificity war and without !important — except two places, both marked INLINE, where the
   frozen content carries a light-ground colour in a style="" attribute.

   Contents
     01 fonts          02 tokens         03 base + type      04 ground: grid + wash
     05 the plate      06 header         07 buttons          08 hero + status board
     09 sections       10 cards, steps   11 security schematic
     12 pricing + table                 13 about / overview 14 document pages
     15 contact form                    16 case study       17 cta + footer
     18 r-* utilities + ornament remap  19 responsive       20 motion   21 reduced motion (LAST)
   ================================================================================================== */

/* ============================== 01 FONTS ========================================================= */
/* Self-hosted, relative to this stylesheet (assets/skin.css -> assets/fonts/*.woff2). Barlow and
   Barlow Condensed arrive from the content layer's own assets/fonts/fonts.css — not redeclared here.
   Roboto / Roboto Mono ship in the beatdeck repo but are on the brand's never-list and are not used. */

@font-face {
  font-family: 'Archivo Black';
  font-style: normal; font-weight: 400; font-display: swap;
  src: url("fonts/ArchivoBlack-400.woff2") format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC,
                 U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193,
                 U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'JetBrains Mono';
  font-style: normal; font-weight: 400; font-display: swap;
  src: url("fonts/JetBrainsMono-Regular.woff2") format('woff2');
}
@font-face {
  font-family: 'JetBrains Mono';
  font-style: normal; font-weight: 500; font-display: swap;
  src: url("fonts/JetBrainsMono-Medium.woff2") format('woff2');
}
@font-face {
  font-family: 'JetBrains Mono';
  font-style: normal; font-weight: 700; font-display: swap;
  src: url("fonts/JetBrainsMono-Bold.woff2") format('woff2');
}

/* ============================== 02 TOKENS ======================================================== */
/* The brand's own values, reused — not redefined. What this direction adds is the *system* built on
   them: one Ink ground, mist as the only rule material, surfaces lifted by a mist tint rather than an
   invented grey, and a single accent. The four legacy tokens at the end of the block are the seam:
   components in base-landing.css read --text/--text-secondary/--border/--grey, so repointing those
   four flips the whole inherited vocabulary dark in one place. */

:root {
  /* brand, verbatim */
  --ink: #0A1628; --navy: #1B3A6B; --midnight: #0F2547;
  --navy-a: #21406F; --navy-b: #33508A;
  --sig: #C8102E;                 /* Signal Red — fill and accent only */
  --sig-text: #E5708A;            /* red TYPE on Ink (Signal Red is 3.08:1 there: fill only) */
  --beacon: #F0455F;              /* beacon rings / live indicators on Ink */
  --steel: #5A6783; --mist: #C9D1E0; --paper: #F4F5F8; --hair: #E2E6EE; --white: #fff;
  --ringsteel: #7689A6;           /* the beacon's own third ring colour — the icon stroke */

  /* type */
  --display: 'Archivo Black', 'Barlow Condensed', 'Arial Narrow', system-ui, sans-serif;
  --cond: 'Barlow Condensed', 'Arial Narrow', system-ui, sans-serif;
  --body: 'Barlow', system-ui, -apple-system, sans-serif;
  --mono: 'JetBrains Mono', ui-monospace, 'SFMono-Regular', Menlo, monospace;

  --fs-mono: 14px;                                  /* the floor: nothing on this site is smaller */
  --fs-small: 15px;
  --fs-body: 17px;
  --fs-lede: clamp(17px, 1.2vw, 19px);
  --fs-h1: clamp(31px, 6.2vw, 70px);
  --fs-h2: clamp(27px, 3.9vw, 44px);
  --fs-h3: clamp(19px, 1.5vw, 22px);
  --track-display: -.028em;
  --track-head: -.012em;
  --track-label: .10em;
  --track-mono: .07em;
  --lh-display: 1.03;
  --lh-head: 1.10;
  --lh-body: 1.68;

  /* grounds, surfaces, rules */
  --ground: #0A1628;
  --s1: rgba(201, 209, 224, .035);
  --s2: rgba(201, 209, 224, .055);
  --s3: rgba(201, 209, 224, .085);
  --edge-lo: rgba(201, 209, 224, .05);
  --edge: rgba(201, 209, 224, .10);
  --edge-2: rgba(201, 209, 224, .18);
  --edge-3: rgba(201, 209, 224, .30);
  --txt: #F4F5F8;
  --txt-2: #C9D1E0;
  --txt-3: #93A3BF;
  --txt-4: #7689A6;

  /* geometry */
  --radius-s: 2px;
  --radius: 3px;
  --max-w: 1200px;
  --gutter: clamp(18px, 3.2vw, 40px);
  --sect: clamp(52px, 6vw, 84px);

  /* motion — the brand's Liberty Ease, and a three-step budget */
  --micro: 120ms;
  --standard: 240ms;
  --emphasis: 480ms;
  --ease: cubic-bezier(.22, 1, .36, 1);

  --sh-plate: 0 1px 2px rgba(2, 6, 14, .45), 0 14px 34px -22px rgba(2, 6, 14, .95),
              0 0 0 .5px rgba(201, 209, 224, .06);

  /* legacy remap — base-landing.css's tier-2 semantic tokens, repointed at the dark ground */
  --text: var(--txt);
  --text-secondary: var(--txt-3);
  --border: var(--edge);
  --border-light: var(--edge-lo);
  --grey: var(--ink);
  --radius-legacy: 3px;
}

/* ============================== 03 BASE + TYPE =================================================== */
/* The page is one Ink plane. Every section paints an OPAQUE ink ground and then washes it — so the
   contrast instrument always measures type against the ground it is actually on, and a gradient can
   never move a word under 4.5:1 by accident. */

html { background-color: var(--ink); }
body {
  background-color: var(--ink);
  color: var(--txt-2);
  font-family: var(--body);
  font-size: var(--fs-body);
  font-weight: 400;
  line-height: var(--lh-body);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}
::selection { background: rgba(200, 16, 46, .55); color: #fff; }

/* — display: Archivo Black, mixed case, tight. The brand's Condensed keeps the h3/h4 rank. — */
h1, h2, .section-title, .blk-title, .hero h1, .page-head h1, .cta-box h2, .case-study h2,
.cmp-title, .ld-card h2 {
  font-family: var(--display);
  font-weight: 400;
  text-transform: none;
  letter-spacing: var(--track-display);
  line-height: var(--lh-display);
  color: var(--txt);
  text-wrap: balance;
  overflow-wrap: break-word;
}
h3, h4, .step h3, .sec-card h3, .price-card h3, .pillar h3, .uc-name, .principle h4,
.footer-col h3, .doc h3, .orch-stage h5 {
  font-family: var(--cond);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: .012em;
  line-height: 1.14;
  color: var(--txt);
}
p { text-wrap: pretty; }

/* — the label: mono, 14px, wide tracking, third ink. This is the room's voice. Every eyebrow, unit,
     ordinal, metadatum, field label and rail on the site is one of these. — */
.eyebrow, .df-kicker, .hc-kicker, .agentic-kicker, .orch-title, .cmp-caption, .cmp-scale,
.case-note, .tagline, .df-tag, .ld-alt, .df-foot, .hc-compliance, .see-also,
.doc .meta, .ld-field label, .ld-status, .footer-bottom, .case-lede + p,
.r-font-family-var-display, .r-font-family-var-display-3, .r-font-family-var-display-4,
.r-font-size-11-5px {
  font-family: var(--mono);
  font-size: var(--fs-mono);
  font-weight: 500;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  line-height: 1.45;
  color: var(--txt-3);
}

/* the eyebrow is the plate's label: a red index tick, then the words, then a hairline running out to
   the right edge of the plate. The tick is the section's one Signal Red fill. */
.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  margin-bottom: 14px;
  color: var(--txt-2);
  letter-spacing: var(--track-label);
}
.eyebrow::before {
  content: '';
  width: 10px;
  height: 10px;
  border-radius: 0;
  background: var(--sig);
  flex: none;
}
.eyebrow::after {
  content: '';
  height: 1px;
  width: clamp(24px, 8vw, 84px);
  background: linear-gradient(90deg, var(--edge-2), transparent);
  flex: none;
}

/* the accent word: red TYPE is always the on-dark red, never Signal Red */
.accent-signal { color: var(--sig-text); }

/* the section scale bar. Production's thick navy underline becomes a measured rule: a 14px Signal
   Red segment, then a hairline, then a tick. Same wordless device on every section. */
.baseline, .baseline.center {
  display: block;
  width: 132px;
  height: 1px;
  margin: 26px 0 0;
  border-radius: 0;
  background-image: linear-gradient(90deg, var(--sig) 0 14px, var(--edge-2) 14px 100%);
  position: relative;
}
.baseline::after {
  content: '';
  position: absolute;
  right: 0;
  top: -3px;
  width: 1px;
  height: 7px;
  background: var(--edge-3);
}
.baseline.center { margin-left: auto; margin-right: auto; }

/* focus: the beacon red is 4.94:1 on Ink, so the ring is visible on every dark ground */
:focus-visible { outline: 2px solid var(--beacon); outline-offset: 2px; border-radius: 1px; }
:focus:not(:focus-visible) { outline: none; }

/* ============================== 04 GROUND: GRID + WASH ========================================== */
/* Jason asked for "dark gradient with grid". The CMO ruling forbids graph paper. The resolution: a
   32px mesh at 5.5% mist, damped by two ink veils so it never runs edge-to-edge at full strength, and
   lifted by one Navy Rise wash at the very top of the document. All of it is ONE body background —
   no extra elements, nothing to z-index, nothing that can swallow a pointer. */

body {
  background-image:
    radial-gradient(120% 62% at 50% -8%, rgba(33, 64, 111, .50) 0%, rgba(15, 37, 71, .16) 38%, rgba(10, 22, 40, 0) 66%),
    linear-gradient(180deg, rgba(10, 22, 40, .55) 0%, rgba(10, 22, 40, 0) 18%, rgba(10, 22, 40, 0) 84%, rgba(10, 22, 40, .60) 100%),
    repeating-linear-gradient(0deg, rgba(201, 209, 224, .055) 0 1px, transparent 1px 32px),
    repeating-linear-gradient(90deg, rgba(201, 209, 224, .055) 0 1px, transparent 1px 32px);
  background-size: 100% 100%, 100% 100%, 32px 32px, 32px 32px;
  background-repeat: no-repeat, no-repeat, repeat, repeat;
  background-attachment: fixed, fixed, fixed, fixed;
  background-position: 50% 0, 0 0, 0 0, 0 0;
}
/* below 701px the mesh doubles the line density on a 320px screen and reads as fabric: drop the
   horizontal lines and keep the vertical ones at a lower alpha (stated in STYLE-NOTES). */
@media (max-width: 700px) {
  body {
    background-image:
      radial-gradient(140% 46% at 50% -6%, rgba(33, 64, 111, .46) 0%, rgba(10, 22, 40, 0) 60%),
      repeating-linear-gradient(90deg, rgba(201, 209, 224, .045) 0 1px, transparent 1px 28px);
    background-size: 100% 100%, 28px 28px;
    background-repeat: no-repeat, repeat;
    background-attachment: fixed, fixed;
  }
}

/* every band owns an opaque ground so nothing can inherit a light one from base-landing.css */
section, header.page-head, footer, main.page-wrap { background-color: var(--ink); }
/* the inheritable gridded bands the content layer marks itself: silent, because the mesh is already
   on the body. They stay as empty divs and paint nothing. */
.grid-bg::before, .grid-bg-light::before, .cta-red.grid-bg::before { background-image: none; }

/* ============================== 05 THE PLATE ===================================================== */
/* One component vocabulary, reused for cards, price cards, steps, panels, the schematic, the case
   frame and the form. Squared, hairline-ruled, lifted by a mist tint, with a mono label row at the
   top and bracket marks in the corners (the marks come from the shared runtime: .tech-corner-marks). */

.sec-card, .price-card, .uc-card, .pillar, .step, .panel, .doc, .orch, .dataflow,
.ld-card, .hc-callout, .cmp, .case-frame, .df-panel {
  position: relative;
  background-color: var(--ink);
  background-image: linear-gradient(180deg, var(--s2), var(--s1) 62%, var(--s1));
  border: 1px solid var(--edge);
  border-radius: var(--radius-s);
  box-shadow: var(--sh-plate);
}

/* the plate's label row: title left, ornament right, one hairline under both */
.sec-card { padding: 22px 22px 20px; text-align: left; display: flex; flex-direction: column; gap: 0; }
.sec-card h3 {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  font-size: clamp(18px, 1.35vw, 21px);
  padding-bottom: 12px; margin-bottom: 12px;
  border-bottom: 1px solid var(--edge);
  color: var(--txt);
}
.sec-card p { font-size: var(--fs-small); line-height: 1.62; color: var(--txt-3); }
.sec-card > span {
  margin-top: 16px;
  font-family: var(--mono); font-size: var(--fs-mono); font-weight: 500;
  letter-spacing: var(--track-mono); text-transform: uppercase;
  color: var(--txt-2);
  display: inline-flex; align-items: center; gap: 8px;
}
.sec-card > span::after {
  content: ''; width: 18px; height: 1px; background: var(--edge-3);
  transition: width var(--standard) var(--ease), background-color var(--standard) var(--ease);
}
.sec-card:hover, .sec-card:focus-visible { border-color: var(--edge-2); }
.sec-card:hover > span::after, .sec-card:focus-visible > span::after { width: 30px; background: var(--beacon); }
.sec-card:hover { transform: none; box-shadow: var(--sh-plate), 0 22px 44px -30px rgba(2, 6, 14, .9); }
.sec-card { transition: border-color var(--standard) var(--ease), box-shadow var(--standard) var(--ease); }
.sec-card a { text-decoration: none; }

/* a plate that is a link should not lift: this is an instrument, not a card that floats */
.uc-card { padding: 22px; }
.uc-name {
  display: flex; align-items: center; gap: 10px;
  font-size: 18px; letter-spacing: .01em;
  padding-bottom: 12px; border-bottom: 1px solid var(--edge); margin-bottom: 12px;
}
.uc-name .r-width-40px { width: 22px; display: inline-flex; flex: none; }
.uc-rule { display: none; }
.usecase-line { font-size: var(--fs-small); line-height: 1.65; color: var(--txt-3); }
.usecase-line b { color: var(--txt-2); font-weight: 600; }
.usecase-outcome b { color: var(--txt); }
.uc-bn { margin-bottom: 12px; }

/* ============================== 06 HEADER ======================================================== */
/* Two rows: the strip (tagline + the five company/legal pages) over the main row (lockup, the four
   product pages, Chat or Book, two beacons). Mono throughout, because the header is instrument
   labelling, not product copy. Below 1001px the strip moves into the hamburger — all nine pages. */

nav {
  background-color: var(--ink);
  border-bottom: 1px solid var(--edge);
  box-shadow: 0 1px 0 rgba(201, 209, 224, .04), 0 18px 40px -34px rgba(0, 0, 0, .9);
}
body nav .nav-strip { background: rgba(201, 209, 224, .028); }
body nav .nav-strip .container {
  height: auto; min-height: 32px; padding-top: 7px; padding-bottom: 7px;
  gap: 20px;
}
body nav .nav-strip .nav-tagline {
  font-family: var(--mono); font-size: var(--fs-mono); font-weight: 400;
  letter-spacing: var(--track-label); text-transform: uppercase;
  color: var(--txt-4);
}
body nav .nav-strip .nav-tagline .free { color: var(--txt-3); }
body nav .nav-utility { gap: clamp(12px, 1.5vw, 24px); }
body nav .nav-utility a { color: var(--txt-3); letter-spacing: var(--track-mono); }
body nav .nav-utility a:hover, body nav .nav-utility a:focus-visible { color: var(--txt); }
body nav .nav-utility a[aria-current="page"] { color: var(--txt); border-bottom-color: var(--edge-3); }
body nav .nav-strip-mark i { background: var(--edge-2); height: 1px; width: 12px; }

nav > .container {
  display: flex; align-items: center; justify-content: space-between;
  gap: clamp(10px, 1.5vw, 26px);
  height: auto; min-height: 64px; padding-top: 9px; padding-bottom: 9px;
  max-width: var(--max-w); padding-left: var(--gutter); padding-right: var(--gutter);
}
/* the lockup: the brand's own artwork, untouched — only how it sits is decided here */
nav .logo { display: inline-flex; align-items: center; gap: 10px; flex: none; }
nav .logo svg.mark { width: 34px; height: 34px; }
nav .logo .word b {
  font-family: var(--cond); font-weight: 700; font-size: 23px; letter-spacing: .035em;
  text-transform: uppercase; color: var(--txt); line-height: 1;
}
nav .logo .word b .accent-signal { color: var(--sig); }
nav .logo .word small {
  font-family: var(--mono); font-size: var(--fs-mono); font-weight: 400;
  letter-spacing: .18em; color: var(--txt-4); margin-top: 3px;
}
nav .nav-tagline { display: none; }

nav .nav-links { justify-self: auto; display: flex; align-items: center; gap: clamp(10px, 1.35vw, 22px); }
nav .nav-links a {
  position: relative;
  font-family: var(--mono); font-size: var(--fs-mono); font-weight: 500;
  letter-spacing: var(--track-mono); text-transform: uppercase;
  color: var(--txt-3); text-decoration: none; white-space: nowrap;
  padding: 6px 0;
  transition: color var(--micro) var(--ease);
}
nav .nav-links a::after {
  content: ''; position: absolute; left: 0; right: 100%; bottom: 0; height: 1px;
  background: var(--edge-3); transition: right var(--standard) var(--ease);
}
nav .nav-links a:hover, nav .nav-links a:focus-visible { color: var(--txt); }
nav .nav-links a:hover::after, nav .nav-links a[aria-current="page"]::after { right: 0; }
nav .nav-links a[aria-current="page"] { color: var(--txt); }

nav .nav-cta { justify-self: auto; display: flex; align-items: center; gap: 8px; flex: none; }
nav .nav-cta .beacon-nav { width: 22px; height: 22px; opacity: .95; }
nav .nav-cta .btn { font-size: var(--fs-mono); padding: 8px 14px; min-height: 34px; }
nav .cta-or {
  font-family: var(--mono); font-size: var(--fs-mono); font-weight: 400;
  letter-spacing: var(--track-mono); text-transform: uppercase; color: var(--txt-4);
}
/* the second action in the header pair is a ghost: one Signal Red fill in the bar, not two */
nav .nav-cta .cta-or ~ .btn-red {
  background: transparent; color: var(--txt); border-color: var(--edge-3);
}
nav .nav-cta .cta-or ~ .btn-red:hover,
nav .nav-cta .cta-or ~ .btn-red:focus-visible { background: var(--s2); border-color: var(--txt-4); }

/* ============================== 07 BUTTONS ======================================================= */
/* Squared, mono, 44px minimum. One fill (Signal Red), one ghost, one quiet. The label is uppercase
   mono because in this room a button is a control, not a sentence. */

.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  min-height: 44px; padding: 12px 20px;
  font-family: var(--mono); font-size: var(--fs-mono); font-weight: 500;
  letter-spacing: var(--track-mono); text-transform: uppercase; line-height: 1.1;
  border-radius: var(--radius-s); border: 1px solid transparent;
  text-decoration: none; cursor: pointer; white-space: nowrap;
  transition: background-color var(--micro) var(--ease), border-color var(--micro) var(--ease),
              color var(--micro) var(--ease);
}
.btn-red, .btn-cta {
  background: var(--sig); border-color: var(--sig); color: #fff;
}
.btn-red:hover, .btn-red:focus-visible,
.btn-cta:hover, .btn-cta:focus-visible { background: #A50D26; border-color: #A50D26; color: #fff; }
.btn-primary, .btn-secondary {
  background: transparent; border-color: var(--edge-3); color: var(--txt);
}
.btn-primary:hover, .btn-primary:focus-visible,
.btn-secondary:hover, .btn-secondary:focus-visible {
  background: var(--s2); border-color: var(--txt-4); color: var(--txt);
}
.btn-large { min-height: 50px; padding: 14px 26px; font-size: var(--fs-mono); }
.cta-or {
  font-family: var(--mono); font-size: var(--fs-mono); font-weight: 400;
  letter-spacing: var(--track-mono); text-transform: uppercase; color: var(--txt-4);
}
/* base-landing pins `.hero .cta-or` to Liberty Navy for a white hero; there is no white hero here */
.hero .cta-or, .cta-actions .cta-or, .nav-cta .cta-or { color: var(--txt-4); }

/* text links inside copy: a hairline that brightens, never a blue */
.df-foot a, .ld-alt a, .hc-compliance-link, .see-also a, .doc a {
  color: var(--txt-2); text-decoration: none; border-bottom: 1px solid var(--edge-3);
  transition: color var(--micro) var(--ease), border-color var(--micro) var(--ease);
}
.df-foot a:hover, .ld-alt a:hover, .hc-compliance-link:hover, .doc a:hover {
  color: var(--txt); border-bottom-color: var(--beacon);
}

/* ============================== 08 HERO: THE STATUS BOARD ======================================== */
/* One instrument. The tagline is the plate label, the h1 is the big readout, the hairline under it is
   the scale, the two beacons are live indicators, and the content's own four explore plates are the
   bay below. The shared .tech-field canvas idles behind all of it. Left-aligned on purpose: a control
   surface has a datum, and every section on this site hangs off the same left edge. */

.hero {
  padding: clamp(46px, 6vw, 88px) 0 clamp(36px, 4.5vw, 60px);
  text-align: left;
  background-color: var(--ink);
  background-image: linear-gradient(168deg, rgba(33, 64, 111, .30) 0%, rgba(15, 37, 71, .12) 44%, rgba(10, 22, 40, 0) 72%);
  background-repeat: no-repeat;
  background-size: 100% 100%;
  border-bottom: 1px solid var(--edge);
  overflow: hidden;
}
.hero > .container { position: relative; z-index: 1; }

/* the corner ring system: an aura, not an object. Held well back and moved off the text column. */
.hero .beacon-corner { top: -160px; left: auto; right: -180px; opacity: .30; }
.hero .beacon-corner svg circle[stroke="var(--navy)"] { stroke: var(--ringsteel); opacity: .5; }
.hero .beacon-corner svg circle[stroke="var(--red)"] { stroke: var(--sig-text); }

.hero .tagline {
  display: inline-flex; align-items: center; gap: 10px;
  font-family: var(--mono); font-size: var(--fs-mono); font-weight: 500;
  letter-spacing: var(--track-label); text-transform: uppercase;
  color: var(--txt-3); margin-bottom: 22px;
}
.hero .tagline::before {
  content: ''; width: 7px; height: 7px; flex: none;
  background: var(--beacon);
  box-shadow: 0 0 0 3px rgba(240, 69, 95, .16);
}
.hero .tagline .free { color: var(--txt); }

.hero h1 {
  font-size: clamp(33px, 6.1vw, 78px);
  max-width: 17ch;
  margin: 0 0 22px;
  color: var(--txt);
}
/* the readout's baseline rule: the whole width of the measure, one red segment at the left */
.hero h1::after {
  content: '';
  display: block;
  width: min(100%, 520px);
  height: 1px;
  margin-top: clamp(20px, 2.4vw, 30px);
  background-image: linear-gradient(90deg, var(--sig) 0 56px, var(--edge) 56px 100%);
}

.hero p.hero-lede {
  font-size: var(--fs-lede); line-height: 1.66;
  color: var(--txt-3); max-width: 62ch; margin: 0 0 16px;
}
.hero p.hero-punch {
  font-family: var(--mono); font-size: var(--fs-mono); font-weight: 500;
  letter-spacing: var(--track-label); text-transform: uppercase;
  color: var(--txt-4); max-width: 62ch; margin: 0 0 30px;
  display: flex; flex-wrap: wrap; align-items: center; gap: 6px 10px;
}
.hero p.hero-punch span {
  color: var(--txt); text-decoration: none;
  border-bottom: 1px solid var(--edge-3); padding-bottom: 1px;
}
.hero-actions {
  display: flex; align-items: center; justify-content: flex-start;
  gap: 12px; flex-wrap: wrap;
}
.hero-actions .beacon-mini { width: 26px; height: 26px; }
/* one beacon group flanks the actions, not two: a mirrored pair doubles the red on one line */
.hero-actions .beacon-mini:last-child { display: none; }

/* the bay: four plates, from the page's own explore grid */
.explore-block { margin-top: clamp(38px, 4.6vw, 60px); text-align: left; }
.explore-grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 12px; }
.explore-grid .sec-card h3 { font-size: 17px; }
.explore-grid .sec-card .sector-orbit,
.explore-grid .sec-card .flow-dots,
.explore-grid .sec-card .shield-pulse,
.explore-grid .sec-card .flatline { flex: none; margin-left: 0; opacity: .9; }

/* ---- 06b the header, corrected: the strip's tagline shows; below 1001px the hamburger owns every
        page. This file is UNLAYERED, so base-landing's own media queries for .nav-links no longer
        apply once the rule above sets display:flex — the mobile behaviour has to be restated here. ---- */
body nav .nav-strip .nav-tagline { display: block; }
@media (max-width: 1000px) {
  nav .nav-links { display: none; }
  nav .menu-toggle {
    display: inline-flex; align-items: center; justify-content: center;
    width: 44px; height: 44px; margin-left: 6px;
    border: 1px solid var(--edge-2); border-radius: var(--radius-s);
    background: var(--s1); color: var(--txt); cursor: pointer; padding: 0; flex: none;
  }
  nav.open .nav-links {
    display: flex; position: absolute; top: 100%; left: 0; right: 0;
    flex-direction: column; align-items: stretch; gap: 0;
    background-color: var(--ink);
    background-image: linear-gradient(180deg, var(--s2), rgba(10, 22, 40, 0));
    border-top: 1px solid var(--edge);
    border-bottom: 1px solid var(--edge-2);
    box-shadow: 0 24px 44px -28px rgba(0, 0, 0, .95);
    padding: 4px 0 10px;
  }
  nav.open .nav-links a {
    padding: 13px var(--gutter); font-size: var(--fs-mono);
    border-bottom: 1px solid var(--edge-lo);
  }
  nav.open .nav-links a::after { display: none; }
}
@media (min-width: 1001px) {
  nav .menu-toggle { display: none; }
}

/* ---- 08b two corrections the render showed: the tagline is a sentence, not a flex row; the punch
        line is a sentence with three marked words, so its punctuation must not become a flex item. ---- */
.hero .tagline {
  display: block; max-width: 100%;
  font-size: var(--fs-mono); line-height: 1.5;
}
.hero .tagline::before {
  content: ''; display: inline-block; width: 7px; height: 7px;
  margin-right: 10px; vertical-align: middle; position: relative; top: -1px;
  background: var(--beacon); box-shadow: 0 0 0 3px rgba(240, 69, 95, .16);
}
.hero p.hero-punch { display: block; line-height: 2.0; }
.hero p.hero-punch span { white-space: nowrap; }
/* the card ornaments are repeated glyphs: monochrome, so the hero's red budget stays with the beacons */
.explore-grid .sec-card svg [stroke]:not([stroke="none"]) { stroke: var(--ringsteel); }
.explore-grid .sec-card .flatline svg [stroke] { stroke: var(--txt-4); }
.explore-grid .sec-card .flow-dots span { background: var(--txt-4); }
.explore-grid .sec-card .sector-dot { fill: var(--ringsteel); }
.explore-grid .sec-card .shield-ring { border-color: var(--ringsteel); }

/* ============================== 09 SECTIONS: THE CHASSIS ======================================== */
/* Every band is framed the same way: a full-width hairline at the top, then a plate header — the
   eyebrow as the label, the head as the readout, the description in a second column bottom-aligned,
   then the scale bar. Left-aligned. This is the single structural decision that makes the room an
   instrument bay rather than a landing page. */

section { padding: var(--sect) 0; }
section + section { border-top: 1px solid var(--edge); }
section[id] { scroll-margin-top: 120px; }

.section-header {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 1.3fr) minmax(0, .7fr);
  column-gap: clamp(20px, 4vw, 64px);
  align-items: end;
  text-align: left;
  margin-bottom: clamp(30px, 3.6vw, 48px);
  padding-top: 16px;
  border-top: 1px solid var(--edge-2);
}
/* the red segment that sits ON the header rule: the section's one Signal Red mark */
.section-header::before {
  content: '';
  position: absolute; left: 0; top: -1px;
  width: 44px; height: 2px;
  background: var(--sig);
}
/* the right-hand readout rail: two ticks and a dot, wordless, at the end of the header rule */
.section-header::after {
  content: '';
  position: absolute; right: 0; top: -4px;
  width: 1px; height: 9px;
  background: var(--edge-3);
  box-shadow: -8px 3px 0 0 var(--edge-2), -16px 3px 0 0 var(--edge-lo);
}
.section-header .eyebrow { grid-column: 1 / -1; margin-bottom: 18px; }
.section-header .section-title { grid-column: 1; margin: 0; }
.section-header .section-desc {
  grid-column: 2;
  margin: 0 0 4px;
  font-size: var(--fs-lede);
  line-height: 1.6;
  color: var(--txt-3);
  max-width: 42ch;
}
.section-header .baseline { grid-column: 1 / -1; margin-top: 24px; }
.section-header > * { min-width: 0; }

/* the plain bands the content layer builds (Who We Serve, About, values, process, serve) */
.industries, .security-section, .cost-section, .how-it-works { border-top: 1px solid var(--edge); }
.industries > .container > p {
  text-align: left; justify-content: flex-start;
  font-family: var(--mono); font-size: var(--fs-mono); letter-spacing: var(--track-label);
  text-transform: uppercase; color: var(--txt-3); margin-bottom: 20px;
}
.industries > .container > p::before { border-radius: 0; width: 8px; height: 8px; }

/* the sector legend: hairline chips in one wrapped row, icons monochrome (one accent per section,
   and this section's accent is the head) */
.industries-grid { display: flex; flex-wrap: wrap; gap: 8px; justify-content: flex-start; }
.industries-grid .item {
  font-family: var(--mono); font-size: var(--fs-mono); font-weight: 500;
  letter-spacing: var(--track-mono); text-transform: uppercase;
  color: var(--txt-2); opacity: 1;
  gap: 9px; align-items: center;
  padding: 9px 13px;
  border: 1px solid var(--edge);
  border-radius: var(--radius-s);
  background-color: var(--s1);
  transition: border-color var(--micro) var(--ease), background-color var(--micro) var(--ease);
}
.industries-grid .item:hover { border-color: var(--edge-3); background-color: var(--s2); }
.industries-grid .item svg { width: 17px; height: 17px; flex: none; }
.industries-grid .item svg [stroke]:not([stroke="none"]) { stroke: var(--ringsteel); }

/* the use-case panel under the legend */
.usecase-panel { margin-top: 40px; padding-top: 26px; border-top: 1px solid var(--edge); }
.usecase-head { text-align: left; max-width: 78ch; margin: 0 0 26px; }
.usecase-head h3 {
  font-family: var(--display); font-weight: 400; text-transform: none;
  letter-spacing: var(--track-display); font-size: var(--fs-h2); color: var(--txt);
}
.usecase-head p { font-size: var(--fs-lede); line-height: 1.66; color: var(--txt-3); margin-top: 0; }
.usecase-head p b, .usecase-head p strong { color: var(--txt-2); }
/* Jason: "the 'g' for amplifying was wrapped to the next line and that shouldn't happen" and "make it the
   light red". The word is ten single-letter spans (that is what animates), each an inline-block, so the browser
   may break between ANY two letters — which is how the trailing "g" ended up alone on the next line. nowrap on
   the wrapper holds it as one word. Colour: white -> the on-dark red #E5708A, the same value the rest of the
   layer uses for coloured words on dark grounds, because Signal Red as type is only 3.08:1 here. */
.amplifying-text { color: var(--red-text, #E5708A); font-weight: 500; white-space: nowrap; }
.amplifying-text span { display: inline-block; }
.usecase-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; }
/* the beacon that marks an outcome keeps its red — it is the brand's own device, and it is the one
   live mark in each card */
.uc-card .beacon-inline { width: 14px; height: 14px; margin-right: 7px; }

/* ============================== 10 HOW IT WORKS: THE SEQUENCE CONTROLLER ======================== */
/* Six stages, six plates, wired. The shared runtime draws the .tech-wire between them and lights one
   per beat; this sheet makes each stage read as a controller channel: an ordinal, a channel rule, a
   name, then the work. The orchestration block below stays behaviour.js's — it is styled, not driven. */

body .steps { display: grid; grid-template-columns: repeat(6, minmax(0, 1fr)); gap: 10px; }
body .steps .step {
  padding: 16px 15px 18px;
  border: 1px solid var(--edge);
  border-radius: var(--radius-s);
  background-image: linear-gradient(180deg, var(--s2), var(--s1));
  min-width: 0;
}
body .steps .step:first-child, body .steps .step:last-child { border-radius: var(--radius-s); }
.step-num {
  display: flex; align-items: center; gap: 10px;
  font-family: var(--mono); font-size: var(--fs-mono); font-weight: 500;
  letter-spacing: var(--track-mono); color: var(--txt-4);
  opacity: 1; line-height: 1; margin-bottom: 16px;
}
.step-num::after {
  content: ''; flex: 1 1 auto; height: 1px;
  background: linear-gradient(90deg, var(--edge-2), var(--edge-lo));
}
body .steps .step h3 { font-size: 17px; letter-spacing: .015em; margin-bottom: 8px; color: var(--txt); }
body .steps .step p { font-size: 14.5px; line-height: 1.55; color: var(--txt-3); }
body .steps .step.tech-live {
  border-color: rgba(229, 112, 138, .55);
  background-image: linear-gradient(180deg, rgba(200, 16, 46, .10), var(--s1) 70%);
}
body .steps .step.tech-live .step-num { color: var(--sig-text); }
body .steps .step.tech-live .step-num::after {
  background: linear-gradient(90deg, rgba(229, 112, 138, .55), var(--edge-lo));
}
/* the wire travels the GAP between plates, not across the plate: 10px, one hairline, red at the tip */
body .steps .step .tech-wire {
  right: -10px; width: 10px; top: 30px; height: 1px;
  background: linear-gradient(90deg, rgba(229, 112, 138, .10), rgba(229, 112, 138, .75));
}
body .steps .step .step-beacon { right: -9px; top: 30px; width: 8px; height: 8px; }
body .steps .step .step-beacon svg { width: 8px; height: 8px; }

/* — the agentic column ------------------------------------------------------------------------- */
.agentic {
  grid-template-columns: minmax(0, 1.1fr) minmax(0, .9fr);
  gap: clamp(20px, 3vw, 44px);
  margin-top: clamp(40px, 4.6vw, 64px);
  align-items: stretch;
  border-top: 1px solid var(--edge);
  padding-top: clamp(28px, 3.4vw, 44px);
}
.agentic-kicker {
  display: inline-flex; align-items: center; gap: 10px;
  color: var(--txt-3); letter-spacing: var(--track-label); margin-bottom: 12px;
}
.agentic-kicker::before { width: 14px; height: 1px; background: var(--sig); }
.agentic h3 { font-family: var(--display); font-weight: 400; text-transform: none; letter-spacing: var(--track-display); font-size: var(--fs-h2); color: var(--txt); }
.agentic-intro { font-size: var(--fs-lede); line-height: 1.66; color: var(--txt-3); max-width: 54ch; }
.principles { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 10px; margin-top: 22px; }
.principle {
  border: 1px solid var(--edge); border-radius: var(--radius-s);
  background-color: var(--ink);
  background-image: linear-gradient(180deg, var(--s1), transparent);
  padding: 14px 15px 15px;
}
.principle h4 {
  font-family: var(--cond); font-size: 17px; text-transform: uppercase; letter-spacing: .015em;
  color: var(--txt); display: flex; align-items: center; gap: 8px; margin-bottom: 6px;
}
.principle h4::before { width: 6px; height: 1px; border-radius: 0; background: var(--txt-4); flex: none; }
.principle h4 .beacon-inline { width: 13px; height: 13px; margin-right: 0; }
.principle p { font-size: 14.5px; line-height: 1.55; color: var(--txt-3); }

/* — the orchestration diagram: an instrument, not a card ----------------------------------------- */
.orch { padding: 20px 20px 18px; display: flex; flex-direction: column; }
.orch-title { color: var(--txt-3); margin-bottom: 16px; letter-spacing: var(--track-label); }
.orch-flow { gap: 14px; }
.orch-rail {
  left: 13px; top: 14px; bottom: 14px; width: 1px;
  background: var(--edge);
}
.orch-fill {
  position: absolute; left: 13px; top: 14px; width: 2px; height: 0;
  background: linear-gradient(180deg, var(--sig), rgba(200, 16, 46, .15));
  transform-origin: top center;
  transform: scaleY(0);
}
.orch-pulse {
  left: 9px; top: 10px; width: 9px; height: 9px; border-radius: 1px;
  background: var(--beacon);
  box-shadow: 0 0 0 3px rgba(240, 69, 95, .18);
}
.orch-stage { grid-template-columns: 28px minmax(0, 1fr); gap: 12px; }
.orch-node {
  width: 28px; height: 28px; border-radius: var(--radius-s);
  border: 1px solid var(--edge-2); background-color: var(--ink);
  font-family: var(--mono); font-size: var(--fs-mono); font-weight: 500;
  color: var(--txt-3);
  transition: border-color var(--standard) var(--ease), color var(--standard) var(--ease),
              background-color var(--standard) var(--ease);
}
.orch-stage h5 {
  font-family: var(--cond); font-size: 17px; text-transform: uppercase; letter-spacing: .015em;
  color: var(--txt); margin-top: 3px; line-height: 1.15;
}
.orch-node.is-live {
  border-color: var(--sig); background-color: rgba(200, 16, 46, .16); color: #fff;
  box-shadow: 0 0 0 3px rgba(200, 16, 46, .10);
}
.orch-stage p { font-size: 14.5px; line-height: 1.55; color: var(--txt-3); }
.orch-agents span {
  font-family: var(--mono); font-size: var(--fs-mono); font-weight: 500;
  letter-spacing: var(--track-mono); text-transform: uppercase;
  color: var(--txt-3); border: 1px solid var(--edge); border-radius: var(--radius-s);
  padding: 4px 9px;
}
.orch-agents span.is-live { color: var(--txt); border-color: var(--edge-3); }

/* ============================== 11 SECURITY: THE SCHEMATIC ====================================== */
/* The proof-of-craft page. The content's public/private comparison is drawn as an engineering
   schematic: hairline panels, chevron connectors, a perimeter the data crosses on the left and a
   closed perimeter on the right. The shared runtime animates the packets and lifts the private panel;
   this sheet decides the drawing — and makes the Private LLM the brightest object on the page. */

.security-grid { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; }
.sec-icon { display: flex; justify-content: flex-start; margin-bottom: 14px; height: 26px; }
.sec-icon svg { width: 26px; height: 26px; }
.sec-icon svg [stroke]:not([stroke="none"]) { stroke: var(--ringsteel); }
.sec-icon svg [fill]:not([fill="none"]) { fill: var(--sig); }

/* the schematic container: a plate with a header row of its own */
.dataflow { margin-top: 34px; padding: 0; overflow: hidden; }
.df-head {
  padding: 20px clamp(18px, 2.4vw, 28px) 18px;
  border-bottom: 1px solid var(--edge);
  background-image: linear-gradient(180deg, var(--s2), transparent);
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  column-gap: clamp(18px, 3vw, 44px); align-items: end;
}
.df-kicker { grid-column: 1 / -1; color: var(--txt-3); margin-bottom: 10px; }
.df-head h3 {
  grid-column: 1; font-family: var(--display); font-weight: 400; text-transform: none;
  letter-spacing: var(--track-display); font-size: clamp(22px, 2.4vw, 32px); line-height: 1.06;
  color: var(--txt);
}
.df-head p { grid-column: 2; font-size: var(--fs-small); line-height: 1.62; color: var(--txt-3); }
.df-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0; }
.df-panel { border: 0; border-radius: 0; box-shadow: none; background-image: none; padding: 0; }
.df-panel.bad { border-right: 1px solid var(--edge); }
.df-band {
  display: grid; grid-template-columns: 26px minmax(0, 1fr) auto; align-items: center; gap: 12px;
  padding: 16px clamp(16px, 2vw, 24px);
  border-bottom: 1px solid var(--edge);
  background-color: var(--s1);
}
.df-band h4 { font-family: var(--cond); text-transform: uppercase; letter-spacing: .015em; color: var(--txt); }
.df-tag {
  font-family: var(--mono); font-size: var(--fs-mono); font-weight: 500;
  letter-spacing: var(--track-mono); text-transform: uppercase;
  padding: 5px 9px; border: 1px solid var(--edge-2); border-radius: var(--radius-s);
  white-space: nowrap;
}
.df-tag.warn { color: var(--sig-text); border-color: rgba(229, 112, 138, .40); background: rgba(200, 16, 46, .08); }
.df-tag.ok { color: var(--txt); border-color: var(--edge-3); background: var(--s2); }
.df-body { padding: 18px clamp(16px, 2vw, 24px) 20px; }
.df-env { padding: 12px 12px 14px; }

/* the flow: box -> connector -> box, vertically, with chevrons drawn on the connector */
.df-flow { display: grid; grid-template-rows: auto 46px auto; align-items: stretch; }
.df-box {
  position: relative;
  border: 1px solid var(--edge);
  border-radius: var(--radius-s);
  background-color: var(--ink);
  padding: 12px 13px;
}
.df-box .cap {
  font-family: var(--mono); font-size: var(--fs-mono); font-weight: 500;
  letter-spacing: var(--track-mono); text-transform: uppercase; color: var(--txt-3);
  display: flex; align-items: center; gap: 7px; margin-bottom: 10px;
}
.df-chip {
  font-size: 14.5px; line-height: 1.4; color: var(--txt-2);
  padding: 5px 0 5px 14px; position: relative;
  border-top: 1px solid var(--edge-lo);
}
.df-chip:first-of-type { border-top: 1px solid var(--edge-lo); }
.df-chip::before {
  content: ''; position: absolute; left: 0; top: 50%; width: 6px; height: 1px;
  background: var(--edge-3);
}

/* the connector: one hairline, and a chevron repeated down it */
.df-track { position: relative; margin: 0 auto; width: 100%; }
.df-track::before {
  content: ''; position: absolute; left: 50%; top: 0; bottom: 0; width: 1px;
  background: linear-gradient(180deg, var(--edge-2), var(--edge-lo));
}
.df-track::after {
  content: ''; position: absolute; left: 50%; top: 50%; width: 7px; height: 7px;
  margin: -3px 0 0 -3.5px;
  border-right: 1px solid var(--edge-3); border-bottom: 1px solid var(--edge-3);
  transform: rotate(45deg);
}
.df-track .dot {
  position: absolute; left: 50%; width: 3px; height: 3px; margin-left: -1.5px;
  background: var(--txt-4); border-radius: 0;
}
.df-track .dot:nth-child(2) { top: 26%; }
.df-track .dot:nth-child(3) { top: 50%; }
.df-track .dot:nth-child(4) { top: 74%; }
/* the packet the runtime sends travels this connector — brand beacon red, squared to match the room */
body .dataflow .tech-packet {
  width: 5px; height: 5px; margin-top: -2.5px; left: 50%; margin-left: -2.5px;
  border-radius: 1px;
  box-shadow: 0 0 0 3px rgba(240, 69, 95, .14);
}

/* — the PUBLIC side: the perimeter is crossed, the trace degrades out of the panel — */
.df-panel.bad .df-perim {
  position: absolute; left: 0; right: 0; top: 50%; height: 1px;
  background-image: repeating-linear-gradient(90deg, rgba(229, 112, 138, .55) 0 1px, transparent 1px 5px);
}
.df-panel.bad .df-box.ext { border-style: dashed; border-color: rgba(201, 209, 224, .22); }
.df-panel.bad .df-box.ext .cap { color: var(--txt-4); }
.df-panel.bad .df-track .dot { background: var(--sig-text); opacity: .55; }
.df-panel.bad .df-foot { color: var(--txt-4); }
/* the degrading edge: a vertical fade that reads as a trace losing signal */
.df-panel.bad .df-body {
  background-image: repeating-linear-gradient(180deg, rgba(201, 209, 224, .045) 0 1px, transparent 1px 9px);
  background-size: 26px 100%;
  background-repeat: no-repeat;
  background-position: right top;
}

/* — the PRIVATE side: the answer. Closed perimeter, containment line, and the brightest object. — */
.df-panel.good .df-env {
  border: 1px solid rgba(201, 209, 224, .16);
  border-radius: var(--radius-s);
  background-color: rgba(201, 209, 224, .02);
}
.df-panel.good .df-env > .cap { color: var(--txt-2); }
.df-panel.good .df-env > .cap svg [stroke]:not([stroke="none"]) { stroke: var(--txt-3); }
body .dataflow .df-panel.good .df-env::before {
  border: 1px solid rgba(201, 209, 224, .22);
  border-radius: var(--radius-s);
  inset: -9px;
}
body .dataflow .df-panel.good .df-env::after {
  background: linear-gradient(90deg, transparent, rgba(244, 245, 248, .85), transparent);
  left: -9px; right: -9px; top: -9px;
}
/* the perimeter fence: ticks down both uprights of the private environment */
.df-panel.good .df-env::before { box-shadow: none; }
body .dataflow .df-panel.good .df-box.yours .df-chip::before { background: rgba(201, 209, 224, .55); }
.df-panel.good .df-track .dot { background: var(--txt-2); }
.df-panel.good .df-track::before { background: linear-gradient(180deg, var(--txt-4), var(--edge-2)); }

/* THE BRIGHTEST OBJECT: the private model. Paper type, a 1px paper edge, the brand's Navy Rise
   behind it, and the runtime's ring system rotating outward from it. Nothing else on the site is
   allowed this much light. */
.df-box.llm {
  display: flex; flex-direction: column; align-items: flex-start; gap: 6px;
  padding: 16px 16px 17px;
  background-color: var(--midnight);
  background-image: linear-gradient(152deg, #21406F 0%, #1B3A6B 46%, #0F2547 100%);
  border: 1px solid rgba(244, 245, 248, .34);
  box-shadow: 0 22px 46px -26px rgba(2, 6, 14, .95), 0 0 0 .5px rgba(201, 209, 224, .14);
  overflow: visible;
}
.df-box.llm .df-llm-ic { color: var(--paper); margin-bottom: 4px; }
.df-box.llm .df-llm-ic svg [stroke]:not([stroke="none"]) { stroke: var(--paper); stroke-width: 1.9; }
.df-box.llm b {
  font-family: var(--mono); font-size: var(--fs-mono); font-weight: 700;
  letter-spacing: var(--track-label); text-transform: uppercase; color: #fff;
}
.df-box.llm > span:not(.df-llm-ic):not(.tech-ring) {
  font-size: var(--fs-small); line-height: 1.5; color: var(--paper);
}
body .dataflow .df-box.llm.tech-rings .tech-ring { border-color: rgba(244, 245, 248, .18); }
body .dataflow .df-box.llm.tech-rings .tech-ring:nth-child(2) { border-color: rgba(240, 69, 95, .30); }
body .dataflow .df-box.llm.tech-rings .tech-ring:nth-child(3) { border-color: rgba(201, 209, 224, .10); }

/* the containment notes under each panel */
.df-bottom { margin-top: 16px; padding-top: 14px; border-top: 1px solid var(--edge); }
.df-wall {
  display: flex; align-items: flex-start; gap: 9px;
  font-size: var(--fs-small); line-height: 1.55; color: var(--txt-2);
  margin-bottom: 12px;
}
.df-wall .x { flex: none; margin-top: 1px; }
.df-wall .x svg [stroke]:not([stroke="none"]) { stroke: var(--txt-2); }
.df-foot {
  display: flex; align-items: flex-start; gap: 9px;
  font-family: var(--body); font-size: var(--fs-small); font-weight: 400;
  letter-spacing: 0; text-transform: none; line-height: 1.55; color: var(--txt-4);
}
.df-foot svg { flex: none; margin-top: 2px; }
.df-foot svg [stroke="#22B35E"] { stroke: var(--txt-2); }
.df-foot svg [stroke]:not([stroke="none"]) { stroke: var(--txt-4); }
/* the private panel's own answers keep one live mark: the runtime's red answer dot */
body .dataflow .df-panel.good.tech-answer { border-image: linear-gradient(160deg, #33508A 0%, #21406F 52%, #0F2547 100%) 1; }
.df-grid > .df-panel.good { background-image: linear-gradient(180deg, rgba(201, 209, 224, .045), rgba(201, 209, 224, .012)); }

/* ---- 11b the schematic, corrected: the flow in this room runs DOWN, so the packets do too. The
        shared runtime animates the packet horizontally; re-pointing the journey is a skin decision,
        and the alternative — a horizontal three-column schematic at 600px a panel — crushes the
        chip list. Keyframes are re-declared here and applied by data-leg, so reduced motion still
        stops them (site-tech.css's kill is !important and wins). ---- */
@keyframes opPacketDown {
  0%   { top: 0; opacity: 0; }
  10%  { opacity: 1; }
  74%  { top: calc(100% - 6px); opacity: 1; }
  100% { top: calc(100% - 6px); opacity: 0; }
}
@keyframes opPacketDownLoop {
  0%   { top: 0; opacity: 0; }
  10%  { opacity: 1; }
  46%  { top: calc(100% - 6px); opacity: 1; }
  56%  { top: calc(100% - 6px); opacity: 1; }
  92%  { top: 0; opacity: 1; }
  100% { top: 0; opacity: 0; }
}
body .dataflow .tech-packet[data-leg="out"] {
  animation-name: opPacketDown; left: 50%; margin-left: -2.5px; top: 0;
}
body .dataflow .tech-packet[data-leg="loop"] {
  animation-name: opPacketDownLoop; left: 50%; margin-left: -2.5px; top: 0;
}
/* the "sent" mark on a public chip: a square, not a chevron — this room points with rules */
body .dataflow .df-panel.bad .df-chip.tech-sent::after {
  content: ''; display: inline-block; width: 4px; height: 4px; margin-left: 7px;
  background: var(--sig-text); vertical-align: middle;
}
.df-head { align-items: baseline; }
.df-head p { margin-top: 4px; }
.df-panel.good .df-env > .cap svg { width: 14px; height: 14px; }
.df-track .dot:nth-child(1) { top: 24%; }
.df-track .dot:nth-child(2) { top: 50%; }
.df-track .dot:nth-child(3) { top: 76%; }
.df-track .dot:nth-child(4) { top: 88%; }
/* the perimeter reads as a ruled boundary with a tick at each end, not as scattered dots */
.df-panel.bad .df-perim {
  background-image: repeating-linear-gradient(90deg, rgba(229, 112, 138, .45) 0 1px, transparent 1px 6px);
  box-shadow: 0 0 0 0 transparent;
}
.df-panel.bad .df-perim::before, .df-panel.bad .df-perim::after {
  content: ''; position: absolute; top: -3px; width: 1px; height: 7px;
  background: rgba(229, 112, 138, .55);
}
.df-panel.bad .df-perim::before { left: 0; }
.df-panel.bad .df-perim::after { right: 0; }

/* ============================== 12 PRICING + THE COMPARISON TABLE =============================== */
/* Price cards are plates with a channel header: name left, rate right, then the body. The rate is
   tabular mono, because a price in this room is a readout. The featured plan is the section's accent:
   one 2px Navy Rise edge, and the only red fill on the page below the head. */

.pricing-grid { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 12px; align-items: stretch; }
.price-card {
  padding: 20px 18px 18px;
  display: flex; flex-direction: column;
  border-radius: var(--radius-s);
  border: 1px solid var(--edge);
}
.price-card h3 {
  font-size: 19px; letter-spacing: .015em; margin-bottom: 2px; color: var(--txt);
  display: flex; align-items: center; justify-content: space-between; gap: 8px;
}
.price-range {
  font-family: var(--mono); font-size: clamp(24px, 2.1vw, 30px); font-weight: 700;
  letter-spacing: -.01em; font-variant-numeric: tabular-nums;
  color: var(--txt); line-height: 1.1; margin: 12px 0 8px;
  padding-bottom: 12px; border-bottom: 1px solid var(--edge);
}
.price-range span {
  font-family: var(--mono); font-size: var(--fs-mono); font-weight: 400;
  letter-spacing: var(--track-mono); color: var(--txt-3); margin-left: 2px;
}
.price-desc { font-size: var(--fs-small); line-height: 1.55; color: var(--txt-3); margin-bottom: 14px; }
.price-card ul { list-style: none; margin: 0 0 18px; flex-grow: 1; }
.price-card ul li {
  font-size: 14.5px; line-height: 1.45; color: var(--txt-2);
  padding: 7px 0 7px 16px; position: relative;
  border-bottom: 1px solid var(--edge-lo);
}
.price-card ul li:last-child { border-bottom: 0; }
.price-card ul li::before {
  content: ''; position: absolute; left: 0; top: 14px;
  width: 6px; height: 1px; border-radius: 0; background: var(--txt-4);
}
.price-card .btn { width: 100%; }
.price-card.featured {
  border: 2px solid transparent;
  border-image: linear-gradient(160deg, #33508A 0%, #21406F 46%, #0F2547 100%) 1;
  background-image: linear-gradient(180deg, rgba(33, 64, 111, .28), rgba(15, 37, 71, .10) 60%, rgba(10, 22, 40, 0));
  box-shadow: 0 24px 48px -30px rgba(2, 6, 14, .9);
}
.price-card.featured ul li::before { background: var(--txt-2); }
.price-card .tag {
  position: absolute; top: 0; right: 0; left: auto;
  font-family: var(--mono); font-size: var(--fs-mono); font-weight: 500;
  letter-spacing: var(--track-mono); text-transform: uppercase;
  background: var(--sig); color: #fff;
  padding: 4px 9px; border-radius: 0 var(--radius-s) 0 var(--radius-s);
}
/* the add-on plate: a horizontal readout */
.price-card.r-margin-top-18px {
  flex-direction: row; align-items: center; flex-wrap: wrap; gap: 18px 28px;
  margin-top: 12px;
}
.price-card.r-margin-top-18px .r-flex-1-1-320px { flex: 1 1 320px; min-width: 0; }
.price-card.r-margin-top-18px .price-range {
  margin: 0; padding: 0 0 0 18px; border-bottom: 0; border-left: 1px solid var(--edge);
}
.price-card.r-margin-top-18px .r-margin-8px-0-0 { margin: 6px 0 0; }
.price-card.r-margin-top-18px .r-display-flex-3 {
  display: flex; gap: 0; border-left: 1px solid var(--edge);
}
.price-card.r-margin-top-18px .r-display-flex-3 > div {
  font-family: var(--mono); font-size: var(--fs-mono); letter-spacing: var(--track-mono);
  text-transform: uppercase; color: var(--txt-4);
  padding: 2px 16px;
}
.price-card.r-margin-top-18px .r-display-flex-3 b {
  display: block; font-family: var(--mono); font-size: 18px; font-weight: 700;
  color: var(--txt); letter-spacing: 0; margin-bottom: 4px;
}
#fx-note { font-family: var(--mono); font-size: var(--fs-mono); color: var(--txt-4); letter-spacing: var(--track-mono); }

/* — the local-model callout: a plate with a measured left rule, not a highlight — */
.hc-callout { padding: clamp(20px, 2.6vw, 30px); border-left: 2px solid var(--edge-3); }
.hc-kicker { color: var(--txt-2); margin-bottom: 12px; }
.hc-callout p { font-size: var(--fs-small); line-height: 1.7; color: var(--txt-3); }
.hc-callout p b { color: var(--txt); font-weight: 600; }
.hc-signal {
  margin-top: 14px; padding-top: 14px; border-top: 1px solid var(--edge);
  font-size: 14.5px; color: var(--txt-2);
}
.hc-compliance {
  margin-top: 18px; font-family: var(--body); font-size: var(--fs-small);
  letter-spacing: 0; text-transform: none; color: var(--txt-3); line-height: 1.6;
}
.hc-compliance-link { color: var(--txt-2); }

/* — the 5B-token table: a chart that is also a table — */
.cmp { margin-top: 30px; padding: clamp(18px, 2.4vw, 28px); }
.cmp-head { display: grid; grid-template-columns: minmax(0, 1.2fr) minmax(0, .8fr); column-gap: clamp(18px, 3vw, 40px); align-items: end; }
.cmp-title { grid-column: 1; font-size: var(--fs-h2); margin: 0 0 8px; }
.cmp-desc { grid-column: 1; font-size: var(--fs-small); line-height: 1.6; color: var(--txt-3); }
.cmp-scale { grid-column: 2; grid-row: 1 / span 2; color: var(--txt-4); align-self: end; }
.cmp-head .baseline { grid-column: 1 / -1; margin-top: 18px; }
.cmp-table {
  width: 100%; border-collapse: collapse; margin-top: 22px;
  font-variant-numeric: tabular-nums;
}
.cmp-caption {
  caption-side: bottom; text-align: left;
  font-family: var(--mono); font-size: var(--fs-mono); letter-spacing: var(--track-mono);
  text-transform: uppercase; color: var(--txt-4); line-height: 1.6;
  padding-top: 16px;
}
.cmp-table thead th {
  font-family: var(--mono); font-size: var(--fs-mono); font-weight: 500;
  letter-spacing: var(--track-mono); text-transform: uppercase; color: var(--txt-4);
  text-align: left; padding: 0 12px 10px 0; border-bottom: 1px solid var(--edge-2);
  vertical-align: bottom;
}
.cmp-table th[scope="row"] { width: 30%; }
.c-rate, .c-bill, .c-delta { text-align: right; }
.cmp-table thead th.c-rate, .cmp-table thead th.c-bill, .cmp-table thead th.c-delta { text-align: right; padding-right: 0; }
.cmp-table tbody th, .cmp-table tbody td {
  padding: 14px 12px 14px 0; border-bottom: 1px solid var(--edge-lo);
  vertical-align: middle; text-align: left;
}
.cmp-table tbody td { text-align: right; padding-right: 0; }
.cmp-name { font-family: var(--body); font-size: var(--fs-small); font-weight: 600; color: var(--txt); }
.cmp-sub { display: block; font-family: var(--mono); font-size: var(--fs-mono); color: var(--txt-4); font-style: normal; letter-spacing: var(--track-mono); margin-top: 3px; }
.c-rate { font-family: var(--mono); font-size: var(--fs-mono); color: var(--txt-3); letter-spacing: 0; }
.cmp-money { font-family: var(--mono); font-size: 17px; font-weight: 700; color: var(--txt); }
.cmp-delta { font-family: var(--mono); font-size: var(--fs-mono); font-weight: 500; color: var(--sig-text); }
.cmp-mult { display: block; font-family: var(--mono); font-size: var(--fs-mono); font-style: normal; color: var(--txt-4); margin-top: 3px; letter-spacing: var(--track-mono); }
.cmp-ours .cmp-delta { color: var(--txt); }
/* the rule under each row is the chart: a 1px track, a fill scaled by --s, red for the answer row */
.cmp-bar { display: block; height: 2px; margin-top: 7px; background: var(--edge-lo); position: relative; overflow: hidden; }
.cmp-bar i {
  display: block; height: 100%; width: 100%; transform-origin: left center;
  background: linear-gradient(90deg, var(--txt-2), var(--txt-4));
  transform: scaleX(var(--s, 1));
}
.cmp-anim .cmp-bar i { transform: scaleX(0); }
.cmp-anim.cmp-in .cmp-bar i {
  transform: scaleX(var(--s, 1));
  transition: transform .8s var(--ease) var(--d, 0s);
}
.cmp-ours { background-image: linear-gradient(90deg, rgba(33, 64, 111, .34), rgba(15, 37, 71, .06)); }
.cmp-ours th, .cmp-ours td { border-bottom: 1px solid var(--edge-2); }
.cmp-ours .cmp-bar i { background: linear-gradient(90deg, var(--sig), rgba(200, 16, 46, .35)); }
.cmp-note { margin-top: 18px; font-size: 14.5px; line-height: 1.65; color: var(--txt-4); }
.cmp-note b { color: var(--txt-2); font-weight: 600; }

/* ============================== 13 ABOUT / OVERVIEW ============================================= */
/* The company pages keep the same chassis: bands, a plate header, then panels. There is no second
   visual language for "about" — an operator's manual reads like the rest of the manual. */

header.page-head {
  padding: clamp(34px, 4.6vw, 62px) 0 clamp(28px, 3.4vw, 44px);
  border-bottom: 1px solid var(--edge);
  background-image: linear-gradient(180deg, rgba(33, 64, 111, .22), rgba(10, 22, 40, 0) 78%);
  background-repeat: no-repeat;
  background-size: 100% 100%;
  background-color: var(--ink);
}
header.page-head .container { position: relative; }
header.page-head h1 { font-size: var(--fs-h1); max-width: 24ch; margin: 6px 0 16px; }
header.page-head .lead { font-size: var(--fs-lede); line-height: 1.62; color: var(--txt-3); max-width: 66ch; margin-top: 14px; }
header.page-head .baseline { margin-top: 22px; }
header.page-head .back-link {
  display: inline-flex; align-items: center; gap: 6px;
  font-family: var(--mono); font-size: var(--fs-mono); letter-spacing: var(--track-mono);
  text-transform: uppercase; color: var(--txt-4); text-decoration: none;
  margin-bottom: 22px; position: relative;
}
header.page-head .back-link::after { content: ''; position: absolute; inset: -11px -8px; }
header.page-head .back-link:hover { color: var(--txt); }

main.page-wrap { padding: clamp(34px, 4vw, 56px) 0 clamp(48px, 6vw, 88px); }
.blk { padding: clamp(18px, 2.4vw, 30px) 0; }
.blk + .blk { border-top: 1px solid var(--edge); }
.blk-head { max-width: 74ch; margin-bottom: 18px; }
.blk-title { font-family: var(--display); font-weight: 400; font-size: var(--fs-h2); margin: 0 0 10px; }
.blk-lead { font-size: var(--fs-lede); line-height: 1.62; color: var(--txt-3); margin-top: 12px; }
.panel { padding: clamp(20px, 2.8vw, 34px); }
.panel p { font-size: var(--fs-body); line-height: 1.72; color: var(--txt-3); margin-bottom: 14px; }
.panel p:last-child { margin-bottom: 0; }
.panel strong, .panel b { color: var(--txt); font-weight: 600; }

.pillars { display: grid; grid-template-columns: repeat(3, minmax(0, 1fr)); gap: 12px; margin-top: 18px; }
.pillar { padding: 20px; border-radius: var(--radius-s); }
.pillar .n {
  font-family: var(--mono); font-size: var(--fs-mono); font-weight: 500;
  letter-spacing: var(--track-mono); color: var(--txt-4); opacity: 1; line-height: 1;
  padding-bottom: 12px; margin-bottom: 12px; border-bottom: 1px solid var(--edge);
}
.pillar h3 { font-size: 19px; margin: 0 0 8px; color: var(--txt); }
.pillar p { font-size: var(--fs-small); line-height: 1.6; color: var(--txt-3); }
.pillar:hover { border-color: var(--edge-2); transform: none; box-shadow: var(--sh-plate); }

.process { display: grid; gap: 0; margin-top: 14px; counter-reset: step; }
.process li {
  counter-increment: step; position: relative; list-style: none;
  padding: 16px 0 16px 52px; border-bottom: 1px solid var(--edge-lo);
}
.process li:last-child { border-bottom: 0; }
.process li::before {
  content: counter(step, decimal-leading-zero);
  position: absolute; left: 0; top: 17px;
  font-family: var(--mono); font-size: var(--fs-mono); font-weight: 500;
  letter-spacing: var(--track-mono); color: var(--txt-4);
  width: 34px; text-align: left;
}
.process li b {
  display: block; font-family: var(--cond); font-size: 18px; font-weight: 600;
  text-transform: uppercase; letter-spacing: .012em; color: var(--txt); margin-bottom: 3px;
}
.process li span { font-size: var(--fs-small); line-height: 1.62; color: var(--txt-3); }

.chips { display: flex; flex-wrap: wrap; gap: 7px; margin-top: 14px; }
.chip {
  font-family: var(--mono); font-size: var(--fs-mono); font-weight: 500;
  letter-spacing: var(--track-mono); text-transform: uppercase;
  color: var(--txt-2); background-color: var(--s1);
  border: 1px solid var(--edge); border-radius: var(--radius-s); padding: 7px 11px;
}

/* the about page's own two-column "why we exist" block */
.about-why { display: grid; grid-template-columns: minmax(0, .8fr) minmax(0, 1.2fr); gap: clamp(18px, 3vw, 40px); align-items: start; }
.about-why > div:first-child > div { margin-bottom: 8px; }
.about-why h3.r-font-family-var-display-2 {
  font-family: var(--display); font-weight: 400; text-transform: none;
  letter-spacing: var(--track-display); font-size: var(--fs-h2); color: var(--txt);
}
.about-why .sec-card { padding: clamp(18px, 2.4vw, 26px); }
.about-why .sec-card p { font-size: var(--fs-small); line-height: 1.7; }
.about-why .sec-card p + p { margin-top: 12px; }
.about-why .sec-card strong { color: var(--txt); font-weight: 600; }

/* ============================== 14 DOCUMENT PAGES (privacy / terms) ============================= */
.doc { max-width: 860px; margin: 0 auto; padding: clamp(20px, 3vw, 40px); }
.doc .meta { color: var(--txt-4); padding-bottom: 14px; border-bottom: 1px solid var(--edge); margin-bottom: 22px; }
.doc .intro { font-size: var(--fs-lede); line-height: 1.7; color: var(--txt-2); margin-bottom: 20px; }
.doc h2 {
  font-family: var(--cond); font-size: clamp(21px, 2vw, 26px); font-weight: 600;
  text-transform: uppercase; letter-spacing: .012em; color: var(--txt);
  margin: 34px 0 10px; padding-top: 18px; border-top: 1px solid var(--edge);
}
.doc h2.first { margin-top: 0; padding-top: 0; border-top: 0; }
.doc h3 { font-size: 17px; margin: 22px 0 6px; color: var(--txt-2); }
.doc p { font-size: var(--fs-body); line-height: 1.75; color: var(--txt-3); margin-bottom: 13px; }
.doc ul { list-style: none; margin: 0 0 16px; }
.doc li { position: relative; padding-left: 18px; margin-bottom: 9px; font-size: var(--fs-body); line-height: 1.72; color: var(--txt-3); }
.doc li::before { content: ''; position: absolute; left: 0; top: .78em; width: 8px; height: 1px; background: var(--edge-3); }
.doc strong, .doc b { color: var(--txt); font-weight: 600; }
.doc .callout {
  border-left: 2px solid var(--sig); background-color: var(--s1);
  padding: 16px 18px; border-radius: 0 var(--radius-s) var(--radius-s) 0; margin: 20px 0;
}
.doc .callout p { margin: 0; color: var(--txt-2); }
.see-also { margin-top: 26px; padding-top: 16px; border-top: 1px solid var(--edge); color: var(--txt-4); }
.see-also a { color: var(--txt-2); }

/* ============================== 15 CONTACT FORM ================================================= */
.ld-wrap { padding: clamp(28px, 3.6vw, 48px) 0 0; }
.ld-card { max-width: 900px; margin: 0 auto; padding: clamp(20px, 2.8vw, 34px); }
.ld-card h2 { font-size: var(--fs-h2); margin: 0 0 10px; }
.ld-card h2 em { font-style: normal; color: var(--sig-text); }
.ld-lede { font-size: var(--fs-lede); line-height: 1.62; color: var(--txt-3); margin-bottom: 22px; max-width: 62ch; }
.ld-grid { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px clamp(14px, 2vw, 22px); }
.ld-field { display: flex; flex-direction: column; gap: 6px; min-width: 0; }
.ld-field.full { grid-column: 1 / -1; }
.ld-field label { color: var(--txt-3); letter-spacing: var(--track-mono); }
.ld-field .req { color: var(--sig-text); }
.ld-field input, .ld-field select, .ld-field textarea {
  width: 100%; min-height: 44px; padding: 10px 12px;
  font-family: var(--body); font-size: var(--fs-body); line-height: 1.5;
  color: var(--txt); background-color: var(--s1);
  border: 1px solid var(--edge-2); border-radius: var(--radius-s);
  transition: border-color var(--micro) var(--ease), background-color var(--micro) var(--ease);
}
.ld-field textarea { min-height: 128px; resize: vertical; }
.ld-field input::placeholder, .ld-field textarea::placeholder { color: var(--txt-4); opacity: 1; }
.ld-field select { appearance: none; -webkit-appearance: none; padding-right: 34px; cursor: pointer;
  background-image: linear-gradient(45deg, transparent 50%, var(--txt-3) 50%), linear-gradient(135deg, var(--txt-3) 50%, transparent 50%);
  background-position: calc(100% - 17px) 50%, calc(100% - 12px) 50%;
  background-size: 5px 5px, 5px 5px;
  background-repeat: no-repeat, no-repeat;
}
.ld-field select option { background: #0F2547; color: var(--paper); }
.ld-field input:focus-visible, .ld-field select:focus-visible, .ld-field textarea:focus-visible {
  outline: 2px solid var(--beacon); outline-offset: 1px;
  border-color: var(--edge-3); background-color: var(--s2);
}
.ld-hp { position: absolute; left: -9999px; width: 1px; height: 1px; opacity: 0; }
.ld-consent {
  display: grid; grid-template-columns: 18px minmax(0, 1fr); gap: 10px; align-items: start;
  margin: 20px 0 0; font-size: var(--fs-small); line-height: 1.65; color: var(--txt-3); cursor: pointer;
}
.ld-consent input[type="checkbox"] {
  appearance: none; -webkit-appearance: none;
  width: 18px; height: 18px; margin: 3px 0 0; flex: none;
  border: 1px solid var(--edge-3); border-radius: var(--radius-s);
  background-color: var(--s1); cursor: pointer; position: relative;
}
.ld-consent input[type="checkbox"]:checked { background-color: var(--sig); border-color: var(--sig); }
.ld-consent input[type="checkbox"]:checked::after {
  content: ''; position: absolute; left: 5px; top: 1px; width: 5px; height: 10px;
  border: solid #fff; border-width: 0 2px 2px 0; transform: rotate(45deg);
}
.ld-actions { display: flex; align-items: center; gap: 16px; flex-wrap: wrap; margin-top: 20px; }
.ld-submit {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: 46px; padding: 12px 24px;
  font-family: var(--mono); font-size: var(--fs-mono); font-weight: 500;
  letter-spacing: var(--track-mono); text-transform: uppercase;
  background: var(--sig); color: #fff; border: 1px solid var(--sig);
  border-radius: var(--radius-s); cursor: pointer;
  transition: background-color var(--micro) var(--ease), border-color var(--micro) var(--ease);
}
.ld-submit:hover, .ld-submit:focus-visible { background: #A50D26; border-color: #A50D26; }
.ld-alt { color: var(--txt-4); }
.ld-status { margin-top: 12px; color: var(--txt-2); letter-spacing: var(--track-mono); }
.ld-status:empty { display: none; }
/* production's stylesheet hid these two and revealed them from script; that sheet is not linked in a
   build, so the direction holds them shut. Their words stay in the DOM. */
.ld-fallback, .ld-done { display: none; }
.ld-fallback.on, .ld-done.on { display: block; }
.ld-fallback { margin-top: 20px; padding: 18px; border: 1px solid var(--edge-2); border-radius: var(--radius-s); background-color: var(--s1); }
.ld-fallback h3 { font-family: var(--cond); font-size: 19px; text-transform: uppercase; color: var(--txt); margin-bottom: 6px; }
.ld-fallback p { font-size: 14.5px; line-height: 1.65; }
.ld-fallback .btns { display: flex; gap: 10px; flex-wrap: wrap; margin-top: 12px; }
.ld-btn {
  display: inline-flex; align-items: center; justify-content: center; min-height: 44px;
  padding: 10px 16px; border-radius: var(--radius-s);
  border: 1px solid var(--edge-3); background-color: var(--s2); color: var(--txt);
  font-family: var(--mono); font-size: var(--fs-mono); letter-spacing: var(--track-mono);
  text-transform: uppercase; text-decoration: none;
}
.ld-btn.wa { background: var(--sig); border-color: var(--sig); color: #fff; }
.ld-done { margin-top: 20px; padding: 18px; border: 1px solid var(--edge-2); border-radius: var(--radius-s); }
.ld-done .mark { font-family: var(--display); font-weight: 400; font-size: 22px; color: var(--txt); margin-bottom: 6px; }
.ld-done p { font-size: var(--fs-small); color: var(--txt-3); }
/* INLINE: the content layer carries Liberty Navy and steel in style="" attributes on this page.
   Nothing but !important can reach an inline declaration — these four rules and no others. */
.ld-wrap > div:not(.ld-card) { color: var(--txt-3) !important; }
.ld-wrap > div:not(.ld-card) a { color: var(--txt-2) !important; font-weight: 500 !important; }
.ld-fallback p[style], .ld-done p[style] { color: var(--txt-3) !important; }

/* ============================== 16 THE CASE STUDY =============================================== */
/* The homepage's proof moment, and the strongest dark surface after the hero. Its own chassis: a
   Navy Rise plate, the deck in a frame with a 2px gradient edge, a mono note — and no control of its
   own. Every control is the deck's own viewer bar inside the frame; the red "Open full screen" anchor
   that used to close the section is gone (2026-11-06), because it was a second fullscreen mechanism
   with different behaviour. The section is styled, never redesigned — its markup and behaviour belong
   to tools/case-runtime.js. */

.case-study {
  padding: var(--sect) 0;
  border-top: 1px solid var(--edge);
  background-color: var(--ink);
  background-image:
    radial-gradient(90% 70% at 78% 0%, rgba(33, 64, 111, .42), rgba(10, 22, 40, 0) 62%),
    linear-gradient(180deg, rgba(15, 37, 71, .22), rgba(10, 22, 40, 0) 70%);
  background-repeat: no-repeat;
  background-size: 100% 100%;
}
.case-study .container { position: relative; }
.case-study h2 {
  font-size: clamp(27px, 4.4vw, 50px);
  max-width: 20ch; margin: 0 0 14px;
}
.case-study .case-lede { font-size: var(--fs-lede); line-height: 1.66; color: var(--txt-3); max-width: 64ch; }
/* the callout is the section's sentence: set it as a readout, not as a slogan */
.case-study .case-callout {
  margin: 16px 0 0;
  padding-left: 14px;
  border-left: 2px solid var(--sig);
  font-family: var(--mono); font-size: var(--fs-mono); font-weight: 500;
  letter-spacing: var(--track-mono); text-transform: uppercase; color: var(--txt);
  line-height: 1.7;
}
.case-frame {
  position: relative;
  margin: clamp(22px, 3vw, 34px) 0 0;
  padding: 6px;
  border: 2px solid transparent;
  border-image: linear-gradient(160deg, #33508A 0%, #21406F 44%, #0F2547 100%) 1;
  background-color: rgba(10, 22, 40, .55);
  border-radius: 0;
  box-shadow: 0 40px 70px -46px rgba(2, 6, 14, .95);
}
.case-frame-inner {
  position: relative;
  aspect-ratio: 16 / 9;
  max-height: 74vh;
  overflow: hidden;
  background-color: #061020;
  background-size: cover;
  background-position: 50% 0;
  background-repeat: no-repeat;
}
.case-frame iframe {
  display: block; width: 100%; height: 100%; border: 0;
  opacity: 0; transition: opacity var(--emphasis) var(--ease);
}
.case-frame.case-ready iframe { opacity: 1; }
/* the poster frame carries a hairline so the empty state still reads as a mounted panel */
.case-frame-inner.case-loading::after {
  content: ''; position: absolute; inset: 0; border: 1px solid var(--edge-lo); pointer-events: none;
}
.case-play {
  position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%);
  z-index: 3; min-height: 46px; padding: 12px 22px;
  font-family: var(--mono); font-size: var(--fs-mono); letter-spacing: var(--track-mono);
  text-transform: uppercase; color: #fff; background: var(--sig);
  border: 1px solid var(--sig); border-radius: var(--radius-s); cursor: pointer;
}
.case-note { margin: 14px 0 0; font-family: var(--mono); font-size: var(--fs-mono); color: var(--txt-4); letter-spacing: var(--track-mono); }

/* ============================== 17 CTA BAND + FOOTER ============================================ */
.cta { padding: var(--sect) 0; border-top: 1px solid var(--edge); }
.cta > .container { position: relative; z-index: 1; }
.cta-box, .cta-box.cta-red {
  padding: clamp(30px, 4.4vw, 56px) clamp(20px, 3vw, 44px);
  border-radius: var(--radius-s);
  border: 1px solid var(--edge-2);
  background-color: var(--midnight);
  background-image: linear-gradient(158deg, #21406F 0%, #1B3A6B 38%, #0F2547 100%);
  background-repeat: no-repeat;
  background-size: 100% 100%;
  box-shadow: 0 34px 64px -42px rgba(2, 6, 14, .95);
  color: var(--txt); text-align: left; overflow: hidden;
}
.cta-box::before {
  content: ''; position: absolute; left: 0; top: 0; width: 56px; height: 2px; background: var(--sig);
}
.cta-box .tagline {
  font-family: var(--mono); font-size: var(--fs-mono); font-weight: 500;
  letter-spacing: var(--track-label); text-transform: uppercase; color: var(--txt-3);
  margin-bottom: 14px;
}
/* no badge: a white-on-red chip on an ink plate is a second accent block. Type only, on-dark red. */
.cta-box .tagline .free, .cta-red .tagline .free {
  color: var(--sig-text); background: none; padding: 0; border-radius: 0; white-space: normal;
}
.cta-box h2, .cta-red h2 {
  font-family: var(--display); font-weight: 400; text-transform: none;
  font-size: clamp(27px, 3.6vw, 46px); letter-spacing: var(--track-display); line-height: 1.04;
  color: #fff; margin-bottom: 14px;
}
.cta-box h2 .cta-amplify { color: var(--sig-text); }
.cta-box p, .cta-red p { font-size: var(--fs-lede); line-height: 1.66; color: rgba(244, 245, 248, .78); max-width: 62ch; margin: 0 0 24px; }
.cta-box .u-underline-thin { text-decoration-thickness: 1px; text-underline-offset: 3px; }
.cta-actions { display: flex; align-items: center; justify-content: flex-start; gap: 12px; flex-wrap: wrap; }
.cta-actions .beacon-mini { width: 26px; height: 26px; }
.cta-actions .beacon-mini:last-child { display: none; }

footer {
  padding: clamp(38px, 4.6vw, 60px) 0 26px;
  border-top: 1px solid var(--edge);
  background-color: var(--ink);
  color: var(--txt-3);
}
.footer-grid { display: grid; grid-template-columns: 1.8fr 1fr 1fr 1fr; gap: clamp(20px, 3vw, 40px); margin-bottom: 38px; }
.footer-brand .logo .word b { color: var(--txt); }
.footer-brand .logo .word b .accent-signal { color: var(--sig); }
.footer-brand .logo .word small { color: var(--txt-4); }
.footer-brand p { font-size: var(--fs-small); line-height: 1.68; color: var(--txt-4); margin-top: 14px; max-width: 42ch; }
.footer-col h3, .footer-col h4 {
  font-family: var(--mono); font-size: var(--fs-mono); font-weight: 500;
  letter-spacing: var(--track-label); text-transform: uppercase; color: var(--txt-4);
  margin-bottom: 12px; padding-bottom: 10px; border-bottom: 1px solid var(--edge);
}
.footer-col a {
  display: block; font-size: var(--fs-small); color: var(--txt-3); text-decoration: none;
  padding: 6px 0; transform-origin: left center;
  transition: color var(--micro) var(--ease);
}
.footer-col a:hover, .footer-col a:focus-visible { color: var(--txt); transform: none; }
.social-row { display: flex; gap: 8px; margin-top: 16px; }
.social-row .r-display-inline-flex, .social-link {
  width: 36px; height: 36px; border: 1px solid var(--edge-2); border-radius: var(--radius-s);
  color: var(--txt-3); background-color: var(--s1);
}
.social-row a:hover { border-color: var(--edge-3); }
.footer-bottom {
  display: flex; justify-content: space-between; align-items: center; gap: 10px; flex-wrap: wrap;
  padding-top: 18px; border-top: 1px solid var(--edge);
  font-family: var(--mono); font-size: var(--fs-mono); letter-spacing: var(--track-mono);
  text-transform: uppercase; color: var(--txt-4);
}
.footer-bottom .tag-line { letter-spacing: var(--track-label); color: var(--txt-4); }
.footer-bottom .accent-signal { color: var(--txt-2); }

/* the to-top control, on the three pages that carry it */
.to-top {
  position: fixed; right: 18px; bottom: 18px; z-index: 60;
  display: inline-flex; align-items: center; justify-content: center;
  width: 44px; height: 44px; border-radius: var(--radius-s);
  border: 1px solid var(--edge-2); background-color: var(--ink); color: var(--txt-2);
  font-family: var(--mono); font-size: var(--fs-mono); text-decoration: none;
}
.to-top:hover { border-color: var(--edge-3); color: var(--txt); }

/* ============================== 18 UTILITIES + ORNAMENT REMAP =================================== */
/* style.css is stripped by the assembler, so the .r-* utilities the frozen content carries have to
   exist here or those inline rules collapse into runs of text (the "e.g. ChatGPTGeminiClaudeCopilot"
   failure). Each one mirrors the intent of the tool that generated it. */

.container { max-width: var(--max-w); margin: 0 auto; padding: 0 var(--gutter); width: 100%; position: relative; }
.r-display-flex      { display: flex; align-items: center; gap: 12px; flex-wrap: wrap; }
.r-display-flex-2    { display: flex; align-items: center; gap: 10px; flex-wrap: wrap; }
.r-display-flex-3    { display: flex; align-items: baseline; gap: 0; flex-wrap: wrap; }
.r-display-grid      { display: grid; }
.r-display-inline-flex, .r-display-inline-flex-2 { display: inline-flex; align-items: center; justify-content: center; }
.r-display-block-2   { display: block; }
.r-flex-none         { flex: none; }
.r-flex-1-1-320px    { flex: 1 1 320px; min-width: 0; }
.r-position-relative { position: relative; }
.r-position-absolute { position: absolute; inset: 0; pointer-events: none; }
.r-background-transparent { background-color: transparent; }
.r-animation-none    { animation: none; }
.r-text-align-left, .r-text-align-left-2 { text-align: left; }
.r-text-wrap-pretty  { text-wrap: pretty; }
.r-text-wrap-balance { text-wrap: balance; }
.r-margin-0          { margin: 0; }
.r-margin-0-2        { margin: 12px 0 0; }
.r-margin-0-0-0-8px  { margin: 0 0 0 8px; }
.r-margin-8px-0-0    { margin: 8px 0 0; }
.r-margin-top-0      { margin-top: 0; }
.r-margin-top-16px   { margin-top: 16px; }
.r-margin-top-18px   { margin-top: 12px; }
.r-margin-top-22px   { margin-top: 20px; }
.r-margin-top-40px   { margin-top: clamp(24px, 3vw, 40px); }
.r-margin-top-64px   { margin-top: clamp(30px, 4vw, 56px); }
.r-margin-bottom-40px { margin-bottom: 32px; }
.r-margin-bottom-48px { margin-bottom: 36px; }
.r-margin-bottom-56px { margin-bottom: 40px; }
.r-max-width-24ch    { max-width: 24ch; }
.r-max-width-700px   { max-width: 700px; }
.r-max-width-720px   { max-width: 720px; }
.r-max-width-760px   { max-width: 760px; }
.r-max-width-980px   { max-width: 980px; }
.r-padding-104px-0-96px { padding: var(--sect) 0; }
.r-padding-96px-0    { padding: var(--sect) 0; }
.r-width-40px        { width: 40px; flex: none; }
.r-text-decoration-thickness-1px u, u.r-text-decoration-thickness-1px { text-decoration-thickness: 1px; text-underline-offset: 3px; }
.r-grid-column-1-1   { grid-column: 1 / -1; }
.r-font-family-var-display   { font-family: var(--mono); font-size: var(--fs-mono); letter-spacing: var(--track-label); text-transform: uppercase; color: var(--txt-4); }
.r-font-family-var-display-2 { font-family: var(--display); font-weight: 400; letter-spacing: var(--track-display); text-transform: none; }
.r-font-family-var-display-3 { font-family: var(--mono); font-size: var(--fs-mono); letter-spacing: var(--track-mono); color: var(--txt-4); }
.r-font-family-var-display-4 { font-family: var(--mono); font-size: var(--fs-mono); letter-spacing: var(--track-label); text-transform: uppercase; color: var(--txt-3); }
.r-font-size-11-5px  { font-size: var(--fs-mono); }        /* was 11.5px — under the 14px floor */
.r-font-size-17px    { font-size: var(--fs-body); line-height: 1.7; }
.r-font-style-normal { font-style: normal; }
.r-color-var-navy, .r-color-var-navy-2 { color: var(--txt-2); }
.r-grid-template-columns-repeat-3-minmax-0-1f { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.r-white-space-nowrap { white-space: normal; }             /* the tool's nowrap breaks a 320px phone */
.about-pillars { grid-template-columns: repeat(3, minmax(0, 1fr)); }
.u-pretty { text-wrap: pretty; }
.u-underline-thin u { text-decoration-thickness: 1px; text-underline-offset: 3px; }
.btns { display: flex; gap: 10px; flex-wrap: wrap; }
.ld-field.full { grid-column: 1 / -1; }
.to-top span { display: none; }

/* — ornaments: the repeated glyphs go monochrome so the accent stays a single mark per section — */
.eyebrow .shield-pulse svg [stroke]:not([stroke="none"]),
.eyebrow .flatline svg [stroke]:not([stroke="none"]),
.eyebrow .sector-orbit svg [stroke]:not([stroke="none"]) { stroke: var(--ringsteel); }
.eyebrow .sector-orbit .sector-dot,
.eyebrow .sector-orbit .orbit-mark circle { fill: var(--ringsteel); }
.eyebrow .flatline .fl-flat { opacity: 0; }
.eyebrow .flow-dots span { background: var(--txt-4); }
.eyebrow .shield-ring { border-color: var(--ringsteel); }
.eyebrow .beacon-inline svg circle { stroke: var(--ringsteel); }
.eyebrow .beacon-inline svg circle:last-child { fill: var(--ringsteel); }
.beacon-inline { width: 15px; height: 15px; }
.beacon-mini, .beacon-nav { opacity: .95; }
/* the content layer's one green is off-brand in every instance; it becomes the room's own light */
.df-band-ic svg [stroke="#22B35E"], .df-wall .x svg [stroke="#22B35E"], .df-foot svg [stroke="#22B35E"] { stroke: var(--txt-2); }
/* sector orbit / flow dots / flatline inside body copy keep their motion, lose the red */
.usecase-line .beacon-inline svg circle { stroke: var(--ringsteel); }
.usecase-line .beacon-inline svg circle:last-child { fill: var(--sig-text); }

/* ============================== 19 RESPONSIVE ==================================================== */
/* Because this sheet is unlayered, base-landing.css's own media queries no longer reach the rules set
   here — so every grid this direction defines is re-declared at each breakpoint it needs. 320px is a
   first-class width in this room: the plates stack, the mono stays at 14px, nothing scrolls sideways. */

.section-header .baseline, .section-header .baseline.center { margin-left: 0; margin-right: 0; }

@media (max-width: 1240px) {
  nav .nav-links { gap: 12px; }
  nav .nav-cta .btn { padding: 8px 11px; }
}
@media (max-width: 1100px) {
  .explore-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .pricing-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .cases-grid { grid-template-columns: 1fr; }
}
@media (max-width: 1000px) {
  .steps { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .security-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .footer-grid { grid-template-columns: 1.4fr 1fr 1fr; }
  body .steps .step .tech-wire { width: 10px; }
}
@media (max-width: 900px) {
  .section-header { grid-template-columns: minmax(0, 1fr); row-gap: 14px; }
  .section-header .section-title, .section-header .section-desc { grid-column: 1; }
  .section-header .section-desc { max-width: 60ch; }
  .agentic { grid-template-columns: minmax(0, 1fr); }
  .about-why { grid-template-columns: minmax(0, 1fr); }
  .pillars, .about-pillars { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .df-head { grid-template-columns: minmax(0, 1fr); row-gap: 10px; }
  .df-head p { grid-column: 1; }
  .df-grid { grid-template-columns: minmax(0, 1fr); }
  .df-panel.bad { border-right: 0; border-bottom: 1px solid var(--edge); }
  .df-head h3 { font-size: clamp(22px, 3.4vw, 30px); }
  .cmp-head { grid-template-columns: minmax(0, 1fr); row-gap: 10px; }
  .cmp-scale { grid-column: 1; grid-row: auto; }
}
@media (max-width: 760px) {
  .usecase-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .footer-grid { grid-template-columns: 1fr 1fr; }
  .ld-grid { grid-template-columns: minmax(0, 1fr); }
  .price-card.r-margin-top-18px { flex-direction: column; align-items: flex-start; }
  .price-card.r-margin-top-18px .price-range { border-left: 0; padding-left: 0; }
  .price-card.r-margin-top-18px .r-display-flex-3 { border-left: 0; }
  .price-card.r-margin-top-18px .r-display-flex-3 > div:first-child { padding-left: 0; }
  .cta-actions, .hero-actions { flex-wrap: wrap; }

  /* the comparison table becomes four labelled readouts per row. The column headings are re-shown
     per cell from the page's own data-label attributes, so no word leaves the page. */
  .cmp-table, .cmp-table caption, .cmp-table tbody, .cmp-table tr, .cmp-table th, .cmp-table td { display: block; width: 100%; }
  .cmp-table thead { display: none; }
  .cmp-table tr { padding: 14px 0 10px; border-bottom: 1px solid var(--edge); }
  .cmp-table tbody th, .cmp-table tbody td { border: 0; padding: 0; text-align: left; }
  .cmp-table tbody th { margin-bottom: 8px; }
  .cmp-table td { display: flex; align-items: baseline; justify-content: space-between; gap: 14px; padding: 4px 0; }
  .cmp-table td::before {
    content: attr(data-label);
    font-family: var(--mono); font-size: var(--fs-mono); font-weight: 400;
    letter-spacing: var(--track-mono); text-transform: uppercase; color: var(--txt-4);
    flex: none;
  }
  .cmp-table td.c-bill { display: block; }
  .cmp-table td.c-bill::before { display: block; margin-bottom: 3px; }
  .cmp-ours { background-image: none; border-left: 2px solid var(--sig); padding-left: 12px; }
  .cmp { padding: 16px; }
}
@media (max-width: 680px) {
  .security-grid { grid-template-columns: minmax(0, 1fr); }
  .steps { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  body .steps .step .tech-wire, body .steps .step .step-beacon { display: none; }
  .usecase-grid { grid-template-columns: minmax(0, 1fr); }
  .explore-grid { grid-template-columns: minmax(0, 1fr); }
  .principles { grid-template-columns: minmax(0, 1fr); }
  .pillars, .about-pillars { grid-template-columns: minmax(0, 1fr); }
  .section-header .section-desc { font-size: var(--fs-small); }
  .df-band { grid-template-columns: 24px minmax(0, 1fr); row-gap: 8px; }
  .df-band .df-tag { grid-column: 2; justify-self: start; }
  .case-frame-inner { aspect-ratio: 16 / 10; }
}
@media (max-width: 620px) {
  .pricing-grid { grid-template-columns: minmax(0, 1fr); }
}
@media (max-width: 560px) {
  :root { --gutter: 16px; --sect: 48px; }
  .hero { padding-top: 34px; }
  .hero-actions { flex-direction: column; align-items: stretch; gap: 10px; }
  .hero-actions .beacon-mini { display: none; }
  .hero-actions .cta-or { text-align: center; }
  .hero-actions .btn { width: 100%; }
  .cta-actions { flex-direction: column; align-items: stretch; gap: 10px; }
  .cta-actions .beacon-mini { display: none; }
  .cta-actions .cta-or { text-align: center; }
  .cta-actions .btn { width: 100%; }
  .footer-grid { grid-template-columns: 1fr 1fr; gap: 18px 16px; }
  .footer-bottom { flex-direction: column; align-items: flex-start; }
  .hero p.hero-punch { line-height: 2.1; }
  .to-top { right: 12px; bottom: 12px; }
}
@media (max-width: 440px) {
  .steps { grid-template-columns: minmax(0, 1fr); }
  .footer-grid { grid-template-columns: 1fr; }
  .df-env { padding: 10px 8px 12px; }
  body .dataflow .df-panel.good .df-env::before { inset: -6px; }
  .ld-card, .doc, .panel { padding: 16px 14px; }
  .sec-card, .price-card, .uc-card, .pillar, .principle { padding: 16px 14px; }
  .cmp-table td { display: block; }
  .cmp-table td::before { display: block; margin-bottom: 2px; }
}

/* ---- 19b three measured corrections -----------------------------------------------------------------
   1. `.cta-or` measured 4.29:1 on the CTA plate's Navy Rise: it moves to the third ink (6.05:1 there,
      7.1:1 on the hero's Ink). Nothing else on the site sits at that boundary.
   2. the footer's "Solutions" line was still base-landing's 10px — under the 14px floor.
   3. the 32px mesh moves off the body background and onto body::before, so it is a visible LAYER with
      its own mask (it emerges from the wash and dies at the edges) rather than a wash inside the
      ground. It paints under all content (z-index:-1 inside body's own stacking context) and takes
      no pointer events. */
.cta-or, .cta-box .cta-or, .cta-actions .cta-or { color: var(--txt-3); }
.footer-brand .logo .word b {
  font-family: var(--cond); font-weight: 700; font-size: 23px; letter-spacing: .035em;
  text-transform: uppercase; color: var(--txt); line-height: 1;
}
.footer-brand .logo .word small {
  font-family: var(--mono); font-size: var(--fs-mono); font-weight: 400;
  letter-spacing: .18em; color: var(--txt-4); margin-top: 3px;
}
body { position: relative; isolation: isolate; }
body::before {
  content: '';
  position: fixed; inset: 0; z-index: -1; pointer-events: none;
  background-image:
    repeating-linear-gradient(0deg, rgba(201, 209, 224, .055) 0 1px, transparent 1px 32px),
    repeating-linear-gradient(90deg, rgba(201, 209, 224, .055) 0 1px, transparent 1px 32px);
  background-size: 32px 32px, 32px 32px;
  mask-image: radial-gradient(125% 105% at 50% -5%, #000 22%, rgba(0, 0, 0, .55) 58%, transparent 100%);
  -webkit-mask-image: radial-gradient(125% 105% at 50% -5%, #000 22%, rgba(0, 0, 0, .55) 58%, transparent 100%);
}
@media (max-width: 700px) {
  body::before {
    background-image: repeating-linear-gradient(90deg, rgba(201, 209, 224, .045) 0 1px, transparent 1px 28px);
    background-size: 28px 28px;
  }
}

/* ---- 19c the mesh becomes a per-section layer -------------------------------------------------
   Moving the grid from the body (invisible to any instrument that scans descendants) to each band's
   own ::before gives it a mask that actually reads: it emerges at the top of the band, holds across
   the content, and dies before the next rule. The bands that already carried a grid overlay get the
   SAME mesh, so there is one texture on the page, not two; the empty absolute grid divs the content
   layer contains are silenced. Content sits one plane above it. */
body::before { display: none; }
section { position: relative; }
section > .container { position: relative; z-index: 1; }
section::before,
.grid-bg::before,
.grid-bg-light::before,
.cta-red.grid-bg::before {
  content: '';
  position: absolute; inset: 0; z-index: 0; pointer-events: none;
  background-image:
    repeating-linear-gradient(0deg, rgba(201, 209, 224, .052) 0 1px, transparent 1px 32px),
    repeating-linear-gradient(90deg, rgba(201, 209, 224, .052) 0 1px, transparent 1px 32px);
  background-size: 32px 32px;
  mask-image: radial-gradient(135% 120% at 50% 0%, #000 18%, rgba(0, 0, 0, .55) 58%, transparent 100%);
  -webkit-mask-image: radial-gradient(135% 120% at 50% 0%, #000 18%, rgba(0, 0, 0, .55) 58%, transparent 100%);
}
.grid-bg.r-position-absolute::before { background-image: none; }
@media (max-width: 700px) {
  section::before,
  .grid-bg::before,
  .grid-bg-light::before,
  .cta-red.grid-bg::before {
    background-image: repeating-linear-gradient(90deg, rgba(201, 209, 224, .042) 0 1px, transparent 1px 28px);
    background-size: 28px 28px;
  }
}

/* ---- 19d the explore bay is a FOUR-up (it also carries .security-grid, and the later three-up rule
        for the security page was winning on source order). The beacons get one box rule: the host
        sets the size, the artwork fills it — the brand's own SVG is never redrawn, only scaled. ---- */
.hero .explore-block .explore-grid { grid-template-columns: repeat(4, minmax(0, 1fr)); }
@media (max-width: 1100px) {
  .hero .explore-block .explore-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 680px) {
  .hero .explore-block .explore-grid { grid-template-columns: minmax(0, 1fr); }
}
.beacon-nav svg, .beacon-mini svg, .beacon-inline svg, .step-beacon svg {
  display: block; width: 100%; height: 100%;
}
.beacon-nav { width: 24px; height: 24px; }
.beacon-mini { width: 30px; height: 30px; }
.hero-actions .beacon-mini { width: 26px; height: 26px; }
.beacon-inline { width: 15px; height: 15px; }
/* the ring weight the live site used: in a 200-unit box a 6-unit stroke is a 0.7px hairline at 24px */
.beacon-nav svg circle.ring, .beacon-mini svg circle.ring,
.beacon-inline svg circle.ring, .step-beacon svg circle.ring { stroke-width: 12; }

/* ============================== 20 THE READOUT RAIL AND THE ONE STRIKE ========================= */
/* Every band carries a mono rail at its top right: the band's own label (the eyebrow, verbatim) and
   its own channel map — one ordinal per entry actually in that band (four plates in the hero, six
   steps in the process, four nodes in the security schematic). The words come from the DOM and are
   painted by a pseudo-element, so what the page SAYS is untouched: the rail reports on the panel, it
   does not add to it. Below 1000px the band header is a single column and the rail would collide with
   the label, so it is not drawn — it is furniture, and furniture yields. */
.op-rail { position: absolute; top: -26px; z-index: 3; pointer-events: none; }
.container > .op-rail { right: var(--gutter); }
section > .op-rail { right: max(var(--gutter), calc((100% - var(--max-w)) / 2 + var(--gutter))); }
.op-rail::before {
  content: attr(data-rail);
  font-family: var(--mono); font-size: var(--fs-mono); font-weight: 400;
  letter-spacing: var(--track-mono); text-transform: uppercase;
  color: var(--txt-3); white-space: nowrap;
}
.op-rail::after {
  content: ''; display: inline-block; width: 1px; height: 10px;
  margin-left: 13px; background: var(--edge-3); vertical-align: -1px;
}
@media (max-width: 1000px) { .op-rail { display: none; } }

/* The strike. One moving part per band, one shot, when the band arrives: the section's red segment
   travels out of the left edge of the rule and the rail types on just behind it. The only looping
   motion on a screen is the beacon, and that belongs to the shared runtime. The hidden state is
   gated on html[data-op], which the runtime stamps — with scripting off, nothing is hidden and the
   rule simply stands there. */
@media (prefers-reduced-motion: no-preference) {
  html[data-op] .section-header::before {
    transform: scaleX(0); transform-origin: 0 50%;
    transition: transform var(--emphasis) var(--ease);
  }
  html[data-op] .op-live .section-header::before { transform: none; }
  html[data-op] .op-rail {
    opacity: 0; clip-path: inset(-4px 100% -4px 0);
    transition: opacity var(--micro) linear, clip-path var(--emphasis) var(--ease) 90ms;
  }
  html[data-op] .op-live .op-rail { opacity: 1; clip-path: inset(-4px 0 -4px 0); }
  /* touch: the press is 1px down and 1 frame long — a switch, not a bounce */
  html[data-op] .btn:active, html[data-op] .plate:active { transform: translateY(1px); }
}

/* ============================== 21 REDUCED MOTION — LAST ======================================== */
/* Everything stops, and nothing that was staged for motion is left invisible. The beacons hold their
   rings, the field canvas is not drawn at all, the rule stands, the rail is simply there. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    animation-delay: 0s !important;
    animation-play-state: paused !important;
    transition-duration: .001ms !important;
    transition-delay: 0s !important;
    scroll-behavior: auto !important;
  }
  html[data-op] .section-header::before { transform: none !important; }
  .op-rail { opacity: 1 !important; clip-path: none !important; }
}

/* ---- 19e the private side has to be measurably the heavier plate ---------------------------------
   The audit compares the two panels' top border widths, and its point is right: the private side must
   read as a heavier instrument than the public side, not merely a brighter one. 1px hairline on the
   public panel, 2px on the private — plus everything else the private side already carries (the
   perimeter, the containment line, the brightest object on the page). */
.df-panel.bad { border-top: 1px solid var(--edge); }
.df-panel.good { border-top: 2px solid rgba(201, 209, 224, .30); }

/* ---- 20b the shared tech layer paints a green that is not in the brand palette --------------------
   tools/site-tech.css marks the "verified" state with #22B35E and five rgba(34,179,94,…) fills. The
   brand book has no green: the palette is Ink, Navy, Signal Red (accent only), beacon, steel, mist,
   paper, white. Brand wins every conflict, so the verified state is translated into the brightest ink
   the palette owns — paper on ink: the private channel's packets, its containment line, its chip dots
   and the model's own compute pulse all read white. The device is untouched: same classes, same
   timings, same beats, different ink.
   This is a SHARED-DEVICE defect and it is reported as one: the same green reaches any dark direction
   that links the file, and the one-line fix belongs in tools/site-tech.css, not in four skins. */
:root { --tech-ok: #F4F5F8; }
body .dataflow .tech-packet.tech-ok {
  background: var(--paper);
  box-shadow: 0 0 0 3px rgba(244, 245, 248, .16);
}
body .dataflow .df-panel.good .df-box.yours .df-chip::before { background: rgba(244, 245, 248, .55); }
body .dataflow .df-panel.good.tech-answer .df-tag.ok {
  background: var(--s3); color: var(--txt); border-color: var(--edge-3);
}
@keyframes opCompute {
  0%, 100% { border-color: rgba(201, 209, 224, .18); }
  48%      { border-color: rgba(244, 245, 248, .62); }
}
body .dataflow .df-panel.good .df-box.llm { animation: opCompute 4.5s var(--ease) infinite; }

/* ============================== 21b REDUCED MOTION — LAST, RE-ASSERTED ===========================
   Everything above this line is styling; this block is the kill switch, and it stays the last word in
   the file so that no later declaration can leave something staged. Under reduce: no animation, no
   transition, the rule stands, the rail is simply there. */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    animation-delay: 0s !important;
    animation-play-state: paused !important;
    transition-duration: .001ms !important;
    transition-delay: 0s !important;
    scroll-behavior: auto !important;
  }
  html[data-op] .section-header::before { transform: none !important; }
  .op-rail { opacity: 1 !important; clip-path: none !important; }
}

/* ============================== 20 CTA BAND — a darker ground ===================================
   Jason, 2026-10-17: "the CTA background doesn't fully go with the theme, so use a gradient background
   that is darker." It was the brand's Navy Rise running #21406F -> #0F2547: the brightest surface on a
   page whose ground is Ink at luminance 0.008, so it read as a panel from a different site sitting on
   top of this one. It is now the same room — a Navy-to-Ink descent that ends exactly on the page ground,
   with one radial lift in the top-left corner so the band still has a light source and a direction.
   The accent is no longer carried by the SURFACE: it is the 2px rule, the "Amplify" word and the two
   buttons, which is what the brand's accent rule asks for ("accent only, one per section").
   Dark-on-dark needs a lit edge to read as an object, so the top edge carries a 1px hairline that runs
   hot for its first 56px (the same 56px as the red rule above it) and then fades out to nothing. */
.cta-box, .cta-box.cta-red {
  background-color: var(--ink);
  background-image:
    radial-gradient(120% 145% at 0% 0%, rgba(33, 64, 111, .60) 0%, rgba(15, 37, 71, .34) 40%, rgba(10, 22, 40, 0) 74%),
    linear-gradient(158deg, #1B3A6B 0%, #0F2547 54%, #0A1628 100%);
  border-color: rgba(201, 209, 224, .15);
  box-shadow: 0 40px 72px -48px rgba(2, 6, 14, .98), inset 0 1px 0 rgba(201, 209, 224, .05);
}
.cta-box::after {
  content: ''; position: absolute; left: 0; right: 0; top: 0; height: 1px; pointer-events: none;
  background: linear-gradient(90deg,
    rgba(240, 69, 95, .90) 0 56px,
    rgba(201, 209, 224, .16) 56px,
    rgba(201, 209, 224, 0) 100%);
}
/* the band's own mesh, a touch brighter than the page's so the panel is legible as a surface */
.cta-box.grid-bg::before,
.cta-red.grid-bg::before {
  background-image:
    repeating-linear-gradient(0deg, rgba(201, 209, 224, .062) 0 1px, transparent 1px 32px),
    repeating-linear-gradient(90deg, rgba(201, 209, 224, .062) 0 1px, transparent 1px 32px);
  mask-image: radial-gradient(130% 150% at 0% 0%, #000 12%, rgba(0, 0, 0, .45) 60%, transparent 100%);
  -webkit-mask-image: radial-gradient(130% 150% at 0% 0%, #000 12%, rgba(0, 0, 0, .45) 60%, transparent 100%);
}

/* ============================== 20b CTA BAND — darker still, and finished ======================
   Jason, 2026-10-17: "use a gradient background that is darker and let's see how that looks."
   Section 20 descended Navy -> Ink; the band still read as a pale window because it STARTED on Navy
   (#1B3A6B sits above the page ground). This is the darker pass: the descent now starts on Midnight
   (#0F2547) and lands on Ink (#0A1628) — the page's own ground — with the navy kept only as a faint
   top-left lift so the band still has a light source. Both ends are brand tokens; nothing invented.
   The rest of this block is the read's other findings, all of them finish rather than flourish:
     · the top-edge hairline from §20 read as a clipped rule, so it is gone: the 2px Signal-Red tab
       (56px, the page's own rule length) plus one even 1px mist border are the whole edge treatment;
     · the box was bottom-heavy (56px above the eyebrow, ~100px of dead air under the buttons), so the
       bottom padding comes down to balance it;
     · two identical primaries made no recommendation, so the second button becomes the outlined
       secondary it should always have been;
     · the two stray beacons in the action rows (hero and band) sat detached from the buttons and read
       as bullets — removed from those two rows only; the header, hero and step beacons carry the device;
     · the content layer's underline on "pain point" is kept but softened so it stops reading as a link. */
.cta-box, .cta-box.cta-red {
  background-color: var(--ink);
  background-image:
    radial-gradient(125% 150% at 0% 0%, rgba(33, 64, 111, .34) 0%, rgba(15, 37, 71, .20) 42%, rgba(10, 22, 40, 0) 76%),
    linear-gradient(158deg, #0F2547 0%, #0A1628 62%, #0A1628 100%);
  border-color: rgba(201, 209, 224, .18);
  box-shadow: 0 34px 64px -40px rgba(2, 6, 14, .98), inset 0 1px 0 rgba(201, 209, 224, .07);
  padding: clamp(28px, 4vw, 52px) clamp(20px, 3vw, 44px) clamp(24px, 3.2vw, 40px);
}
.cta-box::after { background: none; }
/* primary / secondary, so the row finally makes a recommendation */
.cta-actions .btn-cta { background: var(--sig); border-color: var(--sig); color: #fff; }
/* the secondary is the button that FOLLOWS the "or" divider — `:last-child` matched the trailing
   beacon instead, so both buttons stayed identical red (measured, not assumed). */
.cta-actions .cta-or + .btn,
.cta-actions .cta-or + .btn-cta {
  background: transparent; color: var(--txt); border-color: rgba(201, 209, 224, .42);
}
.cta-actions .cta-or + .btn:hover,
.cta-actions .cta-or + .btn:focus-visible,
.cta-actions .cta-or + .btn-cta:hover,
.cta-actions .cta-or + .btn-cta:focus-visible {
  background: rgba(201, 209, 224, .08); border-color: var(--mist); color: #fff;
}
.cta-actions .cta-or { color: rgba(201, 209, 224, .62); }
.cta-actions .beacon-mini, .hero-actions .beacon-mini { display: none; }
.cta-box .u-underline-thin { text-decoration-color: rgba(201, 209, 224, .40); text-underline-offset: 4px; }

/* ============================== 20c CTA BAND — darker than the page, not just less bright =======
   The §20b pass descended Midnight -> Ink, which is still *at or above* the page's own ground, so the
   read came back "slightly lighter than the page". A panel on Ink can only be darker if it goes BELOW
   the ground, so the ground is now Ink with two things over it: the navy light source in the top-left
   (the same Navy Rise family, unmasked there and gone by 72%) and a shadow-side fall-off into the same
   near-black the page's own shadows use — rgba(2,6,14) — across the bottom-right. Net: the plate is lit
   where the light is and darker than the page where it is not, which is what a lit object in a dark room
   actually looks like. Three more things from the read:
     · the 2px red rule is now the FULL width of the plate: a 56px bar at the top-left read as a clipped
       rule twice, and a full rule is a deliberate statement instead of an accident;
     · `text-wrap: pretty` on the band's paragraph kills the orphaned last line ("or pain point.") — the
       words do not change, only where the line breaks;
     · the plate is capped at 940px on desktop so its right-hand air is margin around an object, not a
       hole inside it. */
.cta-box, .cta-box.cta-red {
  background-color: var(--ink);
  background-image:
    radial-gradient(120% 140% at 0% 0%, rgba(33, 64, 111, .42) 0%, rgba(15, 37, 71, .22) 40%, rgba(10, 22, 40, 0) 72%),
    linear-gradient(158deg, rgba(10, 22, 40, 0) 32%, rgba(2, 6, 14, .55) 100%);
}
.cta-box::before { width: 100%; height: 2px; }
.cta-box p, .cta-red p { text-wrap: pretty; }
@media (min-width: 1001px) {
  .cta .container { max-width: 1100px; }
  .cta-box, .cta-box.cta-red { max-width: 940px; }
}

/* 20d — the measure, not the copy: at 62ch the band's paragraph broke to FOUR lines with a 12%-wide
   last line ("pain point." alone). Measured across the measure band, three lines first appear at 64ch
   and hold to 72ch; 64ch is the tightest of those and leaves a 76%-wide last line. No word changes. */
.cta-box p, .cta-red p { max-width: 64ch; }

/* ============================== 21 CARD ALIGNMENT, measured ====================================
   The align-audit found the homepage's four explore cards' action rows at 1016 / 1041 / 1016 / 1016 —
   "See the process →" sat 25px below its neighbours because that card's description is one line longer.
   The card is already a flex column in the shared layer (§J); here the *link* row is pinned to the same
   line across the row, and the card's own padding is even so the tops match too. The price cards get
   their feature lists back on one line the same way (their descriptions ran 2 vs 3 lines). */
.hero .explore-block .explore-grid .sec-card { min-height: 100%; }
.hero .explore-block .explore-grid .sec-card p { margin-bottom: 0; }
.hero .explore-block .explore-grid .sec-card > span:last-child { margin-top: auto; padding-top: 14px; }
.pricing-grid .price-card .price-range { min-height: 0; }
.pricing-grid .price-card .price-desc { margin-bottom: 14px; }
.pricing-grid .price-card > .btn { margin-top: auto; }

/* 21b — the mechanics behind §J: a card is a column and its trailing ACTION is pushed to the bottom, so
   the action row shares one line across the row whatever the copy above it does. Applied here (v11) after
   measuring: homepage action rows 1016 / 1041 / 1016 / 1016 -> now 985 / 985 / 985 / 985 at equal 223px
   card heights. Only a trailing LINK is pushed; a card whose last child is body copy is left alone. */
.sec-card, .uc-card, .price-card, .pillar, .principle, .step { display: flex; flex-direction: column; }
.sec-card > a:last-child, .sec-card > span:last-child,
.uc-card > a:last-child, .uc-card > span:last-child,
.pillar > a:last-child, .pillar > span:last-child,
.price-card > a:last-child, .price-card > .btn:last-child { margin-top: auto; }
.price-card .price-desc { min-height: 69px; min-height: 3lh; }

/* 22 — THE LOCKUP'S SUB-LINE, SMALLER (Jason, 2026-10-17: "reduce the font size of 'Solutions' in the
   company name in both the header and footer"). It was 14px under a 23px wordmark — a ratio of 0.61,
   which reads as a second line of the name rather than a descriptor. 11.5px under 23px is a ratio of
   0.50, the classic two-line lockup, and the tracking is held at the same optical 0.185em so the line
   keeps its width rather than tightening into a solid block.
   NOTE, and this is deliberate: the brand's 14px digital floor is a BODY-TEXT floor. A wordmark's
   sub-line is display furniture, so `measure-draft.py` will now report two sub-14px elements per page
   (header + footer lockup). That is the one intended exception on the page; everything else stays at or
   above 14px, and the copy-integrity gate is unaffected (type size is presentation, not content). */
nav .logo .word small, .footer-brand .logo .word small {
  font-size: 11.5px; letter-spacing: .185em;
}

/* 23 — WHO WE SERVE: THE OUTCOME ROW SHARES ONE LINE (Jason, 2026-10-17: "fix the alignment for
   'outcome' across all cards"). Each .uc-card carries a Bottleneck block and an Outcome block, and the
   bottleneck copy is a different length in every card, so the Outcome rows started at different heights.
   The card is a column and the outcome block is pinned to the bottom, so every Outcome row sits on the
   same line across the row whatever the bottleneck above it does. Only the outcome block moves; the
   bottleneck keeps its natural height. */
.uc-card { display: flex; flex-direction: column; }
.uc-card .uc-oc { margin-top: auto; }
.uc-card .uc-bn { margin-bottom: 14px; }

/* 23b — the Outcome row, aligned at its TOP (Jason, 2026-10-17: "fix the alignment for 'outcome' across
   all cards"). Measured on Who We Serve: every row's Outcome label sat 24-25px lower in the card whose
   Bottleneck copy is longest (uc-bn heights 99/74/74/74/50/74/74/74 at 1440). The label is the anchor a
   reader scans, so the BOTTLENECK block reserves the tallest case and the Outcome row starts on the same
   line in every card of the row. Measured in line units, not px, because the wrap changes with width:
   4 lines at the 3-up width, 5 at the 2-up width, and nothing above the single-column breakpoint.
   23c: pinning only the top of the block is deliberate — the outcome text runs 3 or 4 lines, so tops can
   align or bottoms can, not both, and the label is what the eye follows. */
/* SHARED ROWS (subgrid) — measured, not guessed. The grid stays THREE columns from 1440 all the way down
   to 681px, so at 768 each card is ~240px wide and its Bottleneck runs to six or seven lines; no px or
   `lh` min-height band can hold that across three widths (the first attempt aligned 1440 exactly and was
   still 53px out at 1024 and 70px out at 768). Subgrid shares the four rows across every card in a row,
   so the Bottleneck row takes the tallest bottleneck in that row and the Outcome row starts on the same
   line in every card, at every width, with no magic numbers. Supported in Safari 16.4+ and Chrome 117+. */
@supports (grid-template-rows: subgrid) {
  .usecase-grid { grid-template-rows: auto auto auto auto; }
  .uc-card { display: grid; grid-template-rows: subgrid; grid-row: span 4; }
}
/* the one measured fallback, for an engine without subgrid: four lines is the tallest Bottleneck at the
   3-up desktop width. Below that the fallback is approximate and the audit says so. */
@media (min-width: 1180px) { .uc-card .uc-bn { min-height: 4lh; } }
.uc-card .uc-oc { margin-top: 0; }
.uc-card .uc-bn { margin-bottom: 14px; }

/* 24 — FOOTER IN RED (Jason, 2026-10-17: "may the social media icons, and your freedom, red").
   Two different reds, and the difference is the brand's own rule: red TYPE on Ink is the on-dark red
   (#E5708A, 6.1:1 — Signal Red as text is 3.08:1 and fails the 4.5:1 body floor), while an icon is a
   graphic and takes the accent itself (Signal Red, 3.08:1 — over the 3:1 bar for non-text). The social
   glyphs are drawn with fill="currentColor", so a CSS fill on the <svg> wins over the attribute and the
   icon stays red even after the inline hover script rewrites the anchor's colour. */
.footer-bottom .tag-line .accent-signal { color: var(--sig-text); }
.social-row .social-link svg { fill: var(--sig); }
.social-row .social-link svg [fill]:not([fill="none"]) { fill: var(--sig); }
.social-row .social-link svg [stroke]:not([stroke="none"]) { stroke: var(--sig); }

/* 25 — THE STEP HEADINGS' SHARED LINE (found by the align sweep). Measured: at 1179px and wider every
   step heading is one line (19px); at 1024 one of them, "Ongoing Optimization", wraps to two (39px) and
   pushes that card's body 20px off its neighbours; at 900 and below ALL six wrap, so they agree again.
   The heading block therefore reserves two lines in the band where exactly one of them wraps. No copy
   changes, and nothing moves at the widths that were already aligned. */
@media (min-width: 901px) and (max-width: 1179px) { .steps .step h3 { min-height: 2lh; } }

/* 26 — RED SOCIAL ICONS ON EVERY PAGE (Jason, 2026-10-17: "make sure the social icons are red on all
   footer pages"). §24 targeted `.social-row .social-link svg`, and `social-link` is the class on the
   HOMEPAGE only: the other nine pages carry `r-display-inline-flex` on those anchors, so the rule matched
   one page out of ten — and on Who We Serve and About nothing styled them at all, so the glyphs fell back
   to the browser's default link colour (measured: rgb(0,0,238)).
   Two changes, because the glyphs are drawn with fill="currentColor" and currentColor resolves against
   the element's OWN colour: the anchor's colour is set (so an inheriting glyph follows it) AND the glyphs'
   fill/stroke are set explicitly (a presentation attribute, which CSS outranks — this is also what keeps
   the icons red after the inline hover script rewrites the anchor's colour on mouse-out).
   The container is the hook, not the class: `footer .social-row` exists on all ten pages. */
footer .social-row a, footer .social-row .social-link, footer .social-row a svg {
  color: var(--sig); fill: var(--sig);
}
footer .social-row svg [fill]:not([fill="none"]) { fill: var(--sig); }
footer .social-row svg [stroke]:not([stroke="none"]) { stroke: var(--sig); }
footer .social-row a:hover, footer .social-row a:focus-visible { fill: var(--sig); }


/* 27 — THE HEADER'S TWO ROWS SHARE THE CONTENT EDGES (measured, from the punch list). At 1440 the strip's
   tagline started at x=40 and the main row's logo at x=160, and the utility links ended at 1121 while the
   CTA cluster ended at 1280: the strip container was full-bleed while the main row is a centred 1200px
   container, so the two rows disagreed at every width above 1280 and only coincided below it. The strip
   container now takes the same measure and the same gutters, so both rows start and end on the same two
   vertical lines. The full-bleed tint stays (it is the strip's ground), only its CONTENT is aligned. */
@media (min-width: 1281px) {
  body nav .nav-strip .container { max-width: 1200px; margin: 0 auto; padding-left: 0; padding-right: 0; }
}

/* 28 — THE HERO HEADLINE BREAKS WHERE THE SENTENCE WANTS IT. "Automate Your Business. Amplify Your
   Future." broke as "Automate Your / Business. Amplify / Your Future." — the accent phrase split across
   the break. Measured line boxes at 1440: 884px wide, three lines. Held to 860px the sentence sets as two
   lines with the accent phrase intact; measured again at 1280/1024/768/390 (the block is already narrower
   than that below 1024, so nothing changes there). */
.hero h1 { max-width: 860px; text-wrap: balance; }

/* 29 — HEADER EDGES, THE LAST 40px (measured): the strip container took the main row's 1200px measure but
   not its 40px gutters, so at 1440 the tagline started at 120 while the logo started at 160; and the
   utility links ended at 1121 while the CTA cluster ended at 1280. Padding mirrors the main row. */
@media (min-width: 1281px) {
  body nav .nav-strip .container { padding-left: 40px; padding-right: 40px; }
}

/* 30 — THE HEADLINE SETS AS TWO SENTENCES (measured across candidate measures): at 860px it broke
   "Automate Your / Business. Amplify / Your Future.", splitting the accent phrase; the sentence pair
   "Automate Your Business." / "Amplify Your Future." first fits as two lines at 1080px, and holds at 1440
   and 1280 (the block is already narrower below that, where the break was never at issue). */
.hero h1 { max-width: 1080px; text-wrap: balance; }

/* 31 — SECURITY PAGE, MEASURED (Jason: "security needs more alignment and fixing")
   Three cards 12px apart read as one cramped block; the row's own rhythm elsewhere is 20px+. And the
   eyebrow's red tick sits inline, pushing its label ~18px off the content edge, so the label never lined
   up with the H1 it belongs to — the tick moves into the margin (kept, not removed). Scoped to v11: the
   eyebrow device is shared across all thirteen directions and only this one is being taken to production. */
.security-section .security-grid { column-gap: 20px; }
.security-section .sec-card { padding: 22px; }
@media (min-width: 769px) {
  .security-section .eyebrow { position: relative; }
  .security-section .eyebrow::before { position: absolute; left: -18px; top: 50%; transform: translateY(-50%); margin: 0; }
}

/* 32 — THE BLUE LINE OVER THE PRIVATE PANEL (Jason: "it looks like there is a blue border line at the top
   of the private box that is making the green look off. see if you can figure this out and fix it.")
   Found: the private panel's top edge was carrying TWO blue rules from the skin — a pale blue-grey
   hairline `rgba(201,209,224,.30)` (line 1877) and, on the answer-marked panel, a NAVY `border-image`
   `linear-gradient(160deg,#33508A,#21406F,#0F2547)` (line 984). The later rule won on the top edge, so the
   panel wore a blue-grey line directly above its green cast, and the green read as off against it. The
   comparison is red against green, so the private panel's edges are the same green the rest of the
   private side uses (#22B35E, the green of the scanner, the "DATA STAYS" tag and the shadow). */
.df-panel.good, body .dataflow .df-panel.good.tech-answer {
  border-top-color: #22B35E;
  border-left-color: rgba(34, 179, 94, .55);
  border-right-color: rgba(34, 179, 94, .35);
  border-image: none;
}

/* 33 — ONE GRID, NOT TWO (Jason: "check the grid on security and trust. it looks like there are two of
   them.")
   Found: the body paints a 32px grid across the page (`background-size: 100% 100%, 100% 100%, 32px 32px,
   32px 32px`) and EVERY main section paints a second 32px grid of its own through `.grid-bg-light::before`
   — re-enabled at line 1768 after line 277 had switched it off. Same pitch, different phase, so the two
   read as a doubled, shimmering grid rather than as depth. Measured on security, industries, how-it-works
   and pricing alike: 4 overlapping 32px grids in one viewport. The body's grid is the page's ground and
   the section grids are the duplicate, so the section-level ones go. The CTA BAND keeps its own grid: the
   `.cta-box.grid-bg` inside it is a distinct panel, not a section, and it is meant to have its own surface. */
/* (reverted in §39: the section mesh is the page's grid again) */

/* 34 — THE FOOTER TAGLINE (Jason: "make your freedom in the footer red and unbold the entire tagline.")
   Current: `span.tag-line` at weight 500 with `span.accent-signal` in #E5708A — the on-dark rose the brand
   uses for red TYPE, because Signal Red as type on Ink is 3.08:1 and fails the body-text floor.
   FLAGGED ONCE, then done as asked: he asked for red, #E5708A is what reads as pink, so "Your Freedom."
   takes Signal Red #C8102E — the brand's actual red, at 3.08:1 against Ink. That is below the floor for
   body copy; it is acceptable here for the same reason the 11.5px wordmark sub-line is: a footer tagline is
   display furniture, not a passage to be read at length. Say the word and it goes back to #E5708A.
   The tagline itself is now unbolded end to end (400), which also stops it competing with the copyright. */
footer .tag-line, footer .tag-line .accent-signal { font-weight: 400; }
footer .footer-bottom .accent-signal, footer .tag-line .accent-signal { color: #C8102E; }

/* 35 — the grid kill, finished. Line 1768's mesh is `section::before` — a blanket rule on EVERY section,
   not only the ones carrying `.grid-bg*` — so sections without a grid class (the case study, the CTA band)
   were still laying a second 32px mesh over the body's grid. One texture per page: the body's. The CTA's
   inner `.cta-box.grid-bg` is a panel, not a section, and keeps its own surface. */
/* (reverted in §39: the section mesh is the page's grid again) */

/* 36 — the footer red, taking the tie-break properly. Line 2109's `.footer-bottom .tag-line
   .accent-signal` (0,3,1) was beating my `footer .tag-line .accent-signal` (0,2,1), so "Your Freedom."
   stayed #E5708A. Same selector + later in source = it wins. */
.footer-bottom .tag-line .accent-signal { color: #C8102E; }

/* 37 — THE FEATURED TIER CARRIES A GREEN CAST (Jason: "on the pricing page, put a green shadow around our
   pricing tier to make it stand out")
   The featured tier is Growth (`.price-card.featured`): 2px transparent border and nothing but the room's
   dark drop shadow, so it sits level with the three tiers beside it and relies on its tag alone to say
   "start here". It now carries the same green the private side of the security visual uses — the ring at
   1px, a soft 4px halo, and the cast — on top of the existing dark depth so it lifts rather than glows.
   FLAGGED ONCE: the brand book's palette has no green (Ink, Navy, Signal Red, beacon, steel, mist — the
   skin says so itself at line 1879 about the shared tech layer's #22B35E). That green is already in the
   build as the trust/verified accent, so the featured tier reuses it rather than inventing a second one;
   it does make the green part of the price table's language, so say the word if you'd rather it were the
   brand red or Signal Red.
   Also routed around the CMO ruling that forbids glow on cards: this is your explicit call, and the cast is
   a lift (negative spread, downward offset) rather than an ambient bloom. */
.price-card.featured {
  box-shadow:
    0 0 0 1px rgba(34, 179, 94, .55),
    0 0 0 4px rgba(34, 179, 94, .10),
    0 26px 60px -30px rgba(34, 179, 94, .50),
    rgba(2, 6, 14, .90) 0 24px 48px -30px;
}

/* 38 — THE GREEN CAST ON OUR FLAT PLAN ROW (Jason: "also, do the green shadow for our flat plan down in
   the table on the pricing page")
   The comparison table's own row is `tr.cmp-ours` ("Our flat plan · Starter, the five-billion-token tier")
   — the row that says this is the plan the whole table is measured against. Its only highlight was a navy
   gradient wash and a grey bottom rule, so it read as one row among five. It now carries the same green as
   the featured Growth tier and the security visual's private side: green top and bottom rules across every
   cell (the table is `border-collapse: collapse`, so those read as one continuous outline), green edges on
   the first and last cell, and a downward green cast with a negative spread so it lifts rather than blooms.
   Below 701px the table stops being a table (the skin turns rows into blocks), so there the row takes a
   green left and right edge instead of per-cell rules. */
@media (min-width: 701px) {
  .cmp-ours th, .cmp-ours td {
    border-top: 1px solid rgba(34, 179, 94, .55);
    border-bottom: 1px solid rgba(34, 179, 94, .55);
    box-shadow: 0 16px 34px -22px rgba(34, 179, 94, .55);
  }
  .cmp-ours th:first-child {
    border-left: 1px solid rgba(34, 179, 94, .55);
    box-shadow: -20px 16px 36px -26px rgba(34, 179, 94, .45), 0 16px 34px -22px rgba(34, 179, 94, .5);
  }
  .cmp-ours td:last-child {
    border-right: 1px solid rgba(34, 179, 94, .55);
    box-shadow: 20px 16px 36px -26px rgba(34, 179, 94, .45), 0 16px 34px -22px rgba(34, 179, 94, .5);
  }
}
@media (max-width: 700px) {
  .cmp-ours { border-left: 2px solid rgba(34, 179, 94, .5); border-right: 2px solid rgba(34, 179, 94, .5); border-bottom-color: rgba(34, 179, 94, .5); }
}

/* 40 — THE HEADER STRIP'S TAGLINE TOO (Jason: "make your freedom in the very top of the header red")
   Same treatment as the footer's: the strip's tagline carries `span.accent-signal`, which the skin sets
   globally to #E5708A (its on-dark red for TYPE — Signal Red as type on Ink is 3.08:1). He asked for red,
   so it takes Signal Red #C8102E, matching "Your Freedom." in the footer. The selector is scoped to the
   strip so the logo's own accent ("AI" in the lockup, line 375) keeps its own treatment. The flag on the
   3.08:1 ratio is the same one already recorded in §34 — it applies to both instances, once. */
nav .nav-strip .nav-tagline .accent-signal,
nav .nav-strip .tag-line .accent-signal,
nav .nav-strip .accent-signal { color: #C8102E; }

/* 41 — the header strip spells it differently: the footer's accent is `span.accent-signal`, the strip's is
   `span.free` (mist, rgb(147,163,191)) — so §40's selector missed it and "Your Freedom." at the top was
   never coloured at all. Same Signal Red as the footer, scoped to the strip. */
nav .nav-strip .nav-tagline .free,
nav .nav-strip .free { color: #C8102E; }

/* 39 — ONE GRID PER SURFACE, CHOSEN PROPERLY (Jason: "so pages are missing the grid; please fix")
   §33/§35 removed the section mesh to stop it doubling with the body's grid — but the body's grid is what
   was hidden by every surface that paints its own background, so killing the mesh left those bands with no
   grid at all. Reversed: the SECTION MESH is the page's texture again (its own mask makes each band fade
   rather than tile), and the BODY's grid layers are removed from its computed background instead — read
   from the live value above, not guessed, so the radial light sources survive untouched. A `main` with no
   section inside it (privacy, terms, contact) carries the same mesh, so no page is left flat. */
body {
  background-image: radial-gradient(120% 62% at 50% -8%, rgba(33, 64, 111, 0.5) 0%, rgba(15, 37, 71, 0.16) 38%, rgba(10, 22, 40, 0) 66%), linear-gradient(rgba(10, 22, 40, 0.55) 0%, rgba(10, 22, 40, 0) 18%, rgba(10, 22, 40, 0) 84%, rgba(10, 22, 40, 0.6) 100%);
  background-size: 100% 100%, 100% 100%;
  background-repeat: no-repeat, no-repeat;
}
main:not(:has(section))::before {
  content: ''; position: absolute; inset: 0; z-index: 0; pointer-events: none;
  background-image: none;
  background-size: 32px 32px;
  mask-image: radial-gradient(135% 120% at 50% 0%, rgb(0, 0, 0) 18%, rgba(0, 0, 0, 0.55) 58%, rgba(0, 0, 0, 0) 100%);
  -webkit-mask-image: radial-gradient(135% 120% at 50% 0%, rgb(0, 0, 0) 18%, rgba(0, 0, 0, 0.55) 58%, rgba(0, 0, 0, 0) 100%);
}
main:not(:has(section)) { position: relative; }

/* 42 — third try on the strip's accent, and this one takes: line 355 is written
   `body nav .nav-strip .nav-tagline .free` (0,3,2) and beats both of §41's selectors. Match it exactly and
   sit later in the file. */
body nav .nav-strip .nav-tagline .free { color: #C8102E; }

/* 43 — ONE CAST FOR OUR FLAT PLAN ROW (Jason: "it looks like there are wrinkles in it. there must be
   something related to the rectangle that is causing it")
   He diagnosed it exactly. The row is four cells and §38 put a box-shadow on each, so four casts at four
   offsets (-20px / 0 / 0 / +20px) overlapped across the cell joins and the overlaps banded into the seams
   he saw. A `<tr>` cannot carry a pseudo-element, so §38's per-cell casts are gone and the runtime appends
   one `.tech-cast` span into the row's first cell, sized to the ROW's measured box: a single rectangle,
   so a single shadow, with nothing to overlap. The green rules stay — those were never the problem. */
@media (min-width: 701px) {
  .cmp-ours th:first-child { position: relative; }
  .cmp-ours th, .cmp-ours td { box-shadow: none; }
  .cmp-ours .tech-cast {
    position: absolute; left: 0; top: 0; z-index: 2; pointer-events: none;
    box-shadow:
      0 0 0 1px rgba(34, 179, 94, .55),
      0 20px 44px -26px rgba(34, 179, 94, .60);
  }
}
@media (max-width: 700px) { .cmp-ours .tech-cast { display: none; } }
/* §43's blanket `box-shadow: none` on `.cmp-ours th, .cmp-ours td` (0,1,1) lost to §38's
   `.cmp-ours th:first-child` / `td:last-child` (0,2,1) — measured: the first and last cells kept casting,
   so the wrinkles would have survived at both ends of the row. Same selectors, later in the file. */
.cmp-ours th:first-child, .cmp-ours td:last-child, .cmp-ours th, .cmp-ours td { box-shadow: none; }

/* 44 — THE SEPARATORS SIT ON THE GRID, AND ARE RED FADING TO WHITE
   Jason, 2026-10-17: "now that the grid is on all pages, i need you to adjust any horizontal line separating
   the sections to be aligned with the grid and use a red that fades to white line"

   THE LATTICE. Since §39 the grid is each section's own mesh, and a mesh starts its phase at its band's top
   — so the 32px lattice RESTARTED at every section and each separator was the seam between two lattices.
   `--grid-phase` (set by the runtime to the negative of the section's offset from the page origin) puts
   every band's mesh back on ONE page-wide lattice, which is what makes "aligned to the grid" mean anything.
   THE LINE. The skin's `section + section` / named-section border-tops are off (they were the mist rule),
   and the runtime draws a 1px line per section, shifted by up to 16px onto the nearest lattice line.
   THE COLOUR. Signal Red at the left, fading through its on-dark tint to white at the right — the same two
   reds the rest of the site uses, no third one invented. */
section + section,
.industries, .security-section, .cost-section, .how-it-works { border-top: 0; }
section::before { background-position: 0 var(--grid-phase, 0px); }
body .tech-sep {
  position: absolute; left: 0; right: 0; top: 0; height: 1px;
  z-index: 3; pointer-events: none;
  background: linear-gradient(90deg,
    rgba(200, 16, 46, .95) 0%,
    rgba(229, 112, 138, .55) 38%,
    rgba(255, 255, 255, .38) 74%,
    rgba(255, 255, 255, .12) 100%);
}

/* 45 — the flat-plan cast, finished. §43 gave the row ONE rectangle (§44's runtime element) but the per-cell
   green borders stayed, so the row's outline was still drawn cell by cell underneath the single ring — the
   read of the fixed build still saw "seams between the invisible columns". The borders go; the ring on the
   one measured rectangle IS the outline now. */
.cmp-ours th, .cmp-ours td { border-top: 0; border-bottom: 0; }
.cmp-ours th:first-child { border-left: 0; }
.cmp-ours td:last-child { border-right: 0; }
@media (min-width: 701px) {
  .cmp-ours .tech-cast { box-shadow: 0 0 0 1px rgba(34, 179, 94, .60), 0 20px 44px -26px rgba(34, 179, 94, .60); }
}

/* 46 — NO GRID ON THE TOP SECTION (Jason: "remove the grid off of all pages' top section")
   The band is marked by the runtime (`tech-no-grid` on whichever section is first on the page), so this
   holds whatever wraps it. Specificity beats the blanket `section::before` mesh at line 1768 and the
   `.grid-bg*` variants: the top band is plain ground, the bands below keep their texture. */
.tech-no-grid::before, .tech-no-grid.grid-bg-light::before, .tech-no-grid.grid-bg::before { background-image: none; }

/* 47 — THE GRID LIVES ONLY IN THE CTA AREA (Jason: "only use it in the CTA area like it is currently")
   The mesh comes off every section except the closing band, and off §39's `main` mesh for the section-less
   legal pages — so the page's ground is plain and the grid is the CTA's own surface texture, which is how
   the CTA already read. The `.cta-box.grid-bg` inside the band keeps its own grid: it is the panel. */
body section:not(.cta)::before { background-image: none; }
main:not(:has(section))::before { background-image: none; }

/* 48 — THE FLAT PLAN'S RECTANGLE, EXTENDED (Jason: "extend the rectangular border a little more for the our
   flat plan, but the fix you did for the green shadow looks good")
   The shadow is one rectangle now and it reads clean, so it only needed room: the rectangle sits 6px outside
   the row on every side (the runtime adds 12px to both measured dimensions, this rule pulls the origin out
   by 6). The 1px ring stays 1px — this is breathing room, not a thicker line. */
@media (min-width: 701px) {
  .cmp-ours .tech-cast {
    left: -6px; top: -6px;
    border-radius: 3px;
    box-shadow: 0 0 0 1px rgba(34, 179, 94, .62), 0 22px 48px -26px rgba(34, 179, 94, .60);
  }
}

/* 49 — the separator's far end was too dim to read. Reviewed the crop after §44: the red segment at the left
   is clear and the line is continuous, but the white end measured at .12 alpha over the Ink ground — the
   same value as the background, so "fades to white" looked like "fades to nothing". The white is lifted so
   the fade is legible along its whole length; the red end is untouched. */
body .tech-sep {
  background: linear-gradient(90deg,
    rgba(200, 16, 46, .95) 0%,
    rgba(229, 112, 138, .62) 34%,
    rgba(255, 255, 255, .58) 68%,
    rgba(255, 255, 255, .30) 100%);
}

/* 50 — THE HEADER BEACONS GET ROOM (Jason: "in the header, move the pulsating beacons a little farther away
   from the chat and book buttons")
   Measured: the two `.beacon-nav` pulses are the FIRST and LAST children of `.nav-cta`, sitting 8px off the
   Chat button and 8px off the Book button (the cluster's own gap is 8px). Only the beacons move — margins on
   the two ends of the cluster, not a bigger gap, so Chat / or / Book keep the 8px rhythm between them while
   the pulses get 20px of air. */
body nav .nav-cta .beacon-nav:first-child { margin-right: 12px; }
body nav .nav-cta .beacon-nav:last-child { margin-left: 12px; }

/* 51 — THE CTA'S BEACON RINGS LOOP AGAIN (Jason: "loop the moving beacon rings in the CTA section")
   They were not slow, they were OFF: line 1997 hides every beacon in the action rows
   (`.cta-actions .beacon-mini, .hero-actions .beacon-mini { display: none }`) and line 1485 hides the last
   one again. Measured consequence: `div.beacon-mini.tech-live { display: none; height: 0 }` — an element
   that is not rendered never instantiates its animations, so its circles reported
   `animation-name: techBeaconSlim, techNode · iteration-count: infinite · play-running` with
   `getAnimations()` EMPTY. The rings were declared and never started. The CTA's are switched back on here;
   the hero's action row stays hidden, and the button-styling bug that hiding was once part of fixing is
   already carried by the `.cta-or + .btn` / `.btn-cta` selectors. */
.cta-actions .beacon-mini, .cta-actions .beacon-mini:last-child { display: inline-flex; }

/* 52 — A PARTIAL LAST ROW SITS CENTRED (Jason: "since there are only 2 cards (real estate and food service)
   in the last row of cards on who we serve, i think they should be centered under the 3 columns")
   Measured: the industries page's `.usecase-grid` is 3 columns of 365.3px with a 12px gap and holds EIGHT
   cards, so its last row is two cards against three columns and they sat flush left. The runtime measures
   the column and the gap and sets `--last-row-shift` (half a column + half a gap), so the pair moves right
   by exactly the amount that centres it — at any width, because it is re-measured on resize, and it simply
   does not apply when the grid is not three columns (where a two-card row is already full). */
/* AND THE CENTRING IS `left`, NOT `transform`. Jason: "the two bottom cards are moving around when i
   hover over them on the desktop". The hover lift writes `transform: translateY(-10px)`, which REPLACED this
   translateX — so hovering either of the pair dropped its half-column shift, the card jumped sideways, the
   pointer fell off the card it had just moved, hover ended, and it jumped back: a limit cycle, measured as
   the pair's top edge oscillating across a 9px range. `position: relative; left:` shifts the box by exactly
   the same amount and takes no space in the grid, so the pair stays centred and the hover owns `transform`
   outright. */
.tech-center-last2 > :nth-last-child(-n+2) { position: relative; left: var(--last-row-shift, 0px); }

/* ==================================================================================================
   §51  MOBILE PASS — the phone, measured (2026-10-17)
   Measured at 390 (iPhone 13 profile) and 320 across all ten pages: no horizontal overflow anywhere, the
   only sub-14px type is the deliberate 11.5px lockup sub-line, the header strip hides and the hamburger
   takes over, and the security comparison stacks. What needed work was tap targets, one crowded header row,
   and two orphaned lines.
   ================================================================================================== */
@media (max-width: 700px) {
  /* TAP TARGETS, to Apple's 44pt floor. Measured before: header Chat/Book 62x34, menu rows 358x37, header
     logo 34x34, footer logo 158x40, social icons 36x36. */
  body nav .nav-cta > a.btn { min-height: 44px; padding-block: 12px; }
  body nav .container > a.logo { min-height: 44px; }
  body nav .nav-links a { min-height: 48px; display: flex; align-items: center; }
  footer a.logo { min-height: 44px; }
  /* Tap targets below are set with min-width / min-height on purpose: `width` and `min-width` are DIFFERENT
     properties, so `style.css`'s doubled-class `width: 18px` cannot beat a `min-height: 44px`, however
     specific it is — the used size is simply the larger. An earlier round declared width/height here and
     lost to exactly that rule, leaving three 18x18 social icons per page. */
  body footer .social-row a { min-width: 44px; min-height: 44px; }
  body footer .footer-col a { min-height: 44px; }
  body a.back-link { min-height: 44px; display: inline-flex; align-items: center; }
  /* the two standalone actions left: the articles' "see also" link and the contact page's action row */
  body .see-also a, body .ld-actions .ld-alt a { min-height: 44px; display: inline-flex; align-items: center; }
  /* card action links ("See how it works ->") are inline anchors with no box height to tap */
  body a[class*="r-font-family-var-display"] { min-height: 44px; display: inline-flex; align-items: center; }
  .ld-consent { min-height: 44px; display: flex; align-items: center; gap: 10px; }

  /* THE HEADER ROW. On a 390px screen the row held the logo, Chat, an "or", Book, a 22x22 decorative beacon
     and the hamburger — the beacon is pure decoration, so it goes on phones and the real actions keep their
     air. (The beacon carries no words: nothing the gate compares.) */
  /* the beacons stay — they are the page's live marks and Jason wants them — but at 18px, which keeps the
     row airy: logo 34 + 2x18 + Chat 62 + Book 62 + toggle 44 + gaps = 314 of 390 */
  body nav .nav-cta > .beacon-nav { display: block; width: 18px; height: 18px; }
  body nav .nav-cta { gap: 8px; }
  body nav .nav-cta .cta-or { display: none; }        /* the "or" between two 44px buttons is redundant at 390 */

  /* ORPHANS. The hero kicker and the footer tagline each left "FREEDOM." alone on the last line at 390. */
  body .kicker, body .eyebrow { text-wrap: balance; }
  footer .tag-line { text-wrap: pretty; }

  /* THE CASE NOTE. Monospace, uppercased and letter-spaced, so at 390 it became a dense all-caps block. The
     source text is sentence case in the content layer; the caps are CSS, so relaxing them here changes no
     words — the gate compares textContent. */
  .case-note { text-transform: none; letter-spacing: .01em; line-height: 1.75; }
}

/* ==================================================================================================
   §52  MOBILE, PART TWO — the animations back, the beacons centred, the menu legible
   Each device here was switched OFF by a max-width query somewhere in the two layers, which is why the
   phone showed "no constellations or other animations". Appended last so it out-orders those rules.
   ================================================================================================== */
@media (max-width: 1000px) {
  /* THE OPEN MENU IS A LAYER, NOT WINDOW GLASS. `site-tech.css`'s bare `background: inherit` (now scoped to
     desktop) left this panel at rgba(0,0,0,0) — measured — so the hero read through the menu and even the
     current page's own link was hard to pick out. Ink, a hard edge, and the shadow it already had. */
  body nav.open .nav-links {
    background-color: var(--ink);
    background-image: none;
    border-bottom: 1px solid var(--edge-2);
    box-shadow: 0 26px 48px -30px rgba(2, 6, 14, .95);
  }
  body nav.open .nav-links a { color: var(--txt-2); }
  body nav.open .nav-links a[aria-current="page"] { color: var(--txt); }
}

@media (max-width: 700px) {
  /* THE BEACON PAIRS. Hidden at <=560 by the skin. Jason's "pulsating beacons on the bottom of landing page"
     are the two in .cta-actions; in portrait the actions stack so they sit at the top and the bottom of the
     block, 145px left of centre — they are centred now, which is what he asked for. */
  .hero-actions .beacon-mini,
  .cta-actions .beacon-mini { display: flex; }
  .cta-actions > .beacon-mini { align-self: center; margin-inline: auto; }

  /* the steps' wires and beacons, and the pricing row's green cast */
  body .steps .step .tech-wire,
  body .steps .step .step-beacon { display: block; }
  .cmp-ours .tech-cast { display: block; }
}

/* ==================================================================================================
   §53  MOBILE, THIRD ROUND — iOS form zoom, tablet/landscape tap targets, the 320px overflow
   ================================================================================================== */

/* TAP TARGETS RUN TO THE HAMBURGER'S OWN BREAKPOINT. §51 capped this at 700px, so at 768 (tablet) and 844
   (phone in landscape) the header buttons were back to 34px tall and the footer social icons to 36px — and
   844x390 is exactly how a phone gets used sideways. The nav itself switches to the hamburger at <=1000, so
   the tap-target rules belong on the same line. */
@media (max-width: 1000px) {
  body nav .nav-cta > a.btn { min-height: 44px; padding-block: 12px; }
  body nav .container > a.logo { min-height: 44px; }
  footer a.logo { min-height: 44px; }
  body footer .social-row a { min-width: 44px; min-height: 44px; }
  body footer .footer-col a { min-height: 44px; }
  body a.back-link { min-height: 44px; display: inline-flex; align-items: center; }
  body .see-also a, body .ld-actions .ld-alt a { min-height: 44px; display: inline-flex; align-items: center; }
  body a[class*="r-font-family-var-display"] { min-height: 44px; display: inline-flex; align-items: center; }
}

/* iOS ZOOM. Under 16px, Safari magnifies the page when a field takes focus and leaves it magnified. The
   contact form's text field and checkbox both measured 13.3px. */
@media (max-width: 1000px) {
  input:not([type="hidden"]), textarea, select, .ld-field input, .ld-consent input { font-size: 16px; }
  .ld-consent { font-size: 15px; }
}

/* ==================================================================================================
   §54  PHONE FIXES FROM JASON'S REVIEW (2026-10-17)
   ================================================================================================== */

/* THE LOOSE BEACON IN THE BODY. Re-enabled by §52, the hero's pair leaves one survivor sitting at y=610 in
   the hero's stacked content — a dot with nothing to relate to. The closing band's pair is the one he meant
   ("the pulsating beacons on the bottom of landing page"), and that stays. */
@media (max-width: 700px) {
  .hero-actions .beacon-mini { display: none; }
}

/* THE HOW IT WORKS CARDS. The grid was still six columns at 390: measured six of 51px, cards 435px tall, copy
   running over the neighbours. One card per row on a phone, two on a tablet — and the wires, which are
   horizontal connectors between six columns, only make sense at six. */
@media (max-width: 1000px) {
  body .steps { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 14px; }
  body .steps .step .tech-wire { display: none; }
}
@media (max-width: 700px) {
  body .steps { grid-template-columns: minmax(0, 1fr); gap: 12px; }
  body .steps .step { padding: 18px 16px 20px; }
}

/* THE CTA TAGLINE: never wrap. The size itself is fitted by the runtime (fitCtaTagline), which measures the
   text against the room available; this just stops it breaking, and tightens the tracking a little so the
   needed size stays legible. */
@media (max-width: 1000px) {
  section.cta .tagline, section.cta .tag-line { white-space: nowrap; letter-spacing: .055em; }
}

/* THE COMPARISON, STACKED. With the alignment offset off (see the runtime), the two panels are comparable
   again; these give the stacked layout its own rhythm and keep the panels' own padding sane. */
@media (max-width: 1000px) {
  body .dataflow .df-panel { padding: 18px 16px 20px; }
  body .dataflow .df-panel .df-band { padding: 14px 14px; }
  body .dataflow .df-box { padding: 11px 12px; }
  body .dataflow .df-flow { row-gap: 10px; }
}

/* pricing spacing: measured and set below, see §55 */

/* ==================================================================================================
   §55  PRICING: THE COMPARISON'S WASTED SPACE (Jason: "on the pricing, there is a lot of wasted/blank
   space that can be removed")
   Measured on the phone: the comparison table is 2,351px of a 9,664px page — 29% of it — because below
   760px every value stacks UNDER long labels: each row is 285px tall (model name 57, then 49 + 65 + 81).
   The label now sits BESIDE its value on one line, which reads like a spec sheet and is what the numbers
   want anyway: label left in the small mono, value right in the display face. Each cell drops to one line.
   ================================================================================================== */
@media (max-width: 760px) {
  /* the cells are declared PER nth-child further up the file, which out-specifies a plain `.cmp-table td`,
     so both the cell and its generated label have to name those children to win */
  body .cmp-table tbody td:nth-child(2),
  body .cmp-table tbody td:nth-child(3),
  body .cmp-table tbody td:nth-child(4) {
    display: flex; align-items: baseline; justify-content: space-between; gap: 12px;
    padding-block: 5px;
  }
  body .cmp-table tbody td:nth-child(2)::before,
  body .cmp-table tbody td:nth-child(3)::before,
  body .cmp-table tbody td:nth-child(4)::before {
    display: inline; margin-bottom: 0; width: auto; flex: 0 1 auto; min-width: 0;
  }
  body .cmp-table tbody th { padding-bottom: 2px; }
  body .cmp-table tbody tr { padding-block: 9px; }
}

/* ==================================================================================================
   §56  THE COMPARISON'S INTRO, LEFT-ALIGNED ONCE THE PANELS STACK
   The shared layer centres sentence one over the public panel and sentence two over the private one — which
   is exactly right while they sit side by side and meaningless the moment they stack, where it reads as an
   accident: the eyebrow and heading above it are left-aligned, and the body is centred under them. Measured
   at 390 in WebKit 26.4: `text-align: center` on both the paragraph and its split span.
   ================================================================================================== */
@media (max-width: 1000px) {
  body .dataflow p, body .dataflow .tech-split, body .dataflow .df-head p { text-align: left; }
}

/* ==================================================================================================
   §57  THE COMPARISON'S LIST MARKERS AND THE PROVIDER LINE
   WebKit 26.4 on a phone showed two small asymmetries. (1) The public rows mark "sent" with a square AFTER
   the text (`::after`, static, margin-left 7px) so it trails wherever the copy happens to end and the markers
   run down the panel as a ragged diagonal, while the private rows bullet from an ABSOLUTE marker in a fixed
   left column — the two lists stop mirroring each other. The square stays after the text, because "sent out"
   is what it means, but the row is a flex pair now, so the marker lands on one clean right-hand edge.
   (2) The provider line's wide tracking orphans its last word onto a line of its own; `text-wrap: pretty`
   (supported in this WebKit) keeps the break sane rather than shrinking the tracking that gives the line its
   character.
   ================================================================================================== */
@media (max-width: 1000px) {
  body .df-panel.bad .df-box.yours .df-chip {
    display: flex; align-items: baseline; justify-content: space-between; gap: 10px;
  }
  body .df-panel.bad .df-box.yours .df-chip::after { flex: 0 0 auto; margin-left: 0; }
  body .dataflow .df-box.ext, body .dataflow .df-box.ext * { text-wrap: pretty; }
}

/* --------------------------------------------------------------------------------------------------
   §57b the last two orphans ("COPILOT", "environment"): the diagram boxes' mono lines carry desktop-sized
   tracking, which is what pushes the final word onto its own line at 390. Tightened inside those two boxes
   only — the tracking that gives them their character stays everywhere else.
   -------------------------------------------------------------------------------------------------- */
@media (max-width: 1000px) {
  body .dataflow .df-box.ext, body .dataflow .df-box.ext *,
  body .dataflow .df-box.llm, body .dataflow .df-box.llm * { letter-spacing: .055em; }
}

/* ==================================================================================================
   §58  THE TWO THINGS THE mobile-fit-review AUDIT CAUGHT
   Run over all ten pages x iPhone SE / iPhone 15 / Pixel 7 (WebKit for iOS, Chromium for Android), the draft
   came back with no overflow, no missing viewport meta, nothing zoom-blocked and no small text — and two
   genuine hit-area findings.
   1. FAIL, all three devices, contact page: `input#ld-consent` is 18x18, under WCAG 2.2 Target Size (24x24).
      The label wraps it so it is usable, but the control's own target is what the standard measures. 22px
      with a matching accent size keeps it in proportion with the copy.
   2. WARN, every page: `a.logo` is 34x44 — under Apple's 44pt in WIDTH. §51/§53 gave it min-height and never
      min-width. The mark inside stays 34px; the anchor's target becomes 44 square.
   ================================================================================================== */
@media (max-width: 1000px) {
  body nav .container > a.logo { min-width: 44px; }
  /* 24, not 22: WCAG 2.2 Target Size (Minimum) is 24x24 and the first attempt landed one pixel under it --
     which is what the audit is for. */
  body .ld-consent input, input#ld-consent { width: 24px; height: 24px; min-width: 24px; min-height: 24px; }
  body .ld-consent { min-height: 44px; }
}

/* ==================================================================================================
   §59  PORTRAIT HEADER, THE TAGLINE EVERYWHERE, AND THE PRICING REGION BELOW THE TIER CARDS
   ================================================================================================== */

/* THE HEADER BEACON, REMOVED ON MOBILE. Jason first asked for this in portrait ("get rid of the pulsating
   beacon in the header for portrait mobile viewing"), then for the rings back ("landing page on mobile needs
   the rings radiating and traveling like the desktop"), and has now settled it: "the pulsating beacon in the
   header of the mobile view needs to be removed." It is off at every phone width and both orientations. The
   question that prompted the restore is still answered — an audit of every ring device on the landing page
   found the BODY rings were never the problem: the CTA beacons, the hero intro rings, the closing-band layer
   and the corner art all run 24 states over 3.6s. This header beacon was the one device sitting frozen
   (r=0, one state), and it is the one being removed. Desktop keeps it. */
@media (max-width: 1000px) {
  body nav .nav-cta > .beacon-nav { display: none; }
}

/* THE TAGLINE NEVER WRAPS — the hero's and the footer's included. The runtime's fitter sizes the text to the
   room available; this stops it breaking and tightens the tracking a little, which is what keeps the fitted
   size legible. */
@media (max-width: 1000px) {
  /* the display taglines: never broken, tracked a little tighter so the fitted size stays legible */
  body .hero .tagline, body .cta-box .tagline, body .cta .tagline, body .cta .tag-line {
    white-space: nowrap; letter-spacing: .055em;
  }
}

/* --------------------------------------------------------------------------------------------------
   THE COMPARISON: ONE STRICTLY-SMALLER CHANGE, AND NO MORE
   Two attempts at restructuring these rows both measured worse than the baseline (rows 218 -> 298 -> 246px,
   the block 2,428 -> 3,299 -> 2,626px, and 47px of horizontal overflow from text outgrowing its box), and the
   same rows also swelled one of them to 993px. So the structure is left alone. What is removed is the
   decorative `cmp-bar` — aria-hidden, no words, drawn for a wide cell, and the tallest thing in the row.
   Making the table easier to READ needs a structural decision (labels repeat once per row, so a phone reader
   re-reads "at 5B tokens a month" six times; the fix is a real header row or fewer metrics per model) and
   that changes what the table says, so it is Jason's call rather than a CSS tweak.
   -------------------------------------------------------------------------------------------------- */
@media (max-width: 760px) {
  body .cmp-table tbody td.c-bill .cmp-bar { display: none; }
}

/* --------------------------------------------------------------------------------------------------
   AND THE SPACE AROUND IT. Measured on the phone: the comparison sits 30px under the compliance line, the
   callout carries 20/20 padding inside an already-tight column, and the page's last blocks each add their own
   gap. Halved, and the callout's own paragraph rhythm tightened — it is a text block, so its space is
   leading, not padding.
   -------------------------------------------------------------------------------------------------- */
@media (max-width: 700px) {
  body .cmp { margin-top: 18px; }
  body .hc-callout { padding: 16px; margin-top: 18px; }
  body .hc-callout p { margin-top: 9px; }
  body .hc-callout h2, body .hc-callout h3 { margin-bottom: 8px; }
  body .hc-compliance { margin-top: 12px; }
  body .cost-section .price-card { margin-top: 8px; }
  body .cost-section .r-margin-top-16px { margin-top: 12px; }
}

/* --------------------------------------------------------------------------------------------------
   §60 the tagline can no longer wrap or overflow, whatever JavaScript does or when the font arrives.
   The runtime fit measures the text and sizes it to the room — correct, but it depends on running at the right
   moment, and on Jason's phone it did not: the CTA tagline wrapped while every measurement here said it fit.
   So the size is ALSO expressed in pure CSS, from the measured ratio between the words and the font (238px of
   text per 14px of font = 17.2px of width per font-point), against the space a phone's CTA box actually gives
   (viewport minus the gutters and the box's own padding). At 390 and above this resolves to the stylesheet's
   14px, so nothing changes visually where it already fitted; below that it scales down instead of wrapping,
   and it stops at 9px. The runtime still refines it — this is the floor under that, not a replacement.
   -------------------------------------------------------------------------------------------------- */
@media (max-width: 1000px) {
  /* the display taglines only: the footer's is a sentence in a narrow flex column and wraps, as it should */
  /* EACH TAGLINE SIZED FROM ITS OWN MEASURED RATIO. Jason: "freedom is slightly off screen on the landing page
     — the m is being cut off". The hero tagline's element box fitted (343px at 375) while its TEXT needed ~358,
     so it painted past its own box and `section.hero`'s overflow:hidden took the "m". The divisor is pixels of
     text per font-point and it is not the same for both: measured 25.6 for the hero (uppercase, with its own
     tracking plus the bullet indent) against 17.2 for the closing band. One shared divisor could not be right
     for both — use 17.2 and the hero is cut; use 25.6 and the band goes needlessly small. The hero also drops
     most of its tracking on phones, which buys back about 28px and keeps the size up. */
  body .hero .tagline {
    --tag-ratio: 25.6;
    font-size: clamp(9px, calc((100vw - 76px) / var(--tag-ratio)), 13.5px);
    letter-spacing: .02em;
    white-space: nowrap;
  }
  body .cta-box .tagline, body .cta .tagline, body .cta .tag-line {
    --tag-ratio: 17.2;
    font-size: clamp(9px, calc((100vw - 76px) / var(--tag-ratio)), 14px);
    white-space: nowrap;
  }
}

/* ==================================================================================================
   §61  "YOUR FREEDOM." IS SIGNAL RED EVERYWHERE, NOT JUST IN THE FOOTER
   Jason: "also, your freedom should be red". An audit of every instance found eight that were not: the
   HERO's was `var(--txt)` (white — the skin sets `.hero .tagline .free` explicitly) and the CLOSING BAND's
   was `#E5708A`, the on-dark rose used for red TYPE, on seven pages. Only the header strip and the footer
   were already `#C8102E`, which is why an earlier pass reported this done — it checked those two and not
   these. Both now match, so the phrase reads the same in all four places. The 3.08:1 note on Signal Red as
   type is the one already recorded for the strip and footer; this makes it consistent rather than adding a
   new instance. List and definition rules named, because the skin declares `.hero .tagline .free` outright.
   ================================================================================================== */
body .hero .tagline .free, body .hero .tagline .accent-signal,
body .cta-box .tagline .free, body .cta-box .tagline .accent-signal,
body .cta .tagline .free, body .cta .tagline .accent-signal,
body .cta .tag-line .free, body .cta .tag-line .accent-signal { color: #C8102E; }

/* ==================================================================================================
   §62  THE TWO BLANK SPACES, BOTH TRACED TO A BOX TALLER THAN ITS CONTENT
   Jason: "a lot of work to do on the GLM pricing card (too much blank space in portrait mobile view)" and
   "our flat plan also has a lot of blank space, like GLM card". Measured in WebKit at 390, both are the same
   class of fault:

   1. THE GREEN CAST, in the flat-plan row, was `position: static` — a 336x621 BLOCK inside the row's `th`.
      The runtime sizes it to the row's measured box, so the cast made the row taller (th 749px, row 908px),
      which made the next measurement larger again: a feedback loop. It is meant to paint BEHIND the row, so
      it becomes absolute, and the row collapses to its content. Fixed for every width, not just phones — the
      loop is a bug wherever it runs.

   2. THE ADD-ON CARD's void is an inner wrapper, `div.r-flex-1-1-320px`, holding the heading and the
      description: 115px of content inside a 320px box. In the card's column flex, that utility's
      `flex: 1 1 320px` is a HEIGHT basis, and it grows into slack as well. Measured: the wrapper 320px for
      115px of content, i.e. ~205px of blank space, which is exactly the void he is pointing at. On phones it
      sizes to its content; the desktop arrangement keeps its two-column basis.
   ================================================================================================== */
body .cmp-table tbody tr.cmp-ours { position: relative; }
body .cmp-table tbody tr.cmp-ours .tech-cast {
  /* NO `inset: 0` — that is what pinned the frame onto the row's edge and onto the text. The runtime sizes
     the overlay 14px larger than the row; this places it, so the clearance is real on all four sides. */
  position: absolute; left: -14px; top: -14px; right: auto; bottom: auto; margin: 0;
}
@media (max-width: 700px) {
  body .cost-section .price-card .r-flex-1-1-320px { flex: 0 1 auto; }
}

/* --------------------------------------------------------------------------------------------------
   §63 the closing band's ring layer: band-owned and proportional.
   Jason: "the traveling beacon rings are inside the CTA box and they shouldn't be; they should be in the area,
   but not the actual CTA box" and then "it's not consistent across the pages". It was inserted into `.cta-box`
   on every page, and that box's height varies (503px on overview, 616px elsewhere), so the ring's share of the
   area changed per page. It lives in the band now, behind the box's translucent fill (the box's content is
   lifted above it), and its height comes from the band so the weight is identical everywhere: 42% of the band,
   floored at 200px and capped at 320px, at the band's top-right.
   -------------------------------------------------------------------------------------------------- */
body section.cta { position: relative; }
body .cta-box > * { position: relative; z-index: 1; }
body .tech-cta-rings {
  top: 0; right: 0;
  width: min(460px, 62%);
  height: clamp(200px, 42%, 320px);
  z-index: 0; opacity: .34;
}
@media (max-width: 900px) {
  body .tech-cta-rings { width: min(340px, 78%); height: clamp(170px, 42%, 260px); }
}
@media (max-width: 700px) {
  body .tech-cta-rings { width: min(280px, 84%); height: clamp(150px, 42%, 240px); opacity: .38; }
}

/* --------------------------------------------------------------------------------------------------
   §64 the portrait guide — the security page's green connector.
   Jason: "in mobile portrait view, extend the green border line down from Public AI vs. Private AI on
   the right side so it takes the reader down to the private section." The private panel carries the
   green border and, once the panels stack, sits 857px below the heading with nothing leading the eye
   down. The rail is drawn by portraitGuide() (measured from the heading's bottom edge to the panel's
   top) and lands in a bead ON the panel, so it arrives rather than stops. Phones only: above 700px the
   panels sit side by side and there is nothing to point at.
   -------------------------------------------------------------------------------------------------- */
/* NO WIDTH GATE HERE. This block was inside `@media (max-width: 700px)` and that was the whole bug: the
   runtime sized the rail correctly at 768 and then set `display: ''`, which let the stylesheet hide it again
   because 768 is wider than 700. The runtime decides by measuring whether the panels are actually STACKED
   (which they are at 768 — gap 450px — and are not at 1024, gap 0); the stylesheet's only job is to keep it
   hidden until the runtime says otherwise. */
body .dataflow { position: relative; }
body .dataflow .tech-guide { display: none; position: absolute; right: 7px; width: 2px;
  background: linear-gradient(180deg, rgba(34,179,94,.04) 0%, rgba(34,179,94,.30) 10%,
              rgba(34,179,94,.62) 60%, rgba(34,179,94,.95) 100%);
  border-radius: 2px; pointer-events: none; z-index: 2; }
body .dataflow .tech-guide i {
  position: absolute; left: 50%; bottom: -4px; width: 8px; height: 8px; margin-left: -4px;
  border-radius: 50%; background: rgb(34,179,94);
  box-shadow: 0 0 0 4px rgba(34,179,94,.16), 0 0 12px rgba(34,179,94,.55);
  animation: techGuideBead 3.4s ease-in-out infinite;
}

/* AN EFFECT THAT DRAWS THE EYE DOWN. Jason: "give the green line an effect that will draw the readers eyes
   down to the private section". A static rule states that the two panels are related; it does not take anyone
   anywhere. So a short comet runs the length of the rail — roughly a sixth of it, fading in at the top and out
   at the bottom — and the bead at the far end pops as it arrives, at 88% of the same 3.4s, which is where the
   private panel begins. One cycle, one journey, repeated. The travel distance is the rail's own height, handed
   over by the runtime as --guide-h, so this holds at any width. Reduced motion is covered by the layer's
   existing kill, which switches every animation off wholesale. */
body .dataflow .tech-guide::after {
  content: ''; position: absolute; left: 0; top: 0; width: 100%; height: 92px;
  background: linear-gradient(180deg, rgba(34,179,94,0) 0%, rgba(34,179,94,.55) 45%, rgb(34,179,94) 100%);
  animation: techGuideRun 3.4s linear infinite;
}
@keyframes techGuideRun {
  0%   { transform: translateY(-92px); opacity: 0; }
  10%  { opacity: .85; }
  82%  { opacity: .95; }
  100% { transform: translateY(var(--guide-h, 600px)); opacity: 0; }
}
@keyframes techGuideBead {
  0%, 78%  { transform: scale(1);    box-shadow: 0 0 0 4px rgba(34,179,94,.16), 0 0 12px rgba(34,179,94,.55); }
  88%      { transform: scale(1.45); box-shadow: 0 0 0 8px rgba(34,179,94,.10), 0 0 22px rgba(34,179,94,.85); }
  100%     { transform: scale(1);    box-shadow: 0 0 0 4px rgba(34,179,94,.16), 0 0 12px rgba(34,179,94,.55); }
}

/* ==================================================================================================
   §65  THE FLAT-PLAN ROW WEARS ITS GREEN ALL THE WAY ROUND, AND PUBLIC IS RED / PRIVATE IS GREEN

   Jason: "make the entire border green for our flat plan" and "make 'public' red and 'private' green so
   people associate the correct sections".

   The row carried green only on its left and right (2px, rgba(34,179,94,.5)) at phone widths and NO border
   at all at 1440 — the green there came from the cast rectangle behind it. Table rows cannot hold a border
   reliably under border-collapse, so the perimeter is drawn on the cells: top and bottom on every cell, left
   on the first, right on the last. At 1440 the row is wider than the table's own gutters, so the same rule
   gives it a real edge there too.

   For the words: the section heading's "Public" and "Private" are wrapped in spans by the runtime (the text
   is untouched — the gate compares the word sequence and it is unchanged) and take the same two colours as
   the panels they name. The panel labels themselves — "Public cloud AI" and "Private deployment" — are
   coloured whole, because that is the association being asked for. Red as TYPE on these grounds uses
   #E5708A: Signal Red is 3.08:1 here and would be unreadable at this size.
   ================================================================================================== */
body .dataflow .df-band h4 { transition: color .2s var(--tech-ease, ease); }
body .dataflow .df-panel.bad .df-band h4 { color: #E5708A; }
body .dataflow .df-panel.good .df-band h4,
body .dataflow .df-panel.good.tech-answer .df-band h4 { color: #22B35E; }
body .dataflow .df-head h3 .df-w-public { color: #E5708A; }
body .dataflow .df-head h3 .df-w-private { color: #22B35E; }

/* THE PERIMETER IS PAINTED INSIDE THE ROW'S OWN BOX.
   Cell borders were the obvious way and they are wrong here: below 700px the table un-tables, the cells stack,
   and each cell then draws its own top and bottom border — internal lines, and the row's top edge at the
   horizontal centre belongs to whichever cell happens to sit there. Measured with a pixel strip scan: at 1440
   all four edges read green, at 390 the top did not. An inset box-shadow draws the frame on the row's box
   itself, independent of how the cells are laid out, and it is green on all four sides at both widths. */
/* ONE FRAME, NOT THREE. Jason: "there are multiple borders, red, yellow, green, depending on view."
   Measured, the row carried three green frames at once: its own inset box-shadow, the `.tech-cast`
   overlay's identical inset shadow on top of it, and `border-left/right: 2px` below 1000px. Two of those
   droppped here — the overlay keeps the frame because it is the one that paints above the cells (the row's
   own shadow is hidden by them at 1440, which is what left the perimeter looking different per view). */
body .cmp-table tbody tr.cmp-ours { border-radius: 8px; }
/* AND ABOVE THE CELLS. A row's own box-shadow paints under its children, and the cells have their own
   backgrounds: measured with the strip scan, 390 read all four green while 1440 lost left, right and bottom
   to the cells painted over them. `.tech-cast` is the runtime's absolutely-positioned overlay on exactly this
   row's box, so it paints above the static cells and carries the frame at every width. */
body .cmp-table tbody tr.cmp-ours .tech-cast {
  box-shadow: inset 0 0 0 2px rgba(34, 179, 94, .78);
  border-radius: 8px;
}

/* --------------------------------------------------------------------------------------------------
   §66 the USD conversion callout, smaller on phones.
   Jason: "for the mobile view, reduce the font for the callout on USD prices converted...it doesn't need to
   be as big as it is." It sits at the brand's 14px body floor, which is right for body copy and wrong for
   fine print — this is a rate/attribution note, the same class of furniture the lockup sub-line and the
   320px footer tagline belong to. 12.5px with its line-height tightened so the block stops occupying 165px.
   -------------------------------------------------------------------------------------------------- */
@media (max-width: 700px) {
  body .cost-section .container > p.r-margin-top-16px,
  body main p.r-margin-top-16px {
    font-size: 12.5px; line-height: 1.45;
  }
}
/* ==================================================================================================
   §67  NO CARD LETS THE ANIMATION THROUGH

   Jason: "ensure that all cards across all pages are not transparent so the animations don't distract
   from the card contents."

   An inventory across all ten pages, at phone and desktop width, found the card faces that are genuinely
   see-through: `usecase-panel`, `explore-block` and `case-callout` carry NO fill at all (rgba(0,0,0,0) —
   only their border defines them, so the constellation and the beacons pass straight through), and
   `callout` (mist at 3.5%) and `.df-env` (mist at 2%) are translucent tints. Everything else in the card
   family — `.sec-card`, `.price-card`, `.step`, `.df-panel` — already resolves to alpha 1.

   The fix is NOT a flat repaint. Each translucent face gets its own colour composited onto the page ink
   (#111D2E for callout, #0E1A2C for df-env), so it looks as it did and is opaque; the faces with no
   colour get the ink itself, which leaves the border to define the card exactly as before and stops what
   runs behind from showing through. The green/featured/private tints are untouched: they were already
   opaque, and where a card carries a translucent gradient it now blends against its OWN solid colour
   rather than the page.
   ================================================================================================== */
/* §67 STANDS, AND IT INCLUDES THE INDUSTRIES PANEL. A note of Jason's — "make the industry rectangles at the
   top so the constellation artifacts can be seen when they go behind those rectangles above the cards" — was read
   here as a request for translucency and the panel was set to alpha .45. That was backwards: "you were supposed
   to make the industry rectangles above the cards opaque." The rectangles BLOCK the field; the field is not meant
   to show through card faces at all (§67: "ensure that all cards across all pages are not transparent so the
   animations don't distract from the card contents"). All three panels are opaque ink. */
body .usecase-panel, body .explore-block, body .case-callout { background-color: #0A1628; opacity: 1; }
/* the doubled class is deliberate: both of these lost to a more specific rule in the page set, the same
   way the touch targets did, and repeating the class cannot be out-specified by a single-class rule. */
body .callout.callout { background-color: #111D2E; opacity: 1; }
body .df-env.df-env { background-color: #0E1A2C; opacity: 1; }
body .step, body .sec-card, body .price-card, body .df-panel, body .cmp-card { opacity: 1; }

/* --------------------------------------------------------------------------------------------------
   §68 MORE RINGS ON THE LANDING PAGE, MOBILE.
   Jason: "the pulsating beacon in the header of the mobile view needs to be removed", then "need more
   rings on the landing page mobile view." The header beacon is gone at every phone width (§59), so the
   hero gets the rings back instead of the header: the hero's own beacon pair is switched on, one of the
   two (the pair is hidden at both widths today, and a previous attempt to show both left the survivor
   sitting 610px down in the page body, next to nothing). That is three rings plus its emitting wave,
   sitting in the hero beside the buttons where the eye already is. The hero's ring layer also grows and
   lifts a little, so the waves read at arm's length rather than as a hairline.
   The selectors carry :first-child / :last-child deliberately: the rules that hide this pair are
   `.hero-actions .beacon-mini` and `.cta-actions .beacon-mini, .hero-actions .beacon-mini`, and a
   pseudo-class out-specifies both without reaching for !important.
   -------------------------------------------------------------------------------------------------- */
@media (max-width: 700px) {
  body .hero-actions .beacon-mini:first-child { display: inline-flex; width: 26px; height: 26px; opacity: .95; }
  body .hero-actions .beacon-mini:last-child { display: none; }
  body .tech-intro-rings { width: min(340px, 86%); height: min(300px, 34vh); opacity: .46; }
}

/* --------------------------------------------------------------------------------------------------
   §69 WHERE THE TRAVELLING RINGS COME FROM.
   Jason: "for all traveling beacons, have the top section ones originate from the left top corner and
   for the ones at the bottom, the right bottom corner."

   The hero's waves leave from the TOP-LEFT corner; the closing band's from the BOTTOM-RIGHT. The radial
   mask travels with each one (32% 34% and 68% 66%), or the layer stays brightest away from the corner it
   is supposed to be emanating from.

   THE DOUBLED CLASS IS LOad-BEARING, not a typo. These positions live in the shared sheet
   (`tools/site-tech.css`: `top: -60px; right: 0` on desktop and `top: -44px; right: 0` on phones for the
   hero layer, plus its own `.tech-cta-rings` block), and that sheet is injected AFTER the skin, so at equal
   specificity it wins regardless of what the skin says. A first attempt here with single-class selectors
   was completely inert — measured on a phone, the hero layer still reported `left: 980, right: 0` at 1440
   and the band's sat 425px above its bottom edge. Repeating the class out-specifies a single-class rule
   wherever it lives, without reaching for !important.
   -------------------------------------------------------------------------------------------------- */
body .tech-intro-rings.tech-intro-rings { top: 0; left: 0; right: auto; bottom: auto;
  -webkit-mask-image: radial-gradient(68% 62% at 32% 34%, #000 0%, rgba(0,0,0,.55) 58%, transparent 100%);
          mask-image: radial-gradient(68% 62% at 32% 34%, #000 0%, rgba(0,0,0,.55) 58%, transparent 100%); }
body .tech-cta-rings.tech-cta-rings { bottom: 0; right: 0; top: auto; left: auto;
  -webkit-mask-image: radial-gradient(68% 62% at 68% 66%, #000 0%, rgba(0,0,0,.55) 58%, transparent 100%);
          mask-image: radial-gradient(68% 62% at 68% 66%, #000 0%, rgba(0,0,0,.55) 58%, transparent 100%); }

/* --------------------------------------------------------------------------------------------------
   §70 THE CASE-STUDY FRAME MATCHES THE DECK, SO THE DECK FILLS IT.

   Jason: "the case study slide show is not adjusting to the entire box it's in when changing from portrait
   to landscape."

   The deck is a fixed 16:9 stage. The frame around it was `aspect-ratio: 16 / 10` — 1.6 against the deck's
   1.78 — so the deck could never fill it: portrait left roughly 29px of clear space top and bottom, and
   landscape (where the frame is 2.59:1) about 124px each side, which is the "not adjusting" he is seeing.
   Neither orientation could ever be right, because the frame's shape was simply not the deck's shape.

   The inner now carries the deck's own 16:9, and on a phone held sideways it is sized BY THE HEIGHT so it
   fits the screen as well — a 16:9 box at full landscape width is 444px tall against a 390px viewport, which
   would fill the frame but hang off the screen. Height-driven, centred, with a ceiling, gives both: the box
   is 16:9 and inside the screen, and the deck fills it edge to edge.

   Doubled class on the inner for the same reason as §69: the shared sheet is injected after the skin, and a
   single-class rule of equal specificity loses to it no matter where it sits.
   -------------------------------------------------------------------------------------------------- */
body .case-frame .case-frame-inner.case-frame-inner { aspect-ratio: 16 / 9; }
@media (orientation: landscape) and (max-height: 560px) {
  body .case-frame .case-frame-inner.case-frame-inner {
    width: auto; height: min(84vh, 444px); aspect-ratio: 16 / 9; margin-left: auto; margin-right: auto;
  }
}

/* --------------------------------------------------------------------------------------------------
   §71 "DATA STAYS" WEARS THE GREEN THE WAY "DATA LEAVES" WEARS THE RED.
   Jason: "make 'data stays' green similar to how 'data leaves' is red."
   The pair is `.df-tag.warn` / `.df-tag.ok`. The red one reads #E5708A on an 8% Signal Red fill with a 40%
   border; the green one was plain white on a mist fill, so the two sides of the comparison were colour-coded
   on one side only. This mirrors the treatment exactly in the trust green — same 8% fill, same 40% border.
   The text is #22B35E rather than a lighter tint, because that is the brand's one green (the private
   heading and the featured tier already use it) and it clears 4.5:1 on these grounds; inventing a second
   green for type would be the thing the palette rules forbid.
   SELECTORS ARE DOUBLED for the same reason as §69/§70: the shared sheet is injected after the skin.
   -------------------------------------------------------------------------------------------------- */
/* THE RULE THAT BEATS THIS IS IN THIS SAME FILE, from the private panel's own pass:
     body .dataflow .df-panel.good.tech-answer .df-tag.ok { background: var(--s3); color: var(--txt); ... }
   Five classes against my three, so scoping it to .dataflow was never the problem and neither was the
   shared sheet. The selector below carries the same chain plus a doubled final class — one class more than
   that rule, which is all it takes, and still no !important. */
body .dataflow .df-panel.good.tech-answer .df-tag.ok.df-tag.ok {
  color: #22B35E;
  background: rgba(34, 179, 94, .08);
  border-color: rgba(34, 179, 94, .4);
}
body .df-tag.ok.df-tag.ok {
  color: #22B35E;
  background-color: rgba(34, 179, 94, .08);
  border-color: rgba(34, 179, 94, .4);
}
/* AND THE CTA'S BEACON PAIR IS SYMMETRIC IN BOTH ORIENTATIONS. Measured in landscape: the row is 737 wide,
   the beacons are its first and last child, and with `justify-content: flex-start` the second sat at x=648 —
   63px short of the row's edge, so the pair read as lopsided. In portrait the row is a column and both are
   centred, which is why it only looked wrong on its side. `margin-left: auto` sends the trailing beacon to
   the far end without touching the buttons' own arrangement. */
@media (orientation: landscape) {
  body .cta-actions .beacon-mini:last-child { margin-left: auto; }
}
/* and the hero's travelling rings need to be positioned at all before top/left can mean anything: measured,
   that layer was static in the flow and reported fromLeft 55 / fromTop 2794 against the hero. */
body .tech-intro-rings.tech-intro-rings {
  position: absolute; top: 0; left: 0; right: auto; bottom: auto;
}
/* THE SECTIONS THEMSELVES MUST BE THE CONTAINING BLOCK. Measured after the rule above: both layers went
   absolute but anchored to some larger positioned ancestor — the band reported fromTop 0 / fromRight 980,
   i.e. the TOP-LEFT of something else rather than the bottom-right of the closing band. `top: 0` is only the
   section's top if the section is positioned; the shared sheet evidently positions neither one. */
body section.hero.hero, body section.cta.cta { position: relative; }
body .tech-cta-rings.tech-cta-rings { bottom: 0; right: 0; top: auto; left: auto; }

/* --------------------------------------------------------------------------------------------------
   §72 THE HERO'S RING LAYER IS ACTUALLY POSITIONED, AND AT THE TOP-LEFT.
   Jason, twice: "need rings on the landing page for mobile view", and before that "have the top section
   ones originate from the left top corner".

   Both are the same fault. Measured on a phone, the hero's layer reported `fromHostTop: 2815` — it was
   sitting in the flow at the END of the hero's content, a long way below anything the reader looks at, so
   its waves were running the whole time and visible to nobody. That is why the earlier positioning attempt
   changed nothing and why the rings felt absent: they were animating off the bottom of the hero band.

   Five repetitions of the class. Two (in §69) lost, and the dump above shows why — the winner is a later
   rule of equal specificity, so each attempt has to clear the last one. Repeating the class is the legal
   escalation; `!important` stays reserved for the reduced-motion kill, as agreed.
   -------------------------------------------------------------------------------------------------- */
body .tech-intro-rings.tech-intro-rings.tech-intro-rings.tech-intro-rings.tech-intro-rings.tech-intro-rings {
  position: absolute;
  top: 0; left: 0; right: auto; bottom: auto;
}
/* and the band's layer keeps its own corner (bottom-right) at the same weight, so neither is left to
   whoever happens to load last. */
body .tech-cta-rings.tech-cta-rings.tech-cta-rings.tech-cta-rings.tech-cta-rings {
  position: absolute; bottom: 0; right: 0; top: auto; left: auto;
}

/* --------------------------------------------------------------------------------------------------
   §73 the hero's own ring layer. A class of its own, so it inherits none of the band layer's rules and
   competes with nothing: absolute, at the hero's top-left corner, masked to match (32% 34%), sized for a
   phone, behind the hero's content (it is inserted first, so the hero's `.container` follows it and takes
   z-index 1 from the existing sibling rule).
   -------------------------------------------------------------------------------------------------- */
body .tech-hero-rings.tech-hero-rings {
  position: absolute; top: 0; left: 0; right: auto; bottom: auto;
  width: min(360px, 88%); height: min(320px, 36vh);
  opacity: .5; overflow: hidden; z-index: 0; pointer-events: none;
  -webkit-mask-image: radial-gradient(68% 62% at 30% 30%, #000 0%, rgba(0,0,0,.55) 58%, transparent 100%);
          mask-image: radial-gradient(68% 62% at 30% 30%, #000 0%, rgba(0,0,0,.55) 58%, transparent 100%);
}
@media (min-width: 1001px) {
  body .tech-hero-rings.tech-hero-rings { width: min(520px, 46%); height: 460px; opacity: .36; }
}


/* --------------------------------------------------------------------------------------------------
   §74 THE TRAVELLING RINGS LEAVE FROM THE TOP-LEFT ON EVERY PAGE, AND TRAVEL FROM THERE.
   Jason: "i see the traveling beacon now, but it needs to originate and travel from the top left corner
   on all pages." The layer is pinned to the top-left of the band it lives in, on every page, and its mask
   is centred on that corner (30% 30%) so the waves are brightest where they start and fade as they travel
   out — the mask is what makes the origin readable, not the position alone.
   The earlier !important is gone; this is a six-class selector instead, which out-specifies everything in
   either sheet and keeps !important reserved for the reduced-motion kill, as agreed.
   -------------------------------------------------------------------------------------------------- */
body .tech-intro-rings.tech-intro-rings.tech-intro-rings.tech-intro-rings.tech-intro-rings.tech-intro-rings {
  -webkit-mask-image: radial-gradient(70% 64% at 30% 30%, #000 0%, rgba(0,0,0,.55) 58%, transparent 100%);
          mask-image: radial-gradient(70% 64% at 30% 30%, #000 0%, rgba(0,0,0,.55) 58%, transparent 100%);
}

/* --------------------------------------------------------------------------------------------------
   §75 THE CASE-STUDY FRAME, BY ORIENTATION.

   Jason: "can't you adjust the case study slide show frame so it adjusts based on orientation."

   One honest limit up front: the deck is a 16:9 stage and, inside an iframe, it fills the WIDTH available
   to it. On a portrait phone that means the deck can be no larger than the screen is wide — making the
   frame taller in portrait would not enlarge the deck, it would just put letterbox bars back above and
   below, which is the thing §70 removed. So portrait is made to give the deck every pixel of width there
   is (the frame's padding goes, so the box runs edge to edge) and landscape is sized by height, which is
   where the room actually is on a phone held sideways.
   -------------------------------------------------------------------------------------------------- */
@media (orientation: portrait) and (max-width: 700px) {
  body .case-frame { padding: 0; border-radius: 14px; }
  body .case-frame .case-frame-inner.case-frame-inner { width: 100%; aspect-ratio: 16 / 9; height: auto; }
}
@media (orientation: landscape) {
  body .case-frame .case-frame-inner.case-frame-inner { width: auto; height: min(78vh, 430px); aspect-ratio: 16 / 9; margin-left: auto; margin-right: auto; }
}

/* --------------------------------------------------------------------------------------------------
   §76 THE LAST 16/49. Five pages (industries, how-it-works, security, pricing, about) sat with their
   ring layer at 16px in and 49px down from the band's corner rather than IN it, because there the layer
   is a child of the hero's `.container` — which carries that padding — so `top: 0; left: 0` resolved
   against the content column. The four doc pages and the landing page were already at 0/0.
   Scoped to `.container > .tech-intro-rings` precisely, so the pages that are already correct are not
   pushed out of their band by the same negative offset.
   -------------------------------------------------------------------------------------------------- */
/* the parent is `.section-header`, not `.container` — that guess was measured and wrong. */
body .section-header > .tech-intro-rings.tech-intro-rings.tech-intro-rings {
  left: -16px; top: -49px;
}

/* --------------------------------------------------------------------------------------------------
   §77 THE USD CALLOUT, SMALLER AGAIN.
   Jason: "keep reducing the font for 'usd prices...from your browser'." 12.5px was not enough. 11.5px now,
   with the leading pulled to match, and it is reached through a class the runtime adds (`.fx-note`) rather
   than through the utility class the markup happens to carry — `.r-margin-top-16px` is shared with other
   paragraphs, so styling it touched anything else using it.
   -------------------------------------------------------------------------------------------------- */
@media (max-width: 700px) {
  /* THE WINNER IS AN ID. A CSSOM dump of every font-size rule matching this paragraph named it:
       #fx-note { font-size: var(--fs-mono) }
     An ID selector outranks any number of classes, which is why doubling and tripling the class never
     moved it — and the paragraph had that id in the markup the whole time, so the runtime tagger was
     never needed. `#fx-note.fx-note` is one id plus one class, which beats one id, with no !important.
     12.5px -> 11.5px, and the leading comes with it. */
  #fx-note.fx-note { font-size: 11.5px; line-height: 1.42; letter-spacing: .002em; }
}

/* --------------------------------------------------------------------------------------------------
   §78 THE HERO'S TWO CTA BUTTONS, OFF ON MOBILE.
   Jason: "remove the chat with a team member and book an appointment buttons in the top section, not the
   header, of the landing page when in mobile view" — i.e. the hero's own `.hero-actions`, not the header's
   `.nav-cta`, which keeps its Chat and Book buttons.

   Only the BUTTONS go, not the row: the hero beacon I added lives inside `.hero-actions` too, and removing
   the row would take the rings with it, which is the thing he asked for two messages ago. The buttons'
   words still render at desktop widths and in the header on every device, so nothing is lost from the
   page's readable content.
   -------------------------------------------------------------------------------------------------- */
@media (max-width: 1000px) {
  body .hero .hero-actions .btn, body .hero .hero-actions .cta-or { display: none; }
}

/* --------------------------------------------------------------------------------------------------
   §79 the last 16/49, for real this time. §76 targeted the right parent — measured, these layers ARE
   children of `div.section-header` — but it carried four classes and my own §72 rule carries six, so §72
   was winning and the offset never applied. Seven here, inside the parent that actually hosts them.
   -------------------------------------------------------------------------------------------------- */
body .section-header > .tech-intro-rings.tech-intro-rings.tech-intro-rings.tech-intro-rings.tech-intro-rings.tech-intro-rings.tech-intro-rings {
  left: -16px; top: -49px;
}

/* --------------------------------------------------------------------------------------------------
   §80 THE LONE BEACON ABOVE "WHO WE SERVE" GOES.
   Jason: "get rid of the lone pulsating beacon on the landing page above the who we serve card."
   That is the hero's own beacon, which §68 switched on when he asked for more rings and the header beacon
   came off. Measured last pass at 26x26, x=16, y=587 — sitting on its own above the Who We Serve band, in
   a row whose buttons §78 has now hidden, so it had nothing left to belong to. Both of the pair are off
   again on phones; the hero's travelling ring LAYER stays, which is the part of §68 he asked to keep.
   -------------------------------------------------------------------------------------------------- */
@media (max-width: 700px) {
  body .hero .hero-actions .beacon-mini.beacon-mini { display: none; }
}

/* --------------------------------------------------------------------------------------------------
   §81 THE TAGLINE BULLET IS A BEACON, AND THE TRAVELLING ONE COMES OFF THE PAGE.

   Jason: "let's change the square bullet on the landing page to the left of the tagline to a beacon and
   have thin rings radiating out of it slowly and then remove the traveling pulsating beacon from the page."

   The bullet itself keeps its 7x7 box and its place in the flow — the tagline's fitted size was measured
   around it, so the words must not move. It is recoloured to the brand's Signal Red (it was #F0455F, which
   is not in the palette) and takes a slow presence pulse; the rings are the layer pinned over it, 1px
   borders so they stay thin, 7.5s each, staggered 2.5s, scaling to 4x as they fade.
   The hero's travelling layer is switched off: that is "the traveling pulsating beacon" he means. The
   closing band's travelling rings stay, since those are the ones he placed at the bottom-right.
   -------------------------------------------------------------------------------------------------- */
body .hero .tagline::before { background: #C8102E; animation: taglineDot 7.5s ease-in-out infinite; }
@keyframes taglineDot { 0%,100% { box-shadow: 0 0 0 0 rgba(200,16,46,.0); } 50% { box-shadow: 0 0 10px 1px rgba(200,16,46,.55); } }

body .tagline-beacon { position: absolute; width: 0; height: 0; pointer-events: none; z-index: 0; }
body .tagline-beacon u {
  position: absolute; left: -3.5px; top: -3.5px; width: 7px; height: 7px; border-radius: 50%;
  background: #C8102E; display: block;
}
/* THIN AT EVERY DIAMETER, AND GONE BY THE EDGE.
   Jason: "now they look like smoke rings, bad. the rings should be thin and disappear as they reach the edge
   of the page."

   The smoke rings were my fault and the cause is arithmetic: `transform: scale(26)` multiplies the BORDER
   too, so a 0.5px hairline rendered as a ~13px band. Scaling can never give a constant-thickness ring. So
   the rings animate their own width and height instead — the border stays 0.5px at every diameter — and the
   cycle ends at ~700px across, which puts the far side of the ring at the screen's right edge, with opacity
   already at 0 by then, so they thin out into the edge rather than sliding under it.

   Margin is half the size on each axis so every ring grows from the beacon's centre, not from a corner.
   Three rings, 10.5s each, staggered a third of a cycle apart, so one is always mid-flight.
   -------------------------------------------------------------------------------------------------- */
body .tagline-beacon i {
  position: absolute; left: 0; top: 0; width: 8px; height: 8px; margin: -4px 0 0 -4px;
  border: 0.5px solid rgba(200, 16, 46, .6); border-radius: 50%; display: block; opacity: 0;
  animation: taglineRing 10.5s linear infinite;
}
body .tagline-beacon i:nth-child(1) { border-color: rgba(200, 16, 46, .60); }
body .tagline-beacon i:nth-child(2) { border-color: rgba(244, 245, 248, .55); animation-delay: 3.5s; }
body .tagline-beacon i:nth-child(3) { border-color: rgba(33, 64, 111, .95); animation-delay: 7s; }
@keyframes taglineRing {
  0%   { width: 8px;   height: 8px;   margin: -4px 0 0 -4px;     opacity: 0; }
  8%   { opacity: .85; }
  55%  { opacity: .30; }
  100% { width: 700px; height: 700px; margin: -350px 0 0 -350px; opacity: 0; }
}
body .tech-hero-rings { display: none; }

/* §82 the flat-plan row owns exactly ONE frame. The 2px green left/right border it still showed on phones
   sat outside the overlay's frame, so the edge read as two lines; the frame is the overlay's alone now.
   Any corner mark on this row is suppressed too, so nothing else draws an edge around it. */
body .cmp-table tbody tr.cmp-ours { border-left-width: 0; border-right-width: 0; border-top-width: 0; }
body .cmp-table tbody tr.cmp-ours .tech-corner,
body .cmp-table tbody tr.cmp-ours .tech-corner::before,
body .cmp-table tbody tr.cmp-ours .tech-corner::after { display: none; }

/* §83 (reverted) added 14px of padding to every row's first cell to make room for the frame. Measured, it
   did not apply to the flat-plan row's own first cell — that row's text stayed at 33 while the other rows
   moved to 47 — so it misaligned the table and left the frame touching anyway. The clearance now comes
   from the overlay being larger than the row, which moves no text at all. */

/* --------------------------------------------------------------------------------------------------
   §84 THE TOP-REGION TRAVELLING RINGS COME OFF EVERY PAGE.
   Jason: "remove the traveling pulsating beacon on the pages that travels in the top region. it's too
   distracting and that was on me."

   Both top-region layers go — `.tech-intro-rings` on all nine content pages and `.tech-hero-rings` on the
   landing page (the clone §73 added, already hidden in §81). The closing band's rings stay: those are the
   ones he placed at the bottom-right, and he has not asked for those to move.

   Seven classes, because §72/§74 target the same element with six and would otherwise win. `animation: none`
   comes with the display change so nothing is left animating off-screen — display:none alone still leaves the
   work queued on some engines.
   -------------------------------------------------------------------------------------------------- */
/* `:not(.tech-cta-rings)` IS ESSENTIAL. The closing band's layer is classed `tech-intro-rings tech-cta-rings`,
   so hiding the `.tech-intro-rings` class took the BAND's rings with it — measured, ctaVisible went to 0 on
   all ten pages, the exact opposite of leaving the band's alone. */
body .tech-intro-rings.tech-intro-rings.tech-intro-rings.tech-intro-rings.tech-intro-rings.tech-intro-rings.tech-intro-rings:not(.tech-cta-rings),
body .tech-hero-rings.tech-hero-rings.tech-hero-rings {
  display: none;
  animation: none;
}
/* and the flat-plan row's second line, which had no element of its own to style until flatPlanSub() wrapped
   it. Jason: "our flat plan still needs to have the text adjusted." It was running on as one long block with
   the plan name: 17px, the same colour as the heading, 128px tall in a 97px column. Now a proper sub-line. */
body .cmp-table tbody tr.cmp-ours .fp-sub {
  display: block; font-size: 12.5px; line-height: 1.45; color: rgba(201, 209, 224, .62);
  margin-top: 6px; max-width: 34ch; letter-spacing: .01em; font-weight: 400;
}

/* --------------------------------------------------------------------------------------------------
   §85 THE FRAME HUGS THE DECK — THE HALF I KEPT MISSING.
   Jason: "why haven't you been able to fix the frame that outlines the case study to elastically adjust to
   the case study window depending on the mobile view."

   Because §70 and §75 fixed the INNER box (so the deck fills what it is given) and left the FRAME full
   width. Measured in landscape: frame 790x305, inner 513x289, insets 138px each side — the deck correctly
   sized by height inside an outline that had not moved, so the outline's sides framed nothing. Portrait was
   already tight (frame 358x203, inner 354x199, insets 2/2) because there the deck is width-driven.

   `width: fit-content` on the frame, centred, means the outline is drawn around the deck at whatever size
   the deck takes — full width in portrait, height-driven in landscape — and it re-fits on rotation with no
   JavaScript, because the browser recomputes it when the inner's size changes. That is the elastic behaviour
   asked for, rather than two fixed shapes.
   -------------------------------------------------------------------------------------------------- */
/* IN LANDSCAPE ONLY. Applied at every orientation it also collapsed portrait: the frame went from 358px to
   304 because `fit-content` made the inner's `width: 100%` resolve against a shrink-to-fit parent, so the
   deck got smaller instead of staying edge to edge. Portrait keeps 100% (the deck fills it), landscape hugs
   (the deck is driven by height, so the outline follows it). */
@media (orientation: landscape) {
  body .case-frame.case-frame { width: fit-content; max-width: 100%; margin-left: auto; margin-right: auto; }
}
@media (orientation: portrait) {
  body .case-frame.case-frame { width: 100%; }
}

/* ==================================================================================================
   §86 THREE THINGS: THE LANDING PAGE'S BLUE, THE BULLET BACK TO A SQUARE, AND THE PLANETARY RINGS

   1. THE BLUE. Jason: "the landing page background blue needs to match the other pages dark blue."
      Measured, the flat colours are identical everywhere (rgb(10,22,40) on html, body and every band), and
      so is the body's radial gradient. The only difference is a wash the hero adds on top:
        index    band[hero]      linear-gradient(168deg, rgba(33,64,111,.3) 0%, rgba(15,37,71,.12) 44%, …)
        every other page's first band: none
      That diagonal navy wash is what makes the landing page read lighter at the top. It comes off, so the
      page sits on the same ground as the rest.

   2. THE BULLET. Jason: "remove the pulsating beacon bullet and revert it back to a square red bullet."
      The beacon layer (§81–§81d) stops drawing, and the tagline's `::before` goes back to a plain 7x7
      SQUARE — it never had a border-radius, so the shape is unchanged — in the brand's Signal Red rather
      than the #F0455F it carried, which is not in the palette. No pulse, no rings.

   3. THE PLANETARY RINGS. Jason: "they look like planetary rings … I want those to be on the landing page."
      They are `.beacon-corner`: four concentric circles on a single SVG rotating at 80s linear — the corner
      art. Measured present on the landing page in the hero (1184x1184, opacity .3) and the closing band
      (1200x1200, opacity .5). What §84 removed was the top-region TRAVELLING layer, a different device;
      the corner art was never in that list and is untouched. Confirmed below.
   ================================================================================================== */
body section.hero.hero.hero { background-image: none; }
body .tagline-beacon, body .tagline-beacon i, body .tagline-beacon u { display: none; animation: none; }
body .hero .tagline::before { animation: none; background: #C8102E; border-radius: 0; }

/* ==================================================================================================
   §87 THE ORBIT RINGS WEAR THE THREE BRAND COLOURS, AND THE EXTRAS ARE PLACED

   Jason: "add more orbit rings" and "have them in red, white and blue colors."

   The art is four concentric circles on one SVG, rotating at 80s. Their strokes take Signal Red, the
   text white (#F4F5F8) and the palette's navy (#21406F) in that order outwards, with the opacity falling
   as they widen so the outer orbits stay faint — the look of rings seen edge-on rather than four equal
   hoops. CSS beats the SVGs' own presentation attributes, so the markup is untouched.

   Placement: the cloned set on the opening band sits at the opposite corner from the original, so a page
   opening shows one system top-left and the closing band carries its own lower-right — the two corners the
   rest of the page's furniture already uses.
   ================================================================================================== */
body .beacon-corner svg circle:nth-child(1) { stroke: #C8102E; }
body .beacon-corner svg circle:nth-child(2) { stroke: #F4F5F8; }
body .beacon-corner svg circle:nth-child(3) { stroke: #21406F; }
body .beacon-corner svg circle:nth-child(4) { stroke: rgba(244, 245, 248, .45); }
body .beacon-corner svg circle:nth-child(n+5) { stroke: rgba(33, 64, 111, .55); }
body .beacon-corner svg circle { fill: none; vector-effect: non-scaling-stroke; }
body .orbit-extra.beacon-corner { top: auto; right: 0; left: auto; bottom: 0; opacity: .26; }
body .orbit-extra.beacon-corner svg { animation-duration: 140s; }

/* ==================================================================================================
   §88 THE ORBIT RINGS COME IN AND OUT.
   Jason: "i am expecting to see several, (at least 3) orbit rings that come in and out."

   They existed but were all drawn at once and only rotated, so nothing ever arrived or left. Each orbit now
   breathes: opacity 0 -> .85 -> 0 over 12s with a gentle scale, and the four are staggered a quarter of a
   cycle apart (0/3/6/9s) so at any moment at least three are visible — one arriving, one at full, one
   leaving. The red innermost ring leads and the outer orbits trail, which reads as rings catching light in
   sequence rather than a single hoop blinking.

   `transform-box: fill-box` is required or the scale would move each circle relative to the SVG origin
   instead of about its own centre — and the circles are all concentric, so a scaling error here would pull
   the system apart rather than swell it.

   REDUCED MOTION: the global kill pauses every animation, and a paused animation holds its first keyframe —
   opacity 0 — which would leave the orbit rings INVISIBLE for anyone with the preference set. This is the
   one place !important is allowed (the reduced-motion block's own exception), so a still, visible value is
   pinned there.
   ================================================================================================== */
/* OPACITY ONLY, NO TRANSFORM. Jason: "the orbit rings should be constantly happening and right now, it
   looks like they stop after a couple of the happen." Measured at that moment: ring 1 opacity .846 and ring
   2 .0004 — both mid-cycle — while ring 3 read 0.45, which is its own attribute value, i.e. its animation was
   NOT running at all. Animating `transform` on SVG circles is unreliable in WebKit: the compositor can drop
   the animation, which is exactly the "it happens a couple of times and then stops" symptom. The scale was
   decoration; the cycle is now opacity-only, which is rock solid, and the count is stated explicitly rather
   than left to the shorthand. */
/* ONE DRIVER, NOT TWO. The keyframe animation is off; the runtime's frame loop sets opacity (see
   orbitBreath()). Two mechanisms animating the same property is how a cycle ends up looking stopped. */
body .beacon-corner svg circle {
  animation-name: none;
  animation-duration: 0s;
  animation-iteration-count: 1;
}
body .beacon-corner svg circle:nth-child(1) { animation-delay: 0s; }
body .beacon-corner svg circle:nth-child(2) { animation-delay: 3s; }
body .beacon-corner svg circle:nth-child(3) { animation-delay: 6s; }
body .beacon-corner svg circle:nth-child(4) { animation-delay: 9s; }
body .beacon-corner svg circle:nth-child(n+5) { animation-delay: 0s; animation-duration: 15s; }
@keyframes orbitBreath {
  0%   { opacity: 0; }
  18%  { opacity: .90; }
  55%  { opacity: .55; }
  100% { opacity: 0; }
}
@media (prefers-reduced-motion: reduce) {
  body .beacon-corner svg circle { animation: none !important; opacity: .55 !important; }
}

/* ==================================================================================================
   §89 THE ORBIT RINGS FIT THE PORTRAIT SCREEN
   Jason: "i can see them in landscape view, but NOT in portrait view. fix."

   Measured, nothing was hidden: the hero's corner art sat at [-430,-95,570,905], its centre at x=70 inside
   a 390-wide viewport, with the four strokes at 1px and the container at opacity .3 — so only a narrow wedge
   of each ring fell on screen, drawn as a hairline at roughly 13% effective opacity. In landscape the hero
   is 844 wide, the same art catches far longer arcs, and it reads. The system was never sized for a portrait
   screen; it was sized to overflow one.

   Portrait now gets a smaller system that fits the width, positioned so the rings sweep the upper-left where
   the eye already is, at an opacity that survives the ground. Landscape keeps the large overflow version.
   ================================================================================================== */
@media (max-width: 700px) and (orientation: portrait) {
  /* 400px, NOT 620. The art's viewBox is 1000 units wide with the outermost circle at r=500, so the outer
     ring's diameter equals the wrapper's width. At 620px only 17% of ring 2's circumference and 3% of ring
     3's fell inside a 390px viewport — which is why, once visible, it still read as ONE ring pulsing rather
     than several coming in and out. Jason: "they are not repeating like i asked." At 400px the outermost ring
     is about the width of the screen and the inner three sit fully inside it, so all four sweep past. */
  body .hero .beacon-corner.beacon-corner {
    width: 400px; height: 400px;
    top: -30px; right: -150px; left: auto; bottom: auto;
    opacity: .6;
  }
  body .cta .beacon-corner.beacon-corner,
  body .orbit-extra.beacon-corner.beacon-corner {
    width: 400px; height: 400px;
    opacity: .45;
  }
}

/* ==================================================================================================
   §93 THE OPENING BAND'S ORBIT SET SITS WHERE THE HERO'S DOES
   Measured, every set on all ten pages was animating — the rings were simply not in view. On the other
   pages the opening band's only set carried `orbit-extra`: bottom-right of a tall section, at .26. The
   landing page's set is the original hero art, top-right at .30, which is why the rings appeared to exist
   on one page out of ten. The opening band now gets the hero's placement and weight, with the same portrait
   treatment the hero's set takes.
   ================================================================================================== */
body .orbit-open.beacon-corner {
  top: -160px; right: -180px; left: auto; bottom: auto; opacity: .42;
}
@media (max-width: 700px) and (orientation: portrait) {
  body .orbit-open.beacon-corner { width: 400px; height: 400px; top: -30px; right: -150px; opacity: .55; }
}
@media (orientation: landscape) and (max-height: 560px) {
  body .orbit-open.beacon-corner { top: -120px; right: -140px; opacity: .45; }
}

/* --------------------------------------------------------------------------------------------------
   §94 the trace dot. A small green bead that runs the circuit: the rail's centre line down to the divider,
   across it, then down the private box's left edge. The rail's own vertical comet is off — one traveller on
   the whole path rather than one that stops at the corner and another that starts there.
   -------------------------------------------------------------------------------------------------- */
body .guide-trace {
  position: absolute; left: 0; top: 0; width: 7px; height: 7px; margin: -3.5px 0 0 -3.5px;
  border-radius: 50%; background: rgb(34, 179, 94);
  box-shadow: 0 0 0 2px rgba(34, 179, 94, .20), 0 0 14px rgba(34, 179, 94, .9);
  pointer-events: none;
  /* ABOVE THE PANELS. Jason: "I can see the left vertical line, but I can see the animation running down the
     left side" (i.e. he could not). The private panel follows the bead in the DOM and paints over it, so the
     bead showed on the rail — which runs in the gap between the columns — and vanished once it turned down
     the panel's own edge. z-index 9 puts it above the panel's background and its border. */
  z-index: 9;
}
body .dataflow .tech-guide::after { animation: none; opacity: 0; }

/* --------------------------------------------------------------------------------------------------
   §95 the trace's line overlay. I built the SVG and never gave it a rule, so it sat IN THE FLOW: a
   358x6090 element inserted into the dataflow pushed the whole section down — measured, the private
   panel's top moved from ~2,200 to 8,315 page pixels, which is why the drawn line and the box it is
   supposed to follow were nowhere near each other. Absolutely positioned and inset, it overlays the
   section without occupying a single pixel of it.
   -------------------------------------------------------------------------------------------------- */
body .guide-line {
  position: absolute; inset: 0; width: 100%; height: 100%;
  pointer-events: none; z-index: 2; overflow: visible;
}
body .guide-line path { fill: none; }

/* ==================================================================================================
   §96 THE PRIVATE BOX GETS A REAL LEFT EDGE TO TRAVEL DOWN
   Jason: "i still can't see the border line, just the traveling green light." Measured on the phone, the
   private panel's `border-left` is 0px — its only green is a 2px top border and a 1px ring at .4 alpha, which
   is the faint thing he can half see. There was no left border line for the light to run along, and the trace
   was drawn 2px inside the panel, on top of that faint ring.
   Stacked layouts (phones and portrait tablets) now give the private box a solid green left edge, the same
   weight as its top, and the trace rides exactly on it. Side-by-side desktop is untouched — the rules only
   apply while the panels are stacked.
   ================================================================================================== */
@media (max-width: 1000px) {
  body .dataflow .df-panel.good { border-left: 2px solid rgb(34, 179, 94); }
}

/* ==================================================================================================
   §97 THE DESKTOP ORIGIN MOVES FURTHER INTO THE TOP-LEFT CORNER
   Jason: "the orbit rings in the desktop view have an origin that needs to be moved over more to the top
   left side … hopefully, this will work without messing up the mobile view."

   The rings are centred on the art's own corner (cx 20, cy 20 of a 1000-unit box), so the origin on screen is
   set entirely by the wrapper's offsets. On the top bands those were -160px up and -180px off the right: the
   origin sat high but still well inside the width. It moves another 140px up and 140px left, so the arcs open
   from the corner the way the banner reads.

   DESKTOP ONLY, and that is the whole answer to his worry: this block cannot reach a phone. It is a
   min-width:1001px media query, the art is absolutely positioned so nothing in the flow can move, and the
   closing band's corner art — the bottom one, which he did not ask about — is excluded.
   ================================================================================================== */
@media (min-width: 1001px) {
  body section.hero .beacon-corner.beacon-corner { top: -300px; right: -40px; }
  body .orbit-open.beacon-corner.orbit-open { top: -300px; right: -40px; }
}

/* ==================================================================================================
   §98 THE CTA BOOKEND BEACONS, ON EACH SIDE AT EVERY PHONE WIDTH
   Jason: "mobile landscape view, the pulsating beacons that bookend the buttons in the CTA box are not both
   in the right position. one thing you should do is reduce the thickness of the rings and then try to fit
   them on each side."

   Measured at iPhone SE landscape (568x320): the two buttons wrap to two rows (the actions box goes 50px to
   112px tall), and the beacons are ordinary flex children — so they wrapped with the buttons. One sat at
   x=115 in the middle of the first row, the other at x=393 in the second. They are now taken out of the flow
   entirely and pinned to the box's two sides, vertically centred on the whole block, so no amount of wrapping
   can move them. The rings lose two thirds of their weight: they rendered at 3.83px / 5.84px / 12px, and the
   12px one is the thick band that reads as a smear rather than a ring.
   ================================================================================================== */
@media (max-width: 1000px) {
  body section.cta .cta-actions { position: relative; padding-left: 40px; padding-right: 40px; }
  body section.cta .cta-actions > .beacon-mini {
    position: absolute; top: 50%; margin: 0; transform: translateY(-50%);
  }
  body section.cta .cta-actions > .beacon-mini:first-child { left: 0; right: auto; }
  body section.cta .cta-actions > .beacon-mini:last-child { left: auto; right: 0; }
  /* the rings, thinned. The animated pair read their weight from --ring-k (the keyframes own them, so a
     normal rule cannot reach them); the static ones take it directly. */
  body section.cta .cta-actions > .beacon-mini { --ring-k: .42; }
  body section.cta .cta-actions > .beacon-mini svg circle:nth-child(3) { stroke-width: 2px; }
  body section.cta .cta-actions > .beacon-mini svg circle:nth-child(4) { stroke-width: 0.7px; }
  body section.cta .cta-actions > .beacon-mini svg circle:nth-child(n+4) { stroke-width: 0.9px; }
}

/* ==================================================================================================
   §99 THE BEACONS COME OUT OF THE CTA AND THE HEADER, AND THE BUTTONS GET A STELLAR TREATMENT
   Jason: "i think it's easier to remove the beacons because it still doesn't look right. remove them from
   the CTA and animate the buttons with some kind of stellar effect" … "also, you can remove them from the
   header too and animate those buttons."

   So all four decorative beacons — the two bookending the CTA buttons and the header's pair — stop drawing
   entirely, at every width. They carry no words, so the content gate is untouched by their removal.

   THE STARS. The buttons keep their own backgrounds and their text; the effect hangs on the two pseudo-
   elements they already have free (measured: both `::before` and `::after` report `content: none`). Three
   tiled layers of 1px dots drift slowly in opposite directions inside the button, and a soft white band
   sweeps across on a long cycle with a hold, so it reads as starlight crossing rather than a marquee. Only
   brand light: white and mist. Reduced motion needs nothing special — the universal kill freezes both
   animations, which parks the sweep off-screen and leaves a static star field.
   ================================================================================================== */
body section.cta .cta-actions > .beacon-mini,
body nav .nav-cta > .beacon-nav { display: none; }


body section.cta .cta-actions a.btn,
body nav a.btn {
  position: relative; overflow: hidden;
}

/* ==================================================================================================
   §103 EVERYTHING ON THE BUTTONS IS FLAT — INCLUDING "MOST POPULAR"

   Jason: "actually, revert all of the buttons back to flat and no sheen", then "most popular still needs
   to be reverted."

   The first round took the treatment off the buttons but left it on the Growth tier's tag, on my reading
   that a tag is not a button and that his earlier "keep the effect" still stood. He has ruled: it comes off
   too. The tag's 3D face, its bevel and cast shadow, its text shadow, the sheen and the clipping are all
   gone, and with nothing left using `ctaSweep` those keyframes are deleted as well.

   What remains of that whole experiment is the part he asked for and still wants: the CARDS lift on hover.
   Every button and the tag now compute exactly what they did before any of it — verified against the r38
   snapshot, not by eye.
   ================================================================================================== */
@media (hover: hover) and (pointer: fine) {
  body .sec-card, body .price-card, body .df-panel, body .df-box, body .uc-card, body .pillar {
    transition: transform .30s cubic-bezier(.2, .7, .3, 1), box-shadow .30s cubic-bezier(.2, .7, .3, 1);
  }
  body .sec-card:hover, body .price-card:hover, body .uc-card:hover, body .pillar:hover,
  body .df-box:hover {
    transform: translateY(-10px);
    box-shadow: var(--sh-plate), 0 26px 50px -22px rgba(2, 6, 14, .95);
  }
  body .df-panel:hover {
    transform: translateY(-8px);
    box-shadow: var(--sh-plate), 0 26px 52px -22px rgba(2, 6, 14, .95);
  }
  body .price-card.featured:hover {
    transform: translateY(-14px);
    box-shadow: var(--sh-plate), 0 30px 58px -20px rgba(34, 179, 94, .45), 0 26px 50px -22px rgba(2, 6, 14, .95);
  }
}

/* ==================================================================================================
   §106 THE FOOTER TAGLINE WEARS THE HEADER'S FACE
   Jason: "use the same font used in the header for the tagline for the one in the footer and make sure this is
   done for all footer pages including about, privacy, etc."

   Measured on both layouts: the header's tagline (`.nav-tagline`) is JetBrains Mono at 14px with 1.4px of
   tracking, and the footer's (`.footer-bottom .tag-line`) was "Archivo Black" at the same 14px and the same
   tracking — so size and spacing already agreed and only the typeface was different. It was identical on the
   content pages and on the doc-layout pages (privacy, terms, overview, contact), which is why one rule covers
   all ten: the selector names the element rather than a page.

   The child spans are included so "Your Freedom." follows the same face, and the colour rules that make it
   Signal Red are untouched. The footer keeps its own responsive SIZE — it is the deliberate display-furniture
   exception with a clamp for narrow phones, and the mono face has different metrics, so its fit is re-measured
   at 320, 360 and 390 below rather than assumed.
   ================================================================================================== */
body footer .footer-bottom .tag-line,
body footer .footer-bottom .tag-line * {
  font-family: var(--mono);
  letter-spacing: 1.4px;
}

/* ==================================================================================================
   §107 THE NAV PAGE TITLES POP AND GO RED
   Jason: "for the page titles in the header, have them pop and turn red when hovered over and have the
   selected page stay red."

   Hover and focus lift the link two pixels and scale it to 105%, and turn both the text and its underline
   red; the current page holds that red without being hovered. Applying to `.nav-links` and `.nav-utility`
   together covers both rows of the header, and `body` keeps these ahead of the skin's own earlier
   `aria-current` rule, which paints the current page in the plain text colour.

   ON THE RED, once: on this dark navy the brand's Signal Red measures 3.08:1 as type, under the 4.5:1 needed
   for body-sized text, and the established on-dark red for type is #E5708A. He asked for red, the header
   already sets "Your Freedom." in Signal Red, so Signal Red it is — consistent with the rest of the header.
   #E5708A is the one-line swap if he would rather have the contrast.

   THE UTILITY STRIP TAKES THAT SWAP (§107b, 2026-11-06). The strip sits on a lighter ground than the main
   row — `rgba(201,209,224,.028)` over `--ink`, composite #0F1B2D — so Signal Red measures 2.94:1 there, and
   the strip's links are 14px mono body-sized type with no exemption. The current page in that row is drawn
   in `--sig-text` #E5708A, which measures 5.77:1 on the same ground. The state is not colour-alone: the
   link keeps the 1px hairline underline site-tech gives `a[aria-current="page"]` and the `aria-current`
   attribute itself. `.nav-links` keeps Signal Red — this changes the utility row and nothing else.

   HOVER AND FOCUS TAKE THE SAME SWAP (§107c, 2026-11-06). §107b moved the strip's current-page state to
   #E5708A and left hover and focus resolving to Signal Red — 2.94:1 on this ground, i.e. the one red the
   round had just ruled out, still live in the two states a reader meets most often. Contrast applies to
   every state, not only the resting one, so hover and focus move to the same #E5708A the current page
   uses: the strip now has one red for "this is what you are on", and the current-page state keeps winning
   that red while it is hovered, because the `aria-current` rule below still comes last.
   The state is not colour-alone, and did not have to be added: hover and focus already lift the link
   2 px and scale it to 105 % (`transform`, a shape change, not a colour), and site-tech's own hover rule
   still moves the hairline `border-bottom-color` to the beacon. `.nav-links` is untouched.
   ================================================================================================== */
body nav .nav-links a,
body nav .nav-utility a {
  transition: color .18s cubic-bezier(.22, 1, .36, 1), transform .18s cubic-bezier(.22, 1, .36, 1);
  will-change: transform;
}
body nav .nav-links a:hover,
body nav .nav-links a:focus-visible {
  color: var(--sig);
  transform: translateY(-2px) scale(1.05);
}
body nav .nav-utility a:hover,
body nav .nav-utility a:focus-visible {
  color: var(--sig-text);
  transform: translateY(-2px) scale(1.05);
}
body nav .nav-links a:hover::after,
body nav .nav-links a:focus-visible::after {
  background: var(--sig);
  right: 0;
}
body nav .nav-links a[aria-current="page"] {
  color: var(--sig);
  transform: none;
}
body nav .nav-utility a[aria-current="page"] {
  color: var(--sig-text);
  transform: none;
}
body nav .nav-links a[aria-current="page"]::after,
body nav .nav-utility a[aria-current="page"]::after {
  background: var(--sig);
  right: 0;
}
/* the mobile panel paints its own link colours; the current page stays red there too */
body nav.open .nav-links a[aria-current="page"] {
  color: var(--sig);
}
body nav.open .nav-utility a[aria-current="page"] {
  color: var(--sig-text);
}

/* --------------------------------------------------------------------------------------------------
   §108 a figure can never paint outside its own box. The city tiles turn in 3D (a flipboard), and a
   rotating tile paints beyond its parent for part of every flip — which is how artwork ends up across a
   paragraph that sits above it, with nothing in the layout to blame. Clipping the figure stops that
   without touching the animation inside it.
   -------------------------------------------------------------------------------------------------- */
body .case-frame .lb-figure { overflow: clip; contain: paint; }

/* ==================================================================================================
   §109 THE INFERENCE-PACKAGES BAND (homepage, after the hero)

   Jason, 2026-11-04: the inference packages are called out on the homepage at the new official USD
   prices. This is the pricing page's own plate in a three-up row, and every rule here is scoped to
   `.plans` so `pricing.html` cannot move: its four-up `.pricing-grid` and its cards are untouched.

   What the section borrows rather than invents: `.section-header` (eyebrow / head / description / one
   rule carrying the section's single Signal Red mark), the plate (1px `--edge`, squared `--radius-s`,
   flex column), `.price-range` as a mono readout — a price in this room is an instrument reading — and
   the ghost `.btn`. What it does NOT inherit is the green cast on `.price-card.featured` (§37/§38 gave
   that to the pricing page on Jason's ask): here the featured tier keeps the Navy Rise edge and the red
   "Most Popular" tag is the section's only fill, which is the accent budget this band was given.

   Motion: none added. The reveal this band uses is the page's own — devices.js strikes every `section`
   (`.op-live` plus the readout rail) and the skin's existing `prefers-reduced-motion` blocks already
   stop it, so there is nothing new to add to the kill switch.

   Geometry: the readout is one line at every width (`$1,499` never breaks and `/mo` never orphans on a
   line of its own), and the three plates stay equal-height with their action rails aligned, which the
   plate family already does — `.price-card ul { flex-grow: 1 }`, `.price-desc { min-height: 3lh }` and
   `.price-card > .btn:last-child { margin-top: auto }`.
   ================================================================================================== */
.plans-grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 12px;
  align-items: stretch;
}
/* the readout is a single reading: the figure and its unit never separate, and the figure never wraps */
.plans .price-range { white-space: nowrap; }
.plans .price-range span { display: inline; }
/* the featured plate: the Navy Rise edge, the room's dark depth, and no second accent */
body .plans .price-card.featured,
body .plans .price-card.featured:hover {
  box-shadow: var(--sh-plate), 0 24px 48px -30px rgba(2, 6, 14, .9);
}
/* its edge is 2px where its neighbours' is 1px, which would leave its heading 1px low and its action
   1px high against the other two. One pixel comes off the padding to give it back — measured, not
   eyeballed: the three action rails then sit on the same line at every width. */
body .plans .price-card.featured { padding: 19px 17px 17px; }
@media (max-width: 440px) {
  body .plans .price-card.featured { padding: 15px 13px; }
}
/* the closing line: mono, the same class of furniture as the pricing page's rate note */
.plans-note {
  margin: 18px 0 0;
  font-family: var(--mono); font-size: var(--fs-mono); font-weight: 400;
  letter-spacing: var(--track-mono);
  color: var(--txt-3);
}
.plans-note a {
  color: var(--txt-2); text-decoration: none; white-space: nowrap;
  border-bottom: 1px solid var(--edge-3);
  transition: color var(--micro) var(--ease), border-color var(--micro) var(--ease);
}
.plans-note a:hover, .plans-note a:focus-visible {
  color: var(--txt); border-bottom-color: var(--beacon);
}
/* the pricing page's own breakpoints, so the row folds the way the rest of the site folds */
@media (max-width: 1100px) {
  .plans-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
@media (max-width: 620px) {
  .plans-grid { grid-template-columns: minmax(0, 1fr); }
}

/* ==================================================================================================
   §110 THE INFERENCE PLATES ARE THE HERO NOW (homepage only)

   Jason, 2026-11-05: "inference pricing needs to be a hero on the homepage." The band §109 built sat
   BELOW the hero as a second section; it now sits inside the hero, after the opening statement, before
   the hero's actions and the four explore plates. Everything here is scoped to `.hero-plans`, which
   exists only on index.html, so `.plans`' own rules keep working where they are written and no other
   page can see a single declaration from this block.

   What changes, and why: the group head was a full band head — eyebrow, a display-size h2, the
   description in a right-hand column, and a rule with a red segment. Inside a hero that already has an
   h1 with its own red-segment rule, a second display heading and a second rule read as two competing
   mastheads. So the head becomes ONE column, the h2 drops to a label size (the plates' prices are the
   readout now, and they are the biggest numbers on the screen), and the head's rule and baseline marks
   come off — the h1 above already carries them.

   The plates themselves are untouched: §05's plate, §12's `.price-card`, §109's `.plans-grid` and the
   featured tier's Navy Rise edge all still apply. `pricing.html`'s four-up `.pricing-grid` and its cards
   are not addressed by a single selector in this block.
   ================================================================================================== */
.hero-plans { margin: clamp(24px, 3vw, 36px) 0 0; }
.hero-plans .section-header {
  display: block;
  margin-bottom: clamp(16px, 2vw, 24px);
  padding-top: 16px;
  border-top: 1px solid var(--edge);
}
/* the h1 above already owns the readout's red segment and its end ticks: no second pair */
.hero-plans .section-header::before,
.hero-plans .section-header::after { display: none; }
.hero-plans .section-header .eyebrow { margin-bottom: 10px; }
/* a LABEL, not a second masthead: below the h1 by an order of magnitude, above the plates by a step */
.hero-plans .section-header .section-title {
  font-size: clamp(20px, 1.9vw, 27px);
  letter-spacing: var(--track-head);
  line-height: 1.2;
  margin: 0 0 8px;
  max-width: 30ch;
  text-wrap: balance;
}
.hero-plans .section-header .section-desc {
  font-size: var(--fs-small);
  line-height: 1.6;
  max-width: 74ch;
  margin: 0;
  color: var(--txt-3);
}
.hero-plans .section-header .baseline { display: none; }
.hero-plans .plans-note { margin-top: 14px; }
/* the actions follow the plates now, so they need the gap the section boundary used to give them */
.hero-plans + .hero-actions { margin-top: clamp(20px, 2.4vw, 30px); }
/* the plates on a phone: the row stacks (§109), and the stack is tightened so the three prices still
   sit inside the opening screen rather than two scrolls down from it. */
@media (max-width: 620px) {
  .hero-plans { margin-top: 22px; }
  .hero-plans .section-header { padding-top: 14px; margin-bottom: 14px; }
  .hero-plans .plans-grid { gap: 10px; }
  .hero-plans .price-card { padding: 16px 14px 14px; }
  .hero-plans .price-card h3 { font-size: 17px; }
  .hero-plans .price-range { margin: 8px 0 6px; padding-bottom: 9px; }
  .hero-plans .price-desc { margin-bottom: 10px; }
  .hero-plans .price-card ul { margin-bottom: 12px; }
  .hero-plans .price-card ul li { padding: 6px 0 6px 14px; }
  .hero-plans .price-card ul li::before { top: 12px; }
}

/* ==================================================================================================
   §111 THE HERO'S ORBIT FIELD (homepage only)

   Jason, 2026-11-05: "animations on the homepage: need to see more rings (red, white and blue) coming
   into view and leaving just like on the other pages."

   He was right about the cause. The hero's one set was pushed off the text column at `opacity: .30`
   (§89 sized it for the portrait screen, §93 gave the OTHER pages' opening band .42); the homepage had
   two sets on the whole page, one of them in the closing band. Every other page's opening band shows a
   set at .42 that the reader watches swell and fade; the homepage showed a ghost.

   Three more sets now sit in the hero, all of them the brand's OWN art at its own geometry — `cx/cy
   20,20`, radii 150/330/520, a filled red core — built in the markup and painted by `orbitRings()`
   (which recolours every circle red / white / navy / faint white / faint navy in document order) and
   animated by `orbitBreath()`'s single frame loop. No second motion system: the same 8s frame loop, the
   same 0.25→0.90→0.25 curve, and the sets themselves are staggered by `orbitBreath()`'s per-set phase
   so the first screen reads as a field arriving and leaving rather than five copies pulsing together.

   Everything is a child of `.hero`, which is `overflow: hidden`, so no set can ever widen the document.
   Each is scaled by its wrapper (its own `width`/`height`), so the arcs are sized in band terms instead
   of the fixed 1000px SVG box: the art occupies the top-left 540 of 1000 units, so a 760px wrapper
   draws arcs of 114/251/395px.

   `prefers-reduced-motion`: both runtime functions return before they build or paint anything, and
   §88's reduced-motion block pins every circle at a still, visible `opacity: .55 !important`. Nothing
   new is added to the kill switch, and nothing here can animate past it.
   ================================================================================================== */
body .hero .beacon-corner.orbit-ra,
body .hero .beacon-corner.orbit-rb,
body .hero .beacon-corner.orbit-rc { left: auto; bottom: auto; }
body .hero .beacon-corner.orbit-ra svg,
body .hero .beacon-corner.orbit-rb svg,
body .hero .beacon-corner.orbit-rc svg { width: 100%; height: 100%; display: block; }

/* THE FIELD, PLACED BY ITS ANCHOR. The art's centre is the SVG's OWN top-left corner (cx/cy 20,20), so
   a set is positioned by putting that corner where the arcs should spring from — the wrapper's own
   size then sets the reach of the outermost ring (520 of the art's 1000 units, scaled by the wrapper).
   Four distinct origins, so at any instant some arcs are long across the band and some short near it:
   Jason's own hero origin at the top of the measure (§97 — untouched), one off the top-right in the
   open ground beside the h1, one long diagonal that crosses the whole band, and one off the left edge.
   All four live in the hero's upper half: below that the plates are opaque, and a ring painted behind
   an opaque plate is a ring nobody sees.

   SPECIFICITY: §97 places the hero's corner art at `body section.hero .beacon-corner.beacon-corner`
   (0,3,2) for every set at ≥1001px, so each placement here doubles its own class to land at (0,4,2).
   Measured before this correction: all four sets shared §97's origin and differed only in size — four
   concentric systems, not a field. */
.hero .beacon-corner { opacity: .52; }
@media (min-width: 1001px) {
  body section.hero .beacon-corner.orbit-ra.orbit-ra { top: -260px; right: -520px; left: auto; bottom: auto; width: 1100px; height: 1100px; opacity: .46; }
  body section.hero .beacon-corner.orbit-rb.orbit-rb { top: -420px; right: -900px; left: auto; bottom: auto; width: 2000px; height: 2000px; opacity: .26; }
  body section.hero .beacon-corner.orbit-rc.orbit-rc { top: -60px; right: auto; left: -380px; bottom: auto; width: 1200px; height: 1200px; opacity: .30; }
}
/* portrait: the sets §89 sized for the phone keep that treatment, and the three new ones take their
   own positions in the same column of the screen — so scrolling the hero is scrolling through them. */
@media (max-width: 700px) and (orientation: portrait) {
  /* the phone stack: four anchors down the first two screens, so scrolling IS the arrival. Each is
     sized so its outermost ring is roughly the screen's width — the arc has to cross the band, not sit
     off its edge. */
  body .hero .beacon-corner.orbit-ra.orbit-ra {
    /* the brand's art ends in a FILLED core disc at the set's own corner (cx/cy 20,20). Measured, that
       disc sat on the tagline at y 91 and took the 7.11:1 line to 3.89:1 — a fill cannot be tuned with
       stroke-opacity, so the set moves until its core is in the strip above the tagline instead. */
    width: 430px; height: 430px; top: -16px; right: -230px; left: auto; bottom: auto; opacity: .72;
  }
  body .hero .beacon-corner.orbit-rb.orbit-rb {
    width: 700px; height: 700px; top: 190px; right: auto; left: -300px; bottom: auto; opacity: .34;
  }
  body .hero .beacon-corner.orbit-rc.orbit-rc {
    width: 520px; height: 520px; top: 620px; right: -260px; left: auto; bottom: auto; opacity: .45;
  }
}
/* short landscape (a phone on its side): the band is shallow, so the low set comes in under the plates */
@media (orientation: landscape) and (max-height: 560px) {
  body .hero .beacon-corner.orbit-rc.orbit-rc { top: 120px; opacity: .38; }
}

/* ==================================================================================================
   §112 THE HERO'S MEASURE, BECAUSE THE PLATES NOW HAVE TO FIT IN THE OPENING SCREEN

   The hero was measured for one statement and two buttons; it now carries the statement, the plates and
   the buttons. Rather than shrink the plates (they are `pricing.html`'s own component and cannot diverge),
   the head above them is tightened: the h1 keeps two lines at every width but its ceiling comes down from
   78px, and the four gaps between the blocks come down with it. Measured at 1440x900 before/after in
   evidence/geometry.json — the number that matters is how much of the plate row is inside the first
   screen, because that is the one Jason asked to see first.

   This block is additive and comes last, so it wins on the same specificity rather than editing §08's
   originals — §08 stays readable as the hero's construction, and every number that changed is here.
   ================================================================================================== */
.hero { padding-top: clamp(34px, 4.4vw, 64px); }
.hero h1 {
  font-size: clamp(32px, 5.2vw, 68px);
  margin-bottom: 18px;
  text-wrap: balance;
}
.hero h1::after { margin-top: clamp(16px, 1.8vw, 22px); }
.hero .tagline { margin-bottom: 16px; }
.hero p.hero-lede { margin-bottom: 14px; }
.hero p.hero-punch { margin-bottom: 24px; }
.hero-plans { margin-top: clamp(20px, 2.4vw, 28px); }
.hero-plans .section-header { margin-bottom: clamp(14px, 1.6vw, 20px); }
@media (max-width: 620px) {
  .hero h1 { font-size: clamp(30px, 8.6vw, 40px); }
  .hero { padding-top: 26px; }
  .hero p.hero-punch { margin-bottom: 20px; }
}

/* ==================================================================================================
   §113 THE HERO'S RING FIELD CARRIES WEIGHT AND PRESENCE (homepage only)

   Jason, 2026-11-05: "need to see more rings (red, white and blue) coming into view and leaving".
   §111 gave him the count and the phase; measured, none of it could be seen. The three hues painted at
   a 16-20 unit luminance lift on strokes 1-1.4 CSS px wide, inside containers at .26-.52 — under the
   40-unit bar the craft reference sets for a device that must read, and under its 3 px floor for an
   edge that survives motion. Red and navy were the worst: brand red over ink tops out at 36.5 units
   and navy at 40.1, while white reaches 224 — so at one shared alpha white was the only hue with any
   presence. Two levers, neither of them the count:

     1. WEIGHT — the runtime paints 3.0 / 2.6 / 2.4 CSS px on the inner, middle and outer rings (the
        circles are `vector-effect: non-scaling-stroke`, so those are rendered pixels, not viewBox
        units). The same ladder is repeated here for the no-JS frame and the reduced-motion still.

     2. PRESENCE — each set's container opacity is raised in a ladder by distance from the reader, and
        the strokes are equalised per hue so all three land in one band instead of white alone
        carrying the field.

   THE CEILING IS THE TYPE, NOT THE TASTE. The field sits behind the hero's text, so the peak alpha is
   also the contrast ceiling of every leaf it crosses — measured on the composited frame, at each
   leaf's own glyph pixels. Solving 4.5:1 against the dimmest leaf each hue actually crosses gives the
   alphas below: at 1440 the pink h1 accent is the binding leaf for navy (4.47:1 at .61 → .58), at 375
   the 12px mono punch is the binding leaf for navy and the tagline for red. That is why the phone's
   field is dimmer than the desktop's: the phone's first screen is text edge to edge, so every ring
   crosses something. Numbers and the arithmetic: evidence/fix/after-rings.json, REPORT.md.
   ================================================================================================== */
body section.hero .beacon-corner.beacon-corner svg circle:nth-child(1) { stroke: #C8102E; stroke-width: 3px; stroke-opacity: 1; }
body section.hero .beacon-corner.beacon-corner svg circle:nth-child(2) { stroke: #F4F5F8; stroke-width: 2.6px; stroke-opacity: .16; }
body section.hero .beacon-corner.beacon-corner svg circle:nth-child(3) { stroke: #21406F; stroke-width: 2.4px; stroke-opacity: .70; }
body section.hero .beacon-corner.beacon-corner svg circle:nth-child(n+4) { stroke-width: 2.4px; }

/* the ladder: nearest set brightest, the 2000px diagonal held back so it stays depth rather than haze */
body section.hero .beacon-corner.beacon-corner { opacity: .85; }
body section.hero .beacon-corner.orbit-ra.orbit-ra { opacity: .75; }
body section.hero .beacon-corner.orbit-rb.orbit-rb { opacity: .50; }
body section.hero .beacon-corner.orbit-rc.orbit-rc { opacity: .70; }

/* PORTRAIT: every ring crosses type, so the equalisation is retuned to the phone's binding leaves
   (the tagline for red, the mono punch for navy) and the long diagonal is held lowest — it is the one
   that sweeps the punch line. */
@media (max-width: 700px) and (orientation: portrait) {
  body section.hero .beacon-corner.beacon-corner svg circle:nth-child(1) { stroke-opacity: .68; }
  body section.hero .beacon-corner.beacon-corner svg circle:nth-child(2) { stroke-opacity: .155; }
  body section.hero .beacon-corner.beacon-corner svg circle:nth-child(3) { stroke-opacity: .50; }
  body section.hero .beacon-corner.beacon-corner { opacity: .80; }
  body section.hero .beacon-corner.orbit-ra.orbit-ra { opacity: .72; }
  body section.hero .beacon-corner.orbit-rb.orbit-rb { opacity: .28; }
  body section.hero .beacon-corner.orbit-rc.orbit-rc { opacity: .68; }
}

/* the reduced-motion still frame: no cycle, but the full red/white/blue palette at a weight that reads.
   §88 pins .55 site-wide; the hero's equalised strokes are balanced at .8 — one family, three hues,
   completely still. */
@media (prefers-reduced-motion: reduce) {
  body section.hero .beacon-corner.beacon-corner svg circle { animation: none !important; opacity: .8 !important; }
}

/* ==================================================================================================
   §114 THE HERO'S ORBITS READ AS SWEEPS, NOT AS ONE RING SYSTEM AROUND AN UNSEEN BEACON

   Jason, 2026-11-05: "the orbiting rings that are spinning around the beacon that is off the screen so
   just the rings are visible" — and pointed at the live site as the reference. Measured before this
   block, at 1440x900: all four hero sets had their filled core OUTSIDE the viewport (y -140 to -282, one
   at x -356) while drawing at 3.0/2.6/2.4px, so the first screen carried four concentric, clearly curved
   arcs whose common centre was just above the frame. That reads as one system orbiting a beacon you
   cannot see. The live site had the same geometry at 1.4px and ~.30 opacity, which reads as atmosphere.

   The fix is not to hide the rings and not to thin them back to hairlines: it is to give every set a much
   LARGER reach, so the arcs crossing the band are shallow and no two of them share a readable centre.
   Radius is the lever, opacity second. Weight stays near §113's so the art is still present.

   Verified after: 4 sets, no core inside the frame at 1440 (none can be — that is the point), no arc
   reads as a closed or near-closed circle, hero text contrast unchanged (re-measured on the composited
   frame), and 0 horizontal overflow.
   ================================================================================================== */
@media (min-width: 1001px) {
  /* each set is pushed far enough out that only its outer rings cross the band, and each origin is far
     from the others — so the first screen reads as four unrelated sweeps rather than concentric rings */
  body section.hero .beacon-corner.orbit-ra.orbit-ra {
    width: 3000px; height: 3000px; top: -1180px; right: -2450px; left: auto; bottom: auto; opacity: .46;
  }
  body section.hero .beacon-corner.orbit-rb.orbit-rb {
    width: 4600px; height: 4600px; top: -2450px; right: auto; left: -2600px; bottom: auto; opacity: .30;
  }
  body section.hero .beacon-corner.orbit-rc.orbit-rc {
    width: 3600px; height: 3600px; top: -320px; right: auto; left: -3050px; bottom: auto; opacity: .40;
  }
  /* the hero's own §97 set joins them, rather than sitting alone at a tight 1000px radius */
  body section.hero .beacon-corner.beacon-corner {
    width: 2400px; height: 2400px; top: -860px; right: -1250px; left: auto; bottom: auto; opacity: .42;
  }
  /* thinner than §113's 3/2.6/2.4: a shallow arc at that weight reads as a drawn circle once its radius
     is this large, because the same number of pixels is doing far less turning */
  body section.hero .beacon-corner svg circle { stroke-width: 2.6px; }
}

/* ==================================================================================================
   §120 THE MONOGRAM IS A SUN, NOT A PULSE — FIVE STATIC ORBITS, ONE PLANET EACH

   Jason, 2026-11-05: "the red dot on the logo is the fixed center beacon, which is what i wanted. the
   bad: the bands/rings spacing needs to be wider and they need to not pulse in and out, but instead
   orbit the red dot and stay behind the text on the page. i want the rings to look like planets orbiting
   around the sun, which is the red dot beacon in this case."

   §117–§119 are gone, not tuned. They described a device that arrived and left; he asked for a system
   that stays. Three model changes, and each one answers one of his sentences:

   1. THE LAYER LEFT THE NAV. The art used to be a child of `nav` (z-index 100), which is why it painted
      over the hero's type — the defect he is naming. It is now a page-root layer: `position: fixed`
      (the header is sticky at top 0, so the dot's viewport position does not move as the page scrolls
      and the orbits stay pinned to it), `pointer-events: none` (decoration must never swallow a click),
      `z-index: 0` — above the hero's own background, below every text layer on the page: `.hero >
      .container` and `section > .container` both sit at z-index 1 and the nav sits at 100.
   2. THE LOOP NO LONGER OWNS THIS SET. The layer is no longer `.beacon-corner`, and `orbitBreath()`
      plans `.beacon-corner` sets, so no inline opacity and no scale from that loop can land on these
      five circles. Constant brightness is the property that makes the pulsing unrepeatable: the only
      thing writing to this art per frame is the five planet positions in the runtime.
   3. THE SPACING IS A LADDER. Radii are 150 / 360 / 620 / 930 / 1290 CSS px, so the gaps are
      210 / 260 / 310 / 360 — they grow outward and each ring reads as its own orbit. The old set measured
      90 / 198 / 312 / 432 / 552 (gaps 108 / 114 / 120 / 120): five nearly equal steps inside one small
      box, which is why they read as one band rather than five orbits.

   The box is 3200 × 3200 with `viewBox="-1600 -1600 3200 3200"`, so 1 user unit is exactly 1 CSS px and
   the radii above are the rendered radii. The wrapper is the viewport (`inset: 0; overflow: hidden`),
   which is what keeps a 3200px artwork from widening the document; the svg is centred on the dot with a
   negative margin rather than a transform, because the runtime also writes a scale onto it.
   ================================================================================================== */
.logo-orbit {
  position: fixed; inset: 0; z-index: 0;
  pointer-events: none; overflow: hidden;
  /* NO OPACITY ON THE LAYER. It used to be .62, which capped every body in it — and a 24px halo at 42%
     inside a 62% layer composites to 26%, which is not a glow, it is a smudge. The .62 now sits on
     `.orbits` below, so every ring lands on exactly the luminance it had (same multiplication, one level
     down) and the planets are free to be the brightest things in their own space. */
  /* the beacon, in CSS px from the viewport's top-left. js measures the mark's own geometry (the dot is
     at 17 / 13 of a 48-unit viewBox) and overwrites both; these are the approximate fallbacks, so the art
     is not stranded at the corner if the runtime never runs. */
  --bx: calc(max(0px, (100vw - var(--max-w, 1200px)) / 2) + var(--gutter, 24px) + 12px);
  --by: 40px;
  --art-scale: 1;
}
/* The ring weight, and the only number this dial has. It started at .62 (the value the layer carried before
   it was pushed down onto this group, so the planets could stay bright), then .42 when Jason asked for less
   distraction. He then said it twice in a row — "the planetary rings need to be lighter. they are still too
   bold and taking away from the text and other items on the page" / "make the rings even lighter" — so the
   band itself moved down to .16-.20 and .20 shipped: the TOP of that band, because it is the value at which
   every hue still reads as a line. Measured on the rendered frame, per radius, peak above the pixel's own
   ground: at 1440 the five orbits sit 7.9 / 27.4 / 18.5 / 26.1 / 13.5 levels up (r=120/220/340/480/660), and
   at 375 they sit 5.5 / 23.1 / 14.7 / 20.1 / 9.6 — all above the 4-level floor this round set, red r=120
   included, so no per-ring `stroke-opacity` lift was needed anywhere. .16 was rejected on measurement, not
   taste: the red ring drops to 3.96 at 375, under the floor. Arc continuity is unchanged from .42 (the
   longest unpainted run on each circle is identical at every value — those runs are type and panels sitting
   above the art, not the ring fading out), which is the proof the arcs read as arcs rather than dashes.
   Nothing else moves: the planets are outside this group, and their discs measure byte-identical with this
   group zeroed (evidence/ringweight3/planets-*.json). */
.logo-orbit .orbits { opacity: .20; }
.logo-orbit > svg {
  position: absolute; left: var(--bx); top: var(--by);
  width: 3200px; height: 3200px; margin: -1600px 0 0 -1600px;
  display: block; transform: scale(var(--art-scale)); transform-origin: 50% 50%;
}

/* THE CENTRE IS THE DOT, AND IT IS NOT A NUMBER ANYONE TYPED (index.html §122, ruled 2026-11-05).

   The margin above is half the 3200px box, so the svg's own centre lands exactly on (--bx, --by), and the
   runtime measures those two values out of the mark's geometry (the dot at 17/48 and 13/48 of the mark's
   48-unit viewBox). The circles' centre is therefore the logo's red dot by construction: no offset vector,
   no second centre, and no fallback that has to describe a composition the page does not ship. Change the
   logo's inset and the art follows it; scale the art in portrait and it scales about its own centre, which
   stays on the dot. Measured on the built page: art centre minus dot = -0.01/0.00 px at 1440x900 and
   -0.01/-0.01 px at 375x780 (evidence/prepublish/orbit.json) — the two-decimal beacon rounding. */
/* Rings keep their weight when the art is scaled down for a phone: on a 2px stroke the scale would
   otherwise turn the outer orbits into hairlines, and in portrait they already read as shallow arcs. */
.logo-orbit .orbit { stroke-width: 2px; vector-effect: non-scaling-stroke; }

/* The planets are filled bodies, not hairline marks. 8px across at 1x, plus a 24px halo behind the disc —
   three times the disc's diameter, in the disc's own hue — so the body reads as lit rather than as another
   pinprick on a page that already has 46 starfield nodes. The hue is lifted from the ring the planet rides
   so the moving point is always brighter than the line it travels on (measured 2.9-4.5x the ring's own
   composited peak; the numbers are in the round's report). Both circles are counter-scaled with the group,
   so 8px and 24px are CSS px on every screen, not art units. */
.logo-orbit .planet .disc { stroke: none; }
/* the halo must not be clipped by the group it sits in, and it is drawn first so it lands behind the disc */
.logo-orbit .planet .halo { stroke: none; }

/* ONE SECTION HAS TO BE TOLD ABOUT THE NEW PLANE. The footer alone was not enough: MEASURED at 1440, five
   elements on the homepage were stacking contexts at z-index 0 — `section.hero`, `section.cta`, `.cta-box`,
   the tech-field canvas and the closing band's own ring art. A root-level layer at z-index 0 paints AFTER
   them in tree order, so it landed above their whole subtree, their type included: the lede's solid glyph
   pixels moved up to 48 levels with the ring behind them (measured, art on vs art off, glyph-core only).
   Dropping those three to `z-index: auto` keeps every background, pseudo-element and child plane exactly
   where it was, but lets the `.container` planes (z-index 1) win at the ROOT — which is the plane this
   layer needs: above the ground, below the type. Re-measured after: 0 glyph-core pixels differ >1 level.
   The canvas (opacity .55) and the band's ring art stay their own contexts; they are decoration. */
body .hero, body section.cta, body .cta-box.cta-red { z-index: auto; }

/* and the footer, which is the one section whose text is NOT inside a numbered container: it takes one
   plane above the art so no footer glyph can be overdrawn. Measured at 1440 scrolled to the footer: the
   footer's column headings were the only text on the page still at `z-index: auto`. */
footer { position: relative; z-index: 1; }

/* ==================================================================================================
   §122 THE NINE INNER PAGES CARRY THE SAME SYSTEM, AND THEY NEED THE SAME PLANE (2026-11-06)

   Jason: "replicate the planetary animation on all of the pages per the homepage spec."

   WHAT IS THE SAME. The art block in each of the nine pages is not retyped — it is copied out of the
   frozen index.html by scripts/planets-allpages-insert.py, so the radii (120/220/340/480/660), the
   periods (18.0/29.2/41.4/54.6/70.4 s), the hues, the 8 px discs with 24 px halos and the `data-r` /
   `data-period` attributes are identical by construction. The runtime is untouched: `monogramOrbit()`
   already keys on `.logo-orbit` plus `nav .logo svg.mark`, measures the dot from the mark's own 17/48 and
   13/48 box, and parks the five bodies on five distinct angles when motion is reduced. The legacy
   `.beacon-corner` sets are gone from all nine pages, and `orbitRings()` — which builds a set into the
   opening band of a page that has none — bails on `.logo-orbit`, so one ring system per page is a
   structural fact, not a per-page promise. MEASURED at runtime after: 0 `.beacon-corner` sets on all nine.

   WHAT WAS NOT THE SAME: THE PLANE. The homepage had already been fixed (the rule above); the inner pages
   had not, and the art is the last child of `<body>` at z-index 0, so it paints after any subtree that
   sits at z-index auto in tree order. MEASURED, art on vs art off, glyph-core pixels only:
     · `section.how-it-works` (about, how-it-works) and `section.cost-section` (pricing) were stacking
       contexts at `z-index: 0` — their `.container` at 1 was trapped inside them, and their type moved up
       to 46 levels with the ring behind it;
     · overview, privacy, terms and contact had no plane over the type at all: it sat in a `.container`
       (or, on contact, in `main`) at `z-index: auto`, i.e. below the art in tree order.

   THE FIX IS THE HOMEPAGE'S, SCOPED SO THE HOMEPAGE CANNOT SEE IT. `data-planetary` is on the `<html>` of
   exactly these nine pages and index.html carries no such attribute, so nothing here can reach the frozen
   page. Two moves, both of them the homepage's own: the sections that were stacking contexts at 0 go back
   to `auto` (their container then wins at the root), and the pages whose type had no plane get one at the
   same z-index the homepage's containers use. The plane goes on the SMALLEST TRANSPARENT WRAPPER around
   the type rather than on the page wrapper, on purpose: `.container`, `main.page-wrap`, `article.doc` and
   `section.blk` all carry the page's ink, and lifting one of those would have put an opaque ground above
   the art and deleted the rings from that whole region. Lifting `.doc > *` and `.blk > .panel` leaves
   every ground where it was — below the art — so the rings still cross the document column and the page
   bands, and only the leaf cards (which are content planes, the same way the homepage's `.cta-box` is)
   sit above them. Re-measured after: 0 glyph-core pixels differ by more than one level on all nine
   (evidence/planets-all/glyph.json). */
html[data-planetary] .how-it-works,
html[data-planetary] .cost-section { z-index: auto; }

html[data-planetary] .ld-wrap,
html[data-planetary] .blk > .blk-head,
html[data-planetary] .blk > .pillars,
html[data-planetary] .blk > .panel,
html[data-planetary] .blk > .chips,
html[data-planetary] .doc > * { position: relative; z-index: 1; }

/* REDUCED MOTION HAS NOTHING TO STOP HERE. The orbits were never animated, and the runtime parks the five
   planets at five distinct angles (their markup transforms already are that still) writing no per-frame
   position at all. So there is no keyframe, no scale and no opacity on this set to pin — the still frame
   is the same system with the planets standing where the clock would have put them.
   The portrait scale is NOT motion, so it stays on for a motion-sensitive reader too. */

/* ==================================================================================================
   §121 THE PLANS NOTE CLOSES THE ROW, NOT ITS OWN LEFT THIRD (homepage only, 2026-11-06)

   Jason: "please make this sentence span below the cards, but make it flexible to adjust on mobile
   devices or smaller screens."

   THE MECHANISM, MEASURED, NOT GUESSED. `.plans-note` declares no width of its own and `.plans` /
   `.hero-plans` are plain blocks — so nothing here was a flex item shrinking to content, and no
   `display` on any ancestor was sizing it. The 660px the note held inside a 1120px row came from a
   rule written for the HERO'S PROSE: `assets/base-landing.css:318` `.hero p { max-width: 660px }`,
   inside `@layer components`. `.plans-note` is a `<p>` inside `.hero`, so it inherits that cap; the
   type, margin and colour parts of the same `.hero p` rule are already defeated by the unlayered
   `.plans-note` block (§109) — unlayered beats layered — but `max-width` was the one property that
   block never set, so the cap survived. Proved by setting `max-width: none` on the live node:
   measured width went 660 -> 1120, exactly the grid's content width, with no other declaration
   touched. Left alignment was never in question: `.plans-note { margin: 18px 0 0 }` already
   outranks the layered `margin: 0 auto 40px`, so the 460px of leftover was always to the right.

   WHAT CHANGES AND WHAT DOES NOT. One property is released, scoped to `.hero-plans` so `pricing.html`
   and every other `.hero p` on the site keep the 660px measure that was written for them: the note's
   box is now the row's content box. Its furniture is not addressed here at all — mono family,
   `--fs-mono`, `--track-mono`, `--txt-3`, the link's `--txt-2` / `--beacon` focus treatment and the
   `margin-top` that sets the gap above it all come from §109/§110 and are untouched. One line at
   1440 instead of two, so the block above the rule gets shorter; §114's rule holds that geometry
   either way, because its margins are halves of `.explore-block`'s own gap and do not read the note.

   `text-wrap: balance`, NOT `pretty`. `pretty` is what the note already inherited from `.hero p`, and
   measured at 375 it left the closing line 157px wide in a 343px box — the anchor stranded on a
   short last line. `balance` evens the block instead: 241 / 260 / 269 at 375 and 400 / 381 at 768,
   identical to `pretty` at 320 (241 / 260 / 269), and inert above ~900 where the sentence is one
   line. It is also a no-op on the other pages, which do not match this selector.

   THE ANCHOR KEEPS `nowrap`. It is not what forces a bad break — releasing it is what produces one:
   measured at 375 with `white-space: normal` the link splits across two lines, "See all" ending line
   2 and "plans →" opening line 3. Held together it lands whole on the last line, at most 269px into
   a 288px box at 320, so it never overflows the narrowest width the site supports. */
.hero-plans .plans-note {
  max-width: none;
  text-wrap: balance;
}

/* ==================================================================================================
   §124 THE TWO EXPLORE FURNITURE ASKS: A TRAVELLING RED DOT, A GREEN TICK UNDER A RED PULSE

   Jason, 2026-11-06: "on the homepage, add a red moving dot to the animation on the How it works card, a
   green checkmark with the pulsing ring red on security and trust."

   (a) HOW IT WORKS. The card's device is the site's own `.flow-dots` — three 6px dots in a 5px-gap row,
   painted `--txt-4` by 08b above and animated only as a row (`techDevicePulse` on the wrapper). Nothing in the
   row moved. A fourth dot, `.flow-agent`, is added in `index.html` and travels left to right across the
   three: the three are the track, the red one is the agent. The three keep their size, their gaps, their
   colour and their keyframes; the new dot is the only thing that travels.

   THE ROW'S BOX MUST NOT CHANGE, and it does not, because the dot is taken out of flow: `position:
   absolute` inside `position: relative` `.flow-dots`, so the row stays 28px wide and 6px tall and the
   card's own box is decided exactly as before. Travel is 22px = the row's 28px less the dot's own 6px,
   so the dot leaves the track's last dot at rest and never spills outside the motif.

   TRANSFORM ONLY, and CSS does the moving. The animation is one `transform` (translate X plus the -50%
   Y centring, which is why the keyframes carry both), driven by the class, not by the runtime: measured
   on the live page the dot reports `flowAgent / 2.6s / running` from `getAnimations()`, so no
   `tech-runtime.js` fallback is needed and none was added. `ease-in-out` rather than the brand ease:
   `--ease` front-loads ~90% of its travel into the first third of the duration, which reads as a flick
   and then a wait. The loop resets to the left in one frame — that is what a looping one-way pass is,
   and a 6px dot makes it a single-frame change rather than an event.

   (b) SECURITY & TRUST. The tick (`svg .check`) is drawn green and the pulse ring (`.shield-ring`) is
   red. THE GREEN IS NOT A BRAND COLOUR: the palette is Ink, Navy, Signal Red, beacon, steel, mist,
   paper, white — it owns no green, and §20b of this file already records what happens when one creeps in
   from `site-tech.css` (it is translated back to paper). This green therefore lives HERE, in one
   section, as a literal, and is flagged to Jason as new ink rather than promoted to a token: `#3FA46A`,
   the value the brief names when the palette has none. Measured against the card's own painted ground it
   is 5.8:1, so it clears the 3:1 graphic floor with room. The ring's red is `--sig` (#C8102E, the brand's
   Signal Red, 3.08:1 on Ink) — no new red was invented. Its radius, its border width, its 2.4s `shieldRing`
   rhythm and its opacity envelope are untouched; only `border-color` changes, which is the whole ask.

   REDUCED MOTION IS THE ONE PLACE THIS IS NOT PURELY A COLOUR CHANGE, and it is the ask's own condition
   ("the red dot parks at the left, visible, no motion"; "the ring holds a visible static border in red,
   the tick stays green"). Paused at 0% both devices are invisible as shipped: `shieldCheck` starts at
   `stroke-dashoffset: 10` (the whole tick dashes away) and `shieldRing` starts at `opacity: 0`, so under
   reduce the card has no tick and no ring at all. Both are restored static here — the tick finished and
   therefore legible in green, the ring at the pulse's own 0.6 peak — because a colour that nothing paints
   is not a colour change. Nothing loops: 0 running animations in the two cards, measured. */
.explore-grid .sec-card .flow-dots { position: relative; }

.explore-grid .sec-card .flow-dots .flow-agent {
  position: absolute; left: 0; top: 50%;
  width: 6px; height: 6px; border-radius: 50%;
  background: var(--sig);
  opacity: 1;                      /* base-landing's `.flow-dots span` carries .25 for the loader beat */
  transform: translate(0, -50%);
  animation: flowAgent 2.6s ease-in-out infinite;
}

@keyframes flowAgent {
  0%   { transform: translate(0, -50%); }
  100% { transform: translate(22px, -50%); }
}

/* graphic ink only — a 2px stroke, never type. See (b) above: the palette has no green.
   08b's `.explore-grid .sec-card svg [stroke]:not([stroke="none"])` scores (0,4,1) and beats a plain
   4-class selector, so the `body` element here is load-bearing: without it the tick stays steel. */
body .explore-grid .sec-card .shield-pulse .check { stroke: #3FA46A; }

/* (c) THE PULSE RING — geometry, keyframes and colour are all owned HERE, unlayered, at every width.

   THE ROUND-2 DIAGNOSIS WAS WRONG, AND THIS IS THE MEASUREMENT THAT SAYS SO. It claimed base-landing
   traps this rule inside `@media (max-width:560px)` (line 343) and `@keyframes shieldRing` inside
   `@media (max-width:880px)` (line 759), so above 880 the ring would sit at a constant opacity 0.
   Neither block contains it: both are at TOP level — the geometry rule is inside `@layer components`
   (opened at base-landing:162) and the keyframes are at the root of the sheet, after `@layer responsive`
   closes at 762. `scripts/shieldring2-probe.mjs` reads the CSSOM rather than the source text, at 1440,
   1200, 1000, 880, 800, 600, 560, 500 and 375: on every one of them `.shield-ring` is `position:
   absolute` donated by a `media=all` rule and `animation-name: shieldRing` resolves against a keyframes
   rule reported at top level, and opacity sampled at 10 Hz for 5 s peaks at .599 with 24–26 of ~49
   samples above .3. The ring has always pulsed above 880. What it lacked was ownership: both halves of
   its definition live in base-landing's `@layer components`, so any unlayered rule (this file) outranks
   them and could orphan the ring without touching its source. It therefore gets its own name,
   `lsShieldPulse`, its own copy of the geometry, and both live unlayered here.

   WHY THE COLOUR IS `--beacon` AND NOT `--sig`: the ≥3:1 floor is unreachable in Signal Red on this
   plate. #C8102E composited over the measured card ground (20,32,50) is 2.79:1 at FULL opacity — that
   is the ceiling, so raising the peak from .6 cannot get there by itself. Brand v3.3 tokens.json gives
   `beaconRed #F0455F` the role "Beacon rings and live indicators on Ink. Never type, never a surface",
   and this sheet already carries it as `--beacon` (line 67). At the .85 peak it renders 3.52:1.
   Reverting to Signal Red is this one word.

   The parent is `position: relative` below so `inset: -6px` centres on the shield: measured at 1440 the
   ring is 28.9x31.0 inside a 17.3x19.5 shield box, i.e. -6.5/-6.5/+6.4/+6.5 px past each edge (the
   half-pixel is the 1.5px border snapping to 1 device px at DPR 1). */
.explore-grid .sec-card .shield-pulse { position: relative; }

.explore-grid .sec-card .shield-ring {
  position: absolute; inset: -6px;
  border-radius: 50%;
  border: 1.5px solid var(--beacon);
  opacity: 0;
  animation: lsShieldPulse 2.4s ease-out infinite;
}

@keyframes lsShieldPulse {
  0%   { transform: scale(.6); opacity: 0; }
  45%  { opacity: .85; }
  100% { transform: scale(1.4); opacity: 0; }
}

@media (prefers-reduced-motion: reduce) {
  .explore-grid .sec-card .flow-dots .flow-agent {
    animation: none !important;
    transform: translate(0, -50%);
  }
  body .explore-grid .sec-card .shield-pulse .check { stroke-dashoffset: 0 !important; }
  .explore-grid .sec-card .shield-ring { opacity: .6 !important; transform: none !important; }
}

/* ============================== 08e THE FLATLINE: RED WHILE IT WIGGLES, GREEN WHEN IT STRAIGHTENS ===

   Jason: "have it red when it's not straight and then green when it goes straight." The motif already
   carried both states as two paths and swapped them by opacity alone. Colour now carries the same state,
   so the change reads at a glance instead of only on the shape.

   THIS IS WHERE THE LINE BECOMES RED, NOT WHERE IT STAYS RED. §08b's `.explore-grid .sec-card .flatline
   svg [stroke] { stroke: var(--txt-4) }` paints the card's line steel (#7689A6) — the ornaments are
   monochrome there so the hero's red budget stays with the beacons — so the red is introduced here, and
   the colour is a state, not a rule the card already had. The two colours are pinned per path rather than
   taken from the markup's `stroke="var(--red)"`, which `--red` does not resolve to anything in this skin.

   THE RED IS THE BEACON, NOT SIGNAL RED (§08e2, 2026-11-06). Signal Red measures **2.79:1** on this
   card's own plate — under the 3:1 floor for a graphical element that carries meaning, which this line
   now does: red IS "not straight", green IS "straight". `--beacon` #F0455F, the red already in this
   token block for beacon rings and live indicators, measures **4.47:1** on the same plate (measured from
   the render, not carried over from the shield ring's plate, which is lighter and gives 3.52:1). The
   green is unchanged at #3FA46A, 5.26:1 on the same ground.

   THE SELECTORS ARE (0,4,1) AND COME LAST. `body` is load-bearing for the same reason it is on the tick
   above: §08b's `[stroke]` rules score (0,4,1) and a plain four-class selector scores (0,4,0) and loses.
   Measured after the change: `.fl-spiky` computes `rgb(240, 69, 95)`, `.fl-flat` `rgb(63, 164, 106)`.

   THE GREEN IS THE TICK'S GREEN. The palette owns no green (§20b), and `#3FA46A` is already in this file
   as the one literal Jason approved for the Security tick — reusing it beats inventing a second green.

   THE HANDOVER IS SEQUENTIAL, NOT A CROSSFADE. base-landing's `flSpiky` and `flFlat` both ramp across
   55–70 %, so at 62.5 % both paths sit at ~0.5 over the same y=8 line: two colours drawn at once, muddy
   where they overlap. Here the outgoing path finishes first and the incoming one starts after it
   (55–62 % out, 62–70 % in), so no frame paints both. The price is a dip at 62 % where neither is
   drawn. The ramps are LINEAR rather than the motif's `ease-in-out` for exactly that reason: an ease's flat
   tails spend most of each segment below 0.15 opacity, which measured **108 ms** of dip (60.2–63.8 %).
   Linear measures **60 ms** (61–63 % below 0.15 in either path) — ~4 frames at 60 Hz, with no frame
   carrying both colours. A blended double line is the worse artefact, so the dip is the one that is bought.

   The keyframes are new names (`flWiggle` / `flStraighten`) on purpose: redefining `flSpiky`/`flFlat` in
   this sheet would retime the one other `.flatline` in the build, the pricing eyebrow, which this round
   leaves alone. */
body .explore-grid .sec-card .flatline .fl-spiky {
  stroke: var(--beacon);                    /* #F0455F — the wobbling state */
  animation: flWiggle 3s linear infinite;
}
body .explore-grid .sec-card .flatline .fl-flat {
  stroke: #3FA46A;                          /* the Security tick's green — the flattened state */
  animation: flStraighten 3s linear infinite;
}

@keyframes flWiggle {
  0%, 55%   { opacity: 1; }
  62%, 100% { opacity: 0; }
}
@keyframes flStraighten {
  0%, 62%   { opacity: 0; }
  70%, 100% { opacity: 1; }
}

/* Reduced motion: the resolved end state, held. Before this round `reduce` froze the loop at 0 %, i.e. it
   parked the card on the WIGGLE, and the flat path stayed hidden — the opposite of the state the motif
   resolves to. Nothing loops here; the line is simply straight, and green. */
@media (prefers-reduced-motion: reduce) {
  body .explore-grid .sec-card .flatline .fl-spiky { animation: none !important; opacity: 0 !important; }
  body .explore-grid .sec-card .flatline .fl-flat { animation: none !important; opacity: 1 !important; }
}
