/* ==========================================================================
   ANGARIA CubeRight — site stylesheet

   NEAR-WHITE THEME, aligned to the product's UI-PIVOT-PLAN so the marketing
   site and the application read as one system. Ground, ink ramp, the
   three-teal accent and the gold rule are that plan's values verbatim.

   Two rules from the plan that must survive any edit:
     · --ink-4 is DECORATIVE ONLY. It is 2.6:1 on white. Never put text in it.
     · Teal has three jobs and one value cannot do all three at AA.
       --brand (#0E8A7D, 4.24:1) is identity — rules, borders, chart series.
       --brand-solid carries a white label. --brand-ink is teal TEXT.
     · Gold means "the computed optimum" and nothing else. One per composition.
   ========================================================================== */

/* --------------------------------------------------------------------------
   1 · Tokens
   -------------------------------------------------------------------------- */
:root {
  /* ---- Ground ---------------------------------------------------------- */
  --canvas:    #FBFBFC;
  --surface:   #FFFFFF;
  --surface-2: #F5F6F8;
  --surface-3: #EEF0F4;

  --border:   #E6E8EC;
  --border-2: #D6D9E0;
  --border-3: #C3C7D1;

  /* ---- Ink, contrast measured on #FFFFFF ------------------------------- */
  --ink:   #14161C;   /* 16.1:1 — headings, primary values                  */
  --ink-2: #4B5060;   /*  8.2:1 — body copy                                 */
  --ink-3: #686E7E;   /*  5.1:1 — labels, captions. Smallest text allowed.  */
  --ink-4: #A1A7B4;   /*  2.6:1 — DECORATIVE ONLY. Never text.              */

  /* ---- The one accent, in three contrast-correct jobs ------------------ */
  --brand:        #0E8A7D;  /* identity: rules, borders, series. Not text.  */
  --brand-solid:  #0B7C6F;  /* fills carrying a white label — 5.1:1         */
  --brand-ink:    #0A6C61;  /* teal TEXT on white — 6.3:1                   */
  --brand-hover:  #085D53;
  --brand-2:      #12A192;
  --brand-soft:   #E6F4F1;
  --brand-soft-2: #D2EBE6;
  --brand-border: #B4DED6;

  /* ---- Gold: the computed optimum. One use per composition. ------------ */
  --gold:        #E3AC49;
  --gold-ink:    #8A6516;   /* the only AA-safe gold for text               */
  --gold-soft:   #FFFDF8;
  --gold-soft-2: #FBF4E6;
  --gold-border: #E5D3AC;

  /* ---- Categorical series colors ---------------------------------------
     For identifying competitor categories in charts only. Never UI, never a
     button, never a state. Contrast on white is 5:1 or better so the same
     value can carry the legend label. */
  --cat-early:    #C2410C;   /* early-cubing specialists  — orange  */
  --cat-api:      #7C3AED;   /* cartonization APIs        — violet  */
  --cat-load:     #1D4ED8;   /* load-optimization engines — blue    */
  --cat-platform: #BE185D;   /* supply-chain platforms    — magenta */
  --cat-wms:      #57534E;   /* WMS / ERP modules         — slate   */

  /* ---- Semantic, separate from the accent ------------------------------ */
  --red:        #B23B2C;
  --red-soft:   #FBE7E3;
  --red-border: #EFC9C1;

  /* ---- Channel triplets for translucency ------------------------------- */
  --ink-rgb:   20, 22, 28;
  --brand-rgb: 14, 138, 125;
  --gold-rgb:  227, 172, 73;

  /* ---- Structural aliases -----------------------------------------------
     The sheet was authored against a dark/light pair of surfaces. Those
     names are kept so section classes and descendant rules keep working;
     on this theme both families resolve to the same near-white values.
     Restoring a dark theme means re-pointing this block, nothing else.  */
  --midnight:        var(--surface);
  --midnight-deep:   var(--surface-2);
  --midnight-lift-1: var(--surface-2);
  --midnight-lift-2: var(--surface-3);

  --ivory:       var(--surface);
  --ivory-hi:    var(--canvas);
  --ivory-shade: var(--surface-2);

  --teal:      var(--brand);
  --teal-deep: var(--brand-hover);
  --teal-lift: var(--brand-solid);
  --teal-glow: var(--brand-ink);

  --amber:    var(--gold);
  --amber-hi: #F4CD78;
  --amber-lo: var(--gold-ink);

  --ivory-rgb:    var(--ink-rgb);
  --midnight-rgb: var(--ink-rgb);
  --deep-rgb:     var(--ink-rgb);
  --lift-rgb:     var(--ink-rgb);
  --teal-rgb:     var(--brand-rgb);
  --glow-rgb:     var(--brand-rgb);
  --amber-rgb:    var(--gold-rgb);

  /* Text — both families now resolve on white. */
  --td-1: var(--ink);
  --td-2: var(--ink-2);
  --td-3: var(--ink-3);
  --td-4: var(--ink-4);

  --tl-1: var(--ink);
  --tl-2: var(--ink-2);
  --tl-3: var(--ink-3);
  --tl-4: var(--ink-4);

  /* Hairlines */
  --rule-dark:    var(--border);
  --rule-dark-2:  var(--surface-3);
  --rule-light:   var(--border);
  --rule-light-2: var(--surface-3);

  /* Semantic roles */
  --on-accent:      #FFFFFF;
  --on-accent-lift: #FFFFFF;
  --on-amber:       #3A2708;
  --flag:           var(--red);
  --error:          var(--red);

  /* ---- ONE family, matching the product ---------------------------------
     Hierarchy is carried by size, weight and tracking. Alignment that a mono
     face used to provide comes from font-variant-numeric: tabular-nums.
     The display/mono aliases are kept so existing rules resolve; they all
     point at the same family. */
  --font: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto,
          Helvetica, Arial, sans-serif;
  /* The display face is a BRAND face: display headings and the stat figures
     only. It was Fraunces until 21 Aug; its lowercase f has a stunted, clipped
     hook that the owner flagged on a phone, and it is the face's design rather
     than a setting — WONK 0 was in the CSS but Google Fonts never served that
     axis, so A/B testing it changed nothing.

     Newsreader replaces it: an editorial screen serif with a properly
     overhanging f, real optical sizing, and enough contrast to stay distinct
     beside Inter without being quirky.

     Optical size must TRACK the rendered size, never be pinned. Every heading
     used to carry 'opsz' 110-140 in font-variation-settings, which overrides
     font-optical-sizing — a 120pt display cut rendered at the 32px a phone
     actually uses is all hairline. Do not put an opsz value back.
     It must never appear in UI chrome, labels, tables or body copy. */
  --font-display: 'Newsreader', 'Iowan Old Style', Georgia, serif;
  --font-ui:      var(--font);
  --font-mono:    var(--font);

  /* Measure & rhythm */
  --container: 1240px;
  --container-narrow: 880px;
  --gutter: clamp(1.25rem, 5vw, 3rem);
  --section-y: clamp(3.75rem, 2.4rem + 4.6vw, 6.75rem);

  --radius-sm: 3px;
  --radius: 5px;
  --radius-lg: 8px;

  --ease: cubic-bezier(0.22, 0.61, 0.36, 1);
  --ease-out: cubic-bezier(0.16, 1, 0.3, 1);
}

/* --------------------------------------------------------------------------
   2 · Reset & base
   -------------------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; }

html {
  /* 110% of the user's base — everything below is in rem, so this is the one
     lever that scales the whole page. Never set this in px. */
  font-size: 110%;
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: 108px;
}
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
}

body {
  font-family: var(--font);
  font-size: 1rem;
  line-height: 1.62;
  font-weight: 400;
  color: var(--ink);
  background: var(--surface);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  font-feature-settings: 'cv05' 1, 'cv08' 1, 'ss01' 1;
  overflow-x: hidden;
}

img, svg { display: block; max-width: 100%; }
a { color: inherit; text-decoration: none; }
button, input, textarea, select { font: inherit; color: inherit; }
table { border-collapse: collapse; width: 100%; }

::selection { background: var(--brand-soft-2); color: var(--ink); }

:focus-visible {
  outline: 2px solid var(--teal-lift);
  outline-offset: 3px;
  border-radius: 2px;
}

/* --------------------------------------------------------------------------
   3 · Layout primitives
   -------------------------------------------------------------------------- */
.container {
  width: 100%;
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: var(--gutter);
}
.container--narrow { max-width: var(--container-narrow); }

.section { padding-block: var(--section-y); position: relative; }
.section--tight { padding-block: clamp(3rem, 2rem + 4vw, 5.5rem); }

.section--dark {
  background: var(--surface);
  color: var(--ink);
}
.section--deep {
  background: var(--surface-2);
  color: var(--ink);
}
.section--shade { background: var(--surface-2); }
.section--hi { background: var(--surface); }

/* Skip link */
.skip {
  position: absolute; left: -9999px; top: 0; z-index: 200;
  background: var(--ink); color: #FFFFFF;
  padding: 0.85rem 1.25rem; font-size: 0.935rem;
}
.skip:focus { left: 1rem; top: 1rem; }

/* --------------------------------------------------------------------------
   4 · Typography
   -------------------------------------------------------------------------- */
.display-xl, .display-l, .display-m, .display-s {
  font-family: var(--font-display);
  font-optical-sizing: auto;
  font-weight: 400;
  letter-spacing: -0.022em;
  text-wrap: balance;
}

.display-xl {
  font-size: clamp(2.15rem, 1.25rem + 3vw, 3.35rem);
  line-height: 1.06;
  font-weight: 400;
  letter-spacing: -0.028em;
}
.display-l {
  font-size: clamp(1.8rem, 1.25rem + 2vw, 2.8rem);
  line-height: 1.12;
  font-weight: 400;
  letter-spacing: -0.024em;
}
.display-m {
  font-size: clamp(1.38rem, 1.15rem + 0.9vw, 1.85rem);
  line-height: 1.2;
  font-weight: 500;
}
.display-s {
  font-size: clamp(1.12rem, 1.02rem + 0.42vw, 1.34rem);
  line-height: 1.3;
  font-weight: 500;
  letter-spacing: -0.014em;
}

.lead {
  font-size: clamp(1.04rem, 0.98rem + 0.32vw, 1.2rem);
  line-height: 1.6;
  color: var(--tl-2);
  text-wrap: pretty;
}
.section--dark .lead, .section--deep .lead { color: var(--td-2); }

.eyebrow {
  font-family: var(--font-mono);
  font-size: 0.8rem;
  font-weight: 500;
  letter-spacing: 0.15em;
  text-transform: uppercase;
  color: var(--brand-ink);
  display: flex;
  align-items: center;
  gap: 0.7rem;
  margin-bottom: 1rem;
}
.eyebrow::before {
  content: '';
  width: 1.75rem; height: 1px;
  background: currentColor;
  opacity: 0.55;
  flex: none;
}
.section--dark .eyebrow, .section--deep .eyebrow { color: var(--brand-ink); }
.eyebrow--amber { color: var(--gold-ink); }
.section--dark .eyebrow--amber, .section--deep .eyebrow--amber { color: var(--gold-ink); }

.mono, .num { font-variant-numeric: tabular-nums; font-feature-settings: 'tnum' 1; }

/* Uppercase micro-label — the role the mono face used to signal.
   Weight and tracking carry it now. */
.ml, .eyebrow, .footnote, .horizon__title, .lock__when, .track__label,
.band__k, .clock__date, .stage__n, .stage__name, .coil__head, .fit__s,
.led__h, .spec__t, .shot__label, .shot__pending,
.tablehint, .footer__col h4, .footer__bot, .status-tag, .grade,
.horizon__legend, .horizon__ends, .claim__i, .step__n, .vkey b,
.score thead th, .delta thead th, .lockrow__when, .lockrow__state,
.lockdivider, .sens__v, .delta tbody td, .score tbody td,
.score tfoot td, .vseg__pct, .radar__v {
  font-family: var(--font);
  font-variant-numeric: tabular-nums;
  font-feature-settings: 'tnum' 1, 'cv05' 1;
}

.muted { color: var(--tl-3); }
.section--dark .muted, .section--deep .muted { color: var(--td-3); }

.accent { color: var(--brand-ink); }
.section--dark .accent, .section--deep .accent { color: var(--brand-ink); }

.apex { color: var(--amber-lo); }
.section--dark .apex, .section--deep .apex { color: var(--gold-ink); }

/* Emphasized inline phrase — a hairline underscore, brand-consistent */
.mark {
  background-image: linear-gradient(to top, rgba(var(--gold-rgb), 0.4) 0.28em, transparent 0.28em);
  padding-inline: 0.05em;
}

.section-head { max-width: 62ch; margin-bottom: clamp(2rem, 1.4rem + 2.2vw, 3.25rem); }
.section-head .lead { margin-top: 1.1rem; }

.footnote {
  font-family: var(--font-mono);
  font-size: 0.8rem;
  line-height: 1.6;
  letter-spacing: 0.005em;
  color: var(--tl-3);
}
.section--dark .footnote, .section--deep .footnote { color: var(--td-3); }

/* Evidence grade chip — the corpus discipline, made visible */
.grade {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-mono);
  font-size: 0.8rem;
  font-weight: 600;
  letter-spacing: 0.06em;
  line-height: 1;
  padding: 0.24em 0.44em;
  border: 1px solid currentColor;
  border-radius: 2px;
  vertical-align: 0.12em;
  opacity: 0.8;
}
.grade--a { color: var(--brand-ink); }
.grade--b { color: var(--tl-3); }
.grade--m { color: var(--amber-lo); }
.section--dark .grade--a, .section--deep .grade--a { color: var(--brand-ink); }
.section--dark .grade--b, .section--deep .grade--b { color: var(--td-3); }
.section--dark .grade--m, .section--deep .grade--m { color: var(--gold-ink); }

/* --------------------------------------------------------------------------
   5 · Buttons
   -------------------------------------------------------------------------- */
.btn {
  display: inline-flex;
  align-items: center;
  gap: 0.6rem;
  font-size: 0.9625rem;
  font-weight: 500;
  letter-spacing: 0.005em;
  padding: 0.82rem 1.4rem;
  border-radius: var(--radius);
  border: 1px solid transparent;
  cursor: pointer;
  transition: background-color 0.22s var(--ease), border-color 0.22s var(--ease),
              color 0.22s var(--ease), transform 0.22s var(--ease);
  white-space: nowrap;
}
.btn svg { flex: none; transition: transform 0.28s var(--ease-out); }
.btn:hover svg { transform: translateX(3px); }

/* A white label needs --brand-solid (5.1:1). On --brand it is 4.24:1 and fails. */
.btn--primary {
  background: var(--brand-solid);
  color: var(--on-accent);
  border-color: var(--brand-solid);
}
.btn--primary:hover { background: var(--teal-deep); border-color: var(--teal-deep); }
.section--dark .btn--primary, .section--deep .btn--primary, .nav .btn--primary {
  background: var(--teal-lift); border-color: var(--teal-lift); color: var(--on-accent-lift);
}
.section--dark .btn--primary:hover, .section--deep .btn--primary:hover, .nav .btn--primary:hover {
  background: var(--teal-glow); border-color: var(--teal-glow);
}

.btn--ghost {
  background: transparent;
  color: var(--tl-1);
  border-color: var(--rule-light);
}
.btn--ghost:hover { border-color: var(--border-3); background: var(--surface-2); }
.section--dark .btn--ghost, .section--deep .btn--ghost, .nav .btn--ghost {
  color: var(--td-1); border-color: var(--rule-dark);
}
.section--dark .btn--ghost:hover, .section--deep .btn--ghost:hover, .nav .btn--ghost:hover {
  border-color: var(--border-3); background: var(--surface-2);
}

.btn--sm { padding: 0.58rem 1rem; font-size: 0.845rem; }

.btn-row { display: flex; flex-wrap: wrap; gap: 0.75rem; }
@media (max-width: 460px) {
  .btn-row { display: grid; }
  .btn-row .btn { justify-content: center; }
}

/* Text link with hairline */
.tlink {
  display: inline-flex;
  align-items: center;
  gap: 0.45rem;
  font-size: 0.9625rem;
  font-weight: 500;
  color: var(--brand-ink);
  padding-bottom: 2px;
  border-bottom: 1px solid var(--brand-border);
  transition: border-color 0.2s var(--ease), color 0.2s var(--ease);
}
.tlink:hover { border-color: var(--teal); }
.section--dark .tlink, .section--deep .tlink {
  color: var(--brand-ink); border-bottom-color: var(--brand-border);
}
.section--dark .tlink:hover, .section--deep .tlink:hover { border-bottom-color: var(--brand-ink); }

/* --------------------------------------------------------------------------
   6 · Brand lockup
   -------------------------------------------------------------------------- */
.lockup {
  display: inline-flex;
  align-items: center;
  gap: 0.7rem;
  flex: none;
}
.lockup__mark { width: 28px; height: 28px; flex: none; }
.lockup__type {
  display: flex;
  align-items: baseline;
  gap: 0.62rem;
  line-height: 1;
}
.lockup__parent {
  font-size: 0.85rem;
  font-weight: 600;
  letter-spacing: 0.17em;
  color: currentColor;
}
.lockup__div {
  width: 1px; height: 15px;
  background: currentColor;
  opacity: 0.3;
  align-self: center;
}
.lockup__product {
  font-size: 0.98rem;
  font-weight: 400;
  letter-spacing: -0.005em;
  color: var(--brand-ink);
}
.nav--dark .lockup__product, .footer .lockup__product { color: var(--brand-ink); }

/* --------------------------------------------------------------------------
   7 · Navigation
   -------------------------------------------------------------------------- */
.nav {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 100;
  color: var(--td-1);
  transition: background-color 0.35s var(--ease), border-color 0.35s var(--ease),
              color 0.35s var(--ease), backdrop-filter 0.35s var(--ease);
  border-bottom: 1px solid transparent;
}
.nav--dark { color: var(--td-1); }

.nav.is-stuck {
  background: rgba(255, 255, 255, 0.86);
  backdrop-filter: saturate(150%) blur(14px);
  -webkit-backdrop-filter: saturate(150%) blur(14px);
  border-bottom-color: var(--rule-dark-2);
}

.nav__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 2.5rem;
  height: 84px;
}
.nav__links {
  display: flex;
  align-items: center;
  gap: 1.9rem;
  margin-left: auto;
}
.nav__link {
  font-size: 0.85rem;
  font-weight: 500;
  letter-spacing: -0.002em;
  color: var(--ink-2);
  position: relative;
  padding-block: 0.5rem;
  white-space: nowrap;
  transition: color 0.2s var(--ease);
}
.nav__link::after {
  content: '';
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 1px;
  background: var(--teal-glow);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.3s var(--ease-out);
}
.nav__link:hover { color: var(--td-1); }
.nav__link:hover::after { transform: scaleX(1); }

