/* Self-hosted IBM Plex, latin + latin-ext, pulled from Google Fonts.
   unicode-range is kept exactly as Google shipped it, so a page that
   never uses a latin-ext character still never downloads that file. */

@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(assets/fonts/IBMPlexMono-400-latin-ext.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 400;
  font-display: swap;
  src: url(assets/fonts/IBMPlexMono-400-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url(assets/fonts/IBMPlexMono-500-latin-ext.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: 'IBM Plex Mono';
  font-style: normal;
  font-weight: 500;
  font-display: swap;
  src: url(assets/fonts/IBMPlexMono-500-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'IBM Plex Sans';
  font-style: normal;
  font-weight: 300;
  font-stretch: 100%;
  font-display: swap;
  src: url(assets/fonts/IBMPlexSans-300-latin-ext.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: 'IBM Plex Sans';
  font-style: normal;
  font-weight: 300;
  font-stretch: 100%;
  font-display: swap;
  src: url(assets/fonts/IBMPlexSans-300-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'IBM Plex Sans';
  font-style: normal;
  font-weight: 400;
  font-stretch: 100%;
  font-display: swap;
  src: url(assets/fonts/IBMPlexSans-400-latin-ext.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: 'IBM Plex Sans';
  font-style: normal;
  font-weight: 400;
  font-stretch: 100%;
  font-display: swap;
  src: url(assets/fonts/IBMPlexSans-400-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'IBM Plex Sans';
  font-style: normal;
  font-weight: 500;
  font-stretch: 100%;
  font-display: swap;
  src: url(assets/fonts/IBMPlexSans-500-latin-ext.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: 'IBM Plex Sans';
  font-style: normal;
  font-weight: 500;
  font-stretch: 100%;
  font-display: swap;
  src: url(assets/fonts/IBMPlexSans-500-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

@font-face {
  font-family: 'IBM Plex Sans';
  font-style: normal;
  font-weight: 600;
  font-stretch: 100%;
  font-display: swap;
  src: url(assets/fonts/IBMPlexSans-600-latin-ext.woff2) format('woff2');
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}

@font-face {
  font-family: 'IBM Plex Sans';
  font-style: normal;
  font-weight: 600;
  font-stretch: 100%;
  font-display: swap;
  src: url(assets/fonts/IBMPlexSans-600-latin.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

/* ============ URUS AI — light industrial concept ============
   Structure follows the reference homepage: full-bleed media hero, a filtered
   card rail, one oversized statement, hairline lists with index numbers, a
   dark band as punctuation, oversized CTA rows, sticky dock.
   Detailing is industrial: outline technical drawings, monospaced metadata,
   hairline rules, struck-through readings on conflicting values.

   Every text colour below is measured against its own ground. The greys that
   look right on paper do not survive on the dark band, so light and dark
   contexts carry separate accents rather than sharing one. */

:root {
  --paper: #fafaf8;
  --sheet: #ffffff;
  --dark: #131415;
  /* warm grey band for the findings rail; --rule is too close in value to
     read against it, so the band carries its own hairline.
     Six digits, not eight: this was #f1f0eefe, where the trailing fe is an
     alpha channel leaving the band 0.4% transparent. Invisible for as long as
     nothing sat behind it — then the pinned hero video did, and its headline
     ghosted through the section above. */
  --warm: #f1f0ee;
  --rule-w: #d9d6cd;

  /* on paper — ratios: 17.9 / 7.1 / 5.4 */
  --ink: #111213;
  --ink-2: #52565c;
  --ink-3: #63676d;
  --blue: #16447e;
  --red: #b03d18;

  /* on the dark band — ratios: 5.6 / 5.2 */
  --blue-l: #5b90d8;
  --red-l: #e0603a;

  --rule: #e3e3e0;
  --rule-d: rgba(255, 255, 255, 0.16);

  --sans: "IBM Plex Sans", system-ui, sans-serif;
  --mono: "IBM Plex Mono", ui-monospace, monospace;
  /* heavy condensed numerals for the ghost figures on the platform list */

  /* spacing scale — every gap on the page resolves to one of these */
  --s1: 6px;
  --s2: 10px;
  --s3: 14px;
  --s4: 20px;
  --s5: 30px;
  --s6: 44px;
  --s7: clamp(32px, 3.6vw, 56px);
  --s8: clamp(44px, 3vw, 78px);

  --pad: clamp(20px, 5vw, 76px);
  --nav-h: 68px;
  --dock-h: 62px;
  --tap: 44px;
}

*,
*::before,
*::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

html {
  scroll-behavior: smooth;
}

body {
  font-family: var(--sans);
  font-size: 16px;
  line-height: 1.55;
  color: var(--ink);
  background: var(--paper);
  -webkit-font-smoothing: antialiased;
  padding-bottom: var(--dock-h);
}

img {
  display: block;
  max-width: 100%;
}

a {
  color: inherit;
  text-decoration: none;
}

ol,
ul {
  list-style: none;
}

.sprite {
  position: absolute;
  width: 0;
  height: 0;
}

:where(a, button, [tabindex]):focus-visible {
  outline: 2px solid var(--blue);
  outline-offset: 3px;
}

/* ---------- one label system ----------
   these were eight near-identical declarations; differentiate labels by size
   and tracking, never by making them lighter than the contrast floor */
.kick,
.fc-kick,
.b-k,
.t-k,
.i-k,
.foot-k,
.s-no,
.chips span,
.hero-scroll,
.flow figcaption {
  font-family: var(--mono);
  font-size: 0.78rem;
  font-weight: 500;
  letter-spacing: 0.12em;
  text-transform: uppercase;
}

.kick,
.b-k,
.t-k,
.i-k,
.foot-k {
  color: var(--ink-3);
  margin-bottom: var(--s3);
}

/* the section label sits on a rule, as a drawing header would */
.kick {
  padding-bottom: var(--s3);
  border-bottom: 1px solid var(--rule);
  margin-bottom: var(--s5);
}

.sec-h {
  font-weight: 400;
  font-size: clamp(1.4rem, 2.6vw, 2.2rem);
  letter-spacing: -0.03em;
  margin-bottom: var(--s6);
}

/* ---------- nav ---------- */
.nav {
  position: sticky;
  top: 0;
  z-index: 60;
  min-height: var(--nav-h);
  display: flex;
  align-items: center;
  gap: var(--s5);
  padding: var(--s3) var(--pad);
  /* frosted glass: light enough that the footage moves behind it, opaque
     enough that full-strength ink clears 9:1 over the darkest frame */
  background: rgba(250, 250, 248, 0.66);
  backdrop-filter: blur(18px) saturate(150%);
  -webkit-backdrop-filter: blur(18px) saturate(150%);
  border-bottom: 1px solid rgba(17, 18, 19, 0.09);
  transition: box-shadow 0.35s, background 0.35s;
}

/* no blur support means no frosting, so the tint has to carry legibility alone */
@supports not ((backdrop-filter: blur(1px)) or (-webkit-backdrop-filter: blur(1px))) {
  .nav {
    background: rgba(250, 250, 248, 0.94);
  }
}

/* past the hero it lifts off the page very slightly, but stays glass */
.nav.solid {
  box-shadow: 0 1px 16px rgba(17, 18, 19, 0.07);
}

.nav-brand {
  display: flex;
  align-items: center;
  gap: var(--s2);
  font-weight: 600;
  font-size: 1.08rem;
  letter-spacing: -0.03em;
}

.nav-brand img {
  width: 27px;
  height: 24px;
  object-fit: contain;
}

.nav-brand b {
  font-weight: 600;
  color: var(--ink-3);
}

/* the accreditation mark sits beside the wordmark, separated by a hairline,
   and is deliberately not a link — clicking it should not navigate home */
.nav-cobrand {
  position: relative;
  display: flex;
  align-items: center;
  margin-right: auto;
  margin-left: var(--s3);
  padding-left: var(--s4);
}

.nav-cobrand::before {
  content: "";
  position: absolute;
  left: 0;
  top: 50%;
  transform: translateY(-50%);
  width: 1px;
  height: 24px;
  background: linear-gradient(180deg, transparent, var(--rule) 50%, transparent);
}

/* the accreditation mark is a stacked lockup (2:1), not the wide wordmark the
   15px height was set for — at that size the line under the monogram was an
   illegible smear. 26px gives it room and matches the URUS mark beside it. */
.nav-cobrand img {
  height: 26px;
  width: auto;
}

.nav-links {
  display: flex;
  gap: var(--s5);
  font-size: 0.9rem;
  color: var(--ink);
}

.nav-links a {
  display: inline-flex;
  align-items: center;
  min-height: var(--tap);
  transition: color 0.22s;
}

.nav-links a:hover {
  color: var(--blue);
}

.nav-burger {
  display: none;
  position: relative;
  width: var(--tap);
  height: var(--tap);
  border: 1px solid rgba(17, 18, 19, 0.16);
  background: transparent;
  cursor: pointer;
}

.nav-burger span {
  position: absolute;
  left: 13px;
  width: 18px;
  height: 1.5px;
  background: var(--ink);
  transition: transform 0.3s;
}

.nav-burger span:nth-child(1) {
  top: 18px;
}

.nav-burger span:nth-child(2) {
  top: 24px;
}

.nav-burger.on span:nth-child(1) {
  transform: translateY(3px) rotate(45deg);
}

.nav-burger.on span:nth-child(2) {
  transform: translateY(-3px) rotate(-45deg);
}

/* ---------- buttons ---------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: var(--tap);
  padding: var(--s2) var(--s5);
  font-size: 0.84rem;
  border: 1px solid var(--ink);
  border-radius: 2px;
  transition: background 0.25s, color 0.25s, border-color 0.25s;
}

.btn-solid {
  background: var(--ink);
  color: var(--paper);
}

.btn-solid:hover {
  background: var(--blue);
  border-color: var(--blue);
}

/* ---------- hero ---------- */
/* the hero is exactly one viewport tall and slides under the sticky bar; the
   offset comes from --nav-h rather than a measured constant */
.hero {
  position: relative;
  height: 100svh;
  min-height: 420px;
  margin-top: calc(var(--nav-h) * -1);
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  justify-content: center;
  padding: 0 var(--pad);
  overflow: hidden;
}

.hero-media {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* the engineer sits in the right third; bias the crop so he survives on
     narrower viewports rather than being cropped away */
  object-position: 62% center;
}

/* the plate is a bright image (median luminance 0.81), so the scrim is paper
   rather than black and the type is ink. weighted to the left where the copy
   sits, and clear by 84% so the engineer on the right stays crisp. measured:
   0.40 alone already gives ink 6.1:1 over the darkest pixel under the copy. */
.hero-veil {
  position: absolute;
  inset: 0;
  background:
    linear-gradient(100deg,
      rgba(250, 250, 248, 0.94) 0%,
      rgba(250, 250, 248, 0.8) 30%,
      rgba(250, 250, 248, 0.3) 58%,
      rgba(250, 250, 248, 0) 84%),
    linear-gradient(180deg, rgba(250, 250, 248, 0.5), rgba(250, 250, 248, 0) 26%);
}

.hero-title {
  position: relative;
  z-index: 2;
  font-weight: 300;
  font-size: clamp(1.9rem, 4vw, 3.7rem);
  line-height: 1.14;
  letter-spacing: -0.035em;
  text-align: left;
  max-width: 15ch;
  color: var(--ink);
}

/* each line masked, then slid up on load */
.ln {
  display: block;
  overflow: hidden;
}

.ln>span {
  display: block;
  transform: translateY(105%);
  animation: lineUp 1.05s cubic-bezier(0.16, 0.84, 0.24, 1) forwards;
}

.ln:nth-child(2)>span {
  animation-delay: 0.12s;
}

@keyframes lineUp {
  to {
    transform: none;
  }
}

.hero-scroll {
  position: absolute;
  bottom: var(--s6);
  left: var(--pad);
  z-index: 2;
  display: flex;
  align-items: center;
  gap: var(--s3);
  min-height: var(--tap);
  color: var(--ink-2);
}

.hero-scroll i {
  font-style: normal;
  animation: nudge 2.4s ease-in-out infinite;
}

@keyframes nudge {

  0%,
  100% {
    transform: translateY(0);
  }

  50% {
    transform: translateY(6px);
  }
}

/* ---------- section frame ---------- */
section {
  padding: var(--s8) var(--pad);
}

/* ---------- findings rail ---------- */
.rail {
  padding-left: 0;
  padding-right: 0;
  background: var(--warm);
}

.rail .kick {
  border-bottom-color: var(--rule-w);
}

.rail .arw {
  border-color: var(--rule-w);
}

.rail>.kick,
.rail-note {
  margin-left: var(--pad);
  margin-right: var(--pad);
}

.rail-head {
  display: flex;
  align-items: center;
  gap: var(--s4);
  padding: 0 var(--pad) var(--s5);
}

.tabs {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s1) var(--s5);
  margin-right: auto;
  font-size: 0.9rem;
}

.tab {
  display: inline-flex;
  align-items: center;
  min-height: var(--tap);
  border: none;
  background: none;
  padding: 0;
  font: inherit;
  color: var(--ink-2);
  cursor: pointer;
  border-bottom: 2px solid transparent;
  transition: color 0.22s, border-color 0.22s;
}

.tab:hover {
  color: var(--ink);
}

.tab.on {
  color: var(--ink);
  font-weight: 500;
  border-bottom-color: var(--ink);
}

.rail-ctrl {
  display: flex;
  gap: var(--s2);
  flex: none;
}

.arw {
  width: var(--tap);
  height: var(--tap);
  border: 1px solid var(--rule);
  background: var(--sheet);
  color: var(--ink);
  font-size: 0.95rem;
  cursor: pointer;
  transition: border-color 0.22s, opacity 0.22s;
}

.arw:hover:not(:disabled) {
  border-color: var(--ink);
}

.arw:disabled {
  opacity: 0.35;
  cursor: default;
}

.rail-track {
  display: flex;
  gap: var(--s4);
  padding: 4px var(--pad) var(--s2);
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  /* without this the snapport starts at the padding edge, so snapping the
     first card to "start" scrolls the left padding out of view and the card
     ends up flush against the page wall */
  scroll-padding-inline: var(--pad);
  scrollbar-width: none;
}

.rail-track::-webkit-scrollbar {
  display: none;
}

.rail-track.drag {
  cursor: grabbing;
  scroll-snap-type: none;
}

.fcard {
  flex: 0 0 clamp(270px, 30vw, 380px);
  scroll-snap-align: start;
  display: flex;
  flex-direction: column;
  padding: var(--s5);
  background: var(--sheet);
  color: var(--ink);
  /* a white sheet on the warm band has almost no edge of its own, so it
     carries the band's hairline — same treatment as .arw above */
  border: 1px solid var(--rule-w);
  border-top: 2px solid var(--blue);
}

.fcard.crit {
  border-top-color: var(--red);
}

.fcard.hide {
  display: none;
}

/* trailing spacer: some engines collapse padding-inline-end on an overflowing
   flex row, so the gap after the last card is made of a real box */
.rail-track::after {
  content: "";
  flex: 0 0 1px;
  margin-left: calc(var(--pad) - var(--s4));
}

.fc-kick {
  color: var(--ink-2);
  margin-bottom: var(--s3);
}

.fc-kick span {
  opacity: 0.5;
  margin: 0 4px;
}

.fcard h3 {
  font-size: 1.08rem;
  font-weight: 500;
  letter-spacing: -0.02em;
  line-height: 1.3;
  margin-bottom: var(--s4);
}

/* outline technical drawing, the reference's card motif */
.fc-dwg {
  width: 100%;
  height: 110px;
  margin-bottom: var(--s4);
  fill: none;
  /* no token: the drawing is furniture, not text, and wants to sit lighter
     than --ink-3 without disappearing into the sheet */
  stroke: rgba(17, 18, 19, 0.45);
  stroke-width: 1.4;
  stroke-linecap: square;
}

.fc-body {
  font-size: 0.94rem;
  line-height: 1.55;
  color: var(--ink-2);
  margin-bottom: var(--s4);
  flex: 1;
}

.fc-val {
  display: flex;
  align-items: center;
  gap: var(--s2);
  padding-top: var(--s3);
  border-top: 1px solid var(--rule);
  font-family: var(--mono);
  font-size: 0.8rem;
}

/* the rejected reading is still content, so it stays legible rather than
   being dimmed out of reach */
.fc-val s {
  color: var(--ink-3);
  text-decoration-color: var(--red);
}

.fc-val i {
  font-style: normal;
  color: var(--ink-3);
}

.fc-val b {
  font-weight: 500;
}

.rail-note {
  padding-top: var(--s5);
  max-width: 62ch;
  font-family: var(--mono);
  font-size: 0.72rem;
  line-height: 1.7;
  color: var(--ink-3);
}

/* ---------- clients marquee ----------
   sits directly under the hero as a quiet band of proof. three identical sets
   scroll as one track; shifting left by exactly one set lands on a copy, so
   the loop has no seam and needs no JS. */
.marquee {
  padding: 0;
  border-bottom: 1px solid var(--rule);
  background: var(--warm);
}

.mq-label {
  padding: var(--s4) var(--pad) 0;
  font-family: var(--mono);
  font-size: 0.78rem;
  font-weight: 500;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-3);
}

/* fades at both edges so marks enter and leave rather than popping */
.mq-view {
  overflow: hidden;
  padding: var(--s4) 0 var(--s5);
  -webkit-mask-image: linear-gradient(to right, transparent, #000 90px, #000 calc(100% - 90px), transparent);
  mask-image: linear-gradient(to right, transparent, #000 90px, #000 calc(100% - 90px), transparent);
}

.mq-track {
  display: flex;
  width: max-content;
  animation: mqScroll 46s linear infinite;
}

@keyframes mqScroll {
  from {
    transform: translateX(0);
  }

  to {
    transform: translateX(calc(-100% / 3));
  }
}

.mq-set {
  display: flex;
  flex-shrink: 0;
}

.mq-cell {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0 clamp(30px, 4.6vw, 76px);
}

/* both axes capped so a tall mark and a wide wordmark land at a similar
   optical size, whatever their own proportions */
.mq-cell img {
  max-height: clamp(26px, 2.8vw, 36px);
  max-width: clamp(104px, 11vw, 148px);
  width: auto;
  height: auto;
  filter: grayscale(1);
  opacity: 0.66;
  transition: filter 0.3s, opacity 0.3s;
}

.mq-cell:hover img {
  filter: grayscale(0);
  opacity: 1;
}

@media (prefers-reduced-motion: reduce) {
  .mq-track {
    animation: none;
  }
}

/* ---------- oversized statement ---------- */
/* the statement is the one breathing moment, so it gets more air than the
   others — but only about 1.3x, not the 2x it was carrying */
.stmt {
  text-align: center;
  padding-top: clamp(56px, 6vw, 102px);
  padding-bottom: clamp(56px, 6vw, 102px);
}

.stmt h2 {
  max-width: 100%;
  margin: 0 auto;
  font-weight: 400;
  /* was clamp(5rem, 4vw, 3.4rem) — the minimum is larger than the maximum, so
     clamp returned the minimum at every width: a fixed 80px that overflowed a
     phone. Reordered so 80px still holds down to about 816px and it scales
     below that instead of running off the screen. */
  font-size: clamp(2.2rem, 9.8vw, 5rem);
  line-height: 1.16;
  letter-spacing: -0.035em;
}

/* one clause held back — at --ink-3 it still clears the contrast floor */
.stmt em {
  font-style: normal;
  color: var(--ink-3);
}

.stmt-sub {
  max-width: 62ch;
  margin: var(--s5) auto 0;
  color: var(--ink-2);
}

.chips {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s2);
  margin-top: var(--s5);
}

.chips span {
  padding: var(--s1) var(--s3);
  border: 1px solid var(--rule);
  color: var(--ink-2);
}

/* ---------- dark band ---------- */
.band {
  background: var(--dark);
  color: #fff;
}

.band .kick {
  color: rgba(255, 255, 255, 0.72);
  border-bottom-color: var(--rule-d);
}

.band h2 {
  max-width: 20ch;
  margin-bottom: var(--s6);
  font-weight: 400;
  font-size: clamp(1.5rem, 3vw, 2.5rem);
  line-height: 1.18;
  letter-spacing: -0.03em;
}

.band-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 1px;
  background: var(--rule-d);
  border: 1px solid var(--rule-d);
}

.bcell {
  padding: var(--s5) var(--s4);
  background: var(--dark);
}

.b-k {
  color: var(--red-l);
}

.b-t {
  font-size: 1.02rem;
  font-weight: 500;
  letter-spacing: -0.02em;
  margin-bottom: var(--s2);
}

.b-d {
  font-size: 0.86rem;
  line-height: 1.55;
  color: rgba(255, 255, 255, 0.72);
}

/* ---------- process ----------
   a process line rather than five boxes: nodes sit on a spine, the accent runs
   along it as the section arrives, and each node lights as the line reaches it */
.steps {
  position: relative;
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: clamp(16px, 2.2vw, 36px);
}

/* .rise is used here only as an in-view flag; the children carry the fade */
.steps.rise {
  opacity: 1;
  transform: none;
  transition: none;
}

.steps::before,
.steps::after {
  content: "";
  position: absolute;
  top: 9px;
  left: 0;
  height: 1px;
}

.steps::before {
  right: 0;
  background: var(--rule);
}

.steps::after {
  width: 0;
  background: var(--blue);
  transition: width 1.6s cubic-bezier(0.4, 0, 0.2, 1) 0.15s;
}

.steps.in::after {
  width: 100%;
}

.step {
  position: relative;
  padding: 44px var(--s4) 0 0;
}

/* the node */
.step::before {
  content: "";
  position: absolute;
  top: 4px;
  left: 0;
  width: 11px;
  height: 11px;
  border-radius: 50%;
  background: var(--paper);
  border: 2px solid var(--rule);
  transition: border-color 0.4s, background 0.4s;
}

/* flow arrow riding the spine, pointing at the next node */
.step:not(:last-child)::after {
  content: "";
  position: absolute;
  top: 6px;
  left: 52%;
  width: 0;
  height: 0;
  border-top: 3.5px solid transparent;
  border-bottom: 3.5px solid transparent;
  border-left: 6px solid var(--rule);
  transition: border-left-color 0.4s;
}

/* nodes activate in sequence, roughly tracking the line as it draws */
.steps.in .step::before {
  border-color: var(--blue);
  background: var(--blue);
}

.steps.in .step:not(:last-child)::after {
  border-left-color: var(--blue);
}

.step:nth-child(1)::before {
  transition-delay: 0.2s;
}

.step:nth-child(2)::before,
.step:nth-child(1)::after {
  transition-delay: 0.5s;
}

.step:nth-child(3)::before,
.step:nth-child(2)::after {
  transition-delay: 0.8s;
}

.step:nth-child(4)::before,
.step:nth-child(3)::after {
  transition-delay: 1.1s;
}

.step:nth-child(5)::before,
.step:nth-child(4)::after {
  transition-delay: 1.4s;
}

.s-no {
  display: block;
  color: var(--blue);
  margin-bottom: var(--s2);
}

.step h3 {
  font-size: 1.04rem;
  font-weight: 500;
  letter-spacing: -0.02em;
  margin-bottom: var(--s2);
}

.step p {
  font-size: 0.94rem;
  line-height: 1.55;
  color: var(--ink-2);
}

/* ---------- trust ---------- */
.tgrid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--s7);
}

.t-v {
  font-size: 1.04rem;
  font-weight: 500;
  letter-spacing: -0.02em;
  margin-bottom: var(--s2);
}

.t-d {
  font-size: 0.93rem;
  line-height: 1.55;
  color: var(--ink-2);
}

.isnt {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--s6);
  margin-top: var(--s6);
  padding-top: var(--s5);
  border-top: 1px solid var(--rule);
}

.isnt li {
  position: relative;
  padding: var(--s2) 0 var(--s2) var(--s6);
  font-size: 0.94rem;
  border-bottom: 1px solid var(--rule);
}

/* tick for what it is */
.isnt li::before {
  content: "";
  position: absolute;
  left: var(--s2);
  top: 1.15em;
  width: 10px;
  height: 6px;
  border-left: 1.8px solid var(--blue);
  border-bottom: 1.8px solid var(--blue);
  transform: rotate(-45deg);
}

/* cross for what it is not */
.isnt .no li {
  color: var(--ink-2);
}

.isnt .no li::before {
  top: 1.2em;
  width: 11px;
  height: 11px;
  border: none;
  transform: rotate(45deg);
  background:
    linear-gradient(var(--red), var(--red)) center / 11px 1.8px no-repeat,
    linear-gradient(var(--red), var(--red)) center / 1.8px 11px no-repeat;
}

/* ---------- proof ---------- */
/* ---------- proof ----------
   An oversized headline figure on the left with the quote it came from
   underneath, and a card cluster on the right: one wide card carrying the
   metric that has a before-and-after, then two square ones. */
.pf {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.05fr);
  gap: clamp(32px, 5vw, 78px);
  align-items: start;
}

.pf-k {
  font-family: var(--mono);
  font-size: 0.78rem;
  font-weight: 500;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin-bottom: var(--s4);
}

.pf-big {
  font-size: clamp(3.6rem, 10vw, 8.2rem);
  font-weight: 400;
  line-height: 0.84;
  letter-spacing: -0.055em;
}

.pf-chips {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s2);
  margin-top: var(--s5);
}

.pf-chips span {
  font-family: var(--mono);
  font-size: 0.72rem;
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-2);
  padding: 5px var(--s3);
  border-radius: 100px;
  background: var(--warm);
}

.pf-quote {
  max-width: 44ch;
  margin-top: var(--s6);
}

.pf-quote p {
  font-size: 1rem;
  line-height: 1.6;
  color: var(--ink-2);
}

.pf-quote footer {
  margin-top: var(--s3);
  font-family: var(--mono);
  font-size: 0.72rem;
  font-weight: 500;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-3);
}

/* ---------- the card cluster ---------- */
.pf-cards {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--s3);
}

.pf-card {
  position: relative;
  display: flex;
  flex-direction: column;
  padding: var(--s5);
  border-radius: 14px;
  background: var(--sheet);
  border: 1px solid var(--rule);
}

/* the one metric with a before and an after gets the full width and the
   gradient, so the pair reads as a distance travelled */
.pf-wide {
  grid-column: 1 / -1;
  background:
    linear-gradient(90deg,
      rgba(22, 68, 126, 0.19) 0%,
      rgba(22, 68, 126, 0.06) 52%,
      rgba(22, 68, 126, 0) 78%),
    var(--sheet);
}

.pf-ck {
  font-family: var(--mono);
  font-size: 0.78rem;
  font-weight: 500;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-2);
}

/* the reference point sits opposite its metric, on the same line */
.pf-was {
  position: absolute;
  top: var(--s5);
  right: var(--s5);
  font-family: var(--mono);
  font-size: 0.78rem;
  font-weight: 500;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-3);
}

