/* ============================================================
   Chief Perspective — design system
   Newsreader (display serif) + Archivo (body sans)
   Tokens per STYLE-GUIDE.md §2 — single source of truth.
   ============================================================ */

/* ------------------------------------------------------------ webfonts
   SELF-HOSTED, latin subset only. These are the exact files Google was serving
   (same bytes), fetched once and committed. The point is not size — it is that the
   page no longer blocks on a stylesheet from a second origin, and no longer hands
   every visitor's IP address to Google on every page load, which the privacy policy
   would otherwise have to keep disclosing.

   Variable fonts: one file covers the whole weight range per family and style, so
   the weight ranges below are declared rather than one @font-face per step.

   Newsreader and Archivo are both SIL Open Font License 1.1 — see
   dist/assets/fonts/OFL.txt. Self-hosting is permitted; selling the fonts is not.

   font-display: swap keeps text visible during the fetch. Cached for a year by the
   /assets/* rule in _headers. */
@font-face {
  font-family: 'Archivo';
  font-style: normal;
  font-weight: 400 700;
  font-stretch: 100%;
  font-display: swap;
  src: url(/assets/fonts/archivo-normal.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Newsreader';
  font-style: normal;
  font-weight: 300 600;
  font-display: swap;
  src: url(/assets/fonts/newsreader-normal.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: 'Newsreader';
  font-style: italic;
  font-weight: 300 500;
  font-display: swap;
  src: url(/assets/fonts/newsreader-italic.woff2) format('woff2');
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

:root {
  /* color */
  --ink: #101418;
  --ink-deep: #0b0d10;
  --ink-panel: #16181c;
  --ink-hairline: #2a2d33;
  --ink-border: #3a3d44;
  --green: #3f8a5a;
  --green-hover: #357a4e;
  --green-deep: #2f6a45;
  --green-bright: #4f9e6a;
  --green-light: #7fc79b;
  --green-pale: #e6f2ea;
  --green-wash: #f0f7f2;
  --body: #4a5560;
  --body-strong: #3a444c;
  /* Darkened 2 points from #6a747c so muted text clears WCAG AA 4.5:1 on the tinted
     grounds it actually sits on, not just on white: .calc-title sits on --surface
     (was 4.44:1, now 4.57) and .at-ends on --green-wash (was 4.38:1, now 4.51). */
  --faint: #68727a;
  --fainter: #8a949c;
  --on-dark-body: #9aa4ac;
  --on-dark-strong: #b7bec4;
  --surface: #f5f7f8;
  --surface-quiet: #fafbfb;
  --chip: #f0f3f4;
  --hairline: #e6e8ea;
  --rule: #d7dbde;
  /* Control boundaries need 3:1 (WCAG 1.4.11). #cfd6db was 1.47:1, which made
     .btn-secondary read as floating text and form fields as barely-there. This is
     3.09:1. --hairline and --rule keep the lighter values for decorative lines. */
  --border-input: #8a949c;
  --white: #ffffff;
  /* Semantic surface for cards/cells that sit on a tinted section. Several rules
     already referenced --paper while it was undefined, so their background silently
     computed to transparent (the trigger cells on the group pages rendered as one
     gray slab). Defining it here fixes every one of those call sites. */
  --paper: #ffffff;

  /* type scale (desktop → mobile via clamp) */
  /* --fs-display is the page-hero step. It was previously 33→64 and referenced by
     nothing: every hero carried its own bespoke clamp, so the home H1 (70.4px) and
     every other H1 (67.2px) disagreed for no reason. Redefined here to the value the
     heroes were actually using, and now referenced by .hero h1 and .hero-home h1. */
  /* Three steps sit above the title tier:
       display  the page hero H1
       h1       the "big statement" — a section whose heading IS its content
       h2       the standard section heading
     --fs-h1 was defined from the start and referenced by nothing. Seven rules
     hand-rolled their own clamp instead — three of them byte-identical — landing on
     42.88 / 44 / 48px for what was always meant to be one step. It is now that step. */
  --fs-display: clamp(2.6rem, 1.8rem + 3vw, 4.2rem);          /* 41.6 → 67.2 */
  --fs-h1: clamp(1.875rem, 1.45rem + 1.9vw, 3rem);            /* 30 → 48 */
  --fs-h2: clamp(1.625rem, 1.44rem + 0.83vw, 2.125rem);       /* 26 → 34 */
  --lh-display: 1.02;   --ls-display: -.025em;
  --lh-h1: 1.08;        --ls-h1: -.015em;
  --lh-h2: 1.1;         --ls-h2: -.015em;
  --fw-heading: 600;    /* the site's heading voice, hero down to section head */
  --fs-tagline: 1.25rem;                                      /* 20 — hero subhead */
  --fs-lede: clamp(1.0625rem, 1.01rem + 0.25vw, 1.125rem);    /* 17 → 18 — section lede */
  --lh-lede: 1.65;
  --ls-body: normal;    /* for headings restyled to the body voice (h2.grp-lede) */

  /* title scale — the block-title role that sits below a section heading: card titles,
     row titles, accordion titles, panel titles. Anchored on the old --fs-h3 (20→24),
     which stays the middle step, so the most common card title does not move. Weight
     and line-height track the tier so neither gets chosen ad hoc. Before this, 27 rules
     styled this one role at 11 sizes between 15.5px and 30px, in 3 weights.
     Each step scales the same way the old --fs-h3 did — a flat px title would not
     shrink on a phone, which is the bug that caught .leader-grid h2. */
  --fs-title-lg: clamp(1.5rem, 1.371rem + 0.5525vw, 1.8125rem);  /* 24 → 29 */
  --fs-title:    clamp(1.25rem, 1.19rem + 0.42vw, 1.5rem);       /* 20 → 24 */
  --fs-title-sm: clamp(1.125rem, 1.07rem + 0.23vw, 1.25rem);     /* 18 → 20 */
  --lh-title-lg: 1.12;
  --lh-title:    1.2;
  --lh-title-sm: 1.25;
  --fw-title-lg: 600;   /* leads a whole block */
  --fw-title:    500;   /* everything below that — the site's card-title voice */
  --fs-body-lg: clamp(1rem, 0.97rem + 0.21vw, 1.125rem);      /* 16 → 18 */
  --fs-body: clamp(0.9375rem, 0.92rem + 0.1vw, 1rem);         /* 15 → 16 */
  --fs-small: clamp(0.8125rem, 0.8rem + 0.1vw, 0.875rem);     /* 13 → 14 */

  /* label scale — one visual role (the small uppercase label) at three sizes.
     Tracking RISES as size falls: small uppercase text loses the word-shape a reader
     relies on, and letterspacing is the compensation. The ladder is anchored on the
     old .kicker values (12px/600/.14em) so the most-used label on the site does not
     move; every other label converges onto it. Before this existed, 28 rules styled
     this one role in 7 sizes, 3 weights and 17 different letter-spacings. */
  --fs-label-lg: 13px;   --ls-label-lg: .12em;   /* a label doing a heading's job */
  --fs-label:    12px;   --ls-label:    .14em;   /* the default — section eyebrows */
  --fs-label-sm: 11px;   --ls-label-sm: .16em;   /* metadata inside dense components */
  --fw-label:    600;

  /* label color by meaning, not by mood */
  /* --green is 4.20:1 on white — fine for a fill or a rule, short of the 4.5:1 text
     bar. Labels are 11–12px, so they take --green-deep (6.43:1). Keep --green for
     ticks, borders, icons and outlines, where the bar is 3:1. */
  --label-accent:    var(--green-deep);   /* names the thing below it */
  --label-accent-dk: var(--green-light);  /* the same role, on an ink ground */
  --label-link:      var(--green-deep);   /* it goes somewhere when clicked */
  --label-muted:     var(--faint);        /* it describes, it does not navigate */

  /* spacing */
  --section-y: 80px;
  --hero-y: 96px;
  --gutter: 60px;

  /* Height of the sticky .site-header. Anchor targets offset themselves by this so
     an in-page jump (#contact from the nav, #capabilities, the skip link) does not
     land the section underneath the header — which was clipping the contact heading
     in half. Grows below 960px, where the nav swaps to the 44px toggle button. */
  --header-h: 76px;

  /* --------------------------------------------------------------- spacing --
     STYLE-GUIDE.md §4. Added so new work has a ladder to reach for; the existing
     literals are recorded on the ratchet in build/css-baseline.txt and migrate
     opportunistically rather than in one risky sweep. */
  --space-1: 4px;   --space-2: 8px;   --space-3: 12px;  --space-4: 16px;
  --space-5: 24px;  --space-6: 32px;  --space-7: 44px;  --space-8: 64px;
  --space-9: 88px;

  /* ---------------------------------------------------------------- radius --
     The system is square and as of 2026-08 nothing at all breaks that: the round
     tick mark (.lticks .tk) retired with the buyers/sellers cards, so
     --radius-circle currently has no consumers. It stays defined as the one
     sanctioned circle primitive. check_css.py ratchets any new literal, so a
     rounded corner cannot reappear without a deliberate decision. */
  --radius-0: 0;
  --radius-circle: 50%;

  /* ------------------------------------------------------------ breakpoints --
     Documented for reference — custom properties cannot be used in media queries.
     Sanctioned widths: 560 (phone), 860 (tablet, the main collapse), 1000
     (editorial grids), 1040 (nav), 1240 (container cap). build/check_css.py
     ratchets anything else. */


  /* misc */
  --shadow-card: 0 10px 28px rgba(16, 20, 24, .08);
  --shadow-menu: 0 16px 40px rgba(16, 20, 24, .10);
  --ease: cubic-bezier(.22, .61, .36, 1);
  --serif: 'Newsreader', Georgia, serif;
  --sans: 'Archivo', 'Helvetica Neue', Arial, sans-serif;
}

@media (max-width: 1039px) {
  :root { --header-h: 81px; }   /* .nav-toggle is 44px tall, so the bar grows */
}
@media (max-width: 860px) {
  :root {
    --section-y: 48px;
    --hero-y: 56px;
    --gutter: 22px;
  }
}
@media (max-width: 560px) {
  :root { --gutter: 16px; }
}

/* ------------------------------------------------------------ base */
* { margin: 0; padding: 0; box-sizing: border-box; }
@media (prefers-reduced-motion: no-preference) { html { scroll-behavior: smooth; } }
/* Every scroll target clears the sticky header. Applied to [id] rather than a list
   of section ids so a new anchor never has to remember to opt in; it also keeps a
   focused form field from landing behind the header. */
[id] { scroll-margin-top: var(--header-h); }
body {
  font-family: var(--sans);
  font-size: var(--fs-body);
  color: var(--ink);
  background: var(--white);
  -webkit-font-smoothing: antialiased;
  line-height: 1.6;
}
img { display: block; max-width: 100%; }
/* <picture> is only a wrapper for the WebP <source>; it must not become a box, or
   rules like .hero-home-bg img { height: 100% } would resolve against it and
   collapse. display:contents removes it from the box tree entirely. */
picture { display: contents; }
/* display:contents makes the <source> a direct child of whatever holds the
   <picture> — and UA stylesheets do not hide <source>, they just skip it in
   normal flow. Inside a grid it therefore became a real (empty) grid item and
   claimed the first cell of .leader-grid, pushing the portrait into the text
   column. It is metadata, never a box: hide it outright. */
source { display: none; }
a { color: inherit; text-decoration: none; }
a:focus-visible, button:focus-visible, input:focus-visible,
textarea:focus-visible, select:focus-visible, summary:focus-visible {
  outline: 2px solid var(--green);
  outline-offset: 2px;
}
.wrap { max-width: 1240px; margin: 0 auto; padding-left: var(--gutter); padding-right: var(--gutter); }
.skip-link {
  position: absolute; left: -9999px; top: 0; z-index: 100;
  background: var(--ink); color: #fff; padding: 10px 18px; font-size: 14px; font-weight: 600;
}
.skip-link:focus { left: 0; }

/* ------------------------------------------------------------ type */
h1, h2, h3, h4 { font-family: var(--serif); letter-spacing: -.01em; text-wrap: pretty; }
.kicker {
  font-family: var(--sans);
  font-size: var(--fs-label);
  font-weight: var(--fw-label);
  letter-spacing: var(--ls-label);
  text-transform: uppercase;
  color: var(--label-accent);
}
.dark .kicker, .kicker.on-dark { color: var(--label-accent-dk); }
/* Green text runs at --green-deep for contrast; the hover lightens to --green-hover
   (5.19:1) rather than darkening further, which keeps a visible state change without
   dropping below the text bar. Same pattern on .article a and .article-hero .back. */
.tlink { color: var(--green-deep); font-size: var(--fs-small); font-weight: 600; }
.tlink:hover { color: var(--green-hover); }

/* ------------------------------------------------------------ buttons (§2, unified) */
.btn {
  display: inline-block;
  font-family: var(--sans);
  font-size: 14px;
  font-weight: 600;
  letter-spacing: .03em;
  line-height: 1.2;
  padding: 15px 30px;
  border: 0;
  cursor: pointer;
  white-space: nowrap;
  transition: background-color .18s var(--ease), border-color .18s var(--ease), color .18s var(--ease);
}
/* WHITE TEXT NEEDS 4.5:1, AND --green IS 4.20:1. The note at :91 already says
   --green is a fill-and-rule color, not a text color — but a fill *behind white
   text* is the same problem, and these rules were the call sites that slipped
   through. Resting is now --green-hover (5.19:1) and hover darkens to --green-deep
   (6.43:1). Both clear AA at .btn's 14px/600, which is not "large text".
   Do not put --green or --green-bright behind white type. */
.btn-primary { background: var(--green-hover); color: #fff; }
.btn-primary:hover { background: var(--green-deep); }
.btn-secondary { background: transparent; border: 1px solid var(--border-input); color: var(--ink); padding: 14px 29px; }
.btn-secondary:hover { border-color: var(--green); color: var(--green-deep); }
.btn-ink { background: var(--ink); color: #fff; }
.btn-ink:hover { background: var(--green-hover); }
/* --green-bright is 3.27:1 under white — the worst of the three. Dark sections get
   the same darken-on-hover as everywhere else rather than their own lighter one. */
.dark .btn-primary:hover { background: var(--green-deep); }
.dark .btn-secondary { border-color: var(--ink-border); color: var(--white); }
.dark .btn-secondary:hover { border-color: var(--green-light); color: var(--green-light); }

/* ------------------------------------------------------------ header / nav */
.site-header {
  position: sticky; top: 0; z-index: 50;
  background: rgba(255, 255, 255, .92);
  -webkit-backdrop-filter: blur(8px);
  backdrop-filter: blur(8px);
  border-bottom: 1px solid var(--hairline);
}
.nav {
  display: flex; align-items: center; justify-content: space-between; gap: 32px;
  padding-top: 18px; padding-bottom: 18px;
}
/* flex:none — without it the nav's flex layout shrank the wordmark below its
   intrinsic width: measured 148x26 against a correct 217x26 at a 961px viewport. */
/* flex:none goes on .brand, the flex item. It was on the <img>, which does nothing:
   the anchor shrank and the img followed it down via the global max-width:100%.
   Measured 149x26 at a 961px viewport against a correct 217x26 — a 31% horizontal
   crush of the wordmark. The nav needs ~1014px, so the breakpoint moves with it;
   pinning the logo without that would trade squashing for overflow. */
.brand { flex: none; }
.brand img { height: 26px; width: auto; }
.nav-links {
  display: flex; align-items: center; gap: 30px;
  list-style: none;
  font-size: 14px; font-weight: 500; color: var(--body-strong);
}
.nav-links > li > a { display: block; padding: 8px 0; }
.nav-links > li > a:hover { color: var(--green-deep); }
/* "You are here" — shell() stamps aria-current="page" on the matching link.
   Color plus an underline, so the state survives color-blindness and
   forced-colors alike. */
.nav-links a[aria-current="page"] {
  color: var(--green-deep);
  text-decoration: underline; text-decoration-thickness: 2px;
  text-decoration-color: var(--green); text-underline-offset: 8px;
}
/* Current page in a dropdown: underline + color only (inherited from the
   .nav-links rule above). The green-pale background is reserved for :hover, so
   the pointer state and the you-are-here state stay visually distinct. */
.dropdown-menu a[aria-current="page"] { color: var(--green-deep); }
.navtop {
  font: inherit; color: inherit; background: none; border: 0; cursor: pointer;
  padding: 8px 0; white-space: nowrap; display: flex; align-items: center; gap: 6px;
}
.navtop:hover { color: var(--green-deep); }
.navtop .caret { font-size: 10px; color: var(--on-dark-body); transition: transform .18s var(--ease); }
.dropdown { position: relative; }
.dropdown-menu {
  display: none;
  position: absolute; top: 100%; left: -16px; padding-top: 10px; min-width: 280px;
}
.dropdown-menu-inner { background: #fff; border: 1px solid var(--hairline); box-shadow: var(--shadow-menu); padding: 8px; }
.dropdown-menu a { display: block; padding: 11px 14px; font-size: 14px; }
.dropdown-menu a:hover, .dropdown-menu a:focus-visible { background: var(--green-pale); color: var(--green-deep); }
/* Lead row of each services dropdown: the route to the group landing page. The
   top-level trigger is a <button> (it has to open the menu on touch), so this is
   the only way into /transaction-services/ and /cfo-services/ from the nav. */
.dd-overview { border-bottom: 1px solid var(--hairline); margin-bottom: 6px; padding-bottom: 12px; }
.dropdown.open .dropdown-menu { display: block; }
.dropdown.open .caret { transform: rotate(180deg); }
.nav-cta { font-size: 13px; padding: 12px 24px; }
.nav-toggle {
  display: none;
  background: none; border: 0; cursor: pointer; padding: 10px;
  width: 44px; height: 44px; position: relative;
}
.nav-toggle span {
  display: block; width: 22px; height: 2px; background: var(--ink); margin: 0 auto;
  transition: transform .22s var(--ease), opacity .18s var(--ease);
}
.nav-toggle span + span { margin-top: 5px; }
.nav-open .nav-toggle span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.nav-open .nav-toggle span:nth-child(2) { opacity: 0; }
.nav-open .nav-toggle span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

/* Desktop dropdowns open from JS only — see main.js. They used to open on :hover
   and :focus-within while aria-expanded was written solely by the click handler, so
   the two disagreed in both directions: tabbing to a trigger opened the menu while
   still announcing "collapsed", and clicking set it "false" while CSS kept it open.
   One code path now owns the class and the attribute together. */
@media (min-width: 1040px) {
  .dropdown.open .dropdown-menu { display: block; }
}

/* mobile nav */
@media (max-width: 1039px) {
  .nav { gap: 16px; }
  .nav-toggle { display: block; }
  .nav-cta { display: none; }
  .nav-links {
    display: none;
    position: absolute; top: 100%; left: 0; right: 0;
    flex-direction: column; align-items: stretch; gap: 0;
    background: #fff; border-bottom: 1px solid var(--hairline);
    box-shadow: var(--shadow-menu);
    padding: 10px var(--gutter) 22px;
    max-height: calc(100dvh - var(--header-h)); overflow-y: auto;
  }
  .nav-open .nav-links { display: flex; }
  .nav-links > li { border-bottom: 1px solid var(--hairline); }
  .nav-links > li:last-child { border-bottom: 0; }
  .nav-links > li > a, .navtop { width: 100%; padding: 15px 0; font-size: 15px; }
  .navtop { justify-content: space-between; }
  .dropdown-menu { position: static; padding: 0 0 8px; min-width: 0; }
  .dropdown-menu-inner { border: 0; box-shadow: none; padding: 0 0 0 14px; }
  .dropdown-menu a { padding: 11px 10px; }
  .nav-links .nav-cta-mobile { border-bottom: 0; padding-top: 16px; }
  .nav-links .nav-cta-mobile .btn { display: block; text-align: center; }
}
@media (min-width: 1040px) {
  .nav-cta-mobile { display: none; }
}

/* ------------------------------------------------------------ sections */
.section { padding-top: var(--section-y); padding-bottom: var(--section-y); }
.soft { background: var(--surface); }
.pale { background: var(--green-wash); }
.dark { background: var(--ink); color: #fff; }
.dark h1, .dark h2, .dark h3, .dark h4 { color: #fff; }
.bordered-top { border-top: 1px solid var(--hairline); }
.bordered-bottom { border-bottom: 1px solid var(--hairline); }

.section-head { margin-bottom: 44px; }
.section-head .kicker { display: block; margin-bottom: 18px; }
.section-head h2 { font-weight: var(--fw-heading); font-size: var(--fs-h2); line-height: var(--lh-h2); letter-spacing: var(--ls-h2); max-width: 760px; }
.section-head.row { display: flex; justify-content: space-between; align-items: flex-end; gap: 24px; flex-wrap: wrap; }
.section-head.ruled { border-bottom: 1px solid var(--rule); padding-bottom: 24px; }

/* The intro paragraph that sits under a heading and above the content. One role,
   previously styled seven ways at four sizes and five line-heights — the leading
   variation mattered more than the size, since 1.6 and 1.65 at the same 18px make
   visibly different paragraph blocks side by side. */
.lede { font-size: var(--fs-lede); line-height: var(--lh-lede); color: var(--body); max-width: 72ch; margin-top: 18px; }

/* ------------------------------------------------------------ grids */
/* Removed: the generic .grid / .cols-2 / .cols-3 / .cols-4 utility system. It went
   unused when the card components it laid out were dropped — every live grid on the
   site now declares its own columns (.prac-grid, .twoup, .threeup, .spot, .quote-grid,
   .stat-row). The whole system was emitted on zero pages, not just .cols-4. */

/* Removed in 1.2.1.9: .card / .card-pad-lg / .card-quiet (the two documented card
   types), .ticks, and .panel-grid. The generator stopped emitting all of them in
   1.0.5.1.3–1.0.5.2.2 and none has appeared in the built HTML since. Note that
   .tick-list (still live) and .lticks (retired 2026-08 with the buyers/sellers
   cards) were different components — do not conflate them in git archaeology. */

/* chips */
.chip-row { display: flex; flex-wrap: wrap; gap: 12px; }
.chip {
  font-size: 13px; font-weight: 500; color: var(--body);
  background: var(--chip); padding: 10px 18px;
  transition: background-color .15s var(--ease), color .15s var(--ease);
  border: 0; cursor: pointer; font-family: var(--sans);
}
.chip:hover { background: var(--green-pale); color: var(--green-deep); }

/* ------------------------------------------------------------ heroes */
.hero { padding-top: var(--hero-y); padding-bottom: 88px; }
.hero .kicker { display: block; margin-bottom: 26px; }
/* Offering heroes render the kicker as a breadcrumb trail (group | page) — the
   visible counterpart of the BreadcrumbList JSON-LD those pages already emit.
   Only the group half is a link; hover underlines it so that is discoverable. */
.crumbs a:hover { text-decoration: underline; text-underline-offset: 4px; }
.crumbs .crumb-sep { margin: 0 12px; opacity: .45; }
.hero h1 { font-weight: var(--fw-heading); font-size: var(--fs-display); line-height: var(--lh-display); letter-spacing: var(--ls-display); max-width: 900px; }
.hero .tagline { font-size: var(--fs-tagline); line-height: 1.6; color: var(--on-dark-strong); max-width: 620px; margin-top: 28px; }
.hero .cta-row { display: flex; gap: 14px; margin-top: 42px; flex-wrap: wrap; }
.hero.light .tagline { color: var(--body); }
@media (max-width: 860px) { .hero { padding-bottom: 56px; } }

/* home hero — full-bleed skyline image blended behind the copy */
.hero-home { position: relative; isolation: isolate; overflow: hidden; background: var(--surface); }

/* Layer 1: the photograph. Partly desaturated so its blue does not compete with
   the green accents. object-position keeps the figure at the right edge. */
.hero-home-bg { position: absolute; inset: 0; z-index: -3; background: #eef1f3; }
.hero-home-bg img {
  width: 100%; height: 100%; object-fit: cover; object-position: 88% 58%;
  filter: grayscale(.45) contrast(1.02) brightness(1.03);
  opacity: .92;
}

/* Layer 2: the readability scrim — heavy --surface on the left under the type,
   fading to fully transparent on the right so the figure is untouched. */
.hero-home-scrim {
  position: absolute; inset: 0; z-index: -2;
  background: linear-gradient(100deg,
    rgba(245, 247, 248, .90) 0%,
    rgba(245, 247, 248, .78) 34%,
    rgba(245, 247, 248, .44) 60%,
    rgba(245, 247, 248, .14) 84%,
    rgba(245, 247, 248, 0) 100%);
}

/* Layer 3: softens the top edge under the sticky nav and seats the bottom edge. */
.hero-home-vignette {
  position: absolute; inset: 0; z-index: -1;
  background: linear-gradient(180deg,
    rgba(245, 247, 248, .42) 0%,
    rgba(245, 247, 248, 0) 34%,
    rgba(16, 20, 24, .05) 100%);
}

.hero-home-copy { position: relative; padding-top: 132px; padding-bottom: 124px; }
.hero-home-chip {
  display: inline-block;
  font-size: var(--fs-label); font-weight: var(--fw-label); letter-spacing: var(--ls-label);
  text-transform: uppercase; color: var(--label-accent);
  background: rgba(255, 255, 255, .82);         /* was --green-pale; now sits on the photo */
  padding: 7px 14px; margin-bottom: 30px;
}
.hero-home h1 {
  font-weight: var(--fw-heading); font-size: var(--fs-display);
  line-height: var(--lh-display); letter-spacing: var(--ls-display);
  max-width: 16ch;                              /* keeps the headline clear of the figure */
}
.hero-home .sub { font-size: var(--fs-tagline); line-height: 1.65; color: var(--body-strong); max-width: 520px; margin-top: 26px; }
.hero-home .cta-row { display: flex; gap: 14px; margin-top: 38px; flex-wrap: wrap; }
.hero-home .btn { white-space: nowrap; }
/* the secondary CTA now sits on the image, so it needs its own ground */
.hero-home .btn-secondary { background: rgba(255, 255, 255, .55); border-color: var(--green); color: var(--green-deep); }

@media (max-width: 860px) {
  .hero-home-copy { padding-top: 72px; padding-bottom: 64px; }
  .hero-home h1 { max-width: none; }
  /* the copy occupies most of the frame on a phone, so the scrim goes near-solid.
     The figure stands at ~72% of the image's width, and object-position moves the
     crop WINDOW, not the subject: 96% framed the window on the image's right edge
     and dropped the figure at the left of a narrow phone slice. Anchoring the
     window at the figure's own x instead lands him at the right of the frame. */
  .hero-home-bg img { object-position: 72% 58%; }
  .hero-home-scrim {
    background: linear-gradient(160deg,
      rgba(245, 247, 248, .95) 0%,
      rgba(245, 247, 248, .88) 55%,
      rgba(245, 247, 248, .55) 100%);
  }
}

/* Removed in 1.2.1.9: the FAQ component (.faq-grid / .faq-list / .faq and children).
   The generator stopped emitting it in 1.0.5.1.9 and the removal was complete — no
   FAQ entries remain in data.py and no FAQPage structured data is emitted — so only
   the stylesheet was left behind. */

/* ------------------------------------------------------------ forms */
.contact h2 { font-weight: var(--fw-heading); font-size: var(--fs-h1); line-height: var(--lh-h1); letter-spacing: var(--ls-h1); margin-bottom: 12px; }
.contact .contact-sub { font-size: var(--fs-lede); line-height: var(--lh-lede); color: var(--body); max-width: 600px; margin-bottom: 32px; }
.form { max-width: 660px; display: grid; gap: 16px; }
.form .row { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
.form label { font-size: 13px; font-weight: 600; display: block; margin-bottom: 6px; }
.form label .opt { font-weight: 400; color: var(--faint); }
.form input, .form textarea, .form select {
  width: 100%; padding: 13px 14px;
  border: 1px solid var(--border-input);
  font-family: var(--sans); font-size: 15px; background: #fff; color: var(--ink);
  border-radius: 0;
}
.form input:focus-visible, .form textarea:focus-visible, .form select:focus-visible {
  outline: 2px solid var(--green); outline-offset: 0; border-color: var(--green);
}
.form textarea { resize: vertical; }
.form .fine { font-size: 12px; line-height: 1.5; color: var(--faint); }
/* The privacy link under every submit button. It inherits --faint from .fine, so
   without this it is the same color as the sentence around it and carries no
   underline — indistinguishable from plain text, which is a link nobody can find
   (and 1.4.1, since nothing but color would have marked it even if it differed).
   --green-deep is the site's link color and clears 4.5:1 on both grounds this
   sits on; the underline is what actually identifies it. */
.form .fine a { color: var(--green-deep); text-decoration: underline; }
@media (max-width: 560px) { .form .row { grid-template-columns: 1fr; } }

/* ------------------------------------------------------------ posts */
/* Removed in 1.2.1.9: .post-card and children — the generator stopped emitting the
   insights card in 1.1.1.7. Its `.post-card .cat` selector is dropped from the
   shared rule below; .post-row (the /blog/all/ index) is still live. */

/* The article category label. Previously styled in three separate places at two
   different sizes (12px/.06em on the cards and index rows, 11px/.10em in the related
   strips), plus .cat-kicker as a byte-identical duplicate of the latter under another
   name. One rule now, on the label-sm tier — it is metadata inside a dense component,
   not a peer of the section eyebrow. */
.post-row .cat, .related-rows .cat, .cat-kicker {
  font-size: var(--fs-label-sm); font-weight: var(--fw-label);
  letter-spacing: var(--ls-label-sm); text-transform: uppercase; color: var(--label-accent);
}

.post-index { border-top: 1px solid var(--hairline); }
.post-row {
  display: grid; grid-template-columns: 220px 1fr auto; gap: 28px; align-items: center;
  padding: 24px 0; border-bottom: 1px solid var(--hairline);
}
.post-row:hover { background: var(--surface-quiet); }
.post-row h2 { font-weight: var(--fw-title); font-size: var(--fs-title-sm); line-height: var(--lh-title-sm); }
.post-row .more { font-size: 14px; font-weight: 600; color: var(--body); }
@media (max-width: 860px) {
  .post-row { grid-template-columns: 1fr; gap: 8px; }
  .post-row .more { display: none; }
}

/* ------------------------------------------------------------ article */
.article-hero { padding-top: var(--space-8); padding-bottom: var(--space-7); }
.article-hero .back { font-size: 13px; font-weight: 600; color: var(--green-deep); }
.article-hero .back:hover { color: var(--green-hover); }
.article-hero .kicker { display: block; margin: 28px 0 16px; }
/* The article kicker is a link to the category-filtered index; hover makes that
   discoverable without changing the label's resting look. */
.article-hero a.kicker { width: fit-content; }
.article-hero a.kicker:hover { color: var(--green-deep); text-decoration: underline; }
.article-hero h1 { font-weight: var(--fw-heading); font-size: var(--fs-h1); line-height: var(--lh-h1); letter-spacing: var(--ls-h1); max-width: 860px; }
.article-hero .byline { font-size: 14px; color: var(--faint); margin-top: 18px; }

.article-body-wrap { display: grid; grid-template-columns: minmax(0, 760px); justify-content: center; padding-top: var(--space-8); padding-bottom: var(--space-8); }
.article-lead-img { width: 100%; height: 320px; object-fit: cover; margin-bottom: 40px; }
.article { font-size: 16px; line-height: 1.75; color: var(--body-strong); }
.article p { margin: 0 0 18px; }
.article h2 { font-weight: 500; font-size: 28px; letter-spacing: -.01em; margin: 40px 0 16px; color: var(--ink); }
.article h3 { font-weight: 500; font-size: 21px; margin: 28px 0 12px; color: var(--ink); }
.article ul, .article ol { margin: 0 0 18px; padding-left: 22px; }
.article li { margin-bottom: 8px; line-height: 1.7; }
.article a { color: var(--green-deep); text-decoration: underline; }
.article a:hover { color: var(--green-hover); }
.article strong { color: var(--ink); }
/* 2026-08 corpus modules: pull quote, boxed self-assessment, CTA line, FAQ block.
   Typography via tokens only — the check_css ratchet rejects new literal sizes. */
.article blockquote.pull {
  margin: 40px 0; padding: 4px 0 4px 26px; border-left: 3px solid var(--green);
}
.article blockquote.pull p {
  margin: 0; font-family: var(--serif); font-style: italic; font-size: var(--fs-title-lg);
  line-height: var(--lh-title-lg); color: var(--ink);
}
.article .article-box {
  margin: 40px 0; padding: 26px 30px; background: var(--surface);
  border: 1px solid var(--hairline);
}
.article .article-box h3 { margin-top: 0; }
.article .article-box ol:last-child, .article .article-box ul:last-child,
.article .article-box p:last-child { margin-bottom: 0; }
.article .article-box li { margin-bottom: 12px; }
.article .article-cta {
  margin: 40px 0 0; padding-top: 26px; border-top: 1px solid var(--hairline);
  color: var(--body);
}
/* The FAQ is a coda, not a section of the argument: its header drops to the
   label voice and its questions to bold body text, so four stacked Q&As never
   outweigh the article prose above them. Semantics stay h2/h3 for the outline. */
.article .article-faq { margin-top: 16px; border-top: 1px solid var(--hairline); padding-top: 28px; }
.article .article-faq h2 {
  font-family: inherit; font-size: var(--fs-label); font-weight: var(--fw-label);
  letter-spacing: var(--ls-label); text-transform: uppercase;
  color: var(--faint); margin: 0 0 6px;
}
.article .article-faq h3.faq-q {
  font-family: inherit; font-size: var(--fs-body); font-weight: var(--fw-label);
  color: var(--ink); margin: 22px 0 6px;
}
.article .article-faq p { color: var(--body); }
.article figure.chart { margin: 36px 0; }
/* CHARTS SCROLL, THEY DO NOT SHRINK. The SVGs carry a fixed 760px viewBox with
   font-size baked into the markup, so `width:100%` scaled the type down with
   everything else: measured 5.2px labels at a 375px viewport and 4.4px at 320px,
   i.e. unreadable on the device most article traffic arrives on. Below 520px the
   chart now overflows its own scroll container instead. tabindex="0" on that
   container is what lets a keyboard user reach the right-hand side (SC 2.1.1).
   .chart.data tables ride the same wrapper now — _table() in generate.py emits
   it, which is why the figure itself no longer carries overflow-x. */
.article figure.chart .chart-scroll { overflow-x: auto; }
.article figure.chart .chart-scroll:focus-visible { outline: 2px solid var(--green); outline-offset: 2px; }
/* 600px is a compromise, not a cure. It puts the smallest label at ~9px on a phone
   (was 5.2px) for about two screens of horizontal scroll. Raising it further trades
   scroll for size; the honest fix is a narrower viewBox with its own type scale
   below 600px, which means regenerating chart geometry per breakpoint. */
.article figure.chart svg { width: 100%; min-width: 600px; height: auto; display: block; }
.article figure.chart figcaption {
  font-size: 13px; line-height: 1.55; color: var(--faint);
  margin-top: 14px; padding-top: 12px; border-top: 1px solid var(--hairline);
}
.article figure.chart figcaption strong { color: var(--ink); }

/* calculation callout — an "example of the math" figure */
.calc-box {
  background: var(--surface); border: 1px solid var(--hairline);
  border-left: 3px solid var(--green); padding: 22px 26px;
}
.calc-title {
  font-size: var(--fs-label); font-weight: var(--fw-label); letter-spacing: var(--ls-label);
  text-transform: uppercase; color: var(--label-muted); margin: 0 0 14px;
}
.calc-rows { width: 100%; border-collapse: collapse; font-variant-numeric: tabular-nums; }
.calc-rows td { padding: 7px 0; font-size: 15px; line-height: 1.4; }
.calc-l { color: var(--ink); }
.calc-v { text-align: right; font-weight: 600; color: var(--ink); white-space: nowrap; padding-left: 24px; }
.calc-op .calc-l { color: var(--faint); padding-left: 16px; }
.calc-op .calc-v { color: var(--faint); }
.calc-total td { border-top: 1.5px solid var(--ink); padding-top: 12px; font-size: 16px; }
.calc-total .calc-l { font-weight: 600; }
.calc-total .calc-v { color: var(--green-deep); }
@media (max-width: 560px) {
  .calc-box { padding: 18px 18px; }
  .calc-rows td { font-size: 14px; }
}

/* data table figure — a table when a table says it better than a chart.
   Scrolling lives on the inner .chart-scroll (focusable), not the figure. */
.article figure.chart.data .data-table {
  width: 100%; border-collapse: collapse; font-size: 14.5px;
  font-variant-numeric: tabular-nums;
}
.article .data-table th {
  font-size: var(--fs-label-sm); text-transform: uppercase; letter-spacing: var(--ls-label-sm);
  color: var(--label-muted); font-weight: var(--fw-label); padding: 0 16px 10px;
  border-bottom: 1px solid var(--ink); white-space: nowrap;
}
.article .data-table td {
  padding: 11px 16px; border-bottom: 1px solid var(--hairline);
  color: var(--ink); line-height: 1.45;
}
.article .data-table th:first-child, .article .data-table td:first-child { padding-left: 0; }
.article .data-table th:last-child, .article .data-table td:last-child { padding-right: 0; }
.article .data-table tbody tr:last-child td { border-bottom: 0; }
.article .data-table .t-total td {
  border-top: 1.5px solid var(--ink); border-bottom: 0;
  font-weight: 600; padding-top: 12px;
}
.article .data-table .t-total td:last-child { color: var(--green-deep); }
.article .data-table .ta-l { text-align: left; }
.article .data-table .ta-r { text-align: right; }
.article .data-table .ta-c { text-align: center; }

/* ------------------------------------------------------------ footer */
.site-footer { background: var(--ink); color: var(--on-dark-body); border-top: 3px solid var(--green); }
.footer-grid {
  display: grid; grid-template-columns: 1.4fr 1fr 1fr 1fr; gap: 40px;
  padding-top: var(--space-8); padding-bottom: var(--space-8);
}
.footer-grid .brand-col img { height: 24px; width: auto; margin-bottom: 18px; }
.footer-grid .brand-col p { font-size: 14px; line-height: 1.7; max-width: 280px; }
.footer-grid h2 { font-family: var(--sans); color: #fff; font-weight: 600; font-size: 14px; margin-bottom: 6px; }
.footer-grid ul { list-style: none; font-size: 14px; line-height: 2; }
.footer-grid a:hover { color: var(--green-light); }
.footer-grid address { font-style: normal; font-size: 14px; line-height: 2; }
.footer-grid .email { color: var(--green-light); }
.footer-grid .email:hover { color: #b3e6c6; }
.footer-bottom { background: var(--ink-deep); }
/* --faint is a light-ground token; on --ink-deep it was 4.08:1 and failing AA. The
   --on-dark-* family exists for text on ink (7.67:1 here). */
.footer-bottom .wrap { padding-top: 22px; padding-bottom: 22px; font-size: 13px; color: var(--on-dark-body); }
/* Copyright left, legal links right; wraps to two stacked lines on a phone. */
.footer-bottom-row { display: flex; flex-wrap: wrap; justify-content: space-between; gap: 8px 24px; }
.footer-legal a { color: var(--on-dark-strong); }
.footer-legal a:hover { color: var(--green-light); }
.footer-legal a + a { margin-left: 18px; }
@media (max-width: 860px) {
  .footer-grid { grid-template-columns: 1fr 1fr; padding-top: 44px; padding-bottom: 44px; }
  .footer-grid .brand-col { grid-column: 1 / -1; }
}
@media (max-width: 560px) { .footer-grid { grid-template-columns: 1fr; } }

/* slim footer (ad landing) */
.footer-slim { background: var(--ink); color: var(--on-dark-body); }
.footer-slim .wrap {
  display: flex; justify-content: space-between; align-items: center; gap: 24px; flex-wrap: wrap;
  padding-top: var(--space-6); padding-bottom: var(--space-6); font-size: 13px;
}
.footer-slim img { height: 18px; width: auto; }
.footer-slim .email { color: var(--green-light); }

/* ------------------------------------------------------------ misc components */
.trust-strip { border-bottom: 1px solid var(--hairline); }
.trust-strip .wrap { display: flex; align-items: center; gap: 40px; padding-top: var(--space-6); padding-bottom: var(--space-6); }
.trust-strip .label { font-size: var(--fs-label); font-weight: var(--fw-label); letter-spacing: var(--ls-label); text-transform: uppercase; color: var(--label-muted); white-space: nowrap; }
.trust-strip .logos { display: flex; gap: 16px; flex: 1; }
.trust-strip .logos > div { height: 34px; flex: 1; background: #f2f4f5; display: flex; align-items: center; justify-content: center; font-size: 11px; letter-spacing: .12em; color: #b3bac0; }


/* Removed in 1.2.1.9: .aud-col and .proof-strip, both dropped from the generator in
   1.0.5.1.3–1.0.5.2.2. The live proof band is .stat-band / .stat-row further down. */

.related-strip { border-top: 1px solid var(--hairline); }
.related-strip .wrap { display: flex; align-items: center; gap: 24px; flex-wrap: wrap; padding-top: var(--space-7); padding-bottom: var(--space-7); }
.related-strip .label { font-size: var(--fs-label); font-weight: var(--fw-label); letter-spacing: var(--ls-label); text-transform: uppercase; color: var(--label-muted); }

/* about page */
.about-story { display: grid; grid-template-columns: .4fr 1fr; gap: 56px; align-items: start; }
.about-story > .kicker { padding-top: 12px; }
.about-story h2 { font-family: var(--serif); font-weight: var(--fw-heading); font-size: var(--fs-h1); line-height: var(--lh-h1); letter-spacing: var(--ls-h1); color: var(--ink); }
.about-story .story-body p { font-size: var(--fs-lede); line-height: var(--lh-lede); color: var(--body); margin-top: 32px; max-width: 64ch; }
@media (max-width: 860px) { .about-story { grid-template-columns: 1fr; gap: 20px; } }

.leader-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 0 64px; align-items: start; }
.leader-grid .portrait { width: 100%; height: auto; aspect-ratio: 4 / 5; object-fit: cover; object-position: center; }
.leader-grid .bio .kicker { display: block; color: var(--green-light); margin-bottom: 20px; }
/* On the h1 step with .about-story h2, the other statement heading on this page.
   Was a bare 44px, so on a phone the name stayed 44px while every other h2 around it
   had scaled to 26–32px. Both were also w400 — the only headings on the site running
   lighter than 600 — and now match the rest. */
.leader-grid h2 { font-weight: var(--fw-heading); font-size: var(--fs-h1); line-height: var(--lh-h1); letter-spacing: var(--ls-h1); }
/* .leader-grid .role removed — _leader_html() never emitted class="role". The TEAM
   "role" key is still live data: it goes into the portrait's alt text
   ("Mark Haddad, Partner"), so don't mistake it for a dead field. */
.leader-grid .bio p { font-size: 16px; line-height: 1.75; color: var(--on-dark-strong); margin-top: 16px; }
.leader-grid .bio p:first-of-type { margin-top: 28px; }
.leader-grid .bio a { display: inline-block; margin-top: 28px; font-size: 14px; font-weight: 600; color: var(--green-light); }
.leader-facts { display: grid; grid-template-columns: 1fr 1fr; gap: 24px; margin-top: 36px; border-top: 1px solid var(--ink-hairline); padding-top: 28px; }
.leader-facts .fact-label { font-weight: var(--fw-label); letter-spacing: var(--ls-label-sm); text-transform: uppercase; font-size: var(--fs-label-sm); color: var(--label-accent-dk); margin-bottom: 6px; }
.leader-facts .fact-val { color: var(--on-dark-strong); font-size: 14px; line-height: 1.6; }
@media (max-width: 860px) {
  .leader-grid { grid-template-columns: 1fr; gap: 32px; }
  .leader-grid .portrait { max-width: 360px; }
}

/* Removed: .landing-hero / .lead-card — the PREVIOUS design of the ad landing page,
   superseded by .lhero / .llead in the page-scoped block in generate.py. Neither
   class has been emitted since. */

/* calendly embed */
.calendly-block { min-width: min(320px, 100%); height: 1080px; max-width: 900px; margin: 0 auto; background: #fff; border: 1px solid var(--hairline); }
/* Seeded in the markup so the 1080px box is never silently blank; cleared the
   moment the widget initialises, overwritten by the fallback at 5s. */
.calendly-loading { padding: 48px 24px; text-align: center; color: var(--faint); }

/* ------------------------------------------------------------ insights (editorial) */
.insights-masthead { padding-top: var(--space-8); }
.insights-title { font-weight: var(--fw-heading); font-size: var(--fs-display); line-height: var(--lh-display); letter-spacing: var(--ls-display); }
/* The masthead deck is a genuinely distinct role from a section lede — it decks the
   whole publication, under a 64px title — so it keeps its own size and leading. The
   color was the actual inconsistency: every other intro on the site is --body. */
.insights-standfirst { font-size: 20px; line-height: 1.5; color: var(--body); margin-top: 16px; }
.insights-rule { border-top: 1px solid #d7dbde; margin-top: 36px; }
.insights-body { padding-top: var(--space-7); padding-bottom: var(--space-9); }
@media (max-width: 860px) { .insights-masthead { padding-top: 48px; } .insights-body { padding-bottom: 56px; } }

.insights-main { display: grid; grid-template-columns: 1fr 340px; gap: 0 64px; align-items: start; }
.insights-stack { min-width: 0; }
/* tablet band: rail stays beside but narrows so the main column keeps dominating */
@media (min-width: 861px) and (max-width: 1000px) { .insights-main { grid-template-columns: 1fr 260px; gap: 0 40px; } }
@media (max-width: 860px) { .insights-main { grid-template-columns: 1fr; } }

/* animated underline on hover (title link affordance) */
.u-hover {
  background-image: linear-gradient(var(--green), var(--green));
  background-size: 0 1.5px; background-position: 0 100%; background-repeat: no-repeat;
  transition: background-size .3s var(--ease);
}
a:hover .u-hover { background-size: 100% 1.5px; }

/* shared editorial media box */
.ed-media { position: relative; overflow: hidden; background: #eef1f2; }
.ed-media img { width: 100%; height: 100%; object-fit: cover; display: block; }
.ratio-16-11 { aspect-ratio: 16 / 11; }
.ratio-16-10 { aspect-ratio: 16 / 10; }

/* editorial typography */
.ed-title { font-family: var(--serif); letter-spacing: -.01em; color: var(--ink); }
.ed-title-lg { font-size: var(--fs-title-lg); font-weight: var(--fw-title-lg); line-height: var(--lh-title-lg); }
.ed-title-md { font-size: var(--fs-title); font-weight: var(--fw-title); line-height: var(--lh-title); }
/* .ed-title-sm removed in 1.2.1.9 — unused since 1.1.1.7. Only -lg and -md are emitted. */
.ed-dek { font-family: var(--serif); font-style: italic; font-weight: 400; font-size: 18px; line-height: 1.45; color: var(--body-strong); margin-top: 16px; }
.ed-dek-sm { font-size: 17px; margin-top: 14px; }
.eyebrow { font-size: var(--fs-label); font-weight: var(--fw-label); letter-spacing: var(--ls-label); text-transform: uppercase; color: var(--label-muted); margin-top: 20px; }
.eyebrow-sm { font-size: var(--fs-label-sm); letter-spacing: var(--ls-label-sm); margin-top: 12px; }
.ed-item { display: block; }

/* lead articles */
.lead { display: grid; grid-template-columns: 0.66fr 1fr; gap: 44px; align-items: center; padding: var(--space-7) 0; border-bottom: 1px solid var(--hairline); }
.insights-stack > .lead:first-child { padding-top: 0; }
/* fixed 4:3 image box — every lead image renders the same large, near-square size; any upload is cover-cropped to fill it */
.lead .ed-media { aspect-ratio: 4 / 3; }
/* when stacked, the image moves to the top (image → headline → dek → meta) */
@media (max-width: 1000px) {
  .lead { grid-template-columns: 1fr; gap: 20px; }
  .lead .ed-media { order: -1; }
}

/* two-up */
.twoup { display: grid; grid-template-columns: 1fr 1fr; gap: 40px 48px; padding-top: 44px; }
@media (max-width: 1000px) { .twoup { grid-template-columns: 1fr; gap: 32px; } }

/* three-up */
/* between 860–1000 the rail is still beside, so the main column is narrow — drop to 2-up */

/* trending rail */
.rail { border-left: 1px solid var(--hairline); padding-left: 36px; }
/* Thin end-of-article magnet strip (category-mapped; see ARTICLE_MAGNETS). */
.article-magnet {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 8px 16px;
  border: 1px solid var(--hairline); border-left: 3px solid var(--green);
  background: var(--surface); padding: 18px 24px;
}
.article-magnet:hover { border-color: var(--green); }
.article-magnet .am-tag {
  font-size: var(--fs-label); font-weight: var(--fw-label);
  letter-spacing: var(--ls-label); text-transform: uppercase;
  color: var(--label-accent); flex: none;
}
.article-magnet .am-text { color: var(--body-strong); font-size: var(--fs-body); }
.article-magnet .am-go {
  color: var(--green-deep); font-size: var(--fs-small); font-weight: var(--fw-label);
  margin-left: auto; white-space: nowrap;
}

/* Two-up lead-magnet tool cards (group pages). */
.tool-cards { display: grid; grid-template-columns: 1fr 1fr; gap: 24px; margin-top: 8px; }
.tool-card {
  display: flex; flex-direction: column; gap: 10px;
  border: 1px solid var(--hairline); background: var(--paper); padding: 28px 30px;
  transition: border-color .15s;
}
.tool-card:hover { border-color: var(--green); }
.tool-tag {
  font-size: var(--fs-label); font-weight: var(--fw-label);
  letter-spacing: var(--ls-label); text-transform: uppercase; color: var(--label-accent);
}
.tool-title { font-family: var(--serif); font-weight: var(--fw-title); font-size: var(--fs-title); line-height: var(--lh-title); color: var(--ink); }
.tool-dek { font-size: var(--fs-body); color: var(--body); line-height: var(--lh-lede); }
.tool-go { margin-top: auto; padding-top: 8px; color: var(--green-deep); font-size: var(--fs-small); font-weight: var(--fw-label); }
@media (max-width: 860px) { .tool-cards { grid-template-columns: 1fr; } }

/* Same voice as .kicker (the site-wide green section label), with rail spacing. */
.rail-label {
  font-size: var(--fs-label); font-weight: var(--fw-label);
  letter-spacing: var(--ls-label); text-transform: uppercase;
  color: var(--label-accent); margin: 30px 0 18px;
}
.insights-stack > .rail-label { margin-top: 0; }
.rail > .rail-label:first-child { margin-top: 0; }
.rail-item { display: block; margin-bottom: 20px; }
/* h3 since 2026-08-12: the rail's "Guides" / "Tools" labels became real headings
   rather than <div>s, so these moved up a level to sit under them without skipping.
   Selector follows the tag; the visual step (--fs-title-sm) is unchanged. */
.rail-item h3 { font-family: var(--serif); font-weight: var(--fw-title); font-size: var(--fs-title-sm); line-height: var(--lh-title-sm); }
.rail-dek { font-family: var(--serif); font-style: italic; font-size: var(--fs-body); line-height: var(--lh-title-sm); color: var(--body); margin: 6px 0 8px; }
.rail-item.bordered { padding-bottom: 22px; border-bottom: 1px solid var(--hairline); margin-bottom: 22px; }
@media (max-width: 860px) {
  .rail { border-left: 0; padding-left: 0; border-top: 1px solid var(--hairline); padding-top: 34px; margin-top: 8px; }
}

/* spotlight */
.spotlight-title { font-weight: var(--fw-heading); font-size: var(--fs-h1); line-height: var(--lh-h1); letter-spacing: var(--ls-h1); margin-bottom: 44px; }
.spot { display: grid; grid-template-columns: repeat(3, 1fr); gap: 36px; }
.spot .ed-media { margin-bottom: 20px; }
.ed-spot-title { font-weight: var(--fw-title); font-size: var(--fs-title); line-height: var(--lh-title); margin-bottom: 10px; }
.ed-spot-copy { font-size: 15px; line-height: 1.6; color: var(--body); }
@media (max-width: 1000px) { .spot { grid-template-columns: 1fr; } }

/* brand-texture placeholder (service spotlight has no photography) */

/* ------------------------------------------------------------ editorial unification (home + service) */
.cat-kicker { margin-bottom: 14px; }   /* type comes from the shared .cat rule above */

/* home value row — hairline grid capped by an ink rule */

/* ---- "Inside the report" deliverable block -------------------------------
   A document mockup beside a numbered list of report sections. Shared by the
   QoE service page and the /quality-of-earnings-a/ ad landing page, which
   originated it. The landing page still carries its own inline copy of these
   rules via extra_head — which shell() emits AFTER this stylesheet, so its
   values (notably border-radius: 6px) continue to win there. `.doc` is flat
   here to match the rest of the site; the ad page keeps its rounded corners. */
.report { background: var(--surface); }
.report .wrap { display: grid; grid-template-columns: .9fr 1.1fr; gap: 72px; align-items: center; }
.report h2 { font-size: var(--fs-h2); font-weight: var(--fw-heading); line-height: var(--lh-h2); letter-spacing: var(--ls-h2); margin-top: 14px; margin-bottom: 14px; }
.report .lede { margin-top: 0; margin-bottom: 26px; }
.doc-stack { position: relative; height: 520px; }
.doc { position: absolute; border-radius: 0; box-shadow: var(--shadow-card); overflow: hidden; }
.doc-cover {
  width: 62%; height: 90%; left: 0; top: 5%;
  background: linear-gradient(160deg, var(--ink) 0%, #152019 70%, var(--green-deep) 160%);
  transform: rotate(-4deg); padding: 30px;
  display: flex; flex-direction: column; justify-content: space-between;
}
.doc-cover img { width: 150px; height: auto; opacity: .95; }  /* height:auto is load-bearing: the HTML height attribute otherwise survives the
   CSS width override and crushes the 1002x120 wordmark into a square */
.doc-cover .dc-title { font-family: var(--serif); font-size: 24px; color: #fff; line-height: 1.25; font-weight: 300; }
.doc-cover .dc-meta { font-size: 10.5px; letter-spacing: .16em; text-transform: uppercase; color: var(--on-dark-body); }
.doc-toc {
  width: 64%; height: 100%; right: 0; top: 0; background: #fff;
  transform: rotate(1.5deg); padding: 30px 28px; box-shadow: 0 18px 44px rgba(16, 20, 24, .16);
}
.doc-toc .dt-head {
  /* --faint, not --fainter: at 10.5px uppercase the lighter neutral sat at
     3.09:1 against the white mockup — under the 4.5:1 small-text bar. */
  font-size: 10.5px; letter-spacing: .18em; text-transform: uppercase; color: var(--faint);
  border-bottom: 1px solid var(--hairline); padding-bottom: 12px; margin-bottom: 6px;
  display: flex; justify-content: space-between; gap: 16px;
}
.toc-row { display: flex; gap: 14px; align-items: baseline; padding: 13px 0; border-bottom: 1px solid var(--hairline); }
/* --green-deep, not --green: this is 15px TEXT, so it takes the 4.5:1 bar and
   --green is 4.20:1 on white (see the note at the top of this file). --green
   stays correct for the .inc rule below only because that one is a larger step. */
.toc-row .n { font-family: var(--serif); color: var(--green-deep); font-size: 15px; flex: none; width: 22px; }
.toc-row .t { font-weight: 600; font-size: 13.5px; color: var(--ink); }
.toc-row .d { font-size: 11.5px; color: var(--faint); display: block; line-height: 1.45; margin-top: 2px; }
.inc { display: flex; gap: 14px; padding: 13px 0; border-top: 1px solid var(--rule); }
.inc:last-of-type { border-bottom: 1px solid var(--rule); }
.inc .n { font-family: var(--serif); color: var(--green-deep); flex: none; width: 26px; font-size: 17px; }
.inc h3 { font-size: var(--fs-title-sm); font-weight: var(--fw-title); line-height: var(--lh-title-sm); }
.inc p { font-size: 14px; color: var(--body); line-height: 1.55; }
.sample-link {
  display: inline-flex; align-items: center; gap: 8px; margin-top: 26px;
  font-weight: 600; font-size: 15px; color: var(--green-deep); text-decoration: none;
  border-bottom: 2px solid var(--green-pale); padding-bottom: 3px;
}
.sample-link:hover { border-color: var(--green); }
@media (max-width: 1000px) {
  .report .wrap { grid-template-columns: 1fr; gap: 56px; }
  .doc-stack { width: 100%; max-width: 480px; margin: 0 auto; height: 460px; }
}
@media (max-width: 860px) { .doc-stack { height: 420px; } }

/* ---- home teaser to /about/ ---------------------------------------------
   An invitation, not a pitch. The seller-to-buyer axis carries the "both sides"
   idea graphically, so the copy never has to argue it. */
.about-teaser { background: var(--surface); }
.at-head { display: flex; justify-content: space-between; align-items: flex-end; gap: 56px; }
/* Two lines, broken explicitly in the markup. max-width is wide enough that the
   longer first line does not wrap again on desktop; it still wraps gracefully on
   narrow screens. */
.at-head h2 {
  font-weight: var(--fw-heading); max-width: 48ch;
  font-size: var(--fs-h2); line-height: var(--lh-h2); letter-spacing: var(--ls-h2);
}
.at-link {
  flex: none; font-family: var(--sans); font-size: var(--fs-label); font-weight: var(--fw-label);
  letter-spacing: var(--ls-label); text-transform: uppercase; color: var(--label-link);
  border-bottom: 1px solid var(--green-pale); padding-bottom: 7px;
}
.at-link:hover { border-color: var(--green); }
.at-track { display: flex; align-items: center; margin-top: 76px; }
.at-marks { display: flex; gap: 8px; flex: none; }
.at-marks i { width: 11px; height: 11px; background: var(--ink); display: block; }
.at-marks-buy i { background: var(--green); }
.at-line { flex: 1; height: 1px; background: var(--rule); margin: 0 20px; }
.at-ends {
  display: flex; justify-content: space-between; margin-top: 14px;
  font-family: var(--sans); font-size: var(--fs-label-sm); font-weight: var(--fw-label);
  letter-spacing: var(--ls-label-sm);
  text-transform: uppercase; color: var(--label-muted);
}
.at-ends .at-end-buy { color: var(--label-link); }
@media (max-width: 860px) {
  .at-head { flex-direction: column; align-items: flex-start; gap: 26px; }
  .at-head h2 { max-width: none; }
  .at-track { margin-top: 52px; }
  .at-marks i { width: 9px; height: 9px; }
  .at-line { margin: 0 14px; }
  /* keeps the label on-scale at 11px and buys the width back from tracking instead */
  .at-ends { letter-spacing: var(--ls-label); gap: 16px; }
}

/* home services — borderless hairline list */
/* home services: one full-width row per group, three practice areas each.
   The group name sits in its own left rail aligned with its three areas, so the
   grouping reads structurally — no card enclosure needed. */
.svc-groups { border-bottom: 1px solid var(--rule); }
.svc-group {
  display: grid; grid-template-columns: 230px 1fr; gap: 0 56px;
  padding: var(--space-7) 0; border-top: 1px solid var(--rule);
}
.svc-group-name { font-family: var(--serif); font-weight: var(--fw-title-lg); font-size: var(--fs-title-lg); line-height: var(--lh-title-lg); color: var(--ink); }
.svc-group-more {
  display: inline-block; margin-top: 16px;
  font-family: var(--sans); font-size: var(--fs-label); font-weight: var(--fw-label);
  letter-spacing: var(--ls-label); text-transform: uppercase;
  color: var(--label-link);
}
.svc-group-desc { font-size: 16px; line-height: 1.6; color: var(--body); margin: 0 0 34px; max-width: 64ch; }
.svc-areas { display: grid; grid-template-columns: repeat(3, 1fr); gap: 34px; }
.svc-area-name { display: block; font-family: var(--serif); font-weight: var(--fw-title); font-size: var(--fs-title-sm); line-height: var(--lh-title-sm); color: var(--ink); }
.svc-area-desc { display: block; font-size: 15px; line-height: 1.6; color: var(--body); margin-top: 10px; }
@media (max-width: 1000px) {
  .svc-group { grid-template-columns: 1fr; gap: 24px 0; padding: 38px 0; }
  .svc-group-more { margin-top: 10px; }
}
@media (max-width: 860px) { .svc-areas { grid-template-columns: 1fr; gap: 28px; } }

/* who we serve — editorial statement + hairline rows (dark) */
.who-serve { display: grid; grid-template-columns: 380px 1fr; gap: 64px; align-items: start; }
.who-serve .who-lead h2 { font-weight: var(--fw-heading); font-size: var(--fs-h1); line-height: var(--lh-h1); letter-spacing: var(--ls-h1); }
.who-serve .who-lead p { font-size: 15px; line-height: 1.65; color: var(--on-dark-body); margin-top: 22px; }
.who-row { display: flex; gap: 24px; padding: 24px 0; border-top: 1px solid var(--ink-hairline); }
.who-row:last-child { border-bottom: 1px solid var(--ink-hairline); }
.who-row h3 { font-family: var(--serif); font-weight: var(--fw-title); font-size: var(--fs-title-sm); line-height: var(--lh-title-sm); color: #fff; min-width: 180px; }
.who-row p { font-size: 15px; line-height: 1.6; color: var(--on-dark-body); }
@media (max-width: 860px) {
  .who-serve { grid-template-columns: 1fr; gap: 32px; }
  .who-row { flex-direction: column; gap: 8px; }
  .who-row h3 { min-width: 0; }
}

/* home insights — featured article + rail */
/* image fills the featured row height so it stands as tall as the text beside it;
   aspect-ratio:auto overrides the .ratio-4-3 class so it can't force its own width */

/* Shared opening statement: the body-size institutional paragraph used on the two
   group overview pages AND as the capabilities intro on all six service pages.
   Moved here from GROUP_CSS (generate.py) when the service pages adopted it. */
.grp-lede { max-width: 760px; font-size: var(--fs-lede); line-height: var(--lh-lede); color: var(--body); margin: 0 0 64px; }
/* On the six service pages the capabilities intro is semantically an <h2> (it heads the
   section for SEO and screen-reader navigation) but must render identically to the
   paragraph version above: undo the global h1-h4 serif/spacing rule and the UA bold. */
h2.grp-lede { font-family: var(--sans); font-weight: inherit; letter-spacing: var(--ls-body); }
.cap-intro .kicker { display: block; margin-bottom: 18px; }

/* service capabilities — accordion */
.cap-acc { border-top: 1px solid var(--hairline); margin-top: 40px; max-width: 860px; }
.cap-acc-item { border-bottom: 1px solid var(--hairline); }
/* Heading wrapper around each trigger (APG accordion): exists purely for the
   heading outline. All visual type lives on .cap-acc-title, so the h3 just
   gets out of the way. */
.cap-acc-h { margin: 0; font: inherit; }
.cap-acc-head {
  width: 100%; display: flex; align-items: center; justify-content: space-between; gap: 20px;
  background: none; border: 0; cursor: pointer; padding: 24px 0;
  font-family: var(--sans); text-align: left;
}
.cap-acc-title {
  display: flex; align-items: baseline; gap: 18px;
  font-family: var(--serif); font-weight: var(--fw-title); font-size: var(--fs-title); line-height: var(--lh-title); color: var(--ink);
}
.cap-acc-num { font-family: var(--serif); font-size: 15px; font-weight: 400; color: var(--faint); }
.cap-acc-head[aria-expanded="true"] .cap-acc-num { color: var(--green-deep); }
.cap-acc-icon { position: relative; flex: none; width: 22px; height: 22px; }
.cap-acc-icon::before, .cap-acc-icon::after {
  content: ""; position: absolute; background: var(--fainter);
  transition: transform .2s var(--ease), background-color .2s var(--ease);
}
.cap-acc-icon::before { top: 10px; left: 3px; right: 3px; height: 2px; }   /* horizontal bar */
.cap-acc-icon::after  { left: 10px; top: 3px; bottom: 3px; width: 2px; }   /* vertical bar */
.cap-acc-head[aria-expanded="true"] .cap-acc-icon::before,
.cap-acc-head[aria-expanded="true"] .cap-acc-icon::after { background: var(--green); }
.cap-acc-head[aria-expanded="true"] .cap-acc-icon::after { transform: scaleY(0); } /* + becomes − */
.cap-acc-head:hover .cap-acc-num { color: var(--green-deep); }
.cap-acc-panel { padding: 0 0 28px 33px; }
.cap-acc-panel[hidden] { display: none; }
@media (max-width: 860px) {
  .cap-acc-title { gap: 14px; }   /* --fs-title already clamps to 20px here */
  .cap-acc-panel { padding-left: 26px; }
}

/* green-square tick lists (shared: caps + checklist) */
.tick-list { display: flex; flex-direction: column; gap: 14px; list-style: none; }
.tick-list li { display: flex; gap: 12px; font-size: 14px; line-height: 1.55; color: var(--body); }
.tick-list li::before { content: ""; flex: none; width: 7px; height: 7px; margin-top: 6px; background: var(--green); }

/* service "why choose us" — statement + checklist (dark) */
.why-split { display: grid; grid-template-columns: 1fr 1fr; gap: 64px; align-items: center; }
.why-split .why-lead h2 { font-weight: var(--fw-heading); font-size: var(--fs-h1); line-height: var(--lh-h1); letter-spacing: var(--ls-h1); }
.why-split .why-lead .kicker { display: block; margin-bottom: 20px; }
.why-split .why-lead p { font-size: 16px; line-height: 1.65; color: var(--on-dark-body); margin-top: 22px; max-width: 44ch; }
.check-list { display: flex; flex-direction: column; }
.check-item { display: flex; gap: 16px; padding: 22px 0; border-top: 1px solid var(--ink-hairline); }
.check-item:last-child { border-bottom: 1px solid var(--ink-hairline); }
.check-item .tick { flex: none; width: 9px; height: 9px; background: var(--green); margin-top: 8px; }
.check-item h3 { font-family: var(--serif); font-weight: var(--fw-title); font-size: var(--fs-title-sm); line-height: var(--lh-title-sm); color: #fff; margin-bottom: 6px; }
.check-item p { font-size: 14px; line-height: 1.6; color: var(--on-dark-body); }
@media (max-width: 860px) { .why-split { grid-template-columns: 1fr; gap: 36px; } }

/* related insights — hairline rows */
.related-rows { border-top: 1px solid var(--hairline); }
.related-rows a { display: grid; grid-template-columns: 240px 1fr auto; gap: 32px; align-items: center; padding: 28px 0; border-bottom: 1px solid var(--hairline); }
.related-rows h3 { font-family: var(--serif); font-weight: var(--fw-title); font-size: var(--fs-title-sm); line-height: var(--lh-title-sm); color: var(--ink); }
.related-rows .rt { font-size: 13px; color: var(--faint); white-space: nowrap; }
@media (max-width: 860px) {
  .related-rows a { grid-template-columns: 1fr; gap: 8px; }
  .related-rows .rt { display: none; }
}

/* Removed 2026-08: the buyers/sellers cards (.bs-grid / .bs / .lticks / .tk).
   The QoE page's "Two sides" section was retired when the capability accordion
   gained Buy-Side / Sell-Side groups and the split was being said twice. The
   archived ad landing page (build/inactive/qoe_landing.py) still references these
   classes — restore this block from git history if that page is ever revived. */

/* ------------------------------------------------------------ motion */
@media (prefers-reduced-motion: no-preference) {
  .rv { opacity: 0; transform: translateY(18px); transition: opacity .65s var(--ease), transform .65s var(--ease); }
  .rv-in { opacity: 1; transform: none; }
}

/* ------------------------------------------ insights: browse-all (left stack foot) */
.stack-all {
  display: flex; align-items: center; justify-content: space-between; gap: 24px;
  margin-top: 56px; padding: 26px 4px 26px 0;
  border-top: 1px solid var(--ink); border-bottom: 1px solid var(--hairline);
  transition: padding-left .2s var(--ease);
}
.stack-all-t { font-family: var(--serif); font-size: var(--fs-title); font-weight: var(--fw-title); color: var(--ink); line-height: var(--lh-title); }
.stack-all-a { font-size: 22px; color: var(--green-deep); line-height: 1; }
.stack-all:hover { padding-left: 10px; }
.stack-all:hover .stack-all-t { color: var(--green-deep); }
.stack-all:focus-visible { outline: 2px solid var(--green); outline-offset: 3px; }
@media (prefers-reduced-motion: reduce) { .stack-all { transition: none; } .stack-all:hover { padding-left: 0; } }
@media (max-width: 560px) { .stack-all { margin-top: 40px; } }

/* ------------------------------------------ about: proof band, bios, testimonials */
.stat-band { border-top: 1px solid var(--hairline); border-bottom: 1px solid var(--hairline); background: var(--green-wash); }
.stat-band.dark { background: var(--ink-deep); border-color: var(--ink-hairline); }
.stat-band .wrap { padding-top: var(--space-7); padding-bottom: var(--space-7); }
.stat-row { display: grid; grid-template-columns: repeat(4, 1fr); gap: 32px; }
.stat-num { font-family: var(--serif); font-size: clamp(1.9rem, 1.4rem + 1.6vw, 2.6rem); font-weight: 400; line-height: 1; color: var(--green-deep); display: block; }
.stat-band.dark .stat-num { color: var(--green-light); }
.stat-label { font-size: 14px; line-height: 1.5; color: var(--body); display: block; margin-top: 10px; }
.stat-band.dark .stat-label { color: var(--on-dark-body); }
@media (max-width: 860px) { .stat-row { grid-template-columns: 1fr 1fr; gap: 24px 20px; } }

.leader-creds { display: flex; flex-wrap: wrap; gap: 8px; margin-top: 16px; }
.cred-badge { font-size: var(--fs-label-sm); font-weight: var(--fw-label); letter-spacing: var(--ls-label-sm); text-transform: uppercase; color: var(--label-accent-dk); border: 1px solid var(--ink-border); padding: 5px 12px; }

.affil-wrap { display: flex; align-items: center; gap: 28px; flex-wrap: wrap; }
.affil-wrap .kicker { margin: 0; }
.affil-row { display: flex; flex-wrap: wrap; gap: 12px; }
.affil-badge { font-size: 13px; font-weight: 600; color: var(--body-strong); background: #fff; border: 1px solid var(--hairline); padding: 8px 16px; }

.quote-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 24px; }
.quote-card { background: #fff; border: 1px solid var(--hairline); padding: 30px; display: flex; flex-direction: column; gap: 20px; }
.quote-card blockquote { font-family: var(--serif); font-weight: 300; font-size: 18px; line-height: 1.55; color: var(--body-strong); margin: 0; }
.quote-card figcaption { margin-top: auto; display: flex; flex-direction: column; gap: 3px; }
.quote-card .q-name { font-weight: 600; color: var(--ink); }
.quote-card .q-role { font-size: 14px; color: var(--faint); }
@media (max-width: 860px) { .quote-grid { grid-template-columns: 1fr; } }

/* "Sample" review labels — shown while SHOW_PLACEHOLDER_PROOF is on */
/* #7d6317 measures 5.03:1 on the #fbf0cf ground; the previous #8a6d1a was 4.31:1,
   under AA for 10px text. Same gold family, one step darker. */
.sample-badge { display: inline-block; font-size: 10px; font-weight: 700; letter-spacing: .1em; text-transform: uppercase; color: #7d6317; background: #fbf0cf; border: 1px solid #ecd88a; padding: 2px 8px; vertical-align: middle; margin-left: 8px; }
.quote-card .sample-badge { margin-left: 0; align-self: flex-start; }
.proof-note { font-size: 13px; font-style: italic; color: var(--faint); margin: -6px 0 26px; }

/* ------------------------------------------------------------ utilities */
/* UI-11: this class was used on /insights/all/ but never defined, so the search
   label rendered as visible body copy above the field. */
.u-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;
}

/* UI-12: .related-rows a and .post-row are the same component — a full-width
   hairline row link — but only .post-row had a hover. */
.related-rows a:hover { background: var(--surface-quiet); }

/* UI-13: no :active or :disabled existed anywhere. Touch gave no press feedback,
   and the contact form had no hook for a submitting state, which invites a double
   submission on a slow connection. */
.btn:active { transform: translateY(1px); }
.btn[disabled], .btn.is-busy { opacity: .55; cursor: not-allowed; pointer-events: none; }
@media (prefers-reduced-motion: reduce) { .btn:active { transform: none; } }

/* UX-2: shown when the Calendly widget fails to load within five seconds. */
.calendly-fallback { padding: 48px 24px; text-align: center; color: var(--body); }
.calendly-fallback p { margin-bottom: 18px; }

/* UI-8: forced-colors overrides `color` but keeps `background-image`, so panels
   that pair a dark gradient with white type would render dark-on-dark. */
@media (forced-colors: active) {
  .doc-cover, .ph { forced-color-adjust: none; background: Canvas; color: CanvasText; }
  .doc-cover .dc-title, .doc-cover .dc-meta { color: CanvasText; }
  /* .at-marks encodes seller-vs-buyer purely as fill color, which flattens. */
  .at-marks-buy i { outline: 2px solid CanvasText; outline-offset: 1px; }
}

/* UI-18: the articles are the reason this exists — long analytical pieces with
   tables and charts that people print or save to PDF for a board pack. */
@media print {
  .site-header, .site-footer, .related-rows, .related-strip, .contact,
  .skip-link, .rail, .stack-all, .arch-tools { display: none !important; }
  body { background: #fff; color: #000; }
  .wrap { max-width: none; padding: 0; }
  .article { max-width: none; }
  .article figure.chart .chart-scroll { overflow: visible; }
  .article figure.chart svg { min-width: 0; width: 100%; }
  .article a { text-decoration: underline; }
  .article a[href^="http"]::after { content: " (" attr(href) ")"; }
  h1, h2, h3 { break-after: avoid; }
  figure, table { break-inside: avoid; }
}