.nav__cta {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  padding-left: 1.75rem;
  margin-left: 0.4rem;
  position: relative;
}
.nav__cta::before {
  content: '';
  position: absolute;
  left: 0; top: 50%;
  width: 1px; height: 22px;
  background: var(--border-2);
  transform: translateY(-50%);
}
@media (max-width: 1100px) {
  .nav__cta { padding-left: 0; margin-left: 0; }
  .nav__cta::before { display: none; }
}

/* The burger is the only way into nine pages on a phone, and an outlined gray
   square on a near-white chrome is invisible. It carries teal — identity, per
   rule 2 — not gold, which means "the computed optimum" and never a control.
   Soft rather than solid because between 560 and 1100px the primary CTA sits
   beside it; below 560px the CTA moves into the panel and this is the only
   accent left in the bar. Open, it goes solid to read as a live toggle. */
.nav__burger {
  display: none;
  width: 40px; height: 40px;
  align-items: center; justify-content: center;
  background: var(--brand-soft);
  border: 1px solid var(--brand-border);
  border-radius: var(--radius-sm);
  color: var(--brand-ink);
  cursor: pointer;
  transition: background-color 0.22s var(--ease), border-color 0.22s var(--ease),
              color 0.22s var(--ease);
}
.nav.is-open .nav__burger {
  background: var(--brand-solid);
  border-color: var(--brand-solid);
  color: var(--on-accent);
}
.nav__burger span {
  display: block; width: 16px; height: 1.5px;
  background: currentColor;
  position: relative;
  transition: background 0.2s var(--ease);
}
.nav__burger span::before, .nav__burger span::after {
  content: ''; position: absolute; left: 0;
  width: 16px; height: 1.5px; background: currentColor;
  transition: transform 0.28s var(--ease);
}
.nav__burger span::before { top: -5px; }
.nav__burger span::after { top: 5px; }
.nav.is-open .nav__burger span { background: transparent; }
.nav.is-open .nav__burger span::before { transform: translateY(5px) rotate(45deg); }
.nav.is-open .nav__burger span::after { transform: translateY(-5px) rotate(-45deg); }

@media (max-width: 1100px) {
  .nav__burger { display: flex; }
  .nav__links {
    position: fixed;
    inset: 84px 0 auto 0;
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    background: var(--surface);
    border-bottom: 1px solid var(--border);
    padding: 0.25rem var(--gutter) 1rem;
    transform: translateY(-8px);
    opacity: 0;
    pointer-events: none;
    transition: opacity 0.25s var(--ease), transform 0.25s var(--ease);
    /* The panel is ~995px of links and the body is scroll-locked while it is
       open. Without its own scroller, Resources, Pricing and the CTA fall off
       the bottom of any phone shorter than ~1080px and cannot be reached.
       dvh so the iOS URL bar collapsing does not re-hide the last item. */
    max-height: calc(100vh - 84px);
    max-height: calc(100dvh - 84px);
    overflow-y: auto;
    overscroll-behavior: contain;
    -webkit-overflow-scrolling: touch;
  }
  .nav.is-open .nav__links { opacity: 1; transform: none; pointer-events: auto; }
  .nav.is-open { background: rgba(255, 255, 255, 0.97); backdrop-filter: blur(14px); }
  .nav__link {
    padding: 0.95rem 0;
    border-bottom: 1px solid var(--rule-dark-2);
    font-size: 1.045rem;
  }
  .nav__link::after { display: none; }
}

/* Below 560px the bar can only carry the lockup and the burger, so the
   primary CTA moves into the menu panel rather than being dropped. */
.nav__menu-cta { display: none; }
@media (max-width: 560px) {
  .nav__cta .btn--primary { display: none; }
  .nav__menu-cta {
    display: inline-flex;
    justify-content: center;
    margin-top: 1rem;
  }
  .lockup__parent { font-size: 0.814rem; letter-spacing: 0.15em; }
  .lockup__product { font-size: 0.968rem; }
  .lockup__mark { width: 26px; height: 26px; }
}

/* --------------------------------------------------------------------------
   7b · The curtain — the first thing anyone sees
        The page used to open mid-argument, on "every expensive decision is
        made before anyone knows how big the order is". That is the right
        second beat and the wrong first one: it assumes the reader already
        knows what the product is.

        This is the first beat. The mark resolves — silhouette, then the three
        inner edges that make it a solid, then the waypoints, then the gold
        apex — which is the product argument drawn: the shape is known before
        the corner that matters locks. Then four words and the claim.

        Everything animates from a visible resting state via `both` fill, so a
        browser that ignores the animation shows the finished composition
        rather than an empty section.
   -------------------------------------------------------------------------- */