.pf-ico {
  width: 20px;
  height: 20px;
  margin-top: var(--s5);
  fill: none;
  stroke: var(--ink-3);
  stroke-width: 1.7;
  stroke-linecap: round;
  stroke-linejoin: round;
}

.pf-cv {
  font-size: clamp(1.6rem, 3vw, 2.5rem);
  font-weight: 400;
  line-height: 1.05;
  letter-spacing: -0.04em;
  margin-top: var(--s5);
}

.pf-wide .pf-cv {
  margin-top: var(--s4);
}

.pf-cd {
  margin-top: var(--s2);
  font-family: var(--mono);
  font-size: 0.7rem;
  font-weight: 500;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: var(--ink-3);
}

@media (max-width: 900px) {
  .pf {
    grid-template-columns: 1fr;
    gap: var(--s7);
  }
}

@media (max-width: 520px) {
  .pf-cards {
    grid-template-columns: 1fr;
  }

  .pf-wide {
    grid-column: auto;
  }
}

.logos {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: clamp(30px, 4.6vw, 72px);
  margin-top: var(--s6);
  padding-top: var(--s6);
  border-top: 1px solid var(--rule);
}

/* both axes capped so a tall mark and a wide wordmark land at a similar
   optical size, whatever their own proportions */
.logos img {
  max-height: clamp(32px, 3.6vw, 46px);
  max-width: clamp(120px, 13vw, 178px);
  width: auto;
  height: auto;
  filter: grayscale(1);
  opacity: 0.72;
  transition: filter 0.3s, opacity 0.3s;
}

