/* =====================================================================
   ENCODEX — SERVICES · "THE ASSEMBLY BAY" (v8.0 · MONOLITH)
   A restrained editorial layer around one live scene: the Sentinel at
   the bench, the commission taking shape above it (src/services.js).
   Below the bay, eight stations: doctrine (with FIG-00), disciplines
   (with drawn instrument figures), programs (with machined glyphs),
   protocol, bench rules, the register extract, the network, the
   commission. Shared chrome, tokens and controls remain in site.css.

   Reveal pre-states are gated behind html.js — the <head> watchdog
   drops that class if the module controller never comes alive, so no
   copy is ever trapped behind an unfired reveal. The discipline
   schematics follow the same rule: no JS → fully drawn, statically.
   ===================================================================== */

:root {
  --s-house: cubic-bezier(0.16, 0.6, 0.2, 1);
  --s-max: 1280px;
}

body.services-page {
  padding: 0;
  overflow-x: hidden;
  background: #05070b;
}

body.services-page::after {
  background-size: 96px 96px;
  opacity: 0.22;
}

/* Near-opaque bars over a near-black scene: the 4–10% that shows through is
   too dark to read a blur on, but the filter re-rasterizes the strip behind
   each bar every scroll frame (mobile-Safari jank). Dropped to match the other
   pages, which already ship these bars blur-free. Backgrounds unchanged. */
.services-page .site-bottom {
  background: rgba(4, 5, 8, 0.96);
}

.services-page .site-top {
  background: rgba(4, 5, 8, 0.9);
}

main.services {
  width: 100%;
  max-width: none;
  margin: 0;
  padding: 0 0 44px;
  overflow: clip;
}

/* anchored sections land clear of the fixed top bar */
main.services section[id] {
  scroll-margin-top: 74px;
}

.s-shell {
  width: min(100%, var(--s-max));
  margin-inline: auto;
  padding-inline: clamp(20px, 5vw, 72px);
}

.s-section-label,
.s-eyebrow {
  margin: 0;
  font: 500 9.5px var(--f-mono);
  letter-spacing: 0.22em;
  text-transform: uppercase;
  color: #7f8996;
}

.s-section-label {
  padding-top: 3px;
}

.s-eyebrow {
  display: flex;
  align-items: center;
  gap: 13px;
  color: #aeb6c2;
}

.s-eyebrow span {
  color: var(--txt-4);
}

.s-reveal {
  transition:
    opacity 1.15s ease,
    transform 1.15s var(--s-house),
    filter 1.15s ease;
}

html.js .s-reveal {
  opacity: 0;
  transform: translateY(24px);
  filter: blur(9px);
}

html.js .s-reveal.is-visible {
  opacity: 1;
  transform: none;
  filter: none;
}

/* =====================================================================
   HERO — the live bay
   ===================================================================== */

.s-hero {
  position: relative;
  isolation: isolate;
  height: clamp(560px, calc(100svh - 144px), 880px);
  min-height: 0;
  overflow: hidden;
  border-bottom: 1px solid var(--line);
  background: #030406;
}

.s-hero__media,
.s-hero__poster,
#services-scene,
#services-scene canvas,
.s-hero__scrim,
.s-hero__grain {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
}

.s-hero__media {
  z-index: -1;
  overflow: hidden;
  background: #000;
}

.s-hero__poster {
  object-fit: cover;
  object-position: 58% 44%;
  filter: grayscale(1) brightness(0.27) contrast(1.18);
  transform: scale(1.025);
  opacity: 0.68;
  transition: opacity 1.5s ease, transform 3.2s var(--s-house);
}

#services-scene {
  pointer-events: none;
  will-change: transform, opacity; /* scroll parallax writes both */
}

#services-scene canvas {
  display: block;
  opacity: 0;
  transform: scale(1.015);
  transition: opacity 1.6s ease, transform 2.2s var(--s-house);
}

body.s-scene-ready #services-scene canvas {
  opacity: 1;
  transform: none;
}

body.s-scene-ready .s-hero__poster {
  opacity: 0;
  transform: scale(1.06);
}

.s-hero__scrim {
  pointer-events: none;
  background:
    linear-gradient(to bottom, rgba(2, 3, 5, 0.72) 0%, rgba(2, 3, 5, 0) 18%),
    linear-gradient(to right, rgba(2, 3, 5, 0.8) 0%, rgba(2, 3, 5, 0.28) 47%, rgba(2, 3, 5, 0.03) 74%),
    linear-gradient(to top, rgba(2, 3, 5, 0.88) 0%, rgba(2, 3, 5, 0.15) 48%, rgba(2, 3, 5, 0) 72%),
    var(--lens-vignette, none); /* the composer grade's lens vignette — see site.css */
}

.s-hero__grain {
  pointer-events: none;
  opacity: 0.035;
  mix-blend-mode: screen;
  background-image: url("data:image/svg+xml,<svg xmlns='http://www.w3.org/2000/svg' width='150' height='150'><filter id='g'><feTurbulence type='fractalNoise' baseFrequency='0.8' numOctaves='2' stitchTiles='stitch'/><feColorMatrix type='saturate' values='0'/></filter><rect width='150' height='150' filter='url(%23g)'/></svg>");
}

.s-hero__copy {
  position: absolute;
  z-index: 2;
  left: clamp(20px, 5vw, 72px);
  bottom: clamp(72px, 9vh, 108px);
  width: min(700px, calc(100% - clamp(40px, 10vw, 144px)));
}

.s-hero__copy > * {
  transition:
    opacity 1.5s ease,
    transform 1.5s var(--s-house),
    filter 1.5s ease;
}

html.js .s-hero__copy > * {
  opacity: 0;
  transform: translateY(18px);
  filter: blur(10px);
}

html.js body.ready .s-hero__copy > * {
  opacity: 1;
  transform: none;
  filter: none;
}

body.ready .s-hero__copy .s-eyebrow { transition-delay: 0.12s; }
body.ready .s-hero__copy h1 { transition-delay: 0.28s; }
body.ready .s-hero__copy .s-hero__lead { transition-delay: 0.52s; }
body.ready .s-hero__copy .s-hero__actions { transition-delay: 0.74s; }

.s-hero h1 {
  max-width: 16ch;
  margin: 24px 0 23px;
  font-family: var(--f-disp);
  font-size: clamp(34px, 4.35vw, 62px);
  font-weight: 400;
  line-height: 1.12;
  letter-spacing: 0.03em;
  text-transform: uppercase;
  text-wrap: balance;
  color: var(--txt);
  text-shadow: 0 12px 42px rgba(0, 0, 0, 0.62);
}

.s-hero__lead {
  max-width: 55ch;
  margin: 0;
  font-size: clamp(14px, 1.25vw, 16.5px);
  line-height: 1.7;
  letter-spacing: 0.035em;
  color: #a5aeba;
  text-shadow: 0 8px 24px #000;
}

.s-hero__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 13px;
  margin-top: 32px;
}

.s-hero__telemetry {
  position: absolute;
  z-index: 2;
  top: 88px;
  right: clamp(20px, 5vw, 72px);
  display: flex;
  align-items: center;
  gap: 12px;
  font: 400 8px var(--f-mono);
  letter-spacing: 0.2em;
  color: var(--txt-4);
  transition: opacity 1.2s ease 0.9s;
}

html.js .s-hero__telemetry {
  opacity: 0;
}

html.js body.ready .s-hero__telemetry {
  opacity: 1;
}

.s-hero__telemetry-line {
  width: 38px;
  height: 1px;
  background: var(--txt-4);
}

.s-hero__cue {
  position: absolute;
  z-index: 3;
  right: clamp(20px, 5vw, 72px);
  bottom: 70px;
  display: flex;
  align-items: center;
  gap: 13px;
  font: 400 8px var(--f-mono);
  letter-spacing: 0.24em;
  color: var(--txt-3);
}

.s-hero__cue i {
  position: relative;
  display: block;
  width: 46px;
  height: 1px;
  overflow: hidden;
  background: var(--txt-4);
}

.s-hero__cue i::after {
  content: '';
  position: absolute;
  inset: 0;
  background: var(--txt);
  transform: translateX(-100%);
  animation: sCue 2.8s var(--s-house) infinite;
}

@keyframes sCue {
  0%, 18% { transform: translateX(-100%); }
  72%, 100% { transform: translateX(100%); }
}

/* =====================================================================
   SHARED — section headings
   ===================================================================== */

.s-doctrine h2,
.s-section-head h2,
.s-protocol h2,
.s-commission h2 {
  margin: 0;
  font-family: var(--f-disp);
  font-weight: 400;
  letter-spacing: 0.02em;
  line-height: 1.18;
  text-transform: uppercase;
  text-wrap: balance;
  color: var(--txt);
}

.s-section-head {
  display: grid;
  grid-template-columns: minmax(180px, 0.62fr) minmax(0, 1.55fr);
  gap: clamp(32px, 6vw, 96px);
  margin-bottom: clamp(62px, 8vw, 104px);
}

.s-section-head h2 {
  font-size: clamp(28px, 4vw, 52px);
}

.s-section-head > div > p {
  max-width: 48ch;
  margin: 22px 0 0;
  font-size: 15px;
  line-height: 1.7;
  color: var(--txt-2);
}

/* =====================================================================
   01 · THE DOCTRINE
   ===================================================================== */

.s-doctrine {
  padding-top: 76px;
  padding-bottom: clamp(92px, 12vw, 150px);
}

.s-doctrine__grid {
  display: grid;
  grid-template-columns: minmax(130px, 0.58fr) minmax(320px, 1.35fr) minmax(260px, 0.85fr);
  gap: clamp(28px, 5vw, 78px);
  align-items: start;
}

.s-doctrine h2 {
  max-width: 18ch;
  font-size: clamp(28px, 4vw, 52px);
}

/* Italian sets long compounds ("RESPONSABILITÀ") that run wider than this
   column at the shared display size, so single words broke onto their own
   lines and spilled past the column edge. The column is capped by .s-shell
   and does not widen with the viewport, so the cap here is set from the
   column, not the screen. */
html[lang='it'] .s-doctrine h2 {
  font-size: clamp(26px, 2.7vw, 35px);
}

.s-doctrine__body {
  padding-top: 4px;
}

.s-doctrine__body p {
  margin: 0;
  font-size: clamp(14px, 1.25vw, 16px);
  line-height: 1.75;
  color: var(--txt-2);
}

.s-doctrine__body p + p {
  margin-top: 22px;
  color: #7f8996;
}

/* =====================================================================
   02 · THE DISCIPLINES — the bench mega-system, then six bays in
   alternating lab-style rows (text column beside a large system plate)
   ===================================================================== */

.s-disciplines {
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
  background: #07090d;
}

.s-disciplines .s-shell {
  padding-top: clamp(94px, 11vw, 150px);
  padding-bottom: clamp(94px, 11vw, 150px);
}

.s-disc-list {
  border-bottom: 1px solid var(--line);
}

.s-disc {
  position: relative;
  display: grid;
  grid-template-columns: minmax(0, 45fr) minmax(0, 55fr);
  gap: clamp(26px, 4.5vw, 72px);
  align-items: center;
  padding: clamp(38px, 5vw, 60px) 0;
  border-top: 1px solid var(--line);
}

/* white hairline sweeps the top rule on approach */
.s-disc::before {
  content: '';
  position: absolute;
  top: -1px;
  left: 0;
  width: 0;
  height: 1px;
  background: var(--txt);
  transition: width 0.85s var(--s-house);
}

.s-disc:hover::before,
.s-disc:focus-within::before {
  width: 100%;
}

/* even rows flip: the plate leads, the text follows */
.s-disc--flip .s-disc__plate { order: -1; }

.s-disc__col { min-width: 0; }

.s-disc__col .s-disc__body { margin-top: 30px; }

.s-disc__code {
  display: block;
  font: 400 9px var(--f-mono);
  letter-spacing: 0.18em;
  color: var(--txt-4);
}

.s-disc__id h3 {
  margin: 22px 0 0;
  font-family: var(--f-disp);
  font-size: clamp(18px, 2vw, 27px);
  font-weight: 400;
  line-height: 1.25;
  letter-spacing: 0.02em;
  color: var(--txt);
}

.s-disc__id > p {
  margin: 14px 0 0;
  font-size: 14px;
  line-height: 1.55;
  color: #7f8996;
}

.s-disc__body > p:first-child {
  max-width: 58ch;
  margin: 0;
  font-size: 15px;
  line-height: 1.72;
  color: var(--txt-2);
}

.s-disc__body ul {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 18px;
  margin: 24px 0 0;
  padding: 0;
  list-style: none;
}

.s-disc__body li {
  position: relative;
  padding-left: 12px;
  font: 400 9px var(--f-mono);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: #7f8996;
}

.s-disc__body li::before {
  content: '';
  position: absolute;
  left: 0;
  top: 50%;
  width: 4px;
  height: 1px;
  background: var(--txt-3);
}

.s-disc__out {
  display: flex;
  align-items: baseline;
  gap: 14px;
  max-width: 58ch;
  margin: 26px 0 0;
  padding-top: 14px;
  border-top: 1px solid var(--line);
  font-size: 12.5px;
  letter-spacing: 0.02em;
  color: #aeb6c2;
  transition: border-color 0.6s ease;
}