.curtain {
  position: relative;
  overflow: hidden;
  background: var(--surface);
  display: grid;
  place-items: center;
  text-align: center;
  /* Tuned so the scroll cue sits inside a laptop viewport rather than just
     below it — an invitation the reader cannot see is not an invitation. */
  padding-block: clamp(5.25rem, 4.2rem + 3.2vw, 6.5rem) clamp(4.5rem, 3.4rem + 3vw, 6rem);
  min-height: 31rem;
  min-height: min(88svh, 45rem);
}
.curtain__grid {
  position: absolute; inset: 0;
  background-image:
    linear-gradient(to right, rgba(var(--ink-rgb), 0.05) 1px, transparent 1px),
    linear-gradient(to bottom, rgba(var(--ink-rgb), 0.05) 1px, transparent 1px);
  background-size: 74px 74px;
  mask-image: radial-gradient(ellipse 70% 60% at 50% 42%, #000 0%, transparent 76%);
  -webkit-mask-image: radial-gradient(ellipse 70% 60% at 50% 42%, #000 0%, transparent 76%);
  pointer-events: none;
}
.curtain__glow {
  position: absolute;
  left: 50%; top: 42%;
  width: min(74rem, 130%); aspect-ratio: 1.55;
  translate: -50% -50%;
  background: radial-gradient(ellipse at center,
    rgba(18, 161, 146, 0.13) 0%, rgba(18, 161, 146, 0.05) 44%, transparent 70%);
  pointer-events: none;
}
.curtain__inner { position: relative; display: grid; justify-items: center; }

/* ── the mark, resolving ─────────────────────────────────────────────── */
.cubeanim {
  width: clamp(92px, 19vw, 148px);
  height: auto;
  color: var(--brand);
  overflow: visible;
  margin-bottom: clamp(1.5rem, 1.1rem + 1.4vw, 2.2rem);
}
.cubeanim__shell, .cubeanim__spoke { stroke-dasharray: 1; stroke-dashoffset: 0; }
.cubeanim__node, .cubeanim__apex { transform-origin: center; transform-box: fill-box; }

.js .cubeanim__shell {
  stroke-dashoffset: 1;
  animation: cubeDraw 1s var(--ease-out) 0.1s both;
}
.js .cubeanim__spoke {
  stroke-dashoffset: 1;
  animation: cubeDraw 0.55s var(--ease-out) both;
}
.js .cubeanim__spoke--1 { animation-delay: 0.75s; }
.js .cubeanim__spoke--2 { animation-delay: 0.87s; }
.js .cubeanim__spoke--3 { animation-delay: 0.99s; }

.js .cubeanim__node {
  animation: cubePop 0.42s var(--ease-out) both;
  animation-delay: calc(1.25s + var(--n) * 0.06s);
}
.js .cubeanim__apex { animation: cubeApex 0.55s var(--ease-out) 1.7s both; }
/* `pulse` animates box-shadow, which does nothing to an SVG group — the apex
   breathes on scale instead. */
@media (prefers-reduced-motion: no-preference) {
  .js .cubeanim__apex { animation: cubeApex 0.55s var(--ease-out) 1.7s both, apexBreathe 3.6s var(--ease) 2.6s infinite; }
}
@keyframes apexBreathe { 0%, 100% { scale: 1; } 50% { scale: 1.09; } }

@keyframes cubeDraw { from { stroke-dashoffset: 1; } to { stroke-dashoffset: 0; } }
@keyframes cubePop  { from { opacity: 0; scale: 0.3; } to { opacity: 1; scale: 1; } }
@keyframes cubeApex { from { opacity: 0; scale: 0.2; } to { opacity: 1; scale: 1; } }

/* ── the words ───────────────────────────────────────────────────────── */
.curtain__head {
  font-family: var(--font-display);
  font-optical-sizing: auto;
  font-weight: 400;
  font-size: clamp(2.3rem, 1.35rem + 3.6vw, 4rem);
  line-height: 1.04;
  letter-spacing: -0.03em;
  color: var(--ink);
  text-wrap: balance;
  max-width: 18ch;
}

/* ── the teal reflection across the headline ──────────────────────────────
   A band of --brand-2 travelling through ink-coloured letters, clipped to the
   glyphs. Three things make it safe to do this to an <h1>:

   1 · The gradient is --ink at every stop except the narrow band, so the
       resting state IS the plain ink headline. Nothing depends on the
       animation running — no JS, reduced motion and a paused tab all show the
       same finished line the base rule would have painted.
   2 · The background REPEATS. With background-size 250% and the band at 47–51%
       of the image, the tile is 2.5× the element and only ever puts one band
       anywhere near it — but switching this to no-repeat would leave the far
       end of a two-line headline with no background at all, and text clipped
       to nothing is invisible text. Do not add no-repeat.
   3 · forced-colors backs the whole thing out, because a transparent text fill
       in a high-contrast theme is a blank headline.

   At 150% the band sits a full element-width off the left; at -50% it is off
   the right. The keyframe sweeps between those two in the first 24% of its
   period and holds for the rest, which is how a 1.7s glint repeats on a 7s
   cycle without a second animation to schedule it. Both ends of the loop show
   no band, so the wrap-around is invisible. */
@supports ((background-clip: text) or (-webkit-background-clip: text)) {
  .curtain__head {
    background-image: linear-gradient(105deg,
      var(--ink) 0%, var(--ink) 44%,
      var(--brand-2) 49.5%, var(--brand-2) 50.5%,
      var(--ink) 56%, var(--ink) 100%);
    background-size: 250% 100%;
    background-position: 150% 0;
    -webkit-background-clip: text;
    background-clip: text;
    -webkit-text-fill-color: transparent;
    color: transparent;
  }
}
@media (forced-colors: active) {
  .curtain__head {
    background-image: none;
    -webkit-text-fill-color: currentColor;
    color: CanvasText;
  }
}
@keyframes headSheen {
  0%   { background-position: 150% 0; }
  24%  { background-position: -50% 0; }
  100% { background-position: -50% 0; }
}

.curtain__sub {
  margin-top: clamp(1.15rem, 0.95rem + 0.7vw, 1.6rem);
  max-width: 56ch;
  font-size: clamp(1rem, 0.95rem + 0.3vw, 1.15rem);
  line-height: 1.62;
  color: var(--ink-2);
  font-style: italic;
  text-wrap: pretty;
}
/* Cost · Compliance · Efficiency, then the one word that lands. The separators
   are pseudo-elements so the three read as one phrase to a screen reader via
   the paragraph's aria-label rather than as three orphan words. */
/* The triad carries the display face and the accent — teal TEXT, so --brand-ink
   (6.3:1), never --brand (4.24:1). The separators are pseudo-elements and the
   spans are aria-hidden, so a screen reader gets the one phrase on the
   paragraph's aria-label rather than three orphan words. */
.curtain__words {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: baseline;
  gap: 0 0.95rem;
  margin-top: clamp(1.5rem, 1.2rem + 1vw, 2.1rem);
  font-family: var(--font-display);
  font-optical-sizing: auto;
  font-size: clamp(1.2rem, 1rem + 0.85vw, 1.75rem);
  font-weight: 400;
  letter-spacing: -0.012em;
  color: var(--brand-ink);
}
.curtain__words span + span::before {
  content: '·';
  margin-right: 0.95rem;
  color: var(--brand-border);
}

.curtain__cue {
  position: absolute;
  left: 50%; bottom: clamp(1.1rem, 0.8rem + 1vw, 1.9rem);
  translate: -50% 0;
  display: grid; place-items: center;
  width: 40px; height: 40px;
  border-radius: 50%;
  color: var(--ink-3);
  border: 1px solid var(--border);
  background: var(--surface);
  transition: color 0.2s var(--ease), border-color 0.2s var(--ease);
}
.curtain__cue:hover { color: var(--brand-ink); border-color: var(--brand-border); }

/* This selector read `.js .js .curtain__head` until the reflection was added,
   and `.js` is only ever on <html> — so it matched nothing and the headline was
   the one element in the curtain that never rose, while the sub and the three
   words below it did. Corrected to one `.js`, which is what the rest of the
   block uses and what the timing table in the README always described.

   The sheen starts as the rise finishes at 1.3s. Linear, because light moving
   at a constant rate is what reads as a reflection; easing it reads as a wipe. */
.js .curtain__head    { animation: curtainRise 0.8s var(--ease-out) 0.5s both,
                                   headSheen 7s linear 1.2s infinite; }
.js .curtain__words > * { display: inline-block; animation: curtainRise 0.6s var(--ease-out) both;
                          animation-delay: calc(1.15s + var(--w) * 0.14s); }
.js .curtain__sub     { animation: curtainRise 0.7s var(--ease-out) 0.85s both; }
.js .curtain__cue     { animation: cueIn 0.7s var(--ease-out) 2.2s both; }

@keyframes curtainRise { from { opacity: 0; transform: translateY(14px); } to { opacity: 1; transform: none; } }
@keyframes cueIn { from { opacity: 0; } to { opacity: 1; } }
@media (prefers-reduced-motion: no-preference) {
  .js .curtain__cue { animation: cueIn 0.7s var(--ease-out) 2.2s both, cueBob 2.6s var(--ease) 3s infinite; }
}
@keyframes cueBob { 0%, 100% { transform: translateY(0); } 50% { transform: translateY(4px); } }

/* Reduced motion: the composition, arrived at rather than performed. */
@media (prefers-reduced-motion: reduce) {
  .js .cubeanim__shell, .js .cubeanim__spoke { stroke-dashoffset: 0; animation: none; }
  .js .cubeanim__node, .js .cubeanim__apex,
  .js .curtain__head, .js .curtain__words > *,
  .js .curtain__sub, .js .curtain__cue {
    animation: none; opacity: 1; scale: 1; transform: none;
  }
}

/* --------------------------------------------------------------------------
   8 · Hero
   -------------------------------------------------------------------------- */
.hero {
  position: relative;
  background: var(--midnight);
  color: var(--td-1);
  padding-top: clamp(5.6rem, 4.5rem + 1.5vw, 6.7rem);
  padding-bottom: clamp(3rem, 2rem + 3vw, 4.5rem);
  overflow: hidden;
}
/* Faint isometric grid — the brand's relay geometry as ground texture */
.hero__grid {
  position: absolute;
  inset: 0;
  background-image:
    linear-gradient(to right, rgba(var(--ink-rgb), 0.045) 1px, transparent 1px),
    linear-gradient(to bottom, rgba(var(--ink-rgb), 0.045) 1px, transparent 1px);
  background-size: 74px 74px;
  mask-image: radial-gradient(ellipse 90% 70% at 70% 15%, #000 0%, transparent 78%);
  -webkit-mask-image: radial-gradient(ellipse 90% 70% at 70% 15%, #000 0%, transparent 78%);
  pointer-events: none;
}
.hero__glow {
  position: absolute;
  top: -18%; right: -8%;
  width: 46rem; height: 46rem;
  background: radial-gradient(circle, rgba(var(--brand-rgb), 0.07) 0%, transparent 64%);
  pointer-events: none;
}
.hero .container { position: relative; z-index: 1; }

.hero__head { max-width: 23ch; }
.hero h1 { margin-bottom: 0.9rem; }
.hero__sub { max-width: 70ch; }

.hero__actions {
  margin-top: clamp(1.6rem, 1.2rem + 1.2vw, 2.4rem);
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.25rem 2rem;
  flex-wrap: wrap;
}
@media (max-width: 720px) { .hero__actions { flex-direction: column; align-items: flex-start; } }

.hero__note {
  display: flex;
  align-items: center;
  gap: 0.55rem;
  font-family: var(--font-mono);
  font-size: 0.8rem;
  letter-spacing: 0.02em;
  color: var(--td-3);
}
.hero__note .dot {
  width: 5px; height: 5px; border-radius: 50%;
  background: var(--brand);
  box-shadow: 0 0 0 3px rgba(var(--brand-rgb), 0.18);
  flex: none;
}

/* --------------------------------------------------------------------------
   9 · Hero horizon — the signature visual
   -------------------------------------------------------------------------- */
.horizon {
  margin-top: clamp(1.4rem, 1.1rem + 1vw, 1.9rem);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--surface-2);
  padding: clamp(1rem, 0.8rem + 0.8vw, 1.35rem);
  position: relative;
}
.horizon__cap {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: 1rem;
  flex-wrap: wrap;
  margin-bottom: 0.7rem;
  padding-bottom: 0.5rem;
  border-bottom: 1px solid var(--surface-3);
}
.horizon__title {
  font-family: var(--font-mono);
  font-size: 0.8rem;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--td-2);
}
.horizon__legend {
  display: flex;
  gap: 1.25rem;
  font-family: var(--font-mono);
  font-size: 0.8rem;
  letter-spacing: 0.05em;
  color: var(--td-3);
  flex-wrap: wrap;
}
.horizon__legend span { display: inline-flex; align-items: center; gap: 0.4rem; }
.horizon__legend i {
  width: 7px; height: 7px; border-radius: 50%;
  display: inline-block; flex: none;
}
.legend-live { background: var(--brand); }
.legend-blind { background: transparent; border: 1px solid var(--border-3); }

/* Scroll wrapper for narrow screens */
.horizon__scroll { overflow-x: auto; overflow-y: hidden; margin-inline: -0.25rem; padding-inline: 0.25rem; }
.horizon__scroll::-webkit-scrollbar { height: 4px; }
.horizon__scroll::-webkit-scrollbar-thumb { background: var(--border-2); border-radius: 2px; }

.horizon__plot { min-width: 640px; position: relative; --track-label-w: 124px; }

/* Axis of lock points — shares the track's two-column grid so ticks stay aligned */
.horizon__axis {
  display: grid;
  grid-template-columns: var(--track-label-w) 1fr 3.9rem;
  gap: 0.9rem;
  padding-bottom: 0.35rem;
}
.horizon__reach {
  align-self: end;
  font-size: 0.8rem; font-weight: 700; letter-spacing: 0.07em;
  /* --ink-4 is 2.2:1 here. Rules and borders only — never text. */
  text-transform: uppercase; color: var(--ink-3); text-align: right;
}
.horizon__ticks {
  display: grid;
  grid-template-columns: repeat(8, 1fr);
}
.lock {
  text-align: center;
  position: relative;
  padding-inline: 0.15rem;
}
.lock__name {
  font-size: 0.8rem;
  font-weight: 500;
  color: var(--ink-2);
  line-height: 1.25;
  display: flex;
  align-items: flex-start;
  justify-content: center;
  min-height: 2.5em;          /* two lines, so every duration sits on one baseline */
  margin-bottom: 0.15rem;
}
.lock__when {
  font-family: var(--font-mono);
  font-size: 0.8rem;
  letter-spacing: 0.03em;
  color: var(--ink-3);
  display: block;
}

/* The two tracks */
.horizon__track {
  display: grid;
  grid-template-columns: var(--track-label-w) 1fr 3.9rem;
  align-items: center;
  gap: 0.9rem;
  padding-block: 0.46rem;
  border-top: 1px solid var(--rule-dark-2);
}
.horizon__track:last-of-type { border-bottom: 1px solid var(--rule-dark-2); }

.track__label {
  font-family: var(--font-mono);
  font-size: 0.8rem;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  text-align: right;
  line-height: 1.3;
}
.track__label b { display: block; font-weight: 600; letter-spacing: 0.11em; }
.track__label span { color: var(--ink-3); font-size: 0.8rem; letter-spacing: 0.04em; text-transform: none; }

/* Maturity ramp. Three real capability tiers reading as progression, then
   the accent. --tier cascades to the track's line, nodes, label and count. */
/* --tier paints the line and the nodes; --tier-ink paints the words. They are
   the same for every tier except CubeRight's, because --brand #0E8A7D is
   3.92:1 on --surface-2 — legal for a rule, a fail for 14px text. */
.horizon__track { --tier: var(--ink-3); --tier-ink: var(--ink-3); }
.track--pack   { --tier: #B23B2C; --tier-ink: #B23B2C; }
.track--wave   { --tier: #B45309; --tier-ink: #B45309; }
.track--tender { --tier: #1D4ED8; --tier-ink: #1D4ED8; }
.track--cr     { --tier: var(--brand); --tier-ink: var(--brand-ink); }
.horizon__track .track__label b { color: var(--tier-ink); }

.track__count {
  text-align: right;
  font-size: 0.85rem;
  /* the "/8" denominator — same --ink-4 trap as .horizon__reach */
  color: var(--ink-3);
  font-variant-numeric: tabular-nums;
  white-space: nowrap;
}
.track__count b { color: var(--tier-ink); font-weight: 700; font-size: 1.05rem; }

.track__rail {
  position: relative;
  height: 26px;
  display: grid;
  grid-template-columns: repeat(8, 1fr);
  align-items: center;
}
/* base line */
.track__rail::before {
  content: '';
  position: absolute;
  left: 0; right: 0; top: 50%;
  height: 1px;
  background: var(--rule-dark);
  transform: translateY(-50%);
}
/* live segment */
.track__live {
  position: absolute;
  top: 50%;
  height: 2px;
  transform: translateY(-50%);
  transform-origin: left center;
  border-radius: 2px;
}
.track__live { background: var(--tier); }
.track--pack   .track__live { left: 87.5%; right: 0; }
.track--wave   .track__live { left: 75%;   right: 0; }
.track--tender .track__live { left: 62.5%; right: 0; }
.track--cr .track__live {
  left: 0; right: 0;
  background: linear-gradient(90deg, var(--gold) 0%, var(--brand) 14%, var(--brand-solid) 100%);
}
.js .track__live { scale: 0 1; transition: scale 1.1s var(--ease-out) 0.25s; }
.js .is-revealed .track__live { scale: 1 1; }
.js .is-revealed .track--wave   .track__live { transition-delay: 0.38s; }
.js .is-revealed .track--tender .track__live { transition-delay: 0.51s; }
.js .is-revealed .track--cr     .track__live { transition-delay: 0.64s; }

.node {
  position: relative;
  justify-self: center;
  width: 9px; height: 9px;
  border-radius: 50%;
  z-index: 1;
}
.node--blind {
  border: 1px solid var(--border-3);
  background: var(--surface);
}
.node--live {
  background: var(--tier);
  box-shadow: 0 0 0 3px rgba(var(--ink-rgb), 0.06);
  opacity: 0;
  transform: scale(0.4);
  transition: opacity 0.4s var(--ease), transform 0.4s var(--ease-out);
}
.is-revealed .node--live { opacity: 1; transform: scale(1); }

/* Beacon = the gold apex. Exactly one. */
.beacon {
  position: absolute;
  left: 0; top: 50%;
  width: 13px; height: 13px;
  margin-left: -6.5px;
  transform: translateY(-50%);
  border-radius: 50%;
  background: radial-gradient(circle at 50% 35%, var(--amber-hi), var(--gold) 55%, #C6892C);
  box-shadow: 0 0 0 4px rgba(var(--gold-rgb), 0.22);
  z-index: 3;
}
.beacon::after {
  content: '';
  position: absolute;
  inset: 3.5px;
  border-radius: 50%;
  background: var(--surface);
}
@media (prefers-reduced-motion: no-preference) {
  .is-revealed .beacon { animation: pulse 3.4s var(--ease) infinite 1.4s; }
}
@keyframes pulse {
  0%, 100% { box-shadow: 0 0 0 4px rgba(var(--gold-rgb), 0.22); }
  50%      { box-shadow: 0 0 0 9px rgba(var(--gold-rgb), 0.10); }
}

.horizon__ends {
  display: grid;
  grid-template-columns: var(--track-label-w) 1fr 3.9rem;
  gap: 0.9rem;
  margin-top: 0.85rem;
  font-family: var(--font-mono);
  font-size: 0.8rem;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: var(--td-3);
}
.ends__in { display: flex; justify-content: space-between; }

/* --------------------------------------------------------------------------
   11b · The horizon, transposed for a phone
        On a wide screen the figure is eight decisions running left to right
        against four maturity tracks. On a phone that needed a 640px sideways
        scroll, which is the one gesture nobody wants while reading.

        This flips the axes: the eight decisions become rows down the page —
        which is the direction a phone already scrolls — and the four tracks
        become four narrow columns. **No second copy of the markup.** Every
        wrapper collapses with `display: contents` and its children are placed
        directly on one grid, so there is exactly one source of truth for the
        data and the desktop figure is untouched.

        The nodes are addressed with :nth-last-child because the CubeRight
        track carries two extra leading spans (.beacon and .track__live) that
        the others do not — counting from the end makes all four tracks agree.
   -------------------------------------------------------------------------- */
@media (max-width: 820px) {
  .horizon__scroll { overflow: visible; margin-inline: 0; padding-inline: 0; }
  .horizon__plot {
    min-width: 0;
    display: grid;
    /* minmax(0,1fr), not 1fr: a bare 1fr keeps a min-content floor, and
       "appointment" held the label column at 133px. On a 320px screen that
       pushed the CubeRight column past the plot and clipped it. */
    grid-template-columns: minmax(0, 1fr) repeat(4, 34px);
    align-items: center;
    column-gap: 0.35rem;
    /* clips the row rules, which are drawn wide from column 1 */
    overflow: hidden;
  }

  .horizon__axis, .horizon__ticks, .horizon__track, .track__rail { display: contents; }

  /* the axis's leading spacer and the sideways framing have no vertical sense.
     :first-child matters — .horizon__reach is also an aria-hidden div in here
     and it is the label for the totals row. */
  .horizon__axis > div[aria-hidden]:first-child, .horizon__ends { display: none; }
  /* nothing scrolls sideways any more, so the hint would be a lie. The extra
     .horizon outranks .tablehint.is-on for the no-JS case. */
  .horizon .horizon__scroll + .tablehint { display: none; }

  /* column 1 — the eight decisions, in time order down the page */
  .lock {
    grid-column: 1;
    display: grid;
    grid-template-columns: 26px 1fr;
    align-items: center;
    gap: 0 0.55rem;
    text-align: left;
    padding: 0.5rem 0.7rem 0.5rem 0;
  }
  .lock::after {
    content: '';
    position: absolute;
    left: 0; top: 0; width: 100vw; height: 1px;
    background: var(--rule-dark-2);
  }
  .lock__ic { width: 26px; height: 26px; margin: 0; grid-row: 1 / 3; }
  /* .lock__name is a centered flex box on desktop so every duration sits on a
     shared baseline. Vertically there is no such row to share, and a flex box
     ignores text-align — hence justify-content, not text-align, and no
     min-height forcing two lines onto a one-line name. */
  .lock__name {
    grid-column: 2;
    justify-content: flex-start;
    min-height: 0;
    margin-bottom: 0;
    font-size: 0.8rem;
    line-height: 1.25;
  }
  .lock__when { grid-column: 2; white-space: nowrap; }
  .lock:nth-child(1) { grid-row: 2; }
  .lock:nth-child(2) { grid-row: 3; }
  .lock:nth-child(3) { grid-row: 4; }
  .lock:nth-child(4) { grid-row: 5; }
  .lock:nth-child(5) { grid-row: 6; }
  .lock:nth-child(6) { grid-row: 7; }
  .lock:nth-child(7) { grid-row: 8; }
  .lock:nth-child(8) { grid-row: 9; }

  /* the four track headers, rotated so a 42px column can carry a real word */
  .track__label {
    grid-row: 1;
    writing-mode: vertical-rl;
    transform: rotate(180deg);
    text-align: left;
    justify-self: center;
    padding-bottom: 0.5rem;
    letter-spacing: 0.08em;
  }
  .track__label span { display: none; }

  /* the dots: row from position in the track, column from the track itself */
  .node:nth-last-child(8) { grid-row: 2; }
  .node:nth-last-child(7) { grid-row: 3; }
  .node:nth-last-child(6) { grid-row: 4; }
  .node:nth-last-child(5) { grid-row: 5; }
  .node:nth-last-child(4) { grid-row: 6; }
  .node:nth-last-child(3) { grid-row: 7; }
  .node:nth-last-child(2) { grid-row: 8; }
  .node:nth-last-child(1) { grid-row: 9; }

  .track--pack   .node, .track--pack   .track__label, .track--pack   .track__count { grid-column: 2; }
  .track--wave   .node, .track--wave   .track__label, .track--wave   .track__count { grid-column: 3; }
  .track--tender .node, .track--tender .track__label, .track--tender .track__count { grid-column: 4; }
  .track--cr     .node, .track--cr     .track__label, .track--cr     .track__count { grid-column: 5; }

  /* the rail's drawn line, its base hairline and the gold beacon are all
     horizontal ideas. The ::before matters: display:contents removes the
     rail's box but not its pseudo-element's, which would otherwise be
     positioned against .horizon__plot and strike right through the matrix. */
  .track__live, .beacon, .track__rail::before { display: none; }

  /* the reach totals close each column */
  .track__count {
    grid-row: 10;
    text-align: center;
    justify-self: center;
    padding-top: 0.6rem;
    width: 100%;
  }
  .horizon__reach {
    grid-row: 10; grid-column: 1;
    position: relative;
    padding-top: 0.6rem;
    text-align: left;
  }
  .horizon__reach::after {
    content: '';
    position: absolute;
    left: 0; top: 0; width: 100vw; height: 1px;
    background: var(--rule-dark-2);
  }
}

/* Below 380px the decorative icon is what stops "appointment" fitting on one
   line, so it goes. The row label carries the meaning; the icon never did. */
@media (max-width: 380px) {
  .horizon__plot { grid-template-columns: minmax(0, 1fr) repeat(4, 30px); }
  .lock { grid-template-columns: 1fr; }
  .lock__ic { display: none; }
  .lock__name, .lock__when { grid-column: 1; }
}

.horizon__read {
  margin-top: 1.1rem;
  padding-top: 1rem;
  border-top: 1px solid var(--surface-3);
  font-size: 0.92rem;
  line-height: 1.6;
  color: var(--td-2);
  max-width: 76ch;
}
.horizon__read b { color: var(--td-1); font-weight: 600; }

/* --------------------------------------------------------------------------
   10 · Stat band
   -------------------------------------------------------------------------- */
.band {
  border-top: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
  background: var(--surface-2);
  color: var(--ink);
}
.band__grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
}
.band__cell {
  padding: clamp(2rem, 1.4rem + 2vw, 3.25rem) clamp(1rem, 0.5rem + 2vw, 2.5rem);
  border-left: 1px solid var(--rule-dark-2);
}
.band__cell:first-child { border-left: 0; padding-left: 0; }
.band__cell:last-child { padding-right: 0; }

.band__k {
  font-family: var(--font-mono);
  font-size: 0.8rem;
  letter-spacing: 0.13em;
  text-transform: uppercase;
  color: var(--td-3);
  margin-bottom: 0.9rem;
}
.band__v {
  font-family: var(--font-display);
  font-optical-sizing: auto;
  font-size: clamp(1.95rem, 1.3rem + 2.1vw, 2.9rem);
  line-height: 1;
  font-weight: 400;
  letter-spacing: -0.03em;
  margin-bottom: 0.65rem;
}
.band__cell--hi .band__v { color: var(--brand-ink); }
.band__d { font-size: 0.902rem; color: var(--td-2); line-height: 1.5; }

@media (max-width: 780px) {
  .band__grid { grid-template-columns: 1fr; }
  .band__cell {
    border-left: 0;
    border-top: 1px solid var(--rule-dark-2);
    padding-inline: 0;
    padding-block: 1.75rem;
  }
  .band__cell:first-child { border-top: 0; padding-top: 2.25rem; }
}

/* --------------------------------------------------------------------------
   11 · Lock table (decision lock-in)
   -------------------------------------------------------------------------- */
.locktable { border-top: 1px solid var(--rule-light); }
.lockrow {
  display: grid;
  grid-template-columns: 1fr var(--lt-track) var(--lt-when) var(--lt-state);
  align-items: center;
  gap: var(--lt-gap);
  /* single-line rows now the notes live under the table — keep the rhythm
     tight so the bars read as one chart rather than twelve separate rows */
  padding: 0.72rem 0;
  border-bottom: 1px solid var(--rule-light-2);
  position: relative;
}
.lockrow__name {
  display: flex;
  align-items: flex-start;
  gap: 0.7rem;
  min-width: 0;
  font-size: 1.012rem;
  font-weight: 500;
}
.lockrow__when {
  font-family: var(--font-mono);
  font-size: 0.858rem;
  color: var(--tl-2);
  text-align: right;
  font-variant-numeric: tabular-nums;
}
.lockrow__state {
  font-family: var(--font-mono);
  font-size: 0.8rem;
  letter-spacing: 0.07em;
  text-transform: uppercase;
  text-align: right;
  color: var(--ink-3);
}
.lockrow--blind .lockrow__state { color: var(--flag); }
.lockrow--blind .lockrow__state::before {
  content: ''; display: inline-block;
  width: 6px; height: 6px; border-radius: 50%;
  border: 1px solid currentColor;
  margin-right: 0.45rem; vertical-align: 0.05em;
}
.lockrow--partial .lockrow__state { color: var(--amber-lo); }
.lockrow--partial .lockrow__state::before {
  content: ''; display: inline-block;
  width: 6px; height: 6px; border-radius: 50%;
  background: linear-gradient(90deg, currentColor 50%, transparent 50%);
  border: 1px solid currentColor;
  margin-right: 0.45rem; vertical-align: 0.05em;
}
.lockrow--known .lockrow__state { color: var(--brand-ink); }
.lockrow--known .lockrow__state::before {
  content: ''; display: inline-block;
  width: 6px; height: 6px; border-radius: 50%;
  background: currentColor;
  margin-right: 0.45rem; vertical-align: 0.05em;
}
.lockrow--flag { background: linear-gradient(90deg, var(--gold-soft-2), transparent 72%); }
.lockrow--flag .lockrow__name { font-weight: 600; }

.lockdivider {
  display: flex;
  align-items: center;
  gap: 1rem;
  padding: 1.4rem 0 0.9rem;
  font-family: var(--font-mono);
  font-size: 0.8rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--tl-3);
}
.lockdivider::after {
  content: ''; flex: 1; height: 1px;
  background: var(--rule-light);
}


/* --------------------------------------------------------------------------
   12b · The decision runway
        The lock table's own numbers, drawn into it. Each row gains a range bar
        on a logarithmic axis running from six weeks out to the moment of
        shipment, so the cascade from left to right down the table IS the
        argument — and the wave line falls where it actually falls, cutting the
        table in two. No new figures: every bar is the range already stated in
        the row beside it.
   -------------------------------------------------------------------------- */
.locktable {
  position: relative;
  --lt-track: 21rem;
  --lt-when: 6.2rem;
  --lt-state: 7rem;
  --lt-gap: 0.9rem;
  /* the track column's left edge and width, in the table's own coordinates —
     the axis, the bars, the blind zone and the wave line all read these two */
  --lt-off: calc(100% - var(--lt-state) - var(--lt-when) - var(--lt-track) - 2 * var(--lt-gap));
  --lt-w: var(--lt-track);
}

/* Everything committed before cartonization happens today. */
.locktable__zone {
  position: absolute;
  top: 0; bottom: 0;
  left: var(--lt-off);
  width: calc(0.378 * var(--lt-w));
  background: var(--flag);
  opacity: 0.04;
  pointer-events: none;
}
.locktable__wave {
  position: absolute;
  top: 0; bottom: 0;
  left: calc(var(--lt-off) + 0.378 * var(--lt-w));
  width: 0;
  border-left: 1px dashed var(--gold);
  pointer-events: none;
}
/* The label hangs off the bottom of the line, clear of the axis ticks. */
.locktable__wave > i {
  position: absolute;
  bottom: -1.35rem; left: 0;
  translate: -50% 0;
  font-family: var(--font-mono);
  font-size: 0.8rem;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--gold-ink);
  font-style: normal;
  white-space: nowrap;
}

.lockaxis {
  display: grid;
  grid-template-columns: 1fr var(--lt-track) var(--lt-when) var(--lt-state);
  gap: var(--lt-gap);
  align-items: end;
  padding-bottom: 0.55rem;
}
.lockaxis__keys { display: flex; flex-wrap: wrap; gap: 0.3rem 1rem; }
.lockkey {
  font-size: 0.8rem;
  color: var(--tl-3);
  display: inline-flex;
  align-items: center;
  gap: 0.42rem;
}
.lockkey::before { content: ''; width: 15px; height: 7px; border-radius: 999px; flex: none; }
.lockkey--blind::before { background: var(--flag); }
.lockkey--part::before  { background: var(--gold); }
.lockkey--known::before { background: var(--brand-solid); }

.lockaxis__scale {
  position: relative;
  height: 1.15rem;
  border-bottom: 1px solid var(--rule-light);
}
.lockaxis__scale > i {
  position: absolute;
  bottom: 0;
  left: calc(var(--x) * 100%);
  translate: -50% 0;
  font-family: var(--font-mono);
  font-size: 0.8rem;
  letter-spacing: 0;
  color: var(--tl-3);
  font-style: normal;
  white-space: nowrap;
  padding-bottom: 0.18rem;
}
.lockaxis__scale > i::after {
  content: '';
  position: absolute;
  left: 50%; bottom: -4px;
  width: 1px; height: 4px;
  background: var(--rule-light);
}
.lockaxis__scale > i:first-child { translate: 0 0; }
.lockaxis__scale > i:first-child::after { left: 0; }
.lockaxis__scale > i:last-child::after { left: auto; right: 0; }
.lockaxis__scale > i:last-child { translate: -100% 0; color: var(--tl-2); font-weight: 600; }

/* The bar. It reaches back from the moment of shipment to the moment the
   decision stops being changeable. */
.lockrow__rw { position: relative; height: 100%; min-height: 1.1rem; }
.lockrow__band {
  position: absolute;
  top: 50%;
  translate: 0 -50%;
  left: calc(var(--a) * 100%);
  right: calc(100% - var(--b) * 100%);
  min-width: 10px;
  height: 11px;
  border-radius: 999px;
  background: var(--band);
}
.lockrow--blind { --band: var(--flag); }
.lockrow--partial { --band: var(--gold); }
.lockrow--known { --band: var(--brand-solid); }
/* the two "Estimated" rows carry --blind for their state dot but are not blind */
.lockrow--blind.lockrow--flag { --band: var(--gold); }

.lockrow__ic {
  width: 22px; height: 22px; flex: none;
  margin-top: 0.05rem;
  --ic-top: #12A192; --ic-left: #0E8A7D; --ic-right: #085D53;
  --ic-deep: #06463E; --ic-flap: #0B7C6F; --ic-line: #FFFFFF;
  transition: transform 0.3s var(--ease-out);
}
.lockrow__ic svg { width: 100%; height: 100%; display: block; overflow: visible; }
.lockrow:hover .lockrow__ic { transform: translateY(-2px) scale(1.08); }
.lockrow__label { display: block; min-width: 0; }

/* The four rows that need a paragraph get a marker instead, and the paragraph
   goes under the table. Keeping them inline made those rows four to nine lines
   tall, which buried the bars in the rows either side of them. */
.lockref {
  font-family: var(--font-mono);
  /* 0.8rem, not an em fraction — a marker is still text and the site's floor
     is 14.08px. At 0.68em it rendered at 12.1px. */
  font-size: 0.8rem;
  font-weight: 600;
  color: var(--brand-ink);
  vertical-align: super;
  margin-left: 0.2em;
  font-variant-numeric: tabular-nums;
}
.locknotes {
  list-style: none;
  margin: 1.9rem 0 0;
  padding: 0;
  display: grid;
  gap: 0.65rem;
  max-width: 86ch;
}
.locknotes li {
  position: relative;
  padding-left: 1.6rem;
  font-size: 0.88rem;
  line-height: 1.58;
  color: var(--tl-3);
}
.locknotes strong { color: var(--tl-1); font-weight: 600; }
.lockref--key {
  position: absolute;
  left: 0; top: 0.1em;
  margin-left: 0;
  vertical-align: baseline;
  font-size: 0.8rem;
}

.lockfoot {
  margin-top: 1.2rem;
  font-size: 0.83rem;
  line-height: 1.6;
  color: var(--tl-3);
  max-width: 78ch;
}
.lockfoot em { font-style: italic; color: var(--tl-2); }

.js .lockrow__band { transform: scaleX(0); transform-origin: right center; }
.js .locktable.is-revealed .lockrow__band {
  transform: scaleX(1);
  transition: transform 0.55s var(--ease-out);
  transition-delay: calc(0.25s + var(--i) * 0.05s);
}
.js .locktable__zone, .js .locktable__wave { opacity: 0; }
.js .locktable.is-revealed .locktable__zone { opacity: 0.04; transition: opacity 0.5s var(--ease) 0.95s; }
.js .locktable.is-revealed .locktable__wave { opacity: 1; transition: opacity 0.5s var(--ease) 0.95s; }

@media (max-width: 1100px) { .locktable { --lt-track: 13rem; --lt-state: 6.2rem; } }

/* Narrow: the bar drops onto its own full-width line under the row, and the
   axis, blind zone and wave line switch to spanning the whole table. */
@media (max-width: 820px) {
  .locktable { --lt-off: 0px; --lt-w: 100%; }
  /* The label gets the full width so fewer of them wrap to three lines; the
     state and the range share the line beneath it; the bar sits under both. */
  .lockrow {
    grid-template-columns: 1fr auto;
    row-gap: 0.4rem;
  }
  .lockrow__name { grid-column: 1 / -1; grid-row: 1; font-size: 0.968rem; }
  .lockrow__state { grid-column: 1; grid-row: 2; text-align: left; }
  .lockrow__when { grid-column: 2; grid-row: 2; text-align: right; }
  .lockrow__rw { grid-column: 1 / -1; grid-row: 3; height: 11px; min-height: 0; }
  .lockaxis { grid-template-columns: 1fr; gap: 0.7rem; }
  .lockaxis__scale { order: 2; }
  .lockaxis__keys { order: 1; }
  .lockaxis > span:empty { display: none; }
  .lockaxis__scale > i:nth-child(2) { display: none; }   /* 1 d — collides with the wave label */

  /* The bar now spans the whole row, so one full-height rule would strike
     through the text. The wave marker moves inside each bar's own track. */
  .locktable__zone, .locktable__wave { display: none; }
  .lockrow__rw::before {
    content: '';
    position: absolute;
    left: 0; width: 37.8%;
    top: -3px; bottom: -3px;
    background: var(--flag);
    opacity: 0.055;
  }
  .lockrow__rw::after {
    content: '';
    position: absolute;
    left: 37.8%;
    top: -3px; bottom: -3px;
    border-left: 1px dashed var(--gold);
  }
  .lockaxis__scale { overflow: visible; }
  .lockaxis__scale > i.lockaxis__wave { display: block; color: var(--gold-ink); }
}
.lockaxis__wave { display: none; }

@media (prefers-reduced-motion: reduce) {
  .js .lockrow__band { transform: none; transition: none; }
  .js .locktable__zone { opacity: 0.04; }
  .js .locktable__wave { opacity: 1; }
}

/* Pull-quote used as section punctuation */
.pull {
  font-family: var(--font-display);
  font-optical-sizing: auto;
  font-size: clamp(1.32rem, 1.05rem + 1.35vw, 2rem);
  line-height: 1.33;
  font-weight: 400;
  letter-spacing: -0.02em;
  max-width: 30ch;
  text-wrap: balance;
}
.pull--wide { max-width: 42ch; }

.quote-block {
  border-left: 2px solid var(--gold);
  padding-left: clamp(1.25rem, 0.8rem + 1.5vw, 2.25rem);
}

/* --------------------------------------------------------------------------
   12 · Regulatory timeline
   -------------------------------------------------------------------------- */
.clock {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
  gap: 0;
  border-top: 1px solid var(--rule-dark);
}
.clock__item {
  padding: 1.9rem 1.5rem 1.9rem 0;
  border-right: 1px solid var(--rule-dark-2);
  position: relative;
}
.clock__item:last-child { border-right: 0; }
.clock__item + .clock__item { padding-left: 1.5rem; }
.clock__item::before {
  content: '';
  position: absolute;
  top: -1px;
  left: 0;
  width: 9px; height: 9px;
  border-radius: 50%;
  background: var(--surface);
  border: 1px solid var(--border-3);
  transform: translateY(-50%);
}
.clock__item + .clock__item::before { left: 1.5rem; }
.clock__item--now::before {
  background: var(--brand);
  border-color: var(--brand);
  box-shadow: 0 0 0 4px rgba(var(--brand-rgb), 0.15);
}
.clock__item--apex::before {
  background: var(--gold);
  border-color: var(--gold);
  box-shadow: 0 0 0 4px rgba(var(--gold-rgb), 0.22);
}
.clock__date {
  font-family: var(--font-mono);
  font-size: 0.8rem;
  letter-spacing: 0.08em;
  color: var(--brand-ink);
  margin-bottom: 0.7rem;
  display: flex;
  align-items: center;
  gap: 0.5rem;
}
.clock__item--apex .clock__date { color: var(--gold-ink); }
.clock__item--past .clock__date { color: var(--td-3); }
.clock__what { font-size: 0.99rem; font-weight: 500; line-height: 1.4; margin-bottom: 0.45rem; }
.clock__note { font-size: 0.8745rem; color: var(--td-3); line-height: 1.5; }

.status-tag {
  font-family: var(--font-mono);
  font-size: 0.8rem;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  padding: 0.15em 0.4em;
  border: 1px solid currentColor;
  border-radius: 2px;
  opacity: 0.85;
}

@media (max-width: 720px) {
  .clock { grid-template-columns: 1fr; }
  .clock__item, .clock__item + .clock__item {
    border-right: 0;
    border-bottom: 1px solid var(--rule-dark-2);
    padding: 1.5rem 0 1.5rem 1.5rem;
  }
  .clock__item::before, .clock__item + .clock__item::before { left: 0; top: 1.55rem; }
  .clock__item:last-child { border-bottom: 0; }
}

/* --------------------------------------------------------------------------
   13 · Method — six stages
   -------------------------------------------------------------------------- */
.stages {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  border-top: 1px solid var(--rule-light);
  border-left: 1px solid var(--rule-light);
}
.stage {
  padding: clamp(1.25rem, 0.9rem + 1.1vw, 1.75rem);
  border-right: 1px solid var(--rule-light);
  border-bottom: 1px solid var(--rule-light);
  position: relative;
  transition: background-color 0.3s var(--ease);
}
.stage:hover { background: var(--surface-2); }

/* One header line, not three stacked blocks. The icon, the number and the name
   used to occupy 154px of every card before a word of content; on a 3-up grid
   that was 300px of the section spent on furniture. */
.stage__head {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  margin-bottom: 0.85rem;
}
.stage__head::after {
  content: ''; flex: 1; height: 1px; background: var(--rule-light-2);
}
.stage__n {
  font-family: var(--font-mono);
  font-size: 0.8rem;
  letter-spacing: 0.1em;
  color: var(--ink-3);
  flex: none;
}
.stage__name { /* teal TEXT: --brand-ink (6.3:1). --brand is 4.24:1 and fails. */
  font-family: var(--font-mono);
  font-size: 0.9rem;
  font-weight: 600;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: var(--brand-ink);
  flex: none;
}
.stage__body { font-size: 0.9405rem; line-height: 1.54; color: var(--tl-2); }
.stage__body em { color: var(--tl-1); font-style: normal; font-weight: 500; }

/* The FORM stage carries the apex */
.stage--apex { background: var(--gold-soft-2); }
.stage--apex:hover { background: #F8EFDC; }
.stage--apex .stage__name { color: var(--gold-ink); }
.stage--apex::after {
  content: '';
  position: absolute;
  top: -1px; left: -1px;
  width: 34px; height: 2px;
  background: var(--gold);
}

@media (max-width: 900px) { .stages { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 560px) { .stages { grid-template-columns: 1fr; } }

/* --------------------------------------------------------------------------
   13b · The 320px floor
        A 320px screen (SE-class hardware) could not fit the lockup, the burger
        and two 22px gutters. Every page gained a 31px horizontal scroll.
        (The other half of that bug was the contact form's nowrap submit
        button; the form is gone, the .btn rule stays — it is general.)
        Nothing here changes anything above 380px.
   -------------------------------------------------------------------------- */
@media (max-width: 380px) {
  :root { --gutter: 1rem; }
  .lockup { gap: 0.5rem; }
  .lockup__type { gap: 0.45rem; }
  .lockup__parent { font-size: 0.8rem; letter-spacing: 0.1em; }
  .lockup__product { font-size: 0.9rem; }
  /* Two centered lines beat a button that sets the width of the whole page. */
  .btn { white-space: normal; text-align: center; }
}

/* --------------------------------------------------------------------------
   14 · Value bar — where the money is
   -------------------------------------------------------------------------- */
.valuebar { margin-top: 1rem; }
.valuebar__track {
  display: flex;
  height: 88px;
  border-radius: var(--radius);
  overflow: hidden;
  border: 1px solid var(--border);
}
.vseg {
  position: relative;
  display: flex;
  align-items: flex-end;
  /* No padding on the segment itself. With box-sizing: border-box a segment can
     never render narrower than its own padding, which pinned the 0.4%, 3.7% and
     6.3% slices to the same ~25px, pushed the bar 38px past its own track and
     made the proportions — the entire point of the graphic — untrue.
     The inset lives on the label instead. */
  min-width: 0;
  overflow: hidden;
  transform-origin: left center;
  scale: 0 1;
  transition: scale 1.1s var(--ease-out);
}
.is-revealed .vseg { scale: 1 1; }
.is-revealed .vseg:nth-child(2) { transition-delay: 0.09s; }
.is-revealed .vseg:nth-child(3) { transition-delay: 0.16s; }
.is-revealed .vseg:nth-child(4) { transition-delay: 0.22s; }
.is-revealed .vseg:nth-child(5) { transition-delay: 0.27s; }
.is-revealed .vseg:nth-child(6) { transition-delay: 0.31s; }

.vseg--freight { background: linear-gradient(160deg, var(--brand-solid), var(--brand-hover)); }
.vseg--pallet  { background: var(--brand-border); }
.vseg--void    { background: var(--brand-soft-2); }
.vseg--board   { background: var(--gold); }
.vseg--other   { background: var(--surface-3); }

.vseg__pct {
  padding: 0.7rem;
  font-family: var(--font-mono);
  font-size: 0.858rem;
  font-weight: 600;
  color: #FFFFFF;
  white-space: nowrap;
}
.vseg--board .vseg__pct { color: var(--on-amber); }
.vseg--pallet .vseg__pct, .vseg--void .vseg__pct { font-size: 0.8rem; }

.valuebar__keys {
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem 1.5rem;
  margin-top: 1.1rem;
}
.vkey {
  display: inline-flex;
  align-items: center;
  gap: 0.5rem;
  font-size: 0.858rem;
  color: var(--td-2);
}
.vkey i { width: 9px; height: 9px; border-radius: 2px; flex: none; }
.vkey b { font-family: var(--font-mono); font-weight: 500; color: var(--td-1); }

.callout {
  margin-top: 1.75rem;
  display: flex;
  gap: 0.9rem;
  align-items: flex-start;
  padding: 1.1rem 1.25rem;
  border: 1px solid var(--gold-border);
  border-left-width: 2px;
  border-left-color: var(--gold);
  border-radius: var(--radius);
  background: var(--gold-soft-2);
  font-size: 0.946rem;
  line-height: 1.6;
  color: var(--td-2);
}
.callout b { color: var(--td-1); font-weight: 600; }
.callout__i {
  flex: none;
  font-family: var(--font-mono);
  font-size: 0.8rem;
  letter-spacing: 0.1em;
  color: var(--gold-ink);
  text-transform: uppercase;
  padding-top: 0.2rem;
}
@media (max-width: 640px) {
  .callout { flex-direction: column; gap: 0.6rem; }
}

.sens {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 1px;
  background: var(--border);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
  margin-top: 2rem;
}
@media (max-width: 880px) { .sens { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 460px) { .sens { grid-template-columns: 1fr; } }
.sens__cell { background: var(--surface); padding: 1.25rem 1.35rem; }
.sens__k { font-size: 0.858rem; color: var(--td-2); margin-bottom: 0.5rem; }
.sens__v {
  font-family: var(--font-mono);
  font-size: 1.5rem;
  font-weight: 500;
  letter-spacing: -0.02em;
  color: var(--brand-ink);
}
.sens__cell--low .sens__v { color: var(--td-3); }

/* --------------------------------------------------------------------------
   15 · Delta table (measured)
   -------------------------------------------------------------------------- */
/* Wide tables scroll inside their own container so the page body never does.
   The hint appears only at widths where the table actually overflows. */
.deltawrap, .scorewrap { overflow-x: auto; }
.deltawrap::-webkit-scrollbar, .scorewrap::-webkit-scrollbar { height: 4px; }
.deltawrap::-webkit-scrollbar-thumb { background: var(--border-2); border-radius: 2px; }
.scorewrap::-webkit-scrollbar-thumb { background: var(--border-2); border-radius: 2px; }

.tablehint {
  display: none;
  margin-top: 0.7rem;
  font-family: var(--font-mono);
  font-size: 0.8rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--ink-3);
}
.section--dark .tablehint, .section--deep .tablehint { color: var(--ink-3); }
@media (max-width: 780px) { .tablehint { display: block; } }
/* site.js sets this on a hint whose scroller actually overflows, at any width —
   the score table needs it up to ~1150px, well above the 780px breakpoint. */
.tablehint.is-on { display: block; }
.tablehint.is-off { display: none; }

/* Narrow screens: hold the label column still, so a row scrolled sideways never
   becomes a line of bare numbers. The background must be opaque and must match
   the section the table sits on. */
@media (max-width: 780px) {
  .score thead th:first-child,
  .score tbody td:first-child,
  .score tfoot td:first-child,
  .delta thead th:first-child,
  .delta tbody td:first-child {
    position: sticky;
    left: 0;
    z-index: 1;
  }
  .score thead th:first-child,
  .score tbody td:first-child,
  .score tfoot td:first-child { background: var(--surface); }
  .delta thead th:first-child,
  .delta tbody td:first-child { background: var(--surface-2); }
  .delta tr.is-key td:first-child { background: var(--brand-soft); }
  .score tbody td:first-child,
  .score tfoot td:first-child,
  .delta tbody td:first-child { box-shadow: 1px 0 0 var(--rule-light-2); }
}

.deltawrap { overflow-x: auto; }
.delta { min-width: 560px; font-variant-numeric: tabular-nums; }
.delta thead th {
  font-family: var(--font-mono);
  font-size: 0.8rem;
  font-weight: 500;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: var(--td-3);
  text-align: right;
  padding: 0 0 0.6rem;
  border-bottom: 1px solid var(--rule-dark);
}
.delta thead th:first-child { text-align: left; }
.delta tbody td {
  padding: 0.34rem 0;
  line-height: 1.35;
  border-bottom: 1px solid var(--rule-dark-2);
  text-align: right;
  font-family: var(--font-mono);
  font-size: 0.946rem;
  color: var(--td-2);
}
.delta tbody td:first-child {
  text-align: left;
  font-family: var(--font-ui);
  font-size: 0.92rem;
  color: var(--td-1);
  font-weight: 450;
}
.delta .d-pct { color: var(--brand-ink); font-weight: 500; }
.delta tr.is-key td { background: var(--brand-soft); }
.delta tr.is-key td:first-child { font-weight: 600; }
.delta tr.is-key .d-pct { color: var(--brand-ink); font-weight: 600; font-size: 1.045rem; }
.delta tr.is-null td { color: var(--td-3); }
.delta tr.is-null .d-pct { color: var(--td-3); }
/* Inline, not stacked — a second line per row added ~90px of table height for
   a qualifier that reads perfectly well beside the label. */
.delta td small {
  font-family: var(--font-ui);
  font-size: 0.8rem;
  color: var(--ink-3);
  font-weight: 400;
  margin-left: 0.45rem;
}

/* --------------------------------------------------------------------------
   16 · Split feature (form-as-output)
   -------------------------------------------------------------------------- */
.split {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(2.5rem, 1.5rem + 4vw, 5.5rem);
  align-items: center;
}
.split--top { align-items: start; }
.split--radar { grid-template-columns: 1.15fr 1fr; }
@media (max-width: 880px) { .split--radar { grid-template-columns: 1fr; } }
@media (max-width: 880px) { .split { grid-template-columns: 1fr; } }

.coil {
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--surface-2);
  padding: clamp(1.25rem, 1rem + 1vw, 1.85rem);
}
.section--dark .coil, .section--deep .coil {
  border-color: var(--border);
  background: var(--surface-2);
}
.coil__head {
  display: flex; justify-content: space-between; align-items: baseline;
  gap: 1rem; flex-wrap: wrap;
  font-family: var(--font-mono);
  font-size: 0.8rem;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: var(--tl-3);
  padding-bottom: 0.9rem;
  margin-bottom: 1.25rem;
  border-bottom: 1px solid var(--rule-light-2);
}
.coil__fig {
  width: 100%; height: auto;
  /* Coil face tones. The winning form takes the accent; the rest recede. */
  --co-top:    #D6D9E0;  --co-wall:   #B4BAC6;  --co-hole:   #8B91A0;  --co-wind:   #FFFFFF;
  --co-top-w:  #12A192;  --co-wall-w: #0B7C6F;  --co-hole-w: #06463E;  --co-wind-w: #6FD9C9;
}

.claimlist { display: grid; gap: 0; margin-top: 0.5rem; }
.claim {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: 1rem;
  padding: 1.15rem 0;
  border-bottom: 1px solid var(--rule-light-2);
}
.section--dark .claim, .section--deep .claim { border-bottom-color: var(--rule-dark-2); }
.claim:first-child { border-top: 1px solid var(--rule-light-2); }
.section--dark .claim:first-child { border-top-color: var(--rule-dark-2); }
.claim__i {
  font-family: var(--font-mono);
  font-size: 0.8rem;
  color: var(--ink-3);
  padding-top: 0.2rem;
}
.section--dark .claim__i { color: var(--ink-3); }

/* A waypoint node, for lists that are a set rather than a sequence.
   Numbering these would assert an order the content does not have. */
.claim__i--node {
  width: 7px; height: 7px;
  border-radius: 50%;
  background: var(--teal);
  opacity: 0.55;
  margin-top: 0.62rem;
}
.section--dark .claim__i--node, .section--deep .claim__i--node {
  background: var(--teal-glow); opacity: 0.7;
}
.claim__t { font-size: 1.012rem; font-weight: 500; margin-bottom: 0.25rem; }
/* The half of a principle before the comma: accent, upright. --brand-ink and
   not --brand — this is 1.012rem, so small text at a 4.5:1 floor, and --brand
   is 4.24:1. The italic in these lines belongs to the word "just" alone,
   which is the pivot the sentence turns on. */
.claim__lead { color: var(--brand-ink); }
.claim__d { font-size: 0.935rem; color: var(--tl-2); line-height: 1.58; }
.section--dark .claim__d { color: var(--td-2); }

/* --------------------------------------------------------------------------
   17 · Stack-fit grid ("where it slots in")
   -------------------------------------------------------------------------- */
.fitgrid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  border-top: 1px solid var(--border);
  border-left: 1px solid var(--border);
  border-radius: var(--radius-lg);
  overflow: hidden;
}
.fit {
  padding: clamp(1.15rem, 0.9rem + 1vw, 1.6rem);
  border-right: 1px solid var(--border);
  border-bottom: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  gap: 0.5rem;
  background: var(--surface);
  transition: background-color 0.22s var(--ease);
}
.fit:hover { background: var(--brand-soft); }

.fit__ic {
  width: 28px; height: 28px;
  flex: none;
  --ic-top: #12A192; --ic-left: #0E8A7D; --ic-right: #085D53;
  --ic-deep: #06463E; --ic-flap: #0B7C6F; --ic-line: #FFFFFF;
  transition: transform 0.35s var(--ease-out);
}
.fit__ic svg { width: 100%; height: 100%; display: block; overflow: visible; }
.fit:hover .fit__ic { transform: translateY(-2px) scale(1.05); }

/* What each system actually gets back. The section's whole job is to answer
   "where does this sit in my stack" — naming the payload answers it twice. */
.fit__out {
  margin-top: auto;
  padding-top: 0.7rem;
  border-top: 1px solid var(--surface-3);
  font-size: 0.8rem;
  line-height: 1.42;
  color: var(--ink-3);
  font-variant-numeric: tabular-nums;
}
.fit__out span {
  display: inline-block;
  margin-right: 0.5rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--brand-ink);
}
.fit__out span::after { content: ' →'; font-weight: 500; }
/* Icon beside the title, not stacked above it — the same 60px-per-card saving
   the method stages got. */
.fit__head {
  display: flex; align-items: center; gap: 0.65rem;
  margin-bottom: 0.1rem;
}
.fit__t { font-size: 1.012rem; font-weight: 600; letter-spacing: -0.008em; }
.fit__d { font-size: 0.924rem; color: var(--tl-2); line-height: 1.54; flex: 1; }
@media (max-width: 900px) { .fitgrid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 560px) { .fitgrid { grid-template-columns: 1fr; } }

/* --------------------------------------------------------------------------
   18 · Scorecard (honest position)
   -------------------------------------------------------------------------- */
.scorewrap { overflow-x: auto; }
.score { min-width: 700px; }
.score th, .score td { padding: 0.8rem 0.7rem; }
.score thead th {
  font-family: var(--font-mono);
  font-size: 0.8rem;
  font-weight: 500;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--tl-3);
  text-align: center;
  border-bottom: 1px solid var(--rule-light);
  vertical-align: bottom;
}
.score thead th:first-child { text-align: left; width: 32%; }
.score thead th.is-us { color: var(--brand-ink); }
.score tbody td {
  text-align: center;
  border-bottom: 1px solid var(--rule-light-2);
  font-family: var(--font-mono);
  font-size: 0.946rem;
  color: var(--tl-2);
  font-variant-numeric: tabular-nums;
}
.score tbody td:first-child {
  text-align: left;
  font-family: var(--font-ui);
  font-size: 0.9735rem;
  color: var(--tl-1);
  font-weight: 450;
}
.score td.is-us { background: var(--brand-soft); color: var(--brand-ink); font-weight: 600; }
.score tfoot td {
  padding-top: 1.1rem;
  border-top: 1px solid var(--rule-light);
  font-family: var(--font-mono);
  font-size: 1.045rem;
  font-weight: 600;
  text-align: center;
  color: var(--tl-1);
}
.score tfoot td:first-child {
  text-align: left;
  font-family: var(--font-ui);
  font-size: 0.858rem;
  letter-spacing: 0.09em;
  text-transform: uppercase;
  color: var(--tl-3);
  font-weight: 500;
}
.score tfoot td.is-us { color: var(--brand-ink); background: var(--brand-soft-2); }

/* --------------------------------------------------------------------------
   18b · Radar — seven criteria against the market frontier
   -------------------------------------------------------------------------- */
.radar { margin: 0; }
.radar__svg { width: 100%; height: auto; overflow: visible; }

.radar__grid polygon {
  stroke: var(--surface-3);
  stroke-width: 1;
}
.radar__ring-outer { stroke: var(--border-2) !important; }
.radar__spokes line { stroke: var(--surface-3); stroke-width: 1; }

.radar__field {
  fill: none;
  stroke: var(--ink-2);
  stroke-width: 2;
  stroke-dasharray: 6 4.5;
  stroke-linejoin: round;
}
.radar__cr {
  fill: rgba(var(--brand-rgb), 0.14);
  stroke: var(--brand);
  stroke-width: 2;
  stroke-linejoin: round;
}
.radar__dots circle { fill: var(--brand); }

/* Best-of-field markers: a ring, so a CubeRight dot underneath still reads
   on the axes where the two tie. */
.radar__lead circle { fill: var(--surface); stroke-width: 2.4; }

.radar__cats {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(190px, 1fr));
  gap: 0.35rem 1rem;
  width: 100%;
  margin-top: 0.35rem;
  padding-top: 0.7rem;
  border-top: 1px dashed var(--border);
}
.cat {
  display: flex; align-items: center; gap: 0.5rem;
  font-size: 0.84rem; color: var(--ink-2); line-height: 1.35;
}
.cat i {
  width: 9px; height: 9px; border-radius: 50%; flex: none;
  border: 2.2px solid var(--c);
  background: var(--surface);
}

