/* ============================================================================
   Unified Signal — homepage design system ("Switchboard")
   Scope: the homepage only. No other page loads this file.
   Contrast: every text pair below is >= 4.5:1; graphic accents >= 3:1.
   ========================================================================= */

/* ---------- 1. Fonts (self-hosted, latin subset) ---------- */
@font-face {
  font-family: 'Archivo';
  src: url('fonts/archivo-latin-var.woff2') format('woff2-variations');
  font-weight: 400 700;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'IBM Plex Mono';
  src: url('fonts/plexmono-latin-400.woff2') format('woff2');
  font-weight: 400;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'IBM Plex Mono';
  src: url('fonts/plexmono-latin-500.woff2') format('woff2');
  font-weight: 500;
  font-style: normal;
  font-display: swap;
}

/* ---------- 2. Design tokens ---------- */
:root {
  /* Brand — violet sampled from the deck and the live site footer (#3b065e) */
  --u-violet-900: #250340;
  --u-violet-800: #3b065e;
  --u-violet-700: #4c1e6e;
  --u-violet-600: #5f2f85;
  --u-violet-line: #8b61ac;  /* 3.21:1 on violet-800, 3.78:1 on violet-900 — WCAG 1.4.11 */

  /* Brand — amber sampled from the logotype (#FAAF5D) */
  --u-amber: #faaf5d;          /* on violet: 8.27:1 */
  --u-amber-solid: #e8892a;    /* fill on paper; carries --u-ink at 7.03:1 */
  --u-amber-ink: #a24e00;      /* amber-toned text on paper: 5.47:1 */

  /* Paper + ink */
  --u-paper: #fbf8f5;
  --u-paper-2: #f2ece6;
  --u-paper-3: #e6ddd4;
  --u-ink: #1a1024;            /* on paper: 17.36:1 */
  --u-ink-2: #5a4c68;          /* on paper:  7.44:1 */
  --u-ink-line: #d9cec4;

  /* On-violet text */
  --u-on-violet: #ffffff;      /* 15.29:1 */
  --u-on-violet-2: #c9bbd6;    /*  8.42:1 */

  /* Diagram data colors — meaning, never decoration */
  --u-flow-in: #5fc4f0;        /* money arriving  */
  --u-flow-out: #b49cff;       /* money leaving   */
  --u-flow-in-ink: #0b5c80;    /* same meaning, on paper */
  --u-flow-out-ink: #4b2fa8;

  --u-focus: #ffd08a;

  /* Type */
  --u-sans: 'Archivo', 'Segoe UI', system-ui, -apple-system, 'Helvetica Neue', Arial, sans-serif;
  --u-mono: 'IBM Plex Mono', ui-monospace, 'SFMono-Regular', 'Cascadia Mono', Menlo, Consolas, monospace;
  --u-fs-display: clamp(2.35rem, 1.9rem + 2.2vw, 3.25rem);
  --u-fs-h2: clamp(1.8rem, 1.35rem + 2vw, 2.9rem);
  --u-fs-h3: clamp(1.12rem, 1.06rem + .3vw, 1.35rem);
  --u-fs-lead: clamp(1.06rem, 1rem + .5vw, 1.35rem);
  --u-fs-body: clamp(1rem, .98rem + .12vw, 1.0625rem);
  --u-fs-small: .875rem;
  --u-fs-label: .75rem;

  /* Space */
  --u-s1: .25rem;  --u-s2: .5rem;   --u-s3: .75rem;  --u-s4: 1rem;
  --u-s5: 1.5rem;  --u-s6: 2rem;    --u-s7: 3rem;    --u-s8: 4rem;
  --u-s9: 6rem;    --u-s10: 8rem;
  --u-gutter: clamp(1.25rem, 4vw, 3rem);
  --u-measure: 68ch;
  --u-wrap: 1360px;
  --u-section-y: clamp(4rem, 8vw, 7.5rem);

  /* Radii, elevation, layers */
  --u-r1: 3px; --u-r2: 8px; --u-r3: 16px; --u-r4: 26px; --u-rp: 999px;
  --u-shadow-1: 0 1px 2px rgba(26, 16, 36, .06), 0 4px 12px rgba(26, 16, 36, .05);
  --u-shadow-2: 0 2px 6px rgba(26, 16, 36, .07), 0 18px 40px rgba(26, 16, 36, .09);
  --u-z-header: 100; --u-z-menu: 200; --u-z-skip: 300;

  /* Motion */
  --u-dur-1: 150ms; --u-dur-2: 320ms; --u-dur-3: 640ms;
  --u-ease: cubic-bezier(.2, .7, .3, 1);
}

/* ---------- 3. Reset + base ---------- */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }
body {
  margin: 0;
  background: var(--u-paper);
  color: var(--u-ink);
  font-family: var(--u-sans);
  font-size: var(--u-fs-body);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}
img, svg, video { display: block; max-width: 100%; }
img { height: auto; }
h1, h2, h3, h4 { margin: 0; line-height: 1.1; font-weight: 700; letter-spacing: -.02em; text-wrap: balance; }
p { margin: 0; text-wrap: pretty; }
ul, ol { margin: 0; padding: 0; list-style: none; }
a { color: inherit; }
button { font: inherit; color: inherit; }
:target { scroll-margin-top: 6rem; }

:focus-visible {
  outline: 3px solid var(--u-focus);
  outline-offset: 3px;
  border-radius: var(--u-r1);
}
.u-skip {
  position: absolute; left: var(--u-s4); top: -100%;
  z-index: var(--u-z-skip);
  padding: var(--u-s3) var(--u-s5);
  background: var(--u-amber); color: var(--u-violet-900);
  font-weight: 600; border-radius: var(--u-r2); text-decoration: none;
}
.u-skip:focus { top: var(--u-s4); }
.u-sr {
  position: absolute !important; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip-path: inset(50%); white-space: nowrap; border: 0;
}

/* ---------- 4. Layout primitives ---------- */
.u-wrap { width: 100%; max-width: var(--u-wrap); margin-inline: auto; padding-inline: var(--u-gutter); }
.u-section { padding-block: var(--u-section-y); position: relative; }
.u-section--paper { background: var(--u-paper); }
.u-section--paper2 { background: var(--u-paper-2); }
.u-section--violet { background: var(--u-violet-800); color: var(--u-on-violet); }
.u-section--violet-deep { background: var(--u-violet-900); color: var(--u-on-violet); }
.u-section--violet p, .u-section--violet-deep p { color: var(--u-on-violet-2); }

/* Section heading block ------------------------------------------------- */
.u-head { max-width: 62ch; margin-bottom: var(--u-s7); }
.u-eyebrow {
  display: flex; align-items: center; gap: var(--u-s3);
  font-family: var(--u-mono); font-size: var(--u-fs-label); font-weight: 500;
  letter-spacing: .14em; text-transform: uppercase;
  color: var(--u-amber-ink); margin-bottom: var(--u-s4);
}
.u-section--violet .u-eyebrow, .u-section--violet-deep .u-eyebrow { color: var(--u-amber); }
.u-eyebrow::before {
  content: ''; width: 1.75rem; height: 2px; flex: none;
  background: currentColor;
}
.u-eyebrow--center { justify-content: center; }
.u-h2 { font-size: var(--u-fs-h2); }
.u-lead { font-size: var(--u-fs-lead); color: var(--u-ink-2); margin-top: var(--u-s4); line-height: 1.5; }
.u-section--violet .u-lead, .u-section--violet-deep .u-lead { color: var(--u-on-violet-2); }
/* A short standfirst between the heading and the lead. One section carries one:
   #whitelabel, whose heading makes a claim and whose lead immediately qualifies
   it, so a reader scanning at speed needs the claim's scope before the
   qualification arrives. Darker and heavier than the lead, because it is closer
   to the heading in the reading order than it is to the body. */
.u-head__sub {
  margin-top: var(--u-s3); max-width: 46ch;
  font-size: var(--u-fs-lead); font-weight: 500; line-height: 1.45;
  color: var(--u-ink);
}
/* Past ~1000px a single 62ch column leaves a long empty gutter beside every
   heading. Setting the lead alongside the heading reads as one masthead, keeps
   both at a comfortable measure, and returns that vertical space to the
   figures below, which are what the section is actually about. */