.s-disc__out span {
  font: 500 8px var(--f-mono);
  letter-spacing: 0.2em;
  white-space: nowrap;
  color: var(--txt-4);
  transition: color 0.6s ease;
}

.s-disc:hover .s-disc__out { border-top-color: #2c3542; }
.s-disc:hover .s-disc__out span { color: #7f8996; }

/* =====================================================================
   03 · THE PROTOCOL — five stations, each with a hard exit
   ===================================================================== */

.s-protocol {
  padding-top: clamp(94px, 11vw, 150px);
  padding-bottom: clamp(94px, 11vw, 150px);
}

.s-protocol__head {
  display: grid;
  grid-template-columns: minmax(160px, 0.55fr) minmax(320px, 1fr) minmax(260px, 0.8fr);
  gap: clamp(28px, 5vw, 74px);
  align-items: start;
}

.s-protocol h2 {
  font-size: clamp(28px, 3.5vw, 48px);
}

.s-protocol__head > p:last-child {
  margin: 4px 0 0;
  font-size: 15px;
  line-height: 1.72;
  color: var(--txt-2);
}

.s-protocol__line {
  margin-top: clamp(66px, 8vw, 100px);
}

/* the rail: a hairline the pulse travels — work moving down the line */
.s-protocol__rail {
  position: relative;
  height: 1px;
  overflow: hidden;
  background: var(--line);
}

.s-protocol__rail i {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  width: 22%;
  background: linear-gradient(90deg, transparent, rgba(207, 214, 221, 0.9) 50%, transparent);
  transform: translateX(-110%);
  animation: sRail 9s cubic-bezier(0.4, 0.1, 0.6, 0.9) infinite;
}

@keyframes sRail {
  0%, 8% { transform: translateX(-110%); }
  92%, 100% { transform: translateX(560%); }
}

.s-protocol__stations {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  margin: 0;
  padding: 0;
  list-style: none;
  border-bottom: 1px solid var(--line);
}

.s-protocol__stations li {
  display: flex;
  flex-direction: column;
  min-height: 280px;
  padding: 26px clamp(16px, 2vw, 28px) 26px;
  border-left: 1px solid var(--line);
}

.s-protocol__stations li:first-child {
  border-left: 0;
  padding-left: 0;
}

.s-st__code {
  font: 400 9px var(--f-mono);
  letter-spacing: 0.18em;
  color: var(--txt-4);
}

.s-protocol__stations h3 {
  margin: 42px 0 14px;
  font-family: var(--f-disp);
  font-size: 15.5px;
  font-weight: 400;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--txt);
}

.s-protocol__stations li > p:not(.s-st__exit) {
  max-width: 30ch;
  margin: 0 0 24px;
  font-size: 13px;
  line-height: 1.68;
  color: var(--txt-2);
}

/* the station's headline: the one sentence that says what the stage is for.
   Sits between the station name and the body, brighter and a touch larger. */
.s-protocol__stations li > p.s-st__lead {
  margin: 0 0 15px;
  font-size: 14.5px;
  line-height: 1.45;
  letter-spacing: 0.01em;
  color: var(--txt);
}

.s-st__exit {
  display: flex;
  gap: 10px;
  margin: auto 0 0;
  padding-top: 14px;
  border-top: 1px solid var(--line);
  font: 400 9px var(--f-mono);
  letter-spacing: 0.12em;
  line-height: 1.7;
  text-transform: uppercase;
  color: #97a1af;
}

.s-st__exit span {
  letter-spacing: 0.2em;
  color: var(--txt-4);
}

/* the last station never exits — hold it a shade brighter */
.s-protocol__stations li:last-child .s-st__exit {
  border-top-color: #3a4553;
  color: var(--txt);
}

/* =====================================================================
   04 · THE BENCH RULES
   ===================================================================== */

.s-rules {
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
  background: #090c11;
}

.s-rules .s-shell {
  padding-top: clamp(94px, 11vw, 150px);
  padding-bottom: clamp(94px, 11vw, 150px);
}

.s-rules__ledger {
  margin: 0;
  padding: 0;
  list-style: none;
  border-bottom: 1px solid var(--line);
}

.s-rules__ledger li {
  position: relative;
  display: grid;
  grid-template-columns: 110px minmax(220px, 0.85fr) minmax(300px, 1.15fr);
  gap: clamp(22px, 4vw, 60px);
  align-items: start;
  padding: clamp(30px, 3.6vw, 44px) 0;
  border-top: 1px solid var(--line);
}

.s-rules__ledger li::before {
  content: '';
  position: absolute;
  top: -1px;
  left: 0;
  width: 0;
  height: 1px;
  background: var(--txt);
  transition: width 0.85s var(--s-house);
}

.s-rules__ledger li:hover::before {
  width: 100%;
}

.s-rule__no {
  font-family: var(--f-disp);
  font-size: clamp(28px, 3vw, 40px);
  line-height: 1;
  color: #232b36;
  transition: color 0.6s ease;
}

.s-rules__ledger li:hover .s-rule__no {
  color: #3a4553;
}

.s-rules__ledger h3 {
  margin: 4px 0 0;
  font-family: var(--f-disp);
  font-size: clamp(16px, 1.8vw, 22px);
  font-weight: 400;
  letter-spacing: 0.03em;
  color: var(--txt);
}

.s-rules__ledger p {
  max-width: 52ch;
  margin: 7px 0 0;
  font-size: 14.5px;
  line-height: 1.7;
  color: var(--txt-2);
}

/* ---- equipment manifest strip ------------------------------------ */

.s-manifest {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: 14px 26px;
  margin-top: 56px;
  padding: 19px 0;
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
  font: 500 9px var(--f-mono);
  letter-spacing: 0.18em;
}

.s-manifest__label {
  color: var(--txt-4);
}

.s-manifest__items {
  color: #7f8996;
}

.s-manifest__items i {
  font-style: normal;
  color: var(--txt-4);
  padding: 0 4px;
}

.s-manifest__link {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  margin-left: auto;
  color: var(--txt);
  transition: color 0.3s ease;
}

.s-manifest__link b {
  font-weight: 400;
  transition: transform 0.5s var(--s-house);
}

.s-manifest__link:hover {
  color: var(--hi);
}

.s-manifest__link:hover b {
  transform: translateX(5px);
}

/* =====================================================================
   05 · ON RECORD — the register extract
   ===================================================================== */

.s-record {
  padding-top: clamp(104px, 13vw, 175px);
  padding-bottom: clamp(104px, 13vw, 175px);
}

.s-record__list {
  border-bottom: 1px solid var(--line);
}

.s-record__row {
  display: grid;
  grid-template-columns: 80px minmax(170px, 0.95fr) minmax(190px, 1.05fr) 76px;
  align-items: center;
  gap: clamp(14px, 2.5vw, 26px);
  min-height: 92px;
  padding: 20px 0;
  border-top: 1px solid var(--line);
  transition: padding 0.6s var(--s-house), border-color 0.4s ease;
}

a.s-record__row:hover,
a.s-record__row:focus-visible {
  padding-inline: 16px;
  border-color: #566170;
  outline: none;
}

.s-record__ref {
  font: 400 9px var(--f-mono);
  letter-spacing: 0.16em;
  color: var(--txt-4);
}

.s-record__name {
  font-family: var(--f-disp);
  font-size: clamp(13px, 1.5vw, 19px);
  letter-spacing: 0.04em;
  color: var(--txt);
}

.s-record__desc {
  font: 400 10px var(--f-mono);
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: #7f8996;
}

.s-record__go {
  justify-self: end;
  font: 400 15px var(--f-mono);
  font-style: normal;
  color: var(--txt-3);
  transition: color 0.4s ease, transform 0.6s var(--s-house);
}

a.s-record__row:hover .s-record__go,
a.s-record__row:focus-visible .s-record__go {
  color: var(--txt);
  transform: translateX(6px);
}

/* sealed rows — redaction bars, a notched seal, no invitation */
.s-record__row.is-sealed {
  opacity: 0.82;
}

.s-record__seal {
  justify-self: end;
  padding: 5px 8px 4px;
  border: 1px solid #232b36;
  clip-path: polygon(0 0, calc(100% - 5px) 0, 100% 5px, 100% 100%, 5px 100%, 0 calc(100% - 5px));
  font: 500 7.5px var(--f-mono);
  font-style: normal;
  letter-spacing: 0.22em;
  color: var(--txt-3);
}

.s-record__row .bar {
  display: block;
  width: min(170px, 90%);
  height: 12px;
  position: relative;
  overflow: hidden;
  background: #1d242e;
}

.s-record__row .bar--s {
  width: min(210px, 95%);
  height: 9px;
  opacity: 0.75;
}

/* light passes over the seals, slowly */
.s-record__row .bar::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(100deg, transparent 30%, rgba(151, 161, 175, 0.16) 50%, transparent 70%);
  transform: translateX(-100%);
  animation: sSheen 7s ease-in-out infinite;
}

@keyframes sSheen {
  0%, 55% { transform: translateX(-100%); }
  85%, 100% { transform: translateX(100%); }
}

.s-record__action {
  display: flex;
  justify-content: flex-end;
  margin-top: 34px;
}

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  white-space: nowrap;
  border: 0;
}

/* =====================================================================
   06 · THE NETWORK — Milan / Paris / Austin
   ===================================================================== */

.s-network {
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
  background: #06080d;
}

.s-network .s-shell {
  padding-top: clamp(94px, 11vw, 150px);
  padding-bottom: clamp(94px, 11vw, 150px);
}

.s-network__grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 14px;
}

.s-station {
  position: relative;
  padding: 30px 28px 26px;
  background: #0a0d12;
  border: 1px solid var(--line);
  clip-path: polygon(0 0, calc(100% - var(--cut)) 0, 100% var(--cut), 100% 100%, var(--cut) 100%, 0 calc(100% - var(--cut)));
  transition: border-color 0.3s ease, background-color 0.3s ease, transform 0.3s ease;
}

.s-station:hover {
  border-color: #3a4553;
  background: #0c1016;
  transform: translateY(-3px);
}

.s-station__code {
  display: flex;
  align-items: center;
  justify-content: space-between;
  font: 400 8.5px var(--f-mono);
  letter-spacing: 0.2em;
  color: var(--txt-4);
}

.s-station__code i {
  width: 4px;
  height: 4px;
  background: var(--hi);
  box-shadow: 0 0 6px rgba(237, 241, 245, 0.8);
  animation: pulse 3.6s ease-in-out infinite;
}

.s-station h3 {
  margin: 22px 0 0;
  font-family: var(--f-disp);
  font-size: clamp(19px, 2vw, 24px);
  font-weight: 400;
  letter-spacing: 0.1em;
  color: var(--txt);
}

.s-station__role {
  min-height: 42px;
  margin: 14px 0 0;
  font-size: 13px;
  line-height: 1.6;
  color: var(--txt-2);
}

.s-station__coord {
  margin: 18px 0 0;
  font: 400 9px var(--f-mono);
  letter-spacing: 0.14em;
  color: var(--txt-3);
}

.s-station__clock {
  display: flex;
  align-items: baseline;
  gap: 12px;
  margin: 26px 0 0;
  padding-top: 18px;
  border-top: 1px solid var(--line);
}

.s-station__clock time {
  font: 400 24px var(--f-mono);
  letter-spacing: 0.06em;
  color: var(--txt);
  font-variant-numeric: tabular-nums;
}

.s-station__clock span {
  font: 500 8px var(--f-mono);
  letter-spacing: 0.22em;
  color: var(--txt-4);
}

.s-network__note {
  margin: 42px 0 0;
  text-align: center;
  font: 500 9px var(--f-mono);
  letter-spacing: 0.2em;
  color: #7f8996;
}

.s-network__note span {
  padding: 0 8px;
  color: var(--txt-4);
}

/* =====================================================================
   08 · THE FOUNDER — one name on the work
   ===================================================================== */

.s-founder {
  padding-top: clamp(104px, 13vw, 175px);
  padding-bottom: clamp(104px, 13vw, 175px);
  border-top: 1px solid var(--line);
}

.s-founder__body {
  max-width: 760px;
  margin-left: auto;
}

.s-founder__body p {
  margin: 0;
  font-size: clamp(14px, 1.25vw, 16px);
  line-height: 1.75;
  color: var(--txt-2);
}

.s-founder__sig {
  margin-top: 30px !important;
  font: 500 10px var(--f-mono);
  letter-spacing: 0.22em;
  color: var(--txt-3);
}

/* =====================================================================
   07 · THE COMMISSION
   ===================================================================== */

.s-commission {
  position: relative;
  min-height: clamp(560px, 80svh, 800px);
  display: grid;
  place-items: center;
  padding: 100px clamp(20px, 5vw, 72px) 130px;
  text-align: center;
  border-top: 1px solid var(--line);
  background: #040609;
}

.s-commission::before,
.s-commission::after {
  content: '';
  position: absolute;
  pointer-events: none;
  background: var(--line);
}

.s-commission::before {
  top: 0;
  bottom: 0;
  left: 50%;
  width: 1px;
  opacity: 0.4;
}

.s-commission::after {
  top: 50%;
  left: 0;
  right: 0;
  height: 1px;
  opacity: 0.4;
}