.radar__labels text {
  font-family: var(--font-ui);
  font-size: 11.5px;
  font-weight: 500;
  fill: var(--tl-2);
}
.radar__v {
  font-family: var(--font-mono);
  font-weight: 600;
  fill: var(--brand-ink);
}

/* Gated on .js: without scripting the polygons must render immediately,
   or the chart draws its grid and no data. */
.radar__series { transform-origin: 260px 160px; }
.js .radar__series {
  opacity: 0;
  transform: scale(0.86);
  transition: opacity 0.7s var(--ease-out) 0.1s, transform 0.8s var(--ease-out) 0.1s;
}
.js .is-revealed .radar__series { opacity: 1; transform: none; }

.radar__legend {
  display: flex;
  flex-wrap: wrap;
  gap: 0.55rem 1.4rem;
  margin-top: 0.5rem;
  padding-top: 1.1rem;
  border-top: 1px solid var(--rule-light-2);
}
.rkey {
  display: flex;
  align-items: center;
  gap: 0.6rem;
  font-size: 0.88rem;
  color: var(--tl-2);
  line-height: 1.4;
}
.rkey i { width: 16px; height: 0; flex: none; }
.rkey--cr i { border-top: 3px solid var(--brand); }
.rkey--field i { border-top: 2px dashed var(--ink-2); }