@media (min-width: 1000px) {
  .u-section:not(.u-final) .u-head {
    max-width: none;
    display: grid;
    grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr);
    column-gap: var(--u-s8);
    align-items: start;
  }
  .u-section:not(.u-final) .u-head .u-eyebrow { grid-column: 1 / -1; }
  /* Placed explicitly rather than left to auto-placement. A third child in this
     grid would otherwise land in column two on the heading's own row, ahead of
     the lead it is meant to introduce; pinning the heading and the standfirst to
     column one and the lead to row two of column two keeps the reading order the
     same as it is below this breakpoint. Sections with no standfirst place
     exactly as they did before. */
  .u-section:not(.u-final) .u-head .u-h2 { grid-column: 1; }
  .u-section:not(.u-final) .u-head .u-head__sub { grid-column: 1; }
  /* Spanning two rows rather than sitting in one: pinned to row two alone, the
     lead sizes that row to its own six lines and the standfirst underneath the
     heading is pushed to the bottom of them. Spanning lets the rows size to the
     heading and the standfirst, and the lead's extra height falls where there is
     nothing to displace. Sections with no standfirst span into an empty implicit
     row, which changes nothing. */
  .u-section:not(.u-final) .u-head .u-lead { grid-column: 2; grid-row: 2 / span 2; margin-top: 0; padding-top: .45rem; }
}
.u-figcap {
  margin-top: var(--u-s5); font-size: var(--u-fs-small);
  color: var(--u-ink-2); max-width: var(--u-measure);
}
.u-section--violet .u-figcap,
.u-section--violet-deep .u-figcap { color: var(--u-on-violet-2); }
.u-figcap b { font-family: var(--u-mono); font-weight: 500; font-size: .8125rem;
  letter-spacing: .06em; text-transform: uppercase; }