.logos img:hover {
  filter: grayscale(0);
  opacity: 1;
}

/* ---------- oversized CTA rows ---------- */
.bigcta {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s4);
  padding: var(--s7) var(--pad);
  border-top: 1px solid var(--rule);
  font-weight: 400;
  font-size: clamp(1.8rem, 4.4vw, 3.4rem);
  letter-spacing: -0.04em;
  transition: background 0.3s, color 0.3s;
}

.bigcta.muted {
  color: var(--ink-2);
}

.bigcta i {
  font-style: normal;
  font-size: 0.7em;
  transition: transform 0.35s cubic-bezier(0.2, 0.7, 0.2, 1);
}

.bigcta:hover {
  background: var(--ink);
  color: var(--paper);
}

.bigcta:hover i {
  transform: translateX(14px);
}

/* ---------- footer ---------- */
.foot {
  padding: var(--s8) var(--pad);
  border-top: 1px solid var(--rule);
}

.foot-grid {
  display: grid;
  grid-template-columns: 1.6fr 1fr 1fr 1fr;
  gap: var(--s7);
}

.foot-co p {
  font-size: 0.85rem;
  color: var(--ink-2);
  margin-bottom: var(--s3);
}

.foot-addr {
  line-height: 1.65;
}

.pills {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s2);
  margin-top: var(--s4);
}

.pills a {
  display: inline-flex;
  align-items: center;
  min-height: var(--tap);
  padding: 0 var(--s4);
  border: 1px solid var(--rule);
  border-radius: 99px;
  font-family: var(--mono);
  font-size: 0.68rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-2);
  transition: border-color 0.25s, color 0.25s;
}

.pills a:hover {
  border-color: var(--ink);
  color: var(--ink);
}

.foot-col a {
  display: flex;
  align-items: center;
  min-height: 36px;
  font-size: 0.88rem;
  color: var(--ink-2);
  transition: color 0.22s;
}

.foot-col a:hover {
  color: var(--ink);
}

/* ---------- sticky dock ---------- */
.dock {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 70;
  min-height: var(--dock-h);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--s3);
  padding: var(--s1) var(--pad);
  background: rgba(250, 250, 248, 0.94);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  border-top: 1px solid var(--rule);
  transform: translateY(100%);
  transition: transform 0.4s cubic-bezier(0.2, 0.7, 0.2, 1);
}

.dock.up {
  transform: none;
}

.dock-brand {
  display: flex;
  align-items: center;
  gap: var(--s2);
  font-weight: 600;
  font-size: 0.96rem;
  letter-spacing: -0.03em;
}

.dock-brand img {
  width: 22px;
  height: 20px;
  object-fit: contain;
}

.dock-brand b {
  font-weight: 600;
  color: var(--ink-3);
}

.dock .btn {
  min-height: 38px;
  padding: 0 var(--s4);
  font-size: 0.78rem;
}

/* ---------- scroll-in ---------- */
.rise {
  opacity: 0;
  transform: translateY(20px);
  transition: opacity 0.7s ease, transform 0.7s cubic-bezier(0.16, 0.84, 0.24, 1);
  transition-delay: var(--d, 0s);
}

.rise.in {
  opacity: 1;
  transform: none;
}

/* ---------- responsive ---------- */
@media (max-width: 1080px) {

  .band-grid,
  .tgrid {
    grid-template-columns: 1fr 1fr;
  }

  .steps {
    grid-template-columns: repeat(3, 1fr);
    row-gap: var(--s6);
  }

  /* the spine only spans the first row once the grid wraps */
  .steps::before,
  .steps::after {
    display: none;
  }

  .step::before {
    background: var(--blue);
    border-color: var(--blue);
  }

  .step:not(:last-child)::after {
    display: none;
  }
}