@media (max-width: 520px) {
  .radar__labels text { font-size: 13px; }
}

/* --------------------------------------------------------------------------
   19 · Product screens
   -------------------------------------------------------------------------- */
.shots {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: clamp(1rem, 0.7rem + 1vw, 1.5rem);
}
.shot { margin: 0; display: flex; flex-direction: column; }
.shot--wide { grid-column: 1 / -1; }

.shot__chrome {
  display: flex;
  align-items: center;
  gap: 0.75rem;
  padding: 0.6rem 0.85rem;
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-bottom: 0;
  border-radius: var(--radius) var(--radius) 0 0;
}
.shot__dots { display: flex; gap: 5px; flex: none; }
.shot__dots i {
  width: 7px; height: 7px; border-radius: 50%;
  background: var(--border-3);
}
.shot__label {
  font-family: var(--font-mono);
  font-size: 0.8rem;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--td-3);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

/* Placeholder frame. Replace the whole element with <img class="shot__img">
   at the same aspect ratio to drop in a real capture. */
.shot__frame {
  position: relative;
  aspect-ratio: 4 / 3;
  border: 1px solid var(--rule-dark);
  border-radius: 0 0 var(--radius) var(--radius);
  background-color: var(--canvas);
  background-image:
    linear-gradient(to right, var(--surface-3) 1px, transparent 1px),
    linear-gradient(to bottom, var(--surface-3) 1px, transparent 1px);
  background-size: 34px 34px;
  display: grid;
  place-items: center;
}
.shot__frame--wide { aspect-ratio: 21 / 9; }

.shot__img {
  width: 100%;
  height: auto;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  border: 1px solid var(--rule-dark);
  border-radius: 0 0 var(--radius) var(--radius);
}
.shot--wide .shot__img { aspect-ratio: 21 / 9; }

/* Motion on the captures — an extension of the existing reveal/cascade, not a second system.
   The container already carries [data-reveal][data-cascade], so each figure is staggered in by
   the rules in §24. These add two things on top, both deliberately small:

   1. The capture SETTLES. It arrives fractionally enlarged and eases back to true as its figure
      reveals, so the screen reads as coming into focus rather than sliding in flat. The scale is
      1.5% — enough to feel, not enough to notice.
   2. It LIFTS on hover. A real product screen should look like something you could step into.

   No keyframes, no loop, nothing ambient. `object-fit: cover` on an exactly-matched aspect ratio
   means the scale never crops anything real. Both are inert without JS and both stop entirely
   under prefers-reduced-motion, matching the rest of the page. */
.js .shot__img {
  transform: scale(1.015);
  transform-origin: center;
  transition: transform 0.9s var(--ease-out), box-shadow 0.35s var(--ease-out);
  will-change: transform;
}
.js [data-cascade].is-revealed .shot__img { transform: scale(1); }

.shot { transition: transform 0.35s var(--ease-out); }
.shot:hover { transform: translateY(-3px); }
.shot:hover .shot__img {
  transform: scale(1.006);
  box-shadow: 0 14px 34px -18px rgb(16 20 47 / 0.30);
}

html:not(.js) .shot__img { transform: none; }

@media (prefers-reduced-motion: reduce) {
  .shot, .shot__img, .js .shot__img { transition: none; transform: none; }
  .shot:hover { transform: none; }
  .shot:hover .shot__img { transform: none; box-shadow: none; }
}

.shot__pending {
  font-family: var(--font-mono);
  font-size: 0.8rem;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-3);
  border: 1px dashed var(--border-2);
  border-radius: 2px;
  padding: 0.4em 0.8em;
}

.shot__cap {
  font-size: 0.902rem;
  line-height: 1.55;
  color: var(--td-3);
  padding-top: 0.9rem;
}
.shot--wide .shot__cap { font-size: 0.9625rem; max-width: 62ch; }

@media (max-width: 860px) {
  .shots { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 560px) {
  .shots { grid-template-columns: 1fr; }
  .shot__frame--wide { aspect-ratio: 16 / 9; }
}

/* --------------------------------------------------------------------------
   19b · Product surface
   -------------------------------------------------------------------------- */
/* Explicit column counts that divide the 8 cells evenly — auto-fit leaves
   an orphan cell whose gap shows through as a stray rule-colored block. */
.specs {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 1px;
  background: var(--border);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  overflow: hidden;
}
@media (max-width: 900px) { .specs { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 480px) { .specs { grid-template-columns: 1fr; } }
.spec {
  background: var(--surface);
  padding: 1.35rem 1.4rem;
  transition: background-color 0.22s var(--ease);
}
.spec:hover { background: var(--gold-soft); }   /* #FFFDF8 — a warm wash, so the badge still reads against it */

/* Bare isometric icons, exactly as .stage__ic and .fit__ic carry them — no
   plinth behind them. Gold rather than teal, and the one place on the site
   where gold is not "the computed optimum": the product section is what the
   site is selling, so the eight capabilities carry the accent as a set. See
   README rule 3 and the exception recorded under it.
   Inline with the label, not stacked above it, so the grid gains ~10px of
   height rather than a whole row per box. */
.spec__head {
  display: flex;
  align-items: center;
  gap: 0.7rem;
  margin-bottom: 0.75rem;
}
.spec__ic {
  flex: none;
  width: 32px; height: 32px;
  --ic-top: #EFC98A; --ic-left: #E3AC49; --ic-right: #B8862F;
  --ic-deep: #8A6516; --ic-flap: #E3AC49; --ic-line: #FFFDF8;
  transition: transform 0.35s var(--ease-out);
}
.spec__ic svg { width: 100%; height: 100%; display: block; overflow: visible; }
.spec:hover .spec__ic { transform: translateY(-3px) scale(1.06); }

.spec__t {
  font-family: var(--font-mono);
  font-size: 0.8rem;
  letter-spacing: 0.11em;
  text-transform: uppercase;
  color: var(--brand-ink);
}
.spec__d { font-size: 0.913rem; line-height: 1.55; color: var(--td-2); }

/* --------------------------------------------------------------------------
   21 · Footer
   -------------------------------------------------------------------------- */
.footer {
  background: var(--surface-2);
  color: var(--ink);
  padding-block: clamp(3rem, 2rem + 3vw, 4.5rem) 2.5rem;
  border-top: 1px solid var(--rule-dark-2);
}
.footer__top {
  display: grid;
  grid-template-columns: 1.4fr repeat(3, minmax(0, 1fr));
  gap: 2.5rem;
  padding-bottom: 3rem;
  border-bottom: 1px solid var(--rule-dark-2);
}
@media (max-width: 860px) {
  .footer__top { grid-template-columns: 1fr 1fr; gap: 2rem; }
  .footer__brand { grid-column: 1 / -1; }
}
.footer__brand .lockup { color: var(--td-1); margin-bottom: 1.1rem; }
.footer__blurb { font-size: 0.935rem; color: var(--td-3); line-height: 1.6; max-width: 34ch; }
.footer__col h4 {
  font-family: var(--font-mono);
  font-size: 0.8rem;
  font-weight: 500;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--ink-3);
  margin-bottom: 1.1rem;
}
.footer__col ul { list-style: none; padding: 0; display: grid; gap: 0.65rem; }
.footer__col a {
  font-size: 0.9405rem;
  color: var(--td-2);
  transition: color 0.2s var(--ease);
}
.footer__col a:hover { color: var(--brand-ink); }
.footer__bot {
  display: flex;
  justify-content: space-between;
  gap: 1.5rem;
  flex-wrap: wrap;
  padding-top: 1.75rem;
  font-family: var(--font-mono);
  font-size: 0.8rem;
  letter-spacing: 0.03em;
  color: var(--ink-3);
}

/* --------------------------------------------------------------------------
   22 · Reveal on scroll
   -------------------------------------------------------------------------- */
/* Scoped to .js so the page is fully visible if scripting is unavailable
   or the bundle fails — content must never depend on JS to be readable. */
.js [data-reveal] {
  opacity: 0;
  transform: translateY(16px);
  transition: opacity 0.75s var(--ease-out), transform 0.75s var(--ease-out);
}
.js [data-reveal].is-revealed { opacity: 1; transform: none; }
.js [data-reveal][data-delay="1"] { transition-delay: 0.08s; }
.js [data-reveal][data-delay="2"] { transition-delay: 0.16s; }
.js [data-reveal][data-delay="3"] { transition-delay: 0.24s; }

/* Same reasoning for the animated figures: full state is the default. */
html:not(.js) .track--cr .track__live,
html:not(.js) .vseg { scale: 1 1; }
html:not(.js) .node--live { opacity: 1; transform: none; }

@media (prefers-reduced-motion: reduce) {
  .js [data-reveal] { opacity: 1; transform: none; transition: none; }
  .js .radar__series { opacity: 1; transform: none; transition: none; }
  .track--cr .track__live { scale: 1 1; transition: none; }
  .node--live { opacity: 1; transform: none; transition: none; }
  .vseg { scale: 1 1; transition: none; }
  .btn, .btn svg, .nav { transition: none; }
}

/* --------------------------------------------------------------------------
   23 · Utilities
   -------------------------------------------------------------------------- */
.stack-1 > * + * { margin-top: 0.6rem; }
.stack-2 > * + * { margin-top: 1.1rem; }
.stack-3 > * + * { margin-top: 1.75rem; }
.stack-4 > * + * { margin-top: 2.5rem; }
.mt-1 { margin-top: 1rem; }
.mt-2 { margin-top: 1.75rem; }
.mt-3 { margin-top: 2.5rem; }
.mt-4 { margin-top: 3.5rem; }
.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;
}
.rule { height: 1px; background: var(--rule-light); border: 0; }
.section--dark .rule, .section--deep .rule { background: var(--rule-dark); }