/* ---------- 5. Buttons ---------- */
.u-btn {
  display: inline-flex; align-items: center; justify-content: center; gap: var(--u-s3);
  min-height: 48px; padding: var(--u-s3) var(--u-s6);
  border: 2px solid transparent; border-radius: var(--u-rp);
  font-weight: 600; font-size: 1rem; text-decoration: none; cursor: pointer;
  transition: background-color var(--u-dur-1) var(--u-ease),
              border-color var(--u-dur-1) var(--u-ease),
              color var(--u-dur-1) var(--u-ease),
              transform var(--u-dur-1) var(--u-ease);
}
.u-btn:hover { transform: translateY(-1px); }
.u-btn:active { transform: translateY(0); }
.u-btn--primary { background: var(--u-amber); color: var(--u-violet-900); border-color: var(--u-amber); }
.u-btn--primary:hover { background: #ffc37e; border-color: #ffc37e; }
.u-btn--ghost { background: transparent; color: var(--u-on-violet); border-color: var(--u-violet-line); }
.u-btn--ghost:hover { border-color: var(--u-amber); color: var(--u-amber); }
.u-btn__arrow { width: 1em; height: 1em; flex: none; transition: transform var(--u-dur-1) var(--u-ease); }
.u-btn:hover .u-btn__arrow { transform: translateX(3px); }
.u-cta-row { display: flex; flex-wrap: wrap; gap: var(--u-s4); align-items: center; }

/* Inline text link with animated rule */
.u-link {
  display: inline-flex; align-items: center; gap: .4em;
  font-weight: 600; text-decoration: none;
  color: var(--u-amber-ink);
  border-bottom: 2px solid currentColor; padding-block: 2px;
}
.u-link:hover { color: var(--u-ink); }

/* --u-amber-ink is tuned for the paper ground. On a violet ground the same value
   measures 3.11:1, which is a fail — and it was already a fail for the caption
   link under each film, where axe reported it only as "incomplete" and so no
   gate caught it. The lighter amber is the violet-ground pair, at 8.9:1. */
.u-section--violet .u-link,
.u-section--violet-deep .u-link { color: var(--u-amber); }
.u-section--violet .u-link:hover,
.u-section--violet-deep .u-link:hover { color: var(--u-on-violet); }

/* ---------- 6. Header ---------- */
.u-header {
  position: sticky; top: 0; z-index: var(--u-z-header);
  background: var(--u-violet-900);
  border-bottom: 1px solid rgba(255, 255, 255, .1);
}
.u-header__bar {
  display: flex; align-items: center; gap: var(--u-s5);
  min-height: 68px; padding-block: var(--u-s3);
}
.u-header__brand { flex: none; display: inline-flex; align-items: center; text-decoration: none; }
.u-header__brand img { width: 189px; height: 52px; object-fit: contain; }
.u-nav { display: none; margin-left: auto; }
.u-nav__list { display: flex; align-items: center; gap: var(--u-s2); }
.u-nav__link {
  display: inline-flex; align-items: center; gap: .35em;
  padding: var(--u-s2) var(--u-s3); border-radius: var(--u-r2);
  color: var(--u-on-violet); text-decoration: none; font-size: .9375rem; font-weight: 500;
  background: none; border: 0; cursor: pointer;
  transition: background-color var(--u-dur-1) var(--u-ease), color var(--u-dur-1) var(--u-ease);
}
.u-nav__link:hover { background: rgba(255, 255, 255, .1); color: var(--u-amber); }
.u-nav__caret { width: .7em; height: .7em; transition: transform var(--u-dur-1) var(--u-ease); }
.u-nav__item { position: relative; }
.u-nav__item--open > .u-nav__link { background: rgba(255, 255, 255, .1); color: var(--u-amber); }
.u-nav__item--open .u-nav__caret { transform: rotate(180deg); }
.u-nav__panel {
  position: absolute; top: calc(100% + 10px); left: 0; z-index: var(--u-z-menu);
  min-width: 264px; padding: var(--u-s3);
  background: var(--u-violet-700); border: 1px solid var(--u-violet-line);
  border-radius: var(--u-r3); box-shadow: 0 18px 46px rgba(0, 0, 0, .38);
  display: none;
}
.u-nav__item--open .u-nav__panel { display: block; }
.u-nav__panel--2col { min-width: 420px; display: none; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: var(--u-s2); }
.u-nav__item--open .u-nav__panel--2col { display: grid; }
html:not(.u-js) .u-nav__item:hover > .u-nav__panel,
html:not(.u-js) .u-nav__item:focus-within > .u-nav__panel { display: block; }
html:not(.u-js) .u-nav__item:hover > .u-nav__panel--2col,
html:not(.u-js) .u-nav__item:focus-within > .u-nav__panel--2col { display: grid; }
.u-nav__panel a {
  display: block; padding: var(--u-s3); border-radius: var(--u-r2);
  color: var(--u-on-violet); text-decoration: none; font-size: .9375rem;
}
.u-nav__panel a:hover { background: rgba(255, 255, 255, .12); color: var(--u-amber); }
.u-header__cta { display: none; flex: none; }
.u-header__cta .u-btn { min-height: 42px; padding-inline: var(--u-s5); font-size: .9375rem; }
.u-burger {
  margin-left: auto; align-items: center; gap: var(--u-s2);
  min-height: 44px; padding: var(--u-s2) var(--u-s4);
  background: none; border: 1px solid var(--u-violet-line); border-radius: var(--u-rp);
  color: var(--u-on-violet); font-size: .875rem; font-weight: 600; cursor: pointer;
}
.u-burger svg { width: 18px; height: 18px; }
.u-burger__close { display: none; }
.u-burger[aria-expanded='true'] .u-burger__open { display: none; }
.u-burger[aria-expanded='true'] .u-burger__close { display: block; }

/* Progressive enhancement: with JS off the whole menu is simply open and
   usable, and the toggle button is not shown. `u-js` is set by a one-line
   inline script in <head>, so there is no flash and no layout shift. */
.u-mobilenav {
  display: block;
  border-top: 1px solid rgba(255, 255, 255, .1);
  background: var(--u-violet-900);
  max-height: calc(100dvh - 68px); overflow-y: auto;
  padding-block: var(--u-s5) var(--u-s7);
}
.u-js .u-mobilenav[hidden] { display: none; }
.u-burger { display: none; }
.u-js .u-burger { display: inline-flex; }
.u-mobilenav__h {
  font-family: var(--u-mono); font-size: var(--u-fs-label); font-weight: 500;
  letter-spacing: .14em; text-transform: uppercase; color: var(--u-amber);
  margin: var(--u-s5) 0 var(--u-s3);
}
.u-mobilenav > .u-wrap > nav:first-of-type > .u-mobilenav__h { margin-top: 0; }
.u-mobilenav a {
  display: block; padding: var(--u-s3) 0; color: var(--u-on-violet);
  text-decoration: none; border-bottom: 1px solid rgba(255, 255, 255, .09);
  min-height: 44px;
}
.u-mobilenav .u-btn { width: 100%; margin-top: var(--u-s5); }

@media (min-width: 1040px) {
  .u-nav, .u-header__cta { display: block; }
  .u-burger, .u-js .u-burger { display: none; }
  .u-mobilenav { display: none; }
}

/* ---------- 7. Hero ---------- */
.u-hero {
  position: relative; overflow: hidden;
  background: var(--u-violet-900);
  color: var(--u-on-violet);
  padding-block: clamp(3rem, 6vw, 5.5rem) clamp(3rem, 6vw, 5rem);
}
/* Faint schematic grid — the "switchboard" ground. Pure CSS, no image request. */
.u-hero::before {
  content: ''; position: absolute; inset: 0; pointer-events: none;
  background-image:
    linear-gradient(rgba(255, 255, 255, .045) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255, 255, 255, .045) 1px, transparent 1px);
  background-size: 64px 64px;
  mask-image: radial-gradient(115% 85% at 78% 30%, #000 0%, transparent 72%);
}
.u-hero__grid {
  position: relative;
  display: grid; gap: clamp(2.5rem, 5vw, 4rem);
  grid-template-columns: 1fr;
  align-items: center;
}
@media (min-width: 1280px) {
  .u-hero__grid { grid-template-columns: minmax(0, 1.02fr) minmax(0, 1fr); }
}
.u-hero h1 { font-size: var(--u-fs-display); letter-spacing: -.035em; }
.u-hero h1 em { font-style: normal; color: var(--u-amber); }
.u-hero__lead {
  margin-top: var(--u-s5); font-size: var(--u-fs-lead);
  color: var(--u-on-violet-2); max-width: 54ch; line-height: 1.55;
}
.u-hero .u-cta-row { margin-top: var(--u-s7); }

/* Hero diagram — six named services on the logotype's signal arcs -------- */
/* viewBox is 760x545 (was 600x520): six radial labels need the extra width.
   Label sizes below are the old values x 760/600 so the rendered pixel size
   is unchanged at every breakpoint — the SVG scales, the text must follow.

   The diagram is lit from the core outward. Every coordinate is the one that
   shipped before; what is new is light — a ground that falls away, a rim on
   every solid, and one pulse that keeps running the orbit after the entry
   animation ends. The eye is given an order to read in: core, then orbit,
   then services. */
.u-orbit { position: relative; width: 100%; }
.u-orbit__svg { width: 100%; max-width: 620px; height: auto; overflow: visible;
  display: block; margin-inline: auto; }
/* The ground is a 600-unit circle, but the gradient's last stop is transparent
   at 53% — so it paints nothing past r=159 and never reaches the ring at
   r=165. That boundary is load-bearing: an earlier, wider pool lightened the
   backdrop under the nodes and cost the disc stroke 2.25:1 → 2.12:1. */
.u-orbit__ground { fill: url(#u-orbit-ground); }
/* The track is the groove the orbit sits in: a wide, almost-invisible band
   under the hairline. It gives the ring a width without adding a second
   visible line. */
.u-orbit__track { fill: none; stroke: var(--u-on-violet); stroke-opacity: .045; stroke-width: 20; }
.u-orbit__arc { fill: none; stroke: var(--u-violet-line); stroke-width: 1.25; opacity: .9; }
.u-orbit__core-ring { fill: none; stroke: var(--u-amber); stroke-width: 1.5; opacity: .6; }
.u-orbit__spoke { stroke: var(--u-violet-line); stroke-width: 1; opacity: .9; }
.u-orbit__pulse { stroke: var(--u-amber); stroke-width: 3; stroke-linecap: round; opacity: .7; }
.u-orbit__pulse-head { fill: var(--u-amber); }
.u-orbit__node-bg {
  fill: url(#u-orbit-disc); stroke: var(--u-violet-line); stroke-width: 1.25;
  transition: stroke var(--u-dur-1) var(--u-ease);
}
/* The rim light is the entire edge treatment. A drop shadow was built and
   measured out: the ground under the nodes is already --u-violet-900, the
   darkest token there is, so a shadow moved the painted pixel by one part in
   255. Six circles for nothing. */
.u-orbit__node-rim { fill: none; stroke: url(#u-orbit-rim); stroke-width: 1.6; pointer-events: none; }
.u-orbit__node-icon { fill: none; stroke: var(--u-on-violet); stroke-width: 1.35;
  stroke-linecap: round; stroke-linejoin: round; transition: stroke var(--u-dur-1) var(--u-ease); }
.u-orbit__node-label {
  fill: var(--u-on-violet-2); font-family: var(--u-mono); font-size: 13.3px;
  letter-spacing: .08em; text-transform: uppercase;
  transition: fill var(--u-dur-1) var(--u-ease);
}
/* us26.js sets data-active on mouseenter; :hover keeps the highlight working
   with JS off. The disc no longer swaps fill on hover — the gradient's light
   end is already --u-violet-600, the color the flat disc used to change to. */
.u-orbit__node:hover .u-orbit__node-bg,
.u-orbit__node[data-active='true'] .u-orbit__node-bg { stroke: var(--u-amber); }
.u-orbit__node:hover .u-orbit__node-icon,
.u-orbit__node[data-active='true'] .u-orbit__node-icon { stroke: var(--u-amber); }
.u-orbit__node:hover .u-orbit__node-label,
.u-orbit__node[data-active='true'] .u-orbit__node-label { fill: var(--u-on-violet); }
/* The halo breathes over a bloom that does not, so the core never dims below
   its floor. */
.u-orbit__halo { fill: url(#u-orbit-bloom); pointer-events: none; }
.u-orbit__bloom { fill: url(#u-orbit-bloom); pointer-events: none; }
.u-orbit__core { fill: url(#u-orbit-core); }
.u-orbit__core-rim { fill: none; stroke: url(#u-orbit-rim); stroke-width: 2.2; }
.u-orbit__core-icon { fill: none; stroke: var(--u-violet-900); stroke-width: 1.7; }
.u-orbit__core-label {
  fill: var(--u-violet-900); font-family: var(--u-mono); font-size: 11.4px;
  font-weight: 500; letter-spacing: .08em; text-transform: uppercase;
}
/* As the SVG shrinks, the linework has to grow in user units to survive being
   scaled down — otherwise the hairline and the pulse thin out to nothing on a
   phone while the labels stay legible. */
@media (max-width: 700px) {
  .u-orbit__node-label { font-size: 14.6px; }
  .u-orbit__core-label { font-size: 12px; }
  .u-orbit__spoke { stroke-width: 1.4; }
  .u-orbit__arc { stroke-width: 1.6; }
  .u-orbit__pulse { stroke-width: 3.6; }
}
@media (max-width: 560px) {
  .u-orbit__node-label { font-size: 17.7px; }
  .u-orbit__core-label { font-size: 14.6px; }
  .u-orbit__spoke { stroke-width: 1.8; }
  .u-orbit__arc { stroke-width: 2; }
  .u-orbit__pulse { stroke-width: 4.4; }
}
@media (max-width: 430px) {
  .u-orbit__node-label { font-size: 22.8px; }
  .u-orbit__core-label { font-size: 19px; }
  /* The core label grows 67% here while the core disc does not, and two lines at
     19px reach the bottom rim: measured, the second line's box ends 0.3 units
     inside a 116-unit disc. The icon and the label move up together by 6 so the
     spacing between them is the one that was designed, taken out of the 22 units
     of unused disc above the icon. */
  .u-orbit__core-icon, .u-orbit__core-label { transform: translateY(-6px); }
  .u-orbit__spoke { stroke-width: 2.2; }
  .u-orbit__arc { stroke-width: 2.4; }
  .u-orbit__pulse { stroke-width: 5.2; }
}
/* `margin-inline: 0` is load-bearing, not tidying. This is a <figure>, and the
   UA sheet gives <figure> `margin: 1em 40px`. Setting only margin-top left the
   40px side margins standing, so the caption rendered 80px narrower than its
   own column at every width -- 200px inside a 280px column at 320, i.e. 29% of
   the viewport thrown away, which is most of why the kicker below wrapped
   mid-phrase (docs/round-8 E-807). .u-colfig__grid resets the same default one
   rule-block away; this figure was the one that missed it. */
.u-orbit__caption {
  margin: var(--u-s5) 0 0; min-height: 4.5rem;
  padding: var(--u-s4) var(--u-s5);
  border: 1px solid var(--u-violet-line); border-radius: var(--u-r3);
  background: rgba(255, 255, 255, .04);
}
.u-orbit__caption h2 {
  font-family: var(--u-mono); font-size: var(--u-fs-label); font-weight: 500;
  letter-spacing: .12em; text-transform: uppercase; color: var(--u-amber);
  margin-bottom: var(--u-s2);
}
.u-orbit__caption p { font-size: var(--u-fs-small); color: var(--u-on-violet-2); }

/* Orbit motion — the diagram assembles, settles, then comes alive ---------
   The whole sequence, and nothing in it overlaps:

     0.00s  the arc and the core ring draw themselves            (1400ms)
     0.34s  the six services pop in, clockwise from 12           (520ms each,
            80ms apart, so the last settles at 1.26s)
     1.40s  the ring closes — the drawing is now complete
     1.50s  the core takes its first breath
     1.60s  the pulse fades in at 12 o'clock and starts running

   The two loops are held until the ring exists on purpose. Started at 0 they
   run underneath the entry — two unrelated motions competing during the only
   1.4s that has to read clearly — and the pulse spends its first 200ms riding
   a hairline that has not been drawn yet. */
.u-orbit__arc, .u-orbit__core-ring {
  stroke-dasharray: var(--len, 1200); stroke-dashoffset: var(--len, 1200);
  animation: u-draw 1400ms var(--u-ease) forwards;
}
/* The stagger runs clockwise from 12 o'clock, matching the reading order. It
   is carried on --d in the markup rather than on six [data-orbit] rules here:
   this diagram has already shipped once with five of six delays dead because
   the keys were renamed on one side of that join and not the other. */
.u-orbit__node { opacity: 0; animation: u-pop 520ms var(--u-ease) forwards;
  animation-delay: calc(var(--d) * 80ms + .34s); }
/* The pulse rides the orbit inside a group that rotates — a transform, so it
   stays on the compositor, where animating stroke-dashoffset would repaint the
   whole 1037-unit path every frame. Rotation is delayed by the same 1.6s as
   the fade, so the pulse is revealed at 12 o'clock with its tail on the first
   service and runs clockwise from there — the same origin and direction as the
   node stagger, rather than arriving at whatever angle 1.6s of unseen rotation
   happened to leave it at. */
.u-orbit__sweep {
  transform-box: view-box; transform-origin: 380px 268px; opacity: 0;
  animation-name: u-orbit-sweep, u-orbit-in;
  animation-duration: 9s, 600ms;
  animation-timing-function: linear, var(--u-ease);
  animation-iteration-count: infinite, 1;
  animation-fill-mode: none, forwards;
  animation-delay: 1.6s, 1.6s;
}
/* 7s against the pulse's 9s: co-prime, so the two never settle into the shared
   beat 6 and 9 fall into every third second. ease-in-out, not --u-ease, because
   a decelerate curve on a symmetric loop makes the halo snap bright, hang, snap
   dim, hang. `backwards` is load-bearing — without it the halo sits at full
   opacity through the delay and drops to .35 the instant the loop starts. */
.u-orbit__halo {
  transform-box: view-box; transform-origin: 380px 268px;
  animation: u-orbit-breathe 7s ease-in-out 1.5s infinite backwards;
}
@keyframes u-draw { to { stroke-dashoffset: 0; } }
@keyframes u-pop { from { opacity: 0; transform: translateY(6px); } to { opacity: 1; transform: none; } }
@keyframes u-orbit-sweep { to { transform: rotate(360deg); } }
@keyframes u-orbit-in { to { opacity: 1; } }
@keyframes u-orbit-breathe {
  0%, 100% { transform: scale(.88); opacity: .35; }
  50% { transform: scale(1.05); opacity: .6; }
}

/* ---------- 8. Credibility strip ---------- */
.u-strip { background: var(--u-violet-800); border-block: 1px solid var(--u-violet-line); }
.u-strip__list {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: var(--u-s5) var(--u-s6); padding-block: var(--u-s6);
}
@media (min-width: 800px) { .u-strip__list { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
.u-strip__n {
  display: block; font-family: var(--u-mono); font-weight: 500;
  font-size: clamp(1.6rem, 1.2rem + 1.4vw, 2.25rem);
  color: var(--u-amber); letter-spacing: -.02em; line-height: 1.1;
}
.u-strip__t { display: block; margin-top: var(--u-s2); font-size: var(--u-fs-small); color: var(--u-on-violet-2); }

/* ---------- 9. Generic card grid ---------- */
.u-grid { display: grid; gap: var(--u-s5); grid-template-columns: 1fr; }
@media (min-width: 700px) { .u-grid--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 700px) { .u-grid--4 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 900px) { .u-grid--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (min-width: 1100px) { .u-grid--4 { grid-template-columns: repeat(4, minmax(0, 1fr)); } }

.u-card {
  position: relative; padding: var(--u-s6);
  background: #fff; border: 1px solid var(--u-ink-line); border-radius: var(--u-r3);
  box-shadow: var(--u-shadow-1);
}
.u-card h3 { font-size: var(--u-fs-h3); margin-bottom: var(--u-s3); }
.u-card p { color: var(--u-ink-2); font-size: var(--u-fs-small); }
.u-card__n {
  font-family: var(--u-mono); font-size: var(--u-fs-label); font-weight: 500;
  letter-spacing: .1em; color: var(--u-amber-ink); display: block; margin-bottom: var(--u-s4);
}

/* Four inputs converging on one platform. The bracket is a CSS rule rather
   than an image, so it cannot fall out of alignment with the cards; below the
   four-column step it is simply not drawn and the node stands alone. */
.u-converge { margin-top: var(--u-s6); display: grid; justify-items: center; }
.u-converge__rule { display: none; }
.u-converge__node {
  display: inline-grid; gap: 2px; justify-items: center; text-align: center;
  padding: var(--u-s4) var(--u-s6);
  background: #fff; border: 1px solid var(--u-amber-solid); border-radius: var(--u-r3);
  box-shadow: var(--u-shadow-1);
}
.u-converge__node b {
  font-family: var(--u-mono); font-weight: 500; font-size: .9375rem;
  letter-spacing: .08em; text-transform: uppercase; color: var(--u-amber-ink);
}
.u-converge__node span { font-size: var(--u-fs-small); color: var(--u-ink-2); }
@media (min-width: 1100px) {
  .u-converge { margin-top: 0; }
  .u-converge__rule {
    display: block; position: relative; width: 74%; height: 30px;
    border: 1px solid var(--u-ink-line); border-top: 0; border-radius: 0 0 16px 16px;
  }
  .u-converge__rule::after {
    content: ''; position: absolute; left: calc(50% - .5px); top: 100%;
    width: 1px; height: 20px; background: var(--u-ink-line);
  }
  .u-converge__node { margin-top: 20px; }
}

/* ---------- 10. Icon family ---------- */
/* One grid (24×24), one stroke weight, round caps — arcs, nodes and paths only. */
.u-ico { width: 1em; height: 1em; fill: none; stroke: currentColor;
  stroke-width: 1.6; stroke-linecap: round; stroke-linejoin: round; }

/* ---------- 11. Platform architecture ---------- */
.u-layers { display: grid; gap: var(--u-s5); }
@media (min-width: 1000px) { .u-layers { grid-template-columns: repeat(3, minmax(0, 1fr)); align-items: start; } }
.u-layer {
  background: #fff; border: 1px solid var(--u-ink-line); border-radius: var(--u-r3);
  overflow: hidden; box-shadow: var(--u-shadow-1);
}
.u-layer__head { padding: var(--u-s6) var(--u-s6) var(--u-s5); border-bottom: 1px solid var(--u-ink-line); }
.u-layer__badge {
  display: inline-flex; align-items: center; gap: var(--u-s2);
  font-family: var(--u-mono); font-size: var(--u-fs-label); font-weight: 500;
  letter-spacing: .1em; text-transform: uppercase; color: var(--u-amber-ink);
  margin-bottom: var(--u-s3);
}
.u-layer__head h3 { font-size: var(--u-fs-h3); }
.u-layer__head p { margin-top: var(--u-s3); color: var(--u-ink-2); font-size: var(--u-fs-small); }
.u-layer__body { padding: var(--u-s5) var(--u-s6) var(--u-s6); }

.u-caps { display: grid; gap: var(--u-s3); }
.u-cap { display: grid; grid-template-columns: 22px 1fr; gap: var(--u-s3); align-items: start; }
.u-cap svg { width: 22px; height: 22px; color: var(--u-amber-ink); margin-top: 2px; }
.u-cap b { display: block; font-weight: 600; font-size: .9375rem; }
.u-cap span { display: block; color: var(--u-ink-2); font-size: .84rem; line-height: 1.45; }
.u-layer__note {
  margin-top: var(--u-s5); padding-top: var(--u-s5); border-top: 1px solid var(--u-ink-line);
  font-size: .84rem; color: var(--u-ink-2); line-height: 1.55;
}

/* The shared core, stated once and given the weight it carries. Everything in
   the three groups below settles against this band. */
.u-core {
  padding: var(--u-s7) var(--u-s6); margin-bottom: var(--u-s6);
  background: var(--u-violet-900); border: 1px solid var(--u-violet-line);
  border-radius: var(--u-r4);
}
@media (min-width: 800px) { .u-core { padding: var(--u-s7) var(--u-s8); } }
.u-core__h {
  font-family: var(--u-mono); font-size: var(--u-fs-label); font-weight: 500;
  letter-spacing: .14em; text-transform: uppercase; color: var(--u-amber);
  margin-bottom: var(--u-s6);
}
.u-core__caps { display: grid; gap: var(--u-s5); grid-template-columns: 1fr; }
@media (min-width: 620px) { .u-core__caps { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1040px) { .u-core__caps { grid-template-columns: repeat(5, minmax(0, 1fr)); } }
.u-core__cap svg { width: 24px; height: 24px; color: var(--u-amber); }
.u-core__cap b { display: block; margin-top: var(--u-s3); font-weight: 600;
  font-size: .9375rem; color: var(--u-on-violet); }
.u-core__cap span { display: block; margin-top: var(--u-s2); font-size: .8125rem;
  line-height: 1.5; color: var(--u-on-violet-2); }

/* ---------- 11b. White label ---------- */
.u-wl { display: grid; gap: var(--u-s7); align-items: start; }
@media (min-width: 1000px) {
  .u-wl { grid-template-columns: minmax(0, 1fr) minmax(0, 1.02fr); gap: var(--u-s8); }
}
.u-wl__list { gap: var(--u-s5); }
.u-wl__list .u-cap { grid-template-columns: 26px 1fr; gap: var(--u-s4); }
.u-wl__list .u-cap svg { width: 26px; height: 26px; margin-top: 0; }
.u-wl__list .u-cap b { font-size: 1.0625rem; margin-bottom: var(--u-s1); }
.u-wl__list .u-cap span span { font-size: var(--u-fs-small); }

/* What the customer sees, and what runs underneath. Three stacked bands and a
   single connector, so ownership is the only thing the figure draws. Built
   from flow boxes rather than fixed coordinates: the labels keep their real
   size at every width instead of shrinking with a viewBox. */
.u-brandstack { margin: 0; display: grid; gap: var(--u-s4); }
.u-brandstack__band {
  position: relative; padding: var(--u-s5) var(--u-s6);
  border: 1px solid var(--u-ink-line); border-left-width: 4px;
  border-radius: var(--u-r3); background: #fff;
}
.u-brandstack__band + .u-brandstack__band::before {
  content: ''; position: absolute; left: 2rem; top: calc(var(--u-s4) * -1);
  width: 1px; height: var(--u-s4); background: var(--u-ink-line);
}
.u-brandstack__band--yours { border-left-color: var(--u-amber-solid); }
.u-brandstack__band--ours {
  background: var(--u-violet-900); border-color: var(--u-violet-line);
  border-left-color: var(--u-amber);
}
.u-brandstack__k {
  font-family: var(--u-mono); font-size: var(--u-fs-label); font-weight: 500;
  letter-spacing: .1em; text-transform: uppercase; color: var(--u-amber-ink);
}
.u-brandstack__t { margin-top: var(--u-s2); font-weight: 600; font-size: 1.0625rem; }
.u-brandstack__d { margin-top: var(--u-s2); font-size: var(--u-fs-small); color: var(--u-ink-2); }
.u-brandstack__band--ours .u-brandstack__k { color: var(--u-amber); }
.u-brandstack__band--ours .u-brandstack__t { color: var(--u-on-violet); }
.u-brandstack__band--ours .u-brandstack__d { color: var(--u-on-violet-2); }
.u-brandstack .u-figcap { margin-top: var(--u-s4); }

/* ---------- 11b. Showcase figures ---------- */
/* The three supplied product renders, whole, as members of the section's own
   grid. Round 6 put each on a full-bleed band outside .u-wrap, which left the
   artwork centred in the viewport while its caption sat at the reading column's
   edge -- 134px apart at 1280 (docs/round-7 E-702a). Here the artwork hangs off
   the same left edge as every heading and paragraph in its section; verify.mjs
   binds that edge at four viewports.

   Deliberately absent: border, border-radius, box-shadow, object-fit, and any
   fixed aspect-ratio. All three assets are alpha cut-outs carrying their own
   shadows, and every one of those properties fights that.

   Grounds were chosen by compositing each asset and looking at it. See
   docs/round-6/08-REVISION.md and docs/round-7 E-703, E-704. */
.u-colfig { margin-block: var(--u-s8); }
.u-colfig__grid { margin: 0; display: grid; gap: var(--u-s6); }
.u-colfig__art img { display: block; width: 100%; height: auto; }

/* Capped at each source's native width, so nothing is upscaled at 1x -- notably
   in the stacked layout below 1200, where the reading column is wider than two
   of the three sources. verify.mjs binds these numbers to the real files. */
.u-colfig--card .u-colfig__art img { max-width: 1240px; }      /* source 1640 */
.u-colfig--app .u-colfig__art img { max-width: 915px; }        /* source  915 */
.u-colfig--wireless .u-colfig__art img { max-width: 1064px; }  /* source 1064 */

/* The card art is 42.6% feathered alpha and dissolves into --u-violet-800 with
   no edge. Same device as .u-hero::before: the artwork sits in the page's own
   light. Inset 0 horizontally -- a negative inline inset overflows the wrap at
   390 and 768. */
.u-colfig--card .u-colfig__art { position: relative; }
.u-colfig--card .u-colfig__art::before {
  content: ''; position: absolute; inset: -9% 0; z-index: -1; pointer-events: none;
  background: radial-gradient(56% 60% at 50% 48%,
    rgba(250, 175, 93, .12) 0%, rgba(250, 175, 93, .045) 44%, transparent 72%);
}

.u-colfig__k {
  display: block; font-family: var(--u-mono); font-size: var(--u-fs-label);
  font-weight: 500; letter-spacing: .14em; text-transform: uppercase;
  color: var(--u-amber-ink); margin-bottom: var(--u-s3);
}
.u-colfig__note {
  font-size: var(--u-fs-small); color: var(--u-ink-2); max-width: var(--u-measure);
  border-top: 1px solid var(--u-ink-line); padding-top: var(--u-s4);
}
.u-section--violet .u-colfig__note { color: var(--u-on-violet-2); border-top-color: var(--u-violet-line); }
.u-section--violet .u-colfig__k { color: var(--u-amber); }

/* The wireless render carries mock dashboard figures baked into its pixels.
   Not Unified Signal service data, and the page says so. docs/round-6 D-612. */
.u-figcap__note { display: block; margin-top: var(--u-s2); opacity: .82; }

/* Pure #ffffff, and only here, at SECTION level. 86.8% of the wireless asset's
   silhouette-edge pixels are luminance > 235, median 255 -- it is a rectangular
   poster with a ragged white deckle edge, not a cut-out, so it halos on every
   other ground the page has (docs/round-7 E-703). Round 6 met the same
   constraint with a white band starting mid-section, at no heading and no
   section boundary; a section-level ground change is the page's own idiom. */
.u-section--white { background: #fff; }

/* Two columns only once there is room for both. The split began at 900, where
   the annotation took the artwork from 810px wide down to 460px -- smaller than
   it had been stacked (docs/round-7 D-710). The rule and the centring are
   load-bearing, not decoration: the note is three lines in a cell as tall as a
   700px image, and top-pinning it leaves 527-583px of unbounded hole (D-709). */
@media (min-width: 1200px) {
  .u-colfig__grid {
    grid-template-columns: minmax(0, 1fr) clamp(15rem, 22vw, 20rem);
    column-gap: var(--u-s7); align-items: stretch;
  }
  .u-colfig__note {
    align-self: stretch;
    display: flex; flex-direction: column; justify-content: center;
    font-size: var(--u-fs-body); line-height: 1.62;
    border-top: 0; padding-top: 0;
    border-left: 1px solid var(--u-ink-line); padding-left: var(--u-s6);
  }
  .u-colfig__note::before {
    content: ''; display: block; width: 1.75rem; height: 2px;
    background: var(--u-amber-solid); margin-bottom: var(--u-s4);
  }
  .u-section--violet .u-colfig__note { border-left-color: var(--u-violet-line); }
  .u-section--violet .u-colfig__note::before { background: var(--u-amber); }
}

@media (max-width: 700px) {
  .u-colfig { margin-block: var(--u-s7); }
}

/* ---------- 12. Money flow spine ---------- */
/* Five steps on one rule: vertical when the column is narrow, horizontal when
   there is room. The rule is drawn per step from the mark itself, so it stays
   in register at any content height or text size instead of relying on fixed
   coordinates the way an overlaid SVG would. */
.u-spine { position: relative; display: grid; gap: var(--u-s6); }
.u-spine__step {
  position: relative; display: grid;
  grid-template-columns: 48px minmax(0, 1fr); gap: var(--u-s5);
  align-items: start;
}
.u-spine__mark {
  position: relative; z-index: 1;
  display: grid; place-items: center; width: 48px; height: 48px; border-radius: 50%;
  background: var(--u-violet-900); border: 1.5px solid var(--u-amber); color: var(--u-amber);
}
.u-spine__mark svg { width: 22px; height: 22px; }
.u-spine__step:not(:last-child)::before {
  content: ''; position: absolute; left: 23.25px; top: 48px;
  bottom: calc(var(--u-s6) * -1); width: 1.5px;
  background: var(--u-violet-line);
}
.u-spine__h {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--u-s1) var(--u-s3);
  padding-top: .6rem;
  font-family: var(--u-mono); font-size: 1.0625rem; font-weight: 500;
  letter-spacing: .12em; text-transform: uppercase; color: var(--u-on-violet);
}
.u-spine__h span {
  font-family: var(--u-sans); font-size: .8125rem; font-weight: 400;
  letter-spacing: 0; text-transform: none; color: var(--u-amber);
}
/* One line naming what the stage is, between the step heading and its rails.
   White against the rails' muted violet, so the column reads heading -> claim ->
   evidence rather than as one undifferentiated list. */
.u-spine__sum {
  margin-top: var(--u-s3);
  font-size: .9375rem; line-height: 1.5; color: var(--u-on-violet);
}
.u-spine__rails { margin-top: var(--u-s4); display: grid; gap: var(--u-s3); }
.u-spine__rails li {
  position: relative; padding-left: var(--u-s5);
  font-size: .875rem; line-height: 1.5; color: var(--u-on-violet-2);
}
.u-spine__rails li::before {
  content: ''; position: absolute; left: 0; top: .62em;
  width: 9px; height: 1.5px; background: var(--u-flow-in);
}
@media (min-width: 1080px) {
  .u-spine { grid-template-columns: repeat(5, minmax(0, 1fr)); gap: var(--u-s5); }
  /* Laid out as a row, the five steps stretch to the tallest of them. Without
     this the three auto rows share that extra height out between themselves, so
     a step with fewer rails carries its heading down the column and the row of
     headings reads as a staircase. Pack the rows at the top instead. */
  .u-spine__step { grid-template-columns: minmax(0, 1fr); gap: var(--u-s4); align-content: start; }
  .u-spine__step:not(:last-child)::before {
    left: 48px; top: 23.25px; right: calc(var(--u-s5) * -1);
    bottom: auto; width: auto; height: 1.5px;
  }
  .u-spine__h { padding-top: 0; }
}

/* ---------- 13. Video ---------- */
/* preload="none": nothing is requested from the video ORIGIN until a visitor
   presses play. That is unchanged and still gated.
   What changed in round 9: the frame is no longer empty. It carries a `poster`
   -- the film's own frame 0, extracted from the file this player streams and
   served first-party, 39,394 B. So "zero media bytes" is no longer true of this
   section and is not claimed here; "zero bytes from the video origin" is, and
   that is the property the budget was ever really about. Ledger M5 reversed,
   round 9 D-902. */
.u-vids { display: grid; gap: var(--u-s7); }
.u-vid { margin: 0; }
/* The homepage carries one film since the V2 round. The old rule here was a
   two-column grid of figures, which with a single figure left half the row
   empty; letting that figure go full width instead puts a 16:9 frame 700px tall
   at the 1360px wrap and pushes its own caption off the screen. So above 1040px
   the film and its description sit side by side -- the frame stays a sane size,
   the caption keeps a short measure, and the pair reads as one object. Below
   that they stack, and so would a second film if one ever returned. */
@media (min-width: 1040px) {
  .u-vids { gap: var(--u-s8); }
  .u-vid {
    display: grid; grid-template-columns: minmax(0, 1.45fr) minmax(0, 1fr);
    gap: var(--u-s7); align-items: start;
  }
  .u-vid__cap { margin-top: 0; }
}
.u-vid__frame {
  position: relative; overflow: hidden;
  border: 1px solid var(--u-violet-line); border-radius: var(--u-r3);
  background: var(--u-violet-800);
}
.u-vid__el { display: block; width: 100%; height: auto; aspect-ratio: 16 / 9; background: #17032a; }
.u-vid__fallback { padding: var(--u-s6); font-size: var(--u-fs-small); color: var(--u-on-violet-2); }
/* JS enhancement only. Without it the native controls are the only affordance,
   and they already play the file; this adds a target big enough to hit and a
   label saying what is about to load. Removed the moment playback starts. */
.u-vid__play {
  position: absolute; inset: 0; width: 100%; border: 0; cursor: pointer;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: var(--u-s4); color: var(--u-on-violet);
  /* Two layers since round 9, and the first one is load-bearing rather than
     decorative. The linear scrim is round 5's and is unchanged: it grades the
     frame so the PLAY label reads and the caption below feels attached.
     The radial layer is new, and it exists because a two-colour control has a
     worst case it cannot design its way out of. The disc is amber and the ring
     is near-black, so a backdrop landing between them contrasts poorly with
     BOTH -- and the arithmetic puts that floor at 2.99:1, i.e. exactly on the
     3:1 line, no matter how the ring is tuned. The globe's lit rim is close to
     that mid-tone. Darkening locally pulls the backdrop away from the middle
     and toward the ring, which lifts the disc's own term. Measured on the
     shipped poster by the 8b gate in tools/verify.mjs, worst pixel of 720
     angles x 8 radii, at 390 / 1280:

       flat scrim, no ring   2.30:1 / 2.17:1   <- round 8's control, FAILS
       ring only             3.24:1 / 3.65:1
       pool only             4.80:1 / 4.82:1
       ring + pool           4.27:1 / 6.08:1   <- shipped

     Either remedy alone clears 3:1 on THIS frame; neither clears it by much,
     and the rows are not sampling identical pixels -- the annulus starts just
     outside the control's outer edge, so adding the ring moves it 5px further
     out into different picture. Both ship because the margin is what has to
     survive a frame nobody has seen yet. It is a 120px pool centred on the
     control, so it buys that margin without flattening the picture the way a
     heavier full-frame scrim would. Round 9 D-905; receipt R-913. */
  background:
    radial-gradient(circle at 50% 44%, rgba(37, 3, 64, .62) 0, rgba(37, 3, 64, .34) 74px, rgba(37, 3, 64, 0) 120px),
    linear-gradient(180deg, rgba(37, 3, 64, .3), rgba(37, 3, 64, .78));
  transition: background-color var(--u-dur-2) var(--u-ease);
}
/* The ring is round 9's, and it is a WCAG 1.4.11 fix rather than decoration.
   While this disc sat on a flat violet field, "is the control distinguishable
   from what is behind it" had an obvious answer. It now sits on a frame of the
   film, and measured the answer was NO: amber against the globe's lit rim came
   out 2.30:1 at 390 and 2.17:1 at 1280, both under the 3:1 a non-text control
   boundary needs. Nothing else caught it -- axe does not judge non-text
   contrast, and the label's own TEXT ratio stayed fine at 6.96:1 throughout,
   which is exactly why a text gate could not see this.

   Deepening the scrim would also have fixed it, and was rejected: it fixes this
   frame by hiding the picture the owner asked to show, and it would have to be
   re-tuned against every future frame. A boundary that belongs to the CONTROL
   holds whatever is behind it -- including a film the client replaces without
   telling anyone. Sized and coloured against the measurement, not by eye. */
.u-vid__glyph {
  display: grid; place-items: center; width: 68px; height: 68px; border-radius: 50%;
  background: var(--u-amber); color: var(--u-violet-900);
  box-shadow: 0 0 0 5px rgba(19, 2, 34, .88);
  transition: transform var(--u-dur-2) var(--u-ease);
}
.u-vid__glyph svg { width: 26px; height: 26px; margin-left: 3px; fill: currentColor; stroke: none; }
.u-vid__play:hover .u-vid__glyph,
.u-vid__play:focus-visible .u-vid__glyph { transform: scale(1.07); }
.u-vid__playlabel {
  font-family: var(--u-mono); font-size: var(--u-fs-label); font-weight: 500;
  letter-spacing: .12em; text-transform: uppercase;
}
.u-vid__cap { margin-top: var(--u-s5); }
.u-vid__kicker {
  font-family: var(--u-mono); font-size: var(--u-fs-label); font-weight: 500;
  letter-spacing: .1em; text-transform: uppercase; color: var(--u-amber);
}
.u-vid__cap h3 { font-size: var(--u-fs-h3); margin-top: var(--u-s2); }
.u-vid__meta { margin-top: var(--u-s2); }
.u-vid__dur {
  font-family: var(--u-mono); font-size: .8125rem; letter-spacing: .06em;
  color: var(--u-on-violet-2);
}
.u-vid__cap p { color: var(--u-on-violet-2); font-size: var(--u-fs-small); }
.u-vid__cap p + p { margin-top: var(--u-s3); }

/* The longer walkthrough, offered as a link rather than a second player. Sits on
   the violet ground beneath the film, in the same register as the film's own
   metadata: mono for the measured facts, so a reader reads them as specific. */
.u-vidmore {
  margin-top: var(--u-s5); padding-top: var(--u-s4);
  border-top: 1px solid var(--u-violet-line);
  max-width: var(--u-measure);
  font-size: var(--u-fs-small); color: var(--u-on-violet-2);
}
.u-vidmore__k {
  display: block; margin-bottom: var(--u-s2);
  font-family: var(--u-mono); font-size: .75rem; letter-spacing: .08em;
  text-transform: uppercase; color: var(--u-amber);
}
/* `.u-vid__cap p + p` is the more specific selector now that this block sits
   inside the figcaption, and it would collapse the gap above the rule to s3.
   Restate the intended separation rather than weaken the caption's own rhythm. */
.u-vid__cap p.u-vidmore { margin-top: var(--u-s5); max-width: none; }
/* The measure cap is for the old full-width placement. Inside the caption the
   column is already the measure, and capping again left this block's rule
   visibly shorter than the caption note's directly above it. */
.u-vidmore__meta {
  display: block; margin-top: var(--u-s2);
  font-family: var(--u-mono); font-size: .8125rem; letter-spacing: .06em;
  color: var(--u-on-violet-2);
}

/* ---------- 14. Wireless ---------- */
.u-feat { display: grid; gap: var(--u-s4) var(--u-s6); grid-template-columns: 1fr; }
@media (min-width: 640px) { .u-feat { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.u-feat li { display: grid; grid-template-columns: 20px 1fr; gap: var(--u-s3); align-items: start;
  padding-block: var(--u-s2); font-size: .9375rem; }
.u-feat svg { width: 20px; height: 20px; color: var(--u-amber-ink); margin-top: 3px; }

/* ---------- 15. Launch phases ---------- */
.u-steps { display: grid; gap: var(--u-s5); }
@media (min-width: 640px) { .u-steps { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1080px) { .u-steps { grid-template-columns: repeat(5, minmax(0, 1fr)); gap: var(--u-s4); } }
.u-steps__item {
  position: relative; padding: var(--u-s5);
  border: 1px solid var(--u-violet-line); border-radius: var(--u-r3);
  background: rgba(255, 255, 255, .05);
}
.u-steps__n {
  display: grid; place-items: center; width: 38px; height: 38px; border-radius: 50%;
  background: var(--u-amber); color: var(--u-violet-900);
  font-family: var(--u-mono); font-weight: 500; font-size: 1rem;
  margin-bottom: var(--u-s4);
}
.u-steps__item h3 { font-size: 1.0625rem; margin-bottom: var(--u-s3); color: var(--u-on-violet); }
.u-steps__item p { font-size: .8125rem; line-height: 1.55; color: var(--u-on-violet-2); }
/* The rule between phases spans the grid gap only, so it can never overrun a
   card or fall out of alignment when the copy reflows. It draws itself in when
   the section comes into view. */
@media (min-width: 1080px) {
  .u-steps__item:not(:last-child)::after {
    content: ''; position: absolute; left: 100%; top: calc(var(--u-s5) + 18.25px);
    width: var(--u-s4); height: 1.5px; background: var(--u-amber); opacity: .55;
    transform-origin: left center;
  }
  .u-steps.is-live .u-steps__item::after { animation: u-grow 520ms var(--u-ease) backwards; }
  .u-steps.is-live .u-steps__item:nth-child(2)::after { animation-delay: .1s; }
  .u-steps.is-live .u-steps__item:nth-child(3)::after { animation-delay: .2s; }
  .u-steps.is-live .u-steps__item:nth-child(4)::after { animation-delay: .3s; }
}
@keyframes u-grow { from { transform: scaleX(.02); opacity: 0; } to { transform: scaleX(1); opacity: .55; } }

/* ---------- 16. Engagement models ---------- */
.u-model { display: flex; flex-direction: column; height: 100%; }
.u-model__time {
  font-family: var(--u-mono); font-size: .8125rem; font-weight: 500;
  color: var(--u-amber-ink); letter-spacing: .06em; margin-bottom: var(--u-s3); display: block;
}
.u-model ul { margin-top: var(--u-s5); display: grid; gap: var(--u-s2); }
.u-model ul li { display: grid; grid-template-columns: 16px 1fr; gap: var(--u-s3);
  font-size: .875rem; color: var(--u-ink-2); align-items: start; }
.u-model ul svg { width: 16px; height: 16px; color: var(--u-amber-ink); margin-top: 4px; }

/* ---------- 17. Sectors ---------- */
.u-sectors { display: grid; gap: var(--u-s5); grid-template-columns: 1fr; }
/* Ten cards, each now carrying four capability lines. The four-column step moved
   down from 1200px to 1080px because the three-column band is the one that
   strands a card on its own row (3/3/3/1); at four columns ten lands 4/4/2 and
   the short last row reads as a row rather than an orphan. */
@media (min-width: 560px)  { .u-sectors { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 860px)  { .u-sectors { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (min-width: 1080px) { .u-sectors { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
.u-sector {
  padding: var(--u-s6) var(--u-s5);
  background: #fff; border: 1px solid var(--u-ink-line); border-radius: var(--u-r3);
  box-shadow: var(--u-shadow-1);
  transition: border-color var(--u-dur-1) var(--u-ease), transform var(--u-dur-1) var(--u-ease);
}
.u-sector:hover { border-color: var(--u-amber-solid); transform: translateY(-2px); }
.u-sector__ico { width: 26px; height: 26px; color: var(--u-amber-ink); }
.u-sector h3 { font-size: 1rem; margin: var(--u-s4) 0 var(--u-s2); }
.u-sector p { font-size: .84rem; line-height: 1.5; color: var(--u-ink-2); }
/* What the industry actually launches, under the sentence saying why. The rule
   markers use --u-amber-ink rather than --u-amber-solid: the same amber the card
   icon already uses, and the only one of the two that clears 3:1 against white. */
.u-sector__caps { margin-top: var(--u-s4); display: grid; gap: var(--u-s2); }
.u-sector__caps li {
  position: relative; padding-left: var(--u-s4);
  font-size: .8125rem; line-height: 1.45; color: var(--u-ink-2);
}
.u-sector__caps li::before {
  content: ''; position: absolute; left: 0; top: .62em;
  width: 7px; height: 1.5px; background: var(--u-amber-ink);
}

/* ---------- 17b. Insights ---------- */
.u-ins { display: grid; gap: var(--u-s5); }
@media (min-width: 900px) { .u-ins { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
.u-ins__item {
  position: relative; display: flex; flex-direction: column;
  padding: var(--u-s6); background: #fff;
  border: 1px solid var(--u-ink-line); border-radius: var(--u-r3);
  box-shadow: var(--u-shadow-1);
  transition: border-color var(--u-dur-1) var(--u-ease), box-shadow var(--u-dur-1) var(--u-ease);
}
.u-ins__item:hover { border-color: var(--u-amber-solid); box-shadow: var(--u-shadow-2); }
.u-ins__meta {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--u-s2) var(--u-s4);
  font-family: var(--u-mono); font-size: var(--u-fs-label); font-weight: 500;
  letter-spacing: .08em; text-transform: uppercase; color: var(--u-ink-2);
}
.u-ins__kind { color: var(--u-amber-ink); }
.u-ins__title { font-size: 1.0625rem; line-height: 1.45; margin-top: var(--u-s4); }
/* One tab stop per card: the link covers the card for the pointer, and keeps
   its own focus ring on the title where a keyboard user is reading. */
.u-ins__link { display: block; color: inherit; text-decoration: none; }
.u-ins__link::after { content: ''; position: absolute; inset: 0; border-radius: var(--u-r3); }
.u-ins__link:hover { color: var(--u-amber-ink); }
.u-ins__sum {
  margin-top: var(--u-s3); flex: 1 1 auto;
  font-size: var(--u-fs-small); color: var(--u-ink-2);
}
.u-ins__more {
  display: inline-flex; align-items: center; gap: var(--u-s2); margin-top: var(--u-s5);
  font-family: var(--u-mono); font-size: var(--u-fs-label); font-weight: 500;
  letter-spacing: .1em; text-transform: uppercase; color: var(--u-amber-ink);
}
.u-ins__more svg { width: 15px; height: 15px; transition: transform var(--u-dur-1) var(--u-ease); }
.u-ins__item:hover .u-ins__more svg { transform: translateX(3px); }
.u-ins__foot { margin-top: var(--u-s6); display: flex; flex-wrap: wrap; gap: var(--u-s4) var(--u-s7); }

/* ---------- 18. Build / stitch / buy ---------- */
.u-paths { display: grid; gap: var(--u-s5); }
@media (min-width: 900px) { .u-paths { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
.u-path { display: flex; flex-direction: column; height: 100%; }
/* This column is the recommendation, so it is the one that looks like it. */
.u-path--ours {
  background: var(--u-violet-900); border-color: var(--u-amber);
  color: var(--u-on-violet); box-shadow: var(--u-shadow-2);
}
.u-path--ours h3 { color: var(--u-on-violet); }
.u-path--ours .u-path__what { color: var(--u-on-violet-2); }
.u-path--ours dd { color: var(--u-on-violet-2); }
.u-path h3 { font-size: var(--u-fs-h3); }
.u-path__what { margin-top: var(--u-s4); font-size: var(--u-fs-small); color: var(--u-ink-2); }
.u-path dl { margin: var(--u-s5) 0 0; display: grid; gap: var(--u-s4); }
.u-path dt {
  font-family: var(--u-mono); font-size: var(--u-fs-label); font-weight: 500;
  letter-spacing: .1em; text-transform: uppercase; color: var(--u-ink-2); margin-bottom: var(--u-s1);
}
.u-path--ours dt { color: var(--u-amber); }
.u-path dd { margin: 0; font-size: .875rem; }

/* ---------- 19. Final CTA ---------- */
.u-final { text-align: center; }
.u-final h2 { font-size: var(--u-fs-h2); max-width: 20ch; margin-inline: auto; }
.u-final .u-lead { margin-inline: auto; max-width: 56ch; }
.u-final .u-cta-row { justify-content: center; margin-top: var(--u-s7); }
.u-final__direct {
  margin-top: var(--u-s7); padding-top: var(--u-s6);
  border-top: 1px solid var(--u-violet-line);
  display: flex; flex-wrap: wrap; gap: var(--u-s4) var(--u-s7); justify-content: center;
}
.u-final__direct a {
  display: inline-flex; align-items: center; gap: var(--u-s3);
  color: var(--u-on-violet); text-decoration: none; font-size: .9375rem; min-height: 44px;
}
.u-final__direct a:hover { color: var(--u-amber); }
.u-final__direct svg { width: 18px; height: 18px; color: var(--u-amber); flex: none; }

/* ---------- 20. Footer ---------- */
.u-footer { background: var(--u-violet-900); color: var(--u-on-violet); padding-block: var(--u-s8) var(--u-s6); }
.u-footer__top { display: grid; gap: var(--u-s7); grid-template-columns: 1fr; }
@media (min-width: 720px) { .u-footer__top { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1040px) { .u-footer__top { grid-template-columns: 1.4fr repeat(3, minmax(0, 1fr)); } }
.u-footer__brand img { width: 218px; height: 60px; object-fit: contain; }
.u-footer__brand p { margin-top: var(--u-s5); font-size: var(--u-fs-small); color: var(--u-on-violet-2); max-width: 40ch; }
.u-footer h2 {
  font-family: var(--u-mono); font-size: var(--u-fs-label); font-weight: 500;
  letter-spacing: .14em; text-transform: uppercase; color: var(--u-amber); margin-bottom: var(--u-s4);
}
.u-footer nav li { margin-bottom: var(--u-s1); }
.u-footer nav a {
  display: inline-block; padding: 6px 0; color: var(--u-on-violet-2);
  text-decoration: none; font-size: .875rem; min-height: 32px;
}
.u-footer nav a:hover { color: var(--u-amber); }
.u-footer address { font-style: normal; font-size: .875rem; color: var(--u-on-violet-2); line-height: 1.7; }
.u-footer address a { display: inline-block; padding-block: 5px; color: var(--u-on-violet-2); }
.u-footer address a:hover { color: var(--u-amber); }
.u-social { display: flex; gap: var(--u-s3); margin-top: var(--u-s5); }
.u-social a {
  display: inline-flex; align-items: center; justify-content: center;
  width: 44px; height: 44px; border: 1px solid var(--u-violet-line); border-radius: var(--u-rp);
  color: var(--u-on-violet); transition: all var(--u-dur-1) var(--u-ease);
}
.u-social a:hover { border-color: var(--u-amber); color: var(--u-amber); }
.u-social svg { width: 18px; height: 18px; }
.u-footer__bottom {
  margin-top: var(--u-s8); padding-top: var(--u-s5);
  border-top: 1px solid var(--u-violet-line);
  display: flex; flex-wrap: wrap; gap: var(--u-s3) var(--u-s5);
  align-items: center; justify-content: space-between;
  font-size: .8125rem; color: var(--u-on-violet-2);
}
.u-footer__legal { display: flex; flex-wrap: wrap; gap: var(--u-s4); }
.u-footer__legal a { color: var(--u-on-violet-2); text-decoration: none; }
.u-footer__legal a:hover { color: var(--u-amber); }

/* ---------- 21. Scroll reveal (opt-in, JS-added) ---------- */
/* Only ever hidden when JS is present to reveal it again. */
.u-js .u-reveal { opacity: 0; transform: translateY(14px); }
.u-js .u-reveal.is-in {
  opacity: 1; transform: none;
  transition: opacity var(--u-dur-3) var(--u-ease), transform var(--u-dur-3) var(--u-ease);
}

/* ---------- 22. Reduced motion — static, information-equivalent ---------- */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
  }
  .u-orbit__arc, .u-orbit__core-ring { stroke-dashoffset: 0; }
  .u-orbit__node { opacity: 1; }
  /* The pulse is the one element in the diagram that carries no meaning, so it
     is removed rather than parked. Stopped, it would sit as a permanent bright
     arc between two of the six services and say those two are connected to each
     other -- which the diagram does not claim. */
  .u-orbit__sweep { display: none; animation: none; }
  /* `animation: none` here is load-bearing, not tidiness. The rule above zeroes
     animation-duration but not animation-delay, and the halo's `backwards` fill
     would hold its dimmest keyframe for the whole 1.5s delay before jumping. */
  .u-orbit__halo { animation: none; opacity: .5; transform: scale(1); }
  .u-steps__item::after { transform: none; opacity: .55; }
  .u-js .u-reveal { opacity: 1; transform: none; }
  .u-btn:hover { transform: none; }
}

/* ---------- 23. Forced colors ---------- */
@media (forced-colors: active) {
  .u-btn { border: 2px solid ButtonText; }
  .u-card, .u-layer, .u-core, .u-steps__item, .u-sector, .u-ins__item,
  .u-brandstack__band, .u-vid__frame { border: 1px solid CanvasText; }
  .u-orbit__node-bg, .u-spine__mark { forced-color-adjust: none; }
}

/* ---------- 24. Print ---------- */
@media print {
  .u-header, .u-mobilenav, .u-vid__play, .u-orbit__caption { display: none !important; }
  body { background: #fff; color: #000; }
  .u-section--violet, .u-section--violet-deep, .u-hero, .u-footer, .u-strip {
    background: #fff !important; color: #000 !important;
  }
}


/* ===== ROUND 10: HOOK — caption under the artwork ==================== */

.u-colfig--hook { margin-top: calc(var(--u-s8) - var(--u-s7)); }
@media (max-width: 700px)  { .u-colfig--hook { margin-top: 0; } }
@media (min-width: 1000px) { .u-colfig--hook { margin-top: 0; } }

@media (min-width: 1000px) and (max-width: 1199.98px) {
  .u-colfig--hook { margin-top: calc(var(--u-s8) + var(--u-s4)); }
}

@media (min-width: 1000px) {

  /* The brand stack keeps its place by spanning both rows; the artwork takes
     the 280px of column 1 that is empty today. align-items:start is already on
     .u-wl, so the stack stays pinned to the top of the pair. */
  .u-wl .u-wl__list   { grid-column: 1; grid-row: 1; }
  .u-wl .u-brandstack { grid-column: 2; grid-row: 1 / span 2; position: relative; z-index: 1; }
  .u-colfig--hook { grid-row: 2; }

  /* The ink fills column 1 and stops on the line it ends on; the transparent
     corner is what crosses the gutter and runs under the band. Never above the
     asset's native 915, at any width. */
  .u-colfig--hook .u-colfig__art img {
    width: min(915px, calc(100% * 915 / 662));
    max-width: 915px;
  }

  /* One column: artwork, then the caption under it, which is what was asked
     for and is also the layout this component already uses below 1200. */
  .u-colfig--hook { grid-column: 1; }
  .u-colfig--hook .u-colfig__grid { display: block; }

  /* Under the image the vertical rule has nothing to sit against, so the
     caption returns to this component's own stacked treatment — the rule above
     the words, exactly as it is below 1200. */
  .u-colfig--hook .u-colfig__note {
    align-self: auto; display: block;
    max-width: var(--u-measure);
    border-left: 0; padding-left: 0;
    border-top: 1px solid var(--u-ink-line);
    margin-top: var(--u-s6); padding-top: var(--u-s4);
  }
  .u-colfig--hook .u-colfig__note::before { display: none; }
}
