/* =====================================================================
   WIDENINE SOLUTIONS — INSIGHTS + GLOSSARY
   =====================================================================
   Shared stylesheet for /insights/ and /glossary/.

   WHY THIS FILE EXISTS, AND WHY IT IS NOT INLINE LIKE index.html.
   The homepage is deliberately a single self-contained file. Insights
   is many files, so inlining would duplicate the same CSS into every
   article and guarantee drift the first time a token changes. One shared
   stylesheet is the correct trade here.

   TOKENS ARE COPIED VERBATIM from index.html's :root block. If a brand
   token changes there, change it here in the same pass. That is a
   cascade, and index.html is the canonical source.

   COMPONENT PARITY (2026-08-03). These pages are meant to read as the
   same site as the homepage, not as a blog bolted onto it. The shared
   language is: eyebrow + heading-rule, cards that lift on hover with the
   same shadow, alternating mist/white section bands closing on an ink
   band, reveal-on-scroll, and one button system. Where a rule below
   mirrors index.html it is marked MIRRORS. Changing it there means
   changing it here.
   ===================================================================== */

:root {
  --ink: #16202E;
  --navy: #26315E;
  --emerald-light: #35C77E;
  --green: #0B8A4B;
  --electric-green: #22C55E;
  --steel: #5A6B7E;
  --violet: #6D28D9;
  --mist: #F7F9FB;
  --white: #FFFFFF;

  --font-display: 'Archivo', -apple-system, sans-serif;
  --font-accent: 'Sora', -apple-system, sans-serif;

  --max-w: 1120px;
  --read-w: 46rem;              /* reading measure — narrower than the site wrap on purpose */
  --pad-x: clamp(1.5rem, 5vw, 3rem);
  --section-pad-y: clamp(3rem, 7vw, 5rem);

  --ease: cubic-bezier(0.16, 1, 0.3, 1);

  /* MIRRORS index.html .service-card hover shadow. */
  --lift-shadow: 0 20px 40px -20px rgba(22,32,46,0.25);
  --hairline: 1px solid rgba(22,32,46,0.08);
}

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

body {
  margin: 0;
  background: var(--white);
  color: var(--ink);
  font-family: var(--font-display);
  font-size: 16px;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3 { margin: 0; font-family: var(--font-display); font-weight: 700; letter-spacing: -0.02em; }
h1, h2 { text-wrap: balance; }               /* MIRRORS index.html */
p { margin: 0; }
a { color: inherit; text-decoration: none; }
img { max-width: 100%; }

.wrap { max-width: var(--max-w); margin: 0 auto; padding-left: var(--pad-x); padding-right: var(--pad-x); }
.read { max-width: var(--read-w); margin: 0 auto; padding-left: var(--pad-x); padding-right: var(--pad-x); }

/* MIRRORS index.html — INCLUDING THE SIZE. Both files must move together or the
   eyebrow is two different sizes depending on which page you landed on. */
.eyebrow {
  font-family: var(--font-accent);
  font-weight: 700;
  /* 2026-08-18 (Rob's call): 0.78rem (12.48px) -> 1.125rem (18px) at desktop.
     At 12.48px the eyebrow was a caption, not a section label, and it sat under
     a 34.4px H2 with no readable relationship to it. Clamped rather than flat:
     a flat value holds on a 390px phone only because the longest eyebrow on the
     site ("Create leverage. Pursue with intent. Finish with proof.") is allowed
     to wrap, and it looks like a paragraph when it does. The clamp lets it
     settle to ~15px on a phone and reach 18px by ~1000px.
     ** IT SHIPPED AT 20px FIRST AND CAME BACK TO 18px THE SAME DAY, on review.
     ** 20px is 58% of the 34.4px H2 it introduces and read as a competing
     headline; 18px is 52%. The full reasoning, including why 18 rather than 17,
     lives with the matching rule in index.html - THAT ONE IS THE CANONICAL NOTE.
     ** IF THIS VALUE CHANGES, CHANGE index.html's `.eyebrow` AND BOTH
     `h2.eyebrow` PINS IN THE SAME COMMIT. ** Four places, one size. */
  font-size: clamp(0.95rem, 0.62rem + 1.05vw, 1.125rem);
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--green);
  display: inline-block;
  margin-bottom: 1rem;
}
.bg-ink .eyebrow { color: var(--emerald-light); }

/* MIRRORS index.html .heading-rule / .accent-bar */
.heading-rule { width: 64px; height: 3px; background: var(--green); border-radius: 2px; margin: 1.25rem 0 0; }
.bg-ink .heading-rule { background: var(--electric-green); }

/* ============ REVEAL ON SCROLL ============
   MIRRORS index.html. Hiding is gated on html.js so a no-JS visitor — or a
   page where the script never loaded — always sees content. The animation is
   a progressive enhancement, never a prerequisite for the page being visible. */
html.js .reveal { opacity: 0; transform: translateY(16px); transition: opacity 0.7s var(--ease), transform 0.7s var(--ease); }
html.js .reveal.is-visible { opacity: 1; transform: translateY(0); }

/* ============ NAV ============ */
.nav {
  position: sticky; top: 0; z-index: 50;
  background: rgba(255,255,255,0.92);
  backdrop-filter: saturate(180%) blur(12px);
  border-bottom: 1px solid rgba(22,32,46,0.08);
}
.nav-inner {
  max-width: var(--max-w); margin: 0 auto;
  padding: 0.7rem var(--pad-x);
  display: flex; align-items: center; justify-content: space-between; gap: 1rem;
}
/* flex-shrink: 0 IS A TRIPWIRE, NOT A STYLE. 2026-08-18.
   `.nav-inner` is `justify-content: space-between`, so when the bar's contents
   exceed the container the default `flex-shrink: 1` squeezes these two boxes
   instead of overflowing. Their TEXT does not shrink with them, so the failure
   showed up as "SOLUTIONS" printed through "The problem" — invisible to every
   automated check that measures bounding boxes, because the boxes still fit.
   With shrink pinned to 0 the same over-budget bar overflows the container
   instead, which `document.scrollWidth > innerWidth` catches on the first run.
   ** DO NOT REMOVE TO "FIX" AN OVERFLOW. ** An overflow here means the link set
   is too wide; drop a link or shorten a label. */
.nav-logo { display: inline-flex; align-items: center; gap: 0.6rem; flex-shrink: 0; }
/* 40px MIRRORS index.html's `.brandmark-avatar { width: 40px }`. It was 30px here,
   which made the mark visibly smaller on these pages AND — below 861px, where the
   nav button is hidden and the logo becomes the tallest item in the bar — set a
   53px header against the homepage's 63px. Brand asset size and nav parity are
   the same fix. */
.brandmark-avatar { width: 40px; height: 40px; border-radius: 6px; display: block; }
/* .nav-wordmark RULES REMOVED 2026-08-18 along with the markup they styled.
   The header lockup on these pages is now the 40px brandmark only, matching
   index.html exactly — see the long note in build_insights.nav_html(). The old
   rules (1.02rem display face, plus a .sol tag at 0.6rem / 0.22em tracking) and
   the two responsive rules that hid them at 560px and 430px are all gone: with
   no wordmark there is nothing to hide, and the narrow-width budget improved by
   163px as a result. Do not re-add either half without the other. */
.nav-links { display: flex; align-items: center; gap: 1.35rem; flex-shrink: 0; }
.nav-link { font-size: 0.9rem; font-weight: 500; color: var(--ink); transition: color 0.2s var(--ease); white-space: nowrap; }
.nav-link:hover { color: var(--green); }
/* Current section gets a green underline so a reader always knows where they are. */
.nav-link[aria-current="page"] { color: var(--green); position: relative; }
.nav-link[aria-current="page"]::after {
  content: ''; position: absolute; left: 0; right: 0; bottom: -0.45rem;
  height: 2px; border-radius: 2px; background: var(--green);
}
.nav-link.btn[aria-current="page"]::after { display: none; }

/* ---- NAV HEIGHT PARITY WITH index.html, 2026-08-03 (Rob's call) -------------
   These pages rendered a 71px header against the homepage's 63px, so the nav
   visibly jumped every time a reader crossed from / to /insights/. The nav is
   the one component that must feel identical on every page, so this is a bug,
   not a style choice.

   CAUSE (measured, not guessed): nothing to do with header padding — both files
   use 0.7rem top and bottom. It is the "Start a conversation" pill. On the
   homepage, `.nav-links a.nav-link { padding-bottom: 4px }` exists to leave room
   for the green hover underline on TEXT links, and it also lands on the .btn,
   squashing it to 40px. insights.css has no such rule, so the button kept its
   full 0.7rem and rendered 47.2px. The button is the tallest item in the bar, so
   it sets the header height: 40 + 22.4 padding = 63px vs 47.2 + 22.4 = 70.6px.

   FIX: match the homepage's 40px, but SYMMETRICALLY. The homepage arrives at 40px
   via 11.2px top and 4px bottom, which is an accident of that underline rule and
   leaves the label sitting slightly high in the pill. Copying the number is
   right; copying the asymmetry would be copying the bug. 0.475rem both sides
   gives 22.816 line-height + 15.2 padding + 2 border = 40px exactly.

   ** THIS IS THE ONE PLACE THESE FILES DELIBERATELY DIFFER IN VALUE WHILE
   MATCHING IN OUTPUT. ** If the homepage nav button is ever retuned, re-measure
   here — the target is the rendered 63px header, not the padding number. */