/* ══════════════════════════════════════════════════════════════════════════
   24 · Isometric lock icons
   ══════════════════════════════════════════════════════════════════════════ */
.lock__ic {
  display: block;
  width: 31px; height: 31px;
  margin: 0 auto 0.3rem;
  /* Face tones for the sprite. One accent, three depths. */
  --ic-top:   var(--brand-2);
  --ic-left:  var(--brand);
  --ic-right: var(--brand-hover);
  --ic-deep:  #06463E;
  --ic-flap:  var(--brand-solid);
  --ic-line:  #FFFFFF;
  transition: transform 0.5s var(--ease-out), filter 0.4s var(--ease);
}
.lock__ic svg { width: 100%; height: 100%; display: block; overflow: visible; }

/* Pack is the one that already happens today — render it spent, not live. */
.lock:last-child .lock__ic {
  --ic-top:   var(--border-3);
  --ic-left:  var(--ink-4);
  --ic-right: #8B91A0;
  --ic-deep:  #767C8C;
  --ic-flap:  var(--border-3);
}

/* Staged entrance, left to right along the timeline. */
.js .lock__ic { opacity: 0; transform: translateY(9px) scale(0.9); }
.js .is-revealed .lock__ic { opacity: 1; transform: none; }
.js .is-revealed .horizon__ticks .lock:nth-child(1) .lock__ic { transition-delay: 0.10s; }
.js .is-revealed .horizon__ticks .lock:nth-child(2) .lock__ic { transition-delay: 0.18s; }
.js .is-revealed .horizon__ticks .lock:nth-child(3) .lock__ic { transition-delay: 0.26s; }
.js .is-revealed .horizon__ticks .lock:nth-child(4) .lock__ic { transition-delay: 0.34s; }
.js .is-revealed .horizon__ticks .lock:nth-child(5) .lock__ic { transition-delay: 0.42s; }
.js .is-revealed .horizon__ticks .lock:nth-child(6) .lock__ic { transition-delay: 0.50s; }
.js .is-revealed .horizon__ticks .lock:nth-child(7) .lock__ic { transition-delay: 0.58s; }
.js .is-revealed .horizon__ticks .lock:nth-child(8) .lock__ic { transition-delay: 0.66s; }

.lock:hover .lock__ic { transform: translateY(-3px) scale(1.06); }

/* ══════════════════════════════════════════════════════════════════════════
   25 · Adoption ladder
   ══════════════════════════════════════════════════════════════════════════ */
.ladder {
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--surface);
  overflow: hidden;
}
.ladder__head {
  padding: clamp(1.5rem, 1.1rem + 1.4vw, 2.1rem);
  border-bottom: 1px solid var(--border);
  background: var(--brand-soft);
}
.ladder__sub { margin-top: 0.6rem; color: var(--ink-2); max-width: 62ch; font-size: 0.95rem; }

.ladder__steps { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(3, 1fr); }
.rung {
  display: grid;
  /* number · title · body · badge. The body takes the slack so the three
     badges land on one line however unequal the three descriptions are. */
  grid-template-rows: auto auto 1fr auto;
  gap: 0.45rem;
  padding: clamp(1.2rem, 0.9rem + 1vw, 1.6rem);
  border-right: 1px solid var(--border);
  position: relative;
}
.rung:last-child { border-right: 0; }
.rung__n {
  font-size: 0.8rem; font-weight: 600; letter-spacing: 0.1em;
  color: var(--brand-ink); font-variant-numeric: tabular-nums;
}
.rung__t { font-size: 1.08rem; font-weight: 600; letter-spacing: -0.016em; }
.rung__d { font-size: 0.924rem; line-height: 1.54; color: var(--ink-2); }
.rung__d strong { color: var(--ink); font-weight: 600; }
/* The cost of entry at each rung. These were content-width chips floating at
   whatever height their description happened to end at — three different
   rectangles at three different altitudes. They are now one row: full width of
   the rung, equal height, bottom-aligned, each carrying the isometric figure
   for how deeply it touches your stack. */
.rung__w {
  align-self: end;
  margin-top: 0.8rem;
  display: flex;
  align-items: center;
  gap: 0.6rem;
  min-height: 3.15rem;
  padding: 0.5rem 0.75rem;
  font-size: 0.8rem; font-weight: 600; letter-spacing: 0.07em; text-transform: uppercase;
  color: var(--brand-ink);
  background: var(--brand-soft);
  border: 1px solid var(--brand-border);
  border-radius: var(--radius);
  transition: background-color 0.22s var(--ease), border-color 0.22s var(--ease);
}
.rung__ic {
  width: 34px; height: 34px; flex: none;
  --ic-top: #12A192; --ic-left: #0E8A7D; --ic-right: #085D53;
  --ic-deep: #06463E; --ic-line: #FFFFFF;
  transition: transform 0.35s var(--ease-out);
}
.rung:hover .rung__w { background: var(--brand-soft-2); border-color: var(--brand); }
.rung:hover .rung__ic { transform: translateY(-2px) scale(1.06); }
/* The rail that runs through the three rungs — the ladder made visible. */
.rung::before {
  content: '';
  position: absolute;
  left: 0; top: 0; height: 3px;
  width: 100%;
  background: var(--brand);
  transform-origin: left;
  scale: 0 1;
  transition: scale 0.7s var(--ease-out);
}
.rung:nth-child(1)::before { opacity: 1; }
.rung:nth-child(2)::before { opacity: 0.55; }
.rung:nth-child(3)::before { opacity: 0.28; }
.is-revealed .rung::before { scale: 1 1; }
.is-revealed .rung:nth-child(2)::before { transition-delay: 0.16s; }
.is-revealed .rung:nth-child(3)::before { transition-delay: 0.32s; }

@media (max-width: 860px) {
  .ladder__steps { grid-template-columns: 1fr; }
  .rung { border-right: 0; border-bottom: 1px solid var(--border); }
  .rung:last-child { border-bottom: 0; }
}

/* ══════════════════════════════════════════════════════════════════════════
   26 · Motion — one deliberate moment per section
   ══════════════════════════════════════════════════════════════════════════ */

/* Scroll progress, hairline under the nav. */
.progress {
  position: fixed; inset: 0 0 auto 0; height: 2px; z-index: 101;
  background: var(--brand);
  transform-origin: left;
  transform: scaleX(var(--p, 0));
  pointer-events: none;
}

/* Apple-style pinning: the figure holds while its argument scrolls past. */
@media (min-width: 881px) {
  .split--radar .radar,
  .stickycol { position: sticky; top: 114px; align-self: start; }
}

/* Staggered cascade for grids of cards. */
.js [data-cascade] > * { opacity: 0; transform: translateY(18px); }
.js [data-cascade].is-revealed > * {
  opacity: 1; transform: none;
  transition: opacity 0.6s var(--ease-out), transform 0.6s var(--ease-out);
}
.js [data-cascade].is-revealed > *:nth-child(1) { transition-delay: 0.00s; }
.js [data-cascade].is-revealed > *:nth-child(2) { transition-delay: 0.07s; }
.js [data-cascade].is-revealed > *:nth-child(3) { transition-delay: 0.14s; }
.js [data-cascade].is-revealed > *:nth-child(4) { transition-delay: 0.21s; }
.js [data-cascade].is-revealed > *:nth-child(5) { transition-delay: 0.28s; }
.js [data-cascade].is-revealed > *:nth-child(6) { transition-delay: 0.35s; }
.js [data-cascade].is-revealed > *:nth-child(7) { transition-delay: 0.42s; }
.js [data-cascade].is-revealed > *:nth-child(8) { transition-delay: 0.49s; }

/* Lock table: rows arrive in sequence, so the reader watches the horizon
   fill up rather than meeting a wall of twelve rows. */
.js .locktable[data-cascade].is-revealed > *:nth-child(n+9) { transition-delay: 0.56s; }

/* Regulatory clock: the rule draws through the milestones. */
.clock { position: relative; }
.clock::after {
  content: '';
  position: absolute; left: 0; top: -1px; height: 1px; width: 100%;
  background: var(--brand);
  transform-origin: left;
  scale: 0 1;
}
.js .clock.is-revealed::after { scale: 1 1; transition: scale 1.4s var(--ease-out) 0.15s; }

/* Radar: the outline draws, then the fill arrives. */
.js .radar__cr { stroke-dasharray: 760; stroke-dashoffset: 760; fill-opacity: 0; }
.js .is-revealed .radar__cr {
  stroke-dashoffset: 0;
  fill-opacity: 1;
  transition: stroke-dashoffset 1.5s var(--ease-out) 0.2s, fill-opacity 0.7s var(--ease) 1.1s;
}
/* Dashed by design — fade it in rather than draw it, or the dash is lost. */
.js .radar__field, .js .radar__lead { opacity: 0; }
.js .is-revealed .radar__field { opacity: 1; transition: opacity 0.7s var(--ease) 1.0s; }
.js .is-revealed .radar__lead  { opacity: 1; transition: opacity 0.6s var(--ease) 1.35s; }

/* Coil sweep: the engine searching, then landing on the optimum. */
.js .coil__fig .sweep-form { opacity: 0; transform: scale(0.55); transform-origin: center; }
.js .is-revealed .coil__fig .sweep-form {
  opacity: 1; transform: none;
  transition: opacity 0.4s var(--ease), transform 0.55s var(--ease-out);
}
.js .is-revealed .coil__fig .sweep-form:nth-of-type(1) { transition-delay: 0.10s; }
.js .is-revealed .coil__fig .sweep-form:nth-of-type(2) { transition-delay: 0.22s; }
.js .is-revealed .coil__fig .sweep-form:nth-of-type(3) { transition-delay: 0.34s; }
.js .is-revealed .coil__fig .sweep-form:nth-of-type(4) { transition-delay: 0.46s; }
.js .is-revealed .coil__fig .sweep-form:nth-of-type(5) { transition-delay: 0.58s; }
.js .coil__fig .sweep-apex { opacity: 0; transform: scale(0.4); transform-origin: 290px 132px; }
.js .is-revealed .coil__fig .sweep-apex {
  opacity: 1; transform: none;
  transition: opacity 0.45s var(--ease) 0.85s, transform 0.6s var(--ease-out) 0.85s;
}

/* Counters hold their width while the digits run. */
.counting { font-variant-numeric: tabular-nums; }

@media (prefers-reduced-motion: reduce) {
  .js [data-cascade] > * { opacity: 1; transform: none; transition: none; }
  .js .lock__ic { opacity: 1; transform: none; }
  .js .clock.is-revealed::after { scale: 1 1; transition: none; }
  .js .radar__cr { stroke-dashoffset: 0; fill-opacity: 1; transition: none; }
  .js .radar__field, .js .radar__lead { opacity: 1; transition: none; }
  .js .coil__fig .sweep-form, .js .coil__fig .sweep-apex { opacity: 1; transform: none; transition: none; }
  .rung::before { scale: 1 1; transition: none; }
  .split--radar .radar, .stickycol { position: static; }
  .progress { display: none; }
}

/* ══════════════════════════════════════════════════════════════════════════
   27 · Radar comparison picker
   ══════════════════════════════════════════════════════════════════════════ */
.radar-pick { margin-bottom: 1.4rem; }
.radar-pick__lab {
  display: block;
  font-size: 0.8rem; font-weight: 600; letter-spacing: 0.09em;
  text-transform: uppercase; color: var(--ink-3);
  margin-bottom: 0.7rem;
}
.radar-pick__set { display: flex; flex-wrap: wrap; gap: 0.45rem; }

.pick {
  display: inline-flex; align-items: center; gap: 0.5rem;
  font-family: var(--font);
  font-size: 0.85rem; font-weight: 500;
  color: var(--ink-2);
  background: var(--surface);
  border: 1px solid var(--border-2);
  border-radius: var(--radius);
  padding: 0.45rem 0.8rem;
  cursor: pointer;
  transition: border-color 0.18s var(--ease), background-color 0.18s var(--ease),
              color 0.18s var(--ease);
}
.pick i {
  width: 9px; height: 9px; border-radius: 50%; flex: none;
  border: 2.2px solid var(--c); background: var(--surface);
}
.pick:hover { border-color: var(--border-3); background: var(--surface-2); color: var(--ink); }
.pick.is-on {
  border-color: var(--brand); background: var(--brand-soft);
  color: var(--brand-ink); font-weight: 600;
}

/* Comparator value beside CubeRight's, in the holder's color. */
.radar__sep { fill: var(--ink-4); }
.radar__c { font-weight: 600; }
.rkey__c {
  font-variant-numeric: tabular-nums;
  font-weight: 700;
  margin-left: 0.15rem;
}
.rkey--cr .rkey__c { color: var(--brand-ink); }

/* Selected column in the score table follows the picker. */
.score td.is-cmp, .score th.is-cmp { background: var(--surface-2); }
.score tfoot td.is-cmp { background: var(--surface-3); color: var(--ink); }
.score .is-cmp { transition: background-color 0.25s var(--ease); }

@media (max-width: 560px) {
  .pick { font-size: 0.8rem; padding: 0.4rem 0.65rem; }
}

/* ══════════════════════════════════════════════════════════════════════════
   28 · Value levers — the money section, made physical
   ══════════════════════════════════════════════════════════════════════════ */
.levers {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 1px;
  background: var(--border);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  overflow: hidden;
  margin-top: 1.5rem;
}
.lever {
  background: var(--surface);
  padding: 1.4rem 1.15rem 1.25rem;
  display: flex; flex-direction: column; gap: 0.5rem;
}
.lever__ic {
  width: 44px; height: 44px; margin-bottom: 0.35rem;
  --ic-top: #D6D9E0; --ic-left: #B4BAC6; --ic-right: #8B91A0;
  --ic-deep: #767C8C; --ic-flap: #C3C7D1; --ic-line: #FFFFFF;
}
.lever__ic svg { width: 100%; height: 100%; display: block; overflow: visible; }
.lever__v {
  font-family: var(--font-display);
  font-optical-sizing: auto;
  font-size: 1.9rem; line-height: 1; font-weight: 400;
  letter-spacing: -0.03em; color: var(--ink);
}
.lever__t { font-size: 0.95rem; font-weight: 600; letter-spacing: -0.01em; }
.lever__d { font-size: 0.85rem; line-height: 1.5; color: var(--ink-3); }

/* The one that matters carries the accent and the weight. */
.lever--hero { background: var(--brand-soft); }
.lever--hero .lever__ic {
  --ic-top: #12A192; --ic-left: #0E8A7D; --ic-right: #085D53;
  --ic-deep: #06463E; --ic-flap: #0B7C6F;
}
.lever--hero .lever__v { color: var(--brand-ink); font-size: 2.5rem; }
.lever--hero .lever__t { color: var(--brand-ink); }
.lever--hero .lever__d { color: var(--ink-2); }

/* The one the category advertises on carries the gold, and it is a sliver. */
.lever--foil { background: var(--gold-soft-2); }
.lever--foil .lever__ic {
  --ic-top: #EFC98A; --ic-left: #E3AC49; --ic-right: #B8862F;
  --ic-deep: #8A6516; --ic-flap: #E3AC49;
}
.lever--foil .lever__v { color: var(--gold-ink); }
.lever--foil .lever__t { color: var(--gold-ink); }