@media (max-width: 980px) {

  .foot-grid {
    grid-template-columns: 1fr 1fr;
  }
}

@media (max-width: 620px) {
  .nav-cobrand {
    display: none;
  }
}

@media (max-width: 760px) {
  .hero-media {
    object-position: 58% center;
  }

  .hero-veil {
    background: linear-gradient(180deg,
        rgba(250, 250, 248, 0.9),
        rgba(250, 250, 248, 0.82) 55%,
        rgba(250, 250, 248, 0.92));
  }

  .hero-title {
    max-width: none;
  }

  .nav-links {
    display: none;
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    flex-direction: column;
    gap: 0;
    background: var(--sheet);
    border-bottom: 1px solid var(--rule);
  }

  .nav-links.on {
    display: flex;
  }

  .nav-links a {
    padding: 0 var(--pad);
    border-bottom: 1px solid var(--rule);
  }

  .nav-burger {
    display: block;
  }

  .rail-ctrl {
    display: none;
  }

  .fcard {
    flex-basis: 78vw;
  }

  .band-grid,
  .tgrid,
  .isnt,
  .foot-grid {
    grid-template-columns: 1fr;
  }

  .band-grid {
    gap: 1px;
  }

  /* the line turns vertical and runs down the left margin */
  .steps {
    grid-template-columns: 1fr;
    row-gap: 0;
    padding-left: 30px;
  }

  .steps::before,
  .steps::after {
    display: block;
    top: 6px;
    bottom: 10px;
    left: 7px;
    width: 1px;
    height: auto;
    right: auto;
  }

  .steps::after {
    height: 0;
    bottom: auto;
    transition: height 1.6s cubic-bezier(0.4, 0, 0.2, 1) 0.15s;
  }

  .steps.in::after {
    width: 1px;
    height: calc(100% - 16px);
  }

  .step {
    padding: 0 0 var(--s6) 0;
  }

  .step::before {
    top: 2px;
    left: -30px;
  }

  .step:not(:last-child)::after {
    display: none;
  }

  .isnt {
    gap: var(--s6);
  }
}

@media (prefers-reduced-motion: reduce) {
  html {
    scroll-behavior: auto;
  }

  .rise {
    opacity: 1;
    transform: none;
    transition: none;
  }

  .ln>span {
    transform: none;
    animation: none;
  }

  .hero-scroll i {
    animation: none;
  }

  .dock {
    transform: none;
  }
}

/* ============ Subpages ============ */

/* ---------- subpage hero ---------- */
/* no footage here, so the warm band carries the top of the page instead */
/* every subpage hero — plain warm band, no plate */
.phero {
  padding-top: calc(var(--nav-h) + var(--s7));
  padding-bottom: var(--s8);
  background: var(--warm);
}

/* ---------- hero plates ----------
   A hero whose height comes from its artwork's own proportions, so the plate
   is shown whole instead of cropped to whatever height the copy needed. The
   mechanism is shared; each page supplies its own numbers below, because the
   two plates are different shapes and sit on different grounds.

   contain, not cover: cover crops the instant the box is not the plate's
   exact ratio, which is what happens below each page's breakpoint. */
.phero-media {
  position: relative;
  aspect-ratio: var(--plate-w) / var(--plate-h);
  display: flex;
  flex-direction: column;
  justify-content: center;
  /* the plate's own ground, so the letterbox at narrow widths is invisible
     rather than a band of --warm above and below it */
  background-color: var(--plate-ground);
  background-repeat: no-repeat;
  background-position: center;
  background-size: contain;
}

/* The hero's top padding carries the nav's height, so it is far deeper than
   the bottom; centring inside that box drops the copy below the section's true
   middle. --lift rebalances it. It is applied per hero rather than here,
   because it is only wanted where that hero's ratio governs the height — and
   the two cross over at different widths. */
.phero-media {
  --lift: clamp(40px, 9vw, 136px);
}

/* ---------- engineering-review: 1772x888, scene right, copy centred ----------
   The copy is centred, so it does not sit in the plate's clear left side — it
   lands on the scene. The veil therefore runs down the page rather than across
   it: strong through the band the text occupies, clear top and bottom so the
   drawings and the plant still read. 0.88 was measured — the darkest plate
   pixel under the copy is about #9e9e9e, which needs 0.75 to clear AA. */
.phero-plate {
  /* the plate is now a 1280x720 video, so the hero takes 16:9 rather than the
     still's 2:1 — same principle, shown whole rather than cropped */
  --plate-w: 1280;
  --plate-h: 720;
  --plate-ground: #faf8f4;
  align-items: center;
  text-align: center;
}

/* A video cannot be a background, so the layering is explicit: the plate sits
   behind, the veil over it, the copy above both. Both layers are absolutely
   positioned so they stay out of the flex flow that centres the copy. */
.phero-vid,
.phero-veil {
  position: absolute;
  inset: 0;
}

/* cover, not contain: once max-height clamps the hero the box is wider than
   the footage's 16:9, and contain would letterbox it inside its own section.
   This is atmospheric footage behind copy rather than a diagram to be read,
   so filling the frame matters more than showing every pixel of it. */
.phero-vid {
  width: 100%;
  height: 100%;
  object-fit: cover;
  z-index: 0;
}

/* the same veil the still carried, now its own layer: strong through the band
   the copy occupies, clear top and bottom so the plate still reads */
.phero-veil {
  z-index: 1;
  background: linear-gradient(to bottom, rgb(250 248 244 / 0%) 0%, rgb(250 248 244 / 74%) 27%, rgb(250 248 244 / 45%) 75%, rgba(250, 248, 244, 0.18) 100%)
}

.phero-plate h1,
.phero-plate .phero-sub {
  position: relative;
  z-index: 2;
}

.phero-plate h1 {
  max-width: 24ch;
  margin-inline: auto;
}

.phero-plate .phero-sub {
  max-width: 64ch;
  margin-inline: auto;
}

/* Measured: the copy needs 397px at 820px wide, where the ratio still gives
   403px — but by 760px it needs 388px and the ratio gives only 373px. Below
   that crossover the ratio is dropped and the copy sets the height; contain
   keeps the plate whole, letterboxed against its own ground, never cut. */
/* Re-measured for 16:9, which is a taller box than the still's 2:1 and so
   holds the copy much further down: it fits at 640px (346 needed, 360 given)
   and only overruns by 560px. The lift needs more slack than that — at 900px
   the ratio has 69px spare and the lift wants 81 — so it stops higher. */
@media (min-width: 951px) {
  .phero-plate {
    padding-bottom: calc(var(--s8) + var(--lift));
  }
}

@media (max-width: 600px) {
  .phero-plate {
    aspect-ratio: auto;
  }
}

/* narrow enough that the copy runs the full width, so the veil carries all
   the way across instead of clearing only the middle band */
@media (max-width: 860px) {
  .phero-veil {
    background: linear-gradient(to bottom,
        rgba(250, 248, 244, 0.5) 0%,
        rgba(250, 248, 244, 0.93) 22%,
        rgba(250, 248, 244, 0.93) 80%,
        rgba(250, 248, 244, 0.5) 100%);
  }
}

/* ---------- how-it-works: 1832x859, scene right, copy left ----------
   This plate keeps its copy left-aligned, and its artwork does not begin until
   47% across — so the scrim clears the left rather than a middle band. Its
   ground is #f1eeeb, warmer and a shade darker than the other plate's. */
.phero-flow {
  --plate-w: 1832;
  --plate-h: 859;
  --plate-ground: #f1eeeb;
  background-image:
    linear-gradient(to right,
      rgba(241, 238, 235, 0.97) 0%,
      rgba(241, 238, 235, 0.94) 46%,
      rgba(241, 238, 235, 0.6) 62%,
      rgba(241, 238, 235, 0) 80%),
    url("assets/how-it-works-bg.webp");
}

/* The shared 62ch sub-line runs past the plate's clear left side at middling
   widths — measured 2.62:1 at 1000px, under the floor. Holding it to 48ch
   keeps it inside the clear zone at every width the plate governs, which is a
   better fix than washing more of the artwork out to cover it. */
.phero-flow .phero-sub {
  max-width: 48ch;
}

/* Two different limits on this plate, measured separately.

   The lift only fits while the ratio has room for it: at 1180px the copy plus
   lift needs 539px and the ratio gives 546px — seven to spare. Below that the
   lift no longer fits, so it stops.

   The ratio itself survives much further down once the lift is off: the copy
   alone needs 392px at 880px where the ratio gives 406px, and only overruns by
   840px (388 vs 387). So the ratio governs to about 860px. */
@media (min-width: 1181px) {
  .phero-flow {
    padding-bottom: calc(var(--s8) + var(--lift));
  }
}

@media (max-width: 860px) {
  .phero-flow {
    aspect-ratio: auto;
  }
}

@media (max-width: 860px) {
  .phero-flow {
    background-image:
      linear-gradient(to right,
        rgba(241, 238, 235, 0.97) 0%,
        rgba(241, 238, 235, 0.94) 100%),
      url("assets/how-it-works-bg.webp");
  }
}

/* the hero label carries a whole page rather than a section, and at the shared
   0.66rem it was undersized against a display-scale h1. Scoped to .phero so
   the five subpage heroes stay consistent with each other and the section
   labels elsewhere keep the smaller size. */
.phero .kick {
  font-size: clamp(0.86rem, 0.62vw + 0.7rem, 1rem);
  border-bottom-color: var(--rule-w);
}

.phero h1 {
  max-width: 19ch;
  font-weight: 400;
  font-size: clamp(2rem, 4.4vw, 3.6rem);
  line-height: 1.08;
  letter-spacing: -0.04em;
}

.phero-sub {
  max-width: 62ch;
  margin-top: var(--s4);
  font-size: clamp(1rem, 0.4vw + 0.9rem, 1.14rem);
  color: var(--ink);
}

/* ---------- generic section ---------- */
.sec-lead {
  max-width: 64ch;
  margin-top: calc(var(--s6) * -1 + var(--s2));
  margin-bottom: var(--s6);
  font-size: clamp(0.98rem, 0.3vw + 0.9rem, 1.1rem);
  color: var(--ink-2);
}

.sec-note {
  max-width: 68ch;
  margin-top: var(--s6);
  padding-top: var(--s4);
  border-top: 1px solid var(--rule);
  font-size: 0.9rem;
  color: var(--ink-2);
}

.anon {
  max-width: 72ch;
  padding: var(--s4) var(--s5);
  border-left: 2px solid var(--blue);
  background: var(--warm);
  font-family: var(--mono);
  font-size: 0.74rem;
  line-height: 1.75;
  color: var(--ink-2);
}