.s-commission__inner {
  position: relative;
  z-index: 1;
  width: min(860px, 100%);
  padding: clamp(40px, 6vw, 72px) clamp(20px, 5vw, 64px);
  background: #040609;
  border: 1px solid var(--line);
  clip-path: polygon(0 0, calc(100% - var(--cut)) 0, 100% var(--cut), 100% 100%, var(--cut) 100%, 0 calc(100% - var(--cut)));
}

.s-commission h2 {
  margin-top: 24px;
  font-size: clamp(30px, 4.6vw, 60px);
}

.s-commission__inner > p:not(.s-section-label) {
  max-width: 58ch;
  margin: 26px auto 0;
  font-size: clamp(14px, 1.25vw, 16px);
  line-height: 1.75;
  color: var(--txt-2);
}

.s-commission__status {
  display: grid;
  grid-template-columns: repeat(3, auto);
  justify-content: center;
  margin: 38px auto 40px;
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
}

.s-commission__status span {
  display: flex;
  flex-direction: column;
  gap: 9px;
  padding: 16px 26px 18px;
  border-left: 1px solid var(--line);
  font: 400 10px var(--f-mono);
  letter-spacing: 0.14em;
  color: var(--txt);
}

.s-commission__status span:first-child {
  border-left: 0;
}

.s-commission__status b {
  font-weight: 500;
  font-size: 8px;
  letter-spacing: 0.22em;
  color: var(--txt-4);
}

.s-commission__actions {
  display: flex;
  justify-content: center;
  flex-wrap: wrap;
  gap: 13px;
}

.s-commission__clocks {
  position: absolute;
  z-index: 2;
  bottom: 78px;
  left: 50%;
  transform: translateX(-50%);
  justify-content: center;
  white-space: nowrap;
}

/* =====================================================================
   RESPONSIVE
   ===================================================================== */

@media (max-width: 980px) {
  .s-doctrine__grid,
  .s-protocol__head {
    grid-template-columns: 150px minmax(0, 1fr);
  }

  .s-doctrine__body,
  .s-protocol__head > p:last-child {
    grid-column: 2;
  }

  /* discipline rows stack: text column, then the full-width plate */
  .s-disc {
    grid-template-columns: 1fr;
    gap: 30px;
  }

  .s-disc--flip .s-disc__plate { order: 0; }

  .s-rules__ledger li {
    grid-template-columns: 76px minmax(200px, 0.85fr) minmax(240px, 1.15fr);
  }

  .s-record__row {
    grid-template-columns: 70px minmax(150px, 1fr) minmax(160px, 1fr) 70px;
  }
}

@media (max-width: 860px) {
  /* protocol goes vertical: the rail becomes the left spine */
  .s-protocol__rail {
    display: none;
  }

  .s-protocol__stations {
    grid-template-columns: 1fr;
    border-top: 1px solid var(--line);
    border-bottom: 1px solid var(--line);
  }

  .s-protocol__stations li {
    min-height: 0;
    padding: 26px 0 30px;
    border-left: 0;
    border-top: 1px solid var(--line);
  }

  .s-protocol__stations li:first-child {
    border-top: 0;
  }

  .s-protocol__stations h3 {
    margin-top: 18px;
  }

  .s-protocol__stations li > p:not(.s-st__exit) {
    max-width: 58ch;
  }

  .s-st__exit {
    max-width: 480px;
  }

  .s-network__grid {
    grid-template-columns: 1fr;
  }

  .s-station__role {
    min-height: 0;
  }
}

@media (max-width: 760px) {
  /* Give the unit the band back: less below-fold peek, and strip the lead +
     ghost so the title card does not grow up into the subject on short phones. */
  .s-hero {
    height: clamp(460px, calc(100svh - 96px), 760px);
  }

  .s-hero__poster {
    object-position: 58% 36%;
  }

  .s-hero__scrim {
    background:
      linear-gradient(to bottom, rgba(2, 3, 5, 0.66) 0%, rgba(2, 3, 5, 0) 16%),
      linear-gradient(to top, rgba(2, 3, 5, 0.96) 0%, rgba(2, 3, 5, 0.68) 42%, rgba(2, 3, 5, 0) 70%);
  }

  .s-hero__copy {
    bottom: 54px;
    width: calc(100% - 40px);
  }

  .s-hero h1 {
    max-width: 14ch;
    margin-block: 14px;
    font-size: clamp(26px, 8vw, 40px);
    line-height: 1.13;
  }

  /* "TRASFORMIAMO" is 12 glyphs of Michroma — wider than the phone column
     at the shared mobile size, so the first line was clipped by the hero's
     overflow. Scale the Italian headline to the longest word it has to
     carry. */
  html[lang='it'] .s-hero h1 {
    font-size: clamp(21px, 7vw, 40px);
  }

  .s-hero__lead,
  .s-hero__actions .btn.ghost,
  .s-hero__telemetry,
  .s-hero__cue {
    display: none;
  }

  .s-hero__actions {
    margin-top: 18px;
    gap: 0;
  }

  .s-doctrine {
    padding-top: 56px;
  }

  .s-doctrine__grid,
  .s-protocol__head,
  .s-section-head {
    grid-template-columns: 1fr;
    gap: 28px;
  }

  .s-doctrine__body,
  .s-protocol__head > p:last-child {
    grid-column: auto;
  }

  .s-section-head {
    margin-bottom: 52px;
  }

  .s-disc {
    gap: 24px;
    padding-block: 38px;
  }

  .s-disc__col .s-disc__body {
    margin-top: 24px;
  }

  .s-rules__ledger li {
    grid-template-columns: 56px minmax(0, 1fr);
    gap: 16px 18px;
  }

  .s-rules__ledger li p {
    grid-column: 2;
    margin-top: 0;
  }

  .s-rule__no {
    font-size: 24px;
    padding-top: 3px;
  }

  .s-manifest {
    flex-direction: column;
    align-items: flex-start;
    gap: 12px;
  }

  .s-manifest__link {
    margin-left: 0;
  }

  .s-record__row {
    grid-template-columns: minmax(0, 1fr) 70px;
    gap: 7px 16px;
    min-height: 100px;
    align-items: start;
    padding-block: 22px;
  }

  .s-record__ref {
    grid-column: 1;
    font-size: 8px;
  }

  .s-record__name,
  .s-record__desc {
    grid-column: 1;
  }

  .s-record__go,
  .s-record__seal {
    grid-column: 2;
    grid-row: 1 / 4;
    align-self: center;
  }

  .s-commission__status {
    grid-template-columns: repeat(2, minmax(0, auto));
  }

  .s-commission__status span {
    padding: 14px 18px 16px;
  }

  .s-commission__status span:nth-child(odd) {
    border-left: 0;
  }

  .s-commission__status span:nth-child(n + 3) {
    border-top: 1px solid var(--line);
  }
}

@media (max-width: 760px) and (max-height: 720px) {
  /* Short phones: reclaim the full viewport — the 96px peek was eating the
     subject band after the title card. */
  .s-hero {
    height: 100svh;
    height: 100dvh;
  }
}

@media (max-width: 520px) {
  .s-hero__copy {
    left: 20px;
  }

  .s-hero__actions .btn {
    padding-inline: 15px;
    font-size: 9px;
  }

  .s-eyebrow {
    font-size: 8px;
    letter-spacing: 0.18em;
  }


  .s-commission__clocks .cdot {
    display: none;
  }

  .s-commission__clocks {
    gap: 10px;
  }

  .s-commission__clocks .clk {
    gap: 4px;
  }

  .s-commission__clocks .clk b {
    font-size: 8px;
  }

  .s-commission__clocks .clk time {
    font-size: 10px;
  }
}

/* =====================================================================
   REDUCED MOTION
   ===================================================================== */

@media (prefers-reduced-motion: reduce) {
  html.js .s-reveal,
  html.js .s-hero__copy > *,
  html.js .s-hero__telemetry {
    opacity: 1;
    transform: none;
    filter: none;
    transition: none;
  }

  #services-scene canvas {
    transform: none;
    transition: none;
  }

  .s-hero__poster {
    transform: none;
    transition: none;
  }

  .s-hero__cue i::after {
    animation: none;
  }

  /* all perpetual chrome motion stops */
  .s-station__code i,
  .s-protocol__rail i,
  .s-record__row .bar::after {
    animation: none;
  }
}

/* =====================================================================
   ===== v8 ============================================================
   MONOLITH — 03 · THE PROGRAMS (three engagement cards) and the cyber
   note line. (FIG-00, the discipline figures and the old program
   glyphs were replaced by the v8.1 living-system plates further down;
   the program cards now carry FIG-P1/P2/P3 and THE SPINE.)
   ===================================================================== */

/* ---- 02 · the cyber note line -------------------------------------- */

.s-disc__note {
  max-width: 58ch;
  margin: 14px 0 0;
  font-size: 12.5px;
  letter-spacing: 0.02em;
  color: #7f8996;
}

/* ---- 03 · THE PROGRAMS — three ways to engage ---------------------- */

.s-programs {
  padding-top: clamp(94px, 11vw, 150px);
  padding-bottom: clamp(94px, 11vw, 150px);
}

.s-programs__grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 14px;
}

.s-prg {
  position: relative;
  display: flex;
  flex-direction: column;
  padding: 30px 28px 26px;
  background: #0a0d12;
  border: 1px solid var(--line);
  clip-path: polygon(0 0, calc(100% - var(--cut)) 0, 100% var(--cut), 100% 100%, var(--cut) 100%, 0 calc(100% - var(--cut)));
  transition: border-color 0.3s ease, background-color 0.3s ease, transform 0.3s ease;
}

.s-prg:hover {
  border-color: #3a4553;
  background: #0c1016;
  transform: translateY(-3px);
}

.s-prg__head {
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: 18px;
}

.s-prg__code {
  display: block;
  font: 400 8.5px var(--f-mono);
  letter-spacing: 0.2em;
  color: var(--txt-4);
}

.s-prg__id h3 {
  margin: 22px 0 0;
  font-family: var(--f-disp);
  font-size: clamp(18px, 1.9vw, 23px);
  font-weight: 400;
  letter-spacing: 0.08em;
  color: var(--txt);
}

.s-prg__tag {
  margin: 12px 0 0;
  font-size: 13px;
  line-height: 1.5;
  color: #7f8996;
}

.s-prg__body {
  max-width: 44ch;
  margin: 24px 0 28px;
  font-size: 13.5px;
  line-height: 1.68;
  color: var(--txt-2);
}

.s-prg__spec {
  margin: auto 0 0;
  border-top: 1px solid var(--line);
}

.s-prg__spec > div {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 14px;
  padding: 10px 0;
  border-bottom: 1px solid var(--line);
}

.s-prg__spec dt {
  font: 500 8px var(--f-mono);
  letter-spacing: 0.2em;
  color: var(--txt-4);
}

.s-prg__spec dd {
  margin: 0;
  font: 400 9.5px var(--f-mono);
  letter-spacing: 0.14em;
  text-align: right;
  color: #aeb6c2;
}

.s-programs__note {
  margin: 44px 0 0;
  text-align: center;
  font: 500 9px var(--f-mono);
  letter-spacing: 0.2em;
  color: #7f8996;
}

/* ---- v8 responsive -------------------------------------------------- */

@media (max-width: 980px) {
  .s-programs__grid {
    grid-template-columns: 1fr;
    gap: 12px;
  }

  .s-prg__body {
    max-width: 58ch;
  }

  /* THE SPINE is a desktop instrument — below 980 the cards stack
     and the connector would lie about the geometry */
  .s-spine {
    display: none;
  }
}

@media (max-width: 760px) {
  .s-prg {
    padding: 26px 22px 22px;
  }

  .s-programs__note {
    font-size: 8px;
    letter-spacing: 0.16em;
  }
}

/* =====================================================================
   ===== v8.1 ==========================================================
   LIVING SYSTEMS — the lab-plate grammar brought to services:
     FIG-00    · THE OUTCOME ENGINE          (oe-)  16 s
     FIG-BENCH · ONE COMMISSION, SIX HANDS   (bh-)  18 s
     FIG-01    · CONVERGENCE                 (cv-)  15 s
     FIG-02    · CONSTRUCTION                (ct-)  16 s
     FIG-03    · THE SHIPYARD                (sy-)  15 s
     FIG-04    · THE PERIMETER               (pm-)  17 s
     FIG-05    · THE CREW                    (cw-)  16 s
     FIG-06    · SIM TO REAL                 (st-)  18 s
     FIG-P1    · THE BUILD LINE              (bl-)  14 s
     FIG-P2    · THE STANDING WATCH          (wt-)  15 s
     FIG-P3    · THE JOINT ENGINE            (je-)  16 s
     THE SPINE · programs connector          (sp-)  18 s
   All motion CSS-only. Structural linework (.sd/.sd2/.sd3) inks in on
   reveal, texts and dressing (.sf) fade after it; loop transients ride
   shared travel/flash keyframes phase-placed per element with --ad and
   dash length --p; state-holding elements carry bespoke keyframes that
   reset inside the first seconds of each loop. Everything idles until
   the row's .s-reveal gains .is-visible. Reduced-motion freezes live
   at the very END of this file, after every animation rule.
   ===================================================================== */

/* ---- the plate — shared frame, lab grammar ------------------------- */