.nav-links .nav-link.btn { padding-top: 0.475rem; padding-bottom: 0.475rem; }
.visually-hidden {
  position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0;
}
/* ============ NARROW-VIEWPORT NAV ============
   REWRITTEN 2026-08-04 (second pass, same day).

   WHAT THE FIRST PASS DID AND WHY IT WAS WRONG. Earlier today the breakpoint
   here moved 860px -> 1040px to kill a real horizontal-scroll bug: the full
   link set plus the CTA needs ~1026px of nav, so 861-1022px overflowed. The
   number was right and the consequence was not checked. Because `Glossary` and
   the `Start a conversation` button both carried `.hide-sm`, raising the
   breakpoint deleted BOTH of them on every phone and every small laptop — so
   every /insights/ and /glossary/ page shipped with a header containing two
   links, no CTA, and no hamburger to recover the rest. The horizontal scroll
   was a nuisance; a content section with no route to the contact form is a
   dead funnel. Fixing the first bug created a worse one.

   WHAT THIS DOES INSTEAD. The CTA never disappears and NEVER CHANGES ITS TEXT
   at any width — it is the only conversion path these pages have, and its label
   is a client-facing string, not a responsive variable. Space is made by
   dropping links, in the order of how well the footer already covers them (the
   footer carries the full set at every width), and finally by dropping the
   wordmark to the brand mark alone:

     <= 1040px   drop The ungoverned middle / Services / Process / About
     <=  780px   drop Free tools
     <=  560px   wordmark drops "SOLUTIONS"
     <=  430px   drop Glossary and Insights; wordmark drops to the mark alone,
                 leaving brand mark + "Start a conversation" as the floor

   ** THE REMOVED RULE, RECORDED SO IT IS NOT REINTRODUCED. ** Between these two
   passes the button carried two spans and swapped to a short label ("Contact")
   below 720px. Removed on Rob's call, 4 Aug 2026, for three reasons:
     1. "Contact" was an unapproved CTA label coined in markup. Markup is not
        where names get made.
     2. It made the site's single most important button say two different things
        at two screen widths — the exact failure this section's essays are about,
        and the same defect already logged as a watch item for the two
        system-diagram SVGs.
     3. It had a failure mode. With this stylesheet stale, missing or
        mid-deploy, BOTH spans render — "Start a conversationContact" — which is
        ~60% wider than the button is drawn for and pushes the nav into the
        wordmark. That is a broken, overlapping nav produced by a cache state,
        not by a layout bug, so it does not reproduce locally.
   If the CTA ever needs to be shorter, change the one string in nav_html() and
   in the registry — not the viewport.

   Verified: zero horizontal overflow, zero element overlap, a >=16px gap
   between wordmark and first link, and a constant 63px bar height, at every
   20px step from 320px to 1440px across the index, an article and the glossary.
   Re-measure if a nav label gets longer. */
/* ---- NAV WIDTH BUDGET, ADDED 2026-08-17 (the bug this pass fixed) --------
   THE DEFECT. The ladder below was budgeted on 4 Aug for SIX links plus the
   CTA. On 17 Aug the bar went to EIGHT (Pricing and FAQ joined NAV_LINKS when
   the tier cards moved to /pricing/). Nobody re-measured. Measured on the live
   pages, the full eight-link set needed 1092px of nav - but hide-sm does not
   drop anything until 1040px. Between those two numbers nothing gives way, so
   /pricing/ and every pillar page carried up to 52px of HORIZONTAL SCROLL
   across a 51px dead band (1041-1091px). That band is a 1366px laptop at 125%
   browser zoom, or a 1440px window with a side panel open - i.e. real traffic.
   This is the identical failure logged at the top of this block for 861-1022px,
   reintroduced by adding links rather than by moving a breakpoint.

   THE FIX, two parts:
     1. The first nav label is now "What we build" (was "The ungoverned
        middle"). Rob's call, and it is what actually closed the band:
        1092px -> 1029px, which clears 1041 with 12px to spare.
     2. THIS RULE. 12px of headroom is not headroom, it is the next silent
        break. The gap clamp below is the SAME rule index.html has carried
        since 3 Aug, and it is the reason the homepage never had this bug.
        Porting it takes the requirement to 991px and makes the two surfaces
        render the bar identically instead of 1.35rem here and 1.25rem there.
     3. LATER THE SAME DAY, Rob dropped Pricing from the bar (seven links, not
        eight). The full set now needs 922px against a binding width of 1041 -
        ** 119px of headroom **, where this morning it was 51px SHORT.

   ** THE TRIPWIRE: RE-MEASURE AT 1041px, NOT 1440px. **
   1041 is the widest viewport at which the FULL set is still shown. Any label
   that gets longer, or a ninth item, is checked there or not at all. Verified
   17 Aug: zero overflow and a flat 63px bar at every 1px step from 900 to 1200
   on /pricing/ and /pursue/.

   ** 2026-08-18: THE TRIPWIRE WAS RIGHT AND IT WAS IGNORED. ** The eighth link
   ("The answer") was added the next morning and re-measured ON THE HOMEPAGE,
   which reported 147px of slack. These pages were never re-measured, and they
   do not share the homepage's budget: their lockup was 203px against its 40px.
   Result: 8 links + CTA needed 1043px against a 1024px container, so the bar
   was 19px over at EVERY width 1200-1920 and 80px over at 1041 - and because
   `.nav-logo` could still shrink, it failed as text-through-text rather than as
   overflow. Both causes are now closed: the wordmark is gone (one budget, both
   surfaces) and `flex-shrink: 0` above turns any future over-budget bar into a
   scrollWidth overflow a script can see. THE MEASUREMENT MUST STILL BE RUN ON A
   BUILT PAGE, NOT ON index.html. */
.nav-links { gap: clamp(0.85rem, 1.7vw, 1.25rem); }

@media (max-width: 1040px) { .nav-links .nav-link.hide-sm { display: none; } }
/* 780, not 560. MEASURED, do not round this down: logo (254 with the full
   wordmark, 40 since 18 Aug 2026 — the band now has ~163px more slack than this
   note assumes, and 780 is kept only because nothing has been re-measured to
   justify moving it) + Insights + Free tools + Glossary + the CTA + four 1.35rem
   gaps + the gutter needs ~750px. A first attempt dropped `Free tools` at 560 and the
   nav overflowed by 66px across the whole 561-720 band — which is the identical
   dead band this block was written to kill, just moved. Narrowing the gap alone
   recovers only ~42px of the 66, so a link has to go. */
@media (max-width: 780px) { .nav-links .nav-link.hide-xs { display: none; } }
@media (max-width: 560px) {
  .nav-links { gap: 0.7rem; }
  /* NO padding reduction here. index.html holds 0.7rem all the way down, so
     shrinking it on these pages reproduced the 63px-vs-49px jump this whole
     block exists to remove. Measured at 700 / 560 / 480 / 390. */
}
@media (max-width: 430px) {
  .nav-links .nav-link.hide-xxs { display: none; }
  .nav-links { gap: 0.55rem; }
  /* The `.nav-wordmark { display: none }` that used to live here went away with
     the wordmark itself on 18 Aug — the lockup is the 40px mark at every width
     now, so there is nothing left to drop. The rules below are what still buys
     room at the bottom of the range.
     320px (iPhone 5 / Galaxy Fold cover screen) is the narrowest viewport still
     in the wild and is the case this is measured against. */
  .nav-inner { padding-left: 0.85rem; padding-right: 0.85rem; gap: 0.5rem; }
  .nav-logo { gap: 0.4rem; }
  /* Horizontal padding only — the 0.475rem vertical above is what holds the bar
     at 63px to match index.html, and must not be touched. Trimming the pill's
     sides recovers ~22px, which is the difference between an 11px and a 33px
     gap at 320px. Cheaper than dropping the "Insights" link, which is also the
     current-section indicator. */
  .nav-links .nav-link.btn { padding-left: 0.9rem; padding-right: 0.9rem; }
}

/* ============ READING PROGRESS ============
   MIRRORS index.html #progress. On a long-form page this earns its keep: it
   tells a reader how much essay is left before they decide to bail. */
#progress {
  position: absolute; bottom: 0; left: 0;
  height: 3px; width: 0%;
  background: linear-gradient(90deg, var(--ink), var(--navy), var(--green), var(--electric-green), var(--violet));
  background-size: 100vw 100%;
  background-repeat: no-repeat;
  z-index: 5;
  transition: width 0.08s linear;
}

/* ============ BUTTONS ============ MIRRORS index.html */
.btn {
  display: inline-flex; align-items: center; gap: 0.5rem;
  font-family: var(--font-display); font-weight: 600; font-size: 0.92rem;
  padding: 0.7rem 1.35rem; border-radius: 999px;
  background: var(--ink); color: var(--white); border: 1px solid var(--ink);
  cursor: pointer;
  transition: background 0.2s var(--ease), color 0.2s var(--ease), transform 0.2s var(--ease), border-color 0.2s var(--ease);
}
.btn:hover { background: var(--green); border-color: var(--green); transform: translateY(-1px); }
.btn.ghost { background: transparent; color: var(--ink); border-color: rgba(22,32,46,0.25); }
.btn.ghost:hover { background: var(--ink); color: var(--white); border-color: var(--ink); }
.btn.on-navy { background: var(--green); border-color: var(--green); color: var(--white); }
.btn.on-navy:hover { background: var(--electric-green); border-color: var(--electric-green); color: var(--ink); }
.btn.ghost.on-navy { background: transparent; border-color: rgba(255,255,255,0.35); color: var(--white); }
.btn.ghost.on-navy:hover { background: var(--white); color: var(--ink); border-color: var(--white); }
.cta-row { display: flex; gap: 1.15rem; flex-wrap: wrap; }