.cap-lead {
  max-width: 62ch;
  color: var(--ink-2);
  margin-bottom: var(--s4);
}

.cap-list li {
  padding: var(--s2) 0;
  border-top: 1px solid var(--rule);
  font-size: 0.99rem;
  color: var(--ink-2);
}

.cap-list b {
  font-weight: 500;
  color: var(--ink);
}

.cap-note {
  margin-top: var(--s4);
  padding-top: var(--s3);
  border-top: 1px solid var(--rule);
  font-family: var(--mono);
  font-size: 0.74rem;
  line-height: 1.7;
  color: var(--ink-3);
}

/* ---------- three-step chain ---------- */
.chain {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--s7);
}

.chain-item {
  position: relative;
}

/* an arrow between stages, for the chain that describes a sequence */
.chain-flow .chain-item:not(:last-child)::after {
  content: "";
  position: absolute;
  top: 10px;
  right: calc(var(--s7) / -2 - 4px);
  width: 0;
  height: 0;
  border-top: 4px solid transparent;
  border-bottom: 4px solid transparent;
  border-left: 7px solid var(--red);
}

.chain-k {
  display: block;
  font-family: var(--mono);
  font-size: 0.78rem;
  font-weight: 500;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--blue);
  margin-bottom: var(--s3);
}

/* step artwork above each description. The three PNGs are transparent line
   art with unequal frames (1.5, 1.5 and 2.26 wide) and unequal ink inside
   those frames, so they are dropped into one shared box and contained rather
   than sized individually — otherwise the three h3s below them stop aligning
   across the row. 16/9 is the ratio that costs the two portrait-ish frames
   least while still giving the wide third one room. */
.chain-fig {
  width: 100%;
  aspect-ratio: 16 / 9;
  margin-bottom: var(--s4);
}

.chain-fig img {
  width: 100%;
  height: 100%;
  object-fit: contain;
}

.chain-item h3 {
  font-size: 1.14rem;
  font-weight: 500;
  letter-spacing: -0.02em;
  margin-bottom: var(--s3);
}

.chain-item li {
  padding: var(--s2) 0;
  border-top: 1px solid var(--rule);
  font-size: 0.9rem;
  color: var(--ink-2);
}

/* ---------- product naming ----------
   Each capability carries a short line above its description. It sits between
   the name and the body copy in both places the capabilities appear, so it is
   set once here and reused: heavier than the body, lighter than the heading,
   and always on --ink so it reads as a claim rather than as more prose. */
.acc-tag,
.cap-tag {
  font-weight: 500;
  color: var(--ink);
  letter-spacing: -0.01em;
}

.acc-tag {
  font-size: 1.02rem;
  line-height: 1.45;
  max-width: 52ch;
  padding: 0 var(--s5);
  margin-bottom: var(--s3);
}

.ac-dark .acc-tag {
  color: var(--paper);
}

.cap-tag {
  font-size: 1.14rem;
  line-height: 1.4;
  margin-bottom: var(--s3);
  text-wrap: balance;
}

/* the company line. Mono and letter-spaced like the section kickers, so it
   reads as a signature rather than as another sentence of body copy. */
.plat-tagline {
  font-family: var(--mono);
  font-size: clamp(0.82rem, 0.5vw + 0.7rem, 0.95rem);
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--blue);
  margin-bottom: var(--s4);
}

.foot-tag {
  font-family: var(--mono);
  font-size: 0.78rem;
  font-weight: 500;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink) !important;
  margin-bottom: var(--s4) !important;
}

/* ---------- product demo ---------- */
/* The clip is 1836x1080 and the frame carries that ratio, so the box is the
   right height before a single byte of video arrives — the section below it
   never moves. object-fit: cover rather than contain so a re-export at a
   different ratio crops instead of letterboxing onto white. */
.demo-frame {
  max-width: 1080px;
  margin: 0 auto;
  aspect-ratio: 1836 / 1080;
  border: 1px solid var(--rule);
  background: var(--sheet);
  overflow: hidden;
}

.demo-vid {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

/* ---------- comparison strip ---------- */
.cmp {
  display: grid;
  grid-template-columns: 1fr 1fr;
  border: 1px solid var(--rule);
}

.cmp-cell {
  padding: var(--s6) var(--s5);
}

.cmp-cell:first-child {
  border-right: 1px solid var(--rule);
}

.cmp-cell.new {
  background: var(--warm);
}

.cmp-k {
  font-family: var(--mono);
  font-size: 0.78rem;
  font-weight: 500;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin-bottom: var(--s3);
}

.cmp-v {
  font-size: clamp(1.9rem, 3.6vw, 3rem);
  font-weight: 400;
  letter-spacing: -0.04em;
  line-height: 1;
  margin-bottom: var(--s2);
}

.cmp-v.old {
  color: var(--ink-3);
  text-decoration: line-through;
  text-decoration-color: var(--red);
  text-decoration-thickness: 2px;
}

.cmp-d {
  font-size: 0.88rem;
  color: var(--ink-2);
}

/* ---------- anatomy of a finding ---------- */
.anat {
  max-width: 760px;
  margin-bottom: var(--s7);
  border: 1px solid var(--rule);
  background: var(--sheet);
}

.anat-head,
.anat-foot {
  padding: var(--s3) var(--s5);
  font-family: var(--mono);
  font-size: 0.78rem;
  font-weight: 500;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-3);
}

.anat-head {
  border-bottom: 1px solid var(--rule);
}

.anat-foot {
  border-top: 1px solid var(--rule);
  color: var(--blue);
}

.anat-list li {
  display: flex;
  gap: var(--s4);
  padding: var(--s3) var(--s5);
  border-bottom: 1px solid var(--rule);
  font-size: 0.94rem;
}

.anat-list li:last-child {
  border-bottom: none;
}

.anat-list span {
  flex: none;
  font-family: var(--mono);
  font-size: 0.7rem;
  color: var(--blue);
  padding-top: 3px;
}

/* ---------- use case register ---------- */
/* ---------- findings, as a folding stack ----------
   Each finding is sticky at the top, so the one below rises and settles onto
   the one above rather than scrolling past it. The panels must be opaque for
   that to read — the hairline on top of each is what you actually see as the
   seam between two stacked pages. */
.fold {
  /* the number column, the finding, and its reasoning */
  --fold-cols: clamp(64px, 7vw, 104px) minmax(0, 1.15fr) minmax(0, 1fr);
}

.fold-panel {
  position: sticky;
  top: var(--nav-h);
}

/* the transform lives on the inner box: transforming the sticky element
   itself makes it a containing block and some engines then drop the stick */
.fold-inner {
  display: grid;
  grid-template-columns: var(--fold-cols);
  gap: clamp(20px, 3vw, 52px);
  align-items: start;
  min-height: 62vh;
  padding: var(--s7) 0 var(--s8);
  background: var(--paper);
  border-top: 1px solid var(--rule);
  transform-origin: top center;
  transform: var(--fx, none);
  will-change: transform;
}

/* the dim goes on the content, never on .fold-inner itself: that box is what
   hides the panel underneath, and fading it makes the whole stack show
   through the page currently being read */
.fold-inner>* {
  opacity: var(--fo, 1);
}

.fold-no {
  font-size: clamp(2.2rem, 4.6vw, 4rem);
  font-weight: 600;
  line-height: 0.9;
  letter-spacing: -0.05em;
  color: var(--ink);
}

.fold-head h2,
.fold-head h3 {
  font-weight: 400;
  font-size: clamp(1.7rem, 4vw, 3.1rem);
  line-height: 1.03;
  letter-spacing: -0.045em;
  text-wrap: balance;
}

/* the document pair, bracketed like the annotation on a drawing */
.fold-docs {
  margin-top: var(--s5);
  font-family: var(--mono);
  font-size: 0.78rem;
  font-weight: 500;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-3);
}

.fold-detail {
  padding-top: var(--s2);
}

.fold-row+.fold-row {
  margin-top: var(--s5);
}

.fold-rk {
  display: block;
  font-family: var(--mono);
  font-size: 0.78rem;
  font-weight: 500;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin-bottom: var(--s2);
}

.fold-row p {
  font-size: 0.99rem;
  line-height: 1.6;
  color: var(--ink-2);
  max-width: 46ch;
}

@media (max-width: 860px) {
  .fold-inner {
    grid-template-columns: clamp(48px, 12vw, 72px) minmax(0, 1fr);
    row-gap: var(--s5);
    min-height: 0;
  }

  /* the reasoning drops under the finding rather than beside it */
  .fold-detail {
    grid-column: 2;
  }
}

/* no fold, no stack: the findings simply read as a list */
@media (prefers-reduced-motion: reduce) {
  .fold-panel {
    position: static;
  }

  .fold-inner {
    transform: none;
    opacity: 1;
  }
}


/* ---------- flow chips ---------- */
.flowchips {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--s2);
  margin-bottom: var(--s7);
}

.flowchips span {
  padding: var(--s2) var(--s4);
  border: 1px solid var(--rule);
  font-family: var(--mono);
  font-size: 0.68rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-2);
}

.flowchips i {
  font-style: normal;
  color: var(--blue);
  padding: 0 var(--s1);
}

.flowchips .out {
  border-color: var(--blue);
  background: rgba(22, 68, 126, 0.06);
  color: var(--blue);
}

/* ---------- partner cards ---------- */
.pcards {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1px;
  background: var(--rule);
  border: 1px solid var(--rule);
}

.pcard {
  padding: var(--s5) var(--s4);
  background: var(--paper);
}

.pc-name {
  font-size: 1.06rem;
  font-weight: 500;
  letter-spacing: -0.02em;
  margin-bottom: var(--s1);
}

.pc-note {
  font-size: 0.86rem;
  color: var(--ink-2);
}

/* ---------- team ---------- */
/* ---------- the team ----------
   Portraits with the name plate floating over the foot of the shot. Three
   people fit across at desktop, so the rail only scrolls — and the arrows
   only appear — once the viewport is too narrow to hold them. */
.team-head {
  display: flex;
  justify-content: flex-end;
  margin-bottom: var(--s5);
}

.team-ctrl {
  display: flex;
  gap: var(--s2);
}

/* hidden until the JS finds the rail actually overflows, so the controls are
   never present with nothing to control */
.team-ctrl[hidden] {
  display: none;
}

.team {
  display: grid;
  grid-auto-flow: column;
  grid-auto-columns: minmax(0, 1fr);
  gap: var(--s5);
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-padding-inline: 0;
  scrollbar-width: none;
}

.team::-webkit-scrollbar {
  display: none;
}

.person {
  scroll-snap-align: start;
}

/* the shot is the positioning context for the plate */
.person-shot {
  position: relative;
  margin-bottom: var(--s4);
}