@media (max-width: 1020px) { .levers { grid-template-columns: repeat(3, 1fr); } }
@media (max-width: 640px)  { .levers { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 420px)  { .levers { grid-template-columns: 1fr; } }

/* Active page in the primary nav. */
.nav__link.is-current { color: var(--brand-ink); font-weight: 600; }
.nav__link.is-current::after { transform: scaleX(1); background: var(--brand); }
@media (max-width: 1100px) {
  .nav__link.is-current { color: var(--brand-ink); }
}

/* ══════════════════════════════════════════════════════════════════════════
   29 · Grouped navigation
   Four menus rather than nine links. Opens on hover and on focus, so it is
   reachable by keyboard; closes on Escape and on outside click.
   ══════════════════════════════════════════════════════════════════════════ */
.nav__group { position: relative; }

.nav__top {
  display: inline-flex;
  align-items: center;
  gap: 0.4rem;
  background: none;
  border: 0;
  padding: 0.55rem 0;
  font-family: var(--font);
  font-size: 0.85rem;
  font-weight: 500;
  color: var(--ink-2);
  cursor: pointer;
  white-space: nowrap;
  transition: color 0.18s var(--ease);
}
.nav__top:hover { color: var(--ink); }
.nav__chev { transition: transform 0.22s var(--ease); opacity: 0.55; }
.nav__group.is-open .nav__top { color: var(--ink); }
.nav__group.is-open .nav__chev { transform: rotate(180deg); }
.nav__group.is-current .nav__top { color: var(--brand-ink); font-weight: 600; }

.nav__menu {
  position: absolute;
  top: calc(100% + 0.5rem);
  left: -0.9rem;
  min-width: 22.5rem;
  padding: 0.5rem;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  box-shadow: 0 12px 28px -10px rgba(var(--ink-rgb), 0.16),
              0 3px 8px -4px rgba(var(--ink-rgb), 0.08);
  display: grid;
  gap: 1px;
  opacity: 0;
  visibility: hidden;
  transform: translateY(-5px);
  transition: opacity 0.18s var(--ease), transform 0.18s var(--ease), visibility 0.18s;
  z-index: 20;
}
.nav__group.is-open .nav__menu { opacity: 1; visibility: visible; transform: none; }

/* The rightmost menu opens leftward, or it runs off the viewport edge.
   :last-of-type, not :last-child — the mobile CTA anchor is the real last
   child of .nav__links, so :last-child never matches a group. */
.nav__group:last-of-type .nav__menu { left: auto; right: -0.9rem; }
@media (max-width: 1100px) {
  .nav__group:last-of-type .nav__menu { left: auto; right: auto; }
}

/* A hover bridge, so the pointer can cross the gap without the menu closing. */
.nav__group::after {
  content: '';
  position: absolute;
  top: 100%; left: 0; right: 0; height: 0.6rem;
}

.nav__item {
  display: grid;
  gap: 0.1rem;
  padding: 0.6rem 0.75rem;
  border-radius: var(--radius);
  transition: background-color 0.15s var(--ease);
}
.nav__item:hover { background: var(--surface-2); }
.nav__item.is-current { background: var(--brand-soft); }
.nav__item-t { font-size: 0.9rem; font-weight: 600; color: var(--ink); letter-spacing: -0.008em; }
.nav__item.is-current .nav__item-t { color: var(--brand-ink); }
/* text-wrap: pretty so a blurb that does wrap never orphans a single word,
   which is what made the longest two look broken. */
.nav__item-d {
  font-size: 0.8rem;
  line-height: 1.4;
  color: var(--ink-3);
  text-wrap: pretty;
}

@media (max-width: 1100px) {
  /* In the burger panel the menus become a plain stacked list.
     Density: the blurbs are dropped here. Nine items each carrying a
     two-line description is most of what made this panel ~800px tall and
     forced it to scroll on every phone; the labels alone navigate perfectly
     well, and the blurb's job — helping you choose between two pages in the
     same group — is a desktop-hover job. Every row is held at a 44px minimum
     so nothing here is smaller than a thumb. */
  /* Nothing in this panel is bold. The group heading leads on colour instead —
     teal at 0.8rem is 14.08px, small text, so it has to be --brand-ink (6.3:1)
     and never --brand (4.24:1, under the 4.5 floor). Weight 500 rather than 400
     because uppercase at 0.09em tracking goes spindly at 400. */
  .nav__group { border-bottom: 1px solid var(--surface-3); }
  .nav__top {
    width: 100%;
    justify-content: space-between;
    padding: 0.7rem 0 0.3rem;
    font-size: 0.8rem;
    font-weight: 500;
    letter-spacing: 0.09em;
    text-transform: uppercase;
    color: var(--brand-ink);
    pointer-events: none;
  }
  /* `.nav__group.is-current .nav__top` sets 600 outside this block at (0,3,0),
     which no plain `.nav__top` can outrank whatever the source order. It has to
     be matched selector-for-selector or the heading of whichever group owns the
     current page comes back bold. Its teal is now every heading's teal, so
     colour alone no longer marks the group — the current *item* does that. */
  .nav__group.is-current .nav__top { font-weight: 500; }
  .nav__chev { display: none; }
  .nav__menu {
    position: static;
    min-width: 0;
    opacity: 1;
    visibility: visible;
    transform: none;
    border: 0;
    box-shadow: none;
    background: transparent;
    padding: 0 0 0.35rem;
    gap: 0;
  }
  .nav__group::after { display: none; }
  .nav__item {
    display: flex;
    align-items: center;
    min-height: 44px;
    padding: 0.3rem 0;
  }
  .nav__item-d { display: none; }
  /* The links themselves are plain near-black at 400 — the accent above them is
     doing the grouping, so weight here would just be a second signal saying the
     same thing. The current page still marks itself in teal, by colour alone. */
  .nav__item-t { font-size: 0.95rem; font-weight: 400; color: var(--ink); }
  .nav__item:hover { background: transparent; }
  .nav__item.is-current { background: transparent; }
}

/* ══════════════════════════════════════════════════════════════════════════
   30 · Pallet matrix — the integer step-function, drawn
   ══════════════════════════════════════════════════════════════════════════ */
.pmatrix-fig {
  margin: 0 0 clamp(2rem, 1.4rem + 1.8vw, 3rem);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--surface);
  padding: clamp(1.1rem, 0.9rem + 0.8vw, 1.6rem);
}
.pmatrix__cap {
  display: flex; justify-content: space-between; align-items: baseline;
  gap: 1rem; flex-wrap: wrap;
  font-size: 0.8rem; font-weight: 600; letter-spacing: 0.09em;
  text-transform: uppercase; color: var(--ink-3);
  padding-bottom: 0.8rem; margin-bottom: 1rem;
  border-bottom: 1px solid var(--surface-3);
}
.pmatrix__keys { display: flex; gap: 1.1rem; }
.pmatrix__keys span { display: inline-flex; align-items: center; gap: 0.45rem; }
.pmatrix__keys i { width: 11px; height: 11px; border-radius: 2px; flex: none; }
.pk-keep { background: var(--brand); }
.pk-gone { background: var(--red-soft); border: 1.5px solid var(--red); }
.pmatrix__keys span:last-child { color: var(--red); font-weight: 700; }

.pmatrix {
  display: grid;
  grid-template-columns: repeat(19, 1fr);
  gap: 5px;
  max-width: 30rem;
}
.pcell {
  aspect-ratio: 1;
  border-radius: 2px;
  /* a lighter top face, so a square reads as a stacked thing */
  background: linear-gradient(var(--brand-2) 34%, var(--brand) 34%);
}
/* Red, not a dashed outline — a deleted position has to be the thing your eye
   lands on, and a gray dash on a white ground simply is not. */
.pcell--gone {
  background: var(--red-soft);
  border: 1.5px solid var(--red);
}

/* They start the size of everything else and visibly collapse, so the eye
   reads a deletion rather than an absence. */
.js .pcell--gone { transform: none; transition: transform 0.55s var(--ease-out) 1.1s; }
.js .is-revealed .pcell--gone { transform: scale(0.72); }

.pmatrix__read {
  margin-top: 1.1rem; padding-top: 0.9rem;
  border-top: 1px solid var(--surface-3);
  font-size: 0.92rem; line-height: 1.6; color: var(--ink-2); max-width: 76ch;
}
.pmatrix__read b { color: var(--ink); font-weight: 600; }

@media (max-width: 520px) { .pmatrix { gap: 3px; } }

/* ══════════════════════════════════════════════════════════════════════════
   31 · Density cliff — class is a step function, not a slope
   ══════════════════════════════════════════════════════════════════════════ */
.cliff {
  margin: 0;
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  background: var(--surface);
  padding: clamp(1.1rem, 0.9rem + 0.8vw, 1.6rem);
}
.cliff__cap {
  display: flex; justify-content: space-between; align-items: baseline;
  gap: 1rem; flex-wrap: wrap;
  font-size: 0.8rem; font-weight: 600; letter-spacing: 0.09em;
  text-transform: uppercase; color: var(--ink-3);
  padding-bottom: 0.8rem; margin-bottom: 1rem;
  border-bottom: 1px solid var(--surface-3);
}
.cliff__fig { width: 100%; height: auto; }

.cliff__grid line { stroke: var(--surface-3); stroke-width: 1; }
.cliff__band { fill: var(--red-soft); }

.cliff__step {
  fill: none;
  stroke: var(--brand);
  stroke-width: 2.6;
  stroke-linejoin: round;
  stroke-linecap: round;
}
.js .cliff__step { stroke-dasharray: 900; stroke-dashoffset: 900; }
.js .is-revealed .cliff__step { stroke-dashoffset: 0; transition: stroke-dashoffset 1.5s var(--ease-out) 0.2s; }

.cliff__mark line { stroke-width: 1.6; stroke-dasharray: 4 3; }
.cliff__mark--est line   { stroke: var(--red); }
.cliff__mark--est circle { fill: var(--red); }
.cliff__mark--real line   { stroke: var(--brand-ink); }
.cliff__mark--real circle { fill: var(--brand-ink); stroke: var(--surface); stroke-width: 2; }
.js .cliff__mark, .js .cliff__band { opacity: 0; }
.js .is-revealed .cliff__mark { opacity: 1; transition: opacity 0.5s var(--ease) 1.3s; }
.js .is-revealed .cliff__band { opacity: 1; transition: opacity 0.6s var(--ease) 1.5s; }

.cliff__ylab text {
  font-family: var(--font); font-size: 12px; font-weight: 600;
  fill: var(--ink-3); text-anchor: end; font-variant-numeric: tabular-nums;
}
.cliff__xlab text {
  font-family: var(--font); font-size: 12px; fill: var(--ink-3);
  text-anchor: middle; font-variant-numeric: tabular-nums;
}
.cliff__xlab text { transform: translateY(258px); }
.cliff__axis {
  font-family: var(--font); font-size: 10.5px; font-weight: 700;
  letter-spacing: 1.2px; fill: var(--ink-4);
}
.cliff__axis--x { text-anchor: end; }
.cliff__note text {
  font-family: var(--font); font-size: 11.5px; font-weight: 600;
  font-variant-numeric: tabular-nums;
}
.cliff__note text:first-child { fill: var(--red); }
.cliff__note text:last-child  { fill: var(--brand-ink); }

/* ══════════════════════════════════════════════════════════════════════════
   32 · Icons on the regulatory milestones
   ══════════════════════════════════════════════════════════════════════════ */
.clock__ic {
  display: block;
  width: 34px; height: 34px;
  margin-bottom: 0.7rem;
  --ic-top: #12A192; --ic-left: #0E8A7D; --ic-right: #085D53;
  --ic-deep: #06463E; --ic-flap: #0B7C6F; --ic-line: #FFFFFF;
}
.clock__ic svg { width: 100%; height: 100%; display: block; overflow: visible; }
/* The one still ahead of us wears the gold, as the computed optimum does. */
.clock__item--apex .clock__ic {
  --ic-top: #EFC98A; --ic-left: #E3AC49; --ic-right: #B8862F;
  --ic-deep: #8A6516; --ic-flap: #E3AC49;
}
.js .clock__ic { opacity: 0; transform: translateY(8px) scale(0.9); transition: opacity 0.5s var(--ease), transform 0.5s var(--ease-out); }
.js .is-revealed .clock__ic { opacity: 1; transform: none; }
.js .is-revealed .clock__item:nth-child(2) .clock__ic { transition-delay: 0.09s; }
.js .is-revealed .clock__item:nth-child(3) .clock__ic { transition-delay: 0.18s; }
.js .is-revealed .clock__item:nth-child(4) .clock__ic { transition-delay: 0.27s; }

@media (prefers-reduced-motion: reduce) {
  .js .pcell--gone { opacity: 0.45; transform: scale(0.62); transition: none; }
  .js .cliff__step { stroke-dashoffset: 0; transition: none; }
  .js .cliff__mark, .js .cliff__band { opacity: 1; transition: none; }
  .js .clock__ic { opacity: 1; transform: none; transition: none; }
}

/* ══════════════════════════════════════════════════════════════════════════
   33 · Method stages — icon, rail and payload per stage
   ══════════════════════════════════════════════════════════════════════════ */
.stage { position: relative; display: flex; flex-direction: column; }

/* A rail across the top of each card, filling further along the sequence.
   Six stages, so the last one is full — the progression is the point. */
.stage__rail {
  position: absolute;
  top: -1px; left: 0; right: 0; height: 3px;
  background: var(--surface-3);
  overflow: hidden;
}
.stage__rail::after {
  content: '';
  position: absolute; inset: 0;
  background: var(--brand);
  transform-origin: left;
  scale: var(--step) 1;
}
.js .stage__rail::after { scale: 0 1; transition: scale 0.8s var(--ease-out); }
.js .is-revealed .stage__rail::after { scale: var(--step) 1; }
.stage--apex .stage__rail::after { background: var(--gold); }

.stage__ic {
  width: 30px; height: 30px;
  flex: none;
  --ic-top: #12A192; --ic-left: #0E8A7D; --ic-right: #085D53;
  --ic-deep: #06463E; --ic-flap: #0B7C6F; --ic-line: #FFFFFF;
  transition: transform 0.35s var(--ease-out);
}
.stage__ic svg { width: 100%; height: 100%; display: block; overflow: visible; }
.stage:hover .stage__ic { transform: translateY(-3px) scale(1.06); }

/* The differentiator keeps the gold, and so does its icon. */
.stage--apex .stage__ic {
  --ic-top: #EFC98A; --ic-left: #E3AC49; --ic-right: #B8862F;
  --ic-deep: #8A6516; --ic-flap: #E3AC49; --ic-line: #FFFDF8;
}

/* What the stage hands to the next one. */
.stage__out {
  /* Hidden on owner instruction. The markup stays — the six lines are real
     content and the styling below is intact, so this is one line to revert. */
  display: none;
  margin-top: auto;
  padding-top: 0.7rem;
  border-top: 1px solid var(--surface-3);
  font-size: 0.8rem;
  line-height: 1.42;
  color: var(--ink-3);
}
.stage__out span {
  display: inline-block;
  margin-right: 0.5rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--brand-ink);
}
.stage__out span::after { content: ' →'; font-weight: 500; }
.stage--apex .stage__out span { color: var(--gold-ink); }

.stage__n { margin-top: 0.35rem; }

/* ══════════════════════════════════════════════════════════════════════════
   34 · The scenario page — the product told as a trip to the airport
        Everything solid on this page is axonometric SVG, not CSS 3D. That is
        deliberate: `preserve-3d` sorts faces with a painter's algorithm and
        z-fights the moment two solids interpenetrate, which is exactly the
        artifact this page cannot have. Here every face is an explicit polygon
        emitted back-to-front by (x+y+z), so there is no z buffer to fight and
        two solids can never blend into one another. Geometry is generated,
        never hand-typed — see README § The scenario page.
   ══════════════════════════════════════════════════════════════════════════ */

/* ── a numbered scene ─────────────────────────────────────────────────── */
.scn { margin-top: clamp(3rem, 2.2rem + 3vw, 5rem); }
.scn:first-of-type { margin-top: 0; }
.scn__head {
  display: grid; grid-template-columns: auto 1fr; gap: 1.1rem;
  align-items: start; max-width: 66ch; margin-bottom: 1.6rem;
}
.scn__n {
  font-size: 0.8rem; font-weight: 600; letter-spacing: 0.09em;
  color: var(--brand-ink); background: var(--brand-soft);
  border: 1px solid var(--brand-border); border-radius: var(--radius-sm);
  padding: 0.3rem 0.5rem; line-height: 1; margin-top: 0.28rem;
  font-variant-numeric: tabular-nums;
}
.scn__t {
  font-family: var(--font-display); font-optical-sizing: auto; font-weight: 400;
  font-size: clamp(1.3rem, 1.1rem + 0.9vw, 1.85rem);
  line-height: 1.2; letter-spacing: -0.018em; color: var(--ink); text-wrap: balance;
}
.scn__lede { margin-top: 0.6rem; color: var(--tl-2); line-height: 1.62; text-wrap: pretty; }

/* The line that lands the analogy on the real term. Every scene ends on one,
   because an analogy that never names what it stands for is just a story. */
.scn__map {
  margin-top: 1.5rem; max-width: 74ch;
  padding-left: 0.95rem; border-left: 2px solid var(--brand-border);
  font-size: 0.935rem; line-height: 1.62; color: var(--tl-2);
}
.scn__map b:first-child {
  display: block; font-size: 0.8rem; letter-spacing: 0.09em; text-transform: uppercase;
  color: var(--brand-ink); margin-bottom: 0.3rem; font-weight: 600;
}