/* ---- BUTTON BREATHING ROOM, 2026-08-03 (Rob's call) -------------------------
   ** THIS IS A DELIBERATE DIVERGENCE FROM index.html. ** Everything above in the
   BUTTONS block is marked MIRRORS; this override is not, and it is the only place
   these two stylesheets intentionally disagree.

   WHY: .btn is a 999px pill. On a fully-rounded shape the horizontal curve eats
   the visual padding, so 1.35rem of box padding reads as roughly half that beside
   the label — the text looks pressed against the edge. Long labels make it worse,
   and every button on these two pages has a long label ("Browse the glossary",
   "Get your Content Readiness score"), whereas the homepage's are mostly short
   ("Services", "Start a conversation").

   Vertical went 0.7 -> 0.85rem and horizontal 1.35 -> 1.75rem. Hit area grows
   from roughly 38px to 44px tall, which is also the first time these buttons
   clear the 44px minimum touch target on mobile.

   ** IF THE HOMEPAGE BUTTONS ARE EVER RETUNED, DELETE THIS BLOCK AND RESTORE THE
   MIRROR. ** Two button sizes across one site is a bug the moment it is not
   deliberate. Right now it is deliberate, and this comment is the record. */
/* :not(.nav-link) is load-bearing. Without it the nav's "Start a conversation"
   pill grows too, taking the header from 60px to 74px on these pages while the
   homepage stays 60px — and the nav is the one component that must feel
   byte-identical across every page of the site. Caught in measurement, 3 Aug. */
.btn:not(.nav-link) { padding: 0.85rem 1.75rem; }

/* ============ SECTION HEADER (index pages) ============ */
.fn-head {
  position: relative;
  padding: clamp(3.25rem, 8vw, 5.5rem) 0 clamp(2rem, 5vw, 3rem);
  background: var(--mist);
  border-bottom: var(--hairline);
  overflow: hidden;
}
/* A single soft brand wash so the masthead has depth instead of a flat grey slab. */
.fn-head::after {
  content: ''; position: absolute; inset: 0; pointer-events: none;
  background:
    radial-gradient(60rem 22rem at 88% -20%, rgba(34,197,94,0.10), transparent 60%),
    radial-gradient(46rem 20rem at 4% 118%, rgba(38,49,94,0.07), transparent 62%);
}
.fn-head > .wrap { position: relative; z-index: 1; }
.fn-head h1 { font-size: clamp(2.1rem, 5.2vw, 3.3rem); line-height: 1.06; max-width: 20ch; }
.fn-head .standfirst {
  margin-top: 1.4rem; font-size: clamp(1.05rem, 1.7vw, 1.25rem);
  color: var(--steel); line-height: 1.55; max-width: 36rem;
}
.fn-head-meta {
  margin-top: 2rem; padding-top: 1.25rem;
  border-top: 1px solid rgba(90,107,126,0.22);
  font-family: var(--font-accent); font-weight: 700; font-size: 0.72rem;
  letter-spacing: 0.13em; text-transform: uppercase; color: var(--steel);
  display: flex; gap: 0.6rem; flex-wrap: wrap; align-items: center;
}
.fn-head-meta .dot { color: rgba(90,107,126,0.45); }
.fn-head-meta a { color: var(--green); border-bottom: 1px solid rgba(11,138,75,0.35); transition: border-color 0.2s var(--ease); }
.fn-head-meta a:hover { border-bottom-color: var(--green); }

/* ============ INDEX: FEATURED + GRID ============
   The pillar is the page's most valuable asset. A flat reverse-chronological
   list buries it the moment anything newer ships, so it gets a feature card
   and the spokes get a grid. */
.fn-list { padding: clamp(2.75rem, 6vw, 4rem) 0 var(--section-pad-y); background: var(--white); }

.fn-feature {
  display: grid; grid-template-columns: 1.25fr 1fr; gap: clamp(1.5rem, 4vw, 3rem);
  align-items: center;
  background: var(--white);
  border: var(--hairline); border-radius: 20px;
  padding: clamp(1.75rem, 3.5vw, 2.6rem);
  margin-bottom: clamp(2rem, 4vw, 2.75rem);
  transition: transform 0.3s var(--ease), box-shadow 0.3s var(--ease), border-color 0.3s var(--ease);
}
.fn-feature:hover { transform: translateY(-6px); box-shadow: var(--lift-shadow); border-color: rgba(38,49,94,0.35); }
.fn-feature:hover .fn-feature-title { color: var(--green); }
.fn-feature-tag {
  align-self: flex-start; display: inline-block;
  font-family: var(--font-accent); font-size: 0.7rem; font-weight: 700;
  letter-spacing: 0.12em; text-transform: uppercase; color: var(--green);
  border: 1px solid rgba(11,138,75,0.3); border-radius: 999px;
  padding: 0.25rem 0.7rem; margin-bottom: 1.1rem;
}
.fn-feature-title { font-size: clamp(1.55rem, 3.2vw, 2.15rem); line-height: 1.12; transition: color 0.2s var(--ease); }
.fn-feature-dek { margin-top: 0.9rem; color: var(--steel); font-size: 1.05rem; line-height: 1.6; }
.fn-feature-side { border-left: 1px solid rgba(22,32,46,0.1); padding-left: clamp(1.5rem, 3vw, 2.5rem); }
.fn-feature-side p {
  font-family: var(--font-accent); font-weight: 700; font-size: 0.7rem;
  letter-spacing: 0.13em; text-transform: uppercase; color: var(--steel); margin-bottom: 0.9rem;
}
.fn-feature-side ul { list-style: none; margin: 0 0 1.4rem; padding: 0; }
.fn-feature-side li { font-size: 0.94rem; line-height: 1.5; color: var(--ink); margin-bottom: 0.5rem; padding-left: 1.1rem; position: relative; }
.fn-feature-side li::before { content: ''; position: absolute; left: 0; top: 0.62em; width: 6px; height: 6px; border-radius: 2px; background: var(--green); }
.fn-feature-go { font-family: var(--font-accent); font-weight: 700; font-size: 0.74rem; letter-spacing: 0.12em; text-transform: uppercase; color: var(--green); }

@media (max-width: 800px) {
  .fn-feature { grid-template-columns: 1fr; }
  .fn-feature-side { border-left: none; border-top: 1px solid rgba(22,32,46,0.1); padding-left: 0; padding-top: 1.5rem; }
}

.fn-grid-label {
  font-family: var(--font-accent); font-weight: 700; font-size: 0.72rem;
  letter-spacing: 0.13em; text-transform: uppercase; color: var(--steel);
  margin-bottom: 1.25rem;
}
/* `min(300px, 100%)`, not a bare 300px. A bare track minimum is a floor the
   grid cannot go below, so at 320px — iPhone 5, Galaxy Fold cover screen — a
   300px card plus the page gutter overran the viewport and every card row
   scrolled sideways. Pre-existing; found 2026-08-04. The same one-word fix is
   applied to .gl-grid below. */
.fn-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(300px, 100%), 1fr)); gap: 1.5rem; }
.fn-item {
  display: flex; flex-direction: column;
  background: var(--white); border: var(--hairline); border-radius: 18px;
  padding: clamp(1.5rem, 2.6vw, 1.9rem);
  transition: transform 0.3s var(--ease), box-shadow 0.3s var(--ease), border-color 0.3s var(--ease);
}
.fn-item:hover { transform: translateY(-6px); box-shadow: var(--lift-shadow); border-color: rgba(38,49,94,0.35); }
.fn-item:hover .fn-item-title { color: var(--green); }
.fn-meta {
  font-family: var(--font-accent); font-weight: 700; font-size: 0.68rem;
  letter-spacing: 0.13em; text-transform: uppercase; color: var(--steel);
  display: flex; gap: 0.55rem; align-items: center; flex-wrap: wrap;
}
.fn-meta .dot { color: rgba(90,107,126,0.5); }
/* Some question labels wrap to two lines and some don't. Reserving both lines
   keeps every card title on the same baseline across a row. */
.fn-grid .fn-meta { min-height: 2.2rem; align-items: flex-start; align-content: flex-start; }
.fn-item-title { margin-top: 0.35rem; font-size: 1.22rem; line-height: 1.25; transition: color 0.2s var(--ease); }
.fn-item-dek { margin-top: 0.6rem; color: var(--steel); font-size: 0.96rem; line-height: 1.55; }
.fn-item-go {
  margin-top: auto; padding-top: 1.2rem;
  font-family: var(--font-accent); font-weight: 700; font-size: 0.72rem;
  letter-spacing: 0.12em; text-transform: uppercase; color: var(--green);
}

