/* ==========================================================================
   DAEDALUS5 — site.css
   One stylesheet for the whole public site. No build step, no webfonts, no
   imports, no third-party CSS.

   How the system is organised
     1  Tokens          colour, type, geometry, motion
     2  Reset
     3  Layout          wrap / sec / editorial grids
     4  Type            display scale, eyebrow, lede, body
     5  Buttons & links
     6  Header and mobile drawer
     7  Hero
     8  Sections & components
     9  Product system
    10  Pricing (Echo pilot, the quoted offer, sample report)
    11  Accordion and definition lists
    12  Forms (campaign-plan flow, dormant-list calculator)
    13  Footer
    14  Legal pages
    15  Motion & print

   The light band
     `.sec--light` re-declares the colour tokens on itself rather than
     overriding twenty rules. Anything inside it — cards, rules, buttons,
     accordions — reads the same token names and lands correctly on paper.
     That is the whole mechanism; there is no second set of components.

   Accent semantics
     --brand   Daedalus5 orange. Every primary action on every page.
     --ec      D5 Echo emerald green. The one product identifier, never a CTA.
     --sg      Sky blue. Kept as a neutral second accent for diagrams and
               charts after D5 Signal was retired 2026-09-05; it no longer
               names a product. It is the exact complement of the brand
               orange, which is why it survived the cull.
     Buttons are brand orange everywhere. One CTA colour across the whole
     site is what makes it read as one company.
   ========================================================================== */

/* ---------- 1. Tokens ---------------------------------------------------- */

:root {
  /* Ground. Navy in five steps, so a page can change tone without changing
     colour. */
  --navy-900: #060F1B;
  --navy-850: #0A1826;
  --navy-800: #0D2033;
  --navy-750: #102942;
  --navy-700: #14314D;

  /* Paper. Warm off-white, for the light bands. */
  --paper:   #F6F3EE;
  --paper-2: #EFEAE1;

  /* Brand, sampled from the Daedalus5 logo art. --brand-ink is the same hue
     darkened until it passes AA as text on paper; the bright one does not. */
  --brand:      #F79552;
  --brand-hi:   #FFB176;
  --brand-ink:  #A34A17;
  --brand-tint: rgba(247, 149, 82, .12);
  --brand-line: rgba(247, 149, 82, .34);

  /* Accents. The sky blue is the exact complement of the brand orange (179°
     apart) and is now a neutral chart colour, not a product identifier. The
     Echo green sits at 158°, which is 134° from the orange — past the 60–120°
     band that has clashed every time it has been tried — and reads as growth
     rather than as the caution the old yellow carried. The -ink variants are
     the AA-passing versions for paper. */
  --sg:      #6FB7E9;
  --sg-ink:  #1C6DA8;
  --sg-tint: rgba(111, 183, 233, .13);
  --sg-line: rgba(111, 183, 233, .38);
  --ec:      #34D399;
  --ec-ink:  #0E7550;
  --ec-tint: rgba(52, 211, 153, .11);
  --ec-line: rgba(52, 211, 153, .32);

  /* The warning colour. --ember-ink is the same hue darkened until it passes
     AA as small text on paper; the bright one does not, exactly as with the
     brand orange above. */
  --ember:      #E0714E;
  --ember-ink:  #9C3D22;
  --ember-tint: rgba(224, 113, 78, .10);
  --ember-line: rgba(224, 113, 78, .32);

  /* Surfaces and ink — the dark default. */
  --bg:            var(--navy-850);
  --bg-alt:        var(--navy-800);
  --bg-deep:       var(--navy-900);
  --surface:       #10263B;
  --surface-2:     #16334D;
  --border:        rgba(146, 184, 222, .14);
  --border-strong: rgba(146, 184, 222, .28);
  --sheen:         inset 0 1px 0 rgba(255, 255, 255, .04);

  --ink:     #EDF3F9;
  --ink-mid: #B4C7DA;
  --ink-low: #8FA8C1;

  /* The accent running text wears. Orange everywhere; a light band swaps it
     for the darkened version. */
  --accent:      var(--brand);
  --accent-line: var(--brand-line);
  --accent-tint: var(--brand-tint);

  /* Type. System-first, so there is no webfont request and nothing shifts on
     first paint. Segoe UI Variable carries real intermediate weights on
     Windows; elsewhere the browser rounds to the nearest static face. */
  --font: "Segoe UI Variable", "Segoe UI", Inter, -apple-system,
          BlinkMacSystemFont, "Helvetica Neue", Arial, sans-serif;

  --w-display: 680;
  --w-head:    640;
  --w-strong:  600;
  --w-body:    400;

  /* Geometry */
  --r-xs: 6px;
  --r-sm: 10px;
  --r:    14px;
  --r-lg: 20px;

  --wrap:        1200px;
  --wrap-mid:    920px;
  --wrap-narrow: 720px;
  --gutter:      clamp(20px, 4.6vw, 40px);
  --section-y:   clamp(64px, 7.4vw, 112px);
  --hdr-h:       64px;

  /* Motion. Everything lands between 180 and 300ms on one curve. */
  --ease:   cubic-bezier(.2, .7, .3, 1);
  /* The overshoot-free decelerating curve. Anything that MOVES (a lift, a
     reveal, a sheen) rides this; anything that only changes colour rides
     --ease. It is what stops the motion layer feeling mechanical. */
  --ease-out: cubic-bezier(.16, 1, .3, 1);
  --t-fast: 180ms;
  --t:      220ms;
  --t-slow: 300ms;

  --shadow-sm: 0 1px 2px rgba(3, 10, 18, .3);
  --shadow:    0 12px 32px -12px rgba(3, 10, 18, .55);
  --shadow-lg: 0 28px 64px -24px rgba(3, 10, 18, .7);

  --arrow: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3E%3Cpath d='M2 8h11M9 4l4 4-4 4' fill='none' stroke='%23000' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}

/* The light band. Same token names, paper values. */
.sec--light {
  --bg:            var(--paper);
  --bg-alt:        var(--paper-2);
  --bg-deep:       var(--paper-2);
  --surface:       #FFFFFF;
  --surface-2:     var(--paper-2);
  --border:        rgba(10, 24, 38, .12);
  --border-strong: rgba(10, 24, 38, .22);
  --sheen:         inset 0 1px 0 rgba(255, 255, 255, .9);

  --ink:     #0B1B2B;
  --ink-mid: #3E5265;
  --ink-low: #56697C;

  --accent:      var(--brand-ink);
  --accent-line: rgba(163, 74, 23, .30);
  --accent-tint: rgba(163, 74, 23, .07);

  --ember:       var(--ember-ink);

  --shadow-sm: 0 1px 2px rgba(10, 24, 38, .06);
  --shadow:    0 12px 32px -14px rgba(10, 24, 38, .18);
  --shadow-lg: 0 28px 64px -28px rgba(10, 24, 38, .26);

  background: var(--bg);
  color: var(--ink);
}

/* ---------- 2. Reset ----------------------------------------------------- */

*, *::before, *::after { box-sizing: border-box; }

html {
  -webkit-text-size-adjust: 100%;
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--hdr-h) + 16px);
  /* `clip` rather than `hidden`: the closed mobile drawer is a fixed element
     parked at translateX(100%), and only clip removes it from the document's
     scrollable width without turning the root into a scroll container. */
  overflow-x: clip;
}

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font: var(--w-body) clamp(16px, .55vw + 14.4px, 17px)/1.62 var(--font);
  letter-spacing: -.003em;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-rendering: optimizeLegibility;
  overflow-x: hidden;
}

img, svg, video { max-width: 100%; height: auto; display: block; }
a { color: inherit; }
button { font: inherit; color: inherit; }

h1, h2, h3, h4 { margin: 0; font-weight: var(--w-head); letter-spacing: -.02em; }
p { margin: 0 0 1em; }
ul, ol { margin: 0; padding: 0; list-style: none; }
strong, b { font-weight: var(--w-strong); color: var(--ink); }

:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 3px;
  border-radius: var(--r-xs);
}
::selection { background: var(--brand); color: #10202F; }

/* ---------- 3. Layout ---------------------------------------------------- */

.wrap {
  width: 100%;
  max-width: var(--wrap);
  margin-inline: auto;
  padding-inline: var(--gutter);
}
.wrap--mid    { max-width: calc(var(--wrap-mid) + var(--gutter) * 2); }
.wrap--narrow { max-width: calc(var(--wrap-narrow) + var(--gutter) * 2); }

.sec { padding-block: var(--section-y); }
.sec--tight { padding-block: clamp(40px, 4.6vw, 68px); }
.sec--band  { background: var(--bg-alt); }
.sec--deep  { background: var(--bg-deep); }
.sec--hair  { border-top: 1px solid var(--border); }

/* The editorial grid: heading in the left column, content in the right. It
   is the layout most of this site is built on — left-aligned, asymmetric,
   and it collapses to one column without any of the parts moving. */
.ed { display: grid; gap: clamp(28px, 3.6vw, 48px); }
@media (min-width: 900px) {
  .ed { grid-template-columns: minmax(0, 4fr) minmax(0, 6fr); gap: clamp(40px, 5vw, 80px); }
  .ed--wide { grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); }
  .ed--even { grid-template-columns: repeat(2, minmax(0, 1fr)); }
  .ed__side--sticky { position: sticky; top: calc(var(--hdr-h) + 32px); align-self: start; }
}