.person-shot img {
  width: 100%;
  aspect-ratio: 4 / 5;
  object-fit: cover;
  object-position: top center;
  border-radius: 12px;
}

/* the plate sits inset from the shot's own edges and overlaps its foot */
.person-plate {
  position: absolute;
  left: var(--s3);
  right: var(--s3);
  bottom: var(--s3);
  display: flex;
  align-items: center;
  gap: var(--s3);
  padding: var(--s3) var(--s3) var(--s3) var(--s4);
  border-radius: 10px;
  background: var(--paper);
  box-shadow: 0 1px 2px rgba(17, 18, 19, 0.05), 0 10px 26px -18px rgba(17, 18, 19, 0.4);
}

.person-id {
  min-width: 0;
  margin-right: auto;
}

.person-name {
  font-size: 1rem;
  font-weight: 500;
  letter-spacing: -0.02em;
}

.person-role {
  font-family: var(--mono);
  font-size: 0.72rem;
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin-top: 3px;
}

/* the mark is drawn rather than set, so it needs no webfont and no raster */
.person-in {
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  border-radius: 8px;
  background: var(--ink);
  color: var(--paper);
  transition: background 0.25s;
}

.person-in svg {
  width: 19px;
  height: 19px;
  fill: none;
  stroke: currentColor;
  stroke-width: 2.1;
  stroke-linecap: round;
}

.person-in:hover {
  background: var(--blue);
}

.person-bio {
  font-size: 0.95rem;
  line-height: 1.6;
  color: var(--ink-2);
}

/* a definite track width, not minmax(0, x): a zero minimum lets the columns
   collapse to fit the container, so the rail never overflows and therefore
   never scrolls — which also keeps the arrows permanently hidden */
@media (max-width: 900px) {
  .team {
    grid-auto-columns: 74%;
  }
}

@media (max-width: 620px) {
  .team {
    grid-auto-columns: 86%;
  }
}


/* ---------- closing CTA ---------- */
/* The CTA runs the full width but its copy only occupies the left, leaving a
   wide empty right. A drawing grid fills it — graph paper is this page's own
   idiom — kept faint, and masked so it dissolves in every direction instead
   of ending on a hard edge. It is decoration, so it never takes a pointer. */
.close {
  position: relative;
  overflow: hidden;
  border-top: 1px solid var(--rule);
  background: var(--warm);
}

.close::after {
  content: "";
  position: absolute;
  inset: 0 0 0 auto;
  width: min(58%, 780px);
  pointer-events: none;
  background-image:
    radial-gradient(rgba(17, 18, 19, 0.14) 1.1px, transparent 1.2px),
    linear-gradient(to right, rgba(17, 18, 19, 0.05) 1px, transparent 1px),
    linear-gradient(to bottom, rgba(17, 18, 19, 0.05) 1px, transparent 1px);
  background-size: 28px 28px;
  /* an ellipse rather than a left-to-right fade: it has to lose its top and
     bottom edges as well, or the field reads as a pasted-on rectangle */
  -webkit-mask-image: radial-gradient(ellipse 76% 84% at 76% 50%, #000 10%, transparent 72%);
  mask-image: radial-gradient(ellipse 76% 84% at 76% 50%, #000 10%, transparent 72%);
}

/* stacked, the copy runs the full width and the field would sit under it */
@media (max-width: 760px) {
  .close::after {
    width: 74%;
    -webkit-mask-image: radial-gradient(ellipse 70% 46% at 82% 82%, #000 8%, transparent 70%);
    mask-image: radial-gradient(ellipse 70% 46% at 82% 82%, #000 8%, transparent 70%);
  }
}

.close .kick {
  border-bottom-color: var(--rule-w);
}

.close h2 {
  max-width: 20ch;
  font-weight: 400;
  font-size: clamp(1.7rem, 3.6vw, 2.9rem);
  line-height: 1.12;
  letter-spacing: -0.035em;
}

.close-sub {
  max-width: 56ch;
  margin: var(--s4) 0 var(--s6);
  color: var(--ink-2);
}

.btn.lg {
  padding: var(--s3) var(--s6);
  font-size: 0.92rem;
}

/* ---------- current page marker ---------- */
.nav-links a[aria-current="page"] {
  color: var(--blue);
  box-shadow: inset 0 -2px 0 var(--blue);
}

/* ---------- subpage responsive ---------- */
@media (max-width: 1080px) {

  .chain,
  .pcards {
    grid-template-columns: repeat(2, 1fr);
  }

  .chain-flow .chain-item::after {
    display: none;
  }
}

@media (max-width: 760px) {

  .chain,
  .pcards,
  .cmp {
    grid-template-columns: 1fr;
  }

  .cmp-cell:first-child {
    border-right: none;
    border-bottom: 1px solid var(--rule);
  }

  .anat-list li {
    padding-left: var(--s4);
    padding-right: var(--s4);
  }
}

/* ============ Scroll motion ============
   Four additions, all on the existing vocabulary: the hairline that draws
   (borrowed from .steps::after), the masked line reveal (borrowed from .ln),
   a scrubbed ink fill on the statement, and a read-progress rule on the nav.
   Each is inert without JS — the resting state is the finished state, so a
   failed script leaves the page correct rather than blank. */

/* ---------- big figures: masked line reveal ----------
   same mask-and-slide as the hero .ln, fired on entry instead of on load.
   the padding/margin pair buys room for descenders, which the mask would
   otherwise shear off the bottom of "days". */
.mask {
  display: block;
  overflow: hidden;
  padding-bottom: 0.12em;
  margin-bottom: -0.12em;
}

.mask>span {
  display: block;
  transform: translateY(105%);
  transition: transform 0.9s cubic-bezier(0.16, 0.84, 0.24, 1) 0.12s;
}

.rise.in .mask>span {
  transform: none;
}

/* ---------- statement: ink scrubbed in, word by word ----------
   each word mixes its own resting colour toward the paper, so at --p:100 it
   lands on the exact measured value and the held-back em clause keeps its
   lighter ink rather than being flattened to one tone. */
.stmt h2 {
  --fill: var(--ink);
}

.stmt em {
  --fill: var(--ink-3);
}

.stmt .w {
  color: color-mix(in srgb, var(--fill) calc(var(--p, 100) * 1%), var(--paper));
}

/* ---------- nav: how far through the page you are ---------- */
.nav::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  bottom: -1px;
  height: 2px;
  background: var(--blue);
  transform: scaleX(var(--sp, 0));
  transform-origin: 0 50%;
  pointer-events: none;
}

@media (prefers-reduced-motion: reduce) {

  .mask>span {
    transition: none;
    transform: none;
  }

  /* the progress rule is information, not decoration — it stays, it just
     stops being the thing that moves */
  .nav::after {
    transition: none;
  }
}

/* ============ Process diagram ============
   The plate's own ground is #fbf9f6 and --paper is #fafaf8 — two units apart,
   which is below the threshold where an edge is visible. So it sits directly
   on the page with no panel or border: a figure drawn on the sheet, which is
   how the rest of this page treats its drawings. Framing it would invent a
   boundary the artwork does not have. */
.flow {
  max-width: 1080px;
  margin: 0 auto var(--s8);
}

/* Measured off the plate: the title block occupies rows 40-100, the drawing
   runs 186-882, and everything below that is empty. The window keeps 150-920,
   which drops the title — the site's own branding, repeated mid-page under a
   heading that already says "How it works" — and trims the dead margin top
   and bottom, leaving the drawing about 37px of air on each side.
   To show the plate whole again: --flow-keep: 995 and object-position: center. */
.flow-frame {
  --flow-keep: 770;
  aspect-ratio: 1581 / var(--flow-keep);
  overflow: hidden;
}

.flow-frame img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* 67% of the 225px excess sits above the window, putting its top edge at
     row 150 — clear of the title, tight to the drawing */
  object-position: center 67%;
}

/* annotated like a drawing's title block: hairline above, set to the left */
.flow figcaption {
  margin-top: var(--s4);
  padding-top: var(--s3);
  border-top: 1px solid var(--rule);
  color: var(--ink-3);
}

@media (max-width: 720px) {
  .flow {
    margin-bottom: var(--s6);
  }
}

/* ============ Trust: captions beside the enclosure ============
   The four trust captions sit to the left of the illustration, so the grid
   that was four-across full width becomes two-across in half the room. */
.tsplit {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.02fr);
  gap: var(--s7);
  align-items: center;
}

.tsplit .tgrid {
  grid-template-columns: 1fr 1fr;
  gap: var(--s6) var(--s7);
}

/* The shield is an isolated object on real transparency, square canvas, and
   it already fills 91% of that canvas — so there is nothing to crop, nothing
   to fade, and no ground of its own to reconcile against the paper. contain
   rather than cover: it must never be clipped at any column width. */
.tsec {
  aspect-ratio: 1;
  max-width: 460px;
  margin: 0 auto;
}

.tsec img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: contain;
}

@media (max-width: 960px) {
  .tsplit {
    grid-template-columns: 1fr;
    gap: var(--s6);
  }

  /* stacked it has the full column, which a square object does not need */
  .tsec {
    max-width: 340px;
  }
}

/* .tsplit .tgrid outranks the plain .tgrid rule in the 760 breakpoint above,
   so the single-column collapse has to be restated at the same specificity or
   the captions stay two-across on a phone */
@media (max-width: 760px) {
  .tsplit .tgrid {
    grid-template-columns: 1fr;
  }
}

/* ============ Comparison bars ============
   Two columns that grow up out of the page, the URUS one taller. Each bar's
   tint is its own token at low alpha over paper, fading to nothing before the
   bottom edge, so the bars end by dissolving rather than being cut off.
   Per the source deck this compares against manual practice, not against
   competing software — which is what the heading says. */
/* The bars end in a faded tail that does the work bottom padding normally
   would, so the section adds none of its own — the next section's top padding
   sets the gap. Measured against the rest of the page: section gaps here run
   88px, and this join was 219px before the tails were shortened. */
.vsbar {
  padding-bottom: 0;
}

.vb-wrap {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(14px, 2.4vw, 34px);
  align-items: end;
  max-width: 680px;
  margin: 0 auto;
}

/* .rise is only the in-view flag here; .in drives the fill and the copy */
.vb.rise {
  opacity: 1;
  transform: none;
  transition: none;
}

.vb {
  position: relative;
  padding: var(--s6) clamp(16px, 2.4vw, 30px) var(--s8);
  text-align: center;
}

/* both are taller than their copy on purpose: the columns should carry on
   past the last row and dissolve, rather than ending where the words do */
.vb-conv {
  min-height: clamp(380px, 42vw, 480px);
}

/* taller, and it starts higher up the page — the difference is the point */
.vb-urus {
  min-height: clamp(450px, 50vw, 570px);
}