/* ============ ARTICLE HEAD ============ */
.fn-article-head {
  position: relative;
  padding: clamp(2.75rem, 7vw, 4.5rem) 0 0;
  background: var(--mist);
  border-bottom: var(--hairline);
  overflow: hidden;
}
.fn-article-head::after {
  content: ''; position: absolute; inset: 0; pointer-events: none;
  background: radial-gradient(56rem 22rem at 92% -25%, rgba(34,197,94,0.09), transparent 60%);
}
.fn-article-head > .read { position: relative; z-index: 1; }
.fn-article-head h1 { font-size: clamp(1.95rem, 4.4vw, 2.9rem); line-height: 1.08; max-width: 22ch; }
.fn-article-head .standfirst { margin-top: 1.15rem; font-size: clamp(1.02rem, 1.5vw, 1.16rem); color: var(--steel); line-height: 1.55; max-width: 48ch; }
.fn-article-head .fn-meta { margin-bottom: 0.9rem; }
.fn-article-head .read { padding-bottom: clamp(2.5rem, 6vw, 3.5rem); }
.fn-rule { display: block; width: 64px; height: 3px; border-radius: 2px; background: var(--green); margin: 1.9rem 0 0; }

/* ============ ARTICLE BODY ============ */
.fn-body { padding: clamp(2.75rem, 6vw, 4rem) 0 clamp(2.5rem, 5vw, 3.5rem); background: var(--white); }
.fn-body p { margin: 0 0 1.35rem; font-size: 1.09rem; line-height: 1.72; }
.fn-body h2 {
  margin: 3.1rem 0 1.05rem; font-size: clamp(1.32rem, 2.3vw, 1.62rem);
  line-height: 1.22; letter-spacing: -0.018em; position: relative; padding-top: 1.1rem;
}
/* A short green tick above each H2 — the same accent-bar device the homepage
   uses to open a section, scaled down for in-article rhythm. */
.fn-body h2::before {
  content: ''; position: absolute; top: 0; left: 0;
  width: 34px; height: 3px; border-radius: 2px; background: var(--green);
}
.fn-body h3 { margin: 2.2rem 0 0.8rem; font-size: 1.14rem; }
.fn-body ul, .fn-body ol { margin: 0 0 1.35rem; padding-left: 1.3rem; }
.fn-body li { margin-bottom: 0.7rem; font-size: 1.09rem; line-height: 1.68; }
.fn-body strong { font-weight: 700; }
.fn-body em { font-style: italic; }
.fn-body a { color: var(--green); text-decoration: underline; text-underline-offset: 2px; }
.fn-body a:hover { color: var(--ink); }
.fn-body hr { border: none; border-top: 1px solid rgba(22,32,46,0.12); margin: 2.6rem 0; }

/* Pull-quote treatment — a card, not a bare left border. */
.fn-body blockquote {
  margin: 2.2rem 0; padding: 1.4rem 1.6rem;
  border: none; border-left: 3px solid var(--green);
  border-radius: 0 14px 14px 0;
  background: var(--mist);
  color: var(--ink);
}
.fn-body blockquote p { font-size: 1.12rem; line-height: 1.6; margin-bottom: 0.6rem; }
.fn-body blockquote p:last-child { margin-bottom: 0; }

/* Tables read as data cards, not as raw markdown output. */
.fn-body table {
  border-collapse: separate; border-spacing: 0; width: 100%;
  margin: 0 0 1.8rem; font-size: 0.98rem;
  border: var(--hairline); border-radius: 14px; overflow: hidden;
}
.fn-body th, .fn-body td { text-align: left; padding: 0.72rem 1rem; vertical-align: top; }
.fn-body thead th {
  background: var(--mist); font-weight: 700; font-size: 0.74rem;
  font-family: var(--font-accent); letter-spacing: 0.1em; text-transform: uppercase; color: var(--steel);
  border-bottom: 1px solid rgba(22,32,46,0.14);
}
.fn-body tbody tr + tr td { border-top: 1px solid rgba(22,32,46,0.08); }
.fn-body tbody tr:hover td { background: rgba(247,249,251,0.75); }
.fn-table-scroll { overflow-x: auto; }

/* ============ RELATED / CLUSTER LINKS ============
   Cards, because the interlinking IS the topical-authority structure. Making
   it look like a footnote list undersells it and gets fewer clicks. */
.fn-related { margin: 3.2rem 0 0; padding: 2rem 0 0; border-top: 1px solid rgba(22,32,46,0.12); }
.fn-related-group + .fn-related-group { margin-top: 1.9rem; }
.fn-related h3 {
  font-family: var(--font-accent); font-weight: 700; font-size: 0.72rem;
  letter-spacing: 0.13em; text-transform: uppercase; color: var(--steel);
  margin: 0 0 0.95rem;
}
.fn-related ul { list-style: none; margin: 0; padding: 0; display: grid; grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr)); gap: 0.75rem; }
.fn-related li { margin: 0; }
.fn-body .fn-related a {
  display: flex; align-items: center; justify-content: space-between; gap: 0.75rem;
  height: 100%;
  padding: 0.85rem 1.05rem; border-radius: 12px;
  background: var(--mist); border: var(--hairline);
  color: var(--ink); text-decoration: none;
  font-size: 0.95rem; line-height: 1.4; font-weight: 600;
  transition: transform 0.2s var(--ease), border-color 0.2s var(--ease), box-shadow 0.2s var(--ease);
}
.fn-body .fn-related a::after { content: '→'; color: var(--green); flex-shrink: 0; font-weight: 700; }
.fn-body .fn-related a:hover {
  transform: translateY(-2px); border-color: rgba(11,138,75,0.45);
  box-shadow: 0 12px 24px -16px rgba(22,32,46,0.35); color: var(--ink);
}

/* ============ BYLINE ============ */
.fn-byline {
  display: flex; gap: 1.1rem; align-items: flex-start;
  margin-top: 3rem; padding-top: 1.8rem;
  border-top: 1px solid rgba(22,32,46,0.12);
}
.fn-byline img { width: 46px; height: 46px; border-radius: 10px; flex-shrink: 0; }
.fn-byline p { font-size: 0.95rem; color: var(--steel); line-height: 1.62; margin: 0; }
.fn-byline .fn-byline-name {
  display: block; font-family: var(--font-accent); font-weight: 700;
  font-size: 0.74rem; letter-spacing: 0.12em; text-transform: uppercase;
  color: var(--green); margin-bottom: 0.4rem;
}

/* ============ CTA BAND ============
   Full-bleed and dark, mirroring the homepage's closing #contact section, so
   the ask lands as a deliberate end-of-page moment rather than a grey box in
   the middle of the prose. Primary = the scored tool (which is also the email
   capture). Secondary = the call. Hierarchy is deliberate: a cold reader is
   far likelier to trade an email for a score than to book time. */
.fn-cta-band { background: var(--ink); color: var(--white); padding: clamp(3rem, 7vw, 4.75rem) 0; text-align: center; }
.fn-cta-band h2 { font-size: clamp(1.55rem, 3.2vw, 2.15rem); line-height: 1.15; max-width: 24ch; margin: 0 auto; }
.fn-cta-band .heading-rule { margin-left: auto; margin-right: auto; }
.fn-cta-band .fn-cta-copy { margin-top: 1.4rem; font-size: 1.05rem; line-height: 1.6; color: rgba(255,255,255,0.68); max-width: 52ch; margin-left: auto; margin-right: auto; }
.fn-cta-band .cta-row { margin-top: 2.2rem; justify-content: center; }
.fn-cta-note {
  margin-top: 1.5rem; font-family: var(--font-accent); font-weight: 700;
  font-size: 0.7rem; letter-spacing: 0.12em; text-transform: uppercase;
  color: rgba(255,255,255,0.45);
}
/* The .fn-body prose link rule (green + underline) must never reach UI. */
.fn-body .btn { text-decoration: none; }

/* ============ BACK LINK ROW ============ */
.fn-back-row { background: var(--white); padding: clamp(1.75rem, 4vw, 2.5rem) 0; border-top: var(--hairline); }
.fn-back {
  display: inline-flex; align-items: center; gap: 0.5rem;
  font-family: var(--font-accent); font-weight: 700; font-size: 0.72rem;
  letter-spacing: 0.13em; text-transform: uppercase; color: var(--green);
  transition: color 0.2s var(--ease);
}
.fn-back:hover { color: var(--ink); }

/* ============ GLOSSARY ============ */
.gl-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(310px, 100%), 1fr)); gap: 1.5rem; }
.gl-item {
  display: flex; flex-direction: column;
  padding: clamp(1.5rem, 2.6vw, 1.9rem); border-radius: 18px;
  background: var(--white); border: var(--hairline);
  transition: transform 0.3s var(--ease), box-shadow 0.3s var(--ease), border-color 0.3s var(--ease);
}
.gl-item:hover { transform: translateY(-6px); box-shadow: var(--lift-shadow); border-color: rgba(38,49,94,0.35); }
.gl-item:hover .gl-term { color: var(--green); }
.gl-term { font-size: 1.18rem; line-height: 1.25; transition: color 0.2s var(--ease); }
.gl-dek { margin-top: 0.6rem; font-size: 0.95rem; line-height: 1.55; color: var(--steel); }
.gl-item-go {
  margin-top: auto; padding-top: 1.2rem;
  font-family: var(--font-accent); font-weight: 700; font-size: 0.72rem;
  letter-spacing: 0.12em; text-transform: uppercase; color: var(--green);
}
.gl-also {
  margin-top: 1.1rem; padding-top: 0.9rem;
  border-top: 1px solid rgba(22,32,46,0.12);
  font-family: var(--font-accent); font-weight: 700;
  font-size: 0.7rem; letter-spacing: 0.1em; text-transform: uppercase; color: var(--steel);
}
.gl-also strong { color: var(--ink); font-weight: 700; }

