:root{
    --bg:#ffffff; --panel:#ffffff;
    --ink:#000000; --muted:#000000; --muted2:#000000;
    --line:rgba(0,0,0,.12); --line-strong:rgba(0,0,0,.2);
    --sage:#3c6b50; --sage-press:#2e5540;
    /* the one dark ground. Near-black on purpose: #000 stays reserved for type */
    --dark-ink:#14171a;
    /* reserved for form ghost text ONLY — every other glyph on the page is #000 */
    --ghost:#767676;
    /* full-strength pill hues, for ICONS only, never text. --ink-purple is the
       purple pill's own hue (#9A587E) darkened until it joins the band: at
       source it measures 5.16:1 on white, under the 5.35 floor the other three
       hold; #8E4F73 measures 5.97:1, between ochre and green. */
    --ink-green:#3C6B50; --ink-blue:#265E85; --ink-ochre:#7A6A2A; --ink-purple:#8E4F73;
    /* one fluid UI step: nav, pills, lede and the explore link all sit here */
    --ui:clamp(14px, 0.3vw + 11px, 16px);
    --green-bg:#ccdbc2; --green-line:rgba(60,107,80,.42); --green-ink:#000000;
    --yellow-bg:#eadc8f;--yellow-line:rgba(122,106,42,.45);--yellow-ink:#000000;
    --blue-bg:#add9f4;  --blue-line:rgba(38,94,133,.40);  --blue-ink:#000000;
    --purple-bg:#e8c7de;--purple-line:rgba(154,88,126,.38);--purple-ink:#000000;
  }
  *{box-sizing:border-box}
  html,body{margin:0;padding:0}
  body{ display:flex; flex-direction:column; min-height:100vh; background:var(--bg); color:var(--ink); font-family:'Work Sans',system-ui,sans-serif; -webkit-font-smoothing:antialiased; }
  a{color:inherit;text-decoration:none}
  button{font:inherit;background:none;border:none;cursor:pointer;color:inherit}
  /* Every "Book 15 Minute Call" is href="#book" and nothing more — no script.
     A dialog was built and cut: Calendly's widget would not initialise reliably
     inside one (stuck on its spinner, then failing to create the iframe at all),
     while the same embed in the section works. A booking button that sometimes
     opens an empty box is worse than one that always lands on a working
     scheduler. */
  @media (prefers-reduced-motion:no-preference){ html{ scroll-behavior:smooth; } }
  /* the nav is sticky, so the target has to clear it */
  #book, #how-it-works, #partnerships, #partner-form, #servicios, #contacto{ scroll-margin-top:76px; }

  @media (prefers-reduced-motion:reduce){
    *{animation-duration:.001s !important; animation-iteration-count:1 !important}
    /* the timeline arrives fully drawn and fully lit rather than not at all */
    .tl-card, .tl-node{ opacity:1 !important; transform:none !important; transition:none !important; }
    .tl-draw{ stroke-dashoffset:0 !important; }
    /* the thread arrives fully read, with no typing indicator */
    .thr.is-armed > .thr-msg{ opacity:1 !important; animation:none !important; }
    .thr-dots{ display:none !important; }
    /* the five stages arrive as five plain tiles, no tile lit */
    .stage, .stage::before, .st-bar i, .stage-name, .stage-q{ animation:none !important; }
    .stage-name, .stage-q{ opacity:1 !important; }
    .stage{ color:#000000 !important; }
    .stage::before{ background:#ffffff !important; }
    .st-bar i{ opacity:0 !important; }
    /* the stepped arc arrives drawn rather than blank */
    .steps-run{ animation:none !important; stroke-dasharray:none !important; stroke-dashoffset:0 !important; }
    /* all three stages arrive complete rather than as three empty tracks */
    .why-prog i{ animation:none !important; transform:scaleX(1) !important; opacity:1 !important; }
    /* the trust rules arrive green rather than sitting grey forever */
    .trust{ --trust-p:1 !important; }
    /* the filled button's disc stays parked at the right and the label stays put */
    .btn-label, .btn-track, .btn-circle{ transition:none !important; transform:none !important; }
  }

  /* ---------------------------------------------------------------- nav */
  .nav{ position:sticky; top:0; z-index:50; flex:none; display:flex; align-items:center; gap:40px; padding:13px clamp(20px,4vw,44px); background:#ffffff; border-bottom:1px solid var(--line); }
  .nav-mark{ display:block; height:20px; width:auto; flex:none; color:#000000; }
  .nav-links{ display:flex; align-items:center; justify-content:center; gap:30px; flex:1; }
  .nav-links > a{ font:500 var(--ui)/1 'Work Sans',sans-serif; color:var(--ink); padding:8px 0; white-space:nowrap; transition:color .18s ease; }
  .nav-links > a:hover{ color:var(--sage); }
  .nav-item{ position:relative; display:flex; }
  /* both triggers are real links now (/who-we-serve/, /what-we-do/), so the
     cursor has to say so — it read `default` from when Who We Serve was a bare
     span that only opened a panel. */
  .nav-item > .nav-trigger{ display:flex; align-items:center; gap:7px; font:500 var(--ui)/1 'Work Sans',sans-serif; color:var(--ink); padding:8px 0; cursor:pointer; transition:color .18s ease; }
  .nav-item:hover > .nav-trigger, .nav-item:focus-within > .nav-trigger{ color:var(--sage); }
  .caret{ width:5px;height:5px;border-right:1.4px solid currentColor;border-bottom:1.4px solid currentColor;transform:rotate(45deg) translateY(-1px);opacity:.7; }
  .mega{ position:absolute; top:calc(100% + 14px); left:0; display:grid; gap:2px; padding:12px; background:var(--panel); border:1px solid var(--line); border-radius:14px; max-width:calc(100vw - 24px); box-shadow:0 30px 60px -30px rgba(0,0,0,.4), 0 2px 6px -3px rgba(0,0,0,.1); opacity:0; transform:translateY(-8px); pointer-events:none; transition:opacity .3s cubic-bezier(.4,0,.2,1), transform .3s cubic-bezier(.4,0,.2,1); z-index:20; }
  /* invisible bridge over the 14px visual gap between trigger and panel —
     without it, :hover dies the instant the cursor leaves the trigger's own
     box, since nothing is painted in that gap to keep .nav-item:hover true.
     Inherits .mega's own pointer-events (none until hover/focus-within
     flips it to auto), so it's only ever interactive while the menu is
     already open. */
  .mega::before{ content:''; position:absolute; top:-14px; left:0; right:0; height:14px; }
  /* single column now — the four items are a parent, its one child, and two
     more parents at the same indent, not a grid of peers. */
  .mega--services{ grid-template-columns:clamp(220px,20vw,280px); }
  /* One group, two cards across. Business Stage was the left column until
     2026-08-31; the practice does not segment by stage any more, so the panel
     is a single group and matches .mega--services' shape — no label, no
     internal divider, items straight under the trigger. */
  .mega--serve{ grid-template-columns:clamp(440px,44vw,560px); }
  .nav-item:hover > .mega, .nav-item:focus-within > .mega{ opacity:1; transform:none; pointer-events:auto; }
  .mega a{ display:flex; flex-direction:column; gap:3px; padding:11px 14px; border-radius:8px; }
  .mega a:hover{ background:rgba(0,0,0,.04); }
  /* Group F, like everywhere else: one size, weight carries the distinction —
     500 names the destination, 400 describes it. The panel grows ~50px taller
     than it did at 13.5/12 and both panels land on the same height; measured,
     nothing clips and nothing goes offscreen. */
  .mega a b{ font:500 var(--ui)/1.2 'Work Sans',sans-serif; color:var(--ink); }
  .mega a span{ font:400 var(--ui)/1.35 'Work Sans',sans-serif; color:var(--ink); }

  /* Who We Serve — four type cards, two across. No label and no divider: with
     one group left, the trigger already names it. */
  .mega-types{ display:grid; grid-template-columns:repeat(2,1fr); column-gap:8px; row-gap:2px; }
  /* spans both columns but does not stretch across them — as a stretched grid
     item its underline ran the full panel width, well past the label. */
  .mega-types .mega-more{ grid-column:1 / -1; justify-self:start; }
  /* explore-link inside a mega column would otherwise inherit .mega a's
     column-flex tile padding — restore its own inline-flex underline shape.
     Qualified as `.mega a.mega-more` (not `.mega-more` alone): `.mega a` is
     one class + one type, and a bare single-class override loses to it. */
  .mega a.mega-more{ display:inline-flex; flex-direction:row; align-items:center; gap:8px; margin-top:6px; padding:9px 14px 0; border-radius:0; white-space:nowrap; }
  .mega a.mega-more:hover{ background:none; }

  /* What We Do — Accounting nests under Ongoing Management, and the nesting is
     real: Ongoing Management is the retainer, Accounting is what sits inside it.
     The URLs follow the same shape (/what-we-do/ongoing-management/accounting);
     the corner arrow is the connector, indent does the rest. Same row flow,
     not the tile's column flow the other three items use. Same specificity
     note as .mega-more above. */
  .mega a.mega-child{ flex-direction:row; align-items:baseline; gap:6px; padding-left:30px; }
  .mega-connector{ color:#000000; line-height:1; }
  .nav-cta{ display:flex; align-items:center; gap:12px; flex:none; }
  /* ---- the filled button: a pill with a travelling disc ----
     The label sits left with a white disc parked at the right; on hover the
     disc crosses to the left slot and the label slides right into the space it
     left. The two swap ends. Nothing about it is a new value: 999px is the pill
     radius, the disc is #ffffff (a ground) carrying a #000 glyph, and the sage
     and its press state are unchanged.

     GEOMETRY IS DERIVED, NOT TUNED. Disc 36px in a 4px inset = a 44px pill.
     padding-right is 4 + 36 + 12 = 52px, the disc's slot plus the same 12px
     that separates label from disc; padding-left is the old 22px. The label's
     hover travel is therefore exactly 52 - 22 = 30px, and at rest and on hover
     the label keeps a 22px inset and a 12px gap to the disc. Change the disc or
     an inset and all three numbers move together.

     THE DISC'S TRAVEL NEEDS NO KNOWLEDGE OF THE BUTTON'S WIDTH, and that is the
     whole trick — a width-dependent slide would need JS or a container query
     (and `container-type:inline-size` collapses a shrink-to-fit button to
     nothing). `.btn-track` is the full interior and moves -100% = -(W-8); the
     disc inside it moves +100% = +36px of its own box. The sum lands its left
     edge on 4px for every width. Percentages resolve against each element's own
     box, so neither value is a measurement.

     Transform and opacity only, per §5: the 21st.dev original animates its
     padding from ps-6 to ps-14, which is a layout property and relayouts the
     nav on every hover. */
  .btn-solid{ position:relative; display:inline-flex; align-items:center; height:44px;
              padding:0 52px 0 22px; border-radius:999px; background:var(--sage); color:#ffffff;
              font:500 var(--ui)/1 'Work Sans',sans-serif; transition:background .2s linear; }
  .btn-solid:hover{ background:var(--sage-press); }
  .btn-label{ position:relative; z-index:1; transition:transform .45s cubic-bezier(.4,0,.2,1); }
  .btn-solid:hover .btn-label{ transform:translateX(30px); }
  /* the track is the interior, and it is the half of the slide that carries the
     button's width. justify-content parks the disc at the right end. */
  .btn-track{ position:absolute; inset:4px; display:flex; align-items:center; justify-content:flex-end;
              pointer-events:none; transition:transform .45s cubic-bezier(.4,0,.2,1); }
  .btn-solid:hover .btn-track{ transform:translateX(-100%); }
  .btn-circle{ flex:none; display:flex; align-items:center; justify-content:center;
               width:36px; height:36px; border-radius:50%; background:var(--bg); color:var(--ink);
               transition:transform .45s cubic-bezier(.4,0,.2,1); }
  .btn-solid:hover .btn-circle{ transform:translateX(100%) rotate(45deg); }
  .btn-circle svg{ display:block; width:16px; height:16px; }
  .nav-toggle{ display:none; flex:none; padding:8px; }
  .nav-toggle span{ display:block; width:22px; height:2px; background:var(--ink); margin:5px 0; border-radius:2px; }
  .mobile-panel{ display:none; position:fixed; inset:0; z-index:60; background:var(--bg); padding:20px clamp(20px,6vw,44px); overflow-y:auto; }
  .mobile-panel.is-open{ display:block; }
  .mobile-panel .mobile-head{ display:flex; align-items:center; justify-content:space-between; margin-bottom:28px; }
  .mobile-panel a, .mobile-panel .mobile-group b{ display:block; font:500 calc(var(--ui) * 1.4)/1 'Work Sans',sans-serif; padding:14px 0; border-bottom:1px solid var(--line); }
  .mobile-panel .mobile-group b{ color:var(--ink); font-size:var(--ui); letter-spacing:.06em; text-transform:uppercase; border-bottom:none; padding-bottom:4px; }
  /* a nested item sits one indent in — the only device mobile has for the
     nesting the mega menu draws with a connector. Sub-GROUP labels retired
     2026-08-31 with Business Stage; only Accounting nests now. */
  .mobile-panel a.mobile-sub{ padding-left:16px; }
  .mobile-cta{ display:flex; flex-direction:column; gap:12px; margin-top:24px; }
  /* .mobile-panel a wins on specificity over .btn-solid and .caps-cta, so the
     panel's CTA had been rendering as a block of Work Sans at 1.4x --ui — a
     group-E button in group F's clothes, and now also a flex layout the disc
     needs. Restated here: the button's own box, and group E's one size. */
  .mobile-cta a{ display:flex; align-items:center; justify-content:flex-start;
                 padding:0 52px 0 22px; border-bottom:none;
                 font-family:var(--mp); font-size:.9em; }
  @media (max-width:900px){ .nav{ justify-content:space-between; } .nav-links{ display:none; } .nav-cta{ display:none; } .nav-toggle{ display:block; } }

  /* ---------------------------------------------------------------- hero */
  .hero{ position:relative; overflow:hidden; background:var(--bg); flex:1; min-height:calc(100vh - 135px); display:grid; grid-template-rows:1fr auto 1fr; }

  .hero-grid{ grid-row:2; position:relative; z-index:1; width:100%; max-width:1240px; max-height:100%; margin:0 auto; padding:0 44px; }

  /* centred stack: question card, headline, sub, then the two actions. The
     pills ring this — see the safe zone note on .hero-pills. */
  .hero-center{ position:relative; z-index:1; display:flex; flex-direction:column; align-items:center; text-align:center; gap:18px; max-width:940px; margin:0 auto; opacity:0; transform:translateY(14px); animation:fadeUp .7s cubic-bezier(.4,0,.2,1) .15s forwards; }
  @keyframes fadeUp{ to{ opacity:1; transform:none; } }
  /* max-width in ch, not px: the claim must break after "growth" at every
     width, and a pixel cap cannot promise that because the size depends on
     viewport HEIGHT too (2.3vh). Between roughly 770 and 1250 the line was
     landing just under the 940 container and collapsing to one line. 20ch is
     measured in the claim's own font, so it scales with the clamp: the string
     is 35ch, the longest half is 18ch, so the only two-line split that fits
     is the one we want, and text-wrap:balance picks it. */
  .hero-center h1{ margin:0; max-width:20ch; font:600 clamp(32px,2.3vw + 2.3vh,58px)/1.1 'Work Sans',sans-serif; letter-spacing:-.015em; color:#000000; text-wrap:balance; }
  /* second line: same size, lighter weight — one thought, two registers */
  .hero-center p{ margin:0; max-width:620px; font:400 calc(var(--ui) * 1.1)/1.6 'Work Sans',sans-serif; color:#000000; text-wrap:pretty; }
  .hero-center p strong{ font-weight:600; }
  /* phone capture and the explore link share a row, capture first */
  /* phone capture on top, the two underline links in their own row below —
     not one wrapping row of three, so the links always sit under the field
     rather than beside it at in-between widths. */
  .hero-actions{ display:flex; flex-direction:column; align-items:center; gap:18px; width:100%; margin-top:8px; }
  .hero-links{ display:flex; align-items:center; justify-content:center; gap:26px; flex-wrap:wrap; }

  /* all-caps tracked CTA treatment, borrowed for the nav button, the lead-capture
     CTA, and the explore link — kept in Work Sans rather than a new mono face */
  .caps-cta{ text-transform:uppercase; letter-spacing:.07em; font-weight:600; }

  /* width, not flex-basis: .hero-actions is a flex column now (phone field
     over the two links, not beside them), and a basis sizes the *main* axis
     — on a column that's height, which is exactly the 400px-tall box this
     used to render before the fix. */
  .lead-capture{ display:flex; align-items:center; gap:6px; width:100%; max-width:400px; padding:6px 6px 6px 22px; border-radius:999px; background:var(--panel); border:1px solid var(--line-strong); box-shadow:0 16px 34px -22px rgba(0,0,0,.35); }
  .lead-capture input{ flex:1; min-width:0; border:none; outline:none; background:none; font:400 var(--ui)/1 'Work Sans',sans-serif; color:var(--ink); padding:10px 0; }
  .lead-capture input::placeholder{ color:var(--ghost); }
  .lead-capture button{ flex:none; padding:13px 22px; border-radius:999px; background:var(--sage); color:#fff; white-space:nowrap; }
  .lead-capture button:hover{ background:var(--sage-press); }
  .explore-link{ display:inline-flex; align-items:center; gap:8px; font-size:var(--ui); color:var(--ink); padding-bottom:2px; border-bottom:1px solid rgba(0,0,0,.35); transition:color .2s linear, border-color .2s linear; }
  .explore-link:hover{ color:var(--sage); border-color:var(--sage); }
  .explore-link .arrow{ transition:transform .2s ease; }
  .explore-link:hover .arrow{ transform:translateX(3px); }

  /* Full-bleed layer behind the copy. Pills ring the centred column and stay
     out of it: the safe zone is roughly x 26-74%, y 20-84% at desktop, which is
     where the question card, headline, sub and actions live. Sharp pills sit in
     the side margins and the top/bottom bands; blurred ones sit further in,
     where they read as colour rather than text. */
  .hero-pills{ position:absolute; inset:0; z-index:0; }
  /* pill-pos: reveal (opacity/scale) via CSS keyframe + delay.
     pill: ambient drift, on a separate element — one node can't carry both
     a one-shot reveal transform and a continuous keyframe transform without
     one clobbering the other. */
  /* entrance: one-shot CSS animation. JS hands off to the transition below
     once each entrance finishes (a forwards-filled animation would otherwise
     keep overriding any inline opacity/transform the swap timer sets). */
  .pill-pos{ position:absolute; opacity:0; transform:scale(.9) translateY(10px); animation:popIn .7s cubic-bezier(.16,.9,.22,1) both; animation-delay:var(--d,0s); transition:opacity .8s cubic-bezier(.4,0,.2,1), transform .8s cubic-bezier(.4,0,.2,1); }
  @keyframes popIn{ from{ opacity:0; transform:scale(.9) translateY(10px); } to{ opacity:var(--op,1); transform:none; } }
  .pill{ display:inline-block; white-space:nowrap; border-radius:999px; font-family:'Work Sans',sans-serif; font-weight:500; }
  /* One size now — both pill shapes sit on var(--ui), the interface step.
     Depth comes from blur and opacity, not from a second size. */
  /* The blurred pills sit further in than the sharp ones by design — they are
     colour, not text. Their width is fixed but the safe zone is a percentage,
     so as the viewport narrows they walk inward and cross the copy: at ~1100
     the purple one was running through the end of the claim's second line and
     the green one sat behind the phone field. Below 1320 the .pill-side pair
     is hidden and both margins are empty, so these move out into that space. */
  /* the two sharp pills in the top band travel outward on the same schedule */
  .pill-top-l{ left:8%; }
  .pill-top-r{ right:7%; }
  .pill-blur-r{ right:10%; top:35%; }
  .pill-blur-l{ left:10%; top:62%; }
  .pill-blur-b{ right:26%; top:91%; }
  @media (max-width:1320px){
    .pill-side{ display:none; }
    .pill-top-l{ left:1%; }
    .pill-top-r{ right:1%; }
    .pill-blur-r{ right:0; }
    /* left:0 alone is not enough for this one — it is the longest string in
       either pool, so even flush to the edge it still reached the centred
       phone field. It drops instead into the empty band under the actions,
       clear of slot6 at 88%. */
    .pill-blur-l{ left:0; top:74%; }
    .pill-blur-b{ right:14%; }
  }
  .pill--a{ padding:12px 22px; font-size:var(--ui); box-shadow:0 16px 30px -22px rgba(0,0,0,.5); }
  .pill--b{ padding:9px 17px; font-size:var(--ui); box-shadow:0 12px 24px -22px rgba(0,0,0,.4); }
  /* two roles only: sharp pills you read, blurred ones that are just colour */
  .blur-4{ filter:blur(7px); }
  .blur-3{ filter:blur(4px); }
  .blur-2{ filter:blur(2px); }
  .blur-1{ filter:blur(.6px); }
  .pill--green{ background:var(--green-bg); border:1px solid var(--green-line); color:var(--green-ink); }
  .pill--yellow{ background:var(--yellow-bg); border:1px solid var(--yellow-line); color:var(--yellow-ink); }
  .pill--blue{ background:var(--blue-bg); border:1px solid var(--blue-line); color:var(--blue-ink); }
  .pill--purple{ background:var(--purple-bg); border:1px solid var(--purple-line); color:var(--purple-ink); }
  @keyframes drift1{0%,100%{transform:translate3d(0,0,0)}50%{transform:translate3d(14px,-16px,0)}}
  @keyframes drift2{0%,100%{transform:translate3d(0,0,0)}50%{transform:translate3d(-12px,14px,0)}}
  @keyframes drift3{0%,100%{transform:translate3d(0,0,0)}50%{transform:translate3d(16px,12px,0)}}
  @keyframes drift4{0%,100%{transform:translate3d(0,0,0)}50%{transform:translate3d(-14px,-12px,0)}}
  .pill--d1{ animation:drift1 28s ease-in-out infinite; }
  .pill--d2{ animation:drift2 32s ease-in-out infinite; }
  .pill--d3{ animation:drift3 30s ease-in-out infinite; }
  .pill--d4{ animation:drift4 34s ease-in-out infinite; }

  /* The one question that sits inside the safe zone, above the headline —
     roughly half way between the nav and the centre. A step above the pills but
     deliberately quieter than the headline: still white, softer shadow. */
  .hero-q{ grid-row:1; align-self:center; justify-self:center; position:relative; z-index:2; display:block; padding:15px 26px; border-radius:999px; background:var(--panel); border:1px solid var(--line); box-shadow:0 18px 38px -26px rgba(0,0,0,.35), 0 1px 3px -2px rgba(0,0,0,.08); color:#000000; white-space:nowrap; opacity:0; animation:qIn .9s cubic-bezier(.16,.9,.22,1) 1.6s both; }
  @keyframes qIn{ from{ opacity:0; transform:translateY(8px) scale(.97); } to{ opacity:1; transform:none; } }

  /* --- mobile: left content only, pills become a muted background --- */
  @media (max-width:900px){
    .hero{ display:flex; flex-direction:column; align-items:center; justify-content:center; }
    .hero-grid{ padding:40px 24px; }
    /* background texture only — nothing legible, just colour so it is not a
       blank white page */
    .hero-pills{ opacity:.22; pointer-events:none; filter:saturate(.8); }
    .hero-pills .pill{ filter:blur(7px); box-shadow:none; }
    .hero-center h1{ font-size:clamp(28px,7vw,36px); }   /* max-width stays 20ch — the container caps it below ~420px anyway */
    .hero-center p{ max-width:100%; }
    .hero-actions{ gap:16px; width:100%; }
    .hero-links{ flex-direction:column; gap:12px; }
    .lead-capture{ max-width:100%; }
    /* the capsule stops being one nowrap line here, and a wrapped descriptor
       inherits the body's left alignment — centre it explicitly */
    /* font-size lives in the page-wide mobile block at the foot of this
       stylesheet — the shared label rule below would otherwise win on source
       order and this override would silently do nothing. */
    .hero-q{ align-self:auto; justify-self:auto; white-space:normal; text-wrap:balance; text-align:center; padding:12px 20px; margin:0 auto 22px; }
  }

  /* ================= LOCKED: variant C typography =================
     M PLUS Code Latin carries the claim and every control. Optically
     corrected: its cap-height is 73% of em vs Work Sans' 66%, so all-caps
     controls step to .9em or they outweigh everything near them. */
  :root{ --mp:'M PLUS Code Latin', ui-monospace, SFMono-Regular, Menlo, monospace; }

  /* ================= A · statements =================
     The hero claim and every section head share ONE clamp and differ only by
     weight: the claim is 600, the heads are 500. Written once here rather than
     once per section — eight copies of a clamp is what DESIGN.md's own tripwire
     warns about, and it meant a new section's h2 was only correct if you
     remembered to copy the right one.

     Sections keep ONLY what is local to them: margin, colour on the two
     inverted grounds, max-width, text-wrap, and the one left-aligned head.

     Line-height is 1.1 for all of them — at this size the old 1.15/1.20/1.25
     split was three values doing one job. Tracking is -.02em; .hiw h2's
     -.015em was the only element rendering that value.

     NOT included: .grt-title. At this size in the guarantee's narrow left cell
     it broke to three lines on a hanging hyphen and became a peer of the
     section head directly above it. It keeps the old head clamp and is now the
     one member of its own step — the boxed claim. */
  .svc h2, .grt h2, .why h2, .handoff h2, .hiw h2,
  .prc h2, .faq h2, .cta h2, .mtg-copy h2,
  .quad h2, .bridge h2, .lens h2, .gets h2, .eng h2, .opt h2, .band h2,
  .plans h2, .incl h2, .cx h2, .sys h2, .callout-h, .projs h2, .dqs h2,
  .lvr h2, .ex-sec h2, .types h2, .probs h2, .roster h2, .tstm h2, .form-sec h2,
  .pnrs h2{
    font:500 clamp(32px, 2.3vw + 2.3vh, 58px)/1.1 'Work Sans',sans-serif;
    letter-spacing:-.02em; text-align:center;
  }

  /* ================= D · labels =================
     A label says what a block IS. It is never a sentence and never clicked.
     ONE rule for all six: C2's size and weight, and ALL CAPS + .06em tracking
     is the only thing that makes a label a label.

     Tracking came down from .09em/.14em as the size went up, and it more than
     pays for itself — the descriptor capsule measures 615px here against 626px
     at the old 15.32/.14em, so the label got bigger AND narrower.

     A label inside a shape (the month pills) may take this size safely, because
     the capsule separates it from whatever sits below. A bare label above a
     bare heading cannot — which is why .svc-name is the one to watch: it now
     sits 2.15px under .svc-benefit rather than 4.6px. */
  .hero-q, .trust-stat, .svc-name, .why-name, .hiw-cue, .ft-h, .prc-name,
  .quad-name, .chain-name, .stage-name, .eng-cue, .eng-name,
  .plans-table th[scope=col], .dq-name, .sig-name, .ex-name, .ex-cue,
  .ex-headcue, .lever-end, .step-name, .ex-statlabel, .ex-dh, .legal-updated,
  .mtg-copy .mtg-role, .pnr-cue{
    font:500 calc(var(--ui) * 1.1)/1.3 'Work Sans',sans-serif;
    letter-spacing:.06em; text-transform:uppercase;
  }

  /* ================= C1 · section thesis =================
     The paragraph that carries a whole section. ONE rule — it was written out
     four times (.why-lede, .grt-copy, .cta-sub, .mtg-copy p) until 2026-08-31,
     which is the duplicated-clamp tripwire in DESIGN.md §8: four copies drift.
     Members keep only what is local — margin, colour, measure, wrapping. */
  .why-lede, .grt-copy, .cta-sub, .mtg-copy p,
  .hero-center .phero-lede, .bridge-lede, .lens-lede, .eng-lede, .opt-lede, .incl-lede,
  .callout-lede, .projs-lede, .band-lede, .quad-lede, .plans-lede, .incl-list li,
  .probs-lede, .form-lede{
    font:400 calc(var(--ui) * 1.6)/1.5 'Work Sans',sans-serif;
  }

  .hero-center h1{ font-family:'Work Sans',sans-serif; letter-spacing:-.02em; }
  .btn-solid, .lead-capture button, .explore-link, .caps-cta{
    font-family:var(--mp); font-size:.9em; letter-spacing:.09em; font-weight:600;
  }
  /* Group E is now ONE size. Both of these used to opt out: .btn-solid via
     calc(var(--ui) * .9) -> 13.79px, the phone submit via a bare 11.3px. */

  /* ================= descriptor — LOCKED 2026-08-29 =================
     AA caps · pill · Work Sans. Takes group D like every other label; the only
     thing local to it is the capsule. Grid-row 1, centred in the top third,
     15px 26px padding. The capsule is load-bearing: it rhymes with the drifting
     question pills, so the descriptor reads as the answer in the same shape as
     the questions. Do not strip it. */

  /* ================= trust bar — LOCKED T4 =================
     Stacked, anchored at the fold below the hero, not under the nav. Top
     placement stacked a third centred band ahead of the claim: nav, trust,
     then the descriptor pill — two centred caps lines ~70px apart doing
     different jobs. Here it closes the fold instead. */
  /* Both hairlines belong to .trust, and both ease from --line to --sage as the
     bar rises through the viewport. --trust-p is 0..1, written by the script;
     colour-mix interpolates between two members of the closed set, so no third
     value is authored. Paint-only, like the timeline's stroke-dashoffset.
     .svc used to own the rule below this one — it was moved here so the two
     read as a pair and animate together. */
  .trust{ flex:none; display:flex; flex-direction:column; align-items:center; justify-content:center; gap:9px; padding:15px clamp(20px,4vw,44px); background:#ffffff;
          --trust-p:0;
          border-top:1px solid; border-bottom:1px solid;
          border-color:color-mix(in srgb, var(--sage) calc(var(--trust-p) * 100%), var(--line)); }
  .trust-stat{ margin:0; color:#000000; white-space:nowrap; }
  .trust-list{ margin:0; padding:0; list-style:none; display:flex; align-items:center; gap:30px; flex-wrap:wrap; justify-content:center; }
  /* Nav styling — these become links. Same for the footer identity line. */
  /* THE DOT-SEPARATED LIST, written once for its three owners: the trust bar,
     the footer identity line and the examples under each business type. It was
     two identical copies until 2026-09-01. Group F, 500 — every item is a thing,
     not a description of one. */
  .trust-list li, .ft-id li, .type-eg li{ position:relative; color:#000000; font:500 var(--ui)/1 'Work Sans',sans-serif; white-space:nowrap; }
  /* the painted dot is for lists that never wrap. A separator positioned to the
     LEFT of its item lands at the start of a wrapped line, which is why the type
     examples take the footer legal line's text middot instead. */
  .trust-list li + li::before, .ft-id li + li::before{
    content:''; position:absolute; left:-16px; top:50%; width:3px; height:3px; margin-top:-1.5px;
    border-radius:50%; background:rgba(0,0,0,.4); }

  /* ================= services =================
     Reference: Inbox/services .png — rules top and bottom, vertical rules
     between the three, icon in a perfect square.

     Numerals are gone. 01/02/03 as section markers is a machine default, and
     the icons carry the same ordering job while actually saying something.

     .svc-name is group D and the Learn more link is group E — they are no
     longer the same size, and the label is now the larger of the two. This is
     the tightest label/heading pair on the page: .svc-name sits 2.15px under
     .svc-benefit. Check it first if group D ever moves again. */
  /* The horizontal padding moved off the section and onto the two children,
     so .svc-rail can be the full width of the page. Its rules are the only
     thing on the page that runs edge to edge — the tile block inside it stays
     on the 1240 measure, which is what makes the bleed read as deliberate
     rather than as a container that forgot its max-width. */
  /* no border-top: .trust's bottom rule is the one above this section */
  .svc{ padding:clamp(72px,10vh,124px) 0; background:#ffffff; }
  .svc-head{ max-width:1240px; margin:0 auto; padding:0 clamp(20px,4vw,44px); }
  .svc--nohead{ padding-top:clamp(8px,1.4vh,16px); }
  .svc-rail{ border-top:1px solid var(--line-strong); border-bottom:1px solid var(--line-strong); padding:0 clamp(20px,4vw,44px); }
  .svc h2, .grt h2{ margin:0 auto clamp(44px,6.5vh,72px); color:#000000; text-wrap:balance; max-width:26ch; }

  /* rules top and bottom; verticals do the separating */
  /* Closed on both flanks so the three cells are whole squares. The sides are
     --line, the same weight as the dividers between them; the top and bottom
     are --line-strong and live on .svc-rail, where they can run past 1240. */
  .svc-list{ margin:0 auto; padding:0; list-style:none; display:grid; grid-template-columns:repeat(3,1fr);
             max-width:1240px; border-left:1px solid var(--line); border-right:1px solid var(--line); }
  /* subgrid so icon / label / benefit / copy / link line up across all three
     columns. Without it the third benefit wraps to two lines and drags its
     paragraph down, leaving the row tops ragged. */
  .svc-list{ grid-template-rows:auto auto auto 1fr auto; }
  .svc-item{ display:grid; grid-row:span 5; grid-template-rows:subgrid; gap:14px;
             justify-items:start; align-content:start;
             padding:clamp(30px,3vw,42px) clamp(24px,2.4vw,36px); }
  .svc-item + .svc-item{ border-left:1px solid var(--line); }

  /* the perfect square */
  .svc-icon{ display:block; margin-bottom:6px; }
  .svc-icon svg, .grt-icon svg, .why-icon svg, .type-icon svg, .err-icon svg,
  .tstm-icon svg{ width:46px; height:46px; display:block; }   /* h2 cap height is ~23px; this clears it */

  .svc-name{ color:#000000; }
  .svc-benefit, .grt-title, .ex-price, .quad-claim, .get-name, .eng-price,
  .legal h2, .type-name, .roster-eg li, .mtg-copy .mtg-name,
  .hero-center .phero-price, .proj-name, .dq-q, .sig-price,
  .ex-title, .ex-stat,
  .lever-name, .pp-price, .pnr-name{ margin:0; color:#000000; font:600 clamp(19px,.7vw + .9vh,25px)/1.25 'Work Sans',sans-serif; letter-spacing:-.012em; text-wrap:balance; }
  .svc-desc, .why-desc, .why-qs, .quad-copy, .bridge-copy, .stage-q,
  .get-copy, .eng-copy, .band-copy, .callout-copy, .incl-note, .cx-note, .sys-note, .opt-note,
  .proj-copy, .dq-copy, .lever-copy, .ex-focus, .ex-copy, .lvr-note, .pp-what,
  .step-copy, .proj-price, .legal-copy, .legal-list li, .type-copy, .probs-close,
  .tstm-quote, .cform-note, .pnr-copy{ margin:0; color:#000000; font:400 calc(var(--ui) * 1.1)/1.6 'Work Sans',sans-serif; text-wrap:pretty; }
  .svc-item .explore-link{ align-self:end; padding-top:14px; }

  /* Icon colour is the whole device — no filled square. The three glyphs are
     happy faces, each a step happier than the last; the order is the point,
     so do not reshuffle them. Full-strength versions of the pill border hues. */
  .svc-item:nth-child(1) .svc-icon{ color:var(--ink-green); }
  .svc-item:nth-child(2) .svc-icon{ color:var(--ink-blue); }
  .svc-item:nth-child(3) .svc-icon{ color:var(--ink-ochre); }


  /* ================= guarantee =================
     Reference: Inbox/guarantee.png — one outlined box, no fill, split by a
     single vertical hairline. Same cell language as the services row: the
     outer edge is --line-strong (the section rule weight), the internal
     divider is --line (the between-columns weight), radius 0.

     The promise sits left and its terms sit right, so the box is read in the
     order it is argued: what we call it, then what it actually costs us. No
     new type roles — the claim borrows .svc-benefit, the terms borrow
     .svc-desc, the icon borrows the 46px services square. */
  /* No section rule of its own: the services block's bottom rule already runs
     the full width of the page a hundred pixels up, and a second full-width
     line under it was two rules doing one job. */
  /* No padding-top: with no rule between them, .svc's padding-bottom is
     already the whole gap. Keeping both stacked them into 180px against the
     91px that separates the trust bar from the services heading. */
  /* Full-bleed like .svc and .why: the section carries no horizontal padding,
     .grt-head and .grt-rail pay it, and the rail's two rules run edge to edge
     while the box stays on the 1240 measure. */
  .grt{ padding:0 0 clamp(72px,10vh,124px); background:#ffffff; }
  /* padding-top:0 assumes the section above pays the gap in WHITE. An inverted
     block does not: .hiw's bottom padding is dark pixels inside its own ground,
     so /how-it-works had the guarantee h2 sitting 0px off the dark edge against
     100px everywhere else. Same clamp, not a new number. */
  /* ANY section after the dark block pays its own top padding, not just the
     guarantee. .hiw's bottom padding is dark pixels inside its own ground, so a
     white section that follows with padding-top:0 sits flush against the dark
     edge — which is what "Work directly with Joaquin" did until 2026-09-02.
     Written against the sibling rather than a class so the next section moved
     under .hiw inherits it instead of re-discovering it. */
  .hiw + section{ padding-top:clamp(72px,10vh,124px); }

  /* ---- ONE PADDING PER GAP, enforced where a section pays its own top ----
     Most sections pay their bottom padding only, so a white pair is one 90px
     gap. Four sections carry a top padding as well, because on the page they
     were built for they follow a bar or an inverted block. Placed after another
     white section they double it: /who-we-are ran 180px twice, and the business
     type pages ran 135px under the hero. These are the adjacencies that exist —
     add to them, never widen a section's own padding to compensate. */
  .mtg + .svc, .grt + .svc,
  .svc + .callout, .mtg + .callout,
  .phero + .band, .opt + .band, .mtg + .band, .callout + .band{ padding-top:0; }
  .grt-head{ max-width:1240px; margin:0 auto; padding:0 clamp(20px,4vw,44px); }
  .grt-rail{ border-top:1px solid var(--line-strong); border-bottom:1px solid var(--line-strong); padding:0 clamp(20px,4vw,44px); }

  /* 1fr 2fr, not 1fr 1fr: the divider lands on the services grid's first
     vertical rule, so the claim occupies one square and the terms occupy two.
     The horizontals live on the rail; the box closes its own flanks with
     --line, the same as the tile blocks. */
  .grt-box{ max-width:1240px; margin:0 auto; display:grid; grid-template-columns:1fr 2fr;
            border-left:1px solid var(--line); border-right:1px solid var(--line); }
  .grt-claim, .grt-terms{ padding:clamp(30px,3vw,42px) clamp(24px,2.4vw,36px); }
  /* Icon above the claim, not above the terms. It used to sit on the right,
     which pushed the terms down and left the left cell half empty; moving it
     over evens the two cells and takes the wasted space out of the box. Still
     vertically centred, so the pair reads as one block against six lines. */
  .grt-claim{ display:flex; flex-direction:column; align-items:flex-start; justify-content:center; gap:20px; }
  .grt-terms{ display:grid; align-content:center; border-left:1px solid var(--line); }
  .grt-icon{ display:block; margin-bottom:6px; color:var(--ink-purple); }

  /* Both halves step up one rung. No new numbers: the claim takes the section
     head's clamp in Work Sans, the terms take the benefit head's clamp at 400.
     The claim keeps text-wrap:balance on purpose — greedy wrapping fills line
     one with "Our 90-Day Value" and orphans "Guarantee"; balance minimises the
     longest line and breaks it after "Our 90-Day", which is the reading. */
  /* The boxed claim — the one member of its own step. It keeps the clamp the
     section heads used before they moved up to the hero's, because at the head
     size it broke to three lines in this cell and outranked the h2 above it. */
  .grt-title, .ex-price{ font-size:clamp(26px,1.5vw + 1.1vh,38px); line-height:1.15; }
  /* The terms run the full two squares, so the size has to set the measure:
     at var(--ui) the line hit ~100ch and at the benefit clamp ~79ch.
     .grt-copy is C1 and ONLY C1. It used to sit in the C2 rule for its margin
     and colour and then override the size — two groups claiming one element,
     which broke the moment the override was folded into the shared C1 rule.
     Local props only here; the size lives in the C1 rule and nowhere else. */
  .grt-copy{ margin:0; color:#000000; text-wrap:pretty; }
  /* home states the guarantee in one paragraph; the newer pages split it in
     two, which had them running together on one leading. */
  .grt-copy + .grt-copy{ margin-top:.8em; }

  /* ================= who we serve =================
     Centred head, centred thesis, then a three-tile rail on the services
     device, then the disqualifier and the CTA. The two-column version and its
     single boxed list retired 2026-08-31 — the three stages of the buyer are
     the content now, and a stage is a tile, not a bullet.

     The tiles carry only two things forward from .svc: the D label and the C2
     copy. Everything else here is local — the progression rail is what makes
     three tiles read as one sequence rather than three options.

     No padding-top: .grt's padding-bottom is already the whole gap. */
  .why{ padding:0 0 clamp(72px,10vh,124px); background:#ffffff; }

  /* Same full-bleed device as .svc: the section carries no horizontal padding,
     so .why-rail's rules run edge to edge while .why-list stays on the 1240
     measure. Head and foot pay the padding themselves. */
  .why-head{ max-width:1240px; margin:0 auto clamp(44px,6.5vh,72px); padding:0 clamp(20px,4vw,44px); text-align:center; }
  /* local margin only — the clamp is group A's, shared */
  .why h2{ margin:0 auto clamp(18px,2.4vh,28px); color:#000000;
           text-wrap:balance; max-width:26ch; }
  /* C1, centred under the head. 54ch sets two lines at 1440; balance keeps
     them even. The three sage .q underlines retired with the two-column
     layout — the animated rail is the section's sage now. */
  .why-lede{ margin:0 auto; color:#000000; text-wrap:balance; max-width:54ch; }
  /* The ask and the read-on sit as one row, ask first. Both are group E, so
     centring the pair and letting the row's align-items do the vertical work is
     the whole rule — no per-element margin. */
  .why-cta{ display:flex; flex-wrap:wrap; align-items:baseline; justify-content:center;
            gap:clamp(16px,1.6vw,26px); margin-top:1.35em; }

  .why-rail{ border-top:1px solid var(--line-strong); border-bottom:1px solid var(--line-strong); padding:0 clamp(20px,4vw,44px); }
  .why-list{ margin:0 auto; padding:0; list-style:none; display:grid; grid-template-columns:repeat(3,1fr);
             max-width:1240px; border-left:1px solid var(--line); border-right:1px solid var(--line); }
  /* subgrid so icon / label / rail / copy / questions line up across all three
     tiles — without it a two-line label drags one column's rail off the row the
     other two share, and the progression stops reading as one line. */
  .why-list{ grid-template-rows:auto auto auto auto auto; }
  .why-item{ display:grid; grid-row:span 5; grid-template-rows:subgrid; gap:14px;
             justify-items:start; align-content:start;
             padding:clamp(30px,3vw,42px) clamp(24px,2.4vw,36px); }
  .why-item + .why-item{ border-left:1px solid var(--line); }

  .why-icon{ display:block; margin-bottom:6px; }
  .why-name{ color:#000000; }
  /* Icon ink runs green -> blue -> ochre in the same order as the services
     rail. Here the order is the progression the rails animate, so it is
     content: do not reshuffle. */
  .why-item:nth-child(1) .why-icon{ color:var(--ink-green); }
  .why-item:nth-child(2) .why-icon{ color:var(--ink-blue); }
  .why-item:nth-child(3) .why-icon{ color:var(--ink-ochre); }

  /* ---- the progression rail ----
     One 2px track per tile, at --line like every other edge in the box, with a
     sage bar that scales out of its left edge. Transform and opacity only —
     the width never changes, so this stays inside the motion rule.
     2px sage is the thickness the retired .q underline used.

     Cycle is 10.5s, one third per tile. A tile fills over 2.73s, holds, then
     fades back to the track as the next one starts — the handoff overlaps by
     design, so the eye is never looking at three dead rails. */
  .why-prog{ display:block; width:100%; height:2px; background:var(--line); position:relative; overflow:hidden; }
  .why-prog i{ position:absolute; inset:0; background:var(--sage);
               transform:scaleX(0); transform-origin:left center;
               animation:why-prog 10.5s linear infinite both; }
  .why-item:nth-child(2) .why-prog i{ animation-delay:3.5s; }
  .why-item:nth-child(3) .why-prog i{ animation-delay:7s; }
  @keyframes why-prog{
    0%    { transform:scaleX(0); opacity:1; }
    26%   { transform:scaleX(1); opacity:1; }
    31%   { transform:scaleX(1); opacity:1; }
    33.2% { transform:scaleX(1); opacity:0; }
    33.3% { transform:scaleX(0); opacity:0; }
    100%  { transform:scaleX(0); opacity:0; }
  }

  .why-desc{ margin:0; }
  /* C2 as bullets. The disc is the marker the rest of the page does not use,
     and it is what separates a question from the statement above it. */
  .why-qs{ margin:0; padding:0 0 0 1.15em; list-style:disc; display:grid; gap:7px; }
  .why-qs li{ color:#000000; }


  /* ================= /what-we-do =================
     Layout only. Every type role here is a GROUP taken by widening an existing
     selector — A for the heads, B for the card claim, C1 for the theses, C2 for
     the body, D for the labels, E for the links. No size is written twice.

     The page reuses .hero-center for its hero, so the fade-up entrance and the
     h1's clamp come for free and cannot drift from the home page's. */
  /* ---- paper: the drafting grid, page heroes only ----
     Drawn in the HAIRLINE family — black at alpha, no colour enters the set —
     and both alphas sit at roughly HALF --line (.12), so a structural hairline
     always outranks the texture by a clear margin. Set 2026-09-01 to the level
     the bottom of the fade was already reading at. 20px cell, heavy line every 4th, the source's own
     3:12 weight ratio. A texture on the white ground, NOT a fourth ground:
     --bg is untouched and .phero still paints #ffffff underneath.

     THE CLEARING IS A BACKGROUND LAYER, NOT AN OVERLAY. A white radial sits on
     top of the grid inside the same pseudo-element, so the copy's clearing is
     white painted over white — it cannot show an edge. An earlier pass put it
     on .hero-center as a backdrop-filter overlay and the blur's own bounds read
     as a visible oval smudge behind the text.

     Masked open at the top so it arrives under the nav rather than butting into
     it, and closed well before the section ends so it never meets the next
     block's rule. Home's .hero is deliberately excluded. */
  .phero{ position:relative; isolation:isolate; }
  .phero::before{
    content:''; position:absolute; inset:0; z-index:-1; pointer-events:none;
    --cell:20px; --block:80px; --clear:54% 50%;
    --fine:rgba(0,0,0,.035); --heavy:rgba(0,0,0,.055);
    background-image:
      radial-gradient(ellipse var(--clear) at 50% 46%,
        #ffffff 0, #ffffff 26%, rgba(255,255,255,0) 74%),
      repeating-linear-gradient(to right,
        transparent 0, var(--heavy) .57px, var(--heavy) 3.97px, transparent 4.54px, transparent var(--block)),
      repeating-linear-gradient(to bottom,
        transparent 0, var(--heavy) .57px, var(--heavy) 3.97px, transparent 4.54px, transparent var(--block)),
      repeating-linear-gradient(to right,
        transparent 0, var(--fine) .28px, var(--fine) 1.14px, transparent 1.42px, transparent var(--cell)),
      repeating-linear-gradient(to bottom,
        transparent 0, var(--fine) .28px, var(--fine) 1.14px, transparent 1.42px, transparent var(--cell));
    background-position: 0 0, -2.27px 0, 0 -2.27px, -.71px 0, 0 -.71px;
    -webkit-mask-image:linear-gradient(to bottom, transparent 0, #000 16%, #000 50%, transparent 90%);
            mask-image:linear-gradient(to bottom, transparent 0, #000 16%, #000 50%, transparent 90%);
  }

  .phero{ padding:clamp(56px,9vh,104px) clamp(20px,4vw,44px) clamp(64px,9vh,110px); background:#ffffff; }
  .phero-lede{ margin:0; max-width:52ch; color:#000000; text-wrap:pretty; }
  /* ONE sage word, and it is the brand's own name being translated. 6.16:1 on
     white — the same measurement that lets white ink sit on the sage button.
     §3 exception 4, and it is scoped to this class: a second use is a decision,
     not a copy edit. */
  /* 600, not the UA's `bolder`: a <strong> inside a 400 paragraph resolves to
     700, which is not in the set (§8). Same fix as .trust-stat strong had. */
  .em-sage{ color:var(--sage); font-weight:600; }
  /* /404 only: the services 46px square above the claim. .hero-center is a
     centred flex column with its own gap, so the icon needs nothing but a
     colour — ochre, the one ink the page has no other claim on. */
  .err-icon{ display:block; color:var(--ink-ochre); }
  /* the same pair as who-we-serve: ask first, read-on second, baselines aligned */
  .phero-cta{ display:flex; flex-wrap:wrap; align-items:baseline; justify-content:center;
              gap:clamp(16px,1.6vw,26px); margin-top:clamp(10px,1.4vh,18px); }

  /* ---- the four services, 2x2 ----
     The rail pattern (7.5), but the block inside is two rows rather than one.
     The only --line-strong horizontals are the rail's own, top and bottom, so
     the bottom rule lands under the SECOND row — the four cards read as one
     block of four, not as two rows of two. Everything between is --line. */
  .quad{ padding:0 0 clamp(72px,10vh,124px); background:#ffffff; }
  .quad-head{ max-width:1240px; margin:0 auto clamp(44px,6.5vh,72px); padding:0 clamp(20px,4vw,44px); text-align:center; }
  .quad h2{ margin:0 auto clamp(16px,2vh,24px); color:#000000; text-wrap:balance; max-width:26ch; }
  .quad-lede{ margin:0 auto; max-width:62ch; color:#000000; text-wrap:pretty; }
  .quad-rail{ border-top:1px solid var(--line-strong); border-bottom:1px solid var(--line-strong); padding:0 clamp(20px,4vw,44px); }
  .quad-list{ margin:0 auto; padding:0; list-style:none; display:grid; grid-template-columns:repeat(2,1fr);
              max-width:1240px; border-left:1px solid var(--line); border-right:1px solid var(--line); }
  /* 1fr on the body row pins every link to the bottom of its cell, so the four
     links sit on two lines rather than four. No subgrid needed: cells in a row
     already stretch to equal height. */
  .quad-item{ display:grid; grid-template-rows:auto auto auto 1fr auto; gap:14px;
              justify-items:start; padding:clamp(32px,3.2vw,46px) clamp(24px,2.4vw,36px); }
  .quad-item:nth-child(even){ border-left:1px solid var(--line); }
  .quad-item:nth-child(n+3){ border-top:1px solid var(--line); }
  .quad-icon{ display:block; margin-bottom:6px; }
  .quad-icon svg{ width:46px; height:46px; display:block; }
  .quad-name{ color:#000000; }
  /* four services, the four inks, in the order the page lists them */
  .quad-item:nth-child(1) .quad-icon{ color:var(--ink-blue); }
  .quad-item:nth-child(2) .quad-icon{ color:var(--ink-green); }
  .quad-item:nth-child(3) .quad-icon{ color:var(--ink-purple); }
  .quad-item:nth-child(4) .quad-icon{ color:var(--ink-ochre); }

  /* ---- the bridge, and the quote-to-profit chain ----
     Same device as the who-we-serve progression rails, doing the same job:
     showing that a set has an ORDER. scaleX off a left origin plus opacity, one
     segment at a time, looping. Reusing it rather than inventing a second
     sequence gesture is the point. */
  .bridge{ padding:0 clamp(20px,4vw,44px) clamp(72px,10vh,124px); background:#ffffff; }
  .bridge-inner{ max-width:1240px; margin:0 auto; text-align:center; display:flex; flex-direction:column; align-items:center; }
  .bridge h2{ margin:0 auto clamp(18px,2.4vh,28px); color:#000000; text-wrap:balance; max-width:26ch; }
  .bridge-lede{ margin:0 auto; max-width:62ch; color:#000000; text-wrap:pretty; }
  .bridge-copy{ max-width:62ch; color:#000000; text-wrap:pretty; }
  .bridge .explore-link{ margin-top:1.35em; }

  .hero-center .chain{ margin:clamp(30px,4vh,44px) auto clamp(4px,1vh,10px); max-width:820px; }
  .chain{ list-style:none; margin:clamp(38px,5vh,56px) 0; padding:0; width:100%;
          display:flex; align-items:center; justify-content:center; flex-wrap:wrap; gap:clamp(10px,1.4vw,20px); }
  .chain-step{ white-space:nowrap; }
  .chain-name{ color:#000000; }
  .chain-link{ flex:1 1 0; min-width:28px; max-width:120px; }
  .chain-track{ display:block; width:100%; height:2px; background:var(--line); position:relative; overflow:hidden; }
  .chain-track i{ position:absolute; inset:0; background:var(--sage);
                  transform:scaleX(0); transform-origin:left center;
                  animation:chain-fill 8s linear infinite both; }
  /* The links are the 2nd, 4th, 6th and 8th LI — steps and links alternate.
     :nth-of-type counts li, not .chain-link, so (2)(3)(4) gave the first link
     .9s, the second 2.7s and left the last two on 0s: three tracks filling at
     once. Index by the real li position. */
  .chain-link:nth-of-type(4) .chain-track i{ animation-delay:.9s; }
  .chain-link:nth-of-type(6) .chain-track i{ animation-delay:1.8s; }
  .chain-link:nth-of-type(8) .chain-track i{ animation-delay:2.7s; }
  @keyframes chain-fill{
    0%   { transform:scaleX(0); opacity:1; }
    11%  { transform:scaleX(1); opacity:1; }
    46%  { transform:scaleX(1); opacity:1; }
    55%  { transform:scaleX(1); opacity:0; }
    56%  { transform:scaleX(0); opacity:0; }
    100% { transform:scaleX(0); opacity:0; }
  }

  /* ---- the stepped chain — the rail's SECOND FORM, /financial-decisions ----
     Same device and same statement as the flat chain above it: this set has an
     ORDER. What changes is that each stop now carries its own paragraph, so the
     stops cannot sit on one line with the copy under the whole row — the copy
     would stop belonging to a stop. Three stops step down and across instead,
     and the connector becomes an arc because a straight rule between two points
     on different rows reads as a table divider.

     The path is GENERATED in app.js from the laid-out dot positions, exactly
     like the 90-day snake, so it survives a resize, a font swap and the stack
     below 900 without a second SVG. --arc-bulge is the perpendicular hump as a
     fraction of the gap; it goes NEGATIVE below 900 so the vertical stack bulges
     into the left gutter rather than across the copy. */
  .bridge--steps .bridge-inner{ text-align:left; align-items:stretch; position:relative; }
  /* ---- the question field ----
     The stepped arc runs top-left to bottom-right, so it leaves two empty
     triangles: above the second and third stops, and below the first. The
     hero's question pills fill them — same capsule, same four tints.

     ALL SIX ARE SHARP. The hero blurs half its pills because they crowd a
     claim and have to recede to colour; here the triangles are genuinely empty,
     nothing competes, and a blurred pill in clear space reads as a rendering
     fault rather than depth.

     STATIC. The hero's pills drift because they are the only thing moving in
     that block; here the arc already carries the section's one motion, and a
     second loop beside it reads as noise. aria-hidden: they are atmosphere, and
     the questions that matter are the eight named decisions below.

     z-index 0 puts them behind .step (z-index 1) and behind the arc, so a
     narrow viewport can overlap them with copy without the copy suffering.
     They are gone below 1100 anyway — the diagonal collapses to one column and
     the triangles go with it. */
  .bridge-pills{ position:absolute; inset:0; margin:0; padding:0; list-style:none;
                 pointer-events:none; z-index:0; }
  .bp{ position:absolute; }
  .bp-1{ top:34%; right:1%; }
  .bp-2{ top:47%; right:13%; }
  .bp-3{ top:60%; right:3%; }
  .bp-4{ top:74%; left:2%; }
  .bp-5{ top:86%; left:13%; }
  .bp-6{ top:95%; left:0; }
  @media (max-width:1100px){ .bridge-pills{ display:none; } }
  .bridge--steps h2, .bridge--steps .bridge-lede{ text-align:center; }
  .bridge--steps .bridge-lede{ align-self:center; }
  /* The copy is deliberately NARROW. A wide stop wraps to two lines, the drop
     between stops has to grow to clear it, the slope steepens and the arc runs
     out of room at the top of the box — which is how the first hump got clipped.
     Narrow copy -> more lines -> shorter drop -> a shallower arc that fits. */
  .steps{ --arc-bulge:.28; --step-drop:clamp(72px,8vw,104px);
          list-style:none; max-width:1040px; margin:clamp(38px,5vh,56px) auto 0;
          padding:clamp(56px,7vh,96px) 0 clamp(40px,5vh,64px);
          position:relative; display:grid; grid-template-columns:repeat(3,minmax(0,1fr)); }
  .step{ position:relative; z-index:1; padding:0 clamp(20px,2.4vw,40px) 0 0; }
  .step:last-child{ padding-right:0; }
  .step:nth-child(2){ padding-top:var(--step-drop); }
  .step:nth-child(3){ padding-top:calc(2 * var(--step-drop)); }
  .step-dot{ display:block; width:14px; height:14px; border-radius:50%; background:#000000;
             margin:0 0 clamp(18px,2.4vh,28px); }
  .step-name{ margin:0; color:#000000; }
  .step-copy{ max-width:26ch; }
  .steps-svg{ position:absolute; inset:0; width:100%; height:100%; pointer-events:none; overflow:hidden; z-index:0; }
  .steps-track{ fill:none; stroke:var(--line); stroke-width:2; stroke-dasharray:5 9; }
  /* --seg/--rest/--start are written by app.js in px once the path has a length.
     Before that --seg is 0, so nothing paints rather than a full sage arc. */
  .steps-run{ --seg:0px; --rest:9999px; --start:0px;
              fill:none; stroke:var(--sage); stroke-width:2; stroke-linecap:round;
              stroke-dasharray:var(--seg) var(--rest); stroke-dashoffset:var(--start);
              animation:steps-run 8s linear infinite; }
  /* One dash whose PERIOD is the whole path (--seg + --rest = the length), so
     when it runs off the end past the answer the pattern's next repetition is
     already entering at the start: the return leg lights while the answer is
     still lit, and the two read as one line coming back round. Paint-only, like
     .tl-draw — §5's stroke-dashoffset exception. */
  @keyframes steps-run{ to{ stroke-dashoffset:0; } }

  /* ---- closing CTA ----
     EVERY page ends on the scheduler, not on a link to it. Getting onto the
     calendar is the point of the page, and one extra hop is where people stop.
     A link that survives beside it is the SAME underline-with-arrow button
     recoloured for the inverted ground the way §3 recolours every glyph in this
     block — not a third type. */
  .cta-link{ margin-top:clamp(26px,3.4vh,40px); color:var(--on); border-bottom-color:rgba(255,255,255,.5); }
  .cta-link:hover{ color:var(--on); border-bottom-color:var(--on); }
  /* the timeline's own closing link, inside the dark block */
  .hiw-more{ margin-top:clamp(34px,4.5vh,56px); color:#ffffff; border-bottom-color:rgba(255,255,255,.5); }
  .hiw-more:hover{ color:#ffffff; border-bottom-color:#ffffff; }

  /* ================= service sub-pages =================
     /what-we-do/ongoing-management/ and .../accounting/. Same discipline: no
     type, no colour, no radius that is not already in the set. */

  /* screen-reader-only, for the table caption */
  .vh{ position:absolute; width:1px; height:1px; margin:-1px; padding:0; overflow:hidden;
       clip:rect(0 0 0 0); clip-path:inset(50%); white-space:nowrap; border:0; }
  /* the down arrow points at a section on this page, so it must not slide
     sideways on hover like the ones that navigate away */
  .explore-link:hover .arrow--down{ transform:translateY(3px); }

  /* ---- four things you get: the lightest rail on the site ---- */
  .gets{ padding:0 0 clamp(56px,8vh,88px); background:#ffffff; }
  .gets-head{ max-width:1240px; margin:0 auto clamp(36px,5vh,56px); padding:0 clamp(20px,4vw,44px); text-align:center; }
  .gets h2{ margin:0 auto; color:#000000; text-wrap:balance; max-width:26ch; }
  /* ---- what you get: two rows, text one side and a picture the other ----
     No rail rules and no cells. Four ruled boxes said "four features"; the point
     is that the numbers and the conversation are two halves of one service, so
     the four items pair off and each pair sits opposite the thing it produces —
     the money map, then the thread. The text column keeps the width the ruled
     cell had and the picture takes the rest, the same way on both rows: the
     alternating version put unequal margins either side of the section. */
  .gets-rail{ padding:0 clamp(20px,4vw,44px); }
  .gets-row{ max-width:1240px; margin:0 auto; display:grid; grid-template-columns:minmax(0,340px) minmax(0,1fr);
             gap:clamp(30px,5vw,80px); align-items:center; }
  .gets-row + .gets-row{ margin-top:clamp(56px,8vh,104px); }
  .gets-media{ margin:0; min-width:0; }
  .gets-media img{ display:block; width:100%; height:auto; }
  /* The thread row is NOT the money map's row. A chat at the map's 824px is a
     wall of bubbles, so the box is about half that and the pair is centred as a
     group instead of spanning the measure — the two rows deliberately do not
     line up with each other. */
  .gets-row--chat{ grid-template-columns:minmax(0,320px) minmax(0,440px); justify-content:center; }
  /* the thread is an exchange, not an illustration — a box says where it happens.
     16px and --line-strong are the portrait's and the guarantee's, not new. */
  .gets-media--box{ border:1px solid var(--line-strong); border-radius:16px;
                    padding:clamp(22px,2.4vw,34px) clamp(18px,2vw,28px); }
  /* the flanks belong to the ruled grid this row replaced */
  .gets-row .gets-list{ display:flex; flex-direction:column; gap:clamp(30px,4.5vh,52px);
                        max-width:none; border-left:0; border-right:0; }
  .gets-row .get{ display:block; padding:0; border:0; }
  .gets-row .get + .get{ border-left:0; }
  /* the name takes the question wall's capsule — same four tints, same 999px,
     same .pill--b shadow, shuffled so no two neighbours share one */
  .gets-row .get-name{ display:inline-block; margin:0 0 12px; padding:9px 18px; border-radius:999px;
                       background:var(--get-bg); border:1px solid var(--get-line);
                       box-shadow:0 12px 24px -22px rgba(0,0,0,.4); }
  .get--green{ --get-bg:var(--green-bg); --get-line:var(--green-line); }
  .get--blue{ --get-bg:var(--blue-bg); --get-line:var(--blue-line); }
  .get--purple{ --get-bg:var(--purple-bg); --get-line:var(--purple-line); }
  .get--yellow{ --get-bg:var(--yellow-bg); --get-line:var(--yellow-line); }
  .gets-list{ margin:0 auto; padding:0; list-style:none; display:grid; grid-template-columns:repeat(4,1fr);
              max-width:1240px; border-left:1px solid var(--line); border-right:1px solid var(--line); }
  /* no icons and less padding than the tile blocks — "visually light" is a
     smaller cell, not a smaller typeface */
  .get{ display:grid; grid-template-rows:auto 1fr; gap:10px; justify-items:start;
        padding:clamp(24px,2.4vw,32px) clamp(20px,2vw,28px); }
  .get + .get{ border-left:1px solid var(--line); }
  /* --plain: no rules at all. The four-up's frame was tried on the business-type
     pages and cut — those pages are a vertical read with six sections and no
     ruled block anywhere, so a single framed grid in the middle became the one
     thing on the page wearing a box. Cells keep their padding, so the row still
     spaces itself. */
  .gets-list--plain{ border-left:0; border-right:0; }
  .gets-list--plain .get + .get{ border-left:0; }
  /* --tiles: four closed boxes that do not touch, the FAQ's device at 4-up.
     A shared-edge grid says "one object split four ways"; these are four
     separate things we watch, so they take the gap and each closes itself at
     the outer-edge weight. Radius and border are .tstm-card's.

     The modifier is on the SECTION, not the list, because it also owns the
     section's bottom padding: .gets pays 72 and every other section on those
     pages pays 90, which read as a short gap in a six-section vertical. */
  .gets--tiles{ padding-bottom:clamp(72px,10vh,124px); }
  .gets--tiles .gets-list{ border-left:0; border-right:0; gap:clamp(18px,2vw,28px); align-items:stretch; }
  .gets--tiles .get, .gets--tiles .get + .get{
    border:1px solid var(--line-strong); border-radius:16px;
    padding:clamp(26px,2.6vw,34px) clamp(22px,2.2vw,30px); }
  .get-name{ color:#000000; }
  .get-copy{ color:#000000; text-wrap:pretty; }

  /* ---- example engagements ---- */
  .eng{ padding:0 0 clamp(72px,10vh,124px); background:#ffffff; }
  .eng-head{ max-width:1240px; margin:0 auto clamp(40px,5.5vh,64px); padding:0 clamp(20px,4vw,44px); text-align:center;
             display:flex; flex-direction:column; align-items:center; }
  /* the cue labels the tiles, so it comes AFTER the section's thesis and sits
     outside the rail, not over the h2 and not inside the ruled band */
  .eng-cue{ display:block; color:#000000; margin-top:clamp(22px,3vh,32px); }
  .eng h2{ margin:0 auto clamp(16px,2vh,24px); color:#000000; text-wrap:balance; max-width:26ch; }
  .eng-lede{ margin:0 auto; max-width:60ch; color:#000000; text-wrap:pretty; }
  .eng-rail{ border-top:1px solid var(--line-strong); border-bottom:1px solid var(--line-strong); padding:0 clamp(20px,4vw,44px); }
  .eng-list{ margin:0 auto; padding:0; list-style:none; display:grid; grid-template-columns:repeat(3,1fr);
             grid-template-rows:repeat(4,auto);
             max-width:1240px; border-left:1px solid var(--line); border-right:1px solid var(--line); }
  /* the price sits ABOVE the description on purpose: the whole point of the
     section is that the number is scannable before anyone reads prose */
  /* subgrid, so the name / meta / price / copy rows are the LIST's rows and the
     longest name lifts every tile's meta line together instead of pushing only
     its own copy down */
  .eng-item{ display:grid; grid-row:span 4; grid-template-rows:subgrid; row-gap:14px; justify-items:start;
             padding:clamp(30px,3vw,42px) clamp(24px,2.4vw,36px); }
  .eng-item + .eng-item{ border-left:1px solid var(--line); }
  .eng-name{ color:#000000; }
  .eng-price{ color:#000000; }
  .eng-copy{ color:#000000; text-wrap:pretty; }
  /* the dot TRAILS its item and is inline, so the row wraps without orphaning a
     leading dot onto the next line */
  .eng-meta{ list-style:none; margin:0; padding:0; display:flex; flex-wrap:wrap; align-items:center; gap:4px 11px; }
  .eng-meta li{ position:relative; color:#000000; font:400 var(--ui)/1.4 'Work Sans',sans-serif; }
  .eng-meta li:not(:last-child)::after{ content:''; display:inline-block; vertical-align:middle;
      width:3px; height:3px; margin:0 0 2px 11px; border-radius:50%; background:rgba(0,0,0,.4); }

  /* ---- keep your bookkeeper, or don't ---- */
  .opt{ padding:0 clamp(20px,4vw,44px) clamp(72px,10vh,124px); background:#ffffff; }
  .opt-inner{ max-width:1240px; margin:0 auto; display:flex; flex-direction:column; align-items:center; text-align:center; }
  .opt h2{ margin:0 auto clamp(16px,2vh,24px); color:#000000; text-wrap:balance; max-width:26ch; }
  .opt-lede{ margin:0 auto; max-width:64ch; color:#000000; text-wrap:pretty; }
  .opt-ways{ list-style:none; margin:clamp(34px,4.5vh,52px) 0 0; padding:0; width:100%;
             display:grid; grid-template-columns:1fr 1fr; border:1px solid var(--line-strong); }
  .opt-way{ display:grid; gap:12px; justify-items:center; padding:clamp(28px,3vw,40px) clamp(22px,2.2vw,32px); }
  .opt-way + .opt-way{ border-left:1px solid var(--line); }
  /* the two configurations, said as a sum. The part Avanza owns is the filled
     one — colour is not doing the work, weight and ground are. */
  .opt-parts{ display:flex; flex-wrap:wrap; align-items:center; justify-content:center; gap:10px; }
  .opt-part{ display:inline-block; padding:9px 16px; border-radius:999px; border:1px solid var(--line-strong);
             color:#000000; font:500 var(--ui)/1.2 'Work Sans',sans-serif; }
  .opt-part--us{ background:var(--sage); border-color:var(--sage); color:#ffffff; }
  .opt-plus{ color:#000000; font:500 var(--ui)/1 'Work Sans',sans-serif; }
  .opt-note{ color:#000000; text-wrap:pretty; max-width:34ch; }
  .opt .explore-link{ margin-top:clamp(26px,3vh,36px); }
  /* both CTAs sit under the lede and ABOVE the two ways — the choice below is
     easier to read once you know what it is choosing between */
  .opt-cta, .band-cta{ display:flex; flex-wrap:wrap; align-items:baseline; justify-content:center;
                       gap:clamp(18px,2.4vw,30px); margin-top:clamp(24px,3vh,34px); }
  .opt-cta .explore-link{ margin-top:0; }
  .opt-cta + .opt-ways{ margin-top:clamp(34px,4.5vh,52px); }

  /* ---- the narrow band ---- */
  .band{ padding:clamp(44px,6vh,72px) clamp(20px,4vw,44px); background:#ffffff;
         border-top:1px solid var(--line-strong); border-bottom:1px solid var(--line-strong); }
  /* when the band follows a ruled grid its top rule doubles the grid's bottom
     one — two hairlines a section apart read as a mistake */
  .band--flush{ border-top:none; padding-top:clamp(56px,7vh,88px); }
  /* --plain: neither rule. On the business-type pages the band is one of six
     sections in a vertical read and its two rules were the only lines on the
     page; a section that closes itself in the middle of a scroll reads as an
     interruption rather than a step. */
  /* --plain also carries the standard gap: .band pays 54 where every section
     around it pays 90, and on a page with no rules at all that short gap is the
     only thing marking the band as a different kind of block. */
  .band--plain{ border-top:none; border-bottom:none; padding-bottom:clamp(72px,10vh,124px); }
  .band-inner{ max-width:900px; margin:0 auto; display:flex; flex-direction:column; align-items:center; text-align:center; }
  .band h2{ margin:0 auto clamp(14px,1.8vh,20px); color:#000000; text-wrap:balance; max-width:26ch; }
  .band-copy{ color:#000000; text-wrap:pretty; }
  .band-lede{ margin:0 auto; max-width:62ch; color:#000000; text-wrap:pretty; }
  .band .explore-link{ margin-top:clamp(20px,2.6vh,30px); }

  /* ---- one small callout, deliberately not a second service menu ---- */
  .callout{ padding:clamp(72px,10vh,124px) clamp(20px,4vw,44px); background:#ffffff; }
  .callout-box{ max-width:760px; margin:0 auto; border:1px solid var(--line-strong);
                padding:clamp(30px,3.4vw,46px) clamp(24px,2.8vw,40px);
                display:flex; flex-direction:column; align-items:center; text-align:center; }
  .callout-h{ margin:0 0 clamp(14px,1.8vh,20px); color:#000000; text-wrap:balance; }
  /* --out: the head leaves the box. A section head inside its own outline reads
     as a card's title rather than the section's, which is right for a callout
     inside a longer page and wrong when the box IS the section. */
  .callout-h--out{ max-width:1240px; margin:0 auto clamp(26px,3.4vh,40px); text-align:center; }
  /* the split form: head + sub-head left, the paragraph and its link right, and
     NO divider between them — the gap does the separating, so the box stays one
     object rather than reading as two cells */
  .callout--split .callout-box{ max-width:1240px; display:grid; grid-template-columns:1fr 1fr;
                                gap:clamp(24px,3.4vw,56px); align-items:stretch; text-align:left; }
  /* both columns stretch, and the right one pushes its link to the foot — so the
     link sits on the last line of the lede opposite it rather than floating in
     the middle of the box */
  .callout--split .callout-side:last-child{ justify-content:space-between; }
  .callout--split .callout-side:last-child .explore-link{ margin-top:clamp(34px,4.4vh,54px); }
  .callout--split .callout-h{ text-align:left; }
  .callout-lede{ margin:0; color:#000000; text-wrap:pretty; }
  .callout-side{ display:flex; flex-direction:column; align-items:flex-start; }
  .callout-copy{ color:#000000; text-wrap:pretty; }
  /* the box carried one paragraph until /partners; a second one needs the gap
     the band pays between its head and its lede — no new value */
  .callout-copy + .callout-copy{ margin-top:clamp(14px,1.8vh,20px); }
  .callout .explore-link{ margin-top:clamp(22px,2.8vh,32px); }

  /* ---- the plans table ----
     The one genuinely new component on these pages, and it is built out of the
     hairlines the rest of the site already uses: --line between rows, --line
     down the column gutters, --line-strong closing the rail. No fills, no
     zebra striping, no rounded plan cards. */
  .plans{ padding:0 0 clamp(56px,8vh,88px); background:#ffffff; }
  .plans-head{ max-width:1240px; margin:0 auto clamp(40px,5.5vh,64px); padding:0 clamp(20px,4vw,44px); text-align:center; }
  .plans h2{ margin:0 auto; color:#000000; text-wrap:balance; max-width:26ch; }
  /* the space belongs to the lede, not the head: /pricing renders the same head
     WITHOUT a lede, and a margin on the h2 left 18px of dead air under it */
  .plans-lede{ margin:clamp(16px,2vh,24px) auto 0; max-width:62ch; color:#000000; text-wrap:pretty; }
  /* the head's CTA, filled on /accounting and an underline link on /pricing —
     both need the same air under the lede */
  .plans-head .btn-solid, .plans-head .explore-link{ display:inline-flex; margin-top:clamp(26px,3.2vh,38px); }
  /* --even / --flush: one rhythm down the accounting page. Every other section
     on the site pays its gap from the BOTTOM only; .incl and .callout also pay
     a top, which made the gaps read 171 / 90 / 72 / 180 down that page. The
     modifiers drop those tops and even the plans bottom, so every gap is 90.
     Scoped, because both classes render on pages that were not asked to move.
     Tag-qualified: .incl is declared LOWER in the file, so a bare class of the
     same specificity loses to it. */
  section.incl--flush, section.callout--flush{ padding-top:0; }
  section.plans--even{ padding-bottom:clamp(72px,10vh,124px); }
  .plans-rail{ border-top:1px solid var(--line-strong); border-bottom:1px solid var(--line-strong); padding:0 clamp(20px,4vw,44px); }
  /* the table scrolls INSIDE its rail rather than pushing the page sideways —
     the a11y rule is no horizontal overflow on the document, not no scrolling
     container */
  .plans-scroll{ max-width:1240px; margin:0 auto; overflow-x:auto; }
  .plans-table{ width:100%; min-width:720px; border-collapse:collapse; text-align:left; }
  .plans-table th, .plans-table td{ padding:14px clamp(12px,1.4vw,20px); vertical-align:top; color:#000000; }
  /* --tiers: the accounting table is read DOWN a column, so every cell centres
     and only the row label stays left. Scoped, because /pricing renders the same
     component and was not asked to change. */
  .plans-table--tiers th, .plans-table--tiers td{ text-align:center; }
  .plans-table--tiers th[scope=row]{ text-align:left; }
  /* Growing is the column most people land on, so it carries a wash rather than
     a badge. color-mix between two members of the closed set — the same move the
     trust bar makes — so no fifth ground is authored. */
  .plans-table--tiers thead th:nth-child(3),
  .plans-table--tiers tbody td:nth-child(3){ background:color-mix(in srgb, var(--sage) 7%, #ffffff); }
  .plans-table thead th{ border-bottom:1px solid var(--line-strong); }
  .plans-table tbody tr + tr th, .plans-table tbody tr + tr td{ border-top:1px solid var(--line); }
  .plans-table th[scope=row]{ font:400 var(--ui)/1.45 'Work Sans',sans-serif; width:30%; }
  .plans-table td{ font:400 var(--ui)/1.45 'Work Sans',sans-serif; }
  .plans-table td + td, .plans-table th + th, .plans-table th + td{ border-left:1px solid var(--line); }
  /* the row people came for */
  .plans-price th, .plans-price td{ border-top:1px solid var(--line-strong) !important; padding-top:20px; padding-bottom:20px; }
  .plans-price td{ font:600 clamp(19px,.7vw + .9vh,25px)/1.25 'Work Sans',sans-serif; letter-spacing:-.012em; }
  /* no font-size: a tick is not its own type step. It inherits the cell's C2
     size. Writing 1.15x here resolved to 17.87px — an eighth size on the page. */
  .tick{ line-height:1; }
  .tick--no{ color:#000000; opacity:.35; }
  .plans-foot{ max-width:1240px; margin:0 auto; padding:clamp(28px,3.6vh,40px) clamp(20px,4vw,44px) 0; text-align:center; }

  /* ---- what accounting includes ---- */
  .incl{ padding:clamp(72px,10vh,124px) clamp(20px,4vw,44px); background:#ffffff; }
  .incl-inner{ max-width:1240px; margin:0 auto; display:flex; flex-direction:column; align-items:center; text-align:center; }
  .incl h2{ margin:0 auto clamp(16px,2vh,24px); color:#000000; text-wrap:balance; max-width:26ch; }
  .incl-lede{ margin:0 auto clamp(26px,3.2vh,38px); color:#000000; }
  .incl-list{ list-style:none; margin:0; padding:0; width:100%; max-width:1040px;
              display:grid; grid-template-columns:1fr 1fr; gap:clamp(16px,2vh,22px) clamp(24px,3vw,44px); text-align:left; }
  .incl-list li{ position:relative; padding-left:36px; color:#000000; text-wrap:pretty; }
  /* black, not sage. §3: every glyph is #000 outside the two inverted grounds,
     and a tick is a glyph. --sage stays on the button, the rails and the CTA
     ground; it does not leak into type just because it would look nice. */
  .incl-list li::before{ content:'\2713'; position:absolute; left:0; top:0; color:#000000; line-height:1.5; }
  .incl-note{ margin-top:clamp(26px,3.2vh,38px); max-width:62ch; color:#000000; text-wrap:pretty; }

  /* ---- chips: what moves the price, and what we plug into ----
     Not clickable, so not a button. Outline + 999px, both already in the set. */
  .chips{ list-style:none; margin:0; padding:0; display:flex; flex-wrap:wrap; justify-content:center; gap:10px; }
  /* in a hero the chips take the slot the one-line price used to, so they need
     its spacing and the hero's own measure */
  .hero-center .chips{ margin:clamp(18px,2.4vh,26px) auto 0; max-width:900px; }
  .chip{ display:inline-block; padding:9px 16px; border-radius:999px; border:1px solid var(--line-strong);
         color:#000000; font:500 var(--ui)/1.2 'Work Sans',sans-serif; }
  .cx{ padding:0 clamp(20px,4vw,44px) clamp(72px,10vh,124px); background:#ffffff; }
  .cx-inner, .sys-inner{ max-width:940px; margin:0 auto; display:flex; flex-direction:column; align-items:center; text-align:center; }
  .cx h2, .sys h2{ margin:0 auto clamp(24px,3vh,34px); color:#000000; text-wrap:balance; max-width:26ch; }
  .cx-note{ margin-top:clamp(24px,3vh,34px); color:#000000; }
  .cx .explore-link{ margin-top:clamp(18px,2.2vh,26px); }
  .sys{ padding:0 clamp(20px,4vw,44px) clamp(72px,10vh,124px); background:#ffffff; }
  .sys-note{ margin-top:clamp(24px,3vh,34px); max-width:62ch; color:#000000; text-wrap:pretty; }

  /* ---- Setup: a project MENU, scannable in fifteen seconds ----
     Six tight cells, three across. The name leads and the explanation follows,
     because someone scanning is reading names, not sentences. This is the
     densest grid on the site and that density IS the difference between this
     page and /what-we-do/financial-decisions/. */
  .projs{ padding:0 0 clamp(72px,10vh,124px); background:#ffffff; }
  .projs-head{ max-width:1240px; margin:0 auto clamp(40px,5.5vh,64px); padding:0 clamp(20px,4vw,44px); text-align:center; }
  .projs h2{ margin:0 auto clamp(16px,2vh,24px); color:#000000; text-wrap:balance; max-width:26ch; }
  .projs-lede{ margin:0 auto; max-width:62ch; color:#000000; text-wrap:pretty; }
  .projs-rail{ border-top:1px solid var(--line-strong); border-bottom:1px solid var(--line-strong); padding:0 clamp(20px,4vw,44px); }
  .projs-list{ margin:0 auto; padding:0; list-style:none; display:grid; grid-template-columns:repeat(3,1fr);
               max-width:1240px; border-left:1px solid var(--line); border-right:1px solid var(--line); }
  .proj{ display:grid; grid-template-rows:auto 1fr auto; gap:10px; justify-items:start;
         padding:clamp(26px,2.6vw,36px) clamp(22px,2.2vw,30px); }
  .proj:not(:nth-child(3n+1)){ border-left:1px solid var(--line); }
  .proj:nth-child(n+4){ border-top:1px solid var(--line); }
  .proj-name{ color:#000000; text-wrap:balance; }
  .proj-copy{ color:#000000; text-wrap:pretty; }
  /* the 1fr row above pins this to the bottom of the cell, so the three priced
     cells state their floor on the same line rather than wherever the copy ends */
  .proj-price{ align-self:end; padding-top:14px; color:#000000; }

  /* ---- Financial Decisions: a page of the owner's own questions ----
     Two across, not three, and the QUESTION is the largest thing in the cell
     with the formal project name demoted to a label beneath it. Someone lands
     here already holding the question; the job is to let them find it, not to
     teach them a taxonomy. */
  .dqs{ padding:0 0 clamp(72px,10vh,124px); background:#ffffff; }
  .dqs-head{ max-width:1240px; margin:0 auto clamp(40px,5.5vh,64px); padding:0 clamp(20px,4vw,44px); text-align:center; }
  .dqs h2{ margin:0 auto; color:#000000; text-wrap:balance; max-width:26ch; }
  /* No rules on this one. Eight tinted capsules already read as a set, and a
     ruled grid around them fought the pills for the same job — see the hero,
     where the questions are pills on open ground for the same reason. */
  .dqs-rail{ padding:0 clamp(20px,4vw,44px); }
  /* the flanks went with the rules: with no ruled grid there are no cells to
     flank, so the gap carries the spacing the cell padding used to */
  /* Two columns sized to the copy, not to the page: at the full 1240 measure a
     38ch paragraph left the right half of each cell empty and the whole wall
     leaned left under a centred head. The block is capped near its real content
     width and centred instead. */
  .dq-list{ margin:0 auto; padding:0; list-style:none; display:grid;
            grid-template-columns:repeat(2,minmax(0,380px)); justify-content:center;
            max-width:1240px; gap:clamp(48px,6vh,72px) clamp(48px,6vw,104px); }
  .dq{ display:grid; grid-template-rows:auto auto 1fr; gap:12px; justify-items:start; padding:0; }
  .dq-q{ color:#000000; text-wrap:balance; }
  /* the LABEL takes the hero pill's capsule — same four tints, same 999px, same
     shadow as .pill--b, and a label inside a shape may take D's size (§2). The
     question keeps its own weight, so the capsule names the project rather than
     competing with the question above it. Tints are shuffled in the markup so no
     two neighbours share one in either direction. */
  .dq-name{ display:inline-block; padding:9px 17px; border-radius:999px;
            background:var(--dq-bg); border:1px solid var(--dq-line);
            box-shadow:0 12px 24px -22px rgba(0,0,0,.4); }
  .dq--green{ --dq-bg:var(--green-bg); --dq-line:var(--green-line); }
  .dq--yellow{ --dq-bg:var(--yellow-bg); --dq-line:var(--yellow-line); }
  .dq--blue{ --dq-bg:var(--blue-bg); --dq-line:var(--blue-line); }
  .dq--purple{ --dq-bg:var(--purple-bg); --dq-line:var(--purple-line); }
  /* capped so the paragraph wraps to more, shorter lines: it puts real space
     between one question and the next without a rule doing the separating */
  .dq-copy{ margin-top:10px; max-width:38ch; color:#000000; text-wrap:pretty; }

  /* ================= /partners =================
     Seven categories, two across, no rules. Same construction as the Financial
     Decisions wall (7.18) with the label ABOVE the name rather than below it:
     someone reading this page is scanning for what THEY get, so the capsule is
     the scan line and the category name answers it. Every value here is an
     existing group widened — the capsule rule is .dq-name's, taken verbatim.

     Seven is odd on purpose: the copy names seven kinds of partner and writing
     an eighth to square the grid is filler. The last cell sits alone in the
     left column, the cost §7.12 already accepts for the FAQ. */
  .pnrs{ padding:0 0 clamp(72px,10vh,124px); background:#ffffff; }
  .pnrs-head{ max-width:1240px; margin:0 auto clamp(40px,5.5vh,64px); padding:0 clamp(20px,4vw,44px); text-align:center; }
  .pnrs h2{ margin:0 auto; color:#000000; text-wrap:balance; max-width:26ch; }
  .pnrs-rail{ padding:0 clamp(20px,4vw,44px); }
  /* Columns sized to the copy, not to the page — the .dq-list measurement, one
     step wider because these cells carry two paragraphs where a decision cell
     carries one. */
  .pnr-list{ margin:0 auto; padding:0; list-style:none; display:grid;
             grid-template-columns:repeat(2,minmax(0,440px)); justify-content:center;
             max-width:1240px; gap:clamp(48px,6vh,72px) clamp(48px,6vw,104px); }
  /* Rows are content-sized and packed to the top. .dq can afford a 1fr last row
     because a decision cell has exactly three children; these carry a fourth,
     so a 1fr row stretches the FIRST paragraph and drops the second to the
     bottom of the cell — a ragged hole in five of the seven. */
  .pnr{ display:grid; grid-auto-rows:max-content; align-content:start;
        gap:12px; justify-items:start; padding:0; }
  .pnr-name{ color:#000000; }
  /* the capsule is .dq-name's rule; see that block for why a label may take D's
     size inside a shape */
  .pnr-cue{ display:inline-block; padding:9px 17px; border-radius:999px;
            background:var(--dq-bg); border:1px solid var(--dq-line);
            box-shadow:0 12px 24px -22px rgba(0,0,0,.4); }
  .pnr--green{ --dq-bg:var(--green-bg); --dq-line:var(--green-line); }
  .pnr--yellow{ --dq-bg:var(--yellow-bg); --dq-line:var(--yellow-line); }
  .pnr--blue{ --dq-bg:var(--blue-bg); --dq-line:var(--blue-line); }
  .pnr--purple{ --dq-bg:var(--purple-bg); --dq-line:var(--purple-line); }
  .pnr-copy{ max-width:46ch; color:#000000; text-wrap:pretty; }
  /* the grid's row gap separates the paragraphs; a margin on top of it pays the
     gap twice */

  /* ================= /pricing =================
     The page answers one question: what might I pay, and why. Everything here
     is either an existing component or a thin wrapper on one. */

  /* ---- the three headline signals, straight under the hero ---- */
  .sigs{ padding:0 0 clamp(56px,8vh,88px); background:#ffffff; }
  .sigs-rail{ border-top:1px solid var(--line-strong); border-bottom:1px solid var(--line-strong); padding:0 clamp(20px,4vw,44px); }
  .sig-list{ margin:0 auto; padding:0; list-style:none; display:grid; grid-template-columns:repeat(3,1fr);
             max-width:1240px; border-left:1px solid var(--line); border-right:1px solid var(--line); }
  .sig + .sig{ border-left:1px solid var(--line); }
  .sig-link{ display:grid; gap:10px; justify-items:start; padding:clamp(24px,2.4vw,32px) clamp(22px,2.2vw,30px); }
  .sig-link:hover{ background:rgba(0,0,0,.03); }
  .sig-name{ color:#000000; }
  .sig-price{ color:#000000; }

  /* ---- the two levers ----
     A scale that increases to the right is the same statement the progression
     rail already makes: this has an order. So it IS the progression rail —
     .chain-track and its keyframe, unchanged. No slider, no gradient, no new
     device to explain. */
  .lvr{ padding:0 0 clamp(56px,8vh,88px); background:#ffffff; }
  .lvr-head{ max-width:1240px; margin:0 auto clamp(40px,5.5vh,64px); padding:0 clamp(20px,4vw,44px); text-align:center; }
  .lvr h2{ margin:0 auto; color:#000000; text-wrap:balance; max-width:26ch; }
  .lvr-rail{ border-top:1px solid var(--line-strong); border-bottom:1px solid var(--line-strong); padding:0 clamp(20px,4vw,44px); }
  .lever-list{ margin:0 auto; padding:0; list-style:none; display:grid; grid-template-columns:1fr 1fr;
               max-width:1240px; border-left:1px solid var(--line); border-right:1px solid var(--line); }
  .lever{ display:grid; grid-template-rows:auto 1fr auto; gap:14px; justify-items:start;
          padding:clamp(30px,3vw,42px) clamp(24px,2.4vw,36px); }
  .lever + .lever{ border-left:1px solid var(--line); }
  .lever-name{ color:#000000; }
  .lever-copy{ color:#000000; text-wrap:pretty; }
  /* rail on its own row, ends beneath it. Side-by-side, a long right-hand
     label squeezed the rail to ~40px and it stopped reading as a scale. */
  .lever-scale{ width:100%; display:grid; gap:10px; }
  .lever-ends{ display:flex; justify-content:space-between; gap:16px; }
  .lever-end{ color:#000000; }
  .lever-end:last-child{ text-align:right; }
  .lever .chain-track{ width:100%; }
  .lever:nth-child(2) .chain-track i{ animation-delay:1.4s; }
  .lvr-foot{ max-width:1240px; margin:0 auto; padding:clamp(28px,3.6vh,40px) clamp(20px,4vw,44px) 0; text-align:center; }
  .lvr-note{ max-width:70ch; margin:0 auto; color:#000000; text-wrap:pretty; }

  /* ---- example engagements: the centrepiece ----
     Wide horizontal rows, not a column of cards. Facts and price on the left,
     what the engagement actually is on the right. The four rows are meant to be
     triangulated between — "more than the $1,500 one, nowhere near the $4,000
     one" — which only works if they read as one continuous scale, so they share
     a rail and are divided by --line rather than boxed separately. */
  /* ---- example engagements ----
     A boxed FACT SHEET on one side, the story unboxed on the other, alternating
     down the page. The box is where the numbers live, which is why it is the
     only thing with an edge; the account of the work reads as prose because it
     is prose. No rail rules: four bordered cards inside a ruled band would
     frame the same thing twice, the same call as the question wall. */
  .ex-sec{ padding:0 0 clamp(72px,10vh,124px); background:#ffffff; }
  .ex-head{ max-width:1240px; margin:0 auto clamp(40px,5.5vh,64px); padding:0 clamp(20px,4vw,44px); text-align:center;
            display:flex; flex-direction:column; align-items:center; }
  .ex-sec h2{ margin:0 auto; color:#000000; text-wrap:balance; max-width:26ch; }
  /* the home page's cut of this section carries a link on to /pricing; the
     pricing page's own head has none. Same air the band's link gets. */
  .ex-head .explore-link{ margin-top:clamp(20px,2.6vh,30px); }
  .ex-rail{ padding:0 clamp(20px,4vw,44px); }
  .ex-list{ margin:0 auto; padding:0; list-style:none; max-width:1240px;
            display:flex; flex-direction:column; gap:clamp(44px,6vh,76px); }
  .ex{ display:grid; grid-template-columns:minmax(0,600px) minmax(0,1fr);
       gap:clamp(28px,4vw,72px); align-items:center; }
  .ex:nth-child(even){ grid-template-columns:minmax(0,1fr) minmax(0,600px); }
  .ex:nth-child(even) .ex-card{ order:2; }
  .ex-card{ display:grid; gap:clamp(18px,2.4vh,26px);
            border:1px solid var(--line-strong); border-radius:16px;
            padding:clamp(26px,2.6vw,38px); }
  .ex-title{ color:#000000; text-wrap:balance; }
  .ex-stats{ list-style:none; margin:0; padding:0; display:grid; grid-template-columns:repeat(3,1fr); gap:10px; }
  .ex-stats li{ display:grid; gap:4px; justify-items:center; text-align:center;
                border:1px solid var(--line); border-radius:8px; padding:16px 12px; }
  .ex-stat{ color:#000000; }
  .ex-statlabel{ color:#000000; }
  .ex-foot{ display:flex; flex-wrap:wrap; align-items:flex-end; justify-content:space-between; gap:18px 24px; }
  .ex-emph, .ex-money{ margin:0; display:grid; gap:8px; justify-items:start; }
  .ex-money{ justify-items:end; text-align:right; }
  .ex-cue{ color:#000000; }
  /* the tag is the question wall's capsule again, one tint per engagement */
  .ex-tag{ display:inline-block; padding:9px 17px; border-radius:999px;
           background:var(--ex-bg); border:1px solid var(--ex-line);
           box-shadow:0 12px 24px -22px rgba(0,0,0,.4);
           color:#000000; font:500 calc(var(--ui) * 1.1)/1.3 'Work Sans',sans-serif; }
  .ex--green{ --ex-bg:var(--green-bg); --ex-line:var(--green-line); }
  .ex--blue{ --ex-bg:var(--blue-bg); --ex-line:var(--blue-line); }
  .ex--purple{ --ex-bg:var(--purple-bg); --ex-line:var(--purple-line); }
  .ex--yellow{ --ex-bg:var(--yellow-bg); --ex-line:var(--yellow-line); }
  .ex-price{ display:block; color:#000000; }
  .ex-detail{ display:grid; gap:12px; align-content:start; }
  .ex-dh{ margin:0; color:#000000; }
  .ex-copy{ margin:0; color:#000000; text-wrap:pretty; max-width:52ch; }

  /* ---- project pricing: the two-cell block, left-aligned ---- */
  /* A grid item is blockified and STRETCHES, so the link's box grew to fill the
     cell and its border-bottom — the underline — sank to the bottom of that box,
     a couple of lines under its own text. Flex column instead: the link keeps
     its own height, and margin-top:auto drops it to the foot of the cell, which
     also lands both cells' links on the same line. */
  .opt-ways--start .opt-way{ display:flex; flex-direction:column; align-items:flex-start; text-align:left; }
  .opt-ways--start .opt-way .explore-link{ margin-top:auto; align-self:flex-start; }
  .pp-lines{ list-style:none; margin:0; padding:0; display:grid; gap:12px; width:100%; }
  .pp-lines li{ display:grid; gap:2px; }
  .pp-what{ color:#000000; }
  .pp-price{ color:#000000; }

  /* ================= /how-it-works =================
     Layout only again. The page's spine is the SAME dark .hiw timeline and the
     SAME .grt guarantee box the home page uses — reused wholesale, not restyled,
     so the two pages cannot tell different stories about the 90 days. */

  /* ---- the field-service lens: the five stages ---- */
  .lens{ padding:0 0 clamp(56px,8vh,88px); background:#ffffff; }
  .lens-inner{ max-width:1240px; margin:0 auto; padding:0 clamp(20px,4vw,44px); text-align:center;
               display:flex; flex-direction:column; align-items:center; }
  .lens h2{ margin:0 auto clamp(18px,2.4vh,28px); color:#000000; text-wrap:balance; max-width:26ch; }
  .lens-lede{ margin:0 auto; max-width:62ch; color:#000000; text-wrap:pretty; }
  /* No rules round the tiles: each one draws its own edge, and a ruled band on
     top of five outlined cards frames the same thing twice. */
  .lens-rail{ padding:clamp(34px,4.5vh,58px) clamp(20px,4vw,44px) 0; }

  /* ---- quote -> profit: five chevron tiles, and the sequence device ----
     Five across. Each stage is a question, not a paragraph, so the columns can
     be narrow — but five columns of 43ch is not a thing below 1240, which is
     why they go to two and then one.

     THE SHAPE. Each tile points into the next: a notch on the left, a point on
     the right, cut with clip-path. clip-path clips a border too, so the edge is
     drawn as a 1px --line-strong ground with the fill inset 1px on ::before and
     the same shape — an outline that follows the chevron instead of a rectangle
     round it. The first tile has no notch; nothing feeds it.

     THE MOTION. One tile at a time: its fill goes --sage, its text goes #FFF,
     and a WHITE bar wipes across the top in the direction of travel. When the
     wipe finishes the tile drops back to white and the next one lights. Five
     slots of 2.6s, 13s a lap. The wipe is scaleX + opacity; the fill and the
     ink are paint-only, the same class of exception as .tl-draw's dashoffset
     and the trust bar's colour-mix. Nothing here moves a box. */
  .stage-list{ margin:0 auto; padding:0; list-style:none; display:grid; grid-template-columns:repeat(5,1fr);
               max-width:1240px; gap:4px; }
  .stage{ position:relative; display:grid; grid-template-rows:auto auto 1fr; gap:12px; justify-items:start;
          padding:clamp(26px,2.6vw,36px) clamp(26px,2.4vw,34px);
          background:var(--line-strong); color:#000000;
          clip-path:polygon(0 0, calc(100% - 18px) 0, 100% 50%, calc(100% - 18px) 100%, 0 100%, 18px 50%);
          animation:st-ink 16s linear infinite; }
  .stage:first-child{ clip-path:polygon(0 0, calc(100% - 18px) 0, 100% 50%, calc(100% - 18px) 100%, 0 100%); }
  .stage::before{ content:''; position:absolute; inset:1px; background:#ffffff; z-index:0;
                  clip-path:inherit; animation:st-fill 16s linear infinite; }
  .stage > *{ position:relative; z-index:1; }
  .stage-name, .stage-q{ color:inherit; }
  .stage-q{ text-wrap:pretty; }
  .st-bar{ position:absolute; left:1px; right:1px; top:1px; height:6px; z-index:1;
           background:var(--sage); overflow:hidden; }
  .st-bar i{ position:absolute; inset:0; background:#ffffff;
             transform:scaleX(0); transform-origin:left center;
             animation:st-wipe 16s linear infinite; }
  /* ONE delay per tile, carried on a custom property so it inherits: the tile,
     its ::before fill, its wipe and its two text nodes all read the same value
     and cannot drift apart. */
  .stage:nth-child(2){ --st-delay:3.2s; }
  .stage:nth-child(3){ --st-delay:6.4s; }
  .stage:nth-child(4){ --st-delay:9.6s; }
  .stage:nth-child(5){ --st-delay:12.8s; }
  /* the text blinks out, changes colour while it is invisible, and blinks back
     in — 0.16s out, 0.24s in. Fading the COLOUR would run black through grey,
     which §3 forbids; fading the opacity says the same thing and stays legal.
     This shorthand has to sit ABOVE the shared delay rule: `animation` resets
     animation-delay to 0, which had all five tiles blinking in unison. */
  .stage-name, .stage-q{ animation:st-ink-fade 16s linear infinite; }
  .stage, .stage::before, .st-bar i, .stage-name, .stage-q{ animation-delay:var(--st-delay,0s); }
  /* The fill EASES in and out over ~0.3s rather than flipping. The ink cannot
     ease with it — black interpolating to white passes through grey, and §3
     allows no grey text — so it switches once at each end of the fade, which
     leaves ~0.15s of black-on-part-sage going in and white-on-part-white coming
     out. Short fades keep both slips under a fifth of a second; a longer fade
     would put white text on a half-mixed ground for long enough to read. */
  @keyframes st-fill{
    0%     { background:#ffffff; animation-timing-function:cubic-bezier(.4,0,.2,1); }
    1%     { background:var(--sage); }
    19%    { background:var(--sage); animation-timing-function:cubic-bezier(.4,0,.2,1); }
    20.2%  { background:#ffffff; }
    100%   { background:#ffffff; }
  }
  @keyframes st-ink{
    0%     { color:#000000; }
    0.69%  { color:#000000; }
    0.7%   { color:#ffffff; }   /* switched while the text is at opacity 0 */
    19.49% { color:#ffffff; }
    19.5%  { color:#000000; }   /* likewise on the way out */
    100%   { color:#000000; }
  }
  /* 0.05s out, 0.1s in, and the text is only gone for the 0.22s the fill takes
     to change under it — short enough to read as the colour arriving with the
     tile rather than as a blink. */
  @keyframes st-ink-fade{
    0%     { opacity:1; animation-timing-function:cubic-bezier(.4,0,1,1); }
    0.3%   { opacity:0; }
    1.1%   { opacity:0; animation-timing-function:cubic-bezier(0,0,.2,1); }
    1.7%   { opacity:1; }
    18.8%  { opacity:1; animation-timing-function:cubic-bezier(.4,0,1,1); }
    19.1%  { opacity:0; }
    19.9%  { opacity:0; animation-timing-function:cubic-bezier(0,0,.2,1); }
    20.5%  { opacity:1; }
    100%   { opacity:1; }
  }
  /* the wipe waits for the fill, then crosses on an ease so it arrives as the
     tile hands over instead of finishing early and sitting there */
  @keyframes st-wipe{
    0%     { transform:scaleX(0); opacity:1; }
    1.7%   { transform:scaleX(0); opacity:1; animation-timing-function:cubic-bezier(.33,0,.2,1); }
    19%    { transform:scaleX(1); opacity:1; }
    20.2%  { transform:scaleX(1); opacity:0; }
    20.21% { transform:scaleX(0); opacity:0; }
    100%   { transform:scaleX(0); opacity:0; }
  }

  /* ================= how it works =================
     The one dark section on the site. Two rules in DESIGN.md give way here and
     both are recorded as amendments there: every glyph is no longer #000 (type
     inverts to white on the dark ground), and this h2 is Work Sans rather than
     M PLUS. Ground is #14171A — near-black, deliberately not #000, which stays
     reserved for type.

     The 90-day line hands off on white; the dark opens straight on the cue, no
     rule between them. */
  .handoff{ padding:clamp(56px,8vh,96px) clamp(20px,4vw,44px); background:#ffffff; }
  /* no max-width and no text-wrap:balance: the string fits one line down to
     ~1000px and both were forcing three cramped lines out of it */
  /* Authored line breaks in a heading. Three headers use this now, so it is one
     rule rather than three: the spans stack above 900 and go inline below it,
     where the copy re-wraps to the column. **The space between the spans in the
     markup is load-bearing** — inline, it is the only thing keeping the two
     halves apart. A heading using .l should not also carry text-wrap:balance or
     a max-width; the breaks are the point. */
  .l{ display:block; }
  .handoff h2{ max-width:none; margin:0 auto; color:#000000; }

  .hiw{ --on:#ffffff; background:var(--dark-ink); color:var(--on);
        padding:clamp(72px,10vh,124px) clamp(20px,4vw,44px); }
  .hiw-inner{ max-width:1240px; margin:0 auto; }
  .hiw-cue{ display:block; text-align:center; color:var(--on); }
  .hiw h2{ max-width:none; margin:18px auto clamp(52px,7vh,86px); color:var(--on); }
  /* the break is authored, not left to the wrap. Below 900 they go inline and
     the copy re-wraps — the space between the spans in the markup is what keeps
     "field" and "to" apart there, so do not remove it. */


  /* The gutter is the snake's amplitude: a left-hand stop's node sits on the
     gutter's LEFT edge and a right-hand stop's on its RIGHT edge, so the path
     swings the full gutter width. Nodes on the centre line would give a
     straight spine with alternating cards, which is not a snake.

     ol for the sequence, markers off: auto-numbering renders the exact
     "1. 2. 3." that AI Slop Tells bans, and the month pills carry the order. */
  .tl{ position:relative; display:grid; grid-template-columns:1fr clamp(80px,11vw,170px) 1fr;
       row-gap:clamp(52px,8vh,104px); margin:0; padding:0; list-style:none; }
  .tl-svg{ position:absolute; inset:0; width:100%; height:100%; pointer-events:none; overflow:visible; }
  .tl-track{ fill:none; stroke:rgba(255,255,255,.2); stroke-width:2; stroke-linecap:round; }
  .tl-draw{ fill:none; stroke:var(--on); stroke-width:2; stroke-linecap:round; }

  /* rows are pinned: auto-placement drops stop 2 into the free right-hand cell
     of row 1, which puts all three nodes on two rows and collapses the path */
  .tl-stop{ position:relative; z-index:1; }
  .tl-stop:nth-child(1){ grid-row:1; }
  .tl-stop:nth-child(2){ grid-row:2; }
  .tl-stop:nth-child(3){ grid-row:3; }
  .tl-stop[data-side="l"]{ grid-column:1; }
  .tl-stop[data-side="r"]{ grid-column:3; }
  .tl-node{ position:absolute; top:26px; width:11px; height:11px; border-radius:50%;
            background:var(--dark-ink); border:2px solid var(--on); z-index:2;
            transform:scale(.55); opacity:.45;
            transition:transform .45s cubic-bezier(.16,.9,.22,1), opacity .45s linear; }
  .tl-stop[data-side="l"] .tl-node{ right:-5.5px; }
  .tl-stop[data-side="r"] .tl-node{ left:-5.5px; }
  .tl-stop.is-on .tl-node{ transform:none; opacity:1; }

  .tl-card{ opacity:.28; transform:translateY(14px);
            transition:opacity .6s cubic-bezier(.4,0,.2,1), transform .6s cubic-bezier(.4,0,.2,1); }
  .tl-stop.is-on .tl-card{ opacity:1; transform:none; }
  /* the node sits on the card's inner edge, so without this the rail runs down
     the first character of every line */
  .tl-stop[data-side="l"] .tl-card{ padding-right:26px; }
  .tl-stop[data-side="r"] .tl-card{ padding-left:26px; }

  /* pill, then the icon on its own line beneath it, then the title */
  .tl-head{ display:flex; flex-direction:column; align-items:flex-start; gap:14px; margin-bottom:18px; }
  .tl-pill{ display:inline-block; white-space:nowrap; border-radius:999px; padding:9px 17px;
            font:500 calc(var(--ui) * 1.1)/1 'Work Sans',sans-serif; color:#000000; }
  .tl-pill--green{ background:var(--green-bg); border:1px solid var(--green-line); }
  .tl-pill--blue{ background:var(--blue-bg); border:1px solid var(--blue-line); }
  .tl-pill--yellow{ background:var(--yellow-bg); border:1px solid var(--yellow-line); }
  .tl-icon{ display:block; color:var(--on); }
  .tl-icon svg{ width:36px; height:36px; display:block; }
  .tl-title{ margin:0 0 12px; color:var(--on);
             font:600 clamp(19px,.7vw + .9vh,25px)/1.25 'Work Sans',sans-serif; letter-spacing:-.012em; text-wrap:balance; }
  .tl-copy{ margin:0; color:var(--on); font:400 calc(var(--ui) * 1.1)/1.6 'Work Sans',sans-serif; text-wrap:pretty; max-width:46ch; }


  /* ================= pricing =================
     A box, like the guarantee, but split into two EQUAL cells rather than the
     guarantee's 1fr/2fr: these two are parallel offers, where the guarantee is
     one claim against its terms. Same edges as every other box on the page —
     --line-strong across, --line down the sides, radius 0.

     Each cell stacks icon, title, copy, action. The actions bottom-align
     because the cells stretch and each action takes margin-top:auto, the same
     device the who-we-serve column uses. */
  .prc{ padding:clamp(72px,10vh,124px) 0; background:#ffffff; }
  .prc-head{ max-width:1240px; margin:0 auto; padding:0 clamp(20px,4vw,44px); }
  .prc-rail{ border-top:1px solid var(--line-strong); border-bottom:1px solid var(--line-strong); padding:0 clamp(20px,4vw,44px); }
  /* no max-width, no text-wrap:balance — the .l spans author the two lines */
  .prc h2{ margin:0 auto clamp(44px,6.5vh,72px); color:#000000; }
  /* subgrid, same device as .svc-list: icon / name / price / copy / list /
     action each get one shared row across both cells, so a shorter intro
     sentence on one side can't pull its bullets up above the other's. */
  .prc-box{ max-width:1240px; margin:0 auto; display:grid; grid-template-columns:1fr 1fr;
            grid-template-rows:auto auto auto auto 1fr auto; align-items:stretch;
            border-left:1px solid var(--line); border-right:1px solid var(--line); }
  .prc-cell{ display:grid; grid-row:span 6; grid-template-rows:subgrid;
             justify-items:start; align-content:start;
             padding:clamp(30px,3vw,42px) clamp(24px,2.4vw,36px); }
  .prc-cell + .prc-cell{ border-left:1px solid var(--line); }
  /* blue for the ongoing offer, sage for the one-off work — the same device as
     the services row, where colour lives in the icon and not in a filled box */
  /* icon takes the services row's own square — 46px, same margin-bottom as
     .svc-icon — so the two rows read as one family of tiles. */
  .prc-icon{ display:block; margin-bottom:6px; color:var(--sage); }
  .prc-cell:nth-child(1) .prc-icon{ color:var(--ink-blue); }
  .prc-icon svg{ width:46px; height:46px; display:block; }
  /* label takes .svc-name's D-group style (folded into that shared rule
     above); only margin and colour stay local. */
  .prc-name{ display:block; margin:0 0 10px; color:#000000; }
  /* price/scope line takes the B-group size .prc-name used to carry — the
     bolder step, now freed up for the number instead of the label. */
  .prc-price{ margin:0 0 14px; color:#000000;
              font:600 clamp(19px,.7vw + .9vh,25px)/1.25 'Work Sans',sans-serif;
              letter-spacing:-.012em; text-wrap:balance; }
  /* 1.1x, not the guarantee's 1.4x: that size was chosen for a column two
     squares wide, and half a box is 550px, where it set a 36-character line —
     under the floor. 1.1x is the signal text's size, already in the file. */
  .prc-copy{ margin:0 0 18px; color:#000000;
             font:400 calc(var(--ui) * 1.1)/1.6 'Work Sans',sans-serif; text-wrap:pretty; }
  .prc-list{ margin:0 0 clamp(26px,3vh,34px); padding-left:1.1em; color:#000000;
             font:400 calc(var(--ui) * 1.1)/1.6 'Work Sans',sans-serif; }
  .prc-list li + li{ margin-top:6px; }
  /* auto, with the clearance above paid by the list's margin-bottom — the two
     actions then sit on the same line whichever cell runs longer */
  .prc-cell .btn-solid, .prc-cell .explore-link{ margin-top:auto; }

  /* ================= closing CTA =================
     The second and last non-white ground, and the one that retires "--sage,
     filled button only, never a large area". White on sage measures 6.16:1 and
     passes AA; black on it is 3.41:1 and does not, which is why type inverts
     here exactly as it does on the dark block.

     Ground change on both sides, so this section pays its own top padding —
     the one-padding-per-gap rule is for two sections sharing a ground. */
  .cta{ --on:#ffffff; background:var(--sage); color:var(--on);
        padding:clamp(72px,10vh,124px) clamp(20px,4vw,44px); }
  .cta-inner{ max-width:1240px; margin:0 auto; text-align:center; }
  /* the h2 and .cta-sub already centre themselves; the inner pages' link is
     inline-flex, so it needs the block to be centred for it to follow */
  .cta h2{ margin:0 auto; max-width:22ch; color:var(--on); text-wrap:balance; }
  .cta-sub{ margin:18px auto clamp(40px,5.5vh,64px); max-width:58ch; color:var(--on);
            text-align:center; text-wrap:pretty; }

  /* The scheduler is Google's page in an iframe, so nothing inside it can be
     styled from here. The wrapper does the work: white ground so the embed's
     own background never shows a seam, 16px to match the portrait — the site's
     other radius for an embedded object rather than a typographic box — and
     overflow:hidden, without which the iframe's square corners punch straight
     through the rounding. Runs the full 1240 measure, so it lines up with the
     services row and every box above it. */
  /* a page whose closing line needs no sub still needs the sub's gap under the
     head — the value is .cta-sub's bottom margin, not a new one */
  .cta h2 + .cta-embed{ margin-top:clamp(40px,5.5vh,64px); }
  .cta-embed{ margin:0 auto; background:#ffffff; border-radius:16px; overflow:hidden; }
  /* Calendly injects its own iframe into .calendly-inline-widget and sizes it
     to the container, so the height lives on the container. */
  .cta-embed .calendly-inline-widget{ height:700px; }
  .cta-embed iframe{ display:block; border:0; }

  /* ================= FAQ =================
     Four tiles that do NOT touch. Every other box on the page shares its edges
     with its neighbour — services cells, the guarantee halves, the pricing
     halves — so the gap here is the whole point: four separate answers, not one
     object split four ways. Each tile is therefore closed on all four sides at
     the outer-edge weight (--line-strong), where a shared-edge cell would use
     --line down the join.

     Tiles stretch to their row so the pair in each row reads as a set. The last
     answer is about two and a half times the others, so its row runs taller —
     that trailing space is the cost of equal tiles and is preferred to ragged
     bottoms in a two-column grid.

     No padding-top: meet-Joaquin is white too and its padding-bottom is the gap. */
  .faq{ padding:0 clamp(20px,4vw,44px) clamp(72px,10vh,124px); background:#ffffff; }
  .faq-inner{ max-width:1240px; margin:0 auto; }
  .faq h2{ margin:0 auto clamp(44px,6.5vh,72px); color:#000000; }
  .faq-list{ margin:0; padding:0; list-style:none; display:grid; grid-template-columns:1fr 1fr;
             gap:clamp(18px,2vw,28px); align-items:stretch; }
  .faq-item{ border:1px solid var(--line-strong);
             padding:clamp(28px,2.8vw,38px) clamp(24px,2.4vw,34px); }
  .faq-q{ margin:0 0 12px; color:#000000;
          font:600 clamp(19px,.7vw + .9vh,25px)/1.3 'Work Sans',sans-serif;
          letter-spacing:-.012em; text-wrap:balance; }
  .faq-a{ margin:0; color:#000000;
          font:400 calc(var(--ui) * 1.1)/1.6 'Work Sans',sans-serif; text-wrap:pretty; }

  /* ================= meet Joaquin =================
     Back to white, and no centred head — this one opens on the person, so the
     heading sits left in the copy column rather than over the whole section.
     Full padding top and bottom: the one-padding-per-gap rule is for two
     sections sharing a ground, and the dark block above owns its own. */
  /* no padding-top: pricing is white too, and its padding-bottom is already the
     whole gap. (It kept a top padding while the dark block was its neighbour —
     a ground change means both sides pay.) */
  .mtg{ padding:0 clamp(20px,4vw,44px) clamp(72px,10vh,124px); background:#ffffff; }
  /* The photo column is sized to the photo, not to half the section: at half
     the measure the portrait ran ~600px against ~290px of copy and read as
     twice its weight. 360px caps it a quarter down from that.

     Both columns are content-sized and the pair is centred with
     justify-content, rather than the copy column taking 1fr. As 1fr the copy
     box ran to the right edge of the measure while the text stopped at its own
     cap ~200px short, so the whole section hung to the left with dead space on
     the right. Capping the copy column and centring the pair puts the weight
     in the middle without touching the left alignment of the text itself. */
  .mtg-inner{ max-width:1240px; margin:0 auto; display:grid;
              grid-template-columns:clamp(250px,26vw,360px) minmax(0,680px);
              justify-content:center;
              gap:clamp(40px,5vw,84px); align-items:center; }
  .mtg-copy{ display:flex; flex-direction:column; align-items:flex-start; }
  /* the one head that is not centred — this section opens on the person */
  .mtg-copy h2{ margin:0; color:#000000; text-align:left; text-wrap:balance; }
  /* lighter than the head, and 400 rather than 300 on purpose: 300 exists for
     the disqualifier alone, and a second use would mean that amendment was
     wrong. Against a 600 head, 400 is already the lighter weight. */
  /* no max-width: the column caps the measure now, and a second cap inside it
     would silently shorten the line again. The column is 630 rather than 560
     because C1 is 1.6x: at 560 this bio set 40.6 characters, under the floor,
     and 630 only fixed it below 1240. 680 holds 6 lines at 47.3 characters at
     1440, 1240 and 1100 alike, and the gutters stay symmetric (64/64, 44/44,
     0/0). Wider inverts it — 720 drops to 5 lines at 1240 but not at 1440. */
  .mtg-copy p{ margin:22px 0 0; color:#000000; text-wrap:pretty; }
  .mtg-copy .explore-link{ margin-top:clamp(26px,3vh,36px); }
  /* the hero's chips centre themselves; in a left-set copy column they must not */
  .mtg-copy .chips{ justify-content:flex-start; margin-top:clamp(20px,2.6vh,30px); }
  /* Three paragraphs of bio at C1 is a wall of 24.5px type; the home page's
     version is one paragraph and stays C1. --long steps the block down to C2,
     which is what a bio is: explanation, not the section's thesis. Written with
     the parent class for the same specificity reason as the byline below. */
  .mtg-copy--long p{ font:400 calc(var(--ui) * 1.1)/1.6 'Work Sans',sans-serif; }
  /* .mtg-copy p is C1 at (0,1,1) and beats a bare class, so the byline pair is
     written the same way .hero-center .phero-lede is — the group wins, the
     paragraph rule does not. */
  .mtg-copy .mtg-name{ margin:clamp(20px,2.6vh,30px) 0 0; color:#000000; }
  .mtg-copy .mtg-role{ margin:6px 0 0; color:#000000; }

  /* Capped and pushed right rather than filling the column: at the full column
     width the portrait runs ~700px tall and towers over three short blocks of
     copy. 16px is the radius that reads as deliberately rounded at this size —
     8px on a 480px image is invisible. Both are in the closed set. */
  .mtg-shot{ margin:0; width:100%; }
  .mtg-shot img{ display:block; width:100%; height:auto; aspect-ratio:4 / 5;
                 object-fit:cover; object-position:50% 26%; border-radius:16px; }


  /* ================= footer =================
     Same ground as the page and separated by a hairline, exactly as the nav is
     at the other end — one line, no slab of colour. The mark is the nav's own
     inline SVG so it inherits currentColor and never needs a second asset. */
  .ft{ flex:none; background:#ffffff; border-top:1px solid var(--line);
       padding:clamp(48px,7vh,72px) clamp(20px,4vw,44px) clamp(28px,3vh,36px); }
  .ft-inner{ max-width:1240px; margin:0 auto; }
  .ft-top{ display:grid; grid-template-columns:auto 1fr;
           gap:clamp(28px,3vw,60px); align-items:start; }
  /* Three columns since 2026-09-03: the fourth was Resources, and both of its
     links were href="#". A column of destinations that do not exist is worse
     than a narrower footer. Español moved into the Avanza column. */
  .ft-cols{ display:grid; grid-template-columns:repeat(3,1fr); gap:clamp(24px,2.6vw,44px); }
  .ft-mark{ display:block; color:#000000; }
  .ft-mark svg{ display:block; height:20px; width:auto; }
  .ft-h{ display:block; margin-bottom:16px; color:#000000; }
  .ft-col ul{ margin:0; padding:0; list-style:none; display:grid; gap:11px; }
  .ft-col a{ color:#000000; font:500 var(--ui)/1.35 'Work Sans',sans-serif;
             transition:color .18s ease; }
  .ft-col a:hover{ color:var(--sage); }

  .ft-bottom{ display:flex; align-items:center; justify-content:space-between; gap:20px 32px;
              flex-wrap:wrap; margin-top:clamp(40px,5vh,64px); padding-top:clamp(20px,2.4vh,26px);
              border-top:1px solid var(--line); }
  /* dot separators shared with the trust bar and the type examples — the li
     rules live with .trust-list, this is only the container. */
  .ft-id{ margin:0; padding:0; list-style:none; display:flex; align-items:center; gap:30px; flex-wrap:wrap; }
  .ft-legal{ margin:0; color:#000000; font:500 var(--ui)/1 'Work Sans',sans-serif; }
  .ft-legal a{ transition:color .18s ease; }
  .ft-legal a:hover{ color:var(--sage); }

  /* Five stage columns hold to 1240 and no further: below that each is under
     20 characters, which is a column of single words. Two, then one. */
  /* ---- the client thread ----
     Sage bubble = us: the one filled colour, white ink, 6.16:1. Hairline white
     bubble = the client, so no third ground is spent. Copy is group C2. Radii
     16px + 5px and the .pill--b shadow, all already in the set. */
  .thr{ list-style:none; margin:0 auto; padding:0; display:flex; flex-direction:column; gap:7px; max-width:520px; }
  .thr-msg{ display:flex; position:relative; }
  .thr-them{ justify-content:flex-start; }
  .thr-me{ justify-content:flex-end; }
  .thr-b{ margin:0; max-width:80%; padding:12px 18px; border-radius:16px;
          font:400 calc(var(--ui) * 1.1)/1.45 'Work Sans',sans-serif;
          box-shadow:0 12px 24px -22px rgba(0,0,0,.4); }
  .thr-them .thr-b{ background:var(--panel); color:#000000; border:1px solid var(--line-strong);
                    border-bottom-left-radius:5px; transform-origin:bottom left; }
  .thr-me .thr-b{ background:var(--sage); color:#ffffff; border:1px solid var(--sage);
                  border-bottom-right-radius:5px; transform-origin:bottom right; }
  /* The indicator sits INSIDE the message it precedes, absolutely, pinned to
     that bubble's bottom corner: in the flow it added a row's height on every
     beat and walked the whole page up and down. currentColor makes the dots
     #000 in a client bubble and #fff in a sage one, so no fifth grey. */
  .thr-dots{ position:absolute; bottom:0; display:flex; align-items:center; gap:5px;
             padding:16px 18px; border-radius:16px; box-shadow:0 12px 24px -22px rgba(0,0,0,.4); }
  .thr-them .thr-dots{ left:0; background:var(--panel); color:#000000;
                       border:1px solid var(--line-strong); border-bottom-left-radius:5px; }
  .thr-me .thr-dots{ right:0; background:var(--sage); color:#ffffff;
                     border:1px solid var(--sage); border-bottom-right-radius:5px; }
  .thr-dots i{ width:7px; height:7px; border-radius:50%; background:currentColor; opacity:.3;
               animation:thrDot 1.2s ease-in-out infinite; }
  .thr-dots i:nth-child(2){ animation-delay:.16s; }
  .thr-dots i:nth-child(3){ animation-delay:.32s; }
  @keyframes thrDot{
    0%,60%,100%{ opacity:.3; transform:none; }
    30%        { opacity:1;  transform:translateY(-2px); }
  }
  /* Resting state is every message VISIBLE. .is-armed is added by the script and
     is the only thing that hides anything, so the thread reads in full with no JS. */
  .thr.is-armed > .thr-msg{ opacity:0; }
  .thr.is-armed > .thr-msg.is-in{ animation:thrIn .5s cubic-bezier(.16,.9,.22,1) both; }
  @keyframes thrIn{
    from{ opacity:0; transform:scale(.92) translateY(10px); }
    to  { opacity:1; transform:none; }
  }


  /* ================= legal pages =================
     Privacy and Terms. Long-form prose, so the section is the one place on the
     site where the reading column matters more than the 1240 measure: the copy
     caps at 64ch, the top of DESIGN.md's band, and the section keeps the shared
     page-hero padding pattern (no padding-top — .phero above is white and its
     padding-bottom is the gap).

     Nothing here chooses a size. The section heads are group B — the same step
     as .faq-q, which is what a numbered clause is: the name of one member of a
     repeating set, not a section statement. Body and list items are C2, the
     "last updated" stamp is D. Group A stays unused on these pages: at 53px an
     h2 every 120 words reads as fifteen page titles stacked. */
  .legal{ padding:0 clamp(20px,4vw,44px) clamp(72px,10vh,124px); background:#ffffff; }
  /* The ONE measure on these pages, written once on the wrapper and inherited
     by every child, rather than a 64ch cap repeated on the copy, the lists and
     anything added later. The wrapper carries C2's size so its `ch` is C2's
     `ch` — every text child restates its own size from its group rule, so the
     declaration here sizes nothing, it only makes the unit mean what it says.
     Centred: left-set prose against a 1240 container leaves half the page
     empty at 1440, and no other section on the site hangs left. */
  .legal-inner{ max-width:55ch; margin:0 auto; font-size:calc(var(--ui) * 1.1); }
  .legal-updated{ margin:0 0 clamp(30px,4vh,46px); color:#000000; }
  /* Left, not centred: group B carries no text-align of its own, and a centred
     clause head over a left-set paragraph is the tell that a marketing section
     head was reused for a document. */
  .legal h2{ margin:clamp(34px,4.4vh,52px) 0 12px; max-width:34ch; color:#000000; }
  .legal h2:first-of-type{ margin-top:0; }
  .legal-copy{ margin:0 0 14px; color:#000000; }
  .legal-copy:last-child{ margin-bottom:0; }
  /* Disc, like .why-qs. An enumeration inside a clause is the second place on
     the site where a marker carries meaning: it says these are separate items
     of one clause, not a sentence that happens to wrap. */
  .legal-list{ margin:0 0 14px; padding:0 0 0 1.15em; list-style:disc; }
  .legal-list li{ margin:0 0 8px; color:#000000; }
  .legal-list li:last-child{ margin-bottom:0; }
  /* 600, not the browser's 700 — DESIGN.md §1 allows three weights and bold
     is not one of them. */
  .legal-copy strong, .legal-list li strong{ font-weight:600; }
  .legal-copy a{ border-bottom:1px solid rgba(0,0,0,.35); transition:color .18s ease, border-color .18s ease; }
  .legal-copy a:hover{ color:var(--sage); border-bottom-color:var(--sage); }




  /* ================= the contact form =================
     The site's only real form. It carries visible labels, not placeholders —
     a placeholder disappears the moment someone types and is not a label (§6).
     Field borders and radius are the phone field's, at the one radius a
     rectangle uses; --ghost is still placeholders only and there are none.

     NO BACKEND YET. The submit is `method="post"` so the no-JS path cannot put
     a message in a URL, and app.js turns it into a pre-filled mail draft to
     info@ so the page is never a dead end. When a real endpoint exists, the
     action changes and the handler goes. */
  .form-sec{ padding:0 clamp(20px,4vw,44px) clamp(72px,10vh,124px); background:#ffffff; }
  /* .form-sec pays no top padding — it follows a .phero on /contact, and the
     hero's bottom padding is the gap. A ruled .band pays its padding INSIDE
     its own two rules, so nothing lands outside them and the head sits flush
     on the hairline. Same shape as the .hiw + section rule: the section that
     cannot pay from above pays it here, written against the sibling. */
  .band + .form-sec{ padding-top:clamp(72px,10vh,124px); }
  .form-inner{ max-width:640px; margin:0 auto; }
  .form-sec h2{ margin:0 auto clamp(30px,4vh,44px); color:#000000; text-align:center; text-wrap:balance; }
  /* /contact's head sits straight on its form and keeps the full gap. Where a
     sub follows, the head tightens to the band's head/lede gap and the SUB
     pays the gap down to the first field — one gap either way, never two. */
  .form-sec h2:has(+ .form-lede){ margin-bottom:clamp(14px,1.8vh,20px); }
  .form-lede{ margin:0 auto clamp(30px,4vh,44px); max-width:56ch; color:#000000; text-align:center; text-wrap:pretty; }
  .cform{ display:grid; gap:clamp(18px,2.4vh,24px); justify-items:stretch; }
  .cfield{ display:grid; gap:8px; }
  .cfield label{ color:#000000; font:500 var(--ui)/1.3 'Work Sans',sans-serif; }
  .cfield input, .cfield textarea, .cfield select{ width:100%; padding:13px 16px; border-radius:8px;
    border:1px solid var(--line-strong); background:var(--panel); color:var(--ink);
    font:400 calc(var(--ui) * 1.1)/1.5 'Work Sans',sans-serif; }
  .cfield textarea{ resize:vertical; min-height:150px; }
  .cfield input:focus-visible, .cfield textarea:focus-visible,
  .cfield select:focus-visible{ outline:2px solid var(--sage); outline-offset:1px; }
  /* A select's native chrome is the one control the UA paints for itself — its
     own border, its own radius, its own arrow — so it is the one field that
     cannot inherit the box by styling alone. `appearance:none` strips it and
     the nav's .caret draws the chevron, so no new glyph, no background image
     and no second arrow enter the set. The wrapper exists to position it. */
  .cfield select{ appearance:none; -webkit-appearance:none; padding-right:44px;
                  background:#ffffff; font:400 var(--ui)/1.3 'Work Sans',sans-serif; cursor:pointer; }
  .cselect{ position:relative; display:grid; }
  .cselect .caret{ position:absolute; right:18px; top:50%; margin-top:-4px; pointer-events:none; }
  /* the placeholder option reads as a placeholder until something is chosen */
  .cfield select:has(option[value=""]:checked){ color:var(--ghost); }
  .cform .btn-solid{ justify-self:start; }
  .cform-note{ margin:0; color:#000000; }
  /* Honeypot. Off-screen rather than display:none — a bot that skips hidden
     fields still fills this one, which is the entire point. */
  .hp{ position:absolute; left:-9999px; width:1px; height:1px; overflow:hidden; }
  .cform.is-sending .btn-solid, .lead-capture.is-sending button{ opacity:.6; pointer-events:none; }
  .cform-note.is-error, .lead-note.is-error{ color:#8a2018; }
  .lead-note{ margin:10px 0 0; font:400 var(--ui)/1.5 'Work Sans',sans-serif; color:#000000; }
  .cform-done{ display:grid; gap:10px; padding:clamp(20px,3vh,28px) 0; }
  .cform-done h3{ margin:0; font:600 clamp(19px, .7vw + .9vh, 25px)/1.25 'Work Sans',sans-serif; }
  .cform-done p{ margin:0; font:400 calc(var(--ui) * 1.1)/1.6 'Work Sans',sans-serif; }
  .cform-note a{ border-bottom:1px solid rgba(0,0,0,.35); transition:color .18s ease, border-color .18s ease; }
  .cform-note a:hover{ color:var(--sage); border-bottom-color:var(--sage); }

  /* ================= testimonials =================
     Two, and they are real. The card is the engagement card's box — 16px,
     --line-strong, no fill — because §3 says colour lives in the icon and never
     in a filled box: a tinted card would be the first filled panel on the site.
     What carries the colour is the quote glyph and the business capsule, one
     tint per card, which is the same pairing .ex-card uses.

     Grid rather than flex so the two cards match height whatever the quotes
     run to; the attribution is pushed to the bottom by the quote's 1fr row, so
     the two names sit on one line across both cards.

     No padding-top: the guarantee above is white and pays the gap. */
  .tstm{ padding:0 clamp(20px,4vw,44px) clamp(72px,10vh,124px); background:#ffffff; }
  .tstm-inner{ max-width:1240px; margin:0 auto; }
  .tstm h2{ margin:0 auto clamp(40px,5.5vh,60px); color:#000000; text-wrap:balance; }
  .tstm-list{ margin:0; padding:0; list-style:none; display:grid; grid-template-columns:1fr 1fr;
              gap:clamp(18px,2vw,28px); align-items:stretch; }
  .tstm-card{ display:grid; grid-template-rows:auto 1fr auto; gap:14px; justify-items:start;
              border:1px solid var(--line-strong); border-radius:16px;
              padding:clamp(28px,2.8vw,40px) clamp(24px,2.4vw,34px); }
  .tstm-icon{ display:block; }
  .tstm--green .tstm-icon{ color:var(--ink-green); }
  .tstm--blue .tstm-icon{ color:var(--ink-blue); }
  /* C2, not C1: at the section thesis size two quotes ran as long as the
     section above them. The browser's own blockquote margin still has to go or
     the card's gap is paid twice. */
  .tstm-quote{ color:#000000; text-wrap:pretty; }
  /* One line, name and business together — the capsule went with the size, and
     so did group D: tracked caps over a two-line attribution shouts louder than
     the quote above it. Group F, which is what a byline is. */
  .tstm-who{ margin:0; color:#000000; font:500 var(--ui)/1.4 'Work Sans',sans-serif; }

  /* ================= who we serve: the four business types =================
     THE RAIL PATTERN (§7.5) at 2x2 rather than 1x3. The section carries no
     horizontal padding so .types-rail's two --line-strong rules run edge to
     edge; .types-list stays on the 1240 measure and closes its own flanks with
     --line. Same construction as .svc and .why — a ruled block whose rules stop
     at 1240 is the bug.

     Four cells, so the join rules are positional rather than adjacent: the
     right-hand column takes the vertical, the second row takes the horizontal.
     `.type-item + .type-item` would put a left border on three of the four.

     Each item spans four subgrid rows — name / copy / examples / link — so all
     four cells align across the band no matter how many lines a name or a
     description takes. Without subgrid, a two-line name in one cell drags its
     neighbour's examples off the line they share.

     ICON / NAME / COPY / EXAMPLES / LINK — the services row's own order, and
     the icons take the services 46px square and all four inks in cell order:
     green, blue, ochre, purple. Purple was the guarantee's alone until now.
     Photography is still the open question here (see DESIGN-WHY §9); the
     examples list is what gives each cell its texture underneath the glyph. */
  .types{ padding:0 0 clamp(72px,10vh,124px); background:#ffffff; }
  .types-head{ max-width:1240px; margin:0 auto clamp(44px,6.5vh,72px); padding:0 clamp(20px,4vw,44px); text-align:center; }
  .types h2{ margin:0 auto; color:#000000; text-wrap:balance; max-width:26ch; }
  .types-rail{ border-top:1px solid var(--line-strong); border-bottom:1px solid var(--line-strong); padding:0 clamp(20px,4vw,44px); }
  .types-list{ margin:0 auto; padding:0; list-style:none; display:grid; grid-template-columns:repeat(2,1fr);
               max-width:1240px; border-left:1px solid var(--line); border-right:1px solid var(--line); }
  .type-item{ display:grid; grid-row:span 5; grid-template-rows:subgrid; gap:14px;
              justify-items:start; align-content:start;
              padding:clamp(30px,3vw,42px) clamp(24px,2.4vw,36px); }
  .type-item:nth-child(even){ border-left:1px solid var(--line); }
  .type-item:nth-child(n+3){ border-top:1px solid var(--line); }
  .type-icon{ display:block; margin-bottom:6px; }
  .type-item:nth-child(1) .type-icon{ color:var(--ink-green); }
  .type-item:nth-child(2) .type-icon{ color:var(--ink-blue); }
  .type-item:nth-child(3) .type-icon{ color:var(--ink-ochre); }
  .type-item:nth-child(4) .type-icon{ color:var(--ink-purple); }
  .type-name{ margin:0; color:#000000; }
  /* Wrapping dot list — the footer legal line's separator, not the trust bar's.
     The middot lives in the PRECEDING item's ::after behind a non-breaking
     space, so it can never begin a line; the break opportunity after it is what
     starts the next row on a word. Inline flow rather than flex for the same
     reason: a flex gap gives no break point the dot can travel with.
     Line-height is local — group F is set at /1 for lists that stay on one row. */
  .type-eg, .roster-eg{ margin:0; padding:0; list-style:none; }
  /* the wrapping-dot construction, shared. Typography is NOT shared: .type-eg is
     group F, .roster-eg is group B — see .roster. */
  .type-eg li, .roster-eg li{ display:inline; line-height:1.6; white-space:nowrap; }
  .type-eg li:not(:last-child)::after, .roster-eg li:not(:last-child)::after{
    content:'\00a0\00b7'; margin-right:.42em; color:rgba(0,0,0,.4); }
  .type-item .explore-link{ align-self:end; padding-top:14px; }

  /* ================= the shared questions =================
     The hero's question pills, standing still. On the home page they drift and
     rotate because they are decoration behind a claim; here they ARE the
     content, so they take the same capsule and the same four tints and no
     motion at all — §5 allows one infinite loop and it belongs to the
     progression rail. Tints run green / blue / yellow / purple / yellow / green
     so no two match as neighbours or as a column in the 3-up wrap.

     No padding-top: .types above is white and its padding-bottom is the gap. */
  .probs{ padding:0 clamp(20px,4vw,44px) clamp(72px,10vh,124px); background:#ffffff; }
  /* ---- the roster: one dot list, centred, closing a vertical page ----
     The type examples again (see .type-eg), this time as a section of their own.
     Centred because it is a list of names with nothing to align to, and capped
     at the band so it never sets a line the eye has to track back across. */
  .roster{ padding:0 clamp(20px,4vw,44px) clamp(72px,10vh,124px); background:#ffffff; }
  .roster-inner{ max-width:900px; margin:0 auto; text-align:center; }
  .roster h2{ margin:0 auto clamp(26px,3.4vh,38px); color:#000000; text-wrap:balance; max-width:26ch; }
  /* GROUP B, not F. On the parent page the examples sit under a name that is
     already B, so they take the interface step to stay out of its way; here the
     names ARE the section and the nearest thing above them is the h2, so they
     take the item-name step. Different job, different group — which is why this
     is `.roster-eg` and not `.type-eg` in a new context. Weight 600 is B's, and
     the dot's low alpha is what keeps a wall of them from reading as shouting. */
  .roster-eg li{ text-wrap:normal; letter-spacing:0; }
  .probs-inner{ max-width:1240px; margin:0 auto; text-align:center; }
  .probs h2{ margin:0 auto clamp(18px,2.4vh,28px); color:#000000; text-wrap:balance; max-width:26ch; }
  .probs-lede{ margin:0 auto; color:#000000; text-wrap:balance; max-width:54ch; }
  .probs-pills{ list-style:none; margin:clamp(36px,5vh,56px) auto 0; padding:0; max-width:1000px;
                display:flex; flex-wrap:wrap; justify-content:center; gap:14px; }
  .probs-close{ margin:clamp(30px,4vh,44px) auto 0; color:#000000; max-width:54ch; }
  .probs .explore-link{ margin-top:clamp(20px,2.6vh,30px); }

  @media (max-width:1240px){
    /* four light cells go to two before they go to one */
    /* one column: the picture follows the pair it belongs to, on both rows, so
       the flip that distributes the desktop page has nothing to distribute */
    .gets-row{ grid-template-columns:1fr; gap:clamp(26px,4vh,40px); }
    .gets-list{ grid-template-columns:repeat(2,1fr); }
    /* six project cells do the same */
    .projs-list{ grid-template-columns:repeat(2,1fr); }
    .proj:not(:nth-child(3n+1)){ border-left:1px solid var(--line); }
    .proj:nth-child(odd){ border-left:none; }
    .proj:nth-child(n+3){ border-top:1px solid var(--line); }
    .get:nth-child(odd){ border-left:none; }
    .get:nth-child(n+3){ border-top:1px solid var(--line); }
    .stage-list{ grid-template-columns:repeat(2,1fr); }
  }

  @media (max-width:560px){ .thr-b{ max-width:88%; } }

  @media (max-width:900px){
    /* narrow hero: the clearing must out-run the copy, not the box */
    .phero::before{ --clear:88% 44%; }

    /* the dot separators are absolutely positioned; once the row wraps they
       orphan onto the next line, so the gap does the separating instead */
    .trust-list{ gap:8px 26px; }
    .trust-list li + li::before{ display:none; }
    .svc-list{ grid-template-columns:1fr; }
    .svc-item + .svc-item{ border-left:none; border-top:1px solid var(--line); }
    .grt-box{ grid-template-columns:1fr; }
    .grt-terms{ border-left:none; border-top:1px solid var(--line); }
    /* 1.4x --ui sets a 57ch measure across two squares; in a stacked 300px
       column it sets a 31ch one, which is below the floor. The terms drop back
       to the body size here, where they measure the same 43ch as .svc-desc. */
    /* stacked full-width, a chevron points at the tile beside it and there
       is none — the shape goes and the sage bar carries the sequence alone */
    .stage-list{ grid-template-columns:1fr; }
    .stage, .stage:first-child{ clip-path:none; }
    .why-list{ grid-template-columns:1fr; }
    .why-item + .why-item{ border-left:none; border-top:1px solid var(--line); }
    /* one column: the vertical join goes, and every cell after the first takes
       the horizontal one — the nth-child rules above are for the 2x2 only. */
    .tstm-list{ grid-template-columns:1fr; }
    .types-list{ grid-template-columns:1fr; }
    .type-item:nth-child(even){ border-left:none; }
    .type-item + .type-item{ border-top:1px solid var(--line); }
    /* the 2x2 stacks like every other tile block; at 390 two columns are 174px,
       which is under the measure floor for a paragraph */
    .sig-list{ grid-template-columns:1fr; }
    .sig + .sig{ border-left:none; border-top:1px solid var(--line); }
    .lever-list{ grid-template-columns:1fr; }
    .lever + .lever{ border-left:none; border-top:1px solid var(--line); }
    /* stacked, the fact sheet leads on every row. min-width:0 on the children
       and on the stat cells or the widest card's MIN-CONTENT (the price beside
       "Engagement monthly") sets the column and pushes the page 5px sideways. */
    .ex, .ex:nth-child(even){ grid-template-columns:minmax(0,1fr); }
    .ex:nth-child(even) .ex-card{ order:0; }
    .ex-card, .ex-detail{ min-width:0; }
    .ex-stats{ grid-template-columns:repeat(3,minmax(0,1fr)); }
    .ex-stats li{ padding:14px 8px; }
    .ex-foot{ flex-direction:column; align-items:flex-start; }
    .ex-money{ justify-items:start; text-align:left; }
    .projs-list{ grid-template-columns:1fr; }
    .proj:not(:nth-child(3n+1)){ border-left:none; }
    .proj + .proj{ border-top:1px solid var(--line); }
    /* the three stops stack; the dots move into a left gutter and the arc
       bulges the other way, which is what the negative --arc-bulge does */
    .steps{ --arc-bulge:-.10; grid-template-columns:1fr; padding-left:56px; }
    .step, .step:nth-child(2), .step:nth-child(3){ padding:0 0 clamp(30px,4.5vh,44px); }
    .step-dot{ position:absolute; left:-36px; top:.3em; margin:0; }
    .step-copy{ max-width:none; }
    .dq-list, .pnr-list{ grid-template-columns:1fr; }
    .callout--split .callout-box{ grid-template-columns:1fr; }
    .gets-list{ grid-template-columns:1fr; }
    .get + .get{ border-left:none; border-top:1px solid var(--line); }
    .eng-list{ grid-template-columns:1fr; }
    .eng-item + .eng-item{ border-left:none; border-top:1px solid var(--line); }
    .opt-ways{ grid-template-columns:1fr; }
    .opt-way + .opt-way{ border-left:none; border-top:1px solid var(--line); }
    .incl-list{ grid-template-columns:1fr; }
    .quad-list{ grid-template-columns:1fr; }
    .quad-item:nth-child(even){ border-left:none; }
    .quad-item + .quad-item{ border-top:1px solid var(--line); }
    /* one rail down the left; a snake has nowhere to swing in a single column */
    .l{ display:inline; }
    .tl{ grid-template-columns:30px 1fr; row-gap:clamp(38px,5vh,56px); }
    .tl-stop[data-side="l"], .tl-stop[data-side="r"]{ grid-column:2; }
    .tl-stop[data-side="l"] .tl-node, .tl-stop[data-side="r"] .tl-node{ left:-30px; right:auto; }
    .tl-stop[data-side="l"] .tl-card, .tl-stop[data-side="r"] .tl-card{ padding:0; }
    .tl-head{ gap:12px; margin-bottom:14px; }
    .tl-copy{ max-width:none; }
    /* stacked, and the photo already leads in the DOM. Capped: allowed to fill
       a 700px column the portrait runs ~805px tall, which is most of a phone
       screen of scroll for one image. */
    .prc-box{ grid-template-columns:1fr; }
    .prc-cell + .prc-cell{ border-left:none; border-top:1px solid var(--line); }
    /* full-width cell plus the body size runs ~72 characters around 700px */
    .prc-copy{ max-width:560px; }
    /* Labels drop to the interface step on mobile — at 1.1x of a 14px --ui the
       tracked caps ran wider than a 390px column in three places. */
    .hero-q, .trust-stat, .svc-name, .why-name, .hiw-cue, .ft-h, .prc-name,
    .quad-name, .chain-name, .stage-name, .eng-cue, .eng-name,
    .plans-table th[scope=col], .dq-name, .pnr-cue, .sig-name, .ex-name, .ex-cue,
    .ex-headcue, .lever-end, .ex-statlabel, .ex-dh, .legal-updated,
    .mtg-copy .mtg-role{ font-size:var(--ui); }
    .cta-embed .calendly-inline-widget{ height:760px; }
    /* the mark takes its own row, the four columns pair up beneath it */
    .ft-top{ grid-template-columns:1fr; }
    .ft-mark{ margin-bottom:8px; }
    .ft-cols{ grid-template-columns:1fr 1fr; gap:30px 24px; }
    .ft-bottom{ flex-direction:column; align-items:flex-start; }
    .faq-list{ grid-template-columns:1fr; }
    /* one full-width tile at the body size runs ~76 characters around 700px */
    .faq-a{ max-width:520px; }
    .mtg-inner{ grid-template-columns:1fr; justify-content:normal; gap:clamp(30px,4vh,42px); }
    /* one column now, and the portrait is capped well under it — without an
       auto inline margin the cap leaves the photo hanging on the left edge
       while the copy below runs the full width. */
    .mtg-shot{ max-width:340px; margin-inline:auto; }
    .mtg-copy p{ max-width:none; }

    /* ---- the groups step down together below 900 ----
       Each of these was a per-element font-size before the groups existed, and
       the coverage had gone ragged: C1 sat at var(--ui) in three places and
       1.25x in one, while three C2 members had no mobile rule at all and stayed
       on the desktop 1.1x — so the section thesis was rendering SMALLER than the
       item copy beside it. One rule per group, same two steps as desktop. */

    /* A — the heads share the claim's mobile clamp. Without this an h2 rendered
       larger than the h1 at every width below 900. */
    .svc h2, .grt h2, .why h2, .handoff h2, .hiw h2,
    .prc h2, .faq h2, .cta h2, .mtg-copy h2,
    .quad h2, .bridge h2, .lens h2, .gets h2, .eng h2, .opt h2, .band h2,
    .plans h2, .incl h2, .cx h2, .sys h2, .callout-h, .projs h2, .dqs h2,
    .lvr h2, .ex-sec h2, .types h2, .probs h2, .roster h2, .tstm h2, .form-sec h2,
    .pnrs h2{ font-size:clamp(28px,7vw,36px); }

    /* C1 — 1.6x of a 14px --ui in a ~300px column sets ~31 characters, under
       the floor. One step down holds the measure. */
    .why-lede, .grt-copy, .mtg-copy p, .cta-sub,
    .hero-center .phero-lede, .bridge-lede, .lens-lede,
    .eng-lede, .opt-lede, .incl-lede, .callout-lede, .projs-lede,
    .band-lede, .quad-lede, .plans-lede, .incl-list li, .probs-lede,
    .form-lede{ font-size:calc(var(--ui) * 1.25); }

    /* C2 */
    .hero-center p, .svc-desc, .tl-copy, .prc-copy, .faq-a,
    .why-desc, .why-qs, .quad-copy, .bridge-copy, .stage-q,
    .get-copy, .eng-copy, .band-copy, .callout-copy, .incl-note, .cx-note, .sys-note,
    .opt-note, .eng-meta li, .plans-table td, .plans-table th[scope=row], .chip,
    .proj-copy, .dq-copy, .lever-copy, .ex-focus, .ex-copy, .lvr-note, .pp-what,
    .step-copy, .proj-price, .legal-copy, .legal-list li, .type-copy, .probs-close,
    .tstm-quote, .cform-note, .pnr-copy{ font-size:var(--ui); }
  }


  /* ---- toggle bar ---- */