.vb-fill {
  position: absolute;
  inset: 0;
  z-index: 0;
  border-radius: 16px 16px 0 0;
  transform: scaleY(0);
  transform-origin: 50% 100%;
  transition: transform 1.15s cubic-bezier(0.4, 0, 0.2, 1);
}

.vb-conv .vb-fill {
  background: linear-gradient(180deg,
      rgba(176, 61, 24, 0.15),
      rgba(176, 61, 24, 0.05) 46%,
      rgba(176, 61, 24, 0) 93%);
}

.vb-urus .vb-fill {
  background: linear-gradient(180deg,
      rgba(22, 68, 126, 0.2),
      rgba(22, 68, 126, 0.06) 46%,
      rgba(22, 68, 126, 0) 93%);
}

/* the two bars grow in sequence, conventional first */
.vb.in .vb-fill {
  transform: scaleY(1);
}

.vb-urus .vb-fill {
  transition-delay: 0.16s;
}

.vb-body {
  position: relative;
  z-index: 1;
}

.vb-body h3 {
  font-size: 1.06rem;
  font-weight: 500;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  margin-bottom: var(--s5);
}

/* the summary pair reads as the column's identity, so it takes the label
   treatment; --ink-2 rather than --ink-3 because it sits on the strongest
   part of the tint, where --ink-3 falls under the contrast floor */
.vb-sum {
  font-family: var(--mono);
  font-size: 0.78rem;
  font-weight: 500;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-2);
  margin-bottom: var(--s3);
}

.vb-rows {
  margin-top: var(--s6);
}

.vb-rows dt {
  padding-top: var(--s5);
  border-top: 1px solid var(--rule);
  font-family: var(--mono);
  font-size: 0.78rem;
  font-weight: 500;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-2);
  margin-bottom: var(--s2);
}

.vb-rows dd {
  font-size: 0.97rem;
  line-height: 1.5;
  color: var(--ink);
  margin-bottom: var(--s5);
}

.vb-rows dd:last-child {
  margin-bottom: 0;
}

/* the copy lifts in behind the fill, in the order it is read. the list is
   excluded — its rows animate individually just below, and animating the
   container as well would compound the two movements */
.vb-body>*:not(.vb-rows),
.vb-rows>* {
  opacity: 0;
  transform: translateY(12px);
  transition: opacity 0.6s ease, transform 0.6s cubic-bezier(0.16, 0.84, 0.24, 1);
}

.vb.in .vb-body>*:not(.vb-rows),
.vb.in .vb-rows>* {
  opacity: 1;
  transform: none;
}

.vb.in .vb-body>*:nth-child(1) {
  transition-delay: 0.42s;
}

.vb.in .vb-body>*:nth-child(2) {
  transition-delay: 0.50s;
}

.vb.in .vb-body>*:nth-child(3) {
  transition-delay: 0.56s;
}

.vb.in .vb-rows>*:nth-child(1) {
  transition-delay: 0.64s;
}

.vb.in .vb-rows>*:nth-child(2) {
  transition-delay: 0.70s;
}

.vb.in .vb-rows>*:nth-child(3) {
  transition-delay: 0.78s;
}

.vb.in .vb-rows>*:nth-child(4) {
  transition-delay: 0.84s;
}

@media (max-width: 560px) {
  .vb {
    padding-left: var(--s3);
    padding-right: var(--s3);
  }

  .vb-rows dd {
    font-size: 0.84rem;
  }
}

@media (prefers-reduced-motion: reduce) {

  .vb-fill,
  .vb-body>*,
  .vb-rows>* {
    transition: none;
  }

  .vb-fill {
    transform: scaleY(1);
  }

  .vb-body>*,
  .vb-rows>* {
    opacity: 1;
    transform: none;
  }
}

/* ============ Platform: copy beside a capability accordion ============
   Two columns — the claim and its calls to action on the left, the four
   capabilities on the right as coloured cards that open one at a time.

   The reference this follows blocks its cards in periwinkle, lime and black.
   Lime has no counterpart here and would be the only colour on the site that
   belongs to no token, so the four fills are drawn from the palette instead:
   the warm band, the blue, the rust, and the dark. Same rhythm, same page. */
.plat {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.04fr);
  gap: clamp(32px, 5vw, 78px);
  align-items: start;
}

.plat-h {
  font-weight: 400;
  font-size: clamp(2rem, 4.2vw, 3.3rem);
  line-height: 1.06;
  letter-spacing: -0.04em;
  margin-bottom: var(--s5);
}

.plat-sub {
  max-width: 46ch;
  color: var(--ink-2);
  margin-bottom: var(--s6);
}

.plat-cta {
  display: flex;
  flex-wrap: wrap;
  gap: var(--s3);
  margin-bottom: var(--s8);
}

/* the CTAs take the pill shape the reference uses; everything else on the
   page keeps the 2px corner, so this is scoped to the pair */
.plat-cta .btn {
  border-radius: 100px;
  padding-inline: var(--s6);
}

.plat-cta .btn i {
  font-style: normal;
  margin-left: var(--s2);
}

.plat-chip-k {
  font-family: var(--mono);
  font-size: 0.78rem;
  font-weight: 500;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin-bottom: var(--s3);
}

/* ---------- the accordion ---------- */
.acc {
  display: flex;
  flex-direction: column;
  gap: var(--s3);
}

/* --acc-edge is each card's own fill at full strength; the stroke is drawn as
   an inset shadow rather than a border so it costs no layout and cannot shift
   the copy when it appears */
.acc-item {
  border-radius: 14px;
  overflow: hidden;
  box-shadow: inset 0 0 0 1px transparent;
  transition: background 0.3s, box-shadow 0.28s;
}

/* pointer only — on a touch screen a hover state latches after the tap and
   would leave the last card you opened permanently outlined. :focus-within
   carries the same cue to the keyboard. */
@media (hover: hover) {
  .acc-item:hover {
    box-shadow: inset 0 0 0 1px var(--acc-edge);
  }
}

.acc-item:focus-within {
  box-shadow: inset 0 0 0 1px var(--acc-edge);
}

.ac-warm {
  --acc-edge: rgba(17, 18, 19, 0.22);
  background: var(--warm);
}

.ac-blue {
  --acc-edge: rgba(22, 68, 126, 0.5);
  background: rgba(22, 68, 126, 0.14);
}

.ac-rust {
  --acc-edge: rgba(176, 61, 24, 0.48);
  background: rgba(176, 61, 24, 0.13);
}

.ac-dark {
  --acc-edge: rgba(255, 255, 255, 0.32);
  background: var(--dark);
  color: var(--paper);
}

.acc-item h3 {
  margin: 0;
  font-weight: 400;
}

.acc-btn {
  width: 100%;
  display: flex;
  align-items: center;
  gap: var(--s4);
  min-height: 72px;
  padding: var(--s4) var(--s5);
  border: none;
  background: none;
  color: inherit;
  font: inherit;
  font-size: clamp(1.02rem, 1.5vw, 1.24rem);
  letter-spacing: -0.02em;
  text-align: left;
  cursor: pointer;
}

.acc-btn>span:first-child {
  margin-right: auto;
}

/* the circular +/− control. two bars, one of which rotates away on open —
   the same two-bar construction as the nav burger */
.acc-ico {
  position: relative;
  flex: none;
  width: 30px;
  height: 30px;
  border-radius: 50%;
  background: var(--paper);
}

.ac-dark .acc-ico {
  background: rgba(255, 255, 255, 0.14);
}

.acc-ico::before,
.acc-ico::after {
  content: "";
  position: absolute;
  top: 50%;
  left: 50%;
  width: 11px;
  height: 1.5px;
  background: var(--ink);
  transform: translate(-50%, -50%);
  transition: transform 0.3s cubic-bezier(0.2, 0.7, 0.2, 1);
}

.ac-dark .acc-ico::before,
.ac-dark .acc-ico::after {
  background: var(--paper);
}

.acc-ico::after {
  transform: translate(-50%, -50%) rotate(90deg);
}

/* open: the upright bar lies down, leaving a minus */
.acc-item.open .acc-ico::after {
  transform: translate(-50%, -50%) rotate(0deg);
}

/* 0fr -> 1fr animates to the content's own height without measuring it.
   visibility is switched at the far end of the close so the collapsed copy
   leaves the tab order and the accessibility tree rather than just being
   clipped out of sight */
.acc-panel {
  display: grid;
  grid-template-rows: 0fr;
  visibility: hidden;
  transition: grid-template-rows 0.42s cubic-bezier(0.4, 0, 0.2, 1),
    visibility 0s linear 0.42s;
}

.acc-item.open .acc-panel {
  grid-template-rows: 1fr;
  visibility: visible;
  transition: grid-template-rows 0.42s cubic-bezier(0.4, 0, 0.2, 1),
    visibility 0s;
}

/* the padding has to sit on the children, not here: this is the box the grid
   clips to zero, and padding on it survives the collapse as a stubborn band
   of empty space under every closed card */
.acc-inner {
  overflow: hidden;
}

.acc-inner p {
  font-size: 0.95rem;
  line-height: 1.6;
  max-width: 52ch;
  color: var(--ink-2);
  padding: 0 var(--s5);
}

.ac-dark .acc-inner p {
  color: rgba(255, 255, 255, 0.74);
}

.acc-go {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 34px;
  height: 34px;
  margin: var(--s4) var(--s5) var(--s5);
  border: 1px solid rgba(17, 18, 19, 0.28);
  border-radius: 50%;
  transition: background 0.25s, color 0.25s, border-color 0.25s;
}

.acc-go i {
  font-style: normal;
  font-size: 0.9rem;
}

.acc-go:hover {
  background: var(--ink);
  border-color: var(--ink);
  color: var(--paper);
}

.ac-dark .acc-go {
  border-color: rgba(255, 255, 255, 0.34);
}

.ac-dark .acc-go:hover {
  background: var(--paper);
  border-color: var(--paper);
  color: var(--ink);
}

@media (max-width: 900px) {
  .plat {
    grid-template-columns: 1fr;
    gap: var(--s7);
  }

  .plat-cta {
    margin-bottom: var(--s6);
  }
}

@media (prefers-reduced-motion: reduce) {

  .acc-panel,
  .acc-item.open .acc-panel,
  .acc-ico::before,
  .acc-ico::after {
    transition: none;
  }
}

/* ============ Capability deck ============
   The four capabilities were stacked rows; they are now cards you scroll
   sideways through, one at a time with the next one showing at the edge so
   there is something to reach for. Snap does the work — the arrows and the
   drag handler only nudge the same native scroll. */
.capdeck-head {
  display: flex;
  align-items: flex-end;
  gap: var(--s4);
  margin-bottom: var(--s5);
}

.capdeck-head .kick {
  flex: 1;
  margin-bottom: 0;
}

.capdeck-ctrl {
  display: flex;
  align-items: center;
  gap: var(--s2);
  flex: none;
  padding-bottom: var(--s3);
}