/* ============ FOOTER ============ */
footer.bg-ink { background: var(--ink); color: var(--white); padding: 2.6rem 0 1.6rem; }
.footer-inner { display: flex; flex-direction: column; gap: 0.9rem; }
.footer-nav-row { display: flex; align-items: center; gap: 0.75rem; flex-wrap: wrap; font-size: 0.86rem; }
.footer-domain { font-weight: 700; }
.footer-sep { opacity: 0.4; }
.footer-links { display: flex; gap: 1.05rem; flex-wrap: wrap; }
.footer-links a { opacity: 0.82; transition: opacity 0.2s var(--ease), color 0.2s var(--ease); }
.footer-links a:hover { opacity: 1; color: var(--electric-green); }
.footer-copy {
  max-width: var(--max-w); margin: 1.5rem auto 0;
  padding: 1.2rem var(--pad-x) 0;
  border-top: 1px solid rgba(255,255,255,0.12);
  font-size: 0.78rem; opacity: 0.6;
}

@media (prefers-reduced-motion: reduce) {
  * { transition: none !important; animation: none !important; }
  html.js .reveal { opacity: 1 !important; transform: none !important; }
}

/* ============ CROSS-SECTION STRIP (Insights <-> Glossary) ============
   Added 2026-08-03. Deliberately NOT card-shaped: on a page made of cards, a
   third card reads as another article. A full-width strip reads as a different
   kind of object, which is the whole point — it routes to the OTHER section.
   Sits under the feature card and above the grid on /insights/, and above the
   term grid on /glossary/. See cross_strip() in build_insights.py. */
.fn-cross {
  display: flex; align-items: center; justify-content: space-between;
  gap: clamp(1.25rem, 3vw, 2.5rem);
  margin-bottom: clamp(2rem, 4vw, 2.75rem);
  padding: clamp(1.4rem, 2.6vw, 1.9rem) clamp(1.5rem, 3vw, 2.25rem);
  border-radius: 18px;
  background: var(--mist);
  border: 1px solid rgba(11,138,75,0.22);
  transition: transform 0.25s var(--ease), border-color 0.25s var(--ease), box-shadow 0.25s var(--ease);
}
.fn-cross:hover { transform: translateY(-3px); border-color: rgba(11,138,75,0.5); box-shadow: var(--lift-shadow); }
.fn-cross .eyebrow { margin-bottom: 0.55rem; }
.fn-cross h2 { font-size: clamp(1.15rem, 2vw, 1.4rem); line-height: 1.25; }
.fn-cross p { margin-top: 0.5rem; font-size: 0.96rem; line-height: 1.55; color: var(--steel); max-width: 52ch; }
.fn-cross .btn { flex-shrink: 0; }
.fn-cross:hover .btn { background: var(--green); border-color: var(--green); }
@media (max-width: 700px) {
  .fn-cross { flex-direction: column; align-items: flex-start; }
}

/* =====================================================================
   VISUAL BLOCK COMPONENTS  (added 2026-08-04)
   =====================================================================
   Authored in the markdown as ::: fenced blocks and rendered by
   build_insights.py. Every class below has exactly one renderer there —
   if you rename one, rename it in both places in the same pass.

   TOKENS. --amber is new and is the only token added for this work. It is
   the "this is the failure state" colour: the exposure gap, the ungoverned
   side of a comparison, the waiting-on-us span. It is deliberately NOT one
   of the brand greens, because every place it appears is a place the page
   is describing something going wrong.

   BANDS ARE INSET, NOT FULL-BLEED. index.html bands run edge to edge. Here
   the article body lives inside a 46rem measure, and the two ways to get a
   true full-bleed band from inside a centred column (100vw margins, or an
   overflow clip) either introduce horizontal scroll on a scrollbar-visible
   desktop or clip the absolutely-positioned rail and margin quotes. So the
   band spans the .read padding box: edge-to-edge on a phone, an inset panel
   on a desktop. Deliberate deviation, same rhythm, no overflow risk.
   ===================================================================== */