.s-plate {
  position: relative;
  margin: 0;
  border: 1px solid var(--line);
  background-color: #080b10;
  background-image:
    linear-gradient(rgba(27, 33, 43, 0.5) 1px, transparent 1px),
    linear-gradient(90deg, rgba(27, 33, 43, 0.5) 1px, transparent 1px);
  background-size: 28px 28px;
  clip-path: polygon(0 0, calc(100% - var(--cut)) 0, 100% var(--cut), 100% 100%, var(--cut) 100%, 0 calc(100% - var(--cut)));
  padding: 22px 20px 46px;
}

.s-plate svg {
  display: block;
  width: 100%;
  height: auto;
  overflow: visible;
}

.s-plate figcaption {
  position: absolute;
  left: 20px;
  bottom: 15px;
  font: 500 8.5px var(--f-mono);
  letter-spacing: 0.18em;
  color: var(--txt-4);
}

.s-plate__ref {
  position: absolute;
  top: 12px;
  right: 18px;
  font: 400 9px var(--f-mono);
  letter-spacing: 0.12em;
  color: var(--txt-4);
}

/* linework vocabulary — strict monochrome, hairline strokes.
   :where() keeps this at (0,1,0) so the per-figure single-class rules
   declared below it can re-colour their own strokes by order alone.
   No non-scaling-stroke here: Chromium computes dashes in screen
   space under it, which breaks every pathLength-normalised draw and
   travel the moment a plate renders at any scale other than 1:1 (the
   lab reference plates use plain scaled strokes for the same reason). */
.s-plate :where(path, circle, rect, line, polyline, polygon) {
  fill: none;
  stroke: #59636f;
  stroke-width: 1;
}