.capdeck-count {
  font-family: var(--mono);
  font-size: 0.7rem;
  letter-spacing: 0.1em;
  color: var(--ink-3);
  margin-right: var(--s2);
}

.capdeck-count b {
  font-weight: 500;
  color: var(--ink);
}

/* the deck bleeds to both page edges so a card can sit flush while the one
   behind it is still cut by the viewport rather than by a container */
.capdeck {
  display: flex;
  /* each card sizes to its own copy rather than stretching to the tallest.
     Two of the four carry bullet lists and two do not, and a stretched card
     with nothing in the lower half reads as a mistake rather than as brevity.
     They level up again on their own if the shorter two gain bullets. */
  align-items: flex-start;
  gap: var(--s4);
  margin-inline: calc(var(--pad) * -1);
  padding: 4px var(--pad) var(--s4);
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scroll-padding-inline: var(--pad);
  scrollbar-width: none;
}

.capdeck::-webkit-scrollbar {
  display: none;
}

.capdeck.drag {
  cursor: grabbing;
  scroll-snap-type: none;
}

/* The last card has to be able to reach the left edge like every other one,
   which means real empty space after it. Trailing padding will not do: it is
   both too small and routinely dropped by engines on an overflowing flex row
   (the findings rail carries the same note). */
.capdeck::after {
  content: "";
  /* flex-basis 100% resolves against the deck's content box, which is already
     short by one --pad on each side; the last card needs the full client width
     less the scroll-padding it lands against, hence the + var(--pad) */
  flex: 0 0 max(0px, calc(100% + var(--pad) - clamp(280px, 62vw, 660px)));
}

.capcard {
  flex: 0 0 clamp(280px, 62vw, 660px);
  scroll-snap-align: start;
  display: flex;
  flex-direction: column;
  padding: var(--s6) clamp(22px, 3vw, 44px) var(--s6);
  border: 1px solid var(--rule);
  border-radius: 14px;
  background: var(--sheet);
  /* the drawing grid, faint enough to read as paper rather than as content */
  background-image:
    linear-gradient(to right, rgba(17, 18, 19, 0.032) 1px, transparent 1px),
    linear-gradient(to bottom, rgba(17, 18, 19, 0.032) 1px, transparent 1px);
  background-size: 28px 28px;
}

.capcard-ico {
  width: 62px;
  height: 62px;
  margin-bottom: var(--s6);
  fill: none;
  stroke: rgba(17, 18, 19, 0.42);
  stroke-width: 2.6;
  stroke-linecap: square;
}

.capcard h2 {
  display: flex;
  align-items: flex-start;
  gap: var(--s3);
  font-weight: 400;
  font-size: clamp(1.5rem, 2.6vw, 2.1rem);
  line-height: 1.1;
  letter-spacing: -0.035em;
  margin-bottom: var(--s4);
}

/* the filled index disc, as on the reference card */
.capcard-no {
  flex: none;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 38px;
  height: 38px;
  border-radius: 50%;
  background: var(--ink);
  color: var(--paper);
  font-family: var(--mono);
  font-size: 0.76rem;
  font-weight: 500;
  letter-spacing: 0.04em;
  transform: translateY(2px);
}

.capcard .cap-lead {
  max-width: 54ch;
}

.capcard .cap-note {
  margin-top: auto;
}

@media (max-width: 760px) {
  .capcard {
    flex-basis: 84vw;
    padding: var(--s5) var(--s4);
  }

  .capdeck-ctrl {
    display: none;
  }
}

@media (prefers-reduced-motion: reduce) {
  .capdeck {
    scroll-behavior: auto;
  }
}

/* ============ Page transitions ============
   A curtain sweeps up over the outgoing page, carrying the mark, and keeps
   travelling on the page it lands on — one continuous upward wipe across the
   navigation rather than two separate animations.

   The resting state is off-screen ABOVE. That matters: if the script never
   runs, or sessionStorage throws on an opaque origin, the curtain is parked
   out of the way and the site behaves exactly as it did before. It can only
   cover the page while something is actively driving it.

   This replaces the cross-document view transition that was here — running
   both would put a cross-fade underneath a curtain that already hides it. */
.curtain {
  position: fixed;
  inset: 0;
  /* above the nav (60) and the dock */
  z-index: 300;
  display: flex;
  align-items: center;
  justify-content: center;
  background: var(--dark);
  transform: translateY(-100%);
  pointer-events: none;
  will-change: transform;
}

.curtain-mark {
  display: flex;
  align-items: center;
  gap: var(--s3);
  font-size: clamp(1.3rem, 2.6vw, 2rem);
  font-weight: 600;
  letter-spacing: -0.03em;
  color: var(--paper);
  opacity: 0;
}

.curtain-mark b {
  font-weight: 600;
  color: rgba(255, 255, 255, 0.55);
}

/* the mark is mid-grey artwork; brightness(0) flattens it to black and
   invert(1) lifts it to white, which is cheaper than shipping a second file */
.curtain-mark img {
  width: auto;
  height: clamp(30px, 4vw, 46px);
  filter: brightness(0) invert(1);
}

/* leaving: the curtain rises from below and covers */
.curtain.drop {
  animation: curtain-drop 0.22s cubic-bezier(0.4, 0, 0.2, 1) forwards;
}

.curtain.drop .curtain-mark {
  animation: mark-in 0.14s ease 0.04s forwards;
}

@keyframes curtain-drop {
  from {
    transform: translateY(100%);
  }

  to {
    transform: translateY(0);
  }
}

@keyframes mark-in {
  to {
    opacity: 1;
  }
}

/* arriving: it carries on upward and off, uncovering the new page */
.arriving .curtain {
  animation: curtain-lift 0.28s cubic-bezier(0.4, 0, 0.2, 1) both;
}

.arriving .curtain .curtain-mark {
  animation: mark-out 0.16s ease both;
}

@keyframes curtain-lift {
  from {
    transform: translateY(0);
  }

  to {
    transform: translateY(-100%);
  }
}

@keyframes mark-out {
  from {
    opacity: 1;
  }

  to {
    opacity: 0;
  }
}

/* no wipe, no covering — navigation is instant and the curtain never appears */
@media (prefers-reduced-motion: reduce) {

  .curtain,
  .curtain.drop,
  .arriving .curtain {
    animation: none;
    transform: translateY(-100%);
  }
}

/* ============ Headings that arrive word by word ============
   .rise stays as the in-view flag; the words carry the reveal, the same way
   .steps and the comparison bars already do it. Each word's delay comes from
   its index, so the line assembles left to right. */
.sec-h.rise,
.plat-h.rise {
  opacity: 1;
  transform: none;
  transition: none;
}

.sec-h .w,
.plat-h .w {
  /* inline-block so the word can be transformed; the spaces between them are
     still text nodes, so the line wraps exactly as it did before */
  display: inline-block;
  opacity: 0;
  transform: translateY(0.32em);
  transition: opacity 0.32s ease, transform 0.32s cubic-bezier(0.16, 0.84, 0.24, 1);
  transition-delay: calc(var(--i, 0) * 32ms);
}

.sec-h.in .w,
.plat-h.in .w {
  opacity: 1;
  transform: none;
}

@media (prefers-reduced-motion: reduce) {

  .sec-h .w,
  .plat-h .w {
    opacity: 1;
    transform: none;
    transition: none;
  }
}

/* ============ Preconfigured checks: the three layers ============
   One panel, three rows divided by hairlines: the artwork on the left, the
   layer's number and name on the right. The panel is a wash of --blue rather
   than a new grey, so it stays inside the palette. */
.layers {
  border-radius: 16px;
  background: rgba(22, 68, 126, 0.045);
  overflow: hidden;
}

.layer {
  display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, 1fr);
  gap: clamp(20px, 4vw, 64px);
  align-items: center;
  padding: clamp(20px, 3vw, 38px);
}

.layer+.layer {
  border-top: 1px solid rgba(22, 68, 126, 0.1);
}

/* The three plates are 1.72, 1.74 and 1.65 — close but not equal. A single
   box near their average keeps the rows the same height, and contain means
   none of them is cropped to get there. */
.layer-art {
  aspect-ratio: 17 / 10;
}

/* The plates are RGBA with a genuinely clear background, so they need no
   ground of their own — the panel shows straight through and the linework
   reads as drawn onto it. */
.layer-art img {
  width: 100%;
  height: 100%;
  object-fit: contain;
}

.layer-k {
  font-family: var(--mono);
  font-size: 0.78rem;
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin-bottom: var(--s3);
}

.layer-k span {
  margin: 0 var(--s1);
  color: rgba(22, 68, 126, 0.5);
}

.layer-t {
  font-weight: 400;
  font-size: clamp(1.5rem, 3vw, 2.4rem);
  line-height: 1.05;
  letter-spacing: -0.04em;
}

.layer-d {
  max-width: 44ch;
  margin-top: var(--s4);
  font-size: 0.95rem;
  line-height: 1.6;
  color: var(--ink-2);
}

@media (max-width: 760px) {
  .layer {
    grid-template-columns: 1fr;
    gap: var(--s4);
  }

  /* copy first when stacked — the name of the layer should arrive before its
     illustration, not after it */
  .layer-copy {
    order: -1;
  }
}
/* ============ engineering-review: the deck rises over the hero ============
   The hero pins at the top and the capability deck scrolls up over it, so the
   plate is revealed and then covered rather than scrolling away. Both classes
   live only on this page, so the behaviour is inherently scoped to it — the
   other subpage heroes scroll normally.

   Three things this needs to be correct:

   max-height, because a pinned element you cannot scroll is an element whose
   overflow is unreachable. The hero's height comes from the video's 16:9, and
   at wide viewports that exceeds the window — capping it keeps all of the
   plate visible while it is held. The video is object-fit: contain, so it
   still shows whole inside the shorter box rather than being cropped.

   an opaque deck, because .caps had no background of its own and the pinned
   hero would have shown straight through it.

   and the stacking order, so the deck passes in front rather than behind. */
.phero-plate {
  position: sticky;
  top: 0;
  z-index: 0;
  max-height: 100svh;
  /* width must be stated: with aspect-ratio set and max-height clamping the
     height, the browser derives the inline size from the ratio too and the
     section stops short of the viewport edge. Pinning it to 100% keeps the
     box full-bleed and lets the cap only ever shorten it. */
  width: 100%;
}

/* EVERY sibling after the hero, not just the deck. A sticky element is a
   positioned one, so it paints above static content — raising only .caps left
   .close underneath, and the video showed through the section below the deck.
   The sibling combinator covers whatever else this page grows later. */
.phero-plate~* {
  position: relative;
  z-index: 1;
}

/* .caps had no ground of its own, so the pinned hero showed straight through */
.caps {
  background: var(--paper);
}