:root { --amber: #B45309; }

/* ============ SECTION BANDS ============ */
.fn-body { position: relative; }
.fn-sec {
  margin-left: calc(-1 * var(--pad-x)); margin-right: calc(-1 * var(--pad-x));
  padding: 0.1rem var(--pad-x) 1.4rem;
}
.fn-sec.alt { background: var(--mist); border-radius: 18px; }
.fn-sec > h2:first-child { margin-top: 2.4rem; }

/* ============ READING PROGRESS ============
   Intentionally absent. nav_html() has emitted <div id="progress"> inside the
   header since the 3 Aug pass and insights.css already styles it. A second
   progress element was added here on 4 Aug and removed the same day: it was a
   duplicate DOM id, which is invalid HTML and means getElementById returns
   whichever comes first. If you want to restyle the bar, edit the #progress
   rule above — do not add a second element. */

/* ============ SECTION RAIL ============
   Absolutely positioned in the left gutter with a sticky inner, so it never
   touches the reading measure. Hidden below 1240px, where there is no gutter
   to put it in. Nothing in the article depends on it existing. */
.fn-rail { display: none; }
@media (min-width: 1240px) {
  .fn-rail {
    display: block; position: absolute; top: 0; bottom: 0;
    left: calc(50% - 36.5rem); width: 12rem;
  }
  .fn-rail-inner { position: sticky; top: 92px; }
  .fn-rail-label {
    font-family: var(--font-accent); font-size: 0.68rem; font-weight: 700;
    letter-spacing: 0.13em; text-transform: uppercase; color: var(--steel);
    margin: 0 0 0.7rem 0.85rem;
  }
  .fn-rail a {
    display: block; font-family: var(--font-accent); font-size: 0.8rem; line-height: 1.35;
    padding: 0.34rem 0 0.34rem 0.85rem; color: var(--steel);
    border-left: 2px solid rgba(22,32,46,0.10);
    transition: color 0.2s var(--ease), border-color 0.2s var(--ease);
  }
  .fn-rail a:hover { color: var(--ink); border-left-color: rgba(22,32,46,0.3); }
  .fn-rail a.is-current { color: var(--green); font-weight: 700; border-left-color: var(--green); }
}

/* ============ C1 · STAT BAND ============ */
.fn-stats {
  margin: 2.4rem 0; border-top: 2px solid var(--green); border-bottom: var(--hairline);
  padding: 1.5rem 0 1.2rem;
  display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 1.4rem;
}
.fn-stat-n { font-size: clamp(1.9rem, 4.4vw, 2.5rem); font-weight: 800; letter-spacing: -0.04em; line-height: 1; color: var(--ink); }
.fn-stat-n .u { font-size: 0.55em; font-weight: 700; color: var(--green); margin-left: 0.08em; }
.fn-stat-l { font-family: var(--font-accent); font-size: 0.78rem; font-weight: 600; line-height: 1.4; color: var(--steel); margin-top: 0.5rem; }
.fn-stats-src { grid-column: 1 / -1; font-family: var(--font-accent); font-size: 0.74rem; color: var(--steel); margin-top: 0.4rem; }
.fn-stats-src a { color: var(--green); }
.fn-stats.on-ink { background: var(--ink); border: none; border-radius: 16px; padding: 1.8rem 1.6rem; }
.fn-stats.on-ink .fn-stat-n { color: var(--white); }
.fn-stats.on-ink .fn-stat-n .u { color: var(--electric-green); }
.fn-stats.on-ink .fn-stat-l { color: #AFC0D0; }
.fn-stats.on-ink .fn-stats-src { color: #8FA3B6; }
.fn-stats.on-ink .fn-stats-src a { color: var(--electric-green); }

/* ============ C2 · APHORISM BAND ============ */
.fn-aphorism { margin: 2.8rem 0; padding: 1.9rem 1.8rem; background: var(--mist); border-radius: 16px; border-left: 3px solid var(--green); }
.fn-aphorism p { font-size: clamp(1.18rem, 2.4vw, 1.42rem); font-weight: 700; letter-spacing: -0.022em; line-height: 1.32; margin: 0; }
.fn-aphorism .fn-aph-sub { font-family: var(--font-accent); font-size: 0.86rem; font-weight: 400; color: var(--steel); margin-top: 0.75rem; letter-spacing: 0; line-height: 1.55; }
.fn-aphorism.on-ink { background: var(--ink); border-left-color: var(--electric-green); color: var(--white); }
.fn-aphorism.on-ink .fn-aph-sub { color: #AFC0D0; }
/* P3 · margin pull-quote. Below the breakpoint it is an ordinary band — it
   degrades into the component it already is, so there is nothing to break. */
@media (min-width: 1240px) {
  .fn-aph-margin {
    position: absolute; right: calc(50% - 36.5rem); width: 12rem;
    margin: 0; padding: 0.15rem 0 0.15rem 0.9rem;
    background: none; border-radius: 0; border-left: 2px solid var(--green);
  }
  .fn-aph-margin p { font-size: 1.02rem; line-height: 1.34; }
  .fn-aph-margin .fn-aph-sub { font-size: 0.78rem; margin-top: 0.5rem; }
  .fn-aph-margin.on-ink { background: none; color: var(--ink); border-left-color: var(--green); }
  .fn-aph-margin.on-ink .fn-aph-sub { color: var(--steel); }
}

/* ============ C3 · COMPARISON SPLIT ============ */
.fn-versus { margin: 2.6rem 0; display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; }
.fn-vs-col { border: var(--hairline); border-radius: 14px; overflow: hidden; background: var(--white); }
.fn-vs-col.good { border-color: rgba(11,138,75,0.28); }
.fn-vs-col.bad { border-color: rgba(180,83,9,0.26); }
.fn-vs-head { padding: 0.85rem 1.1rem; font-family: var(--font-accent); font-size: 0.74rem; font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase; }
.fn-vs-col.good .fn-vs-head { background: rgba(11,138,75,0.08); color: var(--green); }
.fn-vs-col.bad .fn-vs-head { background: rgba(180,83,9,0.07); color: var(--amber); }
.fn-vs-body { padding: 1.05rem 1.1rem; }
.fn-vs-body ul { margin: 0; padding: 0; list-style: none; }
.fn-vs-body li { position: relative; padding-left: 1.35rem; margin-bottom: 0.6rem; font-size: 0.96rem; line-height: 1.5; }
.fn-vs-body li:last-child { margin-bottom: 0; }
.fn-vs-col.good li::before { content: ''; position: absolute; left: 0; top: 0.52em; width: 7px; height: 7px; border-radius: 2px; background: var(--green); }
.fn-vs-col.bad li::before { content: ''; position: absolute; left: 0; top: 0.44em; width: 8px; height: 8px; border-radius: 50%; border: 1.5px dashed var(--amber); }
.fn-vs-body p { font-size: 0.97rem; line-height: 1.58; margin: 0 0 0.7rem; }
.fn-vs-body p:last-child { margin-bottom: 0; }
.fn-vs-mark { background: rgba(180,83,9,0.14); border-bottom: 2px solid var(--amber); padding: 0 2px; }
.fn-vs-col.good .fn-vs-mark { background: rgba(11,138,75,0.14); border-bottom-color: var(--green); }
.fn-vs-foot { padding: 0.7rem 1.1rem; border-top: var(--hairline); font-family: var(--font-accent); font-size: 0.76rem; color: var(--steel); }
@media (max-width: 640px) { .fn-versus { grid-template-columns: 1fr; } }

/* ============ C3b · PARITY ROWS ============ */
.fn-parity { margin: 2.6rem 0; border-top: var(--hairline); }
.fn-parity-row { display: grid; grid-template-columns: 1fr 46px 1fr; align-items: center; gap: 0.5rem; padding: 1rem 0; border-bottom: var(--hairline); }
.fn-parity-row .l, .fn-parity-row .r { font-size: 0.99rem; line-height: 1.45; }
.fn-parity-row .l { text-align: right; font-weight: 600; }
.fn-parity-row .r { color: var(--amber); font-weight: 600; }
.fn-parity-mid { display: flex; align-items: center; justify-content: center; }
.fn-parity-cap { font-family: var(--font-accent); font-size: 0.72rem; font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase; color: var(--steel); display: grid; grid-template-columns: 1fr 46px 1fr; gap: 0.5rem; padding-bottom: 0.6rem; }
.fn-parity-cap .l { text-align: right; color: var(--green); }
.fn-parity-cap .r { color: var(--amber); }
@media (max-width: 640px) {
  .fn-parity-cap, .fn-parity-mid { display: none; }
  .fn-parity-row { grid-template-columns: 1fr; gap: 0.55rem; padding: 1.1rem 0; }
  .fn-parity-row .l { text-align: left; }
  .fn-parity-row .l::before, .fn-parity-row .r::before {
    display: block; font-family: var(--font-accent); font-size: 0.63rem; font-weight: 700;
    letter-spacing: 0.12em; text-transform: uppercase; margin-bottom: 0.2rem;
  }
  .fn-parity-row .l::before { content: 'Regulated side'; color: var(--green); }
  .fn-parity-row .r::before { content: 'Commercial side'; color: var(--amber); }
}

/* ============ C4 · CRITERIA CARDS ============ */
.fn-criteria { margin: 2.2rem 0; }
.fn-crit-group { font-family: var(--font-accent); font-size: 0.8rem; font-weight: 700; letter-spacing: 0.1em; text-transform: uppercase; color: var(--green); margin: 0 0 0.9rem; }
.fn-crit-group.second { margin-top: 1.9rem; }
.fn-crit-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(215px, 1fr)); gap: 0.85rem; }
/* MIRRORS index.html .service-card hover. */
.fn-crit { border: var(--hairline); border-radius: 13px; padding: 1rem 1.05rem; background: var(--white); transition: transform 0.25s var(--ease), box-shadow 0.25s var(--ease); }
.fn-crit:hover { transform: translateY(-3px); box-shadow: var(--lift-shadow); }
.fn-crit-n { font-family: var(--font-accent); font-size: 0.68rem; font-weight: 700; color: var(--green); letter-spacing: 0.1em; display: block; margin-bottom: 0.4rem; }
.fn-crit h4 { font-size: 1rem; margin: 0 0 0.35rem; font-family: var(--font-display); font-weight: 700; letter-spacing: -0.02em; }
.fn-crit p { font-size: 0.9rem; line-height: 1.5; color: var(--steel); margin: 0; }

/* ============ C5 · STEP STRIP ============ */
.fn-steps { margin: 2.4rem 0; counter-reset: s; }
.fn-step { position: relative; padding-left: 3.1rem; padding-bottom: 1.5rem; counter-increment: s; }
.fn-step:last-child { padding-bottom: 0; }
.fn-step::before {
  content: counter(s); position: absolute; left: 0; top: 0; width: 2.05rem; height: 2.05rem;
  border-radius: 50%; background: var(--green); color: var(--white);
  font-family: var(--font-accent); font-weight: 700; font-size: 0.85rem;
  display: flex; align-items: center; justify-content: center;
}
.fn-step::after { content: ''; position: absolute; left: 1rem; top: 2.35rem; bottom: 0.2rem; width: 2px; background: linear-gradient(180deg, rgba(11,138,75,0.35), rgba(11,138,75,0.06)); }
.fn-step:last-child::after { display: none; }
.fn-step h4 { font-size: 1.02rem; margin: 0 0 0.35rem; padding-top: 0.22rem; font-family: var(--font-display); font-weight: 700; letter-spacing: -0.02em; }
.fn-step p { font-size: 0.97rem; line-height: 1.6; color: var(--steel); margin: 0; }

/* ============ C6 · SELF-AUDIT GRID ============ */
.fn-audit { margin: 2.4rem 0; display: grid; grid-template-columns: repeat(auto-fit, minmax(238px, 1fr)); gap: 0.8rem; }
.fn-audit-item { border: var(--hairline); border-left: 3px solid var(--green); border-radius: 0 13px 13px 0; padding: 0.95rem 1.05rem; background: var(--white); }
.fn-sec.alt .fn-audit-item { background: var(--white); }
.fn-audit-tag { font-family: var(--font-accent); font-size: 0.68rem; font-weight: 700; letter-spacing: 0.11em; text-transform: uppercase; color: var(--green); display: block; margin-bottom: 0.4rem; }
.fn-audit-item p { font-size: 0.95rem; line-height: 1.52; margin: 0; }
.fn-audit-item.measure { border-left-color: var(--violet); }
.fn-audit-item.measure .fn-audit-tag { color: var(--violet); }

/* ============ C7 · TIMELINE ============ */
.fn-timeline { margin: 2.6rem 0; border: var(--hairline); border-radius: 16px; padding: 1.5rem 1.4rem 1.2rem; background: var(--white); }
.fn-tl-title { font-family: var(--font-accent); font-size: 0.72rem; font-weight: 700; letter-spacing: 0.12em; text-transform: uppercase; color: var(--steel); margin: 0 0 1.2rem; }
.fn-tl-rail { position: relative; display: grid; gap: 0.6rem; }
.fn-tl-bar { grid-column: 1 / -1; position: relative; height: 8px; border-radius: 4px; background: rgba(22,32,46,0.07); margin-bottom: 1.05rem; overflow: hidden; }
.fn-tl-fill { position: absolute; left: 0; top: 0; bottom: 0; background: repeating-linear-gradient(135deg, rgba(180,83,9,0.22) 0 7px, rgba(180,83,9,0.10) 7px 14px); border-right: 2px solid var(--amber); }
.fn-tl-step { position: relative; padding-top: 0.2rem; }
.fn-tl-dot { width: 11px; height: 11px; border-radius: 50%; background: var(--steel); margin-bottom: 0.6rem; }
.fn-tl-step.end .fn-tl-dot { background: var(--violet); box-shadow: 0 0 0 4px rgba(109,40,217,0.14); }
.fn-tl-when { font-family: var(--font-accent); font-size: 0.76rem; font-weight: 700; color: var(--ink); display: block; margin-bottom: 0.28rem; }
.fn-tl-what { font-size: 0.9rem; line-height: 1.45; color: var(--steel); margin: 0; }
.fn-tl-step.end .fn-tl-what { color: var(--violet); font-weight: 600; }
.fn-tl-legend { margin-top: 1.1rem; padding-top: 0.85rem; border-top: var(--hairline); font-family: var(--font-accent); font-size: 0.78rem; color: var(--steel); display: flex; gap: 1.3rem; flex-wrap: wrap; }
.fn-tl-legend b { color: var(--amber); font-weight: 700; }
@media (max-width: 700px) {
  .fn-tl-rail { grid-template-columns: 1fr !important; gap: 1rem; }
  .fn-tl-bar { display: none; }
  .fn-tl-step { padding-left: 1.4rem; }
  .fn-tl-dot { position: absolute; left: 0; top: 0.45rem; margin: 0; }
}

/* ============ C9 · RECORD CALLOUT ============ */
.fn-record { margin: 2.3rem 0; border: 1px solid rgba(11,138,75,0.28); border-radius: 14px; overflow: hidden; background: var(--white); }
.fn-record-head { background: rgba(11,138,75,0.07); padding: 0.65rem 1.1rem; font-family: var(--font-accent); font-size: 0.72rem; font-weight: 700; letter-spacing: 0.11em; text-transform: uppercase; color: var(--green); }
.fn-record-body { padding: 1.1rem; }
.fn-record-line { font-family: var(--font-accent); font-size: 1.02rem; font-weight: 600; color: var(--ink); line-height: 1.5; margin: 0; }
.fn-record-vs { margin: 0.9rem 0 0; padding-top: 0.9rem; border-top: var(--hairline); font-size: 0.94rem; color: var(--steel); line-height: 1.6; }
.fn-record-vs del, .fn-record-vs s { color: var(--amber); }

/* ============ FIGURES (inline SVG) ============
   Two authored variants per diagram. A phone gets the .mobile.svg, which is
   drawn at phone proportions rather than scaled down — an 820-wide diagram in
   a 342px viewport renders 13px type at about 5px, which is not a diagram, it
   is a decoration. Where no mobile variant exists the wide one pans instead,
   reusing the .fn-table-scroll behaviour tables already have. */
.fn-figure { margin: 2.7rem 0; }
.fn-figure svg { display: block; width: 100%; height: auto; }
.fn-figcap { font-family: var(--font-accent); font-size: 0.8rem; line-height: 1.5; color: var(--steel); margin-top: 0.85rem; padding-left: 0.9rem; border-left: 2px solid rgba(11,138,75,0.35); }
.fn-fig-narrow { display: none; }
.fn-fig-pan { overflow-x: auto; -webkit-overflow-scrolling: touch; }
.fn-fig-pan svg { min-width: 620px; }
@media (max-width: 640px) {
  .fn-fig-wide { display: none; }
  .fn-fig-narrow { display: block; }
}

/* ---------------------------------------------------------------------
   SPECIFICITY GUARD.
   Every component above renders INSIDE .fn-body, which carries element-level
   rules for p, a and li (`.fn-body p { font-size: 1.09rem }` and friends).
   A single-class selector like `.fn-tl-what` is 0-1-0 and loses to `.fn-body p`
   at 0-1-1 no matter where it sits in the file — so the block components that
   use a bare <p> or <a> need the parent in the selector to win. Rules that are
   already 0-1-1 or higher (.fn-crit p, .fn-step p, .fn-vs-body li) are fine and
   are deliberately not repeated here.

   If you add a component that styles a bare p / a / li, add it to this block.
   --------------------------------------------------------------------- */
.fn-body .fn-stats-src { font-family: var(--font-accent); font-size: 0.74rem; line-height: 1.5; margin: 0.4rem 0 0; }
.fn-body .fn-stats-src a { color: var(--green); text-decoration: underline; }
.fn-body .fn-stats.on-ink .fn-stats-src a { color: var(--electric-green); }
.fn-body .fn-crit-group { font-size: 0.8rem; line-height: 1.4; margin: 0 0 0.9rem; }
.fn-body .fn-crit-group.second { margin-top: 1.9rem; }
.fn-body .fn-tl-title { font-size: 0.72rem; line-height: 1.5; margin: 0 0 1.2rem; }
.fn-body .fn-tl-what { font-size: 0.9rem; line-height: 1.45; margin: 0; }
.fn-body .fn-record-line { font-size: 1.02rem; line-height: 1.5; margin: 0; }
.fn-body .fn-record-vs { font-size: 0.94rem; line-height: 1.6; margin: 0.9rem 0 0; }
.fn-body .fn-audit-item p { font-size: 0.95rem; line-height: 1.52; margin: 0; }
@media (min-width: 1240px) {
  .fn-body .fn-rail-label { font-size: 0.68rem; line-height: 1.4; margin: 0 0 0.7rem 0.85rem; }
  .fn-body .fn-rail a { text-decoration: none; font-size: 0.8rem; color: var(--steel); }
  .fn-body .fn-rail a:hover { color: var(--ink); }
  .fn-body .fn-rail a.is-current { color: var(--green); }
}

/* =====================================================================
   INDEX + GLOSSARY PASS  (added 2026-08-04)
   =====================================================================
   Two surfaces, two jobs. The Insights index is a ROUTING page: its failure
   mode is seven near-identical cards where nothing says what to read first,
   so it gets the pillar diagram and grouped sections. The glossary is a
   SEARCH-LANDING REFERENCE page: its failure mode is being slow or unfound,
   not being plain, so it gets a definition block and a recognition cue and
   otherwise stays quiet. Do not "improve" the glossary by making it busier.
   ===================================================================== */

/* ============ FEATURE CARD — pillar diagram ============ */
.fn-feature { display: block; }                    /* was a 2-col grid with a bullet panel */
.fn-feature-head { max-width: 52rem; }
.fn-feature-fig {
  margin-top: clamp(1.4rem, 3vw, 2.1rem);
  padding-top: clamp(1.3rem, 3vw, 1.9rem);
  border-top: 1px solid rgba(22,32,46,0.1);
}
.fn-feature-fig svg { display: block; width: 100%; height: auto; }
.fn-feature-go { display: inline-block; margin-top: 1.1rem; }
/* The feature card is an <a>. Its figure must not eat the pointer or the whole
   card stops reading as one click target. */
.fn-feature-fig { pointer-events: none; }

/* Caption under the index's system diagram. Carries the registered
   `Deal Velocity System` name per the 4 Aug naming ruling — the name travels in
   the caption, never inside the SVG. Matches .fn-figcap on the article pages in
   everything but the left rule, which would fight the feature card's own
   border. */
.fn-feature-figcap {
  margin: 0.9rem 0 0;
  font-family: var(--font-accent); font-size: 0.78rem; line-height: 1.5;
  color: var(--steel);
}
.fn-feature-figcap strong { color: var(--ink); font-weight: 700; }

/* ============ PILLAR GROUPS ============ */
.fn-group { margin-bottom: clamp(2.4rem, 5vw, 3.4rem); }
.fn-group:last-of-type { margin-bottom: 0; }
.fn-group-head {
  display: flex; align-items: baseline; flex-wrap: wrap; gap: 0.35rem 0.9rem;
  padding-bottom: 0.9rem; margin-bottom: 1.4rem;
  border-bottom: 2px solid rgba(11,138,75,0.25);
}
.fn-group-n {
  font-family: var(--font-accent); font-weight: 700; font-size: 0.72rem;
  letter-spacing: 0.14em; color: var(--green);
}
.fn-group-title { font-size: clamp(1.25rem, 2.4vw, 1.55rem); letter-spacing: -0.025em; }
.fn-group-q { font-family: var(--font-accent); font-size: 0.88rem; color: var(--steel); }
@media (max-width: 560px) { .fn-group-q { flex-basis: 100%; } }

/* ============ GLOSSARY — definition block ============
   The dek IS the definition, and it is what the DefinedTerm schema publishes
   as `description`. Giving it a labelled block makes the visible page and the
   machine-readable claim the same object, which is the whole point. */
.gl-def {
  margin-top: 1.4rem; padding: 1.15rem 1.3rem;
  background: var(--mist); border-left: 3px solid var(--green); border-radius: 0 14px 14px 0;
}
.gl-def-label {
  display: block; font-family: var(--font-accent); font-weight: 700; font-size: 0.68rem;
  letter-spacing: 0.14em; text-transform: uppercase; color: var(--green); margin-bottom: 0.5rem;
}
.gl-def p { font-size: 1.06rem; line-height: 1.6; margin: 0; color: var(--ink); }
/* The original .gl-also is uppercase Sora — right for a small caps line under a
   standfirst, wrong here. These are the words a buyer actually types; setting
   them in caps makes them read as navigation and makes them harder to scan,
   which defeats the only job the line has. */
.gl-def .gl-also {
  margin: 0.75rem 0 0; padding-top: 0.7rem;
  border-top: 1px solid rgba(22,32,46,0.1);
  font-family: var(--font-display); font-weight: 400;
  font-size: 0.9rem; line-height: 1.5; letter-spacing: 0;
  text-transform: none; color: var(--steel);
}
.gl-def .gl-also strong {
  font-family: var(--font-accent); font-weight: 700; font-size: 0.72rem;
  letter-spacing: 0.11em; text-transform: uppercase; color: var(--green);
  display: block; margin-bottom: 0.3rem;
}

/* ============ GLOSSARY — card recognition cue ============ */
.gl-item-alt {
  margin-top: 0.6rem; font-family: var(--font-accent); font-size: 0.78rem;
  line-height: 1.45; color: var(--steel);
}
.gl-item-go { margin-top: auto; padding-top: 0.9rem; }

/* `.fn-grid-label` above is now unused — the pillar group heading replaced it.
   Left in place deliberately: it is one rule, and deleting a selector that a
   future index variant might want is not worth the diff. */

.fn-group-count {
  font-family: var(--font-accent); font-size: 0.76rem; color: var(--steel);
  margin-left: auto;
}
@media (max-width: 560px) { .fn-group-count { margin-left: 0; } }

/* ============ PILLAR TAG ON A CARD ============
   Added 2026-08-04 with the index rewrite. The index used to render one grid
   section per pillar; with three pillars holding a single essay each, that
   left two empty cells in every one of those rows and the page read as
   unfinished. The pillar now travels ON the card instead of ABOVE the grid, so
   the taxonomy survives at full density. See render_index() in
   build_insights.py for the reasoning and the threshold at which grouping is
   worth reinstating.

   Colour carries no new meaning and adds no token: the four pillars are
   distinguished by tint of the existing ink/green/navy/steel, not by a new
   palette. A tag is a wayfinding cue, not a status. */
.fn-tag {
  font-family: var(--font-accent); font-weight: 700; font-size: 0.62rem;
  letter-spacing: 0.12em; text-transform: uppercase;
  padding: 0.24rem 0.5rem; border-radius: 5px; white-space: nowrap;
  background: rgba(22,32,46,0.06); color: var(--steel);
}
.fn-tag-pursue      { background: rgba(11,138,75,0.10);  color: #0B8A4B; }
.fn-tag-respond     { background: rgba(38,49,94,0.10);   color: #26315E; }
.fn-tag-document    { background: rgba(22,32,46,0.075);  color: #16202E; }
.fn-tag-orchestrate { background: rgba(90,107,126,0.13); color: #47576A; }
.fn-item:hover .fn-tag { }

/* The meta row now leads with a tag rather than a date, so it needs its own
   alignment: the tag is a box and the date is text, and baseline-aligning the
   two makes the tag sit low. */
/* Tag on its own line, ALWAYS. As a row it sat beside the date on the two cards
   whose date+question happened to be short enough to fit, and above it on the
   other five — so the card titles started at two different heights across a
   row. A column costs one line of height and makes every card identical. */
.fn-grid .fn-meta {
  flex-direction: column; align-items: flex-start; gap: 0.4rem;
  min-height: 3.6rem;
}
/* The date+question span carries its own line-height because it can wrap to two
   lines inside a flex row that is otherwise single-line boxes. */
.fn-meta-line { line-height: 1.5; }
@media (max-width: 380px) { .fn-grid .fn-meta { min-height: 0; } }

/* ============================================================================
   FOUNDATION + DIAGNOSIS PAGES  (.fp-*)          added 2026-08-09, Rob's call
   ----------------------------------------------------------------------------
   Generated by build_pages.py. These are the five foundations and the Deal
   Velocity Diagnosis as real URLs — until this date all six existed only as JS
   modals and a homepage anchor, which meant none of them was indexable,
   linkable or sendable to a colleague.

   ADDITIVE ONLY. Every rule below is namespaced .fp-. Nothing in the Insights
   or Glossary cascade is touched, so an edge still serving a pre-9-Aug copy of
   this stylesheet renders those pages exactly as before — which is the whole
   reason the additions are namespaced rather than folded into .fn-body.
   ========================================================================== */
.fp-main { background: var(--white); }
.fp-head { padding: clamp(3rem, 7vw, 4.75rem) 0 clamp(1.5rem, 3vw, 2rem); }
.fp-head h1 { font-size: clamp(1.95rem, 4.4vw, 2.9rem); line-height: 1.08; max-width: 20ch; }
.fp-dek { margin-top: 1.15rem; font-size: clamp(1.02rem, 1.5vw, 1.16rem); color: var(--steel); line-height: 1.6; max-width: 54ch; }
.fp-service { margin-top: 1rem; font-family: var(--font-accent); font-size: 0.84rem; letter-spacing: 0.02em; color: var(--steel); }
.fp-service strong { color: var(--ink); font-weight: 700; }

.fp-body { padding-bottom: clamp(2.5rem, 5vw, 3.5rem); }
.fp-body p { margin: 0 0 1.35rem; font-size: 1.09rem; line-height: 1.72; color: var(--ink); }
.fp-body h2 {
  margin: 3.1rem 0 1.05rem; font-size: clamp(1.32rem, 2.3vw, 1.62rem);
  line-height: 1.22; letter-spacing: -0.018em; position: relative; padding-top: 1.1rem;
}
.fp-body h2::before {
  content: ''; position: absolute; top: 0; left: 0;
  width: 34px; height: 3px; border-radius: 2px; background: var(--green);
}
.fp-body a { color: var(--green); text-decoration: underline; text-underline-offset: 2px; }
.fp-body a:hover { color: var(--ink); }

/* The five-foundation route. A reader who lands here from search has no idea
   the other four exist; the homepage nav does not tell them either. */
.fp-sys { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem 0.75rem; padding: 0.9rem 1.1rem; margin-bottom: 0.5rem; background: var(--mist); border-radius: 12px; }
.fp-sys-label { font-family: var(--font-accent); font-weight: 800; font-size: 0.68rem; letter-spacing: 0.13em; text-transform: uppercase; color: var(--steel); margin-right: 0.25rem; }
.fp-sys-item { font-family: var(--font-accent); font-weight: 700; font-size: 0.82rem; color: var(--steel); text-decoration: none; }
a.fp-sys-item:hover { color: var(--green); }
.fp-sys-item.is-current { color: var(--ink); border-bottom: 2px solid var(--green); }

.fp-list { margin: 0 0 1.35rem; padding-left: 1.3rem; }
.fp-list li { margin-bottom: 0.7rem; font-size: 1.09rem; line-height: 1.68; color: var(--ink); }
.fp-list li::marker { color: var(--green); }
.fp-list-neg li::marker { color: var(--steel); }

/* "Done means" is the acceptance definition, verbatim from the delivery
   standard. It is boxed because it is the one paragraph on the page that is a
   contractual test rather than a description. */
.fp-done { background: var(--mist); border-left: 3px solid var(--green); border-radius: 8px; padding: 1rem 1.2rem; font-size: 1rem !important; line-height: 1.65 !important; margin-bottom: 1.35rem; }
.fp-honest { font-size: 0.99rem !important; line-height: 1.65 !important; color: var(--steel) !important; }
.fp-honest strong { color: var(--ink); }

.fp-price { background: var(--mist); border: 1px solid rgba(22,32,46,0.08); border-radius: 14px; padding: 1.2rem 1.35rem; margin-bottom: 1.35rem; }
.fp-price-line { margin: 0 0 0.5rem !important; font-size: 1.05rem !important; }
.fp-price-line strong { font-weight: 800; }
.fp-price-sub { margin: 0 !important; font-size: 0.93rem !important; line-height: 1.6 !important; color: var(--steel) !important; }

.fp-next { margin-top: 2.4rem !important; padding-top: 1.4rem; border-top: 1px solid rgba(22,32,46,0.1); font-size: 0.99rem !important; color: var(--steel) !important; }
.fp-next a { font-weight: 600; }

@media (max-width: 640px) {
  .fp-sys { gap: 0.4rem 0.6rem; }
  .fp-body p, .fp-list li { font-size: 1.03rem; }
}

/* ---- NEWSLETTER OPT-IN (2026-08-09) ------------------------------------
   The third rung in the closing block. Renders only when NEWSLETTER_WEBHOOK is
   set in build_insights.py; until then the markup is not emitted at all, so
   these rules are inert rather than styling a promise that isn't wired. Sits
   inside .fn-cta-band, which is dark, so everything here is on-navy. */
.fn-optin { margin-top: 2.4rem; padding-top: 1.9rem; border-top: 1px solid rgba(255,255,255,0.14); max-width: 46rem; margin-left: auto; margin-right: auto; }
.fn-optin-text { color: rgba(255,255,255,0.72); font-size: 0.95rem; line-height: 1.55; }
.fn-optin-text strong { display: block; color: var(--white); font-family: var(--font-accent); font-weight: 800; font-size: 1rem; margin-bottom: 0.3rem; }
.fn-optin-row { display: flex; flex-wrap: wrap; gap: 0.6rem; justify-content: center; margin-top: 1.1rem; }
.fn-optin-row input { flex: 1 1 18rem; max-width: 24rem; padding: 0.72rem 0.95rem; border-radius: 10px; border: 1px solid rgba(255,255,255,0.24); background: rgba(255,255,255,0.06); color: var(--white); font-size: 0.95rem; }
.fn-optin-row input::placeholder { color: rgba(255,255,255,0.42); }
.fn-optin-row input:focus-visible { outline: 2px solid var(--green); outline-offset: 2px; }
.fn-optin-row button { padding: 0.72rem 1.25rem; border: 0; border-radius: 10px; background: var(--green); color: var(--white); font-family: var(--font-accent); font-weight: 700; font-size: 0.9rem; cursor: pointer; }
.fn-optin-row button:hover { filter: brightness(1.08); }
.fn-optin-row button:disabled { opacity: 0.55; cursor: default; }
.fn-optin-msg { margin-top: 0.85rem; min-height: 1.2em; font-size: 0.9rem; color: rgba(255,255,255,0.78); }