.s-plate svg .ghost { stroke: #232b37; }
.s-plate svg .hi { stroke: #dfe5ec; }
.s-plate svg .dash { stroke-dasharray: 2.5 6; }
.s-plate svg .dot { fill: #59636f; stroke: none; }
.s-plate svg .dot-hi { fill: #edf1f5; stroke: none; }

.s-plate svg text {
  font: 500 9px var(--f-mono);
  letter-spacing: 0.16em;
  fill: #545f6d;
  stroke: none;
}

.s-plate svg text.rd { fill: #7f8996; }

/* small lit dots breathe — the only always-on life */
.s-plate :is(.oe-live, .oe-benchdot) { animation: pulse 4.8s ease-in-out infinite; }

/* ---- reveal: structure inks in, dressing fades after --------------- */

html.js .s-plate :is(.sd, .sd2, .sd3) {
  stroke-dasharray: 1 1;
  stroke-dashoffset: 1;
  transition: stroke-dashoffset 2.2s var(--s-house) 0.2s;
}

html.js .s-plate .sd2 { transition-delay: 0.6s; }
html.js .s-plate .sd3 { transition-delay: 1s; }

html.js .s-plate .sf {
  opacity: 0;
  transition: opacity 1.4s ease 1.3s;
}

html.js .s-reveal.is-visible :is(.sd, .sd2, .sd3) { stroke-dashoffset: 0; }
html.js .s-reveal.is-visible .sf { opacity: 1; }

/* loops idle until the plate's reveal arrives (the .p-anim covenant) */
/* `.anim-live` is toggled on BOTH intersection edges; `.is-visible` is
   permanent because it owns the reveal end-state and the copy must never
   re-hide. Gating on `.is-visible` made this one-way, so once a visitor had
   scrolled past a plate its loops ran off-screen for the rest of the session. */
html.js .s-plate.s-reveal:not(.anim-live) svg *,
html.js .s-reveal:not(.anim-live) .s-plate svg * { animation-play-state: paused; }

/* ---- shared motion machinery ---------------------------------------
   .pp — a travelling pulse (dash of length --p on a pathLength=100
   track); .pk — a packet, same track, thick square dash; .fl — a
   transient flash. Each element places its window in the master loop
   with --ad (animation-delay); transients are invisible at both ends
   of their cycle, so phase offsets never leak across the loop seam. */

.s-plate .pp,
.s-plate .pk {
  stroke: #dfe5ec;
  stroke-width: 1.2;
  stroke-linecap: butt;
  stroke-dasharray: var(--p, 10) 100;
  stroke-dashoffset: var(--p, 10);
  opacity: 0;
}

.s-plate .pk { stroke-width: 5; }

.s-plate .fl { opacity: 0; }

@keyframes sTravel {
  0% { stroke-dashoffset: var(--p, 10); opacity: 0; }
  1% { opacity: 0.92; }
  7% { stroke-dashoffset: -100; opacity: 0.92; }
  8.5%, 100% { stroke-dashoffset: -100; opacity: 0; }
}

@keyframes sTravelSlow {
  0% { stroke-dashoffset: var(--p, 3); opacity: 0; }
  4% { opacity: 0.8; }
  82% { stroke-dashoffset: -100; opacity: 0.8; }
  84%, 100% { stroke-dashoffset: -100; opacity: 0; }
}

@keyframes sBlink {
  0% { opacity: 0; }
  1.2% { opacity: 1; }
  3.4% { opacity: 0.85; }
  6%, 100% { opacity: 0; }
}

@keyframes sMarch { to { stroke-dashoffset: -100; } }

@keyframes sShimmer {
  0%, 100% { opacity: 0.3; }
  50% { opacity: 0.75; }
}

/* =====================================================================
   FIG-00 · THE OUTCOME ENGINE — 16 s: STEADY (0–6 s) users flow and
   telemetry drifts · FAULT (6–10 s) a node flares, the wire races to
   the bench, the answer races back, the seal closes · GROWTH (10–16 s)
   an upgrade packet docks as the eighth node, REV/WK steps up, the
   cluster breathes once. The new node is absorbed as the next loop
   opens.
   ===================================================================== */

.s-fig-engine { margin-top: clamp(58px, 7vw, 88px); }

.s-fig-engine .pp,
.s-fig-engine .pk { animation: sTravel 16s linear var(--ad, 0s) infinite; }

/* telemetry drift — slow continuous pulses, product → lab */
.oe-drift {
  stroke: #8e99a7;
  stroke-dasharray: 5 45;
  opacity: 0.5;
  animation: sMarch 9s linear infinite;
}

/* users lane: dots thread the mesh, ticks file out as SERVED */
.oe-user { animation: sTravelSlow 6.4s linear var(--ad, 0s) infinite; }
.oe-tick { animation: sBlink 6.4s linear var(--ad, 0s) infinite; }

/* the heartbeat strip — subtle; THE WATCH owns this motif */
.oe-hb {
  stroke: #aeb6c2;
  stroke-dasharray: 10 90;
  opacity: 0.45;
  animation: sMarch 11s linear infinite;
}

.oe-spike { opacity: 0; animation: oeSpike 16s linear infinite; }
@keyframes oeSpike {
  0%, 39% { opacity: 0; }
  41% { opacity: 0.9; }
  48% { opacity: 0.35; }
  52%, 100% { opacity: 0; }
}

/* the fault: node 5 flares and holds hot until the seal closes */
.oe-n5 { animation: oeFault 16s linear infinite; }
@keyframes oeFault {
  0%, 37% { stroke: #59636f; }
  38.5% { stroke: #edf1f5; }
  41% { stroke: #8e99a7; }
  55% { stroke: #8e99a7; }
  62%, 100% { stroke: #59636f; }
}

.oe-bang {
  fill: #edf1f5;
  font-size: 11px;
  opacity: 0;
  animation: oeBang 16s linear infinite;
}
@keyframes oeBang {
  0%, 37.5% { opacity: 0; }
  39% { opacity: 1; }
  42% { opacity: 0.65; }
  44% { opacity: 1; }
  55% { opacity: 0.9; }
  58%, 100% { opacity: 0; }
}

/* the bench lights while it works the fault */
.oe-benchlit { opacity: 0; animation: oeBench 16s linear infinite; }
@keyframes oeBench {
  0%, 43% { opacity: 0; }
  45% { opacity: 0.9; }
  54% { opacity: 0.9; }
  58%, 100% { opacity: 0; }
}

/* the seal ring closes around the answered node, and holds */
.oe-seal {
  stroke: #edf1f5;
  stroke-dasharray: 100 100;
  stroke-dashoffset: 100;
  transform-box: fill-box;
  transform-origin: center;
  transform: rotate(-90deg);
  animation: oeSeal 16s linear infinite;
}
@keyframes oeSeal {
  0% { stroke-dashoffset: 0; opacity: 1; }
  4% { stroke-dashoffset: 0; opacity: 0; }
  5% { stroke-dashoffset: 100; opacity: 0; }
  55% { stroke-dashoffset: 100; opacity: 0; }
  56% { opacity: 1; }
  62% { stroke-dashoffset: 0; opacity: 1; }
  100% { stroke-dashoffset: 0; opacity: 1; }
}

.oe-answered { opacity: 0; animation: oeAns 16s linear infinite; }
@keyframes oeAns {
  0%, 53% { opacity: 0; }
  55% { opacity: 1; }
  57% { opacity: 0.4; }
  59% { opacity: 1; }
  66% { opacity: 1; }
  70%, 100% { opacity: 0; }
}

/* growth: the eighth node docks, its edges draw, the bar steps up */
.oe-n8 { stroke: #8e99a7; animation: oeN8 16s linear infinite; }
@keyframes oeN8 {
  0% { opacity: 1; }
  6% { opacity: 0; }
  73% { opacity: 0; }
  74.5% { opacity: 1; }
  100% { opacity: 1; }
}

.oe-grow {
  stroke: #232b37;
  stroke-dasharray: 1 1;
  stroke-dashoffset: 1;
  animation: oeGrow 16s linear infinite;
}
@keyframes oeGrow {
  0% { stroke-dashoffset: 0; opacity: 1; }
  6% { stroke-dashoffset: 0; opacity: 0; }
  7% { stroke-dashoffset: 1; opacity: 1; }
  75% { stroke-dashoffset: 1; opacity: 1; }
  84% { stroke-dashoffset: 0; opacity: 1; }
  100% { stroke-dashoffset: 0; opacity: 1; }
}

.oe-rev rect {
  fill: rgba(237, 241, 245, 0.06);
  stroke: #59636f;
}

.oe-rev8 {
  fill: rgba(237, 241, 245, 0.12);
  stroke: #aeb6c2;
  animation: oeRev8 16s linear infinite;
}
@keyframes oeRev8 {
  0% { opacity: 1; }
  6% { opacity: 0.12; }
  86% { opacity: 0.12; }
  89% { opacity: 1; }
  100% { opacity: 1; }
}

/* the cluster breathes once as growth lands */
.oe-cluster {
  transform-box: fill-box;
  transform-origin: center;
  animation: oeBreathe 16s var(--s-house) infinite;
}
@keyframes oeBreathe {
  0%, 88% { transform: scale(1); }
  93% { transform: scale(1.012); }
  98%, 100% { transform: scale(1); }
}

/* =====================================================================
   FIG-BENCH — 18 s: the brief enters, five stations fire their pulses
   into the rim (CYBER attacks it from outside instead — the rim holds,
   a seal tick files), ROBOTICS honestly idles as FORMING while the
   core lights the final segment itself; the product block exits, the
   seal stamps, and one pulse rides THE WATCH rail home.
   ===================================================================== */

.s-fig-bench { margin: 0 0 clamp(62px, 8vw, 104px); }

.s-fig-bench .pp,
.s-fig-bench .pk { animation: sTravel 18s linear var(--ad, 0s) infinite; }

/* engineering fires a three-pulse train */
.bh-train { stroke-dasharray: 4 4 4 4 4 80; }

/* the rim — twelve segments of progress, group by discipline */
.bh-seg {
  stroke: #dfe5ec;
  stroke-width: 1.6;
  opacity: 0.14;
}
.bh-sgA { animation: bhSgA 18s linear infinite; }
.bh-sgB { animation: bhSgB 18s linear infinite; }
.bh-sgC { animation: bhSgC 18s linear infinite; }
.bh-sgD { animation: bhSgD 18s linear infinite; }
.bh-sgE { animation: bhSgE 18s linear infinite; }
.bh-sgF { animation: bhSgF 18s linear infinite; }
@keyframes bhSgA { 0% { opacity: 1; } 4% { opacity: 0.14; } 17.5% { opacity: 0.14; } 19% { opacity: 1; } 100% { opacity: 1; } }
@keyframes bhSgB { 0% { opacity: 1; } 4% { opacity: 0.14; } 29.5% { opacity: 0.14; } 31% { opacity: 1; } 100% { opacity: 1; } }
@keyframes bhSgC { 0% { opacity: 1; } 4% { opacity: 0.14; } 41.5% { opacity: 0.14; } 43% { opacity: 1; } 100% { opacity: 1; } }
@keyframes bhSgD { 0% { opacity: 1; } 4% { opacity: 0.14; } 60.5% { opacity: 0.14; } 62% { opacity: 1; } 100% { opacity: 1; } }
@keyframes bhSgE { 0% { opacity: 1; } 4% { opacity: 0.14; } 73.5% { opacity: 0.14; } 75% { opacity: 1; } 100% { opacity: 1; } }
@keyframes bhSgF { 0% { opacity: 1; } 4% { opacity: 0.14; } 79% { opacity: 0.14; } 80.5% { opacity: 1; } 100% { opacity: 1; } }

/* the attack lands: rim flashes twice, holds, a seal tick files */
.bh-rimflash { opacity: 0; animation: bhRim 18s linear infinite; }
@keyframes bhRim {
  0%, 53.5% { opacity: 0; }
  55% { opacity: 0.9; }
  56.5% { opacity: 0.15; }
  58% { opacity: 0.75; }
  61%, 100% { opacity: 0; }
}

.bh-sealtick { animation: bhTick 18s linear infinite; }
@keyframes bhTick {
  0% { opacity: 1; }
  4% { opacity: 0; }
  60% { opacity: 0; }
  62% { opacity: 1; }
  100% { opacity: 1; }
}

/* the twelfth segment is lit from the core itself */
.bh-emit {
  stroke: #dfe5ec;
  stroke-width: 1.2;
  stroke-dasharray: 1 1;
  stroke-dashoffset: 1;
  opacity: 0;
  animation: bhEmit 18s linear infinite;
}
@keyframes bhEmit {
  0%, 75.5% { stroke-dashoffset: 1; opacity: 0; }
  76% { opacity: 0.9; }
  78.5% { stroke-dashoffset: 0; opacity: 0.9; }
  81% { stroke-dashoffset: 0; opacity: 0; }
  100% { stroke-dashoffset: 1; opacity: 0; }
}

/* one breath as the build completes */
.bh-core {
  transform-box: fill-box;
  transform-origin: center;
  animation: bhBreathe 18s var(--s-house) infinite;
}
@keyframes bhBreathe {
  0%, 81% { transform: scale(1); }
  84% { transform: scale(1.02); }
  87%, 100% { transform: scale(1); }
}

/* the seal stamp zone — ghosted until the product passes the gate */
.bh-stamp * { stroke: #dfe5ec; }
.bh-stamp { opacity: 0.18; animation: bhStamp 18s linear infinite; }
@keyframes bhStamp {
  0% { opacity: 1; }
  4% { opacity: 0.18; }
  92% { opacity: 0.18; }
  93.5% { opacity: 1; }
  100% { opacity: 1; }
}

/* robotics idles, honestly */
.bh-form { animation: sShimmer 4.5s ease-in-out infinite; }

/* freeze-frame prop: the product held at the gate (reduced motion) */
.bh-prodfreeze {
  fill: rgba(237, 241, 245, 0.14);
  stroke: #aeb6c2;
  opacity: 0;
}

/* =====================================================================
   FIG-01 · CONVERGENCE — 15 s: fourteen assumptions drift right;
   eleven die at MAP (staggered), one at MODEL, one at REDUCE; the
   survivor brightens, gains its ring, parks at THE BET. The ledger
   counts down 14 → 03 → 02 → 01; BOARD-DEFENSIBLE stamps.
   ===================================================================== */

.cv-dot { opacity: 0; }
.cv-a1 { animation: cvA1 15s linear infinite; }
.cv-a2 { animation: cvA2 15s linear infinite; }
.cv-a3 { animation: cvA3 15s linear infinite; }
.cv-b { animation: cvB 15s linear infinite; }
.cv-c { animation: cvC 15s linear infinite; }
.cv-d { animation: cvD 15s linear infinite; }

@keyframes cvA1 {
  0% { transform: translateX(0); opacity: 0; }
  5% { opacity: 0.55; }
  26% { transform: translateX(var(--g1)); opacity: 0.55; }
  27.5%, 100% { transform: translateX(var(--g1)); opacity: 0; }
}
@keyframes cvA2 {
  0% { transform: translateX(0); opacity: 0; }
  5% { opacity: 0.55; }
  31% { transform: translateX(var(--g1)); opacity: 0.55; }
  32.5%, 100% { transform: translateX(var(--g1)); opacity: 0; }
}
@keyframes cvA3 {
  0% { transform: translateX(0); opacity: 0; }
  5% { opacity: 0.55; }
  36% { transform: translateX(var(--g1)); opacity: 0.55; }
  37.5%, 100% { transform: translateX(var(--g1)); opacity: 0; }
}
@keyframes cvB {
  0% { transform: translateX(0); opacity: 0; }
  5% { opacity: 0.55; }
  28% { transform: translateX(var(--g1)); }
  46% { transform: translateX(var(--g2)); opacity: 0.55; }
  47.5%, 100% { transform: translateX(var(--g2)); opacity: 0; }
}
@keyframes cvC {
  0% { transform: translateX(0); opacity: 0; }
  5% { opacity: 0.55; }
  28% { transform: translateX(var(--g1)); }
  46% { transform: translateX(var(--g2)); }
  62% { transform: translateX(var(--g3)); opacity: 0.55; }
  63.5%, 100% { transform: translateX(var(--g3)); opacity: 0; }
}
@keyframes cvD {
  0% { transform: translateX(0); opacity: 0; fill: #59636f; }
  5% { opacity: 0.55; }
  28% { transform: translateX(var(--g1)); }
  46% { transform: translateX(var(--g2)); }
  62% { transform: translateX(var(--g3)); fill: #59636f; opacity: 0.55; }
  65% { fill: #edf1f5; opacity: 1; }
  74% { transform: translateX(var(--g4)); }
  94% { transform: translateX(var(--g4)); fill: #edf1f5; opacity: 1; }
  97%, 100% { transform: translateX(var(--g4)); opacity: 0; }
}

.cv-ring { opacity: 0; animation: cvRing 15s linear infinite; }
@keyframes cvRing {
  0%, 72% { opacity: 0; }
  75% { opacity: 1; }
  94% { opacity: 1; }
  97%, 100% { opacity: 0; }
}

/* freeze-frame prop: the bet, parked (reduced motion) */
.cv-freeze { opacity: 0; }

.cv-x { stroke-width: 1.2; opacity: 0; }
.cv-xa1 { animation: cvXa1 15s linear infinite; }
.cv-xa2 { animation: cvXa2 15s linear infinite; }
.cv-xa3 { animation: cvXa3 15s linear infinite; }
.cv-xb { animation: cvXb 15s linear infinite; }
.cv-xc { animation: cvXc 15s linear infinite; }
@keyframes cvXa1 { 0%, 25.5% { opacity: 0; } 26.5% { opacity: 0.95; } 29.5%, 100% { opacity: 0; } }
@keyframes cvXa2 { 0%, 30.5% { opacity: 0; } 31.5% { opacity: 0.95; } 34.5%, 100% { opacity: 0; } }
@keyframes cvXa3 { 0%, 35.5% { opacity: 0; } 36.5% { opacity: 0.95; } 39.5%, 100% { opacity: 0; } }
@keyframes cvXb { 0%, 45.5% { opacity: 0; } 46.5% { opacity: 0.95; } 49.5%, 100% { opacity: 0; } }
@keyframes cvXc { 0%, 61.5% { opacity: 0; } 62.5% { opacity: 0.95; } 65.5%, 100% { opacity: 0; } }

/* the countdown */
.cv-c14, .cv-c03, .cv-c02, .cv-c01 { opacity: 0; }
.cv-c14 { animation: cvC14 15s linear infinite; }
.cv-c03 { animation: cvC03 15s linear infinite; }
.cv-c02 { animation: cvC02 15s linear infinite; }
.cv-c01 { animation: cvC01 15s linear infinite; }
@keyframes cvC14 { 0% { opacity: 0; } 2% { opacity: 1; } 37% { opacity: 1; } 39%, 100% { opacity: 0; } }
@keyframes cvC03 { 0%, 37% { opacity: 0; } 39% { opacity: 1; } 46% { opacity: 1; } 48%, 100% { opacity: 0; } }
@keyframes cvC02 { 0%, 46% { opacity: 0; } 48% { opacity: 1; } 62% { opacity: 1; } 64%, 100% { opacity: 0; } }
@keyframes cvC01 { 0% { opacity: 1; } 1.5% { opacity: 0; } 62% { opacity: 0; } 64% { opacity: 1; } 100% { opacity: 1; } }

/* the verdict — shared stamp dress for cv/ct */
.cv-stamp path, .ct-stamp path { fill: rgba(237, 241, 245, 0.03); stroke: #3a4553; }
.cv-stamp text, .ct-stamp text { font-size: 8.5px; letter-spacing: 0.14em; fill: #aeb6c2; }
.cv-stamp { opacity: 0; animation: cvStamp 15s var(--s-house) infinite; }
@keyframes cvStamp {
  0% { opacity: 1; }
  3% { opacity: 0; }
  79% { opacity: 0; }
  82% { opacity: 1; }
  100% { opacity: 1; }
}

/* =====================================================================
   FIG-02 · CONSTRUCTION — 16 s: the drafting grid rises, four
   construction passes machine the mark, the mark inks in bright, then
   echoes into desktop / tablet / phone at scale while the motion
   meter sweeps. UNMISTAKABLE stamps.
   ===================================================================== */

.ct-grid { opacity: 0; animation: ctGrid 16s linear infinite; }
@keyframes ctGrid {
  0% { opacity: 0; }
  5% { opacity: 0.9; }
  94% { opacity: 0.9; }
  99%, 100% { opacity: 0; }
}

.ct-c {
  stroke-dasharray: 1 1;
  stroke-dashoffset: 1;
  opacity: 0;
}
.ct-c1 { animation: ctC1 16s linear infinite; }
.ct-c2 { animation: ctC2 16s linear infinite; }
.ct-c3 { animation: ctC3 16s linear infinite; }
.ct-c4 { animation: ctC4 16s linear infinite; }
@keyframes ctC1 {
  0%, 6% { stroke-dashoffset: 1; opacity: 0; }
  7% { opacity: 0.55; }
  18% { stroke-dashoffset: 0; opacity: 0.55; }
  46% { opacity: 0.55; }
  52% { opacity: 0.2; }
  95% { stroke-dashoffset: 0; opacity: 0.2; }
  98%, 100% { stroke-dashoffset: 0; opacity: 0; }
}
@keyframes ctC2 {
  0%, 12% { stroke-dashoffset: 1; opacity: 0; }
  13% { opacity: 0.55; }
  24% { stroke-dashoffset: 0; opacity: 0.55; }
  46% { opacity: 0.55; }
  52% { opacity: 0.2; }
  95% { stroke-dashoffset: 0; opacity: 0.2; }
  98%, 100% { stroke-dashoffset: 0; opacity: 0; }
}
@keyframes ctC3 {
  0%, 18% { stroke-dashoffset: 1; opacity: 0; }
  19% { opacity: 0.55; }
  28% { stroke-dashoffset: 0; opacity: 0.55; }
  46% { opacity: 0.55; }
  52% { opacity: 0.2; }
  95% { stroke-dashoffset: 0; opacity: 0.2; }
  98%, 100% { stroke-dashoffset: 0; opacity: 0; }
}
@keyframes ctC4 {
  0%, 24% { stroke-dashoffset: 1; opacity: 0; }
  25% { opacity: 0.55; }
  34% { stroke-dashoffset: 0; opacity: 0.55; }
  46% { opacity: 0.55; }
  52% { opacity: 0.2; }
  95% { stroke-dashoffset: 0; opacity: 0.2; }
  98%, 100% { stroke-dashoffset: 0; opacity: 0; }
}

.ct-mark {
  stroke-width: 1.4;
  stroke-dasharray: 1 1;
  stroke-dashoffset: 1;
  opacity: 0;
  animation: ctMark 16s linear infinite;
}
@keyframes ctMark {
  0%, 35% { stroke-dashoffset: 1; opacity: 0; }
  36% { opacity: 0.95; }
  46% { stroke-dashoffset: 0; opacity: 0.95; }
  95% { stroke-dashoffset: 0; opacity: 0.95; }
  98% { stroke-dashoffset: 0; opacity: 0; }
  100% { stroke-dashoffset: 1; opacity: 0; }
}

/* the echo: each screen pops lit, the mark landing at scale */
.ct-dev {
  opacity: 0;
  transform-box: fill-box;
  transform-origin: center;
}
.ct-devA { animation: ctDevA 16s var(--s-house) infinite; }
.ct-devB { animation: ctDevB 16s var(--s-house) infinite; }
.ct-devC { animation: ctDevC 16s var(--s-house) infinite; }
@keyframes ctDevA {
  0%, 50% { opacity: 0; transform: scale(1.15); }
  53.5% { opacity: 1; transform: scale(1); }
  94% { opacity: 1; transform: scale(1); }
  98%, 100% { opacity: 0; transform: scale(1.15); }
}
@keyframes ctDevB {
  0%, 58% { opacity: 0; transform: scale(1.15); }
  61.5% { opacity: 1; transform: scale(1); }
  94% { opacity: 1; transform: scale(1); }
  98%, 100% { opacity: 0; transform: scale(1.15); }
}
@keyframes ctDevC {
  0%, 66% { opacity: 0; transform: scale(1.15); }
  69.5% { opacity: 1; transform: scale(1); }
  94% { opacity: 1; transform: scale(1); }
  98%, 100% { opacity: 0; transform: scale(1.15); }
}

/* the motion meter never stops sweeping */
.ct-sweep {
  stroke: #aeb6c2;
  stroke-dasharray: 10 90;
  opacity: 0.55;
  animation: sMarch 3s linear infinite;
}

.ct-stamp { opacity: 0; animation: ctStamp 16s var(--s-house) infinite; }
@keyframes ctStamp {
  0% { opacity: 1; }
  3% { opacity: 0; }
  74% { opacity: 0; }
  77% { opacity: 1; }
  100% { opacity: 1; }
}

/* =====================================================================
   FIG-03 · THE SHIPYARD — 15 s: a train of commits crosses the stack
   (layers ripple), holds at TESTS; the first passes with a tick, the
   second is rejected with an × and rides the rework lane back before
   passing, the third waits its turn; deploys ride the rail to PROD,
   whose instances distribute micro-traffic continuously.
   ===================================================================== */

.s-fig-yard .pp { animation: sTravel 15s linear var(--ad, 0s) infinite; }
.s-fig-yard .fl { animation: sBlink 15s linear var(--ad, 0s) infinite; }

/* instance micro-traffic rides its own short cycle */
.s-fig-yard .sy-micro {
  stroke: #8e99a7;
  stroke-width: 1;
  animation: sTravel 3.6s linear var(--ad, 0s) infinite;
}

.sy-glow {
  fill: #dfe5ec;
  stroke: none;
  opacity: 0;
  animation: syGlow 15s linear var(--ad, 0s) infinite;
}
@keyframes syGlow {
  0%, 3% { opacity: 0; }
  6% { opacity: 0.1; }
  11% { opacity: 0; }
  55% { opacity: 0; }
  58% { opacity: 0.08; }
  62%, 100% { opacity: 0; }
}

/* the third commit waits at the gate for its beat */
.sy-hold { opacity: 0; animation: syHold 15s linear infinite; }
@keyframes syHold {
  0%, 18% { opacity: 0; }
  20% { opacity: 0.6; }
  82% { opacity: 0.6; }
  84%, 100% { opacity: 0; }
}

/* =====================================================================
   FIG-04 · THE PERIMETER, TONIGHT — 17 s: five tracers volley in and
   are absorbed at the outer ring; one penetrates to the middle ring,
   the detector arc sweeps and catches it, a seal segment closes over
   the breach; the counter ticks; the core fires its own SELF-TEST.
   ===================================================================== */

.s-fig-perim .pp { animation: sTravel 17s linear var(--ad, 0s) infinite; }
.s-fig-perim .fl { animation: sBlink 17s linear var(--ad, 0s) infinite; }

.pm-att { stroke: #aeb6c2; }

/* the detector arc sweeps to the breach, catches, releases */
.pm-sweep {
  stroke-width: 1.6;
  opacity: 0;
  transform-box: view-box;
  transform-origin: 218px 148px;
  animation: pmSweep 17s var(--s-house) infinite;
}
@keyframes pmSweep {
  0%, 54% { transform: rotate(-150deg); opacity: 0; }
  56% { opacity: 0.9; }
  62% { transform: rotate(0deg); opacity: 0.9; }
  67% { transform: rotate(0deg); opacity: 0.9; }
  71%, 100% { transform: rotate(0deg); opacity: 0; }
}

/* the seal segment closes over the breach, and holds */
.pm-seal {
  stroke: #edf1f5;
  stroke-width: 2;
  stroke-dasharray: 100 100;
  stroke-dashoffset: 100;
  animation: pmSeal 17s linear infinite;
}
@keyframes pmSeal {
  0% { stroke-dashoffset: 0; opacity: 1; }
  4% { stroke-dashoffset: 0; opacity: 0; }
  5% { stroke-dashoffset: 100; opacity: 1; }
  64% { stroke-dashoffset: 100; opacity: 1; }
  69% { stroke-dashoffset: 0; opacity: 1; }
  100% { stroke-dashoffset: 0; opacity: 1; }
}

/* the ledger line ticks as the volley is absorbed */
.pm-cntA { animation: pmCntA 17s linear infinite; }
.pm-cntB { opacity: 0; animation: pmCntB 17s linear infinite; }
@keyframes pmCntA { 0% { opacity: 1; } 53% { opacity: 1; } 55%, 100% { opacity: 0; } }
@keyframes pmCntB { 0%, 53% { opacity: 0; } 55% { opacity: 1; } 100% { opacity: 1; } }

/* =====================================================================
   FIG-05 · THE CREW — 16 s: the queue drains through the agents; each
   task travels, the agent pulses while working, the DONE ledger gains
   a bar and an audit tick; the flagged task detours up to HUMAN for
   its approve flash. Tools/memory rails march continuously.
   ===================================================================== */

.s-fig-crew .fl { animation: sBlink 16s linear var(--ad, 0s) infinite; }

.cw-bar { fill: rgba(237, 241, 245, 0.14); stroke: none; }

.cw-q1 { animation: cwQ1 16s linear infinite; }
.cw-q2 { animation: cwQ2 16s linear infinite; }
.cw-q3 { animation: cwQ3 16s linear infinite; }
@keyframes cwQ1 { 0% { opacity: 1; } 7% { opacity: 1; } 9% { opacity: 0; } 60% { opacity: 0; } 66% { opacity: 1; } 100% { opacity: 1; } }
@keyframes cwQ2 { 0%, 29% { opacity: 1; } 31% { opacity: 0; } 80% { opacity: 0; } 86% { opacity: 1; } 100% { opacity: 1; } }
@keyframes cwQ3 { 0%, 51% { opacity: 1; } 53% { opacity: 0; } 92% { opacity: 0; } 97% { opacity: 1; } 100% { opacity: 1; } }

.cw-rail {
  stroke: #333b47;
  stroke-dasharray: 2 4;
  animation: sMarch 30s linear infinite;
}

.cw-task { fill: #dfe5ec; stroke: none; opacity: 0; }
.cw-t3 { fill: #edf1f5; }
.cw-t1 { animation: cwT1 16s linear infinite; }
.cw-t2 { animation: cwT2 16s linear infinite; }
.cw-t3 { animation: cwT3 16s linear infinite; }
@keyframes cwT1 {
  0%, 7% { transform: translate(0, 0); opacity: 0; }
  8.5% { opacity: 0.9; }
  15% { transform: translate(124px, 2px); }
  26% { transform: translate(124px, 2px); }
  32% { transform: translate(350px, 8px); opacity: 0.9; }
  33.5%, 100% { transform: translate(350px, 8px); opacity: 0; }
}
@keyframes cwT2 {
  0%, 28% { transform: translate(0, 0); opacity: 0; }
  29.5% { opacity: 0.9; }
  37% { transform: translate(124px, 106px); }
  50% { transform: translate(124px, 106px); }
  56% { transform: translate(350px, 8px); opacity: 0.9; }
  57.5%, 100% { transform: translate(350px, 8px); opacity: 0; }
}
@keyframes cwT3 {
  0%, 52% { transform: translate(0, 0); opacity: 0; }
  53.5% { opacity: 1; }
  60% { transform: translate(150px, 30px); }
  66% { transform: translate(150px, 30px); }
  72% { transform: translate(270px, -62px); }
  78% { transform: translate(270px, -62px); }
  84% { transform: translate(350px, 8px); opacity: 1; }
  85.5%, 100% { transform: translate(350px, 8px); opacity: 0; }
}

/* the agent halo pulses while it works */
.cw-work { opacity: 0; animation: cwWork 16s linear var(--ad, 0s) infinite; }
@keyframes cwWork {
  0% { opacity: 0; }
  1% { opacity: 0.85; }
  4% { opacity: 0.3; }
  7% { opacity: 0.85; }
  11% { opacity: 0.85; }
  13%, 100% { opacity: 0; }
}

/* the DONE ledger accumulates, audit ticks included */
.cw-d1, .cw-d2, .cw-d3 { opacity: 0; }
.cw-d1 { animation: cwD1 16s linear infinite; }
.cw-d2 { animation: cwD2 16s linear infinite; }
.cw-d3 { animation: cwD3 16s linear infinite; }
@keyframes cwD1 { 0% { opacity: 1; } 4% { opacity: 0; } 32% { opacity: 0; } 34% { opacity: 1; } 100% { opacity: 1; } }
@keyframes cwD2 { 0% { opacity: 1; } 4% { opacity: 0; } 55% { opacity: 0; } 57% { opacity: 1; } 100% { opacity: 1; } }
@keyframes cwD3 { 0% { opacity: 1; } 4% { opacity: 0; } 84% { opacity: 0; } 86% { opacity: 1; } 100% { opacity: 1; } }

/* =====================================================================
   FIG-06 · ASSEMBLY LINE 01 — 18 s: the billet rides in (0–9 %), the
   press forms the chassis (9–17 %), the unit docks at STN-B where two
   arms hang six legs, far side first (31–55 %), the scanner calibrates
   at STN-C (61–74 %), then the finished hexapod walks off the line on
   an alternating tripod gait (74–94 %). The belt never stops. Every
   transient is invisible across the loop seam; the seam itself lands
   while the unit is off-canvas.
   ===================================================================== */

/* the unit rides the belt: dock A → dock B → dock C → walk-off */
.s-fig-asm .ax-unit {
  transform-box: view-box;
  transform: translateX(-96px);
  animation: axLine 18s linear infinite;
}
@keyframes axLine {
  0% { transform: translateX(-96px); animation-timing-function: var(--s-house); }
  9% { transform: translateX(105px); }
  24% { transform: translateX(105px); animation-timing-function: var(--s-house); }
  31% { transform: translateX(225px); }
  55% { transform: translateX(225px); animation-timing-function: var(--s-house); }
  61% { transform: translateX(345px); }
  74% { transform: translateX(345px); animation-timing-function: linear; }
  94%, 100% { transform: translateX(565px); }
}

/* limb linework: near legs mid-tone, far legs graphite */
.s-fig-asm .ax-seg {
  fill: none;
  stroke: #59636f;
  stroke-width: 1.3;
  stroke-linejoin: round;
  stroke-linecap: round;
  stroke-dasharray: 1 1;
  stroke-dashoffset: 1;
}
.s-fig-asm .ax-far { stroke: #232b37; }
.s-fig-asm .ax-jt { fill: #59636f; stroke: none; }
.s-fig-asm .ax-ft { fill: #dfe5ec; stroke: none; }

/* the raw billet — consumed by the press */
.s-fig-asm .ax-billet { opacity: 0; animation: axBillet 18s linear infinite; }
@keyframes axBillet {
  0% { opacity: 0.9; }
  11% { opacity: 0.9; }
  14%, 100% { opacity: 0; }
}

/* STN-A — the press descends once, firmly */
.s-fig-asm .ax-ram {
  transform-box: view-box;
  animation: axRam 18s var(--s-house) infinite;
}
@keyframes axRam {
  0%, 8% { transform: translateY(0); }
  11% { transform: translateY(76px); }
  13.5% { transform: translateY(76px); }
  17%, 100% { transform: translateY(0); }
}

/* the chassis inks in under the press; instruments follow */
.s-fig-asm .ax-dr {
  stroke-dasharray: 1 1;
  stroke-dashoffset: 1;
  opacity: 0;
}
.s-fig-asm .ax-ch { animation: axCh 18s var(--s-house) infinite; }
.s-fig-asm .ax-ch2 { animation: axCh2 18s var(--s-house) infinite; }
@keyframes axCh {
  0%, 10.5% { stroke-dashoffset: 1; opacity: 0; }
  11.5% { opacity: 1; }
  16% { stroke-dashoffset: 0; opacity: 1; }
  100% { stroke-dashoffset: 0; opacity: 1; }
}
@keyframes axCh2 {
  0%, 15% { stroke-dashoffset: 1; opacity: 0; }
  16.5% { opacity: 1; }
  19.5% { stroke-dashoffset: 0; opacity: 1; }
  100% { stroke-dashoffset: 0; opacity: 1; }
}

/* STN-B — the fitting arms swing in from parked, nudge twice, return */
.s-fig-asm .ax-arm { transform-box: view-box; }
.s-fig-asm .ax-armL { transform-origin: 213px 80px; animation: axArmL 18s var(--s-house) infinite; }
.s-fig-asm .ax-armR { transform-origin: 237px 80px; animation: axArmR 18s var(--s-house) infinite; }
@keyframes axArmL {
  0%, 29% { transform: rotate(-16deg); }
  33% { transform: rotate(0deg); }
  36% { transform: rotate(3deg); }
  39% { transform: rotate(0deg); }
  44% { transform: rotate(3deg); }
  47% { transform: rotate(0deg); }
  53%, 100% { transform: rotate(-16deg); }
}
@keyframes axArmR {
  0%, 31% { transform: rotate(16deg); }
  35% { transform: rotate(0deg); }
  38% { transform: rotate(-3deg); }
  41% { transform: rotate(0deg); }
  46% { transform: rotate(-3deg); }
  49% { transform: rotate(0deg); }
  55%, 100% { transform: rotate(16deg); }
}

/* six legs hang in sequence — far triple, then near triple */
.s-fig-asm :is(.ax-lf1, .ax-lf2, .ax-lf3, .ax-ln1, .ax-ln2, .ax-ln3) { opacity: 0; }
.s-fig-asm .ax-lf1 { animation: axLf1 18s var(--s-house) infinite; }
.s-fig-asm .ax-lf2 { animation: axLf2 18s var(--s-house) infinite; }
.s-fig-asm .ax-lf3 { animation: axLf3 18s var(--s-house) infinite; }
.s-fig-asm .ax-ln1 { animation: axLn1 18s var(--s-house) infinite; }
.s-fig-asm .ax-ln2 { animation: axLn2 18s var(--s-house) infinite; }
.s-fig-asm .ax-ln3 { animation: axLn3 18s var(--s-house) infinite; }
@keyframes axLf1 {
  0%, 33% { stroke-dashoffset: 1; opacity: 0; }
  34% { opacity: 1; }
  37.5% { stroke-dashoffset: 0; opacity: 1; }
  100% { stroke-dashoffset: 0; opacity: 1; }
}
@keyframes axLf2 {
  0%, 36% { stroke-dashoffset: 1; opacity: 0; }
  37% { opacity: 1; }
  40.5% { stroke-dashoffset: 0; opacity: 1; }
  100% { stroke-dashoffset: 0; opacity: 1; }
}
@keyframes axLf3 {
  0%, 39% { stroke-dashoffset: 1; opacity: 0; }
  40% { opacity: 1; }
  43.5% { stroke-dashoffset: 0; opacity: 1; }
  100% { stroke-dashoffset: 0; opacity: 1; }
}
@keyframes axLn1 {
  0%, 43% { stroke-dashoffset: 1; opacity: 0; }
  44% { opacity: 1; }
  47.5% { stroke-dashoffset: 0; opacity: 1; }
  100% { stroke-dashoffset: 0; opacity: 1; }
}
@keyframes axLn2 {
  0%, 46% { stroke-dashoffset: 1; opacity: 0; }
  47% { opacity: 1; }
  50.5% { stroke-dashoffset: 0; opacity: 1; }
  100% { stroke-dashoffset: 0; opacity: 1; }
}
@keyframes axLn3 {
  0%, 49% { stroke-dashoffset: 1; opacity: 0; }
  50% { opacity: 1; }
  52.5% { stroke-dashoffset: 0; opacity: 1; }
  100% { stroke-dashoffset: 0; opacity: 1; }
}

/* the walk-off gait — two tripods alternate about their hips */
.s-fig-asm .ax-leg { transform-box: fill-box; }
.s-fig-asm .ax-gA { animation: axGaitA 18s var(--s-house) infinite; }
.s-fig-asm .ax-gB { animation: axGaitB 18s var(--s-house) infinite; }
@keyframes axGaitA {
  0%, 74% { transform: rotate(0deg); }
  76.5% { transform: rotate(calc(var(--dir, 1) * 7deg)); }
  79% { transform: rotate(0deg); }
  81.5% { transform: rotate(calc(var(--dir, 1) * 7deg)); }
  84% { transform: rotate(0deg); }
  86.5% { transform: rotate(calc(var(--dir, 1) * 7deg)); }
  89% { transform: rotate(0deg); }
  91.5% { transform: rotate(calc(var(--dir, 1) * 7deg)); }
  94%, 100% { transform: rotate(0deg); }
}
@keyframes axGaitB {
  0%, 76.5% { transform: rotate(0deg); }
  79% { transform: rotate(calc(var(--dir, 1) * 7deg)); }
  81.5% { transform: rotate(0deg); }
  84% { transform: rotate(calc(var(--dir, 1) * 7deg)); }
  86.5% { transform: rotate(0deg); }
  89% { transform: rotate(calc(var(--dir, 1) * 7deg)); }
  91.5% { transform: rotate(0deg); }
  94%, 100% { transform: rotate(0deg); }
}

/* the body rides the gait — a light suspension bob */
.s-fig-asm .ax-chgrp { transform-box: fill-box; animation: axBob 18s ease-in-out infinite; }
@keyframes axBob {
  0%, 74% { transform: translateY(0); }
  76.5% { transform: translateY(-1.6px); }
  79% { transform: translateY(0); }
  81.5% { transform: translateY(-1.6px); }
  84% { transform: translateY(0); }
  86.5% { transform: translateY(-1.6px); }
  89% { transform: translateY(0); }
  91.5% { transform: translateY(-1.6px); }
  94%, 100% { transform: translateY(0); }
}

/* STN-C — the scan sweeps, the ring closes, the eyes light */
.s-fig-asm .ax-scan {
  stroke: #dfe5ec;
  stroke-width: 1;
  opacity: 0;
  transform-box: view-box;
  animation: axScan 18s ease-in-out infinite;
}
@keyframes axScan {
  0%, 62% { transform: translateX(-46px); opacity: 0; }
  63.5% { opacity: 0.55; }
  68.5% { transform: translateX(46px); opacity: 0.55; }
  70%, 100% { transform: translateX(46px); opacity: 0; }
}
.s-fig-asm .ax-ring {
  stroke: #dfe5ec;
  stroke-width: 1;
  stroke-dasharray: 100 100;
  stroke-dashoffset: 100;
  opacity: 0;
  animation: axRing 18s linear infinite;
}
@keyframes axRing {
  0%, 66% { stroke-dashoffset: 100; opacity: 0; }
  67% { opacity: 0.9; }
  71% { stroke-dashoffset: 0; opacity: 0.9; }
  74%, 100% { stroke-dashoffset: 0; opacity: 0; }
}
.s-fig-asm .ax-cal { opacity: 0; animation: axCal 18s linear infinite; }
@keyframes axCal {
  0%, 68% { opacity: 0; }
  69.5% { opacity: 1; }
  74% { opacity: 1; }
  76%, 100% { opacity: 0; }
}
.s-fig-asm .ax-eye { opacity: 0; animation: axEye 18s linear infinite; }
@keyframes axEye { 0%, 66% { opacity: 0; } 68%, 100% { opacity: 1; } }
.s-fig-asm .ax-tag { opacity: 0; animation: axTag 18s linear infinite; }
@keyframes axTag { 0%, 68% { opacity: 0; } 70%, 100% { opacity: 0.9; } }

/* stage readout, completion ticks, contact sparks, chip, belt drive */
.s-fig-asm .ax-st { opacity: 0; }
.s-fig-asm .ax-st1 { animation: axSt1 18s linear infinite; }
.s-fig-asm .ax-st2 { animation: axSt2 18s linear infinite; }
.s-fig-asm .ax-st3 { animation: axSt3 18s linear infinite; }
.s-fig-asm .ax-st4 { animation: axSt4 18s linear infinite; }
@keyframes axSt1 { 0%, 7% { opacity: 0; } 9% { opacity: 1; } 27% { opacity: 1; } 29%, 100% { opacity: 0; } }
@keyframes axSt2 { 0%, 29% { opacity: 0; } 31% { opacity: 1; } 53% { opacity: 1; } 55%, 100% { opacity: 0; } }
@keyframes axSt3 { 0%, 55% { opacity: 0; } 57% { opacity: 1; } 71% { opacity: 1; } 73%, 100% { opacity: 0; } }
@keyframes axSt4 { 0%, 73% { opacity: 0; } 75% { opacity: 1; } 96% { opacity: 1; } 98%, 100% { opacity: 0; } }

.s-fig-asm .ax-tk { opacity: 0; stroke-width: 1.2; }
.s-fig-asm .ax-tk1 { animation: axTk1 18s linear infinite; }
.s-fig-asm .ax-tk2 { animation: axTk2 18s linear infinite; }
.s-fig-asm .ax-tk3 { animation: axTk3 18s linear infinite; }
@keyframes axTk1 { 0%, 19% { opacity: 0; } 21% { opacity: 1; } 95% { opacity: 1; } 97%, 100% { opacity: 0; } }
@keyframes axTk2 { 0%, 51% { opacity: 0; } 53% { opacity: 1; } 95% { opacity: 1; } 97%, 100% { opacity: 0; } }
@keyframes axTk3 { 0%, 71% { opacity: 0; } 73% { opacity: 1; } 95% { opacity: 1; } 97%, 100% { opacity: 0; } }

.s-fig-asm .ax-spark { stroke: #dfe5ec; animation: sBlink 18s linear var(--ad, 0s) infinite; }
.s-fig-asm .ax-chip { animation: sShimmer 5s ease-in-out infinite; }

.s-fig-asm svg .ax-belt {
  stroke-dasharray: 2.5 5.5;
  animation: axBelt 7s linear infinite;
}
@keyframes axBelt { to { stroke-dashoffset: -96; } }

/* =====================================================================
   THE PROGRAM PLATES — mid-size systems in the three engagement cards,
   above each body. Same grammar as the discipline plates, scaled to
   the card column.
   ===================================================================== */

.s-prg__plate {
  margin: 26px 0 0;
  padding: 14px 12px 36px;
}

.s-prg__plate figcaption { left: 12px; bottom: 12px; }
.s-prg__plate .s-plate__ref { top: 10px; right: 12px; }

/* =====================================================================
   FIG-P1 · THE BUILD LINE — 14 s: six weekly pulses leave the rail
   through the manifold; the block gains a segment as each one lands;
   at W06 the seal draws around it and the finished block slides right
   through the PRODUCTION gate. The berth stays; the product ships.
   ===================================================================== */

.s-fig-line .pp { animation: sTravel 14s linear var(--ad, 0s) infinite; }
.s-fig-line .fl { animation: sBlink 14s linear var(--ad, 0s) infinite; }

/* the six segments — lit in build order, bottom row first */
.bl-s {
  fill: rgba(237, 241, 245, 0.06);
  stroke: #aeb6c2;
  opacity: 0;
}
.bl-s1 { animation: blC1 14s linear infinite; }
.bl-s2 { animation: blC2 14s linear infinite; }
.bl-s3 { animation: blC3 14s linear infinite; }
.bl-s4 { animation: blC4 14s linear infinite; }
.bl-s5 { animation: blC5 14s linear infinite; }
.bl-s6 { animation: blC6 14s linear infinite; }
@keyframes blC1 { 0%, 9% { opacity: 0; } 10.3% { opacity: 1; } 12.7% { opacity: 0.78; } 100% { opacity: 0.78; } }
@keyframes blC2 { 0%, 20.4% { opacity: 0; } 21.7% { opacity: 1; } 24.1% { opacity: 0.78; } 100% { opacity: 0.78; } }
@keyframes blC3 { 0%, 31.9% { opacity: 0; } 33.2% { opacity: 1; } 35.6% { opacity: 0.78; } 100% { opacity: 0.78; } }
@keyframes blC4 { 0%, 43.3% { opacity: 0; } 44.6% { opacity: 1; } 47% { opacity: 0.78; } 100% { opacity: 0.78; } }
@keyframes blC5 { 0%, 54.7% { opacity: 0; } 56% { opacity: 1; } 58.4% { opacity: 0.78; } 100% { opacity: 0.78; } }
@keyframes blC6 { 0%, 66.1% { opacity: 0; } 67.4% { opacity: 1; } 69.8% { opacity: 0.78; } 100% { opacity: 0.78; } }

/* the seal closes around the finished block */
.bl-seal {
  stroke-width: 1.2;
  stroke-dasharray: 100 100;
  stroke-dashoffset: 100;
  opacity: 0;
  animation: blSeal 14s linear infinite;
}
@keyframes blSeal {
  0%, 68% { stroke-dashoffset: 100; opacity: 0; }
  69.5% { opacity: 1; }
  76% { stroke-dashoffset: 0; opacity: 1; }
  100% { stroke-dashoffset: 0; opacity: 1; }
}

/* the sealed product slides through the gate; the berth stays */
.bl-ship { animation: blShip 14s var(--s-house) infinite; }
@keyframes blShip {
  0%, 78% { transform: translateX(0); opacity: 1; }
  86% { transform: translateX(46px); opacity: 1; }
  89%, 100% { transform: translateX(46px); opacity: 0; }
}

/* the readout files as the block crosses */
.bl-shipped { opacity: 0; animation: blShipped 14s linear infinite; }
@keyframes blShipped {
  0%, 83% { opacity: 0; }
  84.5% { opacity: 1; }
  86% { opacity: 0.4; }
  87.5% { opacity: 1; }
  95% { opacity: 1; }
  98%, 100% { opacity: 0; }
}

/* =====================================================================
   FIG-P2 · THE STANDING WATCH — 15 s: the site's one true heartbeat.
   The trace scrolls as the carrier hum; at 6 s an incident spike rises,
   the catch bracket snaps shut, the seal dot lands, MTTR files, the
   spike eases back down. The SLO dial holds at 99.9 and re-verifies
   once a loop; the console pings — the line stays open.
   ===================================================================== */

.s-fig-watch .fl { animation: sBlink 15s linear var(--ad, 0s) infinite; }

/* the trace — one 132-unit period, scrolled by transform only */
.wt-wave { animation: wtScroll 5.5s linear infinite; }
@keyframes wtScroll { to { transform: translateX(-132px); } }
.wt-ecg { stroke: #8e99a7; opacity: 0.6; }

/* the SLO dial — a near-closed gauge, notch at twelve */
.wt-arc {
  stroke-dasharray: 99.7 0.3;
  transform: rotate(-90deg);
  transform-box: fill-box;
  transform-origin: center;
}

/* the incident: rise, catch, seal, recover */
.wt-spike {
  transform-box: fill-box;
  transform-origin: 50% 100%;
  animation: wtSpike 15s var(--s-house) infinite;
}
@keyframes wtSpike {
  0%, 39% { transform: scaleY(0.03); opacity: 0; }
  40.5% { transform: scaleY(0.12); opacity: 0.9; }
  43% { transform: scaleY(1); opacity: 1; }
  83% { transform: scaleY(1); opacity: 1; }
  88% { transform: scaleY(0.08); opacity: 0.35; }
  90%, 100% { transform: scaleY(0.03); opacity: 0; }
}

.wt-br { animation: wtBr 15s var(--s-house) infinite; }
@keyframes wtBr {
  0%, 45% { transform: translateX(var(--bx)); opacity: 0; }
  46.5% { opacity: 0.95; }
  48.5% { transform: translateX(0); opacity: 0.95; }
  84% { transform: translateX(0); opacity: 0.95; }
  88%, 100% { transform: translateX(0); opacity: 0; }
}

.wt-sdot { animation: wtSdot 15s linear infinite; }
@keyframes wtSdot {
  0%, 51% { opacity: 0; }
  52.5% { opacity: 1; }
  86% { opacity: 1; }
  89%, 100% { opacity: 0; }
}

.wt-mttr { opacity: 0; animation: wtMttr 15s linear infinite; }
@keyframes wtMttr {
  0%, 54% { opacity: 0; }
  55.5% { opacity: 1; }
  57% { opacity: 0.35; }
  58.5% { opacity: 1; }
  92% { opacity: 1; }
  95%, 100% { opacity: 0; }
}

/* the console pings twice a loop — the founder's line, open */
.wt-pdot { animation: pulse 4.8s ease-in-out infinite; }
.wt-ping {
  stroke: #8e99a7;
  opacity: 0;
  transform-box: fill-box;
  transform-origin: center;
  animation: wtPing 7.5s ease-out infinite;
}
@keyframes wtPing {
  0% { transform: scale(0.25); opacity: 0; }
  5% { opacity: 0.45; }
  42%, 100% { transform: scale(1.7); opacity: 0; }
}

/* =====================================================================
   FIG-P3 · THE JOINT ENGINE — 16 s: three waves of pulses ride both
   rails into the core; each wave ignites it and a ring draws on; the
   split meter fills from both ends and meets in the middle; then the
   returns ride back out — both directions, both parties.
   ===================================================================== */

.s-fig-joint .pp { animation: sTravel 16s linear var(--ad, 0s) infinite; }
.s-fig-joint .fl { animation: sBlink 16s linear var(--ad, 0s) infinite; }

.je-core { animation: pulse 4.8s ease-in-out infinite; }

.je-ign { animation: jeIgn 16s linear infinite; }
@keyframes jeIgn {
  0%, 15% { opacity: 0; }
  16% { opacity: 0.9; }
  19% { opacity: 0; }
  45% { opacity: 0; }
  46% { opacity: 0.9; }
  49% { opacity: 0; }
  75% { opacity: 0; }
  76% { opacity: 0.9; }
  79%, 100% { opacity: 0; }
}

/* the rings — drawn on, held, absorbed at the loop seam */
.je-r1, .je-r2, .je-r3 {
  stroke-dasharray: 100 100;
  stroke-dashoffset: 100;
  opacity: 0;
  transform: rotate(-90deg);
  transform-box: fill-box;
  transform-origin: center;
}
.je-r1 { animation: jeR1 16s linear infinite; }
.je-r2 { animation: jeR2 16s linear infinite; }
.je-r3 { animation: jeR3 16s linear infinite; }
@keyframes jeR1 {
  0%, 17% { stroke-dashoffset: 100; opacity: 0; }
  18.5% { opacity: 0.9; }
  24% { stroke-dashoffset: 0; opacity: 0.9; }
  96% { stroke-dashoffset: 0; opacity: 0.9; }
  99.5%, 100% { stroke-dashoffset: 0; opacity: 0; }
}
@keyframes jeR2 {
  0%, 47% { stroke-dashoffset: 100; opacity: 0; }
  48.5% { opacity: 0.7; }
  54% { stroke-dashoffset: 0; opacity: 0.7; }
  96% { stroke-dashoffset: 0; opacity: 0.7; }
  99.5%, 100% { stroke-dashoffset: 0; opacity: 0; }
}
@keyframes jeR3 {
  0%, 77% { stroke-dashoffset: 100; opacity: 0; }
  78.5% { opacity: 0.5; }
  83% { stroke-dashoffset: 0; opacity: 0.5; }
  96% { stroke-dashoffset: 0; opacity: 0.5; }
  99.5%, 100% { stroke-dashoffset: 0; opacity: 0; }
}

/* the split meter — stepped from both ends, meets in the middle */
.je-mL, .je-mR {
  stroke-width: 3;
  transform-box: fill-box;
}
.je-mL { transform-origin: 0 50%; animation: jeML 16s var(--s-house) infinite; }
.je-mR { transform-origin: 100% 50%; animation: jeML 16s var(--s-house) infinite; }
@keyframes jeML {
  0%, 20% { transform: scaleX(0); opacity: 1; }
  27% { transform: scaleX(0.34); }
  50% { transform: scaleX(0.34); }
  57% { transform: scaleX(0.67); }
  80% { transform: scaleX(0.67); }
  85.5% { transform: scaleX(1); opacity: 1; }
  96.5% { transform: scaleX(1); opacity: 1; }
  99%, 100% { transform: scaleX(1); opacity: 0; }
}

.je-verdict { opacity: 0; animation: jeVerdict 16s linear infinite; }
@keyframes jeVerdict {
  0%, 86% { opacity: 0; }
  88% { opacity: 1; }
  96.5% { opacity: 1; }
  99%, 100% { opacity: 0; }
}

/* =====================================================================
   THE SPINE — the quiet hairline beneath the three programs, desktop
   only. Every commission goes live into THE WATCH (GO-LIVE); a dashed
   branch rises toward VENTURE (THE RARE CASE). 18 s; it connects, it
   does not shout.
   ===================================================================== */

.s-spine {
  margin: 10px 0 0;
}

.s-spine svg {
  display: block;
  width: 100%;
  height: auto;
  overflow: visible;
}

.s-spine :where(path, circle) {
  fill: none;
  stroke: #59636f;
  stroke-width: 1;
}

.s-spine svg .ghost { stroke: #232b37; }
.s-spine svg .dash { stroke-dasharray: 2.5 6; }
.s-spine svg .dot-hi { fill: #edf1f5; stroke: none; }

.s-spine svg text {
  font: 500 10px var(--f-mono);
  letter-spacing: 0.16em;
  fill: #545f6d;
  stroke: none;
}

/* spine reveal — same ink-in machinery as the plates */
html.js .s-spine :is(.sd, .sd2) {
  stroke-dasharray: 1 1;
  stroke-dashoffset: 1;
  transition: stroke-dashoffset 2.2s var(--s-house) 0.2s;
}
html.js .s-spine .sd2 { transition-delay: 0.6s; }
html.js .s-spine .sf {
  opacity: 0;
  transition: opacity 1.4s ease 1.3s;
}
html.js .s-spine.s-reveal:not(.anim-live) svg * { animation-play-state: paused; }

/* the two travellers — slow comets, never urgent */
.s-spine .pp {
  stroke: #8e99a7;
  stroke-width: 1.2;
  stroke-linecap: butt;
  stroke-dasharray: var(--p, 12) 100;
  stroke-dashoffset: var(--p, 12);
  opacity: 0;
  animation: spTravel 18s linear var(--ad, 0s) infinite;
}
.s-spine .sp-rare { stroke: #77808d; }
@keyframes spTravel {
  0% { stroke-dashoffset: var(--p, 12); opacity: 0; }
  2% { opacity: 0.55; }
  38% { stroke-dashoffset: -100; opacity: 0.55; }
  41%, 100% { stroke-dashoffset: -100; opacity: 0; }
}

.s-spine .fl {
  opacity: 0;
  animation: sBlink 18s linear var(--ad, 0s) infinite;
}

/* ---- v8.1 responsive ------------------------------------------------ */

@media (max-width: 760px) {
  .s-plate { padding: 16px 12px 40px; }

  .s-plate figcaption { left: 12px; bottom: 13px; }

  .s-plate__ref { display: none; }

  .s-fig-engine { margin-top: 48px; }

  .s-fig-bench { margin-bottom: 56px; }

  .s-prg__plate { margin-top: 20px; }
}

/* =====================================================================
   ===== v8.1 REDUCED MOTION ===========================================
   Kept at the very END of the file so these statics cascade after
   every animation rule above. Each plate freezes at its FINAL, most
   legible state: systems lit, packets hidden, counters at their final
   value, seals closed.
   ===================================================================== */

@media (prefers-reduced-motion: reduce) {
  /* structure arrives fully drawn; dressing fully faded in */
  html.js .s-plate :is(.sd, .sd2, .sd3) {
    transition: none;
    stroke-dashoffset: 0;
  }

  html.js .s-plate .sf {
    transition: none;
    opacity: 1;
  }

  /* every plate loop stops dead */
  .s-plate svg * { animation: none !important; }

  /* travelling pulses, packets and transient flashes vanish */
  .s-plate :is(.pp, .pk, .fl),
  .oe-drift, .oe-hb, .oe-user, .oe-spike, .oe-benchlit, .oe-bang,
  .oe-answered, .bh-rimflash, .cv-x, .ct-sweep, .sy-glow, .sy-hold,
  .cw-task, .cw-work, .pm-sweep { opacity: 0; }

  /* FIG-00 — eight nodes lit, seal closed, REV bar full */
  .oe-tick { opacity: 0.6; }
  .oe-n8 { opacity: 1; }
  .oe-grow { stroke-dashoffset: 0; opacity: 1; }
  .oe-seal { stroke-dashoffset: 0; opacity: 1; }
  .oe-rev8 { opacity: 1; }

  /* FIG-BENCH — all twelve segments lit, product at gate, seal stamped */
  .bh-seg { opacity: 1; }
  .bh-emit { stroke-dashoffset: 0; opacity: 0.5; }
  .bh-sealtick { opacity: 1; }
  .bh-stamp { opacity: 1; }
  .bh-form { opacity: 0.55; }
  .bh-prodfreeze { opacity: 1; }

  /* FIG-01 — the bet parked and ringed, count at 01, verdict stamped */
  .cv-dot { opacity: 0; }
  .cv-freeze { opacity: 1; }
  .cv-ring { opacity: 1; }
  .cv-c14, .cv-c03, .cv-c02 { opacity: 0; }
  .cv-c01 { opacity: 1; }
  .cv-stamp { opacity: 1; }

  /* FIG-02 — mark machined, screens lit, verdict held */
  .ct-grid { opacity: 0.9; }
  .ct-c { stroke-dashoffset: 0; opacity: 0.2; }
  .ct-mark { stroke-dashoffset: 0; opacity: 0.95; }
  .ct-dev { opacity: 1; transform: none; }
  .ct-stamp { opacity: 1; }

  /* FIG-04 — breach sealed, ledger at its final count */
  .pm-seal { stroke-dashoffset: 0; opacity: 1; }
  .pm-cntA { opacity: 0; }
  .pm-cntB { opacity: 1; }

  /* FIG-05 — queue steady, ledger full, rails parked */
  .cw-q1, .cw-q2, .cw-q3 { opacity: 1; }
  .cw-d1, .cw-d2, .cw-d3 { opacity: 1; }
  .cw-rail { stroke-dashoffset: 0; }

  /* FIG-06 — line at rest: unit calibrated at STN-C, ticks filed,
     READY shown, transients hidden */
  .s-fig-asm .ax-unit { transform: translateX(345px); }
  .s-fig-asm :is(.ax-ram, .ax-arm, .ax-leg, .ax-chgrp) { transform: none; }
  .s-fig-asm :is(.ax-seg, .ax-dr) { stroke-dashoffset: 0; opacity: 1; }
  .s-fig-asm :is(.ax-lf1, .ax-lf2, .ax-lf3, .ax-ln1, .ax-ln2, .ax-ln3) { opacity: 1; }
  .s-fig-asm :is(.ax-eye, .ax-tag) { opacity: 1; }
  .s-fig-asm :is(.ax-billet, .ax-scan, .ax-ring, .ax-cal, .ax-spark) { opacity: 0; }
  .s-fig-asm .ax-tk { opacity: 1; }
  .s-fig-asm :is(.ax-st1, .ax-st2, .ax-st3) { opacity: 0; }
  .s-fig-asm .ax-st4 { opacity: 1; }
  .s-fig-asm .ax-chip { opacity: 0.55; }

  /* FIG-P1 — six segments lit, seal closed, block at the berth,
     readout filed */
  .bl-s { opacity: 0.78; }
  .bl-seal { stroke-dashoffset: 0; opacity: 1; }
  .bl-ship { transform: none; opacity: 1; }
  .bl-shipped { opacity: 1; }

  /* FIG-P2 — the incident answered: spike risen, bracket closed,
     seal landed, MTTR filed, dial lit, trace parked */
  .wt-ping { opacity: 0; }
  .wt-wave { transform: none; }
  .wt-spike { transform: none; opacity: 1; }
  .wt-br { transform: none; opacity: 0.95; }
  .wt-sdot { opacity: 1; }
  .wt-mttr { opacity: 1; }

  /* FIG-P3 — three rings grown, meter met, verdict held */
  .je-ign { opacity: 0; }
  .je-r1 { stroke-dashoffset: 0; opacity: 0.9; }
  .je-r2 { stroke-dashoffset: 0; opacity: 0.7; }
  .je-r3 { stroke-dashoffset: 0; opacity: 0.5; }
  .je-mL, .je-mR { transform: scaleX(1); opacity: 1; }
  .je-verdict { opacity: 1; }

  /* THE SPINE — line drawn, labels on, travellers hidden */
  .s-spine svg * { animation: none !important; }
  .s-spine :is(.pp, .fl) { opacity: 0; }
  html.js .s-spine :is(.sd, .sd2) {
    transition: none;
    stroke-dashoffset: 0;
  }
  html.js .s-spine .sf {
    transition: none;
    opacity: 1;
  }
}