.grid { display: grid; gap: clamp(16px, 1.8vw, 22px); }
@media (min-width: 620px)  { .grid--2 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 760px)  { .grid--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
@media (min-width: 620px)  { .grid--4 { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1000px) { .grid--4 { grid-template-columns: repeat(4, minmax(0, 1fr)); } }

.skip {
  position: absolute; left: -9999px; top: 0; z-index: 200;
  background: var(--brand); color: #10202F; font-weight: var(--w-strong);
  padding: 12px 18px; border-radius: 0 0 var(--r-sm) 0;
}
.skip:focus { left: 0; }

/* ---------- 4. Type ------------------------------------------------------ */

/* Display sizes clamp against a viewport-width middle term, so they scale
   continuously rather than stepping at a breakpoint. Negative tracking grows
   with size — the thing that stops large type looking gappy — while body copy
   stays at 400 with 1.62 leading and a measured line length. */

.d1 {
  font-size: clamp(34px, 4.4vw + 8px, 62px);
  line-height: 1.05;
  letter-spacing: -.032em;
  font-weight: var(--w-display);
  text-wrap: balance;
}
.d2 {
  font-size: clamp(27px, 2.4vw + 12px, 42px);
  line-height: 1.1;
  letter-spacing: -.026em;
  font-weight: var(--w-head);
  text-wrap: balance;
}
.d3 {
  font-size: clamp(20px, 1vw + 14px, 25px);
  line-height: 1.22;
  letter-spacing: -.018em;
  font-weight: var(--w-head);
  text-wrap: balance;
}
.d4 {
  font-size: clamp(17px, .5vw + 15px, 19px);
  line-height: 1.32;
  letter-spacing: -.014em;
  font-weight: var(--w-strong);
}
.d1 em, .d2 em, .d3 em { font-style: normal; color: var(--accent); }

.eyebrow {
  display: flex; align-items: center; gap: 10px;
  margin: 0 0 18px;
  font: var(--w-strong) 12px/1.2 var(--font);
  text-transform: uppercase;
  letter-spacing: .13em;
  color: var(--accent);
}
.eyebrow::before {
  content: ""; flex: 0 0 auto; width: 20px; height: 1px;
  background: currentColor; opacity: .55;
}
.eyebrow--plain { color: var(--ink-low); }

/* Body measures. 58–72 characters, enforced rather than hoped for. */
.lede {
  font-size: clamp(18px, .7vw + 15.6px, 21px);
  line-height: 1.5;
  letter-spacing: -.012em;
  font-weight: var(--w-body);
  color: var(--ink-mid);
  max-width: 34em;
}
.sub   { color: var(--ink-mid); max-width: 38em; }
.note  { color: var(--ink-low); font-size: 14.5px; line-height: 1.55; max-width: 44em; }
.muted { color: var(--ink-low); }
.tight > :last-child { margin-bottom: 0; }

.sec__head { max-width: 46em; margin-bottom: clamp(32px, 3.6vw, 52px); }
/* .d1 was missing here, so a page whose section head is an h1 — /getstarted/
   — ran its lede straight into the heading with no gap at all. */
.sec__head .d1 + .lede, .sec__head .d1 + .sub,
.sec__head .d2 + .lede, .sec__head .d2 + .sub { margin-top: 18px; }
.sec__head--center { margin-inline: auto; text-align: center; }
.sec__head--center .lede, .sec__head--center .sub { margin-inline: auto; }
.sec__head--center .eyebrow { justify-content: center; }

/* A single emphatic line. Used sparingly — twice a page at most. */
.pull {
  margin: clamp(32px, 3.6vw, 48px) 0 0;
  padding-left: clamp(16px, 2vw, 24px);
  border-left: 2px solid var(--accent-line);
  font-size: clamp(19px, 1vw + 14px, 24px);
  line-height: 1.36;
  letter-spacing: -.02em;
  font-weight: var(--w-strong);
  color: var(--ink);
  max-width: 30em;
}

/* ---------- 5. Buttons & links ------------------------------------------- */

/* A button is the loudest object on the page, so it behaves like a physical
   one: lit from above, lifting toward the cursor, pressing in when clicked,
   and throwing a little of its own colour onto the page underneath.

   isolation:isolate is what makes the sheen work. It gives the button its own
   stacking context, so ::before with z-index:-1 paints ABOVE the button's own
   background but BELOW its text — a highlight sweep that never covers the
   label. Without isolate the pseudo-element drops behind the whole button and
   disappears. */
.btn {
  position: relative; isolation: isolate; overflow: hidden;
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  min-height: 46px;
  padding: 11px 22px;
  border: 1px solid transparent;
  border-radius: var(--r-sm);
  background-color: var(--brand);
  background-image: linear-gradient(180deg, var(--brand-hi), var(--brand) 62%);
  color: #10202F;
  font: var(--w-strong) 15px/1.2 var(--font);
  letter-spacing: -.008em;
  text-decoration: none;
  cursor: pointer;
  box-shadow: 0 1px 0 rgba(255, 255, 255, .28) inset,
              0 6px 18px -10px rgba(247, 149, 82, .7);
  transition: background var(--t) var(--ease), border-color var(--t) var(--ease),
              color var(--t) var(--ease),
              transform var(--t-fast) var(--ease-out),
              box-shadow var(--t) var(--ease);
}
.btn::before {
  content: ""; position: absolute; z-index: -1; inset: 0;
  background: linear-gradient(105deg, transparent 34%,
              rgba(255, 255, 255, .55) 50%, transparent 66%);
  transform: translateX(-120%);
  transition: transform 620ms var(--ease-out);
}
.btn:hover {
  background-color: var(--brand-hi);
  background-image: linear-gradient(180deg, #FFC48F, var(--brand-hi) 62%);
  transform: translateY(-2px);
  box-shadow: 0 1px 0 rgba(255, 255, 255, .38) inset,
              0 16px 34px -14px rgba(247, 149, 82, .85);
}
.btn:hover::before { transform: translateX(120%); }
.btn:active {
  transform: translateY(0) scale(.985);
  box-shadow: 0 1px 0 rgba(255, 255, 255, .2) inset,
              0 4px 12px -8px rgba(247, 149, 82, .6);
  transition-duration: 60ms;
}
.btn:focus-visible { outline: 2px solid var(--brand-hi); outline-offset: 3px; }

.btn--ghost {
  background: none; background-color: transparent;
  border-color: var(--border-strong); color: var(--ink);
  box-shadow: none;
}
.btn--ghost:hover {
  background-color: rgba(255, 255, 255, .06); border-color: var(--brand);
  color: var(--ink);
  box-shadow: 0 12px 28px -18px rgba(247, 149, 82, .6);
}
.btn--ghost::before { background: linear-gradient(105deg, transparent 34%, rgba(255, 255, 255, .16) 50%, transparent 66%); }
.sec--light .btn--ghost:hover { background-color: rgba(10, 24, 38, .04); }

/* The one CTA per page that should catch the eye before it is looked for.
   A slow halo, not a flash — it repeats, so it has to be ignorable. */
.btn--pulse::after {
  content: ""; position: absolute; z-index: -2; inset: -2px;
  border-radius: inherit;
  box-shadow: 0 0 0 0 rgba(247, 149, 82, .5);
  animation: halo 3.2s var(--ease) infinite;
}
.btn--pulse:hover::after { animation-play-state: paused; }

.btn--sm { min-height: 40px; padding: 9px 16px; font-size: 14px; }
.btn--lg { min-height: 52px; padding: 14px 28px; font-size: 16px; }
/* Some CTAs are a full sentence and wrap to two lines on a phone. The words
   are the point, so the box gives way rather than the copy. */
@media (max-width: 480px) { .btn--lg { padding: 11px 18px; font-size: 15px; } }
.btn--block { width: 100%; }

.cta-row { display: flex; flex-wrap: wrap; align-items: center; gap: 14px 20px; margin-top: clamp(26px, 3vw, 34px); }
.cta-row--center { justify-content: center; }
.cta-note { margin: 14px 0 0; font-size: 14px; line-height: 1.5; color: var(--ink-low); max-width: 44em; }

/* The secondary action in most sections is this, not a second button. */
.tlink {
  display: inline-flex; align-items: center; gap: 7px;
  min-height: 30px;
  color: var(--accent);
  font-weight: var(--w-strong);
  font-size: 15px;
  text-decoration: none;
  transition: gap var(--t) var(--ease), color var(--t) var(--ease);
}
.tlink::after {
  content: ""; width: 14px; height: 14px; flex: 0 0 auto;
  background: currentColor;
  -webkit-mask: var(--arrow) center / contain no-repeat;
  mask: var(--arrow) center / contain no-repeat;
}
.tlink:hover { gap: 11px; }
.tlink--plain { color: var(--ink); min-height: 0; }
.tlink--plain:hover { color: var(--accent); }
/* A text link standing in for a button gets a real target; one sitting inside
   a sentence keeps its line height. */
.cta-row .tlink, .foot__cta .tlink { min-height: 44px; }

/* ---------- 6. Header and mobile drawer ---------------------------------- */

/* The header's blur lives on a pseudo-element, not on .hdr itself.
   backdrop-filter (like transform and filter) makes an element a containing
   block for fixed-position descendants — and the mobile drawer is a fixed
   descendant of this header. Put the filter on .hdr and the drawer collapses
   to the height of the header bar. Keep it on ::before. */
.hdr { position: sticky; top: 0; z-index: 96; }
.hdr::before {
  content: ""; position: absolute; inset: 0; z-index: -1;
  background: rgba(10, 24, 38, .72);
  border-bottom: 1px solid transparent;
  transition: background var(--t-slow) var(--ease), border-color var(--t-slow) var(--ease),
              box-shadow var(--t-slow) var(--ease);
}
@supports ((-webkit-backdrop-filter: blur(1px)) or (backdrop-filter: blur(1px))) {
  .hdr::before {
    background: rgba(10, 24, 38, .62);
    -webkit-backdrop-filter: saturate(160%) blur(16px);
    backdrop-filter: saturate(160%) blur(16px);
  }
}
.hdr.is-stuck::before {
  background: rgba(8, 20, 33, .92);
  border-bottom-color: var(--border);
  box-shadow: 0 1px 0 rgba(0, 0, 0, .2);
}

.hdr__inner { display: flex; align-items: center; gap: 16px; min-height: var(--hdr-h); }
.brand { display: inline-flex; align-items: center; gap: 10px; min-height: 44px; text-decoration: none; flex: 0 0 auto; }
.brand img { width: 128px; height: auto; }
.brand__tag {
  display: none;
  padding: 3px 8px;
  border: 1px solid var(--border-strong);
  border-radius: var(--r-xs);
  font: var(--w-strong) 11px/1.4 var(--font);
  text-transform: uppercase; letter-spacing: .1em;
  color: var(--ink-low);
}
@media (min-width: 620px) { .brand__tag { display: inline-block; } }

.hdr__end { display: flex; align-items: center; gap: 10px; margin-left: auto; }
.hdr__cta { display: none; }
@media (min-width: 520px) { .hdr__cta { display: inline-flex; } }
@media (max-width: 959px) { .hdr__cta { min-height: 44px; padding-inline: 14px; } }

.burger {
  display: inline-flex; align-items: center; justify-content: center;
  width: 44px; height: 44px; padding: 0;
  border: 1px solid var(--border-strong);
  border-radius: var(--r-sm);
  background: transparent;
  cursor: pointer;
  transition: border-color var(--t) var(--ease);
}
.burger:hover { border-color: var(--ink-low); }
.burger span { position: relative; display: block; width: 17px; height: 1.5px; background: var(--ink); border-radius: 2px; transition: background var(--t) var(--ease); }
.burger span::before, .burger span::after {
  content: ""; position: absolute; left: 0; width: 17px; height: 1.5px;
  background: var(--ink); border-radius: 2px;
  transition: transform var(--t) var(--ease), top var(--t) var(--ease);
}
.burger span::before { top: -5.5px; }
.burger span::after  { top: 5.5px; }
.burger[aria-expanded="true"] span { background: transparent; }
.burger[aria-expanded="true"] span::before { top: 0; transform: rotate(45deg); }
.burger[aria-expanded="true"] span::after  { top: 0; transform: rotate(-45deg); }

.nav { flex: 1 1 auto; }
.nav__list { display: flex; }
.nav__link {
  display: inline-flex; align-items: center; gap: 6px;
  min-height: 44px; padding: 0 12px;
  border: 0; background: none;
  font: 450 15px/1.2 var(--font);
  letter-spacing: -.006em;
  color: var(--ink-mid);
  text-decoration: none;
  cursor: pointer;
  transition: color var(--t) var(--ease);
}
.nav__link:hover, .nav__link[aria-current="page"] { color: var(--ink); }

@media (max-width: 959px) {
  .nav {
    position: fixed; inset: var(--hdr-h) 0 0 auto;
    width: min(420px, 100%);
    z-index: 1;
    padding: 20px var(--gutter) 40px;
    background: var(--navy-900);
    border-left: 1px solid var(--border);
    overflow-y: auto;
    overscroll-behavior: contain;
    transform: translateX(100%);
    visibility: hidden;
    transition: transform var(--t-slow) var(--ease), visibility 0s linear var(--t-slow);
  }
  .nav.is-open { transform: none; visibility: visible; transition-delay: 0s, 0s; }
  .nav__list { flex-direction: column; align-items: stretch; }
  .nav__item { border-bottom: 1px solid var(--border); }
  .nav__link { width: 100%; min-height: 54px; justify-content: space-between; padding-inline: 2px; font-size: 17px; color: var(--ink); }
  .nav__cta { display: flex; margin-top: 24px; }
  .nav__cta .btn { width: 100%; }
  body.nav-open { overflow: hidden; }
  .nav__scrim {
    position: fixed; inset: var(--hdr-h) 0 0 0; z-index: 94;
    background: rgba(4, 10, 18, .55);
    opacity: 0; pointer-events: none;
    transition: opacity var(--t-slow) var(--ease);
  }
  .nav__scrim.is-open { opacity: 1; pointer-events: auto; }
}

@media (min-width: 960px) {
  .burger, .nav__cta, .nav__scrim { display: none; }
  .nav { display: flex; justify-content: center; }
  .nav__list { align-items: center; gap: 2px; }
  .nav__item { position: relative; }
}

/* ---------- 7. Hero ------------------------------------------------------ */

.hero { position: relative; padding-block: clamp(52px, 6.4vw, 96px) clamp(52px, 6vw, 88px); overflow: hidden; }
.hero::before {
  content: ""; position: absolute; inset: -20% -10% auto -10%; height: 70%;
  background: radial-gradient(58% 74% at 68% 24%, var(--brand-tint), transparent 68%);
  pointer-events: none;
}
.hero > * { position: relative; }
.hero__grid { display: grid; gap: clamp(36px, 4.4vw, 56px); align-items: center; }
@media (min-width: 940px) {
  .hero__grid { grid-template-columns: minmax(0, 1fr) minmax(0, 1.02fr); gap: clamp(44px, 5vw, 72px); }
}
.hero .d1 + .lede { margin-top: 20px; }
.hero__support {
  margin: clamp(24px, 2.8vw, 32px) 0 0;
  padding-top: 18px;
  border-top: 1px solid var(--border);
  font-size: 14.5px;
  letter-spacing: .01em;
  color: var(--ink-low);
}
.hero__support b { color: var(--ink-mid); font-weight: var(--w-strong); }

/* The hero figure, and every other generated diagram, sits in one of these. */
.fig {
  position: relative;
  padding: clamp(18px, 2.2vw, 26px);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  background: linear-gradient(180deg, rgba(255, 255, 255, .045), transparent 60%), var(--surface);
  box-shadow: var(--sheen);
}
.fig svg { width: 100%; height: auto; overflow: visible; }
.fig__cap { margin: 16px 0 0; font-size: 13.5px; line-height: 1.5; color: var(--ink-low); }

/* Shared diagram paint. Every generated figure reads these tokens, so one
   accent change recolours all of them. */
.dg-node     { fill: rgba(146, 184, 222, .045); stroke: var(--border-strong); stroke-width: 1; }
.dg-node--on { fill: var(--accent-tint); stroke: var(--accent-line); }
.dg-link     { fill: none; stroke: var(--border-strong); stroke-width: 1.25; }
.dg-link--on { stroke: var(--accent); stroke-opacity: .5; }
.dg-dot      { fill: var(--ink-low); fill-opacity: .5; }
.dg-t        { font: var(--w-strong) 13px/1 var(--font); fill: var(--ink); letter-spacing: -.01em; }
.dg-t--sm    { font: var(--w-body) 11.5px/1 var(--font); fill: var(--ink-low); letter-spacing: .01em; }
.sec--light .dg-node { fill: rgba(10, 24, 38, .025); }

/* One-time draw-in for the hero figure's connectors. Purposeful, 700ms, once.
   The dash offset that hides them before they are drawn is declared ONLY
   inside no-preference: site.js does not add .is-drawn under reduced motion,
   so if the offset applied unconditionally those routes would simply never
   appear for anyone who asked for less movement. */
@media (prefers-reduced-motion: no-preference) {
  .js .fig--draw .dg-link { stroke-dasharray: 260; stroke-dashoffset: 260; }
  .js .fig--draw.is-drawn .dg-link { animation: draw 700ms var(--ease) forwards; }
  .js .fig--draw.is-drawn .dg-link:nth-of-type(2) { animation-delay: 70ms; }
  .js .fig--draw.is-drawn .dg-link:nth-of-type(3) { animation-delay: 140ms; }
  .js .fig--draw.is-drawn .dg-link:nth-of-type(4) { animation-delay: 210ms; }
  .js .fig--draw.is-drawn .dg-link:nth-of-type(5) { animation-delay: 280ms; }
}
@keyframes draw { to { stroke-dashoffset: 0; } }

/* ---------- 8. Sections & components ------------------------------------- */

/* A hairline list. The site's default way of presenting several related
   points — no card, no border box, no chip cloud. */
.rules { display: grid; }
.rules > li, .rules > div {
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: 4px 16px;
  padding: clamp(16px, 1.8vw, 22px) 0;
  border-top: 1px solid var(--border);
}
.rules > li:last-child, .rules > div:last-child { border-bottom: 1px solid var(--border); }
.rules b, .rules dt { grid-column: 2; font: var(--w-strong) 16.5px/1.35 var(--font); letter-spacing: -.014em; color: var(--ink); }
.rules p, .rules dd { grid-column: 2; margin: 5px 0 0; font-size: 15px; line-height: 1.55; color: var(--ink-mid); max-width: 46em; }
.rules__mark {
  grid-row: span 2;
  display: grid; place-items: center;
  width: 22px; height: 22px; margin-top: 2px;
  border-radius: 50%;
  border: 1px solid var(--accent-line);
  color: var(--accent);
}
.rules__mark svg { width: 11px; height: 11px; }
.rules__n {
  grid-row: span 2;
  width: 30px; margin-top: 1px;
  font: var(--w-strong) 13px/1.5 var(--font);
  font-variant-numeric: tabular-nums;
  letter-spacing: .06em;
  color: var(--accent);
}
.rules--num > li { padding-block: clamp(18px, 2.2vw, 26px); }

/* A plain card. Used only where a boundary genuinely helps comprehension. */
.card {
  padding: clamp(20px, 2.2vw, 28px);
  border: 1px solid var(--border);
  border-radius: var(--r);
  background: var(--surface);
  box-shadow: var(--sheen);
}
.card > :last-child { margin-bottom: 0; }
.card h3 { margin-bottom: 8px; }
.card p { color: var(--ink-mid); font-size: 15.5px; }

/* A figure strip. Structural numbers only — this site publishes no
   performance data, so nothing here may imply a result. */
.stats { display: grid; gap: 0; border-top: 1px solid var(--border); }
@media (min-width: 620px) { .stats { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 940px) {
  .stats--3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
  .stats--4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
}
.stat { padding: clamp(20px, 2.2vw, 26px) 0; border-bottom: 1px solid var(--border); }
@media (min-width: 620px) {
  .stat { padding-inline: clamp(18px, 2vw, 26px); border-left: 1px solid var(--border); }
  .stats--4 .stat:nth-child(odd), .stats--3 .stat:first-child { padding-left: 0; border-left: 0; }
}
@media (min-width: 940px) {
  .stats--4 .stat { padding-left: clamp(18px, 2vw, 26px); border-left: 1px solid var(--border); }
  .stats--4 .stat:nth-child(4n+1), .stats--3 .stat:nth-child(3n+1) { padding-left: 0; border-left: 0; }
}
.stat b {
  display: block;
  font-size: clamp(28px, 2vw + 16px, 38px);
  line-height: 1; letter-spacing: -.034em;
  font-weight: var(--w-display);
  font-variant-numeric: tabular-nums;
  color: var(--ink);
}
.stat span { display: block; margin-top: 10px; font-size: 14.5px; line-height: 1.5; color: var(--ink-mid); }

/* The disclaimer block. Deliberately plain — it is not a design element. */
.fineprint {
  margin-top: clamp(26px, 3vw, 36px);
  padding-top: clamp(20px, 2.4vw, 26px);
  border-top: 1px solid var(--border);
  font-size: 14px; line-height: 1.6;
  color: var(--ink-low);
  max-width: 78ch;
}
.fineprint p { margin: 0 0 .75em; }
.fineprint p:last-child { margin-bottom: 0; }
.fineprint strong { color: var(--ink-mid); font-weight: var(--w-strong); }

/* ---- 8b. Trust bar ------------------------------------------------------
   Factual operating markers, not statistics. Never a review score, a client
   count or an award — none of those are ours to publish.
   ------------------------------------------------------------------------ */
.trust { display: grid; gap: 0; border-top: 1px solid var(--border); }
@media (min-width: 700px)  { .trust { grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: clamp(20px, 3vw, 40px); } }
@media (min-width: 1060px) { .trust { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
.trust li {
  position: relative;
  padding: 16px 0 16px 22px;
  border-bottom: 1px solid var(--border);
  font-size: 14.5px; line-height: 1.5; color: var(--ink-mid);
}
.trust li::before {
  content: ""; position: absolute; left: 2px; top: 1.25em;
  width: 7px; height: 4px;
  border-left: 1.5px solid var(--accent); border-bottom: 1.5px solid var(--accent);
  transform: rotate(-45deg);
}

/* ---- 8c. Numbered flow --------------------------------------------------
   The four Echo steps. A large numeral in its own column so the step order
   survives a glance, with room under each step for a plain-language aside.
   ------------------------------------------------------------------------ */
.flow { display: grid; gap: 0; counter-reset: flow; }
@media (min-width: 900px) { .flow { grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: clamp(30px, 4vw, 60px); } }
.flow > li {
  display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 4px 16px;
  padding: clamp(20px, 2.4vw, 28px) 0;
  border-top: 1px solid var(--border);
}
@media (max-width: 899px) { .flow > li:last-child { border-bottom: 1px solid var(--border); } }
@media (min-width: 900px) { .flow > li:nth-last-child(-n+2) { border-bottom: 1px solid var(--border); } }
.flow__n {
  grid-row: 1 / span 3;
  display: flex; align-items: center; justify-content: center;
  width: 32px; height: 32px; margin-top: 1px;
  border: 1px solid var(--accent-line); border-radius: 50%;
  background: var(--accent-tint);
  font: var(--w-display) 15px/1 var(--font);
  font-variant-numeric: tabular-nums;
  color: var(--accent);
}
.flow b { font: var(--w-strong) 16.5px/1.35 var(--font); letter-spacing: -.014em; color: var(--ink); }
.flow p { margin: 6px 0 0; font-size: 15px; line-height: 1.55; color: var(--ink-mid); }
.flow__def {
  margin-top: 12px !important;
  padding: 10px 14px;
  border-left: 2px solid var(--border-strong);
  border-radius: 0 var(--r-xs) var(--r-xs) 0;
  background: var(--bg-alt);
  font-size: 14px !important; color: var(--ink-low) !important;
}

/* ---- 8d. Example quotes -------------------------------------------------
   What a qualified conversation sounds like, in the customer's own words.
   ------------------------------------------------------------------------ */
.quotes { display: flex; flex-wrap: wrap; gap: 8px; margin: 14px 0 0; }
.quotes li {
  padding: 8px 14px;
  border: 1px solid var(--border-strong); border-radius: 999px;
  background: var(--surface);
  font-size: 14.5px; line-height: 1.4; color: var(--ink);
}

/* ---- 8e. Responsibility split -------------------------------------------
   Two columns that answer one question: who is doing what. The D5 column is
   tinted so the boundary is visible before either list is read.
   ------------------------------------------------------------------------ */
.split { display: grid; gap: 14px; }
@media (min-width: 760px) { .split { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 18px; } }
.split__col {
  padding: clamp(22px, 2.6vw, 30px);
  border: 1px solid var(--border);
  border-radius: var(--r);
  background: var(--surface);
  box-shadow: var(--sheen);
}
.split__col--d5 { border-color: var(--accent-line); background: linear-gradient(180deg, var(--accent-tint), transparent 58%), var(--surface); }
.split__col h3 { margin-bottom: 14px; }
.split__col ul { display: grid; gap: 9px; }
.split__col li { position: relative; padding-left: 20px; font-size: 15px; line-height: 1.5; color: var(--ink-mid); }
.split__col li::before {
  content: ""; position: absolute; left: 2px; top: .5em; width: 7px; height: 4px;
  border-left: 1.5px solid var(--ink-low); border-bottom: 1.5px solid var(--ink-low);
  transform: rotate(-45deg);
}
.split__col--d5 li::before { border-color: var(--accent); }

/* ---- 8f. Point cards ----------------------------------------------------
   `.rules` is a hairline list: correct, dense, and visually flat. Where a
   set of points IS the argument — the four ways a list leaks money, the
   three reasons these people are different — a flat list makes the reader's
   eye slide past the whole section.

   `.rules--cards` promotes the same markup to a grid of real objects, each
   with a generated glyph. No new HTML shape: it is the same <ul><li><b><p>,
   so a page can be promoted or demoted by changing one class, and the
   plain list stays the default because most lists have not earned this.
   ------------------------------------------------------------------------ */
.rules--cards { display: grid; gap: 14px; }
@media (min-width: 720px) { .rules--cards { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.rules--cards.rules--three { grid-template-columns: minmax(0, 1fr); }
@media (min-width: 900px) { .rules--cards.rules--three { grid-template-columns: repeat(3, minmax(0, 1fr)); } }

.rules--cards > li {
  display: block;
  padding: clamp(20px, 2.2vw, 26px);
  border: 1px solid var(--border);
  border-radius: var(--r);
  background: linear-gradient(180deg, rgba(255, 255, 255, .035), transparent 58%), var(--surface);
  box-shadow: var(--sheen);
  transition: transform var(--t-slow) var(--ease-out),
              border-color var(--t) var(--ease),
              box-shadow var(--t-slow) var(--ease);
}
.sec--light .rules--cards > li {
  background: linear-gradient(180deg, rgba(255, 255, 255, .9), transparent 58%), var(--surface);
}
.rules--cards > li:last-child { border-bottom: 1px solid var(--border); }
.rules--cards > li:hover {
  transform: translateY(-3px);
  border-color: var(--accent-line);
  box-shadow: var(--shadow);
}
/* The hairline list's left-edge wipe belongs to the flat variant only. */
.rules--cards > li::after { content: none; }

.rules--cards b { display: block; grid-column: auto; font-size: 17px; }
.rules--cards p { grid-column: auto; margin-top: 8px; }

/* The glyph. A 34px rounded square holding one generated icon, tinted with
   whatever accent the section is wearing. */
.rules__ico {
  display: grid; place-items: center;
  width: 38px; height: 38px; margin-bottom: 16px;
  border: 1px solid var(--accent-line);
  border-radius: 11px;
  background: var(--accent-tint);
  color: var(--accent);
  transition: transform var(--t-slow) var(--ease-out), background var(--t) var(--ease);
}
.rules__ico svg { width: 19px; height: 19px; }
.rules--cards > li:hover .rules__ico { transform: translateY(-2px) scale(1.06); }

/* A card list carries its own count, so the numbered variant drops the
   separate number column and prints the figure into the glyph instead. */
.rules--cards .rules__n { grid-row: auto; width: auto; margin: 0; }

/* ---------- 9. Product system --------------------------------------------- */

/* A product presentation: art panel one side, argument the other, sides
   alternating down the page. Not a card — a spread. */
.psys { display: grid; gap: clamp(26px, 3.2vw, 42px); align-items: center; }
.psys + .psys { margin-top: clamp(48px, 6vw, 88px); padding-top: clamp(48px, 6vw, 88px); border-top: 1px solid var(--border); }
@media (min-width: 900px) {
  .psys { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: clamp(40px, 5vw, 72px); }
  .psys--flip .psys__art { order: 2; }
}
.psys--ec { --p: var(--ec); --p-tint: var(--ec-tint); --p-line: var(--ec-line); }
.sec--light .psys--ec { --p: var(--ec-ink); }

.psys__art {
  position: relative;
  padding: clamp(22px, 2.8vw, 34px);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  background: linear-gradient(180deg, var(--p-tint), transparent 62%), var(--surface);
  box-shadow: var(--sheen);
  overflow: hidden;
}
.psys__art svg { width: 100%; height: auto; overflow: visible; }
.psys__tag {
  display: inline-flex; align-items: center; gap: 8px;
  margin: 0 0 16px;
  font: var(--w-strong) 12px/1.2 var(--font);
  text-transform: uppercase; letter-spacing: .13em;
  color: var(--p);
}
.psys__tag::before { content: ""; width: 8px; height: 8px; border-radius: 2px; background: currentColor; }
.psys__name { font-size: clamp(25px, 1.6vw + 16px, 34px); line-height: 1.12; letter-spacing: -.026em; font-weight: var(--w-head); }
.psys__line { margin: 14px 0 0; font-size: clamp(17px, .6vw + 15px, 19px); line-height: 1.45; letter-spacing: -.014em; color: var(--ink); font-weight: var(--w-strong); max-width: 22em; }
.psys__body { margin: 14px 0 0; color: var(--ink-mid); max-width: 38em; }
.psys__meta {
  display: flex; flex-wrap: wrap; gap: 6px 18px;
  margin: 18px 0 0; padding-top: 16px;
  border-top: 1px solid var(--border);
  font-size: 14.5px; color: var(--ink-low);
}
.psys__meta b { color: var(--ink); font-weight: var(--w-strong); }
.psys .cta-row { margin-top: 22px; }

/* Product identity paint inside a diagram. */
.p-node  { fill: rgba(146, 184, 222, .05); stroke: var(--p-line); stroke-width: 1; }
.p-line  { fill: none; stroke: var(--p); stroke-opacity: .45; stroke-width: 1.25; }
.p-fill  { fill: var(--p); }
.p-t     { font: var(--w-strong) 12.5px/1 var(--font); fill: var(--ink); letter-spacing: -.008em; }
.p-t--sm { font: var(--w-body) 11px/1 var(--font); fill: var(--ink-low); letter-spacing: .02em; }
.sec--light .p-node { fill: rgba(10, 24, 38, .022); }




/* The sequence diagram needs more width than a product spread normally
   gives its art column, and it carries its own small type scale. */
.psys__art--wide svg { max-width: 100%; }
.seq-day  { font: var(--w-strong) 11.5px/1 var(--font); letter-spacing: .13em; fill: var(--ink-low); }
.seq-lbl  { font: var(--w-body) 12.5px/1 var(--font); fill: var(--ink-mid); }
.seq-cap  { font: var(--w-strong) 11.5px/1 var(--font); letter-spacing: .1em; text-transform: uppercase; fill: var(--ink-low); }
.seq-h    { font: var(--w-strong) 15px/1 var(--font); letter-spacing: -.012em; fill: var(--ink); }
.seq-p    { font: var(--w-body) 13px/1 var(--font); fill: var(--ink-mid); }
.seq-tick { fill: var(--p, var(--accent)); }
.sec--light .seq-day { fill: var(--ink-low); }

/* ---------- 10. Pricing --------------------------------------------------- */

.rung__inc { display: grid; gap: 9px 22px; margin: 0; }
@media (min-width: 560px) { .rung__inc { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.rung__inc li { position: relative; padding-left: 20px; font-size: 15px; line-height: 1.5; color: var(--ink-mid); }
.rung__inc li::before {
  content: ""; position: absolute; left: 2px; top: .5em;
  width: 7px; height: 4px;
  border-left: 1.5px solid var(--ec); border-bottom: 1.5px solid var(--ec);
  transform: rotate(-45deg);
}
.sec--light .rung__inc li::before { border-color: var(--ec-ink); }
.rung__inc .is-spend { color: var(--ink); font-weight: var(--w-strong); }

/* ---- 10b. The Echo Pilot ------------------------------------------------ */
.pilot { display: grid; gap: clamp(26px, 3.2vw, 40px); align-items: start; }
@media (min-width: 820px) { .pilot { grid-template-columns: minmax(0, 1fr) minmax(0, 1fr); gap: clamp(36px, 4vw, 56px); } }
.pilot__price { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 12px; margin: clamp(22px, 2.6vw, 28px) 0 0; }
.pilot__price b { font-size: clamp(34px, 2vw + 22px, 44px); line-height: 1; letter-spacing: -.034em; font-weight: var(--w-display); font-variant-numeric: tabular-nums; color: var(--ink); }
.pilot__price span { font-size: 14.5px; color: var(--ink-low); }
.pilot__note { margin: 20px 0 0; padding-top: 16px; border-top: 1px solid var(--border); font-size: 13.5px; line-height: 1.6; color: var(--ink-low); }

/* ---- 10c. The engagement toggle and the quoted offer --------------------
   One-time and ongoing are the same service run two ways, so one card shows
   both and a real radio group switches which price is visible.

   Two mechanisms, on purpose. site.js mirrors the choice onto .plans as a
   class; the :has() rules do the same job with JavaScript switched off. Where
   neither is available — an old engine, no script — both prices render, which
   is honest rather than broken. Everything that toggles is a block-level
   wrapper, so display:block is always the correct value to restore.
   ------------------------------------------------------------------------ */
.plans { margin-top: clamp(26px, 3vw, 36px); }

.seg {
  display: inline-flex; flex-wrap: wrap; gap: 4px;
  padding: 4px;
  border: 1px solid var(--border-strong); border-radius: 999px;
  background: var(--bg-alt);
}
.seg__in { position: absolute; width: 1px; height: 1px; opacity: 0; pointer-events: none; }
.seg__lb {
  display: inline-flex; align-items: center; justify-content: center;
  min-height: 44px; padding: 10px 20px;
  border-radius: 999px;
  font: var(--w-strong) 15px/1.2 var(--font); letter-spacing: -.012em;
  color: var(--ink-mid); cursor: pointer;
  transition: background var(--t) var(--ease), color var(--t) var(--ease);
}
.seg__lb:hover { color: var(--ink); }
.seg__in:checked + .seg__lb { background: var(--accent); color: #14202C; }
.sec--light .seg__in:checked + .seg__lb { background: var(--brand-ink); color: #FFF; }
.seg__in:focus-visible + .seg__lb { outline: 2px solid var(--accent); outline-offset: 3px; }

.plans__term {
  margin: clamp(16px, 2vw, 22px) 0 0;
  font-size: 14.5px; line-height: 1.6; color: var(--ink-mid); max-width: 62ch;
}
.plans__term b { color: var(--ink); font-weight: var(--w-strong); }

.plangrid { display: grid; gap: 14px; margin-top: clamp(24px, 2.8vw, 32px); }

/* ---- The quoted offer ---------------------------------------------------
   There is one service, so there is one card. It was a four-across tier grid
   until 2026-09-05; a grid of packages invites a visitor to shop between
   columns, and there is nothing to shop between when the real price comes
   from valuing the list. What replaced it leads with the starting figure,
   then says plainly what moves it.
   ------------------------------------------------------------------------ */
.quote {
  display: grid; gap: clamp(28px, 3.4vw, 44px);
  margin-top: clamp(24px, 2.8vw, 32px);
  padding: clamp(24px, 3vw, 40px);
  border: 1px solid var(--border); border-radius: var(--r-lg);
  background: linear-gradient(180deg, rgba(52, 211, 153, .06), transparent 55%), var(--surface);
  box-shadow: var(--sheen);
}
@media (min-width: 900px) {
  .quote { grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); gap: clamp(36px, 4vw, 64px); }
}
.quote__tag {
  display: inline-flex; align-items: center; gap: 8px;
  margin: 0;
  font: var(--w-strong) 12px/1.2 var(--font);
  text-transform: uppercase; letter-spacing: .13em; color: var(--ec);
}
.sec--light .quote__tag { color: var(--ec-ink); }
.quote__tag::before { content: ""; width: 8px; height: 8px; border-radius: 2px; background: currentColor; }

.quote__price { display: block; margin-top: clamp(18px, 2.2vw, 24px); }
.quote__from {
  display: block; margin-bottom: 6px;
  font: var(--w-strong) 13px/1.2 var(--font);
  text-transform: uppercase; letter-spacing: .12em; color: var(--ink-low);
}
.quote__price b {
  display: block;
  font-size: clamp(44px, 3.4vw + 26px, 66px); line-height: .96;
  letter-spacing: -.038em; font-weight: var(--w-display);
  font-variant-numeric: tabular-nums; color: var(--ink);
}
.quote__per { display: block; margin-top: 10px; font-size: 14.5px; line-height: 1.5; color: var(--ink-low); }
.quote__line { margin: clamp(18px, 2.2vw, 24px) 0 0; font-size: 15.5px; line-height: 1.6; color: var(--ink-mid); }
.quote__line b { color: var(--ink); font-weight: var(--w-strong); }
.quote .cta-row { margin-top: clamp(22px, 2.6vw, 28px); }
.quote .cta-row .btn { width: 100%; }
@media (min-width: 480px) { .quote .cta-row .btn { width: auto; } }

.quote__h {
  margin: 0 0 14px;
  font: var(--w-strong) 12px/1.2 var(--font);
  text-transform: uppercase; letter-spacing: .13em; color: var(--ink-mid);
}
.quote__h + * { margin-top: 0; }
.quote__group + .quote__group { margin-top: clamp(24px, 2.8vw, 32px); padding-top: clamp(22px, 2.6vw, 28px); border-top: 1px solid var(--border); }

/* The four things that actually move the number. Stated as inputs, not as a
   pricing formula, because the formula is a conversation and not a table. */
.factors { display: grid; gap: 14px; margin: 0; }
.factors > li { display: grid; grid-template-columns: auto minmax(0, 1fr); gap: 4px 14px; }
.factors b {
  grid-column: 2;
  font: var(--w-strong) 15.5px/1.35 var(--font); letter-spacing: -.014em; color: var(--ink);
}
.factors p { grid-column: 2; margin: 0; font-size: 14.5px; line-height: 1.55; color: var(--ink-mid); }
.factors__n {
  grid-row: span 2;
  display: grid; place-items: center;
  width: 26px; height: 26px; margin-top: 2px;
  border: 1px solid var(--accent-line); border-radius: 50%;
  background: var(--accent-tint);
  font: var(--w-strong) 12px/1 var(--font);
  font-variant-numeric: tabular-nums;
  color: var(--accent);
}

/* ---- The starting-price guide -------------------------------------------
   A visitor who is told "from $1,500" and nothing else assumes the worst.
   These are the same four bands the calculator prices against, so a visitor
   who compares the two never finds a contradiction. If one changes, both
   change, and so does Terms section 7.
   ------------------------------------------------------------------------ */
.plan__more { display: block; margin: 16px 0 0; border-top: 1px solid var(--border); }
.plan__more summary {
  display: flex; align-items: center; justify-content: space-between; gap: 12px;
  min-height: 44px; padding: 12px 0 4px;
  list-style: none; cursor: pointer;
  font: var(--w-strong) 13.5px/1.4 var(--font); color: var(--ink-mid);
}
.plan__more summary::-webkit-details-marker { display: none; }
.plan__more summary:hover { color: var(--accent); }
.plan__more summary:hover .acc__ico { color: var(--accent); }
.plan__more[open] .acc__ico::after { transform: translate(-50%, -50%) rotate(90deg); opacity: 0; }
.plan__more .rung__inc { grid-template-columns: minmax(0, 1fr); gap: 8px; padding: 6px 0 14px; }
.plan__more .rung__inc li { font-size: 14px; }

/* The toggle. Default state is one-time; nothing here needs script to be
   readable, and both prices simply show if neither mechanism applies. */
.plans .is-month { display: none; }
.plans.is-mode-once  .is-month { display: none; }
.plans.is-mode-month .is-month { display: block; }
.plans.is-mode-month .is-once  { display: none; }
.plans:has(#mode-month:checked) .is-month { display: block; }
.plans:has(#mode-month:checked) .is-once  { display: none; }

/* ---- 10d. The illustrative sample report --------------------------------
   Deliberately NOT styled like a case study. The dashed frame and the two
   labels exist so this can never be mistaken for a client result.
   ------------------------------------------------------------------------ */
.rep {
  margin-top: clamp(24px, 3vw, 34px);
  padding: clamp(20px, 2.6vw, 30px);
  border: 1.5px dashed var(--border-strong); border-radius: var(--r-lg);
  background: var(--bg-alt);
}
.rep__flag {
  display: inline-block; margin: 0 0 clamp(20px, 2.4vw, 26px);
  padding: 6px 12px;
  border: 1px solid var(--ember-line); border-radius: var(--r-xs);
  background: var(--ember-tint);
  font: var(--w-strong) 12px/1.3 var(--font);
  text-transform: uppercase; letter-spacing: .1em;
  color: var(--ember);
}
.rep__flag--foot {
  display: block; margin: clamp(20px, 2.4vw, 26px) 0 0;
  border: 0; background: none; padding: 0;
  text-transform: none; letter-spacing: 0;
  font: var(--w-body) 13px/1.6 var(--font); color: var(--ink-low);
}
.rep__head { display: grid; gap: 14px 30px; padding-bottom: 18px; border-bottom: 1px solid var(--border); }
@media (min-width: 560px) { .rep__head { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.rep__k { margin: 0; font: var(--w-strong) 11.5px/1.2 var(--font); text-transform: uppercase; letter-spacing: .13em; color: var(--ink-low); }
.rep__v { margin: 6px 0 0; font: var(--w-strong) 15.5px/1.4 var(--font); letter-spacing: -.014em; color: var(--ink); }
.rep__stats { display: grid; gap: 0; margin: 0 0 clamp(22px, 2.6vw, 30px); }
@media (min-width: 640px) { .rep__stats { grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: clamp(24px, 3vw, 44px); } }
.rep__stats li {
  display: flex; align-items: baseline; justify-content: space-between; gap: 16px;
  padding: 11px 0; border-bottom: 1px solid var(--border);
  font-size: 14.5px; color: var(--ink-mid);
}
.rep__stats b { font: var(--w-strong) 16px/1.2 var(--font); font-variant-numeric: tabular-nums; color: var(--ink); }
.rep__stats .is-key { color: var(--ink); }
.rep__stats .is-key b { color: var(--ec); font-size: 19px; }
.sec--light .rep__stats .is-key b { color: var(--ec-ink); }
.rep__tablewrap { overflow-x: auto; }
.rep__table { width: 100%; min-width: 460px; border-collapse: collapse; text-align: left; font-size: 14.5px; }
.rep__table caption { text-align: left; padding-bottom: 12px; font: var(--w-strong) 11.5px/1.2 var(--font); text-transform: uppercase; letter-spacing: .13em; color: var(--ink-low); }
.rep__table th, .rep__table td { padding: 11px 14px 11px 0; border-top: 1px solid var(--border); vertical-align: top; }
.rep__table thead th { border-top: 0; padding-top: 0; font: var(--w-strong) 13px/1.3 var(--font); color: var(--ink); }
.rep__table tbody th { font: var(--w-body) 14.5px/1.5 var(--font); color: var(--ink-mid); }
.rep__table td { color: var(--ink); font-variant-numeric: tabular-nums; }
@media (max-width: 560px) {
  /* Stack it rather than scroll it — same mechanism as the homepage
     comparison table, and the same reason: three columns do not read at
     320px, and a sideways scroll inside a report is easy to miss. */
  .rep__tablewrap { overflow-x: visible; }
  .rep__table { min-width: 0; }
  .rep__table, .rep__table tbody, .rep__table tr, .rep__table th, .rep__table td { display: block; }
  .rep__table thead { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }
  .rep__table tr { padding-block: 4px; border-top: 1px solid var(--border); }
  .rep__table tbody th { padding: 12px 0 6px; border: 0; font-weight: var(--w-strong); color: var(--ink); }
  .rep__table td { padding: 0 0 6px; border: 0; }
  .rep__table td::before { content: attr(data-p) " · "; color: var(--ink-low); font-weight: var(--w-strong); }
}
.rep__next { margin: clamp(20px, 2.4vw, 26px) 0 0; padding-top: 16px; border-top: 1px solid var(--border); font-size: 14.5px; line-height: 1.55; color: var(--ink-mid); }
.rep__next b { display: block; margin-bottom: 3px; font: var(--w-strong) 11.5px/1.2 var(--font); text-transform: uppercase; letter-spacing: .13em; color: var(--ink-low); }

/* ---------- 11. Accordion and definition lists ---------------------------- */

.acc { border-top: 1px solid var(--border); }
.acc details { border-bottom: 1px solid var(--border); }
.acc summary {
  display: flex; align-items: flex-start; justify-content: space-between; gap: 20px;
  padding: 20px 0;
  min-height: 44px;
  font-size: clamp(16.5px, .4vw + 15px, 18px);
  line-height: 1.45;
  letter-spacing: -.014em;
  font-weight: var(--w-strong);
  color: var(--ink);
  cursor: pointer;
  list-style: none;
  transition: color var(--t) var(--ease);
}
.acc summary::-webkit-details-marker { display: none; }
.acc summary:hover { color: var(--accent); }
.acc__ico { position: relative; flex: 0 0 auto; width: 20px; height: 20px; margin-top: 2px; color: var(--ink-low); transition: color var(--t) var(--ease); }
.acc__ico::before, .acc__ico::after {
  content: ""; position: absolute; left: 50%; top: 50%; background: currentColor;
  transform: translate(-50%, -50%);
  transition: transform var(--t) var(--ease), opacity var(--t) var(--ease);
}
.acc__ico::before { width: 13px; height: 1.5px; }
.acc__ico::after  { width: 1.5px; height: 13px; }
.acc summary:hover .acc__ico { color: var(--accent); }
.acc details[open] .acc__ico::after { transform: translate(-50%, -50%) rotate(90deg); opacity: 0; }
.acc__a { padding: 0 40px 24px 0; color: var(--ink-mid); font-size: 15.5px; line-height: 1.62; max-width: 62em; }
.acc__a p:last-child { margin-bottom: 0; }
/* Without JavaScript the accordion simply snaps open, which is the correct
   fallback; with it, the panel eases in. */
.js .acc details[open] .acc__a { animation: accIn var(--t-slow) var(--ease); }
@keyframes accIn { from { opacity: 0; transform: translateY(-4px); } }

.dl { display: grid; }
.dl > div { display: grid; gap: 4px 24px; padding: 18px 0; border-top: 1px solid var(--border); }
.dl > div:last-child { border-bottom: 1px solid var(--border); }
@media (min-width: 680px) { .dl > div { grid-template-columns: minmax(0, 1fr) minmax(0, 2fr); } }
.dl dt { font: var(--w-strong) 15px/1.5 var(--font); letter-spacing: -.01em; color: var(--ink); }
.dl dd { margin: 0; color: var(--ink-mid); font-size: 15.5px; }

/* ---------- 12. Forms ----------------------------------------------------- */

.form {
  padding: clamp(22px, 3vw, 38px);
  border: 1px solid var(--border);
  border-radius: var(--r-lg);
  background: var(--surface);
  box-shadow: var(--sheen);
  text-align: left;
}
.form__grid { display: grid; gap: 18px; }
@media (min-width: 680px) { .form__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.form__row--wide { grid-column: 1 / -1; }

.form label, .form legend {
  display: block;
  margin-bottom: 8px;
  font: var(--w-strong) 13px/1.4 var(--font);
  letter-spacing: -.006em;
  color: var(--ink-mid);
}
.form .req { color: var(--accent); }

.form input[type="text"], .form input[type="email"], .form input[type="tel"],
.form input[type="number"], .form select, .form textarea {
  width: 100%;
  min-height: 48px;
  padding: 12px 14px;
  border: 1px solid var(--border-strong);
  border-radius: var(--r-sm);
  background: rgba(6, 15, 27, .5);
  color: var(--ink);
  font: var(--w-body) 16px/1.45 var(--font);
  transition: border-color var(--t) var(--ease), background var(--t) var(--ease), box-shadow var(--t) var(--ease);
  -webkit-appearance: none; appearance: none;
}
.form textarea { min-height: 112px; resize: vertical; }

/* The dark-band fill is a translucent navy, which composites to grey on
   paper. .calc already had this override; .form did not, because until the
   contact form landed on /support/ every form on the site sat on a dark
   band. Any new form on .sec--light needs this, so it lives with the
   component rather than with the page. */
.sec--light .form input[type="text"], .sec--light .form input[type="email"],
.sec--light .form input[type="tel"], .sec--light .form input[type="number"],
.sec--light .form select, .sec--light .form textarea {
  background-color: #FFF;
}
.sec--light .form select {
  background-image:
    linear-gradient(45deg, transparent 50%, var(--ink-mid) 50%),
    linear-gradient(135deg, var(--ink-mid) 50%, transparent 50%);
}
.form ::placeholder { color: var(--ink-low); opacity: 1; }
.form input:hover, .form select:hover, .form textarea:hover { border-color: var(--ink-low); }
.form input:focus, .form select:focus, .form textarea:focus {
  outline: none;
  border-color: var(--accent);
  background: rgba(6, 15, 27, .78);
  box-shadow: 0 0 0 3px var(--accent-tint);
}
/* :user-invalid only fires after the visitor has actually interacted, so a
   pristine required field is never painted as an error. */
.form input:user-invalid, .form textarea:user-invalid, .form select:user-invalid { border-color: var(--ember); }
.form select {
  padding-right: 42px;
  background-image:
    linear-gradient(45deg, transparent 50%, var(--ink-mid) 50%),
    linear-gradient(135deg, var(--ink-mid) 50%, transparent 50%);
  background-position: calc(100% - 21px) calc(50% + 2px), calc(100% - 15px) calc(50% + 2px);
  background-size: 6px 6px, 6px 6px;
  background-repeat: no-repeat;
}
.form select option { background: var(--navy-800); color: var(--ink); }

.form fieldset { margin: 0 0 22px; padding: 0; border: 0; }
.form__actions { display: flex; flex-wrap: wrap; align-items: center; gap: 16px; margin-top: 26px; }
.form__note { flex: 1 1 240px; margin: 0; font-size: 13.5px; line-height: 1.55; color: var(--ink-low); }
.form__hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }
.form__result {
  margin: 22px 0 0;
  padding: 16px 18px;
  border: 1px solid var(--accent-line);
  border-radius: var(--r-sm);
  background: var(--accent-tint);
  font-size: 15.5px; line-height: 1.6;
  color: var(--ink);
}
.form__result.is-bad { border-color: var(--ember-line); background: var(--ember-tint); }
.form__result b { display: block; margin-bottom: 4px; }
.form.is-sending button[type="submit"] { opacity: .6; pointer-events: none; }


/* ---- 12b. Checkbox groups -----------------------------------------------
   Consent is never pre-ticked and never required to submit. The one required
   checkbox on this site is the client confirming that opt-outs are excluded,
   which is a statement of fact about their own list, not a marketing consent.
   ------------------------------------------------------------------------ */
.checks { margin: 0; padding: 0; border: 0; }
.checks legend { display: block; margin-bottom: 6px; padding: 0; }
.checks__hint { margin: 0 0 12px; font-size: 13.5px; line-height: 1.55; color: var(--ink-low); max-width: 52em; }
.form .check {
  display: flex; align-items: flex-start; gap: 12px;
  min-height: 44px; padding: 10px 12px; margin-bottom: 6px;
  border: 1px solid transparent; border-radius: var(--r-sm);
  cursor: pointer;
  transition: background var(--t) var(--ease), border-color var(--t) var(--ease);
}
.form .check:hover { background: rgba(255, 255, 255, .05); }
.sec--light .form .check:hover { background: rgba(10, 24, 38, .04); }
.form .check input[type="checkbox"] {
  flex: 0 0 auto; width: 20px; height: 20px; margin: 1px 0 0;
  accent-color: var(--brand); cursor: pointer;
}
.form .check span {
  display: block; margin: 0;
  font: var(--w-body) 14.5px/1.55 var(--font); color: var(--ink-mid);
}
.form .check--req { border-color: var(--border-strong); background: var(--bg-alt); }
.form .check--req span { color: var(--ink); }

/* ---- 12b. The get-started flow -----------------------------------------
   Every fieldset ships visible with a working submit. site.js adds .is-wiz
   and only then starts hiding steps, so with JavaScript off this is one long
   ordinary form that still posts. Required attributes live in the HTML and
   must never move into script.
   ------------------------------------------------------------------------ */
.wiz { max-width: 760px; margin-inline: auto; }
.wiz__rail { display: none; margin-bottom: clamp(24px, 3vw, 34px); }
.is-wiz .wiz__rail { display: block; }
.wiz__bar { height: 3px; border-radius: 3px; background: var(--border); overflow: hidden; }
.wiz__bar i { display: block; height: 100%; width: var(--p, 20%); border-radius: 3px; background: var(--accent); transition: width var(--t-slow) var(--ease); }
.wiz__count {
  display: flex; justify-content: space-between; gap: 16px; margin-top: 12px;
  font: var(--w-strong) 12px/1.3 var(--font);
  text-transform: uppercase; letter-spacing: .11em;
  color: var(--ink-low);
}
.wiz__count b { color: var(--accent); font-weight: var(--w-strong); }

.wiz__step { margin: 0 0 clamp(28px, 3.6vw, 40px); padding: 0; border: 0; }
.is-wiz .wiz__step { display: none; margin-bottom: 0; }
.is-wiz .wiz__step.is-on { display: block; }
.wiz__q {
  display: block; margin: 0 0 8px; padding: 0;
  font-size: clamp(22px, 1.4vw + 16px, 30px);
  font-weight: var(--w-head);
  letter-spacing: -.026em;
  line-height: 1.16;
  color: var(--ink);
}
.wiz__hint { margin: 0 0 clamp(20px, 2.4vw, 26px); font-size: 15.5px; line-height: 1.6; color: var(--ink-mid); max-width: 46em; }

.opts { display: grid; gap: 10px; margin: 0; }
/* Written as `.form .opt`, not `.opt`: the small-label rule above is
   `.form label` and would otherwise outrank a bare single class. */
.form .opt {
  position: relative; display: block; margin: 0;
  padding: 18px 20px;
  border: 1px solid var(--border-strong);
  border-radius: var(--r-sm);
  background: rgba(255, 255, 255, .025);
  cursor: pointer;
  transition: border-color var(--t) var(--ease), background var(--t) var(--ease), transform var(--t-fast) var(--ease);
}
.form .opt:hover { border-color: var(--ink-low); background: rgba(255, 255, 255, .05); }
.form .opt:active { transform: scale(.996); }
.form .opt input { position: absolute; opacity: 0; width: 0; height: 0; }
.form .opt b { display: block; font: var(--w-strong) 16.5px/1.35 var(--font); letter-spacing: -.016em; color: var(--ink); }
.form .opt span { display: block; margin-top: 6px; font: var(--w-body) 14.5px/1.55 var(--font); color: var(--ink-low); }
.form .opt em {
  display: block; margin-top: 10px; font-style: normal;
  font: var(--w-strong) 12px/1.3 var(--font);
  text-transform: uppercase; letter-spacing: .11em;
  color: var(--accent);
}
.form .opt:has(input:checked) { border-color: var(--accent); background: var(--accent-tint); box-shadow: 0 0 0 1px var(--accent); }
.form .opt:has(input:checked) b { color: var(--accent); }
.form .opt input:checked ~ b { color: var(--accent); }   /* fallback without :has() */
.form .opt input:focus-visible ~ b { outline: 2px solid var(--accent); outline-offset: 4px; border-radius: var(--r-xs); }
.form .opt__price {
  position: absolute; top: 18px; right: 20px;
  font: var(--w-display) 19px/1 var(--font);
  letter-spacing: -.03em; font-variant-numeric: tabular-nums;
  color: var(--ink);
}
.form .opt:has(input:checked) .opt__price { color: var(--accent); }
.form .opt--priced b, .form .opt--priced span { padding-right: 92px; }

.wiz__nav {
  display: flex; flex-wrap: wrap; align-items: center; gap: 14px;
  margin-top: clamp(24px, 3vw, 32px);
  padding-top: clamp(20px, 2.6vw, 26px);
  border-top: 1px solid var(--border);
}
.wiz__nav .btn--back { order: -1; }
.wiz__err { flex: 1 1 100%; margin: 0; font-size: 14.5px; color: var(--ember); }
.wiz__err:empty { display: none; }
.is-wiz .wiz__send { display: none; }

.wiz__recap {
  display: grid; gap: 10px;
  margin: 0 0 clamp(20px, 2.6vw, 28px);
  padding: clamp(16px, 2vw, 22px);
  border: 1px solid var(--border);
  border-radius: var(--r-sm);
  background: rgba(255, 255, 255, .03);
}
.wiz__recap:empty { display: none; }
.wiz__recap div { display: flex; flex-wrap: wrap; gap: 4px 12px; font-size: 15px; }
.wiz__recap dt { flex: 0 0 auto; min-width: 8.5em; font: var(--w-strong) 12px/1.7 var(--font); text-transform: uppercase; letter-spacing: .11em; color: var(--ink-low); }
.wiz__recap dd { margin: 0; color: var(--ink); font-weight: var(--w-strong); letter-spacing: -.01em; }

/* ---- 12c. The dormant-list calculator -----------------------------------
   A financial diagnostic, not an ROI widget. It reports conversations and
   what one customer is worth. It never multiplies every conversation by full
   customer value and presents the total as money already earned. All arithmetic
   is deterministic and lives in site.js.
   ------------------------------------------------------------------------ */
.calc__grid { display: grid; gap: clamp(28px, 3.4vw, 44px); }
@media (min-width: 940px) { .calc__grid { grid-template-columns: minmax(0, 5fr) minmax(0, 7fr); gap: clamp(36px, 4vw, 60px); align-items: start; } }

.calc__side {
  display: grid; gap: clamp(18px, 2vw, 22px);
  padding: clamp(20px, 2.4vw, 28px);
  border: 1px solid var(--border); border-radius: var(--r);
  background: var(--surface); box-shadow: var(--sheen);
}
.calc__main { min-width: 0; }
.calc__field > :last-child { margin-bottom: 0; }
.calc label { display: block; margin-bottom: 8px; font: var(--w-strong) 13px/1.4 var(--font); color: var(--ink-mid); }
.calc input[type="number"], .calc select {
  width: 100%; min-height: 48px; padding: 12px 14px;
  border: 1px solid var(--border-strong); border-radius: var(--r-sm);
  background: rgba(6, 15, 27, .5); color: var(--ink);
  font: var(--w-body) 16px/1.45 var(--font);
  -webkit-appearance: none; appearance: none;
  transition: border-color var(--t) var(--ease), box-shadow var(--t) var(--ease);
}
.sec--light .calc input[type="number"], .sec--light .calc select { background: #FFF; }
.calc select {
  padding-right: 40px;
  background-image: var(--arrow);
  background-repeat: no-repeat; background-position: right 14px center; background-size: 15px;
  transform: rotate(0deg);
}
.calc select option { background: var(--navy-800); color: var(--ink); }
.calc input[type="number"]:hover, .calc select:hover { border-color: var(--ink-low); }
.calc input[type="number"]:focus, .calc select:focus { outline: none; border-color: var(--accent); box-shadow: 0 0 0 3px var(--accent-tint); }
.calc__money { position: relative; }
/* .calc input[type="number"] below sets the padding shorthand and outranks a
   bare .calc__money input, which left the $ sign printing on top of the first
   digit. Match its specificity rather than reordering the file. */
.calc .calc__money input[type="number"] { padding-left: 32px; }
.calc__money::before { content: "$"; position: absolute; left: 14px; top: 50%; transform: translateY(-50%); color: var(--ink-low); font-size: 16px; }
.calc__unit { display: flex; align-items: center; gap: 10px; }
.calc__unit input { flex: 1 1 auto; }
.calc__unit span { flex: 0 0 auto; font-size: 14.5px; color: var(--ink-low); }
.calc__hint { margin: 8px 0 0; font-size: 13px; line-height: 1.5; color: var(--ink-low); }

.calc__scen { margin: 0 0 clamp(20px, 2.4vw, 26px); padding: 0; border: 0; }
.calc__scen legend { display: block; margin-bottom: 12px; padding: 0; font: var(--w-strong) 13px/1.4 var(--font); color: var(--ink-mid); }
.scen { display: grid; gap: 10px; }
@media (min-width: 520px) { .scen { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
.scen__o {
  position: relative; display: block;
  min-height: 44px; padding: 14px 16px;
  border: 1px solid var(--border-strong); border-radius: var(--r-sm);
  background: var(--surface); cursor: pointer;
  transition: border-color var(--t) var(--ease), background var(--t) var(--ease), box-shadow var(--t) var(--ease);
}
.scen__o:hover { border-color: var(--ink-low); }
.scen__o input { position: absolute; opacity: 0; width: 0; height: 0; }
.scen__o b { display: block; font: var(--w-strong) 15px/1.3 var(--font); letter-spacing: -.014em; color: var(--ink); }
.scen__o span { display: block; margin-top: 4px; font: var(--w-display) 20px/1 var(--font); letter-spacing: -.03em; font-variant-numeric: tabular-nums; color: var(--ink-low); }
.scen__o:has(input:checked) { border-color: var(--accent); background: var(--accent-tint); box-shadow: 0 0 0 1px var(--accent); }
.scen__o input:checked ~ b { color: var(--accent); }   /* fallback without :has() */
.scen__o:has(input:checked) span { color: var(--accent); }
.scen__o input:focus-visible ~ b { outline: 2px solid var(--accent); outline-offset: 4px; border-radius: var(--r-xs); }

.calc__def {
  margin: 0 0 clamp(20px, 2.4vw, 26px);
  padding: 14px 16px;
  border-left: 2px solid var(--border-strong); border-radius: 0 var(--r-xs) var(--r-xs) 0;
  background: var(--bg-alt);
  font-size: 14px; line-height: 1.6; color: var(--ink-mid);
}
.calc__def b { color: var(--ink); font-weight: var(--w-strong); }

.calc__out { display: grid; gap: 0; border-top: 1px solid var(--border); }
@media (min-width: 760px) { .calc__out { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
.calc__res { padding: 20px 0; border-bottom: 1px solid var(--border); }
@media (min-width: 760px) { .calc__res + .calc__res { padding-left: 24px; border-left: 1px solid var(--border); } }
.calc__res-k { display: block; font: var(--w-strong) 11.5px/1.3 var(--font); text-transform: uppercase; letter-spacing: .12em; color: var(--ink-low); }
.calc__res-v { display: block; margin-top: 12px; font-size: clamp(26px, 1.6vw + 16px, 34px); line-height: 1; letter-spacing: -.034em; font-weight: var(--w-display); font-variant-numeric: tabular-nums; color: var(--accent); }
.calc__res-sub { display: block; margin-top: 10px; font-size: 13.5px; line-height: 1.5; color: var(--ink-mid); }
.calc__res.is-idle .calc__res-v { color: var(--ink-mid); }

.calc__h { margin: clamp(26px, 3vw, 34px) 0 14px; font-size: 17px; letter-spacing: -.018em; }
.closes { display: grid; gap: 10px; }
@media (min-width: 620px) { .closes { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1180px) { .closes { grid-template-columns: repeat(4, minmax(0, 1fr)); } }
.closes li {
  padding: 16px 18px;
  border: 1px solid var(--border); border-radius: var(--r-sm);
  background: var(--surface); box-shadow: var(--sheen);
}
.closes li[hidden] { display: none; }
.closes__n { display: block; font: var(--w-strong) 12px/1.3 var(--font); text-transform: uppercase; letter-spacing: .1em; color: var(--ink-low); }
.closes__v { display: block; margin-top: 10px; font-size: clamp(20px, 1vw + 15px, 24px); line-height: 1; letter-spacing: -.028em; font-weight: var(--w-display); font-variant-numeric: tabular-nums; color: var(--ink); }

.calc__price {
  margin: clamp(22px, 2.6vw, 28px) 0 0;
  padding: clamp(18px, 2.2vw, 24px);
  border: 1px solid var(--accent-line); border-radius: var(--r);
  background: var(--accent-tint);
  font-size: 15.5px; line-height: 1.6; color: var(--ink-mid);
}
.calc__price b { color: var(--ink); font-weight: var(--w-strong); font-variant-numeric: tabular-nums; }

.calc__even { margin: clamp(20px, 2.4vw, 26px) 0 0; font-size: clamp(16px, .5vw + 14px, 18px); line-height: 1.55; letter-spacing: -.012em; color: var(--ink); }
.calc__role { margin: 16px 0 0; font-size: 14.5px; line-height: 1.6; color: var(--ink-mid); max-width: 62ch; }
.calc__role b { color: var(--ink); font-weight: var(--w-strong); }
.calc__note { margin: 14px 0 0; padding-top: 14px; border-top: 1px solid var(--border); font-size: 13px; line-height: 1.6; color: var(--ink-low); max-width: 68ch; }
.calc__note a { color: var(--accent); }

/* ---- 12d. The homepage mini calculator ----------------------------------
   Two inputs and one figure, on the same default rates as the full one. It
   is a teaser, not a second source of truth: the rates are named in the
   copy and the link goes straight to the version that lets you change them.
   ------------------------------------------------------------------------ */
.mini { display: block; }
.mini__row { display: grid; gap: 14px; }
@media (min-width: 520px) { .mini__row { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.mini__f label {
  display: block; margin-bottom: 8px;
  font: var(--w-strong) 13px/1.4 var(--font); color: var(--ink-mid);
}
.mini input[type="number"] {
  width: 100%; min-height: 48px; padding: 12px 14px;
  border: 1px solid var(--border-strong); border-radius: var(--r-sm);
  background: var(--bg-alt); color: var(--ink);
  font: var(--w-strong) 17px/1.2 var(--font);
  font-variant-numeric: tabular-nums;
  transition: border-color var(--t) var(--ease), box-shadow var(--t) var(--ease);
}
.mini input[type="number"]:hover { border-color: var(--ink-low); }
.mini input[type="number"]:focus {
  outline: none; border-color: var(--accent);
  box-shadow: 0 0 0 3px var(--accent-tint);
}
.mini__money { position: relative; }
.mini .mini__money input[type="number"] { padding-left: 32px; }
.mini__money::before {
  content: "$"; position: absolute; left: 14px; top: 50%; transform: translateY(-50%);
  color: var(--ink-low); font-size: 16px;
}
.mini__out {
  margin-top: clamp(22px, 2.6vw, 28px);
  padding-top: clamp(20px, 2.4vw, 26px);
  border-top: 1px solid var(--border);
}
.mini__k {
  display: block;
  font: var(--w-strong) 12px/1.2 var(--font);
  text-transform: uppercase; letter-spacing: .13em; color: var(--ink-low);
}
.mini__v {
  display: block; margin-top: 12px;
  font-size: clamp(38px, 3vw + 22px, 54px); line-height: 1;
  letter-spacing: -.036em; font-weight: var(--w-display);
  font-variant-numeric: tabular-nums; color: var(--accent);
}
.mini__sub { display: block; margin-top: 10px; font-size: 14.5px; line-height: 1.55; color: var(--ink-mid); max-width: 42em; }
.mini__note { margin: 16px 0 0; font-size: 13px; line-height: 1.55; color: var(--ink-low); }

/* ---------- 13. Footer ---------------------------------------------------- */

.foot { background: var(--navy-900); border-top: 1px solid var(--border); padding-block: clamp(48px, 5.6vw, 76px) 32px; }
.foot__cta {
  display: grid; gap: 18px; align-items: center;
  padding-bottom: clamp(36px, 4vw, 52px);
  margin-bottom: clamp(36px, 4vw, 52px);
  border-bottom: 1px solid var(--border);
}
@media (min-width: 800px) { .foot__cta { grid-template-columns: minmax(0, 1fr) auto; gap: 32px; } }
.foot__cta p { margin: 8px 0 0; color: var(--ink-mid); max-width: 46em; }
.foot__cta .cta-row { margin-top: 0; }

.foot__top { display: grid; gap: clamp(30px, 3.4vw, 44px); }
@media (min-width: 700px)  { .foot__top { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 1000px) { .foot__top { grid-template-columns: minmax(0, 1.4fr) repeat(4, minmax(0, 1fr)); gap: clamp(24px, 2.6vw, 40px); } }
.foot__brand img { width: 140px; margin-bottom: 16px; }
.foot__brand p { color: var(--ink-mid); font-size: 15px; max-width: 34em; }
.foot__contact { display: grid; gap: 4px; margin-top: 18px; font-size: 15px; }
.foot__contact a, .foot__contact span { display: inline-flex; align-items: center; min-height: 26px; }
.foot__contact a { color: var(--ink-mid); text-decoration: none; }
.foot__contact a:hover { color: var(--brand); }
.foot h2 { margin-bottom: 14px; font: var(--w-strong) 12px/1.2 var(--font); text-transform: uppercase; letter-spacing: .13em; color: var(--ink); }
.foot li { margin-bottom: 8px; }
.foot li a { display: inline-flex; align-items: center; min-height: 26px; color: var(--ink-low); font-size: 14.5px; text-decoration: none; transition: color var(--t) var(--ease); }
.foot li a:hover { color: var(--brand); }
.foot__base {
  display: flex; flex-wrap: wrap; align-items: center; gap: 12px 24px;
  margin-top: clamp(36px, 4vw, 52px); padding-top: 24px;
  border-top: 1px solid var(--border);
  font-size: 13.5px; color: var(--ink-low);
}
.foot__base p { margin: 0; }
.foot__base nav { display: flex; flex-wrap: wrap; gap: 8px 20px; margin-left: auto; }
.foot__base nav a { display: inline-flex; align-items: center; min-height: 26px; text-decoration: none; }
.foot__base nav a:hover { color: var(--brand); }

/* Where a finger is doing the pointing, the footer links take a full 44px
   target. On a mouse-driven desktop 26px is enough and keeps the columns
   compact — which is why this is keyed on pointer type, not only on width. */
@media (pointer: coarse), (max-width: 900px) {
  .foot li { margin-bottom: 0; }
  .foot li a, .foot__contact a, .foot__contact span, .foot__base nav a { min-height: 44px; }
}

/* ---------- 14. Legal pages ----------------------------------------------- */

.legal { max-width: 74ch; }
.legal h2 { margin: clamp(34px, 3.6vw, 44px) 0 12px; font-size: clamp(21px, 1vw + 15px, 25px); letter-spacing: -.02em; }
.legal h3 { margin: 26px 0 8px; font-size: 17px; }
.legal p, .legal li { color: var(--ink-mid); }
.legal ul { margin: 0 0 1em; }
.legal ul li { position: relative; padding-left: 20px; margin-bottom: 8px; }
.legal ul li::before { content: ""; position: absolute; left: 2px; top: .62em; width: 5px; height: 5px; border-radius: 50%; background: var(--accent); opacity: .7; }
.legal__meta { margin-bottom: 28px; font-size: 14.5px; color: var(--ink-low); }
.legal a { color: var(--accent); }
.legal__part {
  margin-top: clamp(46px, 5vw, 64px);
  padding-top: 20px;
  border-top: 1px solid var(--border-strong);
  font-size: clamp(23px, 1.2vw + 16px, 28px);
  color: var(--ink);
}
.legal__part + h2 { margin-top: 26px; }

/* ---------- 15. Motion & print -------------------------------------------- */

/* Scroll entrances are opt-in and applied by JavaScript. Nothing is hidden by
   CSS alone: `.js .reveal` only matches once site.js has confirmed
   IntersectionObserver and attached the observer that reveals it. An earlier
   build put opacity:0 on every section and opened the legal pages blank —
   that is why the mechanism is built this way. Do not let .reveal hide
   anything that JavaScript is not guaranteed to bring back. */
.js .reveal {
  opacity: 0;
  transform: translateY(14px);
  transition: opacity 380ms var(--ease-out), transform 380ms var(--ease-out);
}
/* No will-change here on purpose. Opacity and transform are already
   compositor properties, and promoting every revealed block then demoting it
   again on .is-in churned layers on a page with thirty of them — it measured
   worse than leaving the browser alone. will-change belongs on the two
   CONTINUOUS animations (the wash and the ticker), not on one-shot entrances. */
.js .reveal.is-in { opacity: 1; transform: none; }
.js .reveal--d1 { transition-delay: 60ms; }
.js .reveal--d2 { transition-delay: 120ms; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
    scroll-behavior: auto !important;
  }
  .js .reveal { opacity: 1; transform: none; }
}

@media print {
  .hdr, .foot__cta, .cta-row, .burger, .nav { display: none !important; }
  body { background: #fff; color: #000; }
  .sec { padding-block: 18px; }
}

/* NOT HERE: content-visibility: auto on section.sec.
   It was measured at roughly 2.6x the scroll cost and 440ms of DCL on
   /echo/, and then reverted on 2026-09-05, because it BREAKS ANCHOR
   NAVIGATION. A deferred section has only its contain-intrinsic-size
   placeholder height, so the browser computes the wrong scroll offset for a
   fragment link and lands nowhere near it — /echo/#pricing did not scroll at
   all, leaving the target 6,400px down the page. The nav links to
   echo/#pricing, the footer links to #calculator and #report, and the
   homepage links to #how-it-works, so this is not a small edge.

   If it is ever revisited it needs either accurate per-section intrinsic
   sizes or a scroll correction after first render. Do not simply re-add it.
   The reveal handling it required is still in section 5 of site.js and is
   harmless without it. */

/* ---------- 16. Life ------------------------------------------------------
   Added 2026-09-05. The site was accurate and completely inert; this section
   is the difference between a document and a place.

   Three rules govern everything below.

   1. MOTION IS DECORATION, NEVER DELIVERY. Nothing here is the reason a word,
      a price or a control is readable. Every animated thing is either a
      pseudo-element, a generated diagram, or an enhancement layered onto
      content that is already on the page and already visible. The one
      exception, .reveal, is gated behind `.js` and handed to
      IntersectionObserver exactly as it was before, because an earlier build
      hid sections from CSS alone and opened the legal pages blank.
   2. AMBIENT MOTION IS SLOW AND IGNORABLE. Anything that loops runs over
      seconds, not milliseconds, at low contrast. If it can be noticed twice
      it is too fast.
   3. IT ALL STOPS. The reduced-motion block in section 15 already collapses
      every animation and transition on the page; the explicit overrides at
      the bottom of this section exist only where stopping mid-animation
      would leave something in a wrong END state.
   ------------------------------------------------------------------------ */

/* ---- 16a. Ambient ground ------------------------------------------------
   Two offset radial washes that drift against each other on a very long
   loop. The hero already had one static wash; this gives it a second and
   sets them both moving. Purely decorative and pointer-transparent.
   ------------------------------------------------------------------------ */
.aurora { position: relative; overflow: hidden; isolation: isolate; }
.aurora::before, .aurora::after {
  content: ""; position: absolute; z-index: -1;
  pointer-events: none;
  border-radius: 50%;
  opacity: .72;
  will-change: transform;
}
.aurora::before {
  inset: -30% 40% 40% -20%;
  background: radial-gradient(circle closest-side,
              rgba(247, 149, 82, .34) 0%, rgba(247, 149, 82, .18) 38%,
              rgba(247, 149, 82, .06) 62%, transparent 82%);
  animation: drift-a 26s var(--ease) infinite alternate;
}
.aurora::after {
  inset: 30% -20% -30% 45%;
  background: radial-gradient(circle closest-side,
              rgba(111, 183, 233, .26) 0%, rgba(111, 183, 233, .13) 38%,
              rgba(111, 183, 233, .05) 62%, transparent 82%);
  animation: drift-b 32s var(--ease) infinite alternate;
}
.sec--light .aurora::before { opacity: .26; }
.sec--light .aurora::after  { opacity: .18; }

@keyframes drift-a {
  from { transform: translate3d(0, 0, 0) scale(1); }
  to   { transform: translate3d(9%, 7%, 0) scale(1.16); }
}
@keyframes drift-b {
  from { transform: translate3d(0, 0, 0) scale(1.1); }
  to   { transform: translate3d(-8%, -6%, 0) scale(.94); }
}

/* ---- 16b. The Echo pulse ------------------------------------------------
   Concentric rings leaving a single point, forever. It is the product's own
   metaphor, a message going out and coming back, and it asserts nothing, so
   it stays on the right side of the no-invented-data rule.
   ------------------------------------------------------------------------ */
.pulse { position: relative; display: grid; place-items: center; aspect-ratio: 1; }
.pulse__core {
  position: relative; z-index: 2;
  width: 14px; height: 14px; border-radius: 50%;
  background: var(--brand);
  box-shadow: 0 0 0 6px rgba(247, 149, 82, .16), 0 0 26px rgba(247, 149, 82, .8);
}
.pulse__ring {
  position: absolute; inset: 0; margin: auto;
  width: 100%; height: 100%;
  border: 1px solid var(--ec-line);
  border-radius: 50%;
  opacity: 0;
  animation: ring 5.2s var(--ease) infinite;
}
.pulse__ring:nth-child(2) { animation-delay: 1.3s; }
.pulse__ring:nth-child(3) { animation-delay: 2.6s; }
.pulse__ring:nth-child(4) { animation-delay: 3.9s; }

@keyframes ring {
  0%   { transform: scale(.12); opacity: 0; }
  12%  { opacity: .85; }
  100% { transform: scale(1); opacity: 0; }
}

/* ---- 16c. Reveal, with stagger -----------------------------------------
   The mechanism is unchanged from section 15: CSS never hides anything on
   its own. What is new is that site.js numbers the children of a revealed
   group into --i, so a list arrives as a sequence instead of a slab. The
   cap is deliberate. Past about eight items the last one reads as broken
   rather than choreographed, so site.js clamps the index.
   ------------------------------------------------------------------------ */
.js .reveal > * { transition: opacity 380ms var(--ease-out), transform 380ms var(--ease-out); }
.js .reveal.is-stagger > * {
  opacity: 0;
  transform: translateY(12px);
  transition-delay: calc(var(--i, 0) * 45ms);
}
.js .reveal.is-stagger.is-in > * { opacity: 1; transform: none; }

/* Direction variants for whole blocks. */
.js .reveal--left  { transform: translateX(-18px); }
.js .reveal--right { transform: translateX(18px); }
.js .reveal--scale { transform: scale(.97); }
.js .reveal--left.is-in, .js .reveal--right.is-in, .js .reveal--scale.is-in { transform: none; }

/* ---- 16d. Objects that respond -----------------------------------------
   Cards, figures and rows lift slightly toward the pointer and warm their
   border. Small numbers on purpose: 2px and a border is enough to say "this
   is an object", and more turns a page of cards into a trampoline.
   ------------------------------------------------------------------------ */
.fig, .stat, .plan, .quote, .pilot, .rep {
  transition: transform var(--t-slow) var(--ease-out),
              border-color var(--t) var(--ease),
              box-shadow var(--t-slow) var(--ease);
}
.fig:hover, .plan:hover, .quote:hover {
  transform: translateY(-3px);
  border-color: var(--accent-line);
  box-shadow: var(--shadow);
}

/* A rule row warms its left edge rather than moving, because these sit in
   long lists where lifting each one is noise. */
.rules > li, .rules > div { position: relative; transition: color var(--t) var(--ease); }
.rules > li::after, .rules > div::after {
  content: ""; position: absolute; left: 0; top: -1px; bottom: -1px;
  width: 2px;
  background: var(--accent);
  transform: scaleY(0); transform-origin: 50% 0;
  transition: transform var(--t-slow) var(--ease-out);
}
.rules > li:hover::after, .rules > div:hover::after { transform: scaleY(1); }
.rules > li:hover b, .rules > div:hover dt { color: var(--accent); }
.rules__n, .rules__mark { transition: color var(--t) var(--ease), transform var(--t-slow) var(--ease-out); }
.rules > li:hover .rules__n { transform: translateY(-2px); color: var(--accent); }
.rules > li:hover .rules__mark { transform: scale(1.12); }

/* ---- 16e. The eyebrow rule draws itself -------------------------------- */
.eyebrow::before { transform-origin: 0 50%; transition: transform 620ms var(--ease-out) 120ms; }
.js .reveal .eyebrow::before, .js .reveal.eyebrow::before { transform: scaleX(0); }
.js .reveal.is-in .eyebrow::before, .js .reveal.is-in.eyebrow::before { transform: scaleX(1); }

/* ---- 16f. Navigation ---------------------------------------------------- */
.nav__link { position: relative; }
@media (min-width: 960px) {
  .nav__link::after {
    content: ""; position: absolute; left: 12px; right: 12px; bottom: 10px;
    height: 1.5px; border-radius: 2px;
    background: var(--brand);
    transform: scaleX(0); transform-origin: 0 50%;
    transition: transform var(--t-slow) var(--ease-out);
  }
  .nav__link:hover::after, .nav__link[aria-current="page"]::after { transform: scaleX(1); }
}

/* Reading progress, on the header's own hairline. It is a real measure of
   where the visitor is, so it earns its pixel. --p is set by site.js. */
.hdr__prog {
  position: absolute; left: 0; right: 0; bottom: -1px; height: 2px;
  transform: scaleX(var(--p, 0)); transform-origin: 0 50%;
  background: linear-gradient(90deg, var(--brand), var(--ec));
  opacity: 0; pointer-events: none;
  transition: opacity var(--t) var(--ease);
}
.hdr.is-stuck .hdr__prog { opacity: 1; }

/* ---- 16g. Figures that count ------------------------------------------
   Tabular numerals so a tweening figure does not shuffle its own width, and
   a one-off flash when a value changes, so a recalculation is felt rather
   than merely noticed.
   ------------------------------------------------------------------------ */
.count, .calc__res-v, .closes__v { font-variant-numeric: tabular-nums; }
.is-bumped { animation: bump 460ms var(--ease-out); }
@keyframes bump {
  0%   { transform: none; }
  28%  { transform: translateY(-3px) scale(1.035); color: var(--accent); }
  100% { transform: none; }
}

/* ---- 16h. The ticker ----------------------------------------------------
   One strip of the things that actually sit in a neglected list. The content
   is duplicated in the markup and the track translates exactly -50%, so the
   loop is seamless with no JavaScript. The second copy carries aria-hidden,
   or a screen reader reads the list twice.
   ------------------------------------------------------------------------ */
.ticker {
  position: relative;
  padding-block: 14px;
  border-block: 1px solid var(--border);
  overflow: hidden;
  -webkit-mask: linear-gradient(90deg, transparent, #000 9%, #000 91%, transparent);
  mask: linear-gradient(90deg, transparent, #000 9%, #000 91%, transparent);
}
.ticker__track {
  display: flex; width: max-content;
  animation: ticker 42s linear infinite;
  will-change: transform;
}
.ticker:hover .ticker__track { animation-play-state: paused; }
.ticker__set { display: flex; flex: 0 0 auto; }
.ticker__i {
  display: inline-flex; align-items: center; gap: 10px;
  padding-inline: 22px;
  font-size: 14.5px; letter-spacing: -.008em;
  color: var(--ink-low); white-space: nowrap;
}
.ticker__i::before {
  content: ""; width: 5px; height: 5px; flex: 0 0 auto;
  border-radius: 50%; background: var(--ec); opacity: .8;
}
@keyframes ticker { to { transform: translateX(-50%); } }

/* ---- 16i. A line of moving light on the display heading ----------------
   Applied to a single span, never a whole heading. background-clip:text has
   no fallback colour of its own, so the colour is set first and only
   overridden inside @supports. A browser without it gets plain orange text
   rather than an invisible word.
   ------------------------------------------------------------------------ */
.shine { color: var(--accent); }
@supports ((-webkit-background-clip: text) or (background-clip: text)) {
  .shine {
    background: linear-gradient(100deg,
                var(--brand) 0%, var(--ec) 28%, #FFD9A8 46%,
                var(--brand) 64%, var(--brand) 100%);
    background-size: 260% 100%;
    -webkit-background-clip: text; background-clip: text;
    -webkit-text-fill-color: transparent; color: transparent;
    animation: shine 9s var(--ease) infinite;
  }
}
@keyframes shine {
  0%, 12%   { background-position: 130% 0; }
  62%, 100% { background-position: -30% 0; }
}

/* ---- 16j. Halo, for .btn--pulse ---------------------------------------- */
@keyframes halo {
  0%   { box-shadow: 0 0 0 0 rgba(247, 149, 82, .45); }
  70%  { box-shadow: 0 0 0 14px rgba(247, 149, 82, 0); }
  100% { box-shadow: 0 0 0 0 rgba(247, 149, 82, 0); }
}

/* ---- 16k. Generated diagrams that breathe ------------------------------ */
.dg-live { animation: breathe 4.4s var(--ease) infinite; transform-origin: center; }
.dg-live:nth-of-type(2) { animation-delay: .5s; }
.dg-live:nth-of-type(3) { animation-delay: 1s; }
.dg-live:nth-of-type(4) { animation-delay: 1.5s; }
@keyframes breathe {
  0%, 100% { opacity: .35; }
  50%      { opacity: 1; }
}

/* ---- 16l. Where stopping needs an explicit end state -------------------
   Section 15 collapses every animation to .001ms. For a looping animation
   that is the right answer: it lands on its final frame and stays there. For
   these the final frame is wrong (an invisible ring, a ticker scrolled off,
   transparent heading text), so they are switched off rather than
   fast-forwarded.
   ------------------------------------------------------------------------ */
@media (prefers-reduced-motion: reduce) {
  .aurora::before, .aurora::after { animation: none; }
  .pulse__ring { animation: none; opacity: .5; transform: scale(.62); }
  .pulse__ring:nth-child(3) { transform: scale(.82); }
  .pulse__ring:nth-child(4) { transform: scale(1); }
  .ticker__track { animation: none; }
  .dg-live { animation: none; opacity: 1; }
  .btn--pulse::after { animation: none; }
  .shine {
    animation: none;
    background: none;
    -webkit-text-fill-color: currentColor;
    color: var(--accent);
  }
  .js .reveal.is-stagger > * { opacity: 1; transform: none; }
  .eyebrow::before { transform: scaleX(1); }
}

/* ==========================================================================
   17. THE TWO-PRODUCT LAYER  (2026-09-08)

   Daedalus5 stopped being an Echo-only company. Everything in this section
   exists to carry one argument across the site: a business pays to CREATE
   demand, then loses part of it in the space between an inquiry arriving and
   a sale closing. D5 Growth works that space while the opportunity is live;
   D5 Echo goes back for what already fell out of it.

   PRODUCT COLOUR. D5 Growth is --sg sky blue. It is not a new token and it
   is not a new hue decision: --sg was D5 Signal's identifier, survived that
   product's retirement as a neutral chart accent, and is orange's exact
   complement at 179° — the far side of the 60–120° band that has clashed
   every time something was invented there. --sg-ink #1C6DA8 was re-checked
   against BOTH paper values before it was given a product to carry:
   4.99:1 on --paper and 4.61:1 on --paper-2, so it clears AA on the darker
   band as well as the lighter one. (That is the exact trap --ec-ink fell
   into on 2026-09-06.)

   Echo keeps --ec emerald. Orange stays the brand and every primary CTA, so
   neither product ever wears the colour of the button.
   ========================================================================== */

.psys--gr { --p: var(--sg); --p-tint: var(--sg-tint); --p-line: var(--sg-line); }
.sec--light .psys--gr { --p: var(--sg-ink); }

/* The plain-English category, sitting next to a product name. It is set
   against the tag it follows rather than matching it: the name is a small
   uppercase label and the category has to read as ordinary words, or it is
   just more branding. Every tag it sits in wraps, so on a phone it drops to
   its own line instead of squeezing the name. */
.tag__what {
  text-transform: none;
  letter-spacing: -.004em;
  font: var(--w-body) 13px/1.35 var(--font);
  color: var(--ink-low);
}
.psys__tag, .rel__tag, .eng__tag { flex-wrap: wrap; }

/* Drawer only. Five desktop nav items with subtitles do not fit 1200px. */
.nav__what { display: none; }
@media (max-width: 959px) {
  .nav__link { flex-wrap: wrap; align-items: baseline; row-gap: 2px; }
  .nav__what {
    display: block; flex: 1 0 100%;
    font: var(--w-body) 13px/1.3 var(--font);
    letter-spacing: normal;
    color: var(--ink-low);
  }
}

.foot__what {
  margin: -8px 0 14px;
  font: var(--w-body) 12.5px/1.4 var(--font);
  letter-spacing: normal;
  color: var(--ink-low);
}

/* A product word inside running copy, tinted to its own identity. Used
   sparingly — twice in a section at most, or the page turns into a legend. */
.is-gr { color: var(--sg); font-weight: var(--w-strong); }
.is-ec { color: var(--ec); font-weight: var(--w-strong); }
.sec--light .is-gr { color: var(--sg-ink); }
.sec--light .is-ec { color: var(--ec-ink); }

/* ---- 17a. The three stages of demand -----------------------------------
   Created → worked → recovered. The strip that makes two products read as
   one company: each stage names which part of the business it describes,
   and the last two are the ones D5 sells into.
   ------------------------------------------------------------------------ */
.stages { display: grid; gap: 0; border-top: 1px solid var(--border); counter-reset: stage; }
@media (min-width: 860px) {
  .stages { grid-template-columns: repeat(3, minmax(0, 1fr)); border-top: 0; gap: 1px; background: var(--border); }
  .stages > li { background: var(--bg); }
}
.stages > li {
  position: relative;
  padding: clamp(24px, 2.6vw, 32px) 0;
  border-bottom: 1px solid var(--border);
}
@media (min-width: 860px) {
  .stages > li { padding: clamp(26px, 2.8vw, 34px) clamp(20px, 2.2vw, 28px); border-bottom: 0; }
  .stages > li:first-child { padding-left: 0; }
  .stages > li:last-child { padding-right: 0; }
}
.stages__k {
  display: block;
  font: var(--w-strong) 11.5px/1.2 var(--font);
  text-transform: uppercase; letter-spacing: .14em;
  color: var(--ink-low);
}
.stages__h {
  display: block; margin-top: 12px;
  font: var(--w-head) clamp(19px, .8vw + 15px, 22px)/1.2 var(--font);
  letter-spacing: -.022em; color: var(--ink);
}
.stages p { margin: 10px 0 0; font-size: 15px; line-height: 1.55; color: var(--ink-mid); }
/* Who owns the stage. A stage D5 does not sell into says so plainly rather
   than being quietly left blank. */
.stages__who {
  display: inline-flex; align-items: center; gap: 7px;
  margin-top: 16px; padding: 5px 11px 5px 9px;
  border: 1px solid var(--border-strong); border-radius: 999px;
  font: var(--w-strong) 12px/1.2 var(--font); letter-spacing: -.004em;
  color: var(--ink-low);
}
.stages__who::before { content: ""; width: 7px; height: 7px; border-radius: 2px; background: currentColor; }
.stages__who--gr { color: var(--sg); border-color: var(--sg-line); background: var(--sg-tint); }
.stages__who--ec { color: var(--ec); border-color: var(--ec-line); background: var(--ec-tint); }
.sec--light .stages__who--gr { color: var(--sg-ink); }
.sec--light .stages__who--ec { color: var(--ec-ink); }

/* ---- 17b. The revenue journey, and where it leaks ----------------------
   The signature diagram of the site, and deliberately NOT an SVG. An SVG
   with eight stages and eight loss labels is unreadable at 360px — the text
   scales down with the viewBox — so this is markup that reflows instead.

   Two columns: what is supposed to happen, and what actually happens to some
   of it. The losses are the whole point, so they get the ember token and
   their own column heading rather than being footnotes on the stages.
   ------------------------------------------------------------------------ */
.jrn { display: grid; gap: 0; margin: 0; }
.jrn__head { display: none; }
@media (min-width: 820px) {
  .jrn__head {
    display: grid;
    grid-template-columns: 34px minmax(0, 1fr) minmax(0, .92fr);
    gap: 0 clamp(18px, 2vw, 30px);
    padding-bottom: 12px;
  }
  .jrn__head span {
    grid-column: 2;
    font: var(--w-strong) 11.5px/1.2 var(--font);
    text-transform: uppercase; letter-spacing: .13em; color: var(--ink-low);
  }
  .jrn__head span + span { grid-column: 3; }
}

.jrn__s {
  position: relative;
  display: grid;
  grid-template-columns: 34px minmax(0, 1fr);
  gap: 4px clamp(14px, 1.6vw, 18px);
  padding: clamp(16px, 1.8vw, 20px) 0;
  border-top: 1px solid var(--border);
}
@media (min-width: 820px) {
  .jrn__s {
    grid-template-columns: 34px minmax(0, 1fr) minmax(0, .92fr);
    gap: 4px clamp(18px, 2vw, 30px);
    align-items: start;
  }
}
.jrn__s:last-child { border-bottom: 1px solid var(--border); }

/* The rail. A node per stage, joined by a line drawn from the node itself so
   it cannot drift out of alignment with the row padding. */
.jrn__n {
  position: relative; z-index: 1;
  grid-row: 1 / span 3;
  display: flex; align-items: center; justify-content: center;
  width: 26px; height: 26px; margin-top: 1px;
  border: 1px solid var(--border-strong); border-radius: 50%;
  background: var(--bg);
  font: var(--w-strong) 11.5px/1 var(--font);
  font-variant-numeric: tabular-nums;
  color: var(--ink-low);
  transition: color var(--t) var(--ease), border-color var(--t) var(--ease),
              background-color var(--t) var(--ease);
}
.jrn__n::after {
  content: ""; position: absolute; top: 26px; left: 50%; z-index: -1;
  width: 1px; height: calc(100% + clamp(32px, 3.6vw, 40px));
  background: var(--border-strong);
  transform: translateX(-50%);
}
.jrn__s:last-child .jrn__n::after { content: none; }
.jrn__s:hover .jrn__n { color: var(--sg); border-color: var(--sg-line); background: var(--sg-tint); }
.sec--light .jrn__s:hover .jrn__n { color: var(--sg-ink); }

.jrn__t {
  grid-column: 2; margin: 0;
  font: var(--w-strong) 16.5px/1.35 var(--font);
  letter-spacing: -.016em; color: var(--ink);
}
.jrn__d { grid-column: 2; margin: 5px 0 0; font-size: 14.5px; line-height: 1.55; color: var(--ink-mid); max-width: 40em; }

/* What leaves at this stage. Its own column on a wide screen, an indented
   block under the stage on a phone. */
.jrn__leak {
  grid-column: 2; margin: 12px 0 0;
  padding: 11px 14px;
  border: 1px solid var(--ember-line);
  border-left-width: 2px;
  border-radius: var(--r-sm);
  background: var(--ember-tint);
  font-size: 14.5px; line-height: 1.5; color: var(--ink-mid);
}
@media (min-width: 820px) {
  .jrn__leak { grid-column: 3; grid-row: 1 / span 3; margin: 0; }
}
.jrn__leak b { display: block; margin-bottom: 3px; color: var(--ember); font-weight: var(--w-strong); letter-spacing: -.01em; }
.sec--light .jrn__leak b { color: var(--ember-ink); }
/* The last stage is not a loss — a repeat customer is the outcome — so its
   row carries the Echo note instead of an ember one. */
.jrn__leak--ec { border-color: var(--ec-line); background: var(--ec-tint); }
.jrn__leak--ec b { color: var(--ec); }
.sec--light .jrn__leak--ec b { color: var(--ec-ink); }

/* Where the right-hand column goes. This is the sentence that turns two
   products into one company, so it is a statement, not a caption. */
.jrn__sink {
  display: grid; gap: 14px; align-items: center;
  margin-top: clamp(22px, 2.6vw, 30px);
  padding: clamp(20px, 2.2vw, 26px);
  border: 1px solid var(--border-strong);
  border-radius: var(--r);
  background: linear-gradient(180deg, var(--ec-tint), transparent 70%), var(--surface);
  box-shadow: var(--sheen);
}
@media (min-width: 760px) { .jrn__sink { grid-template-columns: minmax(0, 1fr) auto; gap: 24px; } }
.jrn__sink p { margin: 0; font-size: clamp(16px, .5vw + 14px, 18px); line-height: 1.5; letter-spacing: -.012em; color: var(--ink); }
.jrn__sink p b { color: var(--ec); font-weight: var(--w-strong); }
.sec--light .jrn__sink p b { color: var(--ec-ink); }
/* Not inside a .cta-row, so it does not inherit the 44px target rule
   that lives there. It is still the only action in the block. */
.jrn__sink .tlink { margin: 0; min-height: 44px; }

/* ---- 17c. Two problems, introduced before two products -----------------
   The visitor meets the problem, then the product that exists for it. Each
   card wears its product's colour so the association is made before the
   product section arrives.
   ------------------------------------------------------------------------ */
.probs { display: grid; gap: 16px; }
@media (min-width: 880px) { .probs { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: clamp(18px, 2vw, 26px); } }
.probs > li {
  position: relative; display: flex; flex-direction: column;
  padding: clamp(24px, 2.6vw, 34px);
  border: 1px solid var(--border);
  border-top: 2px solid var(--p, var(--border-strong));
  border-radius: var(--r);
  background: linear-gradient(180deg, var(--p-tint, transparent), transparent 62%), var(--surface);
  box-shadow: var(--sheen);
  transition: border-color var(--t) var(--ease), transform var(--t) var(--ease);
}
.probs > li:hover { transform: translateY(-2px); }
.probs--gr > li, li.probs__gr { --p: var(--sg); --p-tint: var(--sg-tint); }
li.probs__ec { --p: var(--ec); --p-tint: var(--ec-tint); }
.sec--light li.probs__gr { --p: var(--sg-ink); }
.sec--light li.probs__ec { --p: var(--ec-ink); }
.probs__k {
  font: var(--w-strong) 11.5px/1.2 var(--font);
  text-transform: uppercase; letter-spacing: .14em; color: var(--ink-low);
}
.probs__q {
  margin: 14px 0 0;
  font: var(--w-head) clamp(20px, 1vw + 16px, 25px)/1.22 var(--font);
  letter-spacing: -.026em; color: var(--ink);
}
.probs > li p { margin: 14px 0 0; font-size: 15.5px; line-height: 1.6; color: var(--ink-mid); }
.probs__ans {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 9px;
  margin-top: auto; padding-top: clamp(20px, 2.2vw, 26px);
  font: var(--w-strong) 14.5px/1.4 var(--font); letter-spacing: -.01em;
  color: var(--p);
}
.probs__ans::before {
  content: ""; flex: 0 0 auto; align-self: center;
  width: 9px; height: 9px; border-radius: 2px; background: currentColor;
}
.probs__ans b { flex: 0 0 auto; white-space: nowrap; font-weight: var(--w-strong); }
.probs__ans span { flex: 1 1 auto; color: var(--ink-low); font-weight: var(--w-body); }

/* ---- 17d. The hybrid ladder — system repetition, human judgment --------
   Alternating rows down one rail. A filled marker is the system; an outlined
   one is a person. That is the whole legend, and it is stated in markup as
   text as well, because a shape difference is not information on its own.
   ------------------------------------------------------------------------ */
.hand { display: grid; gap: 0; margin: 0; }
.hand > li {
  position: relative;
  display: grid;
  grid-template-columns: auto minmax(0, 1fr);
  gap: 3px clamp(14px, 1.6vw, 18px);
  padding: clamp(15px, 1.7vw, 19px) 0;
  border-top: 1px solid var(--border);
}
.hand > li:last-child { border-bottom: 1px solid var(--border); }
.hand__who {
  position: relative; z-index: 1;
  grid-row: 1 / span 2;
  display: inline-flex; align-items: center; gap: 7px;
  align-self: start; margin-top: 2px;
  min-width: 88px;
  padding: 5px 10px;
  border: 1px solid var(--border-strong); border-radius: 999px;
  background: var(--bg);
  font: var(--w-strong) 11px/1.2 var(--font);
  text-transform: uppercase; letter-spacing: .1em;
  color: var(--ink-low);
}
.hand__who::before {
  content: ""; flex: 0 0 auto; width: 8px; height: 8px; border-radius: 50%;
  border: 1.5px solid currentColor;
}
/* The system rows carry Growth's colour and a solid marker; the human rows
   stay neutral with a hollow one. */
.hand__who--sys { color: var(--sg); border-color: var(--sg-line); background: var(--sg-tint); }
.hand__who--sys::before { background: currentColor; }
.sec--light .hand__who--sys { color: var(--sg-ink); }
.hand__who--you { color: var(--ink); border-color: var(--border-strong); }
.hand b { grid-column: 2; font: var(--w-strong) 16px/1.4 var(--font); letter-spacing: -.014em; color: var(--ink); }
.hand p { grid-column: 2; margin: 4px 0 0; font-size: 14.5px; line-height: 1.55; color: var(--ink-mid); max-width: 46em; }

/* ---- 17e. The product relationship -------------------------------------
   Two columns, then the line that lands the point. The landing line is a
   full-width row rather than a caption because it is the argument, and the
   columns are only its evidence.
   ------------------------------------------------------------------------ */
.rel { display: grid; gap: 16px; }
@media (min-width: 880px) { .rel { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: clamp(18px, 2vw, 24px); } }
.rel__col {
  display: flex; flex-direction: column;
  padding: clamp(24px, 2.6vw, 32px);
  border: 1px solid var(--p-line, var(--border));
  border-radius: var(--r);
  background: linear-gradient(180deg, var(--p-tint), transparent 58%), var(--surface);
  box-shadow: var(--sheen);
}
.rel__col--gr { --p: var(--sg); --p-tint: var(--sg-tint); --p-line: var(--sg-line); }
.rel__col--ec { --p: var(--ec); --p-tint: var(--ec-tint); --p-line: var(--ec-line); }
.sec--light .rel__col--gr { --p: var(--sg-ink); }
.sec--light .rel__col--ec { --p: var(--ec-ink); }
.rel__tag {
  display: inline-flex; align-items: center; gap: 8px;
  font: var(--w-strong) 12px/1.2 var(--font);
  text-transform: uppercase; letter-spacing: .13em; color: var(--p);
}
.rel__tag::before { content: ""; width: 8px; height: 8px; border-radius: 2px; background: currentColor; }
.rel__for {
  margin: 16px 0 0;
  font: var(--w-head) clamp(19px, .8vw + 15px, 22px)/1.24 var(--font);
  letter-spacing: -.022em; color: var(--ink);
}
.rel__col > p { margin: 12px 0 0; font-size: 15.5px; line-height: 1.6; color: var(--ink-mid); }
.rel__list { display: grid; gap: 9px; margin: clamp(18px, 2vw, 22px) 0 0; padding-top: clamp(18px, 2vw, 22px); border-top: 1px solid var(--border); }
.rel__list li { position: relative; padding-left: 20px; font-size: 14.5px; line-height: 1.5; color: var(--ink-mid); }
.rel__list li::before {
  content: ""; position: absolute; left: 0; top: .5em;
  width: 9px; height: 9px; border-radius: 2px;
  border: 1.5px solid var(--p);
}
.rel__col .cta-row { margin-top: auto; padding-top: clamp(20px, 2.4vw, 26px); }

.rel__land {
  margin-top: clamp(18px, 2vw, 24px);
  padding: clamp(24px, 2.8vw, 34px);
  border: 1px solid var(--border-strong);
  border-radius: var(--r);
  background: var(--bg-alt);
}
@media (min-width: 880px) { .rel__land { grid-column: 1 / -1; margin-top: 0; } }
.rel__land p {
  margin: 0;
  font: var(--w-head) clamp(20px, 1.1vw + 15px, 27px)/1.3 var(--font);
  letter-spacing: -.026em; color: var(--ink);
  max-width: 30em;
}
.rel__land p + p {
  margin-top: 16px;
  font: var(--w-body) 15.5px/1.6 var(--font);
  letter-spacing: normal; color: var(--ink-mid); max-width: 46em;
}
.rel__land em { font-style: normal; color: var(--accent); }

/* ---- 17f. What demand already cost -------------------------------------
   The investments that produced the inquiry sitting in the inbox. A plain
   dense grid: it is a list of facts about the visitor's own P&L, and
   decorating it would weaken it.
   ------------------------------------------------------------------------ */
.spend { display: grid; gap: 0; border-top: 1px solid var(--border); }
@media (min-width: 560px) { .spend { grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: clamp(24px, 3vw, 44px); } }
@media (min-width: 940px) { .spend { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
.spend li {
  display: flex; align-items: baseline; gap: 12px;
  padding: 13px 0;
  border-bottom: 1px solid var(--border);
  font-size: 15px; line-height: 1.5; color: var(--ink-mid);
}
.spend li::before {
  content: ""; flex: 0 0 auto; width: 6px; height: 6px; border-radius: 2px;
  background: var(--accent); opacity: .55;
  transform: translateY(-2px);
}
.spend__q {
  margin: clamp(28px, 3.2vw, 40px) 0 0;
  padding: clamp(24px, 2.8vw, 34px);
  border: 1px solid var(--accent-line);
  border-radius: var(--r);
  background: linear-gradient(180deg, var(--accent-tint), transparent 64%), var(--surface);
  box-shadow: var(--sheen);
}
.spend__q dt {
  font: var(--w-strong) 11.5px/1.2 var(--font);
  text-transform: uppercase; letter-spacing: .14em; color: var(--ink-low);
}
.spend__q dd {
  margin: 12px 0 0;
  font: var(--w-head) clamp(19px, .9vw + 15px, 24px)/1.3 var(--font);
  letter-spacing: -.024em; color: var(--ink);
}
.spend__q dd + dt { margin-top: clamp(20px, 2.2vw, 26px); padding-top: clamp(18px, 2vw, 22px); border-top: 1px solid var(--border); }
.spend__q .is-ask { color: var(--accent); }

/* ---- 17g. Engagement / pricing, two products side by side --------------
   Growth publishes a setup figure and a monthly figure; Echo publishes one
   floor. Neither is a tier, and the card says the number is a starting point
   in the same breath as the number itself — a "from" that has to be hunted
   for is a price list with extra steps.
   ------------------------------------------------------------------------ */
.eng { display: grid; gap: 16px; }
@media (min-width: 900px) { .eng { grid-template-columns: repeat(2, minmax(0, 1fr)); gap: clamp(18px, 2vw, 24px); } }
.eng__card {
  display: flex; flex-direction: column;
  padding: clamp(26px, 2.8vw, 36px);
  border: 1px solid var(--p-line, var(--border));
  border-radius: var(--r-lg);
  background: linear-gradient(180deg, var(--p-tint), transparent 46%), var(--surface);
  box-shadow: var(--sheen), var(--shadow);
}
.eng__card--gr { --p: var(--sg); --p-tint: var(--sg-tint); --p-line: var(--sg-line); }
.eng__card--ec { --p: var(--ec); --p-tint: var(--ec-tint); --p-line: var(--ec-line); }
.sec--light .eng__card--gr { --p: var(--sg-ink); }
.sec--light .eng__card--ec { --p: var(--ec-ink); }
.eng__tag {
  display: inline-flex; align-items: center; gap: 8px;
  font: var(--w-strong) 12px/1.2 var(--font);
  text-transform: uppercase; letter-spacing: .13em; color: var(--p);
}
.eng__tag::before { content: ""; width: 8px; height: 8px; border-radius: 2px; background: currentColor; }
.eng__what { margin: 14px 0 0; font-size: 15.5px; line-height: 1.55; color: var(--ink-mid); }

.eng__price { margin: clamp(22px, 2.4vw, 28px) 0 0; padding-top: clamp(20px, 2.2vw, 24px); border-top: 1px solid var(--border); }
.eng__line { display: flex; flex-wrap: wrap; align-items: baseline; gap: 4px 10px; }
.eng__line + .eng__line { margin-top: 14px; }
.eng__from {
  font: var(--w-strong) 12px/1.2 var(--font);
  text-transform: uppercase; letter-spacing: .13em; color: var(--ink-low);
  flex: 1 0 100%;
}
.eng__v {
  font-size: clamp(30px, 1.8vw + 20px, 40px); line-height: 1;
  letter-spacing: -.034em; font-weight: var(--w-display);
  font-variant-numeric: tabular-nums; color: var(--ink);
}
.eng__u { font-size: 15px; color: var(--ink-low); }
.eng__plus {
  display: flex; align-items: center; gap: 10px;
  margin: 16px 0;
  font: var(--w-strong) 17px/1 var(--font);
  color: var(--ink-mid);
}
.eng__plus::after {
  content: ""; flex: 1 1 auto; height: 1px; background: var(--border);
}
.eng__note {
  margin: clamp(20px, 2.2vw, 26px) 0 0; padding-top: 16px;
  border-top: 1px solid var(--border);
  font-size: 14.5px; line-height: 1.6; color: var(--ink-mid);
}
.eng__note b { color: var(--ink); font-weight: var(--w-strong); }
.eng__card .cta-row { margin-top: auto; padding-top: clamp(22px, 2.4vw, 28px); }
.eng__card .cta-row .btn { width: 100%; }

/* ---- 17g2. What the fee includes, inside a pricing card -----------------
   The guarantee lives here, as a line item rather than a panel. It shipped
   on 2026-09-08 as a bordered, tinted block and was immediately too loud:
   risk reversal reassures, it does not sell, and it was taking more of the
   card than the price. The caveats that were in the panel with it now sit in
   one shared fine-print line under the grid — they were word-for-word
   identical in both cards, so stating them twice cost space and bought
   nothing.
   ------------------------------------------------------------------------ */
.eng__inc {
  display: grid; gap: 9px;
  margin: clamp(18px, 2vw, 22px) 0 0;
  padding-top: clamp(16px, 1.8vw, 20px);
  border-top: 1px solid var(--border);
}
.eng__inc li {
  position: relative; padding-left: 22px;
  font-size: 14px; line-height: 1.5; color: var(--ink-mid);
}
.eng__inc li::before {
  content: ""; position: absolute; left: 0; top: .42em;
  width: 10px; height: 10px; border-radius: 2px;
  border: 1.5px solid var(--accent);
  background: var(--accent-tint);
}
.eng__inc b { color: var(--ink); font-weight: var(--w-strong); }

/* The guarantee's limits. Quiet by design: it is terms, not an argument, and
   it sits below the offer it qualifies rather than inside it. */
.eng__fine {
  margin: clamp(22px, 2.4vw, 28px) 0 0;
  padding-top: clamp(16px, 1.8vw, 20px);
  border-top: 1px solid var(--border);
  font-size: 13.5px; line-height: 1.65; color: var(--ink-low);
  max-width: 78ch;
}
.eng__fine b { color: var(--ink-mid); font-weight: var(--w-strong); }
.eng__fine a { color: var(--accent); }

/* ---- 17h. Fit and misfit ------------------------------------------------
   Two lists that have to look equally serious. The one that disqualifies is
   the one that earns the other, so it is not styled as a warning.
   ------------------------------------------------------------------------ */
.fit { display: grid; gap: clamp(24px, 3vw, 40px); }
@media (min-width: 820px) { .fit { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
.fit__h {
  margin: 0 0 clamp(16px, 1.8vw, 20px); padding-bottom: 14px;
  border-bottom: 1px solid var(--border-strong);
  font: var(--w-strong) 12px/1.2 var(--font);
  text-transform: uppercase; letter-spacing: .13em; color: var(--ink-low);
}
.fit ul { display: grid; gap: 0; }
.fit li {
  position: relative; padding: 12px 0 12px 26px;
  border-bottom: 1px solid var(--border);
  font-size: 15px; line-height: 1.55; color: var(--ink-mid);
}
.fit li::before {
  content: ""; position: absolute; left: 0; top: 1.05em;
  width: 10px; height: 10px; border-radius: 2px;
  border: 1.5px solid var(--ink-low);
}
.fit__yes li::before { border-color: var(--accent); background: var(--accent-tint); }
.fit__no li::before {
  border-color: var(--ink-low);
  background: none;
}
.fit li b { color: var(--ink); font-weight: var(--w-strong); }

/* ---- 17i. Implementation timeline --------------------------------------
   Map → Build → Test → Launch → Manage, as a horizontal rail on a wide
   screen and a stack on a phone. The numbers are ordinal, not durations —
   nothing here may read as a promise about elapsed time.
   ------------------------------------------------------------------------ */
.impl { display: grid; gap: 0; counter-reset: impl; }
@media (min-width: 900px) { .impl { grid-template-columns: repeat(5, minmax(0, 1fr)); gap: 1px; background: var(--border); } }
.impl > li {
  position: relative;
  padding: clamp(20px, 2.2vw, 26px) 0;
  border-top: 1px solid var(--border);
  background: var(--bg);
}
.impl > li:last-child { border-bottom: 1px solid var(--border); }
@media (min-width: 900px) {
  .impl > li { padding: clamp(22px, 2.4vw, 28px) clamp(16px, 1.8vw, 22px); border-top: 0; border-bottom: 0; }
  .impl > li:first-child { padding-left: 0; }
  .impl > li:last-child { padding-right: 0; border-bottom: 0; }
}
.impl__n {
  display: inline-flex; align-items: center; justify-content: center;
  width: 28px; height: 28px;
  border: 1px solid var(--sg-line); border-radius: 50%;
  background: var(--sg-tint);
  font: var(--w-strong) 12px/1 var(--font); font-variant-numeric: tabular-nums;
  color: var(--sg);
}
.sec--light .impl__n { color: var(--sg-ink); }
.impl b { display: block; margin-top: 14px; font: var(--w-strong) 16.5px/1.3 var(--font); letter-spacing: -.016em; color: var(--ink); }
.impl p { margin: 8px 0 0; font-size: 14.5px; line-height: 1.55; color: var(--ink-mid); }

/* ---- 17j. Workflow inventory -------------------------------------------
   What a Growth build can be configured to handle. Presented as an inventory
   with an explicit ceiling underneath: every implementation is scoped, and a
   long list with no ceiling reads as "unlimited", which is not on offer.
   ------------------------------------------------------------------------ */
.wf { display: grid; gap: 0; border-top: 1px solid var(--border); }
@media (min-width: 620px) { .wf { grid-template-columns: repeat(2, minmax(0, 1fr)); column-gap: clamp(24px, 3vw, 44px); } }
@media (min-width: 1000px) { .wf { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
.wf li {
  padding: 14px 0;
  border-bottom: 1px solid var(--border);
}
.wf b { display: block; font: var(--w-strong) 15px/1.4 var(--font); letter-spacing: -.012em; color: var(--ink); }
.wf span { display: block; margin-top: 4px; font-size: 14px; line-height: 1.5; color: var(--ink-mid); }
.wf__ceiling {
  margin: clamp(22px, 2.4vw, 28px) 0 0;
  padding: clamp(18px, 2vw, 22px);
  border: 1px solid var(--border-strong);
  border-radius: var(--r-sm);
  background: var(--bg-alt);
  font-size: 14.5px; line-height: 1.6; color: var(--ink-mid);
}
.wf__ceiling b { display: inline; color: var(--ink); font-weight: var(--w-strong); }

/* ---- 17k. The hero return loop -----------------------------------------
   It keeps the .dg-link class so the 700ms draw-in in section 16 finds it,
   and this rule repaints it: both selectors are one class deep, so the later
   one in the file wins. It is the heaviest line in the figure on purpose —
   the whole diagram exists to show an opportunity going back INTO the
   pipeline rather than out of the business.
   ------------------------------------------------------------------------ */
.dg-loop { stroke: var(--ec); stroke-width: 2; stroke-opacity: .9; }

/* ---- 17l. The pull quote, product-tinted -------------------------------- */
.pull--gr { border-left-color: var(--sg); }
.pull--ec { border-left-color: var(--ec); }