/* ── the commitment strip ─────────────────────────────────────────────── */
.commit { border: 1px solid var(--border); border-radius: var(--radius-lg); overflow: hidden; }
.commit__row {
  display: grid; grid-template-columns: 11rem 1fr auto; gap: 1rem; align-items: baseline;
  padding: 0.85rem 1.1rem; border-top: 1px solid var(--surface-3); background: var(--surface);
}
.commit__row:first-child { border-top: 0; }
.commit__w {
  font-size: 0.8rem; font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase;
  color: var(--ink-3); font-variant-numeric: tabular-nums;
}
.commit__a { color: var(--ink-2); line-height: 1.5; }
.commit__s {
  font-size: 0.8rem; font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase;
  padding: 0.16rem 0.5rem; border-radius: 100px; white-space: nowrap;
}
.commit__row--blind .commit__s { color: #8A3325; background: #FBEAE7; }
.commit__row--known { background: var(--brand-soft); }
.commit__row--known .commit__a { color: var(--ink); font-weight: 500; }
.commit__row--known .commit__s { color: #FFFFFF; background: var(--brand-solid); }
@media (max-width: 620px) {
  .commit__row { grid-template-columns: 1fr auto; }
  .commit__w { grid-column: 1 / -1; }
}

/* ── isometric figures ────────────────────────────────────────────────── */
.iso { display: block; width: 100%; height: auto; overflow: visible; }
.iso__shadow { fill: rgba(var(--ink-rgb), 0.09); }
/* One hairline in the face colour's own family keeps adjacent solids legible
   where they touch, without drawing a cartoon outline around everything. */
.iso__solid polygon { stroke: var(--c-e); stroke-width: 0.7; stroke-linejoin: round; }
.iso__solid .f-t { fill: var(--c-t); }
.iso__solid .f-l { fill: var(--c-l); }
.iso__solid .f-r { fill: var(--c-r); }

.bag--case  { --c-t: #3E4757; --c-l: #252C39; --c-r: #1A202B; --c-e: rgba(255,255,255,0.10); }
.bag--carry { --c-t: #12A192; --c-l: #0B7C6F; --c-r: #085D53; --c-e: rgba(255,255,255,0.14); }
.bag--hand  { --c-t: #C3C7D1; --c-l: #9BA1AE; --c-r: #7C8391; --c-e: rgba(255,255,255,0.22); }
.pal--mine  { --c-t: #12A192; --c-l: #0B7C6F; --c-r: #085D53; --c-e: rgba(255,255,255,0.14); }
.pal--other { --c-t: #DCE0E6; --c-l: #BFC5CE; --c-r: #A2A9B5; --c-e: rgba(255,255,255,0.55); }
/* The fourth bag — the one thing both doors are about. Gold is legal here on
   rule 3's own terms: not a control, not a status pill, it marks the single
   element the whole figure exists for, exactly like the beacon and the apex. */
.bag--fourth { --c-t: #EFC98A; --c-l: #E3AC49; --c-r: #B8862F; --c-e: rgba(255,255,255,0.3); }

.iso__bin polygon { stroke: #AEB5C0; stroke-width: 0.7; stroke-linejoin: round; }
.iso__bin .b-floor  { fill: #E9ECF1; }
.iso__bin .b-wall-l { fill: #D3D8E0; }
.iso__bin .b-wall-r { fill: #C2C8D2; }
.bin--hold .b-floor { fill: #EDEFF3; }

/* The volume you are paying for whether or not you fill it. */
.iso__ghost polygon, .iso__ghost polyline { fill: none; }
.iso__ghost polygon, .iso__ghost polyline, .iso__ghost line {
  stroke: var(--brand); stroke-width: 1.1; stroke-dasharray: 4 4; stroke-linecap: round;
}
/* The bag that never left the house — an outline, because it is not there. */
.ghost--left polygon, .ghost--left polyline, .ghost--left line { stroke: #B23B2C; }

/* ── figure cards ─────────────────────────────────────────────────────── */
.mixrow { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1.1rem; }
/* The two doors. Equal columns, because both figures are generated into one
   shared viewBox — that is what guarantees the same car renders at the same
   size in both panels. Framed independently they came out 184.6px and 244.6px
   wide for the same object. Do not "fix" this by tuning the columns. */
.doorrow { display: grid; grid-template-columns: 1fr 1fr; gap: 1.1rem; }
@media (max-width: 900px) { .mixrow, .doorrow { grid-template-columns: 1fr; } }

.isocard {
  margin: 0; border: 1px solid var(--border); border-radius: var(--radius-lg);
  background: var(--surface); overflow: hidden;
  display: flex; flex-direction: column;
}
.isocard--win { border-color: var(--gold-border); background: var(--gold-soft); }
.isocard__fig {
  padding: clamp(0.9rem, 0.7rem + 0.7vw, 1.5rem);
  background: linear-gradient(180deg, var(--surface-2), var(--surface));
  border-bottom: 1px solid var(--surface-3);
  /* Centres the figure when the card is stretched taller by its neighbour, so
     a shorter caption never leaves the drawing stranded at the top. */
  display: grid; place-items: center;
}
.isocard--win .isocard__fig { background: linear-gradient(180deg, #FBF4E6, var(--gold-soft)); }
.isocard figcaption {
  display: flex; flex-direction: column; gap: 0.4rem;
  padding: clamp(0.9rem, 0.75rem + 0.5vw, 1.15rem);
  margin-top: auto;
}
.isocard__t {
  display: flex; align-items: center; gap: 0.55rem; flex-wrap: wrap;
  font-size: 1.012rem; font-weight: 500; color: var(--ink);
}
.isocard__flag {
  font-size: 0.8rem; font-weight: 600; letter-spacing: 0.08em; text-transform: uppercase;
  color: var(--on-amber); background: var(--gold); border-radius: 100px; padding: 0.1rem 0.5rem;
}
.isocard__d { font-size: 0.935rem; line-height: 1.55; color: var(--tl-2); text-wrap: pretty; }
.isocard__m {
  font-size: 0.8rem; letter-spacing: 0.04em; color: var(--ink-3);
  font-variant-numeric: tabular-nums; padding-top: 0.4rem;
  border-top: 1px solid var(--surface-3);
}
.isocard__m b { color: var(--ink); font-weight: 600; }
/* The line that lands a door on what it costs in the operation. Set apart
   from the description above it, because one is the story and one is the bill. */
.isocard__real {
  margin-top: 0.15rem; padding-top: 0.7rem;
  border-top: 1px solid var(--surface-3);
  font-size: 0.895rem; line-height: 1.55; color: var(--tl-2); text-wrap: pretty;
}
.isocard__real b:first-child {
  display: block; font-size: 0.8rem; letter-spacing: 0.09em; text-transform: uppercase;
  color: var(--brand-ink); margin-bottom: 0.25rem; font-weight: 600;
}
/* Where the analogy honestly stops. Amber rather than teal, so it reads as a
   caveat and not as another claim. */
.callout--break { border-color: var(--gold-border); background: var(--gold-soft); }
.callout--break .callout__i { color: var(--gold-ink); }

.isocard__leg {
  display: flex; align-items: center; gap: 0.45rem; flex-wrap: wrap;
  font-size: 0.8rem; letter-spacing: 0.05em; text-transform: uppercase; color: var(--ink-3);
}
.isocard__leg i { width: 11px; height: 11px; border-radius: 2px; display: inline-block; }
.isocard__leg i + * { margin-left: 0; }
.leg--mine { background: #0B7C6F; }
.leg--other { background: #BFC5CE; margin-left: 0.8rem; }

/* ── the key table ────────────────────────────────────────────────────── */
.keytab { min-width: 460px; }
.keytab thead th:first-child { width: 42%; }
.callout--wide { margin-top: clamp(3rem, 2.2rem + 3vw, 5rem); }

/* ── motion ───────────────────────────────────────────────────────────── */
/* Solids settle in downward, one after another, in the order they were
   painted — so the figure appears to be packed rather than to fade in. The
   delay classes d0…d13 are emitted by the geometry generator alongside the
   depth sort, which is why the order always reads correctly. */
.js .iso__solid { opacity: 0; transform: translateY(-10px); }
.js .is-revealed .iso__solid {
  opacity: 1; transform: none;
  transition: opacity 0.42s var(--ease-out), transform 0.55s var(--ease-out);
}
.js .iso__bin, .js .iso__ghost, .js .iso__shadow { opacity: 0; }
.js .is-revealed .iso__bin,
.js .is-revealed .iso__shadow { opacity: 1; transition: opacity 0.5s var(--ease-out); }
.js .is-revealed .iso__ghost { opacity: 1; transition: opacity 0.6s var(--ease-out) 0.75s; }
.js .is-revealed .iso__solid.d0  { transition-delay: 0.10s; }
.js .is-revealed .iso__solid.d1  { transition-delay: 0.18s; }
.js .is-revealed .iso__solid.d2  { transition-delay: 0.26s; }
.js .is-revealed .iso__solid.d3  { transition-delay: 0.34s; }
.js .is-revealed .iso__solid.d4  { transition-delay: 0.42s; }
.js .is-revealed .iso__solid.d5  { transition-delay: 0.50s; }
.js .is-revealed .iso__solid.d6  { transition-delay: 0.58s; }
.js .is-revealed .iso__solid.d7  { transition-delay: 0.66s; }
.js .is-revealed .iso__solid.d8  { transition-delay: 0.72s; }
.js .is-revealed .iso__solid.d9  { transition-delay: 0.78s; }
.js .is-revealed .iso__solid.d10 { transition-delay: 0.84s; }
.js .is-revealed .iso__solid.d11 { transition-delay: 0.90s; }
.js .is-revealed .iso__solid.d12 { transition-delay: 0.96s; }
.js .is-revealed .iso__solid.d13 { transition-delay: 1.02s; }

@media (prefers-reduced-motion: reduce) {
  .js .iso__solid, .js .iso__bin, .js .iso__ghost, .js .iso__shadow {
    opacity: 1; transform: none; transition: none;
  }
}

/* ══════════════════════════════════════════════════════════════════════════
   35 · The NMFC page — freight cost, explained by class
        Reuses .scn, .score, .callout and .footnote wholesale so the page reads
        as part of the site rather than as a microsite. Only the four things
        that genuinely have no equivalent are new: the density equation, the
        class ladder, the stack elevation and the fuel bars.
        Figures are generated — see README § The NMFC page.
   ══════════════════════════════════════════════════════════════════════════ */

/* ── a figure in a card, same furniture as .isocard ───────────────────── */
.nm-figbox {
  margin: 0; border: 1px solid var(--border); border-radius: var(--radius-lg);
  background: var(--surface); overflow: hidden;
}
.nm-figbox__fig {
  padding: clamp(1rem, 0.8rem + 0.9vw, 1.8rem);
  background: linear-gradient(180deg, var(--surface-2), var(--surface));
  border-bottom: 1px solid var(--surface-3);
  display: grid; place-items: center;
}
.nm-figbox figcaption {
  padding: clamp(0.9rem, 0.75rem + 0.5vw, 1.2rem);
  font-size: 0.895rem; line-height: 1.55; color: var(--tl-2); text-wrap: pretty;
}
.nm-figbox figcaption b { color: var(--ink); font-weight: 600; }
.nm-fig, .nm-ladder, .nm-elev { display: block; width: 100%; height: auto; overflow: visible; }

.nm-calc { grid-template-columns: 0.85fr 1fr; align-items: start; }
@media (max-width: 880px) { .nm-calc { grid-template-columns: 1fr; } }

/* ── the density equation ─────────────────────────────────────────────── */
.nm-eq { border: 1px solid var(--border); border-radius: var(--radius-lg); overflow: hidden; }
.nm-eq__row {
  display: flex; justify-content: space-between; align-items: baseline; gap: 1rem;
  padding: 0.66rem 1rem; border-top: 1px solid var(--surface-3);
  font-size: 0.935rem; color: var(--tl-2);
}
.nm-eq__row:first-child { border-top: 0; }
.nm-eq__row b { color: var(--ink); font-weight: 600; font-variant-numeric: tabular-nums; }
/* The answer, and the only line in the block that is not an input. */
.nm-eq__row--out {
  background: var(--brand-soft); border-top-color: var(--brand-border);
  color: var(--brand-ink); font-weight: 500;
}
.nm-eq__row--out b { color: var(--brand-ink); font-size: 1.12rem; }

/* ── the class ladder ─────────────────────────────────────────────────── */
.nm-ladder .nm-step { fill: var(--brand-soft); stroke: none; }
.nm-ladder .nm-step:nth-of-type(odd) { fill: var(--brand-soft-2); }
.nm-ladder .nm-tread { stroke: var(--brand); stroke-width: 1.8; }
.nm-ladder .nm-base { stroke: var(--border-2, #D6D9E0); stroke-width: 1; }
.nm-ladder .nm-tick { stroke: var(--ink-4); stroke-width: 1; }
.nm-ladder .nm-cls {
  font-size: 11px; font-weight: 600; fill: var(--brand-ink);
  font-variant-numeric: tabular-nums;
}
.nm-ladder .nm-axis {
  font-size: 10.5px; fill: var(--ink-3); font-variant-numeric: tabular-nums;
}
.nm-ladder .nm-axis--t { font-size: 9.5px; letter-spacing: 0.09em; font-weight: 600; }
/* Where the worked example sits, before and after. Gold marks the resolved
   one — rule 3: this is the computed optimum, not a control. */
.nm-mark line { stroke-width: 1.4; stroke-dasharray: 3 3; }
.nm-mark text { font-size: 11px; font-weight: 600; font-variant-numeric: tabular-nums; }
.nm-mark--before line { stroke: var(--ink-3); }
.nm-mark--before circle { fill: var(--surface); stroke: var(--ink-3); stroke-width: 2; }
.nm-mark--before text { fill: var(--ink-3); }
.nm-mark--after line { stroke: var(--gold); }
.nm-mark--after circle { fill: var(--gold); stroke: var(--surface); stroke-width: 2; }
.nm-mark--after text { fill: var(--gold-ink); }

/* ── the stack elevation ──────────────────────────────────────────────── */
.nm-elev .nm-ground { stroke: var(--ink-4); stroke-width: 1.2; }
.nm-elev .nm-band line { stroke: var(--brand-border); stroke-width: 1; stroke-dasharray: 4 4; }
.nm-elev .nm-band__h { font-size: 10.5px; fill: var(--ink-3); font-variant-numeric: tabular-nums; font-weight: 600; }
.nm-elev .nm-band__c { font-size: 10px; fill: var(--brand-ink); letter-spacing: 0.04em; font-weight: 600; }
.nm-elev .nm-stack__box { fill: var(--brand-soft-2); stroke: var(--brand); stroke-width: 1.6; }
.nm-elev .nm-stack__pal { fill: #C9CFD8; stroke: #9BA1AE; stroke-width: 1; }
.nm-elev .nm-stack__t {
  font-size: 11.5px; fill: var(--ink-2); font-variant-numeric: tabular-nums;
}
.nm-elev .nm-stack__c {
  font-size: 13px; font-weight: 600; letter-spacing: 0.07em; fill: var(--ink);
}
.nm-elev .nm-elev__cap {
  font-size: 10.5px; letter-spacing: 0.09em; text-transform: uppercase;
  font-weight: 600; fill: var(--ink-3);
}
.nm-elev .nm-elev__cap--win { fill: var(--gold-ink); }
.nm-elev .nm-stack--after .nm-stack__box { fill: #FBF4E6; stroke: var(--gold); }
.nm-elev .nm-stack--after .nm-stack__c { fill: var(--gold-ink); }

/* ── tables ───────────────────────────────────────────────────────────── */
.nm-scale { min-width: 420px; }
.nm-heights, .nm-inv { min-width: 520px; }
/* The two subprovisions the worked example passes through. */
.nm-scale tbody tr.is-hit td { background: var(--gold-soft-2, #FBF4E6); }
.nm-scale tbody tr.is-hit td.is-us { background: var(--gold); color: var(--on-amber); }

/* ── the fuel bars ────────────────────────────────────────────────────── */
.nm-fuel {
  display: grid; grid-template-columns: repeat(3, 1fr);
  gap: clamp(1rem, 0.6rem + 2vw, 3rem); align-items: end; height: 250px;
  border: 1px solid var(--border); border-bottom: 0;
  border-radius: var(--radius-lg) var(--radius-lg) 0 0;
  padding: clamp(1.2rem, 1rem + 1vw, 2rem) clamp(1.2rem, 1rem + 2vw, 3rem) 0;
  background: var(--surface);
}
.nm-fuel__bar { display: grid; grid-template-rows: auto 1fr auto; height: 100%; gap: 0.5rem; }
.nm-fuel__v {
  font-family: var(--font-display); font-optical-sizing: auto;
  font-size: clamp(1.25rem, 1rem + 1vw, 1.7rem); line-height: 1;
  color: var(--brand-ink); text-align: center; font-variant-numeric: tabular-nums;
}
.nm-fuel__bar--hi .nm-fuel__v { color: var(--gold-ink); }
.nm-fuel__fill {
  align-self: end; width: 100%; height: var(--h);
  border-radius: var(--radius) var(--radius) 0 0;
  background: linear-gradient(180deg, var(--brand-2), var(--brand-solid));
  transform-origin: bottom center; scale: 1 0;
  transition: scale 0.85s var(--ease-out);
}
.nm-fuel__bar--hi .nm-fuel__fill { background: linear-gradient(180deg, var(--gold), #C6892C); }
.is-revealed .nm-fuel__fill { scale: 1 1; }
.is-revealed .nm-fuel__bar:nth-child(2) .nm-fuel__fill { transition-delay: 0.14s; }
.is-revealed .nm-fuel__bar:nth-child(3) .nm-fuel__fill { transition-delay: 0.28s; }
.nm-fuel__k {
  padding: 0.7rem 0 0; border-top: 1px solid var(--border); text-align: center;
  font-size: 0.8rem; letter-spacing: 0.05em; text-transform: uppercase; color: var(--ink-3);
}
/* --ink-3, not --ink-4. Rule 1: --ink-4 is 2.6:1 and is decorative only —
   this is 14.08px text and measured at 2.41:1 against a 4.5 floor before it
   was changed. The contrast scan catches it; the eye does not. */
.nm-fuel__k i { font-style: normal; letter-spacing: 0; text-transform: none; color: var(--ink-3); }
.nm-fuel__cap {
  border: 1px solid var(--border); border-top: 0;
  border-radius: 0 0 var(--radius-lg) var(--radius-lg);
  padding: 0.9rem clamp(1.2rem, 1rem + 2vw, 3rem) 1.1rem;
  font-size: 0.8rem; color: var(--tl-3); background: var(--surface);
}

/* ── the market strip ─────────────────────────────────────────────────── */
.nm-bench {
  display: grid; grid-template-columns: repeat(3, 1fr);
  border-top: 1px solid var(--border); border-left: 1px solid var(--border);
  border-radius: var(--radius-lg); overflow: hidden;
}
@media (max-width: 900px) { .nm-bench { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 560px) { .nm-bench { grid-template-columns: 1fr; } }
.nm-bench__i {
  border-right: 1px solid var(--border); border-bottom: 1px solid var(--border);
  padding: clamp(1rem, 0.85rem + 0.7vw, 1.5rem);
  display: flex; flex-direction: column; gap: 0.3rem; background: var(--surface);
}
.nm-bench__i b {
  font-family: var(--font-display); font-optical-sizing: auto; font-weight: 400;
  font-size: clamp(1.5rem, 1.2rem + 1.3vw, 2.1rem); line-height: 1;
  color: var(--ink); font-variant-numeric: tabular-nums; letter-spacing: -0.02em;
}
.nm-bench__i span { font-size: 0.935rem; line-height: 1.45; color: var(--tl-2); }
.nm-bench__i i {
  font-style: normal; font-size: 0.8rem; color: var(--ink-3); margin-top: 0.15rem;
}

@media (prefers-reduced-motion: reduce) {
  .nm-fuel__fill { scale: 1 1; transition: none; }
}

/* ── the footer's fine print ──────────────────────────────────────────────
   Product first, parent second. The divider is the lockup's own rule at the
   same weight and opacity, so the line reads as a quieter echo of the mark in
   the bar above rather than as a second piece of branding. */
.footer__by { display: inline-flex; align-items: center; gap: 0.6rem; white-space: nowrap; }
.footer__by b { color: var(--td-1); font-weight: 600; letter-spacing: 0.01em; }
.footer__by i { width: 1px; height: 12px; background: currentColor; opacity: 0.3; }
@media (max-width: 460px) { .footer__by { white-space: normal; } }
