/*
Theme Name: Ecom Enable
Theme URI: https://www.ecomenable.com/
Author: Ecom Enable
Description: Custom theme for Ecom Enable — Amazon growth agency for DTC brands. "THE FIELD": Midnight Navy is the ground, not the ink. Bands alternate between navy and white with no third surface, and a page both opens and closes on navy. Photographs are full-bleed at 0px radius, graded to a navy black point. Every claim is a pair of terms with the lime arrow between them, set on a hairline. Manrope only, 9.3× dynamic range, zero animation. Built from the Ecom Enable Brand Book v1.0 and research/DIRECTION.md (20 Aug 2026).
Version: 1.9.1
Requires at least: 6.0
Tested up to: 6.7
Requires PHP: 7.4
License: GNU General Public License v2 or later
License URI: http://www.gnu.org/licenses/gpl-2.0.html
Text Domain: ecomenable
*/

/* ==========================================================================
   Fonts — Manrope variable (self-hosted, weights 400–800)

   ─────────────────────────────────────────────────────────────────────────
   BUG 1 — U+2197 IS ABSENT FROM THE unicode-range BELOW, AND STAYS ABSENT.
   The latin subset covers U+2191 (↑) and U+2193 (↓) and does NOT cover
   U+2197 (↗). That is why all 78 `&nearr;` and 36 `&rarr;` in the templates
   were drawn by whatever symbol font the visitor's OS supplied — the brand's
   one distinctive mark was the only thing on the site not set in Manrope.

   DO NOT "FIX" THIS BY ADDING U+2197 TO THE RANGE. `unicode-range` only
   declares which codepoints a file is asked for; it cannot put a glyph into
   a .woff2 that was subset without one. Widening the range would send the
   browser to a file that has no ↗ in it and it would fall back anyway —
   the same bug, now with a comment claiming it is fixed.

   THE FIX IS AN ASSET, NOT A FONT RANGE: inc/arrow.php ships a three-symbol
   inline SVG sprite at exactly 45° in `currentColor`, and the .ee-arrow cuts
   that size it are in the v1.8 block at the foot of this file. Never write
   &nearr;, &rarr;, \2197 or \2191 in CSS content or in markup again.
   ─────────────────────────────────────────────────────────────────────────
   ========================================================================== */
@font-face{
  font-family:'Manrope';
  font-style:normal;
  font-weight:400 800;
  font-display:swap;
  src:url('assets/fonts/manrope-latin.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:'Manrope';
  font-style:normal;
  font-weight:400 800;
  font-display:swap;
  src:url('assets/fonts/manrope-latin-ext.woff2') format('woff2');
  unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF;
}

/* ==========================================================================
   Design tokens — THE FIELD
   Navy is the GROUND, not the ink. A band is --navy or it is --bg. There is
   no third surface. Lime is the arrow and the action, and nothing else.

   ─────────────────────────────────────────────────────────────────────────
   THIS BLOCK IS THE ONLY PLACE ANY OF THESE VALUES IS WRITTEN.
   Every repoint below (DIRECTION.md §3.2, build order Tier 0) fixes dozens
   of declarations at once. Do not restate a hex anywhere else in this file.
   The only literals permitted downstream are rgba() tints derived from a
   token here: navy 14,27,43 · on-dark 245,247,249.
   ─────────────────────────────────────────────────────────────────────────
   ========================================================================== */
:root{
  /* Brand (locked — Brand Book v1.0) */
  --navy:#0E1B2B;
  --navy-deep:#08121F;
  --lime:#C6F432;
  --soft-white:#F5F7F9;
  /* The fifth locked brand value, named at last — and given its first job in
     v1.9.1: the resting border of a secondary button on navy. 5.93:1 on
     --navy #0E1B2B and 5.35:1 on --surface-dark #13243A, so it clears the 3:1
     WCAG 1.4.11 asks of a control boundary while leaving --on-dark-body free
     to be the hover step at 8.24:1. Two call sites, both in Buttons/CTA. */
  --slate:#8C98A8;

  /*
   * BUG 2 — repointed. A mid-blue that is in no part of the brand book was
   * invented to fill the gap left by taking navy off the backgrounds, and it
   * became the dominant hue of the site across 68 var(--blue*) usages.
   * The token NAMES are kept on purpose: 68 call sites, 52 templates and
   * ~40 downstream rules already reference them, so repointing the value
   * here retires the colour in three lines instead of in 68 edits.
   * They now mean "the navy accent ramp", not "blue".
   *
   * THE RETIRED HEX IS NOT SPELLED ANYWHERE IN THIS FILE — NOT IN A VALUE
   * AND NOT IN A COMMENT. DIRECTION.md §11 item 13 makes a grep for it a
   * pre-deploy gate, and a "was …" note in a comment is a hit like any
   * other; a gate that reports five hits it is meant to ignore stops being
   * read. Its decimal rgba() spelling is retired with it — writing the
   * colour in decimal is exactly how it survived the first grep.
   */
  --blue:#0E1B2B;       /* was the invented mid-blue — kickers, card links, step numbers, FAQ marker */
  --blue-dark:#3B4E66;  /* was #17497F — hover. Links go LIGHTER: the only hue move left */
  --blue-soft:#EDF0F4;  /* was #E8F0FA — media placeholder ground, tag hover. Neutral cool grey */

  /* Light surfaces (default) */
  --bg:#FFFFFF;
  /*
   * --bg-tint is REPOINTED to brand Soft White and DEMOTED.
   *
   *   IT IS NEVER A SECTION BAND AGAIN.  (DIRECTION.md §3.2 / §3.4 rule 2)
   *
   * Its only remaining job is the fill of an INSET OBJECT sitting on white:
   * .toc, .legal-toc, .author-box, .form-shell, .empty-state, .cs-proof,
   * <pre>, and the .service-row / .next-prev hover. That is the whole list.
   *
   * .section--tint AND ITS ~50 DOWNSTREAM VARIANTS ARE DELETED (v1.9.2).
   * The note that used to sit here said they were retained "ONLY so interior
   * and legal templates do not break". That had stopped being true: no PHP
   * file in the theme emits .section--tint, so nothing could break. A band is
   * .section--navy or it is plain .section — see the usage note on
   * .section--navy in the "Section surfaces" block.
   */
  --bg-tint:#F5F7F9;
  --ink:#0E1B2B;      /* headings */
  --body:#2B3A4D;     /* was #44566E (7.9:1, read as washed/unfinished) → 11.6:1 on white */
  --muted:#5A6A7E;    /* was #5E7590 → 5.5:1 on white, safe at 12px */
  --line:#DFE8F2;
  --line-strong:#C8D7E7;

  /* Dark band surfaces */
  --surface-dark:#13243A;   /* also the architectural arrow fill: navy-on-navy, ~6% lighter */
  --line-dark:#22334A;
  --on-dark:#F5F7F9;
  --on-dark-body:#A8B4C2;

  /* Semantic — NONE OF THESE THREE IS REFERENCED BY ANY RULE IN THIS SHEET,
     or by any inline style in the PHP. They are kept as the agreed palette for
     validation and status messaging, which the theme does not render yet (no
     front-end form survives, and the demo importer styles its own admin
     notices with WordPress core's colours). Delete them or use them; do not
     assume a rule somewhere depends on them. */
  --success:#1F8A5B;
  --warning:#E5A94A;
  --danger:#E5484D;

  /* Type */
  --font-sans:'Manrope','Inter',system-ui,-apple-system,'Segoe UI',Roboto,sans-serif;

  /* Spacing (8px base) */
  --space-1:4px; --space-2:8px; --space-3:12px; --space-4:16px;
  --space-5:24px; --space-6:32px; --space-7:48px; --space-8:64px;
  /* was 72px. Fixes the "cramped vertically, empty horizontally" document feel.
     The clamp replaces the two breakpoint overrides that used to live in the
     Responsive block — see the note there. */
  --section:clamp(88px,9vw,144px);

  /* Radius — hard 0px is the commitment (DIRECTION.md §6).
     2px survives on interactive controls only, so a button still reads as a
     control rather than as a painted rectangle. */
  --radius-sm:2px;  /* was 8px  — buttons, inputs, share links */
  --radius-md:0;    /* was 12px — cards, media, panels, proof frames */
  --radius-lg:0;    /* was 16px — the CTA band and large panels */

  /* Elevation — deleted. Emphasis is a heavier EDGE, never a lift.
     Kept as tokens so the `box-shadow:var(--shadow-*)` call sites do not need
     editing and cannot reintroduce a shadow by accident. There are TWO such
     call sites, not the ~9 this note claimed, and both are --shadow-md
     (.pricing-card--featured and the sticky nav shade). --shadow-sm currently
     has no call site; it is kept only so the pair cannot diverge if one comes
     back. */
  --shadow-sm:none;
  --shadow-md:none;

  /* Layout */
  --container:1240px;   /* was 1160px — paired with .section--bleed */
  --gutter:24px;

  /*
   * Motion — ZERO. The client constraint is absolute and was stated three
   * times. Setting the duration tokens to 0s is how it is enforced in one
   * place: all 29 `transition:… var(--dur-fast)` declarations become
   * instant, and the tokens stay in the file so a future relaxation is a
   * one-line change rather than a re-audit.
   *
   * There are no @keyframes in this stylesheet, no `animation` property, and
   * no `transform` inside any :hover / :focus / :active rule. Transitions
   * are limited to color / background / border-color / outline-color.
   * Do not add a fourth property here.
   */
  --dur-fast:0s; --dur-base:0s;
  /* Unreferenced while the durations are 0s — an easing curve has nothing to
     ease. Kept with them so a future relaxation stays a one-line change. */
  --ease-out:cubic-bezier(.16,1,.3,1);
}

/* ==========================================================================
   Reset & base
   ========================================================================== */
*,*::before,*::after{box-sizing:border-box}
/* scroll-behavior is `auto`, not `smooth`. Smooth scroll is motion. */
html{-webkit-text-size-adjust:100%;scroll-behavior:auto}
body{
  margin:0;
  background:var(--bg);
  color:var(--body);
  font-family:var(--font-sans);
  font-size:17px;
  line-height:1.65;
  -webkit-font-smoothing:antialiased;
}
img{max-width:100%;height:auto;display:block}
figure{margin:0}
a{color:var(--ink);text-decoration:none}
a:hover{text-decoration:underline}
button{font-family:inherit}

/* ──────────────────────────────────────────────────────────────────────────
   TYPE SCALE — DIRECTION.md §4. Range 112 ÷ 12 = 9.3× (it was 5×).
   One family. The second register is tabular numerals and 12px letterspaced
   uppercase labels set against a 112px display — not a second typeface,
   which the brand book forbids.

   THE DESKTOP LADDER, in order. Read it before adding any size:

       12 · 13 · 17 · 18 · 20 · 26 ·  ✕✕✕ 26–40 ✕✕✕ · 40 · 42 · 52 · 72 · 112
       │    │    │    │    │    │                      │    │    │    │    │
       │    │    │    │    │    h3                     │    h1   h2  .tr__to
       │    │    │    │    h4 / .plate__name          .tr__to min       .display
       │    │    body │
       │    .micro    .lead-xl max = 26
       labels

   NOTHING MAY SIT BETWEEN 26px AND 40px. The hole is deliberate: it is what
   makes the system read as engineered rather than templated. Measured at the
   desktop end of every clamp — a clamp may pass through the hole while it
   scales down, but no element's desktop size may land in it. Three legacy
   components were repointed out of the hole; each is flagged at its rule.
   ────────────────────────────────────────────────────────────────────────── */
h1,h2,h3,h4{
  margin:0 0 var(--space-4);
  color:var(--ink);
  text-wrap:balance;
  font-weight:800;letter-spacing:-.022em;
}
h1{font-size:clamp(42px,6vw,80px);line-height:1.00;letter-spacing:-.030em}
/* FLOOR RAISED 30px -> 40px. §4 rule 1: "Nothing sits between 26px and 40px.
   The hole in the middle of the scale is deliberate." A 30px floor is inside
   the hole and the 4.4vw ramp crossed it rather than jumping it, so h2 free-
   floated through 40 -> 28px across the whole 720-909px band with no entry in
   the design table: 768px (iPad portrait, the commonest tablet width) landed
   on 33.8px, dead centre of the hole. This is the same correction already
   made to .post-card--featured .post-card__title further down the file, which
   carries the note "30px sits in the 26-40px gap".
   40px only governs 720-909px: below 720 the mobile block's `h2{font-size:28px}`
   takes over (§4's mobile column), above 909 the 4.4vw ramp is already clear. */
h2{font-size:clamp(40px,4.4vw,52px);line-height:1.06;letter-spacing:-.022em}
h3{font-size:clamp(20px,2.2vw,26px);line-height:1.25;font-weight:700;letter-spacing:-.012em}
h4{font-size:18px;line-height:1.35;font-weight:700;letter-spacing:-.005em}
p{margin:0 0 var(--space-4)}
p:last-child{margin-bottom:0}

/*
 * .display — EXACTLY ONE PER PAGE. The hero H1 and nothing else.
 * (0,1,0) beats `h1,h2,h3,h4{…}` at (0,0,1), so it may be dropped straight
 * onto an <h1> without a wrapper. Colour is deliberately NOT set here: on a
 * navy field .hero-field paints it --on-dark at (0,2,0); on white it
 * inherits --ink from the h1 rule.
 */
/* LINE-HEIGHT .96 -> 1.02. §4's table says .96, and .96 is not physically
   available in this face: measured with canvas TextMetrics in the real loaded
   Manrope ExtraBold, the ink extent of "Thpgy" at 112px is 110.0px against a
   107.5px line step — the leading was 2.5px INSIDE its own ink. That is not a
   theoretical risk; on index.html the descender of the "p" in "profitable"
   and the ascender of the "h" in "channel." overlap horizontally by 4.6px and
   vertically by 0.48px. 1.02 gives a 114.2px step, +4.2px of clearance, and
   is still far tighter than body (1.65), so "tighter leading on display type"
   holds. h1 at 1.00 was measured too and is fine: +1.4px of clearance and no
   real glyph pair collides (worst measured pair on a 2-line h1: +20px). */
.display{
  font-size:clamp(56px,8.5vw,112px);
  font-weight:800;line-height:1.02;letter-spacing:-.035em;
  text-wrap:balance;
  margin:0 0 var(--space-5);
}

/*
 * .lead-xl — hero sub and section leads. Max 50ch, per §4.
 * (0,1,0). It carries no colour either: --body on white by inheritance from
 * <body>, --on-dark-body on navy via the band rules further down.
 */
.lead-xl{
  font-size:clamp(19px,2.1vw,26px);
  font-weight:400;line-height:1.45;letter-spacing:0;
  max-width:50ch;
}

/* .micro — the line under a CTA, a plate date, a legal note. */
/* max-width added: unbounded, .micro under the homepage CTA measured a
   169-character line. 62ch is §4's body measure. */
.micro{font-size:13px;font-weight:400;line-height:1.5;letter-spacing:0;color:var(--muted);max-width:62ch}

/*
 * .lime — the ONE lime keyword permitted in a hero H1, on navy, once per
 * page (§3.4 rule 5, which also deletes the .hl swash from every template).
 * Scoped to a dark ground on purpose: lime on white is 1.2:1. On a light
 * band it falls back to --ink so a mis-placed span degrades to plain type
 * rather than to something illegible.
 */
.lime{color:var(--ink)}
.section--navy .lime,
.hero-field .lime,
.cta-band .lime{color:var(--lime)}

/* Accessibility */
:focus-visible{outline:2px solid var(--ink);outline-offset:3px;border-radius:2px}
.screen-reader-text{position:absolute!important;clip:rect(1px,1px,1px,1px);width:1px;height:1px;overflow:hidden;word-wrap:normal!important}
.skip-link{position:absolute;left:-9999px;top:0;background:var(--navy);color:#fff;padding:12px 20px;z-index:1000;font-weight:700}
.skip-link:focus{left:0}

/* ==========================================================================
   Layout
   ========================================================================== */
.container{max-width:var(--container);margin:0 auto;padding:0 var(--gutter)}
.section{padding:var(--section) 0}
.section__lead{max-width:60ch;color:var(--body);font-size:18px}

/* ──────────────────────────────────────────────────────────────────────────
   SECTION SURFACES — the ground rules (DIRECTION.md §3.4)

   1. A band is .section--navy or it is plain .section. THERE IS NO THIRD
      SURFACE.
   2. No two adjacent sections share a background. The ladder alternates
      navy → white → navy → white WITHOUT EXCEPTION and the page ENDS on
      navy (then the footer on --navy-deep, which is permitted: it is a
      different object, separated by a --line-dark rule).
   3. Target: ~55% of vertical pixels are Midnight Navy. Today it was one
      navy section on the homepage, which is why the brand never read as a
      COLOUR — only as dark type on white, the default state of the web.
   4. Every navy band is full-bleed: .section .section--navy .section--bleed.
      At least four full-bleed moments per page.
   5. Interior pages take the same ladder. Every page opens on a navy field
      and closes on the navy CTA.

   THERE IS NO .section--tint ANY MORE. It was retired from the templates
   first and its rules were left behind "so interior and legal templates keep
   working"; by the time that was checked, no template emitted it at all, so
   the class and its ~50 downstream variants were deleted in v1.9.2. --bg-tint
   survives and is unchanged, but only as the fill of an INSET OBJECT on white
   (.toc, .legal-toc, .author-box, .form-shell, .empty-state, .cs-proof, <pre>,
   and the .service-row / .next-prev hover) — never as a band. If you are
   reaching for a tint to break up two white sections, the answer is to make
   one of them navy or to merge them.
   ────────────────────────────────────────────────────────────────────────── */.section--navy{background:var(--navy);color:var(--on-dark-body)}
/*
 * h1 WAS MISSING FROM THIS LIST (fixed v1.8) — it read h2, h3, h4 only.
 *
 * The base rule `h1,h2,h3,h4{color:var(--ink)}` paints #0E1B2B, so ANY <h1>
 * on a navy band rendered #0E1B2B on #0E1B2B: a 1:1 contrast ratio, i.e.
 * completely invisible. It went unnoticed because the homepage had exactly
 * one navy section and no h1 in it.
 *
 * THE DIRECTION IS WHAT MAKES IT URGENT: §7 puts every interior page's hero
 * on a navy field, so .page-hero and .cs-hero h1 are both about to land on
 * navy across ~10 templates. The homepage hero is already safe — .hero-field
 * sets its own h1 colour — which would have made this look like a template bug
 * on the interior pages only.
 *
 * (This note listed a third class, .archive-head, when it was written. That
 * component has since been retired — its rules are gone and no template emits
 * it; see the retirement note where they used to be.)
 *
 * The print block at the foot of this file already lists `.section--navy h1`
 * among the headings it forces back to ink, which is the tell that h1 was
 * always meant to be here and was simply dropped from the screen rule.
 */
.section--navy h1,.section--navy h2,.section--navy h3,.section--navy h4{color:var(--on-dark)}
.section--navy p{color:var(--on-dark-body)}
.section--navy .kicker__num{color:var(--on-dark-body)}
.section--navy .kicker__label{color:var(--on-dark-body)}
.section--navy .kicker__line{background:var(--line-dark)}
.section--navy .arrow{color:var(--lime)}
/* Section head formula (§7): eyebrow is lime on navy, --muted on white.
   (0,2,0) beats `.eyebrow{color:var(--muted)}` at (0,1,0). */
.section--navy .eyebrow{color:var(--lime)}
.section--navy .lead-xl,
.section--navy .micro{color:var(--on-dark-body)}

/* ──────────────────────────────────────────────────────────────────────────
   THE NAVY PALETTE, MEASURED ONCE

   Every `.section--navy` override in this file resolves to one of six paints.
   Their ratios are recorded here rather than repeated at each of the ~180
   rules that use them, so a component variant added later has a table to
   check itself against instead of a guess. WCAG 2.2, sRGB, computed not
   estimated.

     TEXT ON THE BAND ITSELF          against --navy #0E1B2B
       --on-dark       #F5F7F9       16.16:1   headings, card titles, links
       --on-dark-body  #A8B4C2        8.24:1   body copy, meta, labels
       --lime          #C6F432       13.54:1   eyebrows, arrows, link hover

     TEXT ON A CARD INSET IN THE BAND against --surface-dark #13243A
       --on-dark       #F5F7F9       14.58:1
       --on-dark-body  #A8B4C2        7.44:1
       --lime          #C6F432       12.22:1

   All six clear 4.5:1 for body text and 3:1 for large text with room to
   spare, so a component can ground to the band or to a card without its
   colours needing to change.

   NOT TEXT, AND NOT SUBJECT TO 4.5:1:
       --surface-dark on --navy        1.11:1   the card ground. It is a
                                                separation of two grounds; the
                                                CARD IS READ FROM ITS HAIRLINE,
                                                not from the 6% lift, which is
                                                why every card variant sets
                                                border-color as well.
       --line-dark  #22334A on navy    1.36:1   hairlines. Decorative dividers
                                                carry no minimum; where a
                                                border is the only thing
                                                marking an INTERACTIVE
                                                boundary (focus rings,
                                                :hover, .page-numbers.current)
                                                the variant lifts it to
                                                --on-dark-body 8.2:1 or
                                                --on-dark 16.2:1 instead, both
                                                well over the 3:1 that
                                                non-text UI needs.

   THE TRAP: `--blue` is #0E1B2B — the SAME VALUE AS `--navy`. It was
   repointed when the invented mid-blue was removed, so any light-mode rule
   painting `var(--blue)` renders navy-on-navy (1:1, invisible) the moment its
   component lands on a navy band. That is what `.post-card:focus-within` and
   `.cs-card:focus-within` were doing before v1.8.2. Grep `var(--blue)` before
   adding a component to a navy band.
   ────────────────────────────────────────────────────────────────────────── */

/*
 * .section--bleed — the full-bleed utility (§3.4 rule 3).
 * The <section> loses its own horizontal padding and runs edge to edge; the
 * inner .container re-establishes the reading measure. Use it on the hero,
 * the marketplace band, the team band, the proof field and the final CTA.
 */
.section--bleed{width:100%;max-width:none;padding-left:0;padding-right:0}
.section--bleed > .container{max-width:var(--container);margin:0 auto;padding:0 var(--gutter)}

/*
 * ANCHOR OFFSET FOR EVERY BAND THAT CAN BE LINKED TO.
 *
 * .site-header is `position:sticky; top:0` with a 76px min-height, so a jump
 * to `#calculator` or `#case-studies` parks the band's eyebrow and heading
 * UNDERNEATH the bar and the visitor lands mid-grid, on rows with no head
 * above them. template-parts/section-case-studies.php shipped this scoped to
 * its own band; it is promoted here because the bug is not that band's, it is
 * every id'd band's, and there was no global rule for it anywhere in the file.
 *
 * (0,2,0) — one class plus one attribute. Nothing else in the sheet declares
 * scroll-margin, so this contests nothing; it is written as an attribute
 * selector rather than a utility class so a band cannot acquire an id and
 * forget the offset.
 */
.section[id]{scroll-margin-top:calc(76px + var(--space-5))}

/* ==========================================================================
   Eyebrow / kicker / arrow motif
   ========================================================================== */
.eyebrow{
  display:block;
  font-size:12px;font-weight:700;letter-spacing:.1em;text-transform:uppercase;
  color:var(--muted);margin-bottom:var(--space-4);
}

.kicker{display:flex;align-items:center;gap:14px;margin-bottom:var(--space-5)}
.kicker__num{font-size:12.5px;font-weight:800;color:var(--blue);letter-spacing:.06em;font-variant-numeric:tabular-nums;font-feature-settings:'tnum' 1}
.kicker__line{width:36px;height:1px;background:var(--line-strong)}
.kicker__label{font-size:12px;font-weight:700;letter-spacing:.14em;text-transform:uppercase;color:var(--blue)}

/*
 * .hl — THE LIME SWASH IS DELETED (§3.4 rule 5).
 * Used once it is a signature; it shipped three times in the first three
 * screens, which made it a template default. The 33 template occurrences are
 * being removed; until they are, `.hl` renders as plain --ink on white — the
 * exact behaviour §3.4 specifies — so no template can look broken mid-migration.
 * It is replaced by exactly ONE lime keyword in the hero H1, on navy, once
 * per page: use `.lime` (see the type scale block).
 */
/*
 * THE NAVY HALF OF THE DELETION WAS NEVER DONE. The comment above says the
 * swash is gone and that `.hl` renders as plain --ink "until the templates
 * are removed" — but that only ever applied on white. On navy the line below
 * still painted --lime, and the templates are still shipping .hl 17 times
 * across 14 pages, all of them in SECTION h2s and CTA h2s at 52px. §3.4 rule
 * 5 reserves lime for exactly one keyword, in the hero, once per page, and
 * that keyword is `.lime` — so 14 pages were spending it again below the
 * fold, 1-3 times each, which is the precise thing the rule exists to stop.
 *
 * --on-dark is what a heading is on navy, so this is the same "renders as
 * plain heading colour" behaviour the white branch already had. 16.16:1.
 * The templates can now drop the span at leisure with no visual change.
 */
.hl{color:var(--ink)}
.section--navy .hl{color:var(--on-dark)}

/*
 * .arrow - NOT LEGACY ANY MORE, AND NOT A FALLBACK. Read this before deleting
 * it: the name is the only thing about it that is still historical.
 *
 * It WAS the <span> that wrapped a `&nearr;` / `&rarr;` HTML entity, and it
 * was BUG 1 - U+2197 is not in the shipped Manrope unicode-range, so the mark
 * fell through to whatever symbol font the OS supplied. That is over. No
 * template, template part or JS file in this theme emits either entity, or a
 * literal arrow glyph, any more; the five remaining mentions of `&nearr;` and
 * `&rarr;` in the tree are all inside comments describing the state above, and
 * no element anywhere carries class="arrow" in its own markup.
 *
 * WHAT WEARS THIS CLASS TODAY is the sprite itself. ecomenable_get_arrow() in
 * inc/arrow.php appends whatever $class it is handed to `.ee-arrow` and the
 * cut class, so a call site written as
 *     ecomenable_arrow( 'ne', 'inline', 'arrow' )
 * emits <svg class="ee-arrow ee-arrow--inline arrow"><use href="#ee-arrow-ne">.
 * Around fifty call sites pass 'arrow' and around thirty-five pass
 * 'btn-arrow', for exactly one reason: to keep the colour and sizing hooks in
 * this file - `.arrow`, `.section--navy .arrow`, `.btn--primary .arrow`,
 * `.site-logo .arrow` - pointing at something.
 *
 * WHICH IS WHY IT MUST BE `color` AND NOT `fill`. Each <path> inside the
 * <symbol>s in ecomenable_arrow_sprite() carries fill="currentColor" as a
 * presentation attribute on the path, and author CSS cannot select into a
 * <use> shadow tree - so the path resolves currentColor against the `color`
 * it inherits from this <svg>. Setting `color` here is what paints the mark.
 * See the .ee-plate__arrow rule further down, where a `fill` was doing nothing
 * for exactly this reason.
 *
 * `font-weight:800` is gone with the <span>: it did the work when the mark was
 * a text glyph in Manrope ExtraBold, and it is inert on an <svg>. The stem
 * weight is now drawn into the symbol geometry.
 *
 * NEW MARKUP STILL CALLS ecomenable_arrow() / ecomenable_get_arrow(). Do not
 * hand-write `class="arrow"` on anything, and never on a text node.
 */
.arrow{color:var(--blue)}

/* ==========================================================================
   Buttons
   ========================================================================== */
.btn{
  display:inline-flex;align-items:center;justify-content:center;gap:8px;
  min-height:54px;padding:15px 30px;
  border-radius:var(--radius-sm);  /* was a hard-coded 8px */
  font-size:16px;font-weight:700;line-height:1;
  text-decoration:none;cursor:pointer;border:0;
  transition:background var(--dur-fast),border-color var(--dur-fast),color var(--dur-fast);
}
.btn:hover{text-decoration:none}
/* Lime is the brand action colour — navy text on it clears AA by a mile */
.btn--primary{background:var(--lime);color:var(--navy)}
.btn--primary:hover{background:#B8E82A}
.btn--primary .arrow,.btn--primary .btn-arrow{color:var(--navy)}
.btn--secondary{background:transparent;color:var(--blue);border:1px solid var(--line-strong)}
.btn--secondary:hover{border-color:var(--blue)}
.btn--secondary .arrow{color:var(--blue)}
/* Reachable only via template-parts/empty-state.php, which concatenates
   btn--{primary|secondary|navy}. Invisible to a grep for "btn--navy". */
.btn--navy{background:var(--navy);color:#fff}
.btn--navy:hover{background:#16283C}
.btn--navy .btn-arrow{color:var(--lime)}

/*
 * ─── THE NAVY SECONDARY'S BORDER, REPAINTED (v1.9.1, findings 12 and 32) ──
 *
 * WAS: `border-color:var(--line-dark)`. --line-dark #22334A on --navy #0E1B2B
 * measures 1.36:1 — relative luminances 0.03204 and 0.01051, so
 * (0.03204+0.05)/(0.01051+0.05) = 1.36 — against the 3:1 WCAG 1.4.11 asks of
 * a UI component boundary. `.btn--secondary` sets `background:transparent`,
 * so that border is the ONLY thing separating the control from the band; at
 * 1.36:1 the button reads as a line of text that happens to be indented.
 * v1.9 flagged this and declined it as "a design call, not an integration
 * one". It is taken now, because the pricing estimator made it load-bearing:
 * the `.calc-submit` button in page-pricing.php — "Update the estimate" — is
 * the one control a visitor with JavaScript off must find to use that band at
 * all.
 *
 * NOW: --slate #8C98A8 on --navy #0E1B2B = 5.93:1 (L 0.30857 / 0.01051), and
 * 5.35:1 on the --surface-dark #13243A panels some navy bands inset (L
 * 0.01707). Both clear 3:1 with room to spare.
 *
 * WHY --slate AND NOT --on-dark-body, WHICH IS WHAT BOTH VERIFIERS PROPOSED.
 * --on-dark-body #A8B4C2 is 8.24:1 here, so it clears the bar — but it is the
 * value the NEXT line already uses for :hover. Painting the rest state with
 * the hover colour deletes the hover step: the button would answer a pointer
 * with nothing at all, on every navy band on the site. --slate is the fifth
 * locked brand value (see the token block) and had no job until now; it sits
 * between the two, so the rest state clears 1.4.11 and hover still moves
 * 5.93:1 -> 8.24:1. This is the whole fix — no per-control override.
 *
 * NOT ADDED: `.section--navy .calc-submit .btn--secondary{…}` at (0,3,0),
 * which the comment above page-pricing.php's `.calc-submit` paragraph names. It
 * was requested to lift
 * that one button while the site-wide rule stayed broken; with the site-wide
 * rule repainted it would only make one secondary button louder than every
 * other one — and pinning it to --on-dark-body would cost it its hover step
 * for the same reason as above. The `.calc-submit` wrapper is still
 * load-bearing (the print block hides it, and calculators bind to it), just
 * not for this.
 * ────────────────────────────────────────────────────────────────────────── */
.section--navy .btn--secondary{color:var(--on-dark);border-color:var(--slate)}   /* 16.16:1 ink · 5.93:1 border */
.section--navy .btn--secondary:hover{border-color:var(--on-dark-body)}           /* 8.24:1 */
.section--navy .btn--secondary .arrow{color:var(--lime)}                         /* 13.54:1 */

/* ==========================================================================
   Header / navigation
   ========================================================================== */
.site-header{
  position:sticky;top:0;z-index:100;
  background:rgba(255,255,255,.9);
  backdrop-filter:blur(12px);
  -webkit-backdrop-filter:blur(12px);
  border-bottom:1px solid transparent;
  transition:border-color var(--dur-base);
}
.site-header.is-scrolled{border-bottom-color:var(--line)}
.site-header__inner{
  display:flex;align-items:center;justify-content:space-between;gap:var(--space-5);
  min-height:76px;
}
.site-logo{display:flex;align-items:center;gap:2px;font-size:21px;font-weight:800;color:var(--ink);letter-spacing:-.02em;text-decoration:none}
.site-logo:hover{text-decoration:none}
.site-logo .arrow{font-size:22px;margin:0 2px;color:var(--blue)}
.site-logo img{max-height:36px;width:auto}

.main-nav{display:flex;align-items:center;gap:var(--space-6)}
/* `>` is load-bearing: a descendant selector here also matches the nested
   <ul class="sub-menu"> and lays the dropdown out inline. */
.main-nav > ul{display:flex;gap:var(--space-6);list-style:none;margin:0;padding:0}
.main-nav a:not(.btn){color:var(--ink);font-weight:600;font-size:15.5px;text-decoration:none;transition:color var(--dur-fast)}
.main-nav a:not(.btn):hover,.main-nav .current-menu-item>a:not(.btn){color:var(--muted)}

.nav-toggle{display:none;background:none;border:0;cursor:pointer;padding:10px;min-width:44px;min-height:44px}
/* No transition: the design is deliberately static (see DESIGN.md). The
   transforms below are static end states, not motion. */
.nav-toggle span{display:block;width:24px;height:2px;background:var(--ink);margin:5px 0}
.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)}

@media (max-width:1023px){
  .nav-toggle{display:block}
  /*
   * Anchored to the header itself (.site-header is position:sticky, so it is
   * the positioned ancestor) rather than to a hard-coded 76px from the top of
   * the viewport. That offset was wrong whenever the announcement bar pushed
   * the header down, or the custom logo made the bar taller than 76px.
   */
  /*
   * …AND THE max-height ONE LINE BELOW KEPT THE BUG THE COMMENT ABOVE SAYS
   * IT FIXED. `top` was moved off the hard-coded 76px; `calc(100vh - 76px)`
   * was not. Measured at 375x812 with the announcement bar up: the drawer
   * opened at y=182 (announcement 106 + header 77) and 736px of max-height
   * put its bottom at 918 — 106px past the fold, with "Book a growth audit"
   * at y=902-956, entirely off screen. Its own content overflowed too
   * (scrollHeight 807 v clientHeight 736) but you could not reach the scroll,
   * because the scrolling box itself ran off the bottom of the screen.
   *
   * --nav-offset is set by main.js from header.getBoundingClientRect().bottom
   * each time the drawer opens and on scroll while it is open — the one
   * number CSS cannot see, because the header is sticky and the announcement
   * bar above it scrolls away underneath. The 76px fallback is only reached
   * if the script does not run, which is the state we are already in today.
   * 100dvh, not 100vh, so mobile browser chrome is counted too.
   */
  .main-nav{
    display:none;
    position:absolute;top:100%;left:0;right:0;
    max-height:calc(100dvh - var(--nav-offset,76px));
    background:var(--bg);
    flex-direction:column;align-items:flex-start;
    padding:var(--space-6) var(--gutter);
    overflow-y:auto;
    overscroll-behavior:contain;
  }
  .nav-open .main-nav{display:flex}
  .main-nav > ul{flex-direction:column;gap:var(--space-4);width:100%}
  .main-nav a{font-size:24px;font-weight:700}
  /* 24px/700 gave a 22px-tall hit area on the five top-level items — below
     even the 24px WCAG 2.5.8 floor, let alone 44px. `display:block` + 11px of
     block padding makes the row 44px without moving a single glyph; the
     sub-items already measured 41.2px and are left alone so the drawer does
     not grow any taller than it has to. `:not(.btn)` keeps the full-width
     CTA button out of it — it is already 54px. */
  .main-nav a:not(.btn){display:block;padding:11px 0}
  .main-nav .btn{margin-top:var(--space-5);width:100%}
}

/* ==========================================================================
   Hero — the action row, and nothing else
   ==========================================================================
   THE v1.0 TWO-COLUMN HERO WAS DELETED HERE (v1.8.2). `.hero`, `.hero__grid`,
   `.hero__copy`, `.hero__sub`, `.hero__tagline`, `.hero__micro`,
   `.hero__trust` and `.hero__visual` are gone, along with the tint variant of
   `.hero__trust` and the mobile `.hero` padding. §8 replaced the whole
   construction with `.hero-field`, and a literal grep for each of those eight
   class names across all 60 PHP files returns zero — no template has emitted
   any of them since the field landed. Do not resurrect them: the hero is
   `.hero-field`, and an interior hero is `ecomenable_page_hero()`.

   `.hero__ctas` IS THE ONE SURVIVOR AND IT IS NOT LEGACY. hero-field.php
   emits it for the button row — the row is named for the action it holds
   rather than for the component that holds it, which is why it kept the old
   name when everything around it changed — and `.hero-field__copy
   .hero__ctas` further down re-sizes it inside the field. */
.hero__ctas{display:flex;flex-wrap:wrap;gap:var(--space-3);align-items:center;margin-bottom:var(--space-3)}

/* ─── THE HERO DASHBOARD CARD IS GONE (v1.8.2) ───────────────────────
   `.dash-card`, `.dash-card__head`, `.dash-card__title`, `.dash-card__foot`,
   `.dash-metrics`, `.dash-metric`, `.dash-metric__num`, `.dash-metric__label`,
   `.dash-chart` and `.grid-line` were marked SCHEDULED FOR DELETION while
   front-page.php still carried the markup. front-page.php dropped it, the grep
   across all 60 PHP files now returns zero for every one of those ten names,
   and the block has been deleted as promised — with its tint variant and its
   mobile padding override.

   Nothing replaces it in place. The empty metrics card, its three em dashes
   and its "Illustrative — no client data shown" caption were the single most
   damaging thing in the fold: a written admission that there was nothing in
   it. The hero is `.hero-field` (§8), and proof only ever renders from the
   database. Do not rebuild a metrics card with placeholder figures in it.
   ─────────────────────────────────────────────────────────────────── */

/* ==========================================================================
   Marketplace row — static strip between hairlines
   ========================================================================== */
/* Same 48px step the filter bar uses. This strip always follows a navy band, and
   with padding:0 the label sat at a measured 0px below it against 24px beneath —
   the identical asymmetry the archive filter bar had. One step value for every
   white block that opens directly under a band. */
/* …and the same step CLOSES it. With `0` on the bottom edge the strip's own
   `border-bottom` landed on the exact pixel where the white band handed over
   to navy (measured: 0.0px from .mp-row's box bottom to the section edge), so
   the hairline was invisible AND the band terminated with no breathing room —
   48px open against 0px close, the same asymmetry mirrored onto the other
   edge. 48/48 keeps the sanctioned tight step and gives the hairline
   something to be the edge OF. */
.marketplaces{padding:var(--space-7) 0;margin:0}
/* Specificity 0,2,0 — must out-rank the base `p:last-child{margin-bottom:0}` rule,
   which otherwise collapses this label onto the strip's top hairline. */
.marketplaces .marketplaces__label{
  font-size:12px;font-weight:700;letter-spacing:.1em;text-transform:uppercase;
  color:var(--muted);margin:0 0 var(--space-5);
}
.mp-row{
  border-top:1px solid var(--line);border-bottom:1px solid var(--line);
  padding:26px 0;
}
.mp-row__inner{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:var(--space-4) var(--space-5)}
.mp{font-size:13.5px;font-weight:700;letter-spacing:.1em;text-transform:uppercase;color:var(--blue);white-space:nowrap}
.mp--primary{color:var(--ink)}
.mp--primary .arrow{margin-right:5px;color:var(--ink)}

/* --- The labelled chip (v1.9) -------------------------------------------
 * A chip is now optionally two lines: the channel name, and under it the
 * label saying why the channel is on the list (Primary Focus / Expansion /
 * UK High Intent). The label is SECONDARY INFORMATION and the type has to say
 * so without a box, a pill or a tint — this strip is a hairline row, not a
 * card rack, so the whole hierarchy is carried by size, weight, tracking and
 * colour:
 *
 *   name   13.5px / 700 / .1em  / --ink   #0E1B2B on #FFFFFF = 17.35:1
 *   label  10.5px / 600 / .14em / --muted #5A6A7E on #FFFFFF =  5.53:1
 *
 * 5.53:1 clears AA body text (4.5:1) at any size, so the label is quiet
 * without being unreadable. The wider tracking is what makes it read as a tag
 * rather than as a second, smaller channel name. No transition, no hover:
 * nothing in this strip moves.
 *
 * template-parts/section-marketplaces.php adds --labelled only to the chips
 * that actually carry a label, so a caller passing plain strings keeps the
 * single-line rendering this strip has always had.
 */
/* (0,1,0), same as `.mp` — and there is nothing to resolve. `.mp` declares
   font, colour and white-space and never declares display, flex-direction or
   gap, so this modifier only adds. */
.mp--labelled{display:flex;flex-direction:column;gap:4px}
/* `inline-block` is harmless in an unlabelled chip and is blockified inside a
   labelled one, so one declaration covers both shapes the partial emits. */
.mp__name{display:inline-block}
/* Declared size/weight/colour always beat what this would inherit from `.mp`
   — inherited values carry no specificity — so it needs no scoping to win,
   and staying at (0,1,0) leaves the navy override room to out-rank it. */
.mp__label{
  display:block;
  font-size:10.5px;font-weight:600;letter-spacing:.14em;text-transform:uppercase;
  color:var(--muted);
}
/* Specificity 0,2,0 — must out-rank `.mp-row__inner{align-items:center}` at
   (0,1,0). With centring, a one-line chip sitting beside a labelled one floats
   half a label's height below its neighbours' names and the row loses its
   baseline. Aligning to the start keeps every channel name on one line
   whatever does or does not sit beneath it. */
.mp-row .mp-row__inner--labelled{align-items:flex-start}
@media (max-width:719px){
  .mp-row{padding:22px 0}
  .mp-row__inner{justify-content:flex-start;gap:var(--space-3) var(--space-5)}
}

/* ==========================================================================
   Cards & grids
   ========================================================================== */
.grid{display:grid;gap:var(--space-5)}
.grid--2{grid-template-columns:repeat(2,1fr)}
.grid--3{grid-template-columns:repeat(3,1fr)}
@media (max-width:1023px){.grid--3{grid-template-columns:repeat(2,1fr)}}
@media (max-width:719px){.grid--2,.grid--3{grid-template-columns:1fr}}
/* `.grid--4` HAD THREE RULES HERE AND NO EMITTER — grep the theme and the only
   hits were these three lines. Deleted rather than kept, for the same reason as
   the retired .archive-head block further down this file: an unused modifier
   reads as a supported option, and four 1fr tracks inside the 1240px container
   is a 286px column, which is under the card minimum every real grid on this
   site is built to. The genuine four-up is
   `.team-grid--4` (template-parts/team-grid.php), which is a different
   component with its own breakpoints and is unaffected by this. */

.card{
  display:flex;flex-direction:column;
  background:var(--bg);
  border:1px solid var(--line);
  border-radius:var(--radius-md);
  padding:var(--space-6);
  transition:border-color var(--dur-fast);
}
.card:hover{border-color:var(--line-strong)}
.card h3{margin-bottom:var(--space-3)}
.card p{color:var(--body);font-size:16px}
.card__num{
  font-size:12.5px;font-weight:800;color:var(--muted);
  letter-spacing:.08em;margin-bottom:var(--space-4);
  font-variant-numeric:tabular-nums;font-feature-settings:'tnum' 1;
}
.card__link{
  display:inline-flex;align-items:center;align-self:flex-start;gap:7px;
  margin-top:auto;padding-top:var(--space-5);
  font-weight:700;font-size:15px;color:var(--blue);
}
.card__link:hover{text-decoration:none;gap:11px}.section--navy .card{background:var(--surface-dark);border-color:var(--line-dark)}
.section--navy .card p{color:var(--on-dark-body)}
.section--navy .card__num{color:var(--on-dark-body)}
.section--navy .card__link{color:var(--lime)}

/* ==========================================================================
   Stats
   ========================================================================== */
.stats{display:grid;grid-template-columns:repeat(auto-fit,minmax(190px,1fr));gap:var(--space-6)}
/* The BEM block itself. Layout survives without it because .stats is a grid, but a long
   stat label was free to stretch the track — min-width:0 keeps the columns honest. */
.stat{min-width:0}
.stat__number{
  font-size:clamp(38px,4.4vw,54px);font-weight:800;color:var(--ink);
  letter-spacing:-.03em;line-height:1;font-variant-numeric:tabular-nums;font-feature-settings:'tnum' 1;
  display:flex;align-items:baseline;gap:6px;
}
.stat__label{margin-top:var(--space-3);font-size:15px;color:var(--muted)}
.section--navy .stat__number{color:var(--on-dark)}.section--navy .stat__label{color:var(--on-dark-body)}

/* ==========================================================================
   Process steps
   ========================================================================== */
.steps{counter-reset:step}
.step{
  display:grid;grid-template-columns:52px 1fr;gap:var(--space-5);
  padding:var(--space-5) 0;border-top:1px solid var(--line);
}
.step:last-child{border-bottom:1px solid var(--line)}
.step__num{
  counter-increment:step;
  font-weight:800;font-size:14px;color:var(--blue);
  font-variant-numeric:tabular-nums;font-feature-settings:'tnum' 1;padding-top:5px;
}
.step__num::before{content:counter(step,decimal-leading-zero)}
.step h3{font-size:20px;margin-bottom:var(--space-2)}
.step p{color:var(--body);font-size:16px;max-width:62ch}
.section--navy .step{border-color:var(--line-dark)}
.section--navy .step:last-child{border-bottom-color:var(--line-dark)}

/* ==========================================================================
   Why us / differentiators
   ========================================================================== */
.why-item{display:grid;grid-template-columns:26px 1fr;gap:var(--space-4);align-items:start}
.why-item .arrow{font-size:19px;line-height:1.5;color:var(--blue)}
.why-item h3{font-size:18.5px;font-weight:700;margin-bottom:var(--space-2)}
.why-item p{color:var(--body);font-size:16px}
.callout{
  margin-top:var(--space-7);
  border:1px solid var(--line-strong);border-radius:var(--radius-md);
  background:var(--bg);
  padding:var(--space-5) var(--space-6);
  font-weight:700;font-size:17px;color:var(--ink);
}
.callout .arrow{margin-right:10px}
/*
 * A CALLOUT THAT OPENS A BAND HAS NOTHING ABOVE IT TO STEP AWAY FROM.
 *
 * `.callout{margin-top:var(--space-7)}` is right for a callout that follows
 * something and wrong for one that is the first thing in a band: it stacks
 * its own 48px on top of the section's --section padding. The `.callout` that
 * opens the estimator band in page-pricing.php is exactly that case and used to
 * carry `style="margin-top:0"` on the div —
 * the same spacing-zeroing-by-attribute that rule 6 and the BAND-CONTENT
 * RHYTHM block exist to stop, because an inline attribute is a value no
 * cascade can reach and no audit can find.
 *
 * (0,2,0) — class plus pseudo-class — over the base's (0,1,0). Structural
 * rather than a class in the markup, and the identical idiom
 * `.section-block:first-child{margin-top:0}` already ships in section 1.
 *
 * BLAST RADIUS, CHECKED BY SELECTOR RATHER THAN BY LINE: the only other
 * `.callout` instances are the two editor-note branches on the About founder
 * band (the `! has_post_thumbnail()` note and the placeholder-plate note), the
 * permission callout that closes the About credentials band, and the UK-channel
 * callout that closes the page-marketplaces.php grid. The marketplaces one
 * follows a grid so it never matches. The About ones are all preceded by
 * conditional blocks, so any of them can become the first child when those
 * collapse — and in that case zeroing is what is wanted, for the same reason
 * .section-block:first-child ships with: the band's own padding is already the
 * correct space above the first thing in it.
 */
.callout:first-child{margin-top:0}

/* ==========================================================================
   FAQ (native details)
   ========================================================================== */
.faq{max-width:820px}
.faq details{border-top:1px solid var(--line)}
.faq details:last-child{border-bottom:1px solid var(--line)}
.faq summary{
  cursor:pointer;list-style:none;
  padding:var(--space-5) var(--space-7) var(--space-5) 0;
  font-weight:700;font-size:17.5px;color:var(--ink);position:relative;min-height:44px;
}
.faq summary::-webkit-details-marker{display:none}
.faq summary::after{
  content:'+';position:absolute;right:4px;top:50%;transform:translateY(-50%);
  color:var(--blue);font-size:24px;font-weight:400;
}
.faq details[open] summary::after{transform:translateY(-50%) rotate(45deg)}
.faq .faq__body{padding:0 0 var(--space-5);color:var(--body);max-width:66ch}

/* ==========================================================================
   Final CTA — navy card on white
   ========================================================================== */
/* The 32px here is a leftover from when the CTA was a rounded card floating
   inside a white section — it needed to sit close to the content above it.
   It is now a full-bleed navy band like every other, and a band-boundary audit
   measured it opening at 32px while all seven other bands on the homepage open
   at 88px. Inherit the section rhythm instead of undercutting it. */
.section--cta{padding-top:var(--section)}
.cta-band{
  background:var(--navy);
  border-radius:var(--radius-lg);
  padding:var(--space-8) var(--space-7);
  display:grid;grid-template-columns:1fr auto;gap:var(--space-7);align-items:center;
  text-align:left;
}
/*
 * ─── THE CARD IS FOR THE WHITE-BAND CASE ONLY ────────────────────────────
 *
 * The block above describes a navy card floating on a white section. NO
 * TEMPLATE SHIPS THAT TODAY — correcting a claim this note carried for several
 * rounds. 404, archive, author, category, home, index, search, single and tag
 * were each migrated to `section section--cta section--navy section--bleed`,
 * and a grep for `section--cta` not followed by `section--navy section--bleed`
 * returns only prose and the partial itself. The one surviving path to the card
 * is `surface => 'light'` in template-parts/cta-band.php, which is a supported
 * argument with no caller. Do not delete the block: it is what that argument
 * renders, and deleting it would turn a documented option into a silent no-op.
 *
 * On the OTHER path — the §7 close, `section section--cta section--navy
 * section--bleed`, which is every Phase-1 page and the prototype's 16 pages —
 * the card paints --navy on top of a --navy band. Measured: background
 * rgb(14,27,43) on rgb(14,27,43), border-radius 0. It has no visual presence
 * at all, so its 64px block padding and 48px inline padding are dead space:
 * the band opened at 179.2px where every other band on the page opened at
 * 115.2px, and the eyebrow sat at x=84.5 against the site-wide 36.5px gutter
 * (48px v 24px at 375px).
 *
 * (0,2,0) beats both `.cta-band` (0,1,0) above and the mobile
 * `.cta-band{padding:var(--space-7) var(--space-5)}` (0,1,0) in the
 * Responsive block — a media query adds no specificity, so the reset holds at
 * every width without a second rule and without touching the light variant.
 */
.section--navy .cta-band{background-color:transparent;padding:0}
/*
 * ─── THE EYEBROW ON THIS BAND IS LIME, AND IT WINS ON WEIGHT ──────────────
 *
 * BUG (v1.8.2): front-page.php ships this band as
 * `section section--cta section--navy section--bleed`, so TWO rules matched
 * the eyebrow at identical weight:
 *
 *   .eyebrow                          (0,1,0)   --muted
 *   .section--navy .eyebrow           (0,2,0)   --lime            (in the
 *                                                  section-head formula block)
 *   .cta-band .eyebrow                (0,2,0)   --on-dark-body    (here)
 *
 * (0,2,0) v (0,2,0) is a tie, and a tie is settled by source order alone —
 * so the grey won for no better reason than sitting ~360 lines further down
 * the file. The final CTA rendered a grey eyebrow while every other navy
 * band on the site rendered a lime one. THAT IS THE FOURTH SOURCE-ORDER
 * CASCADE BUG IN THIS STYLESHEET (see also `.trajectory--navy`, the h1 that
 * was missing from the `.section--navy` heading list, and `.step p`), so it
 * is not enough to fix the colour: the winner has to be decided by weight.
 *
 * THE DECISION: lime. §7's section-head formula is "eyebrow is lime on navy,
 * --muted on white", and `.cta-band` paints `--navy` on EVERY page — inside a
 * navy band on the homepage, as an inset navy card on the interior pages. The
 * eyebrow is on navy in both cases, so there was never a page where grey was
 * the right answer.
 *
 * THE MECHANISM: `.section--cta` is on the wrapping <section> of every
 * `.cta-band` in the theme — the one in template-parts/cta-band.php plus the
 * nineteen inline copies in 404, archive, author, category, home, index,
 * page-about, page-contact, page-faq, page-free-audit, page-marketplaces,
 * page-pricing, page-reviews, page-services, search, single, tag,
 * template-marketplace and template-service — so the second selector below
 * computes to
 *
 *   .section--cta .cta-band .eyebrow  (0,3,0)
 *
 * which outranks `.section--navy .eyebrow` (0,2,0) whatever the order of the
 * file. The first selector keeps the standalone case painting the same colour
 * so the two can never disagree. Moving either block now changes nothing.
 *
 * CONTRAST: --lime #C6F432 on --navy #0E1B2B = 13.5:1.
 * ────────────────────────────────────────────────────────────────────────── */
.cta-band .eyebrow,
.section--cta .cta-band .eyebrow{color:var(--lime)}
.cta-band h2{color:var(--on-dark);max-width:19ch;margin-bottom:var(--space-3)}
/* (0,3,0) — it out-ranks the `.section--navy .hl` demotion above, so it has
   to be demoted here too or the CTA headline keeps the swash on all 16 pages.
   Same reason: one lime keyword, in the hero, once per page. */
.cta-band h2 .hl{color:var(--on-dark);box-shadow:none}
.cta-band p{color:var(--on-dark-body);max-width:52ch;margin:0}
/*
 * THE EYEBROW IS A <p> NOW, AND `.cta-band p{margin:0}` WAS EATING ITS GAP.
 *
 * template-parts/cta-band.php emits `<p class="eyebrow">` rather than a
 * <span> (finding 47 — every other band on the site writes it as a paragraph,
 * and `.eyebrow{display:block}` made the two forms one element apart while
 * behaving differently under any future display or em-margin change). One
 * element, every band the partial renders — no count is written here on
 * purpose, because the caller list moves and a number in a comment does not.
 *
 * THE FIGHT: `.eyebrow{margin-bottom:var(--space-4)}` is (0,1,0) and the line
 * directly above is (0,1,1) — one class, one type — so the shorthand's
 * margin:0 out-ranks it on weight and the eyebrow sat hard against the h2:
 * 0px where every other band gives 16px. front-page.php has been rendering
 * that way all along, because its hand-built copy of this band already used a
 * <p>; moving to the partial only made it uniform. (The requesting agent read
 * `.cta-band p` as (0,2,0). It is (0,1,1). The conclusion holds either way —
 * both beat a bare .eyebrow — but the number is corrected so the next person
 * does not compute from it.)
 *
 * (0,2,1): two classes and a type, which beats (0,1,1) on weight rather than
 * on merge order, so reshuffling this section cannot silently undo it.
 *
 * NO COLOUR RULE IS NEEDED: `.section--cta .cta-band .eyebrow` above is
 * (0,3,0) and already beats `.cta-band p`'s (0,1,1) colour on both grounds
 * this partial emits. --lime #C6F432 on --navy #0E1B2B = 13.54:1.
 */
.cta-band p.eyebrow{margin-bottom:var(--space-4)}
.cta-band .btn--primary{background:var(--lime);color:var(--navy)}
.cta-band .btn--primary:hover{background:#B8E82A}
.cta-band .btn--primary .btn-arrow{color:var(--navy)}
/*
 * The band paints --navy itself but is NOT a .section--navy, so neither the
 * `.section--navy .btn--secondary` overrides (in the navy-button contrast
 * block) nor the
 * `.section--navy :focus-visible` umbrella reach inside it. Mirrored here at
 * (0,2,0) / (0,1,1)+.
 *
 * The focus line is the load-bearing one: the base `:focus-visible` ring is
 * `2px solid var(--ink)` -- #0E1B2B on a #0E1B2B band -- so keyboard focus is
 * currently invisible on every CTA button on the site.
 *
 * BORDER REPAINTED WITH THE OTHER ONE (v1.9.1, finding 32, which names this
 * line as the second site of the same pairing). --line-dark on the --navy
 * this band paints itself was 1.36:1, under the 3:1 of WCAG 1.4.11, and this
 * button has a transparent background so the border is its only boundary.
 * --slate #8C98A8 on --navy #0E1B2B = 5.93:1, and hover still steps up to
 * --on-dark-body at 8.24:1. Same reasoning in full at the Buttons section:
 * repainting the rest state --on-dark-body would have deleted the hover step.
 * These two lines and that block must move together — a .cta-band inside a
 * .section--navy matches both, and the two are (0,2,0) each, so if their
 * values ever disagree the winner is decided by source order.
 */
.cta-band .btn--secondary{background:transparent;color:var(--on-dark);border-color:var(--slate)}  /* 16.16:1 ink · 5.93:1 border */
.cta-band .btn--secondary:hover{border-color:var(--on-dark-body)}                                /* 8.24:1 */
.cta-band .btn--secondary .arrow,
.cta-band .btn--secondary .btn-arrow{color:var(--lime)}
.cta-band :focus-visible{outline-color:var(--on-dark)}
@media (max-width:1023px){.cta-band{grid-template-columns:1fr;gap:var(--space-6)}}

/*
 * THE FOOTER IS THE THIRD DARK GROUND AND NOTHING WAS INVERTING ITS RING.
 *
 * .site-footer paints --navy-deep #08121F, but it is neither a .section--navy
 * nor a .cta-band, so neither of the two overrides above reaches it. Every
 * one of its 22 links therefore fell through to the base
 * `:focus-visible{outline:2px solid var(--ink)}` — #0E1B2B on #08121F, a
 * measured 1.08:1 ring on a dark ground. Confirmed by walking the CSSOM: the
 * base rule was the ONLY :focus-visible rule matching a footer link. That is
 * 22 controls x 16 pages with no visible keyboard focus at all.
 *
 * (0,1,1)+(0,1,0) = (0,2,0), so it beats the base (0,1,0) the same way the
 * .cta-band line above does. --on-dark #F5F7F9 on #08121F = 17.4:1.
 */
.site-footer :focus-visible{outline-color:var(--on-dark)}

/* ==========================================================================
   Footer
   ========================================================================== */
.site-footer{background:var(--navy-deep);color:var(--on-dark-body);padding:var(--space-8) 0 var(--space-6);font-size:15.5px}
.site-footer__grid{display:grid;grid-template-columns:2fr 1fr 1fr 1fr;gap:var(--space-6)}
@media (max-width:1023px){.site-footer__grid{grid-template-columns:1fr 1fr;gap:var(--space-7) var(--space-6)}}
@media (max-width:719px){.site-footer__grid{grid-template-columns:1fr}}
/* The two grid-child names footer.php emits and this sheet had no rule for.
   They are not decoration: a grid item defaults to `min-width:auto`, which is
   its CONTENT's minimum, so one unbreakable string — the mailto address in
   .site-footer__contact, or a long menu label in a column — could push its
   track wider than its share and overflow the footer horizontally. min-width:0
   lets the track shrink and the text wrap instead. (0,1,0); nothing else in
   this sheet sets min-width on a footer child, so there is nothing to out-rank.

   footer.php's other two unstyled names, .site-footer__contact-item and
   .site-footer__social-link, were removed from the markup in the same pass
   rather than styled: `.site-footer li` and `.site-footer a` / `.site-footer
   li a` already carry every declaration those two leaves needed, so dropping
   the names changed no computed style. */
.site-footer__brand,.site-footer__col{min-width:0}
.site-footer .site-logo{color:var(--on-dark)}
.site-footer .site-logo .arrow{color:var(--lime)}
.site-footer h4{font-size:12px;letter-spacing:.12em;text-transform:uppercase;color:var(--on-dark-body);font-weight:700;margin-bottom:var(--space-4)}
.site-footer ul{list-style:none;margin:0;padding:0}
.site-footer li{margin-bottom:var(--space-3)}
/* 22px tall in the columns, 18px in the legal row — under the 24px WCAG 2.5.8
   floor on 18 links per page. The padding takes the hit area to 44px and the
   matching negative margin puts the ink back exactly where it was, so the
   12px `.site-footer li` rhythm above is unchanged. inline-block is what
   makes vertical padding apply at all to what is otherwise an inline anchor. */
.site-footer li a{display:inline-block;padding:11px 0;margin:-11px 0}
.site-footer a{color:var(--on-dark);text-decoration:none}
.site-footer a:hover{color:var(--lime);text-decoration:none}
.site-footer__tagline{color:var(--on-dark-body);margin-top:var(--space-4);max-width:38ch}
.site-footer__bottom{
  display:flex;flex-wrap:wrap;justify-content:space-between;gap:var(--space-4);
  margin-top:var(--space-7);padding-top:var(--space-5);
  border-top:1px solid var(--line-dark);
  color:var(--on-dark-body);font-size:13.5px;
}
.site-footer__bottom a{color:var(--on-dark-body)}
.site-footer__bottom a:hover{color:var(--lime)}

/* ==========================================================================
   Inner pages / blog
   ========================================================================== */
.page-hero{padding:var(--section) 0 var(--space-6)}
.page-hero h1{max-width:20ch}
.entry-content{max-width:720px;font-size:18px}
.entry-content a{color:var(--blue);text-decoration:underline}
.entry-content a:hover{color:var(--blue-dark)}
.entry-content h2,.entry-content h3{margin-top:var(--space-8)}
.entry-content ul,.entry-content ol{padding-left:1.3em;margin-bottom:var(--space-5)}
.entry-content li{margin-bottom:var(--space-2)}
/* THE RULE IS NOT LIME. It was, and on insight-post.html that put a 3px lime
   graphic on a #FFFFFF band at 1.2:1 — the one lime-on-white element left on
   the site, and §3.4 rule 4 ("lime never appears on a light ground") is a
   brand-book non-negotiable, not a preference. --line-strong is the token for
   a structural rule of this weight: 1.47:1 on white as a hairline, but this
   is 3px of solid edge doing a quoting job, not a boundary the user has to
   identify. It also reads correctly on navy (11.5:1), so the navy override
   further down no longer needs to say anything about it. */
.entry-content blockquote{
  border-left:3px solid var(--line-strong);margin:var(--space-6) 0;
  padding:var(--space-1) 0 var(--space-1) var(--space-5);
  color:var(--ink);font-weight:600;
}
.entry-content img{border-radius:var(--radius-md)}
.entry-content table{width:100%;border-collapse:collapse;margin-bottom:var(--space-5)}
.entry-content th,.entry-content td{text-align:left;padding:11px 14px;border-bottom:1px solid var(--line)}
.entry-content th{color:var(--ink);font-weight:700}

/* WordPress core alignment */
.alignwide{max-width:1000px}
.alignfull{max-width:none;width:100%}
.wp-block-button__link{border-radius:var(--radius-sm)}  /* was a hard-coded 8px */

/* ==========================================================================
   Forms (Contact Form 7 / WPForms friendly)
   ========================================================================== */
input[type=text],input[type=email],input[type=url],input[type=tel],
input[type=search],input[type=number],select,textarea{
  width:100%;min-height:50px;padding:13px 16px;
  background:var(--bg);border:1px solid var(--line-strong);border-radius:var(--radius-sm);
  color:var(--ink);font-family:inherit;font-size:16px;
  /* `box-shadow` WAS THE FOURTH PROPERTY IN THIS LIST AND IS REMOVED (v1.8).
     The motion note in :root and the v1.5 house rules both say transitions
     are limited to color / background / border-color / outline-color and that
     a fourth must not be added — this declaration was the one place the file
     did not obey its own rule. Inert today only because --dur-fast is 0s,
     which is exactly how it survived two passes unnoticed. The focus ring it
     was animating is untouched: see input:focus below. */
  transition:border-color var(--dur-fast);
}
/* Strip the WebKit search chrome so the field matches every other control. */
input[type=search]{-webkit-appearance:none;appearance:none}
input[type=search]::-webkit-search-decoration,
input[type=search]::-webkit-search-cancel-button{-webkit-appearance:none}
input::placeholder,textarea::placeholder{color:var(--muted)}
input:focus,select:focus,textarea:focus{outline:none;border-color:var(--ink);box-shadow:0 0 0 3px rgba(14,27,43,.08)}
label{font-weight:700;font-size:14px;color:var(--ink);display:block;margin-bottom:7px}
/*
 * ─── `:not(.btn)` IS LOAD-BEARING. IT IS THE FIFTH CASCADE BUG. ───────────
 *
 * Without it this rule is (0,1,1) — an attribute selector plus a type — and
 * `.btn--primary{background:var(--lime)}` is (0,1,0). So on 404.php, where
 * searchform.php emits `<button type="submit" class="btn btn--primary">`,
 * the search button rendered `background rgb(14,27,43)` with white text while
 * the `.btn--primary` link six inches above it on the same page rendered
 * `rgb(198,244,50)` with navy text. Same class, two colours, one page.
 *
 * This block exists for an UNCLASSED submit control — a contact-form plugin,
 * a comment form — so it stays. It just must not out-rank the component when
 * a template has already said which button this is. `:not(.btn)` also lifts
 * the selector to (0,2,1), which is deliberate: it can no longer be beaten by
 * a later single-class rule either.
 *
 * Every property this block sets (border, radius, min-height, padding,
 * weight, size, cursor, transition) is already on `.btn`, so a .btn submit
 * loses nothing by dropping out of it.
 */
input[type=submit]:not(.btn),button[type=submit]:not(.btn){
  background:var(--navy);color:#fff;border:0;border-radius:var(--radius-sm);  /* was 8px */
  min-height:54px;padding:15px 30px;font-weight:700;font-size:16px;cursor:pointer;
  transition:background var(--dur-fast);
}
input[type=submit]:not(.btn):hover,button[type=submit]:not(.btn):hover{background:#16283C}

::selection{background:var(--lime);color:var(--navy)}

/* ==========================================================================
   Reduced motion
   ========================================================================== */
@media (prefers-reduced-motion:reduce){
  html{scroll-behavior:auto}
  *,*::before,*::after{animation:none!important;transition:none!important}
}

/* ==========================================================================
   Responsive
   ========================================================================== */
/*
 * --section is a clamp now, so the two breakpoint overrides that used to sit
 * here (60px at 1023px, 52px at 719px) are DELETED. They would have fought
 * the clamp and reinstated the cramped rhythm the repoint exists to fix.
 * clamp(88px,9vw,144px) resolves to 144px on a wide desktop, ~92px at
 * 1023px and its 88px floor on a phone — the scaling the media queries used
 * to do by hand, done once, in the token.
 */
@media (max-width:1023px){
  h1{font-size:clamp(38px,6vw,64px)}
}
@media (max-width:719px){
  body{font-size:16px}
  /* Mobile column of the §4 table: display 44, h1 38, h2 28, h3 20.
     1.02 for the same reason as the desktop rule — ink at 44px is 43.2px, so
     1.0 left 0.8px of clearance and 1.02 leaves 1.7px. */
  .display{font-size:44px;line-height:1.02}
  h1{font-size:38px}
  h2{font-size:28px}
  h3{font-size:20px}
  .lead-xl{font-size:18px}
  .hero__ctas .btn{width:100%}
  .cta-band{padding:var(--space-7) var(--space-5)}
}

/* ==========================================================================
   ==========================================================================
   v1.5 — EXTENDED COMPONENT LIBRARY  (APPEND-ONLY SECTION)

   Nothing below redefines an existing class, a design token, the @font-face
   blocks or :root — EXCEPT where a v1.7 comment says so explicitly and
   states the reason.

   (v1.7 note: "everything above this line is untouched" no longer holds.
   The v1.7 pass edited :root, the h1–h4 scale, .hl, the two list markers,
   the pill/circle radii and the Responsive block IN PLACE, because those are
   token-layer and base-layer changes and repointing them anywhere else
   would have been the fourth specificity collision in this codebase. Every
   in-place edit carries a "was X" comment at its rule.)

   House rules honoured throughout:
   - Tokens only. The only literals are rgba() tints derived from existing
     tokens: navy 14,27,43 - on-dark 245,247,249.
     (The old note here listed a third rgba() triplet as a permitted literal.
     That was the invented non-brand blue in decimal. It is gone — v1.7.)
   - No animation, no keyframes, no transform on hover, no scroll effects.
     Transitions are limited to color / background / border-color /
     outline-color at var(--dur-fast), which is now 0s.
   - Lime stays where it was already established (.btn--primary). The .hl
     swash is deleted; --blue is now the navy accent ramp, not a blue.
   - Grids collapse at the existing 1023px and 719px breakpoints.
   - Numeric displays carry font-variant-numeric:tabular-nums AND
     font-feature-settings:'tnum' 1. See the TABULAR NUMERALS block in v1.7.
   - THE ARROW IS AN SVG, NOT A GLYPH (v1.7). The note that used to sit here
     said "the brand arrow is U+2191" — that was the workaround for BUG 1,
     not a fix. Use .ee-arrow with the --inline / --ui / --arch cut. Never
     use &nearr;, &rarr;, \2197 or \2191 in new CSS or new markup.

   ---------------------------------------------------------------------------
   SPECIFICITY NOTE — READ THIS BEFORE EDITING. This has bitten the codebase
   twice already. Four base rules out-rank a single-class component rule:

       p:last-child{margin-bottom:0}                (0,1,1)
       a{color:var(--ink)} / a:hover{...}           (0,0,1) / (0,1,1)
       .section--navy p / h2,h3,h4{color:...}       (0,1,1)
       .entry-content ul,.entry-content ol{...}     (0,1,1)

   So every text, heading and link element below is scoped to its own block
   (".post-card .post-card__excerpt", not ".post-card__excerpt") to reach
   (0,2,0) or better. That is deliberate, not redundant. Do not "simplify"
   these selectors down to one class — the margins and colours will silently
   collapse the next time this file is touched.
   ==========================================================================
   ========================================================================== */

/* ==========================================================================
   Breadcrumbs
   Markup: nav.breadcrumbs > ol.breadcrumbs__list > li.breadcrumbs__item
           separators are span.breadcrumbs__sep (aria-hidden)
           the final crumb is li.breadcrumbs__item > span.breadcrumbs__current
   ========================================================================== */
.breadcrumbs{margin:0 0 var(--space-5);font-size:13.5px;line-height:1.4;color:var(--muted)}
.breadcrumbs__list{
  display:flex;flex-wrap:wrap;align-items:center;gap:var(--space-2);
  list-style:none;margin:0;padding:0;
}
/* (0,2,0) — beats `a{color:var(--ink)}` and survives .section--navy. */
.breadcrumbs .breadcrumbs__item{display:inline-flex;align-items:center;gap:var(--space-2);margin:0;color:var(--muted)}
.breadcrumbs .breadcrumbs__item a{
  color:var(--muted);text-decoration:none;
  border-bottom:1px solid transparent;
  transition:color var(--dur-fast),border-color var(--dur-fast);
}
/* (0,3,1) — beats `a:hover{text-decoration:underline}` at (0,1,1). */
.breadcrumbs .breadcrumbs__item a:hover{color:var(--blue);border-bottom-color:var(--line-strong);text-decoration:none}
/*
 * A HAIRLINE TOKEN PAINTED AS TEXT — the same class of bug the tint override
 * eight lines below was already written to fix, left unfixed on the two
 * grounds that actually ship.
 *
 *   was  --line-strong #C8D7E7 on #FFFFFF  = 1.47:1
 *   was  --line-dark   #22334A on #0E1B2B  = 1.34:1   (14 of 16 pages)
 *
 * Both are border tokens, and at 1.3–1.5:1 the "/" between the crumbs simply
 * is not there — the trail reads "Home  Services" with a gap where the
 * separator should be. The fix is the one the tint variant already models:
 * use the ground's BODY-TEXT token, not its line token.
 *
 *   now  --muted        #5A6A7E on #FFFFFF = 5.53:1
 *   now  --on-dark-body #A8B4C2 on #0E1B2B = 8.16:1
 *
 * (The 4.5:1 floor is belt and braces here — the glyph is aria-hidden, so
 * 1.4.3 arguably exempts it as decoration. It still has to be visible.)
 */
.breadcrumbs__sep{color:var(--muted);-webkit-user-select:none;user-select:none}
.breadcrumbs .breadcrumbs__current{color:var(--ink);font-weight:700}

/* Navy band */
.section--navy .breadcrumbs,
.section--navy .breadcrumbs .breadcrumbs__item{color:var(--on-dark-body)}
.section--navy .breadcrumbs .breadcrumbs__item a{color:var(--on-dark-body)}
.section--navy .breadcrumbs .breadcrumbs__item a:hover{color:var(--on-dark);border-bottom-color:var(--line-dark)}
.section--navy .breadcrumbs .breadcrumbs__current{color:var(--on-dark)}
.section--navy .breadcrumbs__sep{color:var(--on-dark-body)}

/* Tint band — the hairline needs lifting off --bg-tint (#F5F7F9) */
@media (max-width:719px){
  .breadcrumbs{font-size:13px}
}

/* ==========================================================================
   Post card — blog / insights listing
   Markup: article.post-card > a.post-card__media + div.post-card__body
           (.post-card__cat, h3.post-card__title, p.post-card__excerpt,
            div.post-card__meta)
   ========================================================================== */
.post-card{
  display:flex;flex-direction:column;height:100%;
  background:var(--bg);
  border:1px solid var(--line);
  border-radius:var(--radius-md);
  overflow:hidden;
  transition:border-color var(--dur-fast);
}
.post-card:hover{border-color:var(--line-strong)}
.post-card:focus-within{border-color:var(--blue)}

.post-card__media{
  display:block;position:relative;
  aspect-ratio:16/9;
  background:var(--blue-soft);
  border-bottom:1px solid var(--line);
  overflow:hidden;
}
/* (0,1,1) — beats the base `img{height:auto}` rule. */
.post-card__media img{width:100%;height:100%;object-fit:cover;border-radius:0}

.post-card__body{
  display:flex;flex-direction:column;flex:1 1 auto;
  padding:var(--space-5);
}
.post-card .post-card__cat{
  /* 11.5px was below the 12px label step §4 uses for every other label on
     the site. The TAP TARGET fix goes on the anchor below, not here: the
     markup is `<p class="post-card__cat"><a>…</a></p>`, so padding on the <p>
     would grow the box without growing the thing you actually press. */
  display:inline-block;align-self:flex-start;
  margin:0 0 var(--space-3);
  font-size:12px;font-weight:700;letter-spacing:.1em;text-transform:uppercase;
  color:var(--blue);text-decoration:none;
  transition:color var(--dur-fast);
}
.post-card .post-card__cat:hover{color:var(--blue-dark);text-decoration:none}
/*
 * template-parts/card-post.php emits <p class="post-card__cat"><a>...</a></p>
 * for the category line. The bare
 * `a{color:var(--ink)}` at (0,0,1) targets the anchor directly, so the kicker
 * lost its blue, and `a:hover` at (0,1,1) underlined it. `color:inherit` at
 * (0,2,1) / (0,3,1) tracks the <p> in every band -- light, tint and navy --
 * so no per-band anchor override is needed.
 */
.post-card .post-card__cat a,
.post-card .post-card__cat a:hover{color:inherit;text-decoration:none}
/* 85 x 17px was the smallest tap target in the build and it is not an inline
   link in a sentence, so WCAG 2.5.8's inline exception does not cover it.
   14px of block padding takes it to 44px; the matching negative margin keeps
   the <p>'s box, the 12px gap to the title and every glyph exactly where they
   were. */
.post-card .post-card__cat a{display:inline-block;padding:14px 0;margin:-14px 0;transition:color var(--dur-fast)}

/* (0,2,0) — a lone .post-card__title would lose the colour fight against
   `.section--navy h3{color:var(--on-dark)}` and the h1–h4 margin reset. */
.post-card .post-card__title{
  margin:0 0 var(--space-3);
  font-size:20px;line-height:1.28;font-weight:700;letter-spacing:-.012em;
  color:var(--ink);
}
.post-card .post-card__title a{color:var(--ink);text-decoration:none;transition:color var(--dur-fast)}
.post-card .post-card__title a:hover{color:var(--blue);text-decoration:none}

/* (0,2,0) — `p:last-child{margin-bottom:0}` at (0,1,1) would otherwise glue
   the excerpt to the meta row whenever the meta row is empty. */
.post-card .post-card__excerpt{
  margin:0 0 var(--space-5);
  color:var(--body);font-size:15.5px;line-height:1.6;
}
.post-card .post-card__meta{
  display:flex;flex-wrap:wrap;align-items:center;gap:var(--space-2) var(--space-4);
  margin:auto 0 0;padding-top:var(--space-4);
  border-top:1px solid var(--line);
  font-size:13px;color:var(--muted);
  font-variant-numeric:tabular-nums;font-feature-settings:'tnum' 1;
}
.post-card .post-card__meta a{color:var(--muted);text-decoration:none}
.post-card .post-card__meta a:hover{color:var(--blue);text-decoration:none}

/* Tint band — #DFE8F2 on #F5F7F9 is too close to read as an edge */
/* Navy band */
.section--navy .post-card{background:var(--surface-dark);border-color:var(--line-dark)}
.section--navy .post-card:hover{border-color:var(--on-dark-body)}
.section--navy .post-card .post-card__media{background:var(--navy-deep);border-bottom-color:var(--line-dark)}
.section--navy .post-card .post-card__cat{color:var(--on-dark-body)}
.section--navy .post-card .post-card__cat:hover{color:var(--on-dark)}
.section--navy .post-card .post-card__title{color:var(--on-dark)}
.section--navy .post-card .post-card__title a{color:var(--on-dark)}
.section--navy .post-card .post-card__title a:hover{color:var(--lime)}
.section--navy .post-card .post-card__excerpt{color:var(--on-dark-body)}
.section--navy .post-card .post-card__meta{border-top-color:var(--line-dark);color:var(--on-dark-body)}
.section--navy .post-card .post-card__meta a{color:var(--on-dark-body)}
.section--navy .post-card .post-card__meta a:hover{color:var(--lime)}
/*
 * THE FOCUS RING WAS INVISIBLE HERE. `.post-card:focus-within` paints
 * `border-color:var(--blue)`, and --blue is #0E1B2B — the same value as
 * --navy — so tabbing into a card on a navy band drew a navy border on a
 * #13243A card: 1.11:1, i.e. nothing. It also TOOK AWAY the --line-dark
 * border the navy variant had given it, because `.post-card:focus-within`
 * (0,2,0) ties with `.section--navy .post-card` (0,2,0) and sits later in the
 * file. (0,3,0) settles both problems on weight.
 * --on-dark #F5F7F9 on --surface-dark #13243A = 14.6:1 (3:1 is the floor for
 * a non-text boundary).
 */
.section--navy .post-card:focus-within{border-color:var(--on-dark)}

@media (max-width:719px){
  .post-card__body{padding:var(--space-5) var(--space-4)}
  .post-card .post-card__title{font-size:19px}
}

/* ==========================================================================
   Case study card — metric-forward, sits in .grid--2 / .grid--3
   Markup: article.cs-card > a.cs-card__media + div.cs-card__body
           (.cs-card__metric, h3.cs-card__title, prose, ul.cs-card__tags > li > .cs-tag)
   .cs-card__body doubles as the padded wrapper AND the prose colour scope,
   so it reads correctly whether the template nests text inside it or not.
   ========================================================================== */
.cs-card{
  display:flex;flex-direction:column;height:100%;
  background:var(--bg);
  border:1px solid var(--line);
  border-radius:var(--radius-md);
  overflow:hidden;
  transition:border-color var(--dur-fast);
}
.cs-card:hover{border-color:var(--line-strong)}
.cs-card:focus-within{border-color:var(--blue)}

.cs-card__media{
  display:block;position:relative;
  aspect-ratio:16/9;
  background:var(--blue-soft);
  border-bottom:1px solid var(--line);
  overflow:hidden;
}
.cs-card__media img{width:100%;height:100%;object-fit:cover;border-radius:0}

.cs-card__body{
  display:flex;flex-direction:column;flex:1 1 auto;
  padding:var(--space-6) var(--space-5) var(--space-5);
  color:var(--body);font-size:15.5px;
}
.cs-card .cs-card__body p{margin:0 0 var(--space-4);color:var(--body);font-size:15.5px;line-height:1.6}
.cs-card .cs-card__body p:last-of-type{margin-bottom:var(--space-5)}

/* HOLE CLEARANCE: was clamp(29px,3.2vw,38px). 38px is inside the deliberate
   26–40px gap in the type scale (§4). Repointed to the same step as
   .cs-result__num so the two metric displays agree and neither lands in it. */
.cs-card .cs-card__metric{
  display:flex;align-items:baseline;flex-wrap:wrap;gap:0 4px;
  margin:0 0 var(--space-2);
  font-size:clamp(26px,3.2vw,40px);font-weight:800;
  color:var(--ink);letter-spacing:-.03em;line-height:1;
  font-variant-numeric:tabular-nums;font-feature-settings:'tnum' 1;
}
.cs-card .cs-card__metric .arrow{font-size:.52em;color:var(--blue)}
/* Each value is one unbreakable unit: without this the flex line broke inside
   a value and "Page 2/3 -> Top 3" set as "Page / 2/3 -> Top / 3". */
.cs-card .cs-card__metric .metric__val{white-space:nowrap}
/* OWN LINE, NOT A FLEX SIBLING. As a bare item next to a 40px number the
   caption was the only shrinkable thing on the line, so flexbox squeezed it to
   its min-content width -- 56px, four lines deep -- while the number itself
   (min-width:auto, no space to break at) overflowed the card by up to 40px at
   1280px. flex:1 0 100% forces a new line and gives the caption full width. */
.cs-card .cs-card__metric small{
  flex:1 0 100%;
  margin-top:var(--space-2);
  font-size:14px;font-weight:700;letter-spacing:0;line-height:1.4;color:var(--muted);
}

/*
 * template-parts/card-case-study.php emits the metric as
 * <p class="cs-card__metric"> inside
 * .cs-card__body, so the prose rule `.cs-card .cs-card__body p` (0,2,1) -- and
 * `...p:last-of-type` (0,3,1) on a card with no excerpt -- both out-ranked
 * `.cs-card .cs-card__metric` (0,2,0) and repainted the flagship number as
 * 15.5px --body at line-height 1.6. Restated at (0,3,1) and placed after both,
 * so it wins the :last-of-type tie on source order.
 */
.cs-card .cs-card__body p.cs-card__metric{
  margin:0 0 var(--space-2);
  font-size:clamp(26px,3.2vw,40px);   /* keep in step with the rule above */
  color:var(--ink);
  line-height:1;
}

.cs-card .cs-card__title{
  margin:0 0 var(--space-3);
  font-size:19px;line-height:1.3;font-weight:700;letter-spacing:-.01em;
  color:var(--ink);
}
.cs-card .cs-card__title a{color:var(--ink);text-decoration:none;transition:color var(--dur-fast)}
.cs-card .cs-card__title a:hover{color:var(--blue);text-decoration:none}

.cs-card__tags{
  display:flex;flex-wrap:wrap;gap:var(--space-2);
  list-style:none;margin:auto 0 0;padding:var(--space-5) 0 0;
}
.cs-card .cs-card__tags li{margin:0}

/* NO PILLS. The 999px radius that used to sit here is removed (§6): "the one
   remaining 999px pill is removed". Hard 0px, applied with total consistency,
   is the only way the extreme works. */
.cs-tag{
  display:inline-flex;align-items:center;
  min-height:26px;padding:4px 11px;
  border:1px solid var(--line);border-radius:0;
  background:var(--bg);
  font-size:12px;font-weight:700;letter-spacing:.04em;
  color:var(--muted);white-space:nowrap;
  transition:color var(--dur-fast),border-color var(--dur-fast),background var(--dur-fast);
}
/* (0,1,1) — element+class beats the bare `a` rule; hover at (0,2,1) beats a:hover. */
a.cs-tag{color:var(--muted);text-decoration:none}
a.cs-tag:hover{color:var(--blue);border-color:var(--blue);background:var(--blue-soft);text-decoration:none}

/* Tint band */
/* Navy band */
.section--navy .cs-card{background:var(--surface-dark);border-color:var(--line-dark)}
.section--navy .cs-card:hover{border-color:var(--on-dark-body)}
.section--navy .cs-card .cs-card__media{background:var(--navy-deep);border-bottom-color:var(--line-dark)}
.section--navy .cs-card .cs-card__body,
.section--navy .cs-card .cs-card__body p{color:var(--on-dark-body)}
.section--navy .cs-card .cs-card__metric{color:var(--on-dark)}
.section--navy .cs-card .cs-card__metric .arrow{color:var(--lime)}
.section--navy .cs-card .cs-card__metric small{color:var(--on-dark-body)}
/* (0,4,1) -- clears `.section--navy .cs-card .cs-card__body p` at (0,3,1). */
.section--navy .cs-card .cs-card__body p.cs-card__metric{color:var(--on-dark)}
.section--navy .cs-card .cs-card__title{color:var(--on-dark)}
.section--navy .cs-card .cs-card__title a{color:var(--on-dark)}
.section--navy .cs-card .cs-card__title a:hover{color:var(--lime)}
.section--navy .cs-tag{background:transparent;border-color:var(--line-dark);color:var(--on-dark-body)}
.section--navy a.cs-tag:hover{color:var(--on-dark);border-color:var(--on-dark-body);background:transparent}
/* Same defect as `.post-card:focus-within`, same fix: `var(--blue)` is
   #0E1B2B, so the ring was navy on a #13243A card (1.11:1) and it also beat
   the variant's own --line-dark border on source order. (0,3,0) wins on
   weight. --on-dark on --surface-dark = 14.6:1. */
.section--navy .cs-card:focus-within{border-color:var(--on-dark)}

@media (max-width:719px){
  .cs-card__body{padding:var(--space-5) var(--space-4)}
}

/* --- The homepage case-study band (v1.9) ----------------------------------
   template-parts/section-case-studies.php. Four classes and no new colour:
   the cards are .cs-card and are fully painted above on both grounds, the
   section head is .eyebrow / h2 / .section__lead, and the way out is
   .card__link. All this adds is the rhythm between those pieces and the
   hairline that separates them — rules between things, not boxes around them
   (DIRECTION §3.4).

   The band does NOT collapse when nothing is published: it holds its white
   ground so the navy/white alternation survives a fresh install, and swaps its
   section head for an honest sentence about only publishing evidenced figures.
   That is a template decision, recorded here because the empty state is what
   `.cs-band__empty` below is FOR.

   `.cs-band` ITSELF CARRIES NO RULE, and that is not an oversight. It shipped
   with one — a scroll-margin-top offsetting the sticky header — which is now
   `.section[id]` in the Layout section, because the bug it fixed belonged to
   every id'd band and not to this one. The class stays on the section as the
   hook the four rules below key off.
   ------------------------------------------------------------------------ */

/* The grid stands off the section head by one step, the same step
   front-page.php was setting inline on .steps and .stats. */
.cs-band__grid{margin-top:var(--space-6)}

/* The way out of the proof, ruled off from the proof itself. */
.cs-band__more{margin-top:var(--space-6);padding-top:var(--space-5);border-top:1px solid var(--line)}

/* Specificity 0,2,0 — out-ranks `.card__link` at (0,1,0) regardless of source
   order. .card__link is built for the foot of a flex card: `margin-top:auto`
   pushes it to the bottom and `padding-top:var(--space-5)` holds it off the
   prose above. Alone in a <p>, `auto` computes to 0 but the 24px padding does
   not — it would stack on the 24px this row already sets above the hairline
   and inflate the link's hit area upward across the rule. */
.cs-band__more .card__link{margin-top:0;padding-top:0}

/* The empty state, deliberately NOT .empty-state: that component paints
   --bg-tint behind a 1px border, and the third surface is retired. A tinted
   panel dropped into the middle of the white band puts back the surface the
   ladder just removed and boxes something the system rules off instead.
   62ch matches .micro's measure so the two paragraphs share an edge. */
.cs-band__empty{margin-top:var(--space-6);padding-top:var(--space-6);border-top:1px solid var(--line);max-width:62ch}

/* Both hairlines above are --line #DFE8F2 on #FFFFFF = 1.24:1, and both below
   are --line-dark #22334A on --navy = 1.36:1. Legal here and only here: these
   separators carry no information and no state, so WCAG 1.4.11 does not apply
   to them, and they are the same tokens .step, .card and .cs-card already draw
   their borders with on the same two grounds. Nothing in this band paints text
   in a line token.

   NOTE FOR THE CALLER, NOT FOR CSS: on navy, `.section--navy .card__link
   {color:var(--lime)}` above repaints "See all case studies" lime. A page that
   has already spent its one lime keyword in the hero must pass
   `surface => 'light'` — which is the default, and what the homepage uses. */
.section--navy .cs-band__more,
.section--navy .cs-band__empty{border-top-color:var(--line-dark)}

/* ==========================================================================
   Case study page — hero, results band, checklist, proof frame
   ========================================================================== */
/* Symmetric. The 32px close against a 115.2px open (ratio 0.28) put the lime
   "Book a growth audit" button 32px from the navy edge while the band above
   it opened at full --section. .cs-hero is a band like any other. */
.cs-hero{padding:var(--section) 0}
.cs-hero h1{max-width:18ch;margin-bottom:var(--space-5)}
.cs-hero .section__lead{margin-bottom:var(--space-6)}
.cs-hero__grid{
  display:grid;grid-template-columns:1.05fr .95fr;
  gap:var(--space-8);align-items:start;
}
.cs-hero__grid img{border-radius:var(--radius-md);border:1px solid var(--line)}

/* Results band — sits between hairlines like .mp-row */
.cs-results{
  display:grid;grid-template-columns:repeat(3,1fr);
  gap:var(--space-6) var(--space-5);
  list-style:none;margin:var(--space-7) 0 0;padding:var(--space-6) 0;
  border-top:1px solid var(--line);border-bottom:1px solid var(--line);
}
/*
 * …EXCEPT WHERE IT OPENS THE BAND.
 *
 * The 48px above is a lead-in for the strip's mid-section use, where it
 * follows body copy. When it is the FIRST block in the band it must not
 * apply: --section has already done that job. Its wrapper <div> carries
 * neither padding nor border (single-case_study.php emits it as a bare
 * `<div style="…">` gap holder), so the margin collapses straight out through
 * .container and stacks on top of the section padding — measured 163.2px
 * where every other band on the page opened at 115.2px.
 *
 * (0,2,2) beats `.cs-results` (0,1,0). The `> div:first-child` step is what
 * scopes this to the opening block; :first-child on .cs-results itself would
 * never match, because the <h2> above it is .screen-reader-text and therefore
 * position:absolute — out of flow, but still a first child.
 */
.section > .container > div:first-child > .cs-results{margin-top:0}

.cs-result{margin:0;min-width:0}
.cs-results .cs-result__num{
  display:flex;align-items:baseline;flex-wrap:wrap;gap:0 4px;
  margin:0;
  font-size:clamp(26px,3.2vw,40px);font-weight:800;
  color:var(--ink);letter-spacing:-.03em;line-height:1;
  font-variant-numeric:tabular-nums;font-feature-settings:'tnum' 1;
}
.cs-results .cs-result__num .arrow{font-size:.52em;color:var(--blue)}
/* Same three corrections as .cs-card__metric above, and for the same reason:
   _ee_cs_result_N_num carries a "from -> to" pair, not a single figure. The
   two metric displays stay in step, which is the invariant this rule and the
   HOLE CLEARANCE note on .cs-card__metric were written to hold. */
.cs-results .cs-result__num .metric__val{white-space:nowrap}
.cs-results .cs-result__num small{
  flex:1 0 100%;
  margin-top:var(--space-2);
  font-size:14px;font-weight:700;letter-spacing:0;line-height:1.4;color:var(--muted);
}
.cs-results .cs-result__label{
  margin:var(--space-3) 0 0;
  font-size:14.5px;line-height:1.45;color:var(--muted);max-width:28ch;
}

/*
 * Checklist — THE ARROW IS GONE FROM THE MARKER (§5).
 * "The .why-item list markers, the .cs-checklist markers, the .mp--primary
 * prefix and the .callout prefix all lose their arrows — that is 40+
 * removals and it is what turns the arrow from wallpaper back into a
 * signature." The arrow is now permitted in five places only: the trajectory
 * lockup, the primary CTA, read-more/card links, the architectural ground
 * shape, and the logo.
 *
 * A 14px hairline replaces it. That is the house language of this direction
 * — the trajectory rule, the step rows, the marketplace band and the service
 * list are all hairlines — so the list still reads as a list, and it costs
 * nothing. Not a tick (U+2713) and not a bullet: neither is in the Manrope
 * subset and both would fall back to an OS face, which is BUG 1 again.
 */
.cs-checklist{list-style:none;margin:0 0 var(--space-5);padding:0}
/*
 * The 24px lead-out is only correct when something follows the list. In every
 * shipped placement it is the LAST flow content of its container, so the
 * margin fell through to the band edge: #included (service-ppc) and
 * #how-we-help (marketplace-amazon) both closed at 139.2px against a 115.2px
 * open.
 *
 * Two selectors because one is not enough. `:last-child` misses the common
 * case — two checklists side by side in a `.grid.grid--2`, where the FIRST is
 * not :last-child, is its own grid item, and sets the row height including
 * its margin. Zeroing only the second would have left the row 24px tall
 * anyway. `.grid > .cs-checklist` catches both; a grid cell holding just this
 * list has nothing for the margin to separate it from.
 * Both (0,2,0) / (0,1,1)+ beat `.cs-checklist` (0,1,0).
 */
.cs-checklist:last-child,
.grid > .cs-checklist{margin-bottom:0}

/*
 * THE BLOCK GAP INSIDE A CASE-STUDY BAND, AS A CLASS.
 *
 * single-case_study.php stacks six OPTIONAL blocks in one band, so which one
 * comes first depends on what the editor filled in and cannot be written into
 * the markup. It solved that with a `$ee_gap` string echoed into a style
 * attribute — which meant every rendered page shipped one `style=""` (the
 * first block, where the string is empty) and up to five inline margins.
 * Same mechanism, expressed as a class the stylesheet owns: the first block
 * gets no class and sits on the band's --section padding, every block after it
 * gets a full step of air.
 */
.cs-block--gap{margin-top:var(--space-8)}
.cs-checklist li{position:relative;margin:0;padding:0 0 var(--space-3) 30px;color:var(--body);font-size:16.5px;line-height:1.55}
.cs-checklist li:last-child{padding-bottom:0}
.cs-checklist li::before{
  content:'';position:absolute;left:0;top:.78em;
  width:14px;height:1px;background:var(--blue);
}
.cs-checklist li strong{color:var(--ink);font-weight:700}

/* Proof frame — screenshot / chart with a caption */
.cs-proof{
  margin:var(--space-6) 0;padding:var(--space-4);
  background:var(--bg-tint);
  border:1px solid var(--line);border-radius:var(--radius-md);
}
.cs-proof img{width:100%;border-radius:var(--radius-sm);border:1px solid var(--line)}
/* (0,2,0) — `p:last-child` and `.section--navy p` both sit at (0,1,1). */
.cs-proof .cs-proof__caption{
  /* max-width added: unbounded, measured at 136 characters on one line. */
  margin:var(--space-4) 0 0;max-width:62ch;
  font-size:13.5px;line-height:1.5;color:var(--muted);
  font-variant-numeric:tabular-nums;font-feature-settings:'tnum' 1;
}

/* Tint band — the tinted proof frame would vanish, so flip it to white */
/* Navy band */
.section--navy .cs-hero__grid img{border-color:var(--line-dark)}
.section--navy .cs-results{border-top-color:var(--line-dark);border-bottom-color:var(--line-dark)}
.section--navy .cs-results .cs-result__num{color:var(--on-dark)}
.section--navy .cs-results .cs-result__num .arrow{color:var(--lime)}
.section--navy .cs-results .cs-result__num small,
.section--navy .cs-results .cs-result__label{color:var(--on-dark-body)}
.section--navy .cs-checklist li{color:var(--on-dark-body)}
/* `background`, not `color`: the marker is a hairline rule now, not a glyph. */
.section--navy .cs-checklist li::before{background:var(--lime)}
.section--navy .cs-checklist li strong{color:var(--on-dark)}
.section--navy .cs-proof{background:var(--surface-dark);border-color:var(--line-dark)}
.section--navy .cs-proof img{border-color:var(--line-dark)}
.section--navy .cs-proof .cs-proof__caption{color:var(--on-dark-body)}

@media (max-width:1023px){
  .cs-hero__grid{grid-template-columns:1fr;gap:var(--space-7)}
  .cs-results{grid-template-columns:repeat(2,1fr)}
}
@media (max-width:719px){
  .cs-results{grid-template-columns:1fr;gap:var(--space-5)}
  .cs-results .cs-result__label{max-width:none}
}

/* ==========================================================================
   Editorial — post meta, author box, table of contents, share row, next/prev
   ========================================================================== */

/* --- .article-single: EMITTED, AND DELIBERATELY UNSTYLED -----------------
 *
 * single.php wraps the whole post in `<article class="article-single ...">` via
 * post_class(), and there is no `.article-single` rule anywhere in this file.
 * That is the decision, not an oversight, and it is load-bearing: the navy hero
 * that carries the H1 sits INSIDE that <article>, and `.section--bleed` breaks
 * out to the full viewport with a negative margin. Give `.article-single` a
 * max-width, a padding or anything that establishes a containing block and the
 * hero stops spanning the viewport — which breaks DIRECTION.md §3.4 rule 3,
 * "every navy band is full-bleed", on every blog post on the site.
 *
 * The measure that an article does need is already set one component down:
 * `.entry-content{max-width:720px}` scopes it to the prose, which is the only
 * part that wants it.
 *
 * So the class is a hook — for post_class() consumers, for a plugin, for a
 * future body-scoped rule — and it stays declaration-free. single.php's own
 * comment beside the wrapper says the same thing from the other side. If you
 * came here to add the "missing" rule, this is the note saying do not.
 * ------------------------------------------------------------------------ */

/* --- Post meta row ------------------------------------------------------ */
.post-meta{
  display:flex;flex-wrap:wrap;align-items:center;gap:var(--space-2) var(--space-3);
  list-style:none;margin:0 0 var(--space-6);padding:0;
  font-size:14px;color:var(--muted);
  font-variant-numeric:tabular-nums;font-feature-settings:'tnum' 1;
}
.post-meta .post-meta__item{display:inline-flex;align-items:center;gap:var(--space-2);margin:0;color:var(--muted)}
/* Hairline separator between items — decorative, never announced.
   Was a 3px circle; it is a 3px SQUARE now. No circles anywhere (§6). */
.post-meta .post-meta__item + .post-meta__item::before{
  content:'';flex:0 0 auto;
  width:3px;height:3px;border-radius:0;
  background:var(--line-strong);margin-right:var(--space-1);
}
.post-meta .post-meta__item strong{color:var(--ink);font-weight:700}
.post-meta .post-meta__item a{color:var(--blue);text-decoration:none;transition:color var(--dur-fast)}
.post-meta .post-meta__item a:hover{color:var(--blue-dark);text-decoration:underline}
.section--navy .post-meta,
.section--navy .post-meta .post-meta__item{color:var(--on-dark-body)}
.section--navy .post-meta .post-meta__item + .post-meta__item::before{background:var(--line-dark)}
.section--navy .post-meta .post-meta__item strong{color:var(--on-dark)}
.section--navy .post-meta .post-meta__item a{color:var(--on-dark)}
.section--navy .post-meta .post-meta__item a:hover{color:var(--lime)}

/* --- Author box --------------------------------------------------------- */
.author-box{
  display:grid;grid-template-columns:64px 1fr;gap:var(--space-5);align-items:start;
  margin:var(--space-7) 0;padding:var(--space-5);
  background:var(--bg-tint);
  border:1px solid var(--line);border-radius:var(--radius-md);
}
/* NO CIRCLES ANYWHERE ON THE SITE (§6, and §12 "Circular avatars — rejected":
   border-radius:50% on a headshot is the single most template-looking gesture
   available). All photographic masks are rectangles. get_avatar() emits its
   own inline sizing but not a radius, so squaring it here is enough. */
.author-box__avatar{
  width:64px;height:64px;flex:0 0 auto;
  border-radius:0;overflow:hidden;
  background:var(--blue-soft);border:1px solid var(--line);
}
.author-box__avatar img{width:100%;height:100%;object-fit:cover;border-radius:0}
.author-box__body{min-width:0}
/* (0,2,1) — beats the h1–h4 margin reset and .section--navy h3/h4. */
.author-box .author-box__body h3,
.author-box .author-box__body h4{margin:0 0 var(--space-2);font-size:17px;font-weight:700;color:var(--ink)}
.author-box .author-box__body p{margin:0 0 var(--space-3);color:var(--body);font-size:15.5px;line-height:1.6}
.author-box .author-box__body p:last-child{margin-bottom:0}
.author-box .author-box__body a{color:var(--blue);text-decoration:none;transition:color var(--dur-fast)}
.author-box .author-box__body a:hover{color:var(--blue-dark);text-decoration:underline}.section--navy .author-box{background:var(--surface-dark);border-color:var(--line-dark)}
.section--navy .author-box__avatar{background:var(--navy-deep);border-color:var(--line-dark)}
.section--navy .author-box .author-box__body h3,
.section--navy .author-box .author-box__body h4{color:var(--on-dark)}
.section--navy .author-box .author-box__body p{color:var(--on-dark-body)}
.section--navy .author-box .author-box__body a{color:var(--on-dark)}
.section--navy .author-box .author-box__body a:hover{color:var(--lime)}

@media (max-width:719px){
  .author-box{grid-template-columns:1fr;gap:var(--space-4)}
  .author-box__avatar{width:56px;height:56px}
}

/* --- Table of contents -------------------------------------------------- */
/* Wide entries scroll inside the box; the page body never scrolls sideways. */
.toc{
  margin:0 0 var(--space-6);padding:var(--space-5);
  background:var(--bg-tint);
  border:1px solid var(--line);border-radius:var(--radius-md);
  max-width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch;
}
.toc h2,.toc h3,.toc h4{
  margin:0 0 var(--space-3);
  font-size:12px;font-weight:700;letter-spacing:.12em;text-transform:uppercase;
  color:var(--muted);
}
/* (0,2,0) — `.entry-content ul,.entry-content ol{padding-left:1.3em}` is
   (0,1,1) and would otherwise re-indent this list inside a post body. */
.toc .toc__list{list-style:none;margin:0;padding:0;min-width:0;font-variant-numeric:tabular-nums;font-feature-settings:'tnum' 1}
.toc .toc__list li{margin:0 0 var(--space-2)}
.toc .toc__list li:last-child{margin-bottom:0}
.toc .toc__list ul,.toc .toc__list ol{list-style:none;margin:var(--space-2) 0 0;padding:0 0 0 var(--space-5)}
/* (0,2,1) / (0,3,1) — beats `.entry-content a` and `a:hover`. */
.toc .toc__list a{
  display:inline-block;
  color:var(--blue);font-size:15px;font-weight:600;line-height:1.45;
  text-decoration:none;border-bottom:1px solid transparent;
  transition:color var(--dur-fast),border-color var(--dur-fast);
}
.toc .toc__list a:hover{color:var(--blue-dark);border-bottom-color:var(--line-strong);text-decoration:none}.section--navy .toc{background:var(--surface-dark);border-color:var(--line-dark)}
.section--navy .toc h2,.section--navy .toc h3,.section--navy .toc h4{color:var(--on-dark-body)}
.section--navy .toc .toc__list a{color:var(--on-dark)}
.section--navy .toc .toc__list a:hover{color:var(--lime);border-bottom-color:var(--line-dark)}

/* --- Share row ---------------------------------------------------------- */
.share-row{
  display:flex;flex-wrap:wrap;align-items:center;gap:var(--space-3);
  margin:var(--space-7) 0;padding:var(--space-5) 0;
  border-top:1px solid var(--line);border-bottom:1px solid var(--line);
}
/* Contextual reset only — the base .eyebrow rule is untouched. */
.share-row .eyebrow{margin-bottom:0;margin-right:var(--space-2)}
.share-link{
  display:inline-flex;align-items:center;justify-content:center;gap:7px;
  /* 40px -> 44px. Padding absorbs the 4px so the label does not move. */
  min-height:44px;padding:10px 15px;
  background:var(--bg);
  border:1px solid var(--line);border-radius:var(--radius-sm);
  color:var(--blue);font-size:14px;font-weight:700;line-height:1;
  text-decoration:none;cursor:pointer;
  transition:color var(--dur-fast),border-color var(--dur-fast),background var(--dur-fast);
}
/* (0,2,0) beats `a:hover{text-decoration:underline}` at (0,1,1). */
.share-link:hover{color:var(--blue-dark);border-color:var(--blue);background:var(--blue-soft);text-decoration:none}
.share-link svg{width:15px;height:15px;fill:currentColor;display:block}.section--navy .share-row{border-top-color:var(--line-dark);border-bottom-color:var(--line-dark)}
.section--navy .share-link{background:transparent;border-color:var(--line-dark);color:var(--on-dark)}
.section--navy .share-link:hover{background:transparent;border-color:var(--on-dark-body);color:var(--lime)}

@media (max-width:719px){
  .share-row{gap:var(--space-2)}
  .share-row .eyebrow{flex:1 0 100%;margin-right:0;margin-bottom:var(--space-2)}
}

/* --- Next / previous ---------------------------------------------------- */
.next-prev{
  display:grid;grid-template-columns:repeat(2,1fr);gap:var(--space-5);
  margin:var(--space-7) 0 0;padding:0;list-style:none;
}
/* (0,2,0) — .next-prev__item is nearly always an <a>. */
.next-prev .next-prev__item{
  display:flex;flex-direction:column;gap:var(--space-2);
  padding:var(--space-5);
  background:var(--bg);
  border:1px solid var(--line);border-radius:var(--radius-md);
  color:var(--ink);text-decoration:none;
  transition:border-color var(--dur-fast),background var(--dur-fast);
}
.next-prev .next-prev__item:hover{border-color:var(--line-strong);background:var(--bg-tint);text-decoration:none}
.next-prev .next-prev__item span{
  font-size:11.5px;font-weight:700;letter-spacing:.1em;text-transform:uppercase;
  color:var(--muted);
}
.next-prev .next-prev__item strong{font-size:17px;font-weight:700;line-height:1.35;color:var(--ink)}
/* Column and mirroring come from the modifier, not from the child index.
   single.php prints each <a> only when that neighbour exists, so on the oldest
   post the lone "Next article" was :nth-child(1): it sat in the left column,
   left-aligned, reading as a previous link. Keying on .next-prev__item--next
   puts it in the right-hand column and mirrors it whether or not a previous
   link is beside it. Both are (0,2,0), the same weight the :nth-child rule
   had, so nothing downstream shifts. */
.next-prev .next-prev__item--prev{grid-column:1}
.next-prev .next-prev__item--next{grid-column:2;text-align:right;align-items:flex-end}
.section--navy .next-prev .next-prev__item{background:var(--surface-dark);border-color:var(--line-dark);color:var(--on-dark)}
.section--navy .next-prev .next-prev__item:hover{background:var(--surface-dark);border-color:var(--on-dark-body)}
.section--navy .next-prev .next-prev__item span{color:var(--on-dark-body)}
.section--navy .next-prev .next-prev__item strong{color:var(--on-dark)}

@media (max-width:719px){
  .next-prev{grid-template-columns:1fr;gap:var(--space-3)}
  /* One column, so `grid-column:2` above would place the next link in a
     second, implicit track. Back to auto, and unmirrored. */
  .next-prev .next-prev__item--next{grid-column:auto;text-align:left;align-items:flex-start}
}

/* ==========================================================================
   Listing — filter bar, pagination, empty state
   ========================================================================== */

/* --- Archive head: RETIRED, and deliberately not replaced ----------------
 *
 * `.archive-head` held five rules here — a 760px measure, an h1 margin, a body
 * paragraph, an eyebrow margin and a navy paragraph colour — plus a sixth as one
 * selector inside the grouped max-width override in the print block at the foot
 * of this file. All six are gone, because by the end of the conversion NOTHING
 * EMITTED THE CLASS. Every template that once
 * opened on `<section class="page-hero archive-head">` now calls
 * ecomenable_page_hero() instead, and each of the five records the swap in its
 * own docblock: archive.php, author.php, category.php, search.php and tag.php.
 *
 * Deleted rather than kept "in case". A third band shape that no template can
 * reach is not a spare part, it is a trap: the next person to write an archive
 * finds a plausible class name in the stylesheet, uses it, and gets a 760px
 * measure inside a band that DIRECTION.md §3.4 says is full-bleed navy. The
 * hero helper is the one band shape, and archive.php's docblock says so.
 *
 * Two comments elsewhere in this file still name the class as history — the
 * `.section--navy h1` note above and the v1.8.2 audit list further down. Both
 * are records of what was true then, and both now say so.
 * ------------------------------------------------------------------------ */

/* --- Filter bar / chips ------------------------------------------------- */
/*
 * SECTION UNDER A BAND. Ten archive templates used to carry an inline
 * `style="padding-top:0"` to pull the filter bar up under the navy hero. An
 * inline style beats every rule in this file, so the bar ended up flush to the
 * band — measured 0px above it against 56px below, which read as broken rather
 * than tight. This class replaces the inline override so the spacing is a
 * decision the stylesheet owns and can tune in one place.
 */
.section--tight-top{padding-top:var(--space-7)}

.filter-bar{
  display:flex;flex-wrap:wrap;align-items:center;gap:var(--space-2);
  list-style:none;margin:0 0 var(--space-6);padding:0 0 var(--space-5);
  border-bottom:1px solid var(--line);
}
.filter-bar li{margin:0}
.filter-chip{
  display:inline-flex;align-items:center;justify-content:center;
  /* 42px -> 44px, the last two pixels of the tap target. */
  min-height:44px;padding:10px 18px;
  background:var(--bg);
  border:1px solid var(--line);border-radius:var(--radius-sm);  /* was 999px — no pills */
  color:var(--body);font-family:inherit;font-size:14px;font-weight:700;line-height:1;
  text-decoration:none;cursor:pointer;white-space:nowrap;
  transition:color var(--dur-fast),border-color var(--dur-fast),background var(--dur-fast);
}
/* (0,2,0) — chips are usually <a>, so this must out-rank `a:hover`. */
.filter-chip:hover{color:var(--blue);border-color:var(--blue);background:var(--blue-soft);text-decoration:none}
.filter-chip--active,
.filter-chip[aria-current="page"],
.filter-chip[aria-pressed="true"]{background:var(--navy);border-color:var(--navy);color:var(--on-dark)}
/* Active chips must not re-colour on hover — (0,2,0) holds the state. */
.filter-chip--active:hover,
.filter-chip[aria-current="page"]:hover,
.filter-chip[aria-pressed="true"]:hover{background:var(--navy);border-color:var(--navy);color:var(--on-dark)}
.section--navy .filter-bar{border-bottom-color:var(--line-dark)}
.section--navy .filter-chip{background:transparent;border-color:var(--line-dark);color:var(--on-dark-body)}
.section--navy .filter-chip:hover{background:transparent;border-color:var(--on-dark-body);color:var(--on-dark)}
.section--navy .filter-chip--active,
.section--navy .filter-chip[aria-current="page"],
.section--navy .filter-chip[aria-pressed="true"]{background:var(--on-dark);border-color:var(--on-dark);color:var(--navy)}
.section--navy .filter-chip--active:hover,
.section--navy .filter-chip[aria-current="page"]:hover,
.section--navy .filter-chip[aria-pressed="true"]:hover{background:var(--on-dark);border-color:var(--on-dark);color:var(--navy)}

/* --- Pagination (WordPress paginate_links markup) ----------------------- */
.pagination{
  display:flex;flex-wrap:wrap;align-items:center;gap:var(--space-2);
  margin:var(--space-7) 0 0;padding-top:var(--space-6);
  border-top:1px solid var(--line);
  font-variant-numeric:tabular-nums;font-feature-settings:'tnum' 1;
}
.pagination .nav-links{display:flex;flex-wrap:wrap;align-items:center;gap:var(--space-2)}
.pagination .page-numbers{
  display:inline-flex;align-items:center;justify-content:center;
  min-width:44px;min-height:44px;padding:0 var(--space-3);
  background:var(--bg);
  border:1px solid var(--line);border-radius:var(--radius-sm);
  color:var(--ink);font-size:15px;font-weight:700;line-height:1;
  text-decoration:none;
  font-variant-numeric:tabular-nums;font-feature-settings:'tnum' 1;
  transition:color var(--dur-fast),border-color var(--dur-fast),background var(--dur-fast);
}
/* (0,3,1) — beats `a:hover{text-decoration:underline}`. */
.pagination a.page-numbers:hover{color:var(--blue);border-color:var(--blue);background:var(--blue-soft);text-decoration:none}
.pagination .page-numbers.current{background:var(--navy);border-color:var(--navy);color:var(--on-dark)}
.pagination .page-numbers.dots{min-width:auto;padding:0 var(--space-1);background:transparent;border-color:transparent;color:var(--muted)}
.section--navy .pagination{border-top-color:var(--line-dark)}
.section--navy .pagination .page-numbers{background:transparent;border-color:var(--line-dark);color:var(--on-dark)}
.section--navy .pagination a.page-numbers:hover{background:transparent;border-color:var(--on-dark-body);color:var(--lime)}
.section--navy .pagination .page-numbers.current{background:var(--on-dark);border-color:var(--on-dark);color:var(--navy)}
.section--navy .pagination .page-numbers.dots{background:transparent;border-color:transparent;color:var(--on-dark-body)}

/* --- Empty state -------------------------------------------------------- */
.empty-state{
  padding:var(--space-7) var(--space-6);
  background:var(--bg-tint);
  border:1px solid var(--line);border-radius:var(--radius-md);
  text-align:center;
}
/* (0,1,1) — beats the h1–h4 margin reset. */
.empty-state h2,.empty-state h3{margin:0 0 var(--space-3);font-size:22px;color:var(--ink)}
.empty-state > p{margin:0 auto var(--space-5);max-width:52ch;color:var(--body);font-size:16.5px}
/* (0,2,1) — reclaims the bottom margin the base `p:last-child` zeroes out. */
.empty-state > p:last-child{margin-bottom:0}
.empty-state .btn{margin-top:var(--space-2)}.section--navy .empty-state{background:var(--surface-dark);border-color:var(--line-dark)}
.section--navy .empty-state h2,.section--navy .empty-state h3{color:var(--on-dark)}
.section--navy .empty-state > p{color:var(--on-dark-body)}

@media (max-width:719px){
  .empty-state{padding:var(--space-6) var(--space-4)}
}

/* ==========================================================================
   Proof — testimonial, logo wall, review grid
   Every one of these blocks must be hidden by the template when the
   Customizer/meta source is empty. Never ship a placeholder that reads
   like a real claim.
   ========================================================================== */

/* --- Testimonial -------------------------------------------------------- */
.testimonial{
  display:flex;flex-direction:column;height:100%;
  padding:var(--space-6);
  background:var(--bg);
  border:1px solid var(--line);border-radius:var(--radius-md);
}
/* (0,2,0) — also kills the UA blockquote margin when this lands on a
   <blockquote>, and out-ranks `.section--navy p`. */
.testimonial .testimonial__quote{
  margin:0 0 var(--space-5);
  color:var(--ink);font-size:19px;font-weight:600;line-height:1.5;
  letter-spacing:-.008em;max-width:56ch;
}
.testimonial .testimonial__quote p{margin:0 0 var(--space-4);color:var(--ink);font-size:19px;font-weight:600}
.testimonial .testimonial__quote p:last-child{margin-bottom:0}
/*
 * testimonial.php wraps the author + meta spans in a <figcaption>, so the
 * attribution block -- not the inline author span -- is the flex item that
 * must be pushed to the card foot and carry the divider. On the span
 * `margin-top:auto` never fired (an inline child is not a flex item) and
 * `border-top` drew a stub rule only as wide as the name.
 */
.testimonial figcaption{
  display:flex;flex-direction:column;
  margin:auto 0 0;padding-top:var(--space-4);
  border-top:1px solid var(--line);
}
.testimonial .testimonial__author{
  display:block;
  color:var(--ink);font-size:15.5px;font-weight:700;font-style:normal;
}
.testimonial .testimonial__meta{
  margin:2px 0 0;
  color:var(--muted);font-size:13.5px;font-weight:400;font-style:normal;
}
/* page-reviews.php puts a link inside .testimonial__meta. Bare a{color:var(--ink)}
   (0,0,1) would win over the inherited --muted, and a:hover would underline it.
   color:inherit at (0,3,1) tracks the parent across light, tint and navy alike. */
.testimonial .testimonial__meta a{color:inherit;text-decoration:underline}
.testimonial .testimonial__meta a:hover{color:var(--blue)}
.section--navy .testimonial .testimonial__meta a:hover{color:var(--lime)}.section--navy .testimonial{background:var(--surface-dark);border-color:var(--line-dark)}
.section--navy .testimonial .testimonial__quote,
.section--navy .testimonial .testimonial__quote p{color:var(--on-dark)}
.section--navy .testimonial figcaption{border-top-color:var(--line-dark)}
.section--navy .testimonial .testimonial__author{color:var(--on-dark)}
.section--navy .testimonial .testimonial__meta{color:var(--on-dark-body)}

@media (max-width:719px){
  .testimonial{padding:var(--space-5) var(--space-4)}
  .testimonial .testimonial__quote,
  .testimonial .testimonial__quote p{font-size:17.5px}
}

/* --- Logo wall — hairline grid, no shadows, no motion -------------------
   THE `margin:0` BELOW IS OVERRIDDEN, AND NOT BY SOURCE ORDER. A logo wall
   used as a band's body needs the standing step under the heading, so
   `.logo-wall.band-body{margin-top:var(--space-6)}` at (0,2,0) beats this
   shorthand's (0,1,0) — see BAND-CONTENT RHYTHM in the v1.9 section. Change
   the shorthand here and check that rule; do not add a second margin. */
.logo-wall{
  display:grid;grid-template-columns:repeat(auto-fit,minmax(160px,1fr));
  gap:1px;
  list-style:none;margin:0;padding:0;
  background:var(--line);
  border:1px solid var(--line);border-radius:var(--radius-md);
  overflow:hidden;
}
.logo-wall__item{
  display:flex;align-items:center;justify-content:center;
  min-height:96px;margin:0;padding:var(--space-5);
  background:var(--bg);
}
.logo-wall .logo-wall__item img{max-height:34px;width:auto;object-fit:contain}
.logo-wall .logo-wall__item span{
  font-size:13.5px;font-weight:700;letter-spacing:.1em;text-transform:uppercase;
  color:var(--muted);text-align:center;
}
.logo-wall .logo-wall__item a{display:flex;align-items:center;justify-content:center;width:100%;color:inherit;text-decoration:none}
.logo-wall .logo-wall__item a:hover{text-decoration:none}.section--navy .logo-wall{background:var(--line-dark);border-color:var(--line-dark)}
.section--navy .logo-wall__item{background:var(--surface-dark)}
.section--navy .logo-wall .logo-wall__item span{color:var(--on-dark-body)}

@media (max-width:719px){
  .logo-wall{grid-template-columns:repeat(2,1fr)}
  .logo-wall__item{min-height:80px;padding:var(--space-4)}
}

/* --- Review grid / card / stars ---------------------------------------- */
.review-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:var(--space-5)}
.review-card{
  display:flex;flex-direction:column;height:100%;
  padding:var(--space-5) var(--space-6);
  background:var(--bg);
  border:1px solid var(--line);border-radius:var(--radius-md);
  transition:border-color var(--dur-fast);
}
.review-card:hover{border-color:var(--line-strong)}
/* .review-stars AND .review-stars svg ARE DELETED (v1.9.2) — AND MUST NOT
   COME BACK. Nothing emits them: page-reviews.php's docblock now states that
   there is no drawn star row on the page and there must not be one, because a
   row of stars drawn from an owner-typed number is a rating claim the site
   cannot evidence. `fill:currentColor` on a `.review-stars svg` was the last
   piece of machinery still standing ready to draw one. If you are reaching for
   a star row, the rating text and its source link carry the claim instead. */
.review-card p{margin:0 0 var(--space-4);color:var(--body);font-size:15.5px;line-height:1.6}
.review-card p:last-child{margin-bottom:0}
.review-card cite{
  display:block;margin-top:auto;padding-top:var(--space-4);
  border-top:1px solid var(--line);
  color:var(--ink);font-size:14.5px;font-weight:700;font-style:normal;
}
.review-card cite span{display:block;color:var(--muted);font-size:13px;font-weight:400}
.section--navy .review-card{background:var(--surface-dark);border-color:var(--line-dark)}
.section--navy .review-card:hover{border-color:var(--on-dark-body)}
.section--navy .review-card p{color:var(--on-dark-body)}
.section--navy .review-card cite{color:var(--on-dark);border-top-color:var(--line-dark)}
.section--navy .review-card cite span{color:var(--on-dark-body)}

@media (max-width:1023px){
  .review-grid{grid-template-columns:repeat(2,1fr)}
}
@media (max-width:719px){
  .review-grid{grid-template-columns:1fr}
  .review-card{padding:var(--space-5) var(--space-4)}
}

/* ==========================================================================
   Commerce — pricing grid
   ========================================================================== */
.pricing-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:var(--space-5);align-items:stretch}
.pricing-card{
  display:flex;flex-direction:column;height:100%;
  padding:var(--space-6);
  background:var(--bg);
  border:1px solid var(--line);border-radius:var(--radius-md);
  transition:border-color var(--dur-fast);
}
.pricing-card:hover{border-color:var(--line-strong)}
/* Emphasis is a heavier edge, never a scale or lift. */
.pricing-card--featured{border-color:var(--navy);box-shadow:var(--shadow-md)}
.pricing-card--featured:hover{border-color:var(--navy)}
/* (0,1,1) — beats the h1–h4 margin reset. */
.pricing-card h3{margin:0 0 var(--space-2);font-size:19px;font-weight:700;color:var(--ink)}
.pricing-card .eyebrow{margin-bottom:var(--space-3)}
.pricing-card .pricing-card__price{
  display:flex;align-items:baseline;flex-wrap:wrap;gap:6px;
  margin:0 0 var(--space-2);
  font-size:clamp(30px,3.2vw,40px);font-weight:800;
  color:var(--ink);letter-spacing:-.03em;line-height:1;
  font-variant-numeric:tabular-nums;font-feature-settings:'tnum' 1;
}
.pricing-card .pricing-card__price small{font-size:14px;font-weight:700;letter-spacing:0;color:var(--muted)}
.pricing-card .pricing-card__price .arrow{font-size:.55em;color:var(--blue)}
/* (0,2,0) — `p:last-child` would flatten the gap above the feature list. */
.pricing-card .pricing-card__list{
  list-style:none;
  margin:var(--space-5) 0 var(--space-6);padding:var(--space-5) 0 0;
  border-top:1px solid var(--line);
}
.pricing-card .pricing-card__list li{
  position:relative;margin:0;padding:0 0 var(--space-3) 28px;
  color:var(--body);font-size:15.5px;line-height:1.55;
}
.pricing-card .pricing-card__list li:last-child{padding-bottom:0}
/* Same hairline marker as .cs-checklist — the arrow is gone from list
   markers sitewide (§5). See the comment on .cs-checklist li::before. */
.pricing-card .pricing-card__list li::before{
  content:'';position:absolute;left:0;top:.78em;
  width:14px;height:1px;background:var(--blue);
}
.pricing-card .pricing-card__list li strong{color:var(--ink);font-weight:700}
.pricing-card > p{margin:0 0 var(--space-4);color:var(--body);font-size:15.5px}
.pricing-card .btn{margin-top:auto;width:100%}
.section--navy .pricing-card{background:var(--surface-dark);border-color:var(--line-dark)}
.section--navy .pricing-card:hover{border-color:var(--on-dark-body)}
.section--navy .pricing-card--featured{border-color:var(--on-dark);box-shadow:none}
.section--navy .pricing-card--featured:hover{border-color:var(--on-dark)}
.section--navy .pricing-card h3{color:var(--on-dark)}
.section--navy .pricing-card .pricing-card__price{color:var(--on-dark)}
.section--navy .pricing-card .pricing-card__price small{color:var(--on-dark-body)}
.section--navy .pricing-card .pricing-card__price .arrow{color:var(--lime)}
.section--navy .pricing-card .pricing-card__list{border-top-color:var(--line-dark)}
.section--navy .pricing-card .pricing-card__list li{color:var(--on-dark-body)}
.section--navy .pricing-card .pricing-card__list li::before{background:var(--lime)}
.section--navy .pricing-card .pricing-card__list li strong{color:var(--on-dark)}
.section--navy .pricing-card > p{color:var(--on-dark-body)}

@media (max-width:1023px){
  .pricing-grid{grid-template-columns:repeat(2,1fr)}
}
@media (max-width:719px){
  .pricing-grid{grid-template-columns:1fr}
  .pricing-card{padding:var(--space-5) var(--space-4)}
}

/* ==========================================================================
   Forms & contact
   The base input/label/submit rules are untouched — these are layout shells
   that sit around whatever Contact Form 7 / WPForms renders.
   ========================================================================== */
.form-shell{
  padding:var(--space-6);
  background:var(--bg-tint);
  border:1px solid var(--line);border-radius:var(--radius-md);
}
.form-shell h2,.form-shell h3{margin:0 0 var(--space-4)}
/* `.form-grid` AND ITS THREE `:has()` FULL-WIDTH ROWS WERE DELETED (v1.8.2):
   no PHP template in the theme emits the class — a grep for `form-grid`
   across *.php still returns nothing, which is the check to repeat rather than
   a file count to trust. page-contact.php and
   page-free-audit.php emit `.form-shell` and let Contact Form 7 / WPForms
   render the fields inside it, so the two-column grid never had a parent to
   sit on and the `:has()` rows never had a `.form-grid` to be a child of.
   `.form-row` STAYS — searchform.php emits it, and the shells style whatever
   the form plugin renders regardless. */
.form-row{display:flex;flex-direction:column;min-width:0}
.form-row label{margin-bottom:7px}
.form-row textarea{min-height:150px;resize:vertical}
/* (0,2,0) — `p:last-child{margin-bottom:0}` sits at (0,1,1). */
.form-shell .form-note,
.form-row .form-note{margin:var(--space-3) 0 0;font-size:13.5px;line-height:1.5;color:var(--muted);max-width:62ch}
.form-note{margin:var(--space-3) 0 0;font-size:13.5px;line-height:1.5;color:var(--muted);max-width:62ch}
.form-shell .form-note a,.form-row .form-note a{color:var(--blue);text-decoration:underline}
.form-shell .form-note a:hover,.form-row .form-note a:hover{color:var(--blue-dark)}
.form-shell .btn,
.form-shell input[type=submit],
.form-shell button[type=submit]{margin-top:var(--space-5)}.section--navy .form-shell{background:var(--surface-dark);border-color:var(--line-dark)}
.section--navy .form-shell label{color:var(--on-dark)}
.section--navy .form-shell input[type=text],
.section--navy .form-shell input[type=email],
.section--navy .form-shell input[type=url],
.section--navy .form-shell input[type=tel],
.section--navy .form-shell input[type=search],
.section--navy .form-shell select,
.section--navy .form-shell textarea{
  background:var(--navy-deep);border-color:var(--line-dark);color:var(--on-dark);
}
.section--navy .form-shell input::placeholder,
.section--navy .form-shell textarea::placeholder{color:var(--on-dark-body)}
.section--navy .form-shell input:focus,
.section--navy .form-shell select:focus,
.section--navy .form-shell textarea:focus{border-color:var(--on-dark);box-shadow:0 0 0 3px rgba(245,247,249,.14)}
.section--navy .form-shell .form-note,
.section--navy .form-row .form-note{color:var(--on-dark-body)}
.section--navy .form-shell .form-note a{color:var(--on-dark)}
.section--navy .form-shell .form-note a:hover{color:var(--lime)}

/* --- Contact layout ----------------------------------------------------- */
.contact-grid{display:grid;grid-template-columns:1.05fr .95fr;gap:var(--space-8);align-items:start}
.contact-detail{
  display:grid;grid-template-columns:26px 1fr;gap:var(--space-4);align-items:start;
  margin:0;padding:var(--space-5) 0;
  border-top:1px solid var(--line);
}
.contact-detail:last-child{border-bottom:1px solid var(--line)}
.contact-detail .arrow{font-size:18px;line-height:1.5;color:var(--blue)}
/* (0,1,1) — beats the h1–h4 margin reset; (0,2,1) below beats .section--navy h3. */
.contact-detail h3,.contact-detail h4{margin:0 0 var(--space-1);font-size:16px;font-weight:700;color:var(--ink)}
.contact-detail p{margin:0;color:var(--body);font-size:16px;line-height:1.55;font-variant-numeric:tabular-nums;font-feature-settings:'tnum' 1}
.contact-detail a{color:var(--blue);text-decoration:none;transition:color var(--dur-fast)}
.contact-detail a:hover{color:var(--blue-dark);text-decoration:underline}.section--navy .contact-detail{border-top-color:var(--line-dark)}
.section--navy .contact-detail:last-child{border-bottom-color:var(--line-dark)}
.section--navy .contact-detail .arrow{color:var(--lime)}
.section--navy .contact-detail h3,.section--navy .contact-detail h4{color:var(--on-dark)}
.section--navy .contact-detail p{color:var(--on-dark-body)}
.section--navy .contact-detail a{color:var(--on-dark)}
.section--navy .contact-detail a:hover{color:var(--lime)}

@media (max-width:1023px){
  .contact-grid{grid-template-columns:1fr;gap:var(--space-7)}
}
@media (max-width:719px){
  .form-shell{padding:var(--space-5) var(--space-4)}
}

/* ==========================================================================
   Services — numbered row list (services & marketplaces index)
   Markup: ul.service-list > li.service-row
           (span.service-row__num, div.service-row__body, optional .btn / link)
   ========================================================================== */
.service-list{list-style:none;margin:0;padding:0;border-top:1px solid var(--line)}
.service-row{
  display:grid;grid-template-columns:64px 1fr auto;
  gap:var(--space-5);align-items:start;
  margin:0;padding:var(--space-6) var(--space-4);
  border-bottom:1px solid var(--line);
  transition:background var(--dur-fast);
}
.service-list .service-row:hover{background:var(--bg-tint)}
.service-row__num{
  padding-top:6px;
  font-size:13px;font-weight:800;letter-spacing:.08em;
  color:var(--blue);
  font-variant-numeric:tabular-nums;font-feature-settings:'tnum' 1;
}
.service-row__body{min-width:0}
/* (0,2,1) — beats both the h1–h4 reset and .section--navy h3. */
.service-row .service-row__body h3{margin:0 0 var(--space-2);font-size:21px;font-weight:700;color:var(--ink)}
.service-row .service-row__body p{margin:0 0 var(--space-3);color:var(--body);font-size:16px;line-height:1.6;max-width:64ch}
.service-row .service-row__body p:last-child{margin-bottom:0}
.service-row .service-row__body a{color:var(--blue);text-decoration:none}
.service-row .service-row__body a:hover{color:var(--blue-dark);text-decoration:underline}
.service-row .btn{align-self:center;white-space:nowrap}

/* The tint hover would disappear on a tint band, so flip it to white. */
.section--navy .service-list{border-top-color:var(--line-dark)}
.section--navy .service-row{border-bottom-color:var(--line-dark)}
.section--navy .service-list .service-row:hover{background:var(--surface-dark)}
.section--navy .service-row__num{color:var(--on-dark-body)}
.section--navy .service-row .service-row__body h3{color:var(--on-dark)}
.section--navy .service-row .service-row__body p{color:var(--on-dark-body)}
.section--navy .service-row .service-row__body a{color:var(--lime)}
.section--navy .service-row .service-row__body a:hover{color:var(--on-dark)}

@media (max-width:1023px){
  .service-row{grid-template-columns:44px 1fr;gap:var(--space-4);padding:var(--space-5) var(--space-3)}
  /* Keep the trailing CTA aligned under the copy, not under the number. */
  .service-row > *:nth-child(3){grid-column:2/-1;margin-top:var(--space-3)}
  .service-row .btn{align-self:start}
}
@media (max-width:719px){
  .service-row{grid-template-columns:1fr;gap:var(--space-2);padding:var(--space-5) 0}
  .service-row > *:nth-child(3){grid-column:1/-1}
  .service-row__num{padding-top:0}
  .service-row .service-row__body h3{font-size:19px}
}

/* --- The two groups (v1.9) -----------------------------------------------
   page-services.php band 2 carries nine rows, and nine rows flat read as a
   menu. Split, they read as a practice: six things run every month, three
   bounded engagements. The obvious way to say that is a second band, and it
   is the one move that page cannot make — band 2 is white and band 3 is navy,
   so a second white band puts the same ground twice in a row (DIRECTION §3.4
   rule 2) and takes the ladder from five rungs to six, landing the CTA on the
   wrong colour. The split is therefore made with space and a label, inside the
   one band. Nothing here restyles a row: everything inside a group is the
   .service-list / .service-row construction above.
   ------------------------------------------------------------------------ */

/* The rows, under the band lead. This was an inline margin-top on the list
   wrapper; as a class the band carries no inline geometry at all. */
.service-groups{margin-top:var(--space-7)}

/* --space-8 is 64px — twice the gap the widest row leaves, and the smallest
   value at which the break stops reading as an unusually tall row. */
.service-group + .service-group{margin-top:var(--space-8)}

/* Specificity 0,2,0 — deliberately out-ranks `.eyebrow` at (0,1,0) on both
   properties it touches, so merge order cannot decide the colour. .eyebrow
   already carries the size, weight, tracking and caps; this only darkens it
   and tightens the gap to the note beneath.
   --ink #0E1B2B on --bg #FFFFFF = 17.35:1. At 12px this is body text, so the
   bar is 4.5:1, not 3:1, and it clears both. (.eyebrow's --muted is 5.53:1 and
   would also pass; it is changed because these labels are structure, not
   decoration, and --muted reads as a caption at the head of a list.) */
.service-group .service-group__label{color:var(--ink);margin-bottom:var(--space-2)}

/* One line under the label saying what the group is. It sits directly above
   the list's top hairline, so its bottom margin is the entire separation
   between the sentence and the first row — hence --space-5 rather than the
   --space-3 a paragraph would normally take.
   --body #2B3A4D on --bg #FFFFFF = 11.57:1. */
.service-group__note{max-width:60ch;margin:0 0 var(--space-5);color:var(--body);font-size:16px;line-height:1.6}

@media (max-width:719px){
  /* Rows drop to a single column and lose their side padding at this width,
     so 64px between groups over-reads as a missing section. */
  .service-group + .service-group{margin-top:var(--space-7)}
}

/* ==========================================================================
   Legal — policy pages (template-legal.php)
   ========================================================================== */
.legal-content{max-width:760px;font-size:16.5px;line-height:1.7;color:var(--body)}
/* (0,1,1) — beats the shared h1–h4 margin reset. */
.legal-content h2{margin:var(--space-7) 0 var(--space-4);font-size:clamp(22px,2.4vw,26px)}
.legal-content h3{margin:var(--space-6) 0 var(--space-3);font-size:19px}
.legal-content h2:first-child,.legal-content h3:first-child{margin-top:0}
.legal-content p{margin:0 0 var(--space-4);color:var(--body)}
/* (0,2,1) — restores the base `p:last-child{margin-bottom:0}` intent, which the
   rule above (an equal-specificity, later-source tie) would otherwise cancel. */
.legal-content p:last-child{margin-bottom:0}
.legal-content ul,.legal-content ol{margin:0 0 var(--space-5);padding-left:1.3em}
.legal-content li{margin-bottom:var(--space-2)}
.legal-content strong{color:var(--ink);font-weight:700}
.legal-content a{color:var(--blue);text-decoration:underline}
.legal-content a:hover{color:var(--blue-dark)}
.legal-content address{font-style:normal;color:var(--body);font-variant-numeric:tabular-nums;font-feature-settings:'tnum' 1}
.legal-content dl{margin:0 0 var(--space-5)}
.legal-content dt{color:var(--ink);font-weight:700;margin-bottom:var(--space-1)}
.legal-content dd{margin:0 0 var(--space-4);padding:0}
/* Effective/updated date lines */
.legal-content time{font-variant-numeric:tabular-nums;font-feature-settings:'tnum' 1}

/* Wide content scrolls inside its own box — the page body never does.
   .wp-block-table is WordPress core markup, not a new component class. */
.legal-content .wp-block-table,
.entry-content .wp-block-table{display:block;max-width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch}
.legal-content table{width:100%;border-collapse:collapse;margin-bottom:var(--space-5)}
.legal-content th,.legal-content td{text-align:left;padding:11px 14px;border-bottom:1px solid var(--line);vertical-align:top}
.legal-content th{color:var(--ink);font-weight:700}
.legal-content pre,.entry-content pre{
  max-width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch;
  padding:var(--space-4);
  background:var(--bg-tint);border:1px solid var(--line);border-radius:var(--radius-sm);
  font-size:14px;line-height:1.5;
}
.legal-content code,.entry-content code{font-size:.92em;word-break:break-word}

/* Legal table of contents — two columns of anchors, collapses to one */
.legal-toc{
  margin:0 0 var(--space-7);padding:var(--space-5);
  background:var(--bg-tint);
  border:1px solid var(--line);border-radius:var(--radius-md);
  max-width:100%;overflow-x:auto;-webkit-overflow-scrolling:touch;
}
.legal-toc h2,.legal-toc h3,.legal-toc h4{
  margin:0 0 var(--space-3);
  font-size:12px;font-weight:700;letter-spacing:.12em;text-transform:uppercase;color:var(--muted);
}
/* The bare selectors sit at (0,1,1) — an exact TIE with
   `.entry-content ul,ol` and `.legal-content ul,ol`, which would leave the
   winner decided by source order alone. The prose-scoped duplicates below
   raise it to (0,2,1) so the TOC keeps its own list geometry no matter where
   this file's rules end up sitting relative to each other. */
.legal-toc ul,.legal-toc ol,
.legal-content .legal-toc ul,.legal-content .legal-toc ol,
.entry-content .legal-toc ul,.entry-content .legal-toc ol{
  list-style:none;margin:0;padding:0;
  columns:2;column-gap:var(--space-6);
  font-variant-numeric:tabular-nums;font-feature-settings:'tnum' 1;
}
.legal-toc li,
.legal-content .legal-toc li,
.entry-content .legal-toc li{margin:0 0 var(--space-2);break-inside:avoid}
.legal-toc a,
.legal-content .legal-toc a,
.entry-content .legal-toc a{color:var(--blue);font-size:15px;font-weight:600;text-decoration:none;border-bottom:1px solid transparent;transition:color var(--dur-fast),border-color var(--dur-fast)}
/* (0,2,1) / (0,3,1) — beats `a:hover`, `.entry-content a:hover` and `.legal-content a:hover`. */
.legal-toc a:hover,
.legal-content .legal-toc a:hover,
.entry-content .legal-toc a:hover{color:var(--blue-dark);border-bottom-color:var(--line-strong);text-decoration:none}
.section--navy .legal-content{color:var(--on-dark-body)}
.section--navy .legal-content p,.section--navy .legal-content li,
.section--navy .legal-content dd,.section--navy .legal-content address{color:var(--on-dark-body)}
.section--navy .legal-content strong,.section--navy .legal-content dt{color:var(--on-dark)}
.section--navy .legal-content a{color:var(--on-dark)}
.section--navy .legal-content a:hover{color:var(--lime)}
.section--navy .legal-content th{color:var(--on-dark)}
.section--navy .legal-content th,.section--navy .legal-content td{border-bottom-color:var(--line-dark)}
.section--navy .legal-content pre,.section--navy .entry-content pre{background:var(--navy-deep);border-color:var(--line-dark);color:var(--on-dark-body)}
.section--navy .legal-toc{background:var(--surface-dark);border-color:var(--line-dark)}
.section--navy .legal-toc h2,.section--navy .legal-toc h3,.section--navy .legal-toc h4{color:var(--on-dark-body)}
.section--navy .legal-toc a{color:var(--on-dark)}
.section--navy .legal-toc a:hover{color:var(--lime);border-bottom-color:var(--line-dark)}
/*
 * THE SAME TOC, REACHED THROUGH A WRAPPER, AND IT WAS A TIE.
 *
 * template-legal.php and single.php can both render the TOC inside
 * `.legal-content` / `.entry-content`, and those two forms are styled
 * separately at the top of this block:
 *
 *   .legal-content .legal-toc a       (0,2,1)  --blue        (= #0E1B2B)
 *   .section--navy .legal-toc a       (0,2,1)  --on-dark
 *
 * An exact tie, so on a navy band the winner was whichever sat lower in the
 * file — today the navy one, by 22 lines. Move either block and every link in
 * a legal table of contents on navy silently turns #0E1B2B on #13243A: 1.11:1,
 * unreadable. These two selectors are (0,3,1) and settle it on weight instead.
 * --on-dark on --surface-dark = 14.6:1; --lime on --surface-dark = 12.2:1.
 */
.section--navy .legal-content .legal-toc a,
.section--navy .entry-content .legal-toc a{color:var(--on-dark)}
.section--navy .legal-content .legal-toc a:hover,
.section--navy .entry-content .legal-toc a:hover{color:var(--lime);border-bottom-color:var(--line-dark)}

@media (max-width:719px){
  .legal-content{font-size:16px}
  .legal-toc{padding:var(--space-4)}
  .legal-toc ul,.legal-toc ol{columns:1}
}

/* ==========================================================================
   Focus-visible — every interactive element added above
   The base rule is `:focus-visible{outline:2px solid var(--ink)}` at (0,1,0).
   These sit at (0,2,0)+ so a component can never lose its ring, and the navy
   overrides swap the ink outline (invisible on #0E1B2B) for --on-dark.
   Deliberately no border-radius here: each component keeps its own. (v1.7:
   there are no pills left — every chip is 0px or --radius-sm now — but the
   principle stands, and the ring must never re-round a hard-edged object.)
   ========================================================================== */
.breadcrumbs .breadcrumbs__item a:focus-visible,
.post-card .post-card__title a:focus-visible,
.post-card .post-card__cat:focus-visible,
.post-card .post-card__meta a:focus-visible,
.post-card__media:focus-visible,
.cs-card .cs-card__title a:focus-visible,
.cs-card__media:focus-visible,
a.cs-tag:focus-visible,
.post-meta .post-meta__item a:focus-visible,
.author-box .author-box__body a:focus-visible,
.toc .toc__list a:focus-visible,
.share-link:focus-visible,
.next-prev .next-prev__item:focus-visible,
.filter-chip:focus-visible,
.pagination .page-numbers:focus-visible,
.empty-state .btn:focus-visible,
.logo-wall .logo-wall__item a:focus-visible,
.review-card a:focus-visible,
.pricing-card .btn:focus-visible,
.form-shell .form-note a:focus-visible,
.contact-detail a:focus-visible,
.service-row .service-row__body a:focus-visible,
.service-row .btn:focus-visible,
.legal-content a:focus-visible,
.legal-toc a:focus-visible{
  outline:2px solid var(--ink);
  outline-offset:3px;
}

/* Navy bands: --ink is the band colour, so the ring has to invert.
   The umbrella rule is last so it also lifts pre-existing components
   (.btn, .card__link, footer links) placed on a navy band. */
.section--navy .breadcrumbs .breadcrumbs__item a:focus-visible,
.section--navy .post-card .post-card__title a:focus-visible,
.section--navy .cs-card .cs-card__title a:focus-visible,
.section--navy a.cs-tag:focus-visible,
.section--navy .toc .toc__list a:focus-visible,
.section--navy .share-link:focus-visible,
.section--navy .next-prev .next-prev__item:focus-visible,
.section--navy .filter-chip:focus-visible,
.section--navy .pagination .page-numbers:focus-visible,
.section--navy .contact-detail a:focus-visible,
.section--navy .legal-toc a:focus-visible,
.section--navy :focus-visible{
  outline-color:var(--on-dark);
}

/*
 * ─── FOUR (0,3,0) SELECTORS THAT OUT-RANK THE UMBRELLA ABOVE ─────────────
 *
 * The umbrella `.section--navy :focus-visible` is (0,2,0). Four entries in
 * the light-band list further up are TWO classes plus the pseudo — e.g.
 * `.pricing-card .btn:focus-visible` = (0,3,0) — and they set the `outline`
 * SHORTHAND, which resets outline-color along with everything else. So on a
 * navy band they win and re-impose --ink.
 *
 * Measured on pricing.html: the three pricing-card buttons drew
 * `2px solid rgb(14,27,43)` on a card painted rgb(19,36,58) = 1.11:1. No
 * visible ring at all.
 *
 * .pricing-card .btn is the one that ships today. The other three are the
 * same trap armed and waiting: each is (0,3,0), each sets the shorthand, and
 * each will fail the moment its component is placed on a navy band.
 * Matched at (0,4,0) here so weight, not source order, decides it.
 */
.section--navy .pricing-card .btn:focus-visible,
.section--navy .empty-state .btn:focus-visible,
.section--navy .service-row .btn:focus-visible,
.section--navy .review-card a:focus-visible{outline-color:var(--on-dark)}

/* ==========================================================================
   ==========================================================================
   v1.6 — COVERAGE FIXES (APPEND-ONLY)

   Rules for classes the templates already ship but the stylesheet never
   defined, plus the navy/tint variants three components were missing.
   Same house rules as v1.5: tokens only, no animation, every text/heading
   selector scoped to its own block so it clears the (0,1,1) base rules.
   ========================================================================== */

/* ==========================================================================
   Primary navigation — depth-2 dropdown
   Markup: header.php -> li.has-submenu > a + ul.sub-menu

   `.has-submenu` comes from the one nav filter header.php scopes to the
   primary menu; `.sub-menu` is core's own and is what every rule below is
   written against. header.php used to append a second class, `.submenu`, to
   the same <ul> — nothing in this file has ever matched it, so it is no
   longer emitted. Do not reintroduce it.
   `.main-nav > ul` (see the Header section) keeps the flex row on the top
   level only; without these rules the submenu renders permanently open and
   inline, which is what shipped.
   ========================================================================== */
.main-nav .has-submenu{position:relative}
/* (0,2,0) — out-ranks `.main-nav > ul` at (0,1,1). */
.main-nav .sub-menu{
  display:none;
  position:absolute;top:100%;left:0;z-index:120;
  min-width:232px;margin:0;padding:var(--space-3) 0;
  flex-direction:column;gap:0;
  list-style:none;
  background:var(--bg);
  border:1px solid var(--line);border-radius:var(--radius-md);
  box-shadow:var(--shadow-md);
}
/* CSS-only, no JS state — which is why header.php ships no aria-expanded. */
.main-nav .has-submenu:hover > .sub-menu,
.main-nav .has-submenu:focus-within > .sub-menu{display:flex}
.main-nav .sub-menu li{margin:0}
.main-nav .sub-menu a:not(.btn){
  display:block;
  padding:var(--space-2) var(--space-5);
  font-size:15px;font-weight:600;line-height:1.4;
}
.main-nav .sub-menu a:not(.btn):hover{color:var(--blue)}

@media (max-width:1023px){
  /* In the mobile overlay the dropdown becomes a plain indented list. */
  .main-nav .sub-menu{
    display:flex;position:static;z-index:auto;
    min-width:0;
    padding:var(--space-3) 0 0 var(--space-4);
    background:none;border:0;border-radius:0;box-shadow:none;
  }
  .main-nav .sub-menu a:not(.btn){padding:var(--space-2) 0;font-size:18px;font-weight:600}
}

/* ==========================================================================
   Announcement bar (header.php)
   Sits above the sticky header; hidden entirely when ee_announcement is blank.
   ========================================================================== */
.announcement-bar{background:var(--navy);color:var(--on-dark-body);font-size:14px}
.announcement-bar__inner{
  display:flex;flex-wrap:wrap;align-items:center;justify-content:center;
  gap:var(--space-2) var(--space-4);
  padding-top:10px;padding-bottom:10px;
}
/* (0,2,0) — beats `p:last-child{margin-bottom:0}` at (0,1,1). */
/* NO MEASURE AT ALL, and the prototype's own copy runs to a 183-character
   single line at 1440px. A banner is not body copy, so it is not held to
   §4's 62ch, but it needs a ceiling and a centre — the bar is already
   justify-content:center. 76ch ~ 100 rendered characters in Manrope. */
.announcement-bar .announcement-bar__text{margin:0;color:var(--on-dark-body);max-width:76ch;margin-inline:auto}
.announcement-bar .announcement-bar__link{
  display:inline-flex;align-items:center;gap:6px;
  color:var(--on-dark);font-weight:700;text-decoration:none;
  transition:color var(--dur-fast);
}
.announcement-bar .announcement-bar__link:hover{color:var(--lime);text-decoration:none}
.announcement-bar .arrow{color:var(--lime)}
@media (max-width:719px){.announcement-bar{font-size:13px}}

/* ==========================================================================
   Footer — rows that were inheriting the stacked `.site-footer li` rule
   ========================================================================== */
.site-footer__social,
.site-footer__legal ul,
.site-footer__meta{
  display:flex;flex-wrap:wrap;align-items:center;
  gap:var(--space-2) var(--space-5);
}
.site-footer__meta{gap:var(--space-2) var(--space-4)}
/* (0,2,1) — beats `.site-footer li{margin-bottom:var(--space-3)}` at (0,1,1). */
.site-footer .site-footer__social li,
.site-footer .site-footer__legal li{margin-bottom:0}
.site-footer__contact{margin-top:var(--space-4)}
.site-footer__social{margin-top:var(--space-5)}
/* Grid `gap` does not reach a sibling outside the grid, so claim the space. */
.site-footer .site-footer__trust{
  margin:var(--space-7) 0 0;
  max-width:60ch;
  color:var(--on-dark-body);font-size:14px;
}
@media (max-width:719px){
  .site-footer__legal ul{gap:var(--space-2) var(--space-4)}
}

/* ==========================================================================
   Editorial — post layout, hero figure, share label, next/prev labels
   ========================================================================== */
.post-layout{
  display:grid;grid-template-columns:250px minmax(0,1fr);
  gap:var(--space-8);align-items:start;
}
.post-layout > .toc{position:sticky;top:96px;margin:0}
/* Caps the editorial furniture to the prose measure set by .entry-content. */
.post-layout__main{min-width:0;max-width:720px}
@media (max-width:1023px){
  .post-layout{grid-template-columns:1fr;gap:var(--space-6)}
  .post-layout > .toc{position:static}
  .post-layout__main{max-width:none}
}

.post-hero-media{margin:0 0 var(--space-6)}
.post-hero-media img{width:100%;border-radius:var(--radius-md)}
.post-hero-media figcaption{
  margin-top:var(--space-3);
  font-size:13.5px;line-height:1.5;color:var(--muted);
}
.section--navy .post-hero-media figcaption{color:var(--on-dark-body)}

/* single.php emits a <span>, so the bare `.share-row .eyebrow` rule never fired. */
.share-row .share-row__label{
  margin-right:var(--space-2);
  font-size:12px;font-weight:700;letter-spacing:.1em;text-transform:uppercase;
  color:var(--muted);
}
.section--navy .share-row .share-row__label{color:var(--on-dark-body)}
@media (max-width:719px){
  .share-row .share-row__label{flex:1 0 100%;margin-right:0;margin-bottom:var(--space-2)}
}

/*
 * single.php uses <span class="next-prev__title">, not <strong>, so the generic
 * `.next-prev .next-prev__item span` rule was painting the title as a micro
 * label. (0,3,0) beats it — and every property that rule sets is reset here.
 */
.next-prev .next-prev__item .next-prev__label{
  /* 11.5px -> 12px, the §4 label step every other label on the site uses. */
  font-size:12px;font-weight:700;letter-spacing:.1em;
  text-transform:uppercase;color:var(--muted);
}
.next-prev .next-prev__item .next-prev__title{
  font-size:17px;font-weight:700;line-height:1.35;
  letter-spacing:normal;text-transform:none;color:var(--ink);
}
.section--navy .next-prev .next-prev__item .next-prev__label{color:var(--on-dark-body)}
.section--navy .next-prev .next-prev__item .next-prev__title{color:var(--on-dark)}

/* ==========================================================================
   Featured post card — full container width, so it needs a two-column split
   or the excerpt runs to ~1100px.

   TWO CLASS NAMES, ONE LAYOUT, AND THAT IS THE FIX FOR A REAL MISMATCH.

   home.php and index.php hand-roll the markup and write `.post-card--featured`.
   template-parts/card-post.php builds the same component from arguments and
   writes `.post-card--wide` for its documented `'wide' => true` option — a
   class that reached the page with no rule anywhere in this file. No template
   passes 'wide' => true today, so nothing was visibly broken; the first one to
   use the option would have got an ordinary card at full container width, with
   the excerpt running the whole 1240px, and no obvious reason why.

   Resolved by widening the selectors rather than by renaming: the two names are
   already documented in two places (card-post.php's docblock advertises 'wide';
   this block's own heading said "home.php / index.php"), and one design should
   not fork into two rule sets that drift. Whichever name a template uses, it
   gets this layout.
   ========================================================================== */
@media (min-width:720px){
  .post-card--featured,
  .post-card--wide{display:grid;grid-template-columns:1.1fr 1fr;align-items:stretch}
  .post-card--featured .post-card__media,
  .post-card--wide .post-card__media{
    aspect-ratio:auto;height:100%;
    border-bottom:0;border-right:1px solid var(--line);
  }
  .post-card--featured .post-card__body,
  .post-card--wide .post-card__body{padding:var(--space-6)}
  /* HOLE CLEARANCE: was clamp(24px,2.6vw,30px) — 30px sits in the 26–40px
     gap. Capped at the h3 step instead. */
  .post-card--featured .post-card__title,
  .post-card--wide .post-card__title{font-size:clamp(22px,2.4vw,26px)}
  .post-card--featured .post-card__excerpt,
  .post-card--wide .post-card__excerpt{max-width:56ch;font-size:16.5px}
}
/* The hairline that separates image from body flips to the dark line token on a
   navy band, exactly as the card's own border does a few hundred lines above.
   No text colour is set here, so both variants keep .post-card's navy palette
   unchanged: title --on-dark on --surface-dark = 14.58:1, excerpt
   --on-dark-body on --surface-dark = 7.44:1. Both clear the 4.5:1 body floor. */
.section--navy .post-card--featured .post-card__media,
.section--navy .post-card--wide .post-card__media{border-right-color:var(--line-dark)}

/* ==========================================================================
   404 page
   ========================================================================== */
.error-404__head{max-width:660px;margin:0 0 var(--space-8)}
/* margin-top was var(--space-6): a 32px lead-in from the paragraph that used
   to sit above it. That paragraph is in the navy hero now, so the search block
   opens the white band — and .error-404__head has neither padding nor border,
   so a 32px top margin would collapse straight out of it and add itself to the
   band's --section padding. Same mechanism as .cs-results; same answer. */
.error-404__search{margin:0 0 var(--space-4);max-width:540px}
/* (0,2,0) — reclaims the margin `p:last-child` zeroes. */
.error-404 .error-404__home{margin:0;font-size:15.5px}
.error-404 .error-404__home a{color:var(--blue);text-decoration:none}
.error-404 .error-404__home a:hover{color:var(--blue-dark);text-decoration:underline}
.error-404__subhead{margin:var(--space-8) 0 var(--space-5)}

/* searchform.php puts the field and the button in one .form-row, which the
   form section sets to column — side by side is what this needs. */
.search-form .form-row{flex-direction:row;flex-wrap:wrap;gap:var(--space-3)}
.search-form .search-field{flex:1 1 240px;min-width:0}
.search-form .btn{flex:0 0 auto}
@media (max-width:719px){
  .search-form .form-row{flex-direction:column}
  /* `flex:1 1 240px` above is a basis for the ROW axis. The line above turns
     the row into a column, at which point flex-basis becomes a HEIGHT and the
     404 search input rendered 312 x 240px — a text field four and a half
     times its own 54px. Release the basis when the axis flips. */
  .search-form .search-field{flex:0 0 auto}
  .search-form .btn{width:100%}
}

/* ==========================================================================
   Missing surface variants
   `.step p`, `.why-item p` and `.faq .faq__body` all sit at or above the
   specificity of `.section--navy p`, and appear later in the file, so they
   won on a navy band and painted --body (#2B3A4D) on navy (1.5:1).
   ========================================================================== */
.section--navy .step p,
.section--navy .why-item p{color:var(--on-dark-body)}
.section--navy .step h3,
.section--navy .why-item h3{color:var(--on-dark)}
.section--navy .step__num{color:var(--on-dark-body)}
.section--navy .why-item .arrow{color:var(--lime)}
.section--navy .section__lead{color:var(--on-dark-body)}
.section--navy .callout{
  background:var(--surface-dark);border-color:var(--line-dark);color:var(--on-dark);
}

.section--navy .faq details{border-top-color:var(--line-dark)}
.section--navy .faq details:last-child{border-bottom-color:var(--line-dark)}
.section--navy .faq summary{color:var(--on-dark)}
.section--navy .faq summary::after{color:var(--lime)}
.section--navy .faq .faq__body{color:var(--on-dark-body)}

/* Tint band: --line (#DFE8F2) on --bg-tint (#F5F7F9) is ~1.06:1 — invisible.
   Every other component already lifts to --line-strong here; these did not. *//* (0,2,1) -- beats `.entry-content th,.entry-content td` at (0,1,1). */
/* ==========================================================================
   ==========================================================================
   v1.8 — THE FIELD: SIGNATURE COMPONENTS  (APPEND-ONLY SECTION)

   Everything below is new. Nothing here redefines an existing class, a token,
   the @font-face blocks or :root. The v1.8 pass edited exactly four things
   in place, each flagged at its own rule: the theme Version line, the BUG 1
   note on @font-face, the retired-blue comments (the hex is now unspellable
   in this file), and `font-feature-settings:'tnum' 1` appended beside all 21
   `font-variant-numeric:tabular-nums` declarations.

   THE FOUR OBJECTS THIS SECTION ADDS, IN THE ORDER A PAGE MEETS THEM:

       .ee-arrow      the mark            — BUG 1, the only ↗ on the site
       .hero-field    the ground          — DIRECTION.md §8
       .plate         the caption         — §2, third device
       .trajectory    the signature       — §2, THE device

   HOUSE RULES, UNCHANGED AND NOT NEGOTIABLE:
   - No @keyframes. No `animation`. No `transform` inside any :hover, :focus
     or :active rule. Nothing below contains the string `transform` at all.
   - Transitions are limited to color / background / border-color /
     outline-color at var(--dur-fast), which is 0s. There are none in this
     section: every object here is a hairline or a photograph, and neither
     has a hover state.
   - Tokens only. The single class of literal permitted is an rgba() tint
     derived from a token above: navy 14,27,43 · on-dark 245,247,249.
   - Hard 0px radius. No fills where a hairline will do. No shadows.

   ---------------------------------------------------------------------------
   SPECIFICITY — THE FOURTH COLLISION IS THE ONE THIS BLOCK EXISTS TO AVOID.

   Five base rules out-rank a single-class component rule. Every one of them
   reaches into the components below, because these components carry <p>, <a>
   and <img> children and sit on a navy ground:

       p{margin:0 0 var(--space-4)}                 (0,0,1)
       img{max-width:100%;height:auto}              (0,0,1)
       a{color:var(--ink)}                          (0,0,1)
       p:last-child{margin-bottom:0}                (0,1,1)
       a:hover{text-decoration:underline}           (0,1,1)
       .section--navy p / h2,h3,h4{color:…}         (0,1,1)
       .card p{color:var(--body);font-size:16px}    (0,1,1)

   So every text, heading, link and image rule below is scoped to its own
   block — `.plate .plate__name`, not `.plate__name` — to reach (0,2,0) or
   better. That is deliberate. Do not "simplify" these selectors to one
   class: the margins and colours collapse silently the next time this file
   is touched, which is how the previous three collisions shipped. The
   computed specificity is stated in a comment wherever it is deliberately
   raised, and wherever a rule wins on SOURCE ORDER rather than on weight —
   the second kind is the fragile kind and it is called out by name.
   ==========================================================================
   ========================================================================== */

/* ==========================================================================
   1. THE ARROW — the SVG sprite cuts                        BUG 1 · §5
   ==========================================================================

   Markup comes from inc/arrow.php:

       <svg class="ee-arrow ee-arrow--inline" aria-hidden="true"
            focusable="false"><use href="#ee-arrow-ne"/></svg>

   Two axes, deliberately not the same list:
       SYMBOL  #ee-arrow-ne (the brand motif, 45°) · #ee-arrow-e (link
               affordance) · #ee-arrow-arch (the architectural ground)
       CUT     --inline (cap height, scales with the type) · --ui (fixed
               16px) · --arch (block, sized by its container)

   Every path is `fill="currentColor"`, so the arrow inherits lime on navy
   and navy on white with no per-context override. Nothing here sets a
   colour, and nothing here should ever start to.

   ─────────────────────────────────────────────────────────────────────────
   THIS BLOCK IS A DELIBERATE DUPLICATE. READ BEFORE CHANGING EITHER COPY.

   inc/arrow.php also prints the three cut rules inline, hooked to `wp_head`
   at priority 1, so the arrow is correctly sized before this stylesheet has
   loaded — the sprite and the geometry that sizes it must not be able to
   ship apart from each other.

   WordPress prints enqueued stylesheets on `wp_head` at priority 8. This
   file therefore lands AFTER that inline <style>, at equal specificity —
   which means THIS COPY WINS EVERY TIE. It is not a harmless duplicate: it
   is the authoritative one, and a divergence here silently overrides the
   critical-path CSS rather than being overridden by it. That is the reverse
   of what "critical CSS" usually implies, and it is the trap.

   KEEP THE TWO COPIES BYTE-IDENTICAL FOR THE THREE CUTS. If a cut needs
   changing, change it in inc/arrow.php first, then mirror it here. The
   fourth rule that file prints — `.site-logo .ee-arrow` — is deliberately
   NOT mirrored; see the note where it would have gone.
   ───────────────────────────────────────────────────────────────────────── */

/* (0,1,0). `flex:0 0 auto` is load-bearing: .btn is inline-flex, and an SVG
   with no intrinsic size is squashed to zero as a flex item without it.
   `vertical-align:-.14em` drops the 1em box so the ink — which occupies the
   central 72 units of the 100-unit viewBox, Manrope's cap height — lands
   exactly baseline-to-cap-height beside the type. */
.ee-arrow{
  display:inline-block;
  width:1em;height:1em;
  vertical-align:-.14em;
  fill:currentColor;stroke:none;
  flex:0 0 auto;
}

/* The default cut, named so a call site can be explicit. Same box as the
   base rule on purpose — .ee-arrow IS the inline cut. */
.ee-arrow--inline{width:1em;height:1em}

/* Fixed 16px, so every button and "read more" on the site carries the
   identical mark whatever the type size around it. */
.ee-arrow--ui{width:16px;height:16px}

/* Scenery, never a pointer target. Sized by its container. */
.ee-arrow--arch{
  display:block;
  width:100%;height:auto;
  vertical-align:baseline;
  pointer-events:none;
}

/*
 * `.site-logo .ee-arrow` IS DELIBERATELY NOT DUPLICATED HERE.
 *
 * inc/arrow.php sets `margin:0 .07em;position:relative;top:-.045em` on it,
 * and the `top` is a derived value, not a taste call: `.site-logo` is a flex
 * row with `align-items:center`, so `vertical-align` — the thing that lands
 * the inline cut on the baseline everywhere else — is ignored on it, and the
 * mark centres 0.99px below the cap band's centre at 22px. 0.045em is exactly
 * that shortfall.
 *
 * Restating only the `margin` half here would leave this file winning the tie
 * on source order for the property it names while the nudge kept applying
 * from the inline copy — the two halves of one optical correction, resolved
 * in two files. It works today and would break the first time someone
 * "completed" this rule. The whole rule stays in inc/arrow.php, next to the
 * arithmetic that produced it.
 *
 * A `.ee-arrow` inside a link needs no `text-decoration:none` either: it is
 * `display:inline-block`, and an inline-block does not take the propagated
 * decoration of an ancestor inline box. The underline already stops at it.
 */

/* The sprite host — the <svg class="ee-arrow-sprite"> that
   ecomenable_arrow_sprite() in inc/arrow.php prints once per page, holding the
   three <symbol>s every ecomenable_get_arrow() call points a <use> at. That
   element already carries these four declarations (and display:none besides)
   in a style attribute, so in a normal request this rule changes nothing on
   screen. It is here because the class was reaching the page with no rule
   behind it anywhere in the theme, and because a filter or a
   Content-Security-Policy that strips inline style attributes would otherwise
   drop a full-size SVG into the top of every page. */
.ee-arrow-sprite{position:absolute;width:0;height:0;overflow:hidden}


/* ==========================================================================
   2. THE TRAJECTORY RULE — the signature device              §2 · §8.3 L4
   ==========================================================================

   THE most-used object on the site and the thing a visitor remembers. A
   full-bleed 1px hairline, two or three cells beneath it divided by 1px
   vertical hairlines, one hairline closing the row. Two hairlines and some
   type. IT IS NOT A CARD: no fill, no border box, no radius, no shadow.

   Markup:

       <div class="trajectory trajectory--navy">
         <div class="trajectory__inner">
           <div class="tr-cell">
             <span class="tr__from">Guesswork</span>
             <span class="tr__arrow"><svg class="ee-arrow">…</svg></span>
             <span class="tr__to">Evidence</span>
             <span class="tr__label">How we decide</span>
           </div>
           …
         </div>
       </div>

   ONE PER PAGE, plus one per case-study results block. Not more.

   TWO CONTENT MODES, ONE COMPONENT — and this is the whole point of the
   thing. Qualitative (`Guesswork ↗ Evidence`) is honest and shippable today
   with no client data; numeric (`£250k ↗ £640k`) is the upgrade whenever a
   real figure exists. Nothing in the CSS knows which is which. Switching is
   a content edit, not a redesign, and it is why this band never has to
   render `[stat]` or an em dash to hold its place in the ladder.

   THE LOCKUP IS A FIXED TYPOGRAPHIC UNIT — a low term, a rising mark, a tall
   term. The proportions never change, which is what makes it recognisable as
   a SHAPE before it is read as content. That is enforced here by setting the
   `to` size ONCE, on .tr-cell, and deriving everything else from it in `em`:

       .tr__to     1em      of the cell        = full size, weight 800
       .tr__from   .58em    of the cell        = 58%, exactly, weight 700
       .tr__arrow  1em box  of the cell        → ink at .72em = the cap
                                                 height of the `to` term
       margins     .4em     of the arrow's em  = the specified space either
                                                 side, in the `to` term's em

   Change the cell font-size and the whole lockup rescales in proportion.
   There is no second number to keep in step. */

/* THE COMPONENT ------------------------------------------------------------
   Full-bleed by construction: .trajectory is the full width of whatever
   contains it, so both horizontal hairlines run edge to edge, and
   .trajectory__inner re-establishes the reading measure inside them.
   Drop it straight into a .section--bleed band or into .hero-field. */
.trajectory{
  width:100%;
  border-top:1px solid var(--line);
  border-bottom:1px solid var(--line);
}

/* §2's prose says "a full-bleed 1px hairline with cells beneath it"; §2's
   diagram draws a rule above AND below. The diagram is the more concrete
   spec and is what is built. Where the row butts the bottom edge of a band
   the closing rule doubles up with the next section's edge — that is what
   this utility is for, and it is the only modifier the component has beyond
   the two colour variants. */
.trajectory--flush{border-bottom:0}

/*
 * NO HORIZONTAL PADDING HERE, AND THE CELLS CARRY THE GUTTER INSTEAD.
 *
 * The obvious construction — `padding:0 var(--gutter)` on the inner, then
 * `padding-left:0` on the first cell and `padding-right:0` on the last to
 * flush the outer terms to the reading measure — produces THREE CELLS OF
 * DIFFERENT WIDTHS. That is invisible until the type is sized from the cell:
 * `cqi` resolves against the container's CONTENT box, so the middle cell
 * (padded both sides) computed 33.2px while its neighbours (padded one side)
 * computed 36.5px. Three lockups at two different sizes in one row, which is
 * precisely the "fixed typographic unit" the device depends on, broken.
 *
 * Giving every cell the same 24px padding and taking the gutter off the inner
 * puts the first cell's text exactly 24px inside the 1240px box — the same
 * place `.container` puts its own content, so the trajectory still lines up
 * with the hero copy and the section heads above it — while keeping all three
 * content boxes identical. Same alignment, one size, no special cases.
 */
.trajectory__inner{
  max-width:var(--container);
  margin:0 auto;
  padding:0;
  display:grid;
  /* Column flow, not a fixed template: the component takes 2 or 3 cells and
     divides the measure evenly with no modifier class and no count in the
     markup. */
  grid-auto-flow:column;
  grid-auto-columns:1fr;
}

/* THE CELL -----------------------------------------------------------------
   `flex-wrap` + a 100%-basis label is what puts the lockup on line 1 and the
   label on line 2 without a wrapper element — the brief specifies from /
   arrow / to / label as siblings, so there is no lockup div to lay out.
   `align-content:center` then centres both lines in the 128px cell. */
.tr-cell{
  display:flex;flex-wrap:wrap;
  align-items:baseline;align-content:center;
  min-height:128px;min-width:0;
  /* UNIFORM ON ALL FOUR SIDES AND ON EVERY CELL — see the note on
     .trajectory__inner. Equal padding is what keeps the content boxes equal,
     which is what keeps every lockup in the row at one size. */
  padding:var(--space-5);
  /* THE ONE SIZE THE LOCKUP IS BUILT FROM. §4: the `to` step, 40 → 72px.
     Nothing else in the component carries a px font-size except the label.
     It is a CEILING, not the final size — see the cqi note on .tr__to. */
  font-size:clamp(40px,5.2vw,72px);
  /* Makes the cell a query container so the lockup can measure ITSELF
     against the width it actually got. See the note on .tr__to. */
  container-type:inline-size;
}
/* The vertical hairlines. On the cell, not on a pseudo-element, so they
   inherit the cell's full height and need no positioning context.

   DRAWN AS A BOX-SHADOW, NOT A BORDER, AND THAT IS THE WHOLE POINT.
   `container-type:inline-size` above makes each cell a query container, and
   both terms are sized in cqi. A 1px border is INSIDE the container box, so
   cells 2 and 3 measured 364.33px of content against cell 1's 365.33px — and
   10cqi of one less pixel gave `to` at 36.43px next to 36.53px, `from` at
   21.13px next to 21.19px. The row was three subtly different sizes.
   A box-shadow paints outside the box and costs the container nothing, so the
   note on .trajectory__inner — "equal padding is what keeps the content boxes
   equal, which is what keeps every lockup in the row at one size" — is true
   again. Inset -1px so it lands where the left border did. */
.tr-cell + .tr-cell{border-left:0;box-shadow:-1px 0 0 0 var(--line)}

/* THE LOCKUP ---------------------------------------------------------------
   All three at (0,2,0). Scoped to .trajectory because a template may emit
   these as <p> or wrap a cell in an <a>, and `p:last-child` (0,1,1),
   `.section--navy p` (0,1,1) and `a{color:var(--ink)}` (0,0,1) all reach in.
   A bare `.tr__to` at (0,1,0) would lose the colour fight on a navy band. */
.trajectory .tr__from{
  flex:0 0 auto;
  margin:0;
  font-size:min(.58em,5.8cqi);     /* exactly 58% of the `to` term */
  font-weight:700;line-height:1;letter-spacing:-.02em;
  color:var(--muted);
  font-variant-numeric:tabular-nums;font-feature-settings:'tnum' 1;
}

/* The arrow sits in a 1em box — the `to` term's em — so the ink lands at
   .72em, its cap height. `.4em` either side, measured in that same em, is
   the specified space. `line-height:1` keeps the span's line box from
   inflating the row. */
.trajectory .tr__arrow{
  flex:0 0 auto;
  display:inline-block;
  margin:0 .4em;
  font-size:min(1em,10cqi);line-height:1;
  /*
   * NAVY ON WHITE, LIME ON NAVY — and this is a deliberate departure from
   * §2's table, which specifies the lockup arrow as lime unconditionally.
   *
   * §3.4 rule 4 is a brand-book non-negotiable: lime never appears as small
   * text on a light ground, because #C6F432 on #FFFFFF is 1.2:1. The arrow
   * here is not decorative — it is the operator between the two terms, so it
   * carries meaning and WCAG 2.1 wants 3:1 of it as a graphic. Lime on white
   * gives 1.2:1 at any size, so on a white band the arrow is navy.
   *
   * The component's specified homes — the hero field and the proof band —
   * are both navy, where it is lime as intended. The white variant exists
   * for the case-study results block.
   */
  color:var(--navy);
}

/*
 * ─── THE 72px CEILING IS UNREACHABLE FOR 3-CELL QUALITATIVE CONTENT ───────
 * THIS IS THE ONE PLACE THE BUILD DEPARTS FROM A LITERAL VALUE IN §4, AND IT
 * IS A GEOMETRY PROBLEM, NOT A TASTE ONE. IT NEEDS A DESIGN DECISION.
 *
 * §4 sets `.tr__to` to clamp(40px, 5.2vw, 72px). §2 sets the component at two
 * or three cells inside the 1240px container, with `Guesswork ↗ Evidence` as
 * its own worked example. Those two do not fit together. Measured in the
 * browser at a 1440px viewport, three cells across the container, the widest
 * `to` size that keeps each lockup on ONE LINE is:
 *
 *     Guesswork ↗ Evidence   41.8px     (spec asks for 72px — 1.7x over)
 *     Chaos ↗ Control        48.7px
 *     Listings ↗ Profit      56.4px
 *     £250k ↗ £640k          90.1px     (2-cell numeric mode: 72px is fine)
 *
 * At the specified 72px the lockup wraps onto three lines and stops being a
 * lockup — and the shape, "a low term, a rising mark, a tall term", is the
 * entire reason the device works before it is read.
 *
 * THE FIX: size from the CELL, not the viewport. `10cqi` is 10% of the cell's
 * own inline size, so the type tracks the width the lockup actually got —
 * smaller with three cells, larger with two, larger again in a full-bleed
 * placement — and the §4 clamp is kept as the `min()` ceiling, so the spec
 * value still governs wherever it fits. The 5.8/10 pair preserves the fixed
 * 58% proportion exactly, and the arrow's `.4em` margins keep tracking the
 * `to` size because they resolve against this same computed value.
 *
 * WHY IT ALSO FIXES MOBILE FOR FREE: below 719px the cells stack full width,
 * where 10cqi would be enormous — the `min()` against the 34px rule in the
 * mobile block caps it at 34px with no extra rule.
 *
 * TWO THINGS TO CHECK BEFORE LAUNCH:
 *   1. RE-MEASURE WITH REAL MANROPE. The numbers above were taken with a
 *      fallback face, because the woff2 cannot load in the test harness.
 *      10cqi leaves only ~5% headroom on the worst case in that face. If
 *      Manrope ExtraBold is wider, drop the pair to 9.5/5.51.
 *   2. THE ALTERNATIVE FIX IS A COPY DECISION, AND IT MAY BE THE BETTER ONE:
 *      keep 72px and shorten the terms. `Guesswork ↗ Evidence` is 19
 *      characters; `Chaos ↗ Control` is 15 and already fits at 48.7px. If the
 *      qualitative pairs are capped at ~8 characters a side, revert both
 *      declarations to `1em` / `.58em` and delete `container-type` above.
 * ───────────────────────────────────────────────────────────────────────── */
.trajectory .tr__to{
  flex:0 1 auto;
  min-width:0;margin:0;
  font-size:min(1em,10cqi);
  font-weight:800;line-height:1;letter-spacing:-.03em;
  color:var(--ink);
  font-variant-numeric:tabular-nums;font-feature-settings:'tnum' 1;
}

/* `flex:0 0 100%` is what forces the label onto its own line — it is the
   line break, and it is why the component needs no lockup wrapper.
   12px fixed, NOT em: the label is a label at every cell size. (0,2,0)
   also reclaims the bottom margin `p:last-child` zeroes if it is a <p>. */
.trajectory .tr__label{
  flex:0 0 100%;
  margin:14px 0 0;
  font-size:12px;font-weight:600;line-height:1.4;
  letter-spacing:.12em;text-transform:uppercase;
  color:var(--muted);
}

/* THE NAVY VARIANT ---------------------------------------------------------
   Three ways in, all resolving to the same paint:
     .trajectory--navy   explicit, for a standalone placement
     .section--navy      the band carries it
     .hero-field         the hero field carries it

   `.trajectory.trajectory--navy` is written as a DOUBLE CLASS on purpose.
   `.trajectory--navy .tr__from` computes to (0,2,0) — an exact TIE with the
   base rule `.trajectory .tr__from`, which would leave the winner decided by
   source order alone. That is the fragile pattern this codebase has been
   bitten by three times. The doubled class lifts it to (0,3,0) and it wins
   on weight. The two descendant forms are (0,3,0) already. */
.trajectory.trajectory--navy,
.section--navy .trajectory,
.hero-field .trajectory{border-top-color:var(--line-dark);border-bottom-color:var(--line-dark)}

/* Mirrors the box-shadow divider above — a border-left-color override would
   have nothing left to colour. */
.trajectory.trajectory--navy .tr-cell + .tr-cell,
.section--navy .trajectory .tr-cell + .tr-cell,
.hero-field .trajectory .tr-cell + .tr-cell{box-shadow:-1px 0 0 0 var(--line-dark)}

.trajectory.trajectory--navy .tr__from,
.section--navy .trajectory .tr__from,
.hero-field .trajectory .tr__from{color:var(--on-dark-body)}

/* The arrow is lime here, as §2 specifies. 13.5:1 on navy. */
.trajectory.trajectory--navy .tr__arrow,
.section--navy .trajectory .tr__arrow,
.hero-field .trajectory .tr__arrow{color:var(--lime)}

.trajectory.trajectory--navy .tr__to,
.section--navy .trajectory .tr__to,
.hero-field .trajectory .tr__to{color:var(--on-dark)}

.trajectory.trajectory--navy .tr__label,
.section--navy .trajectory .tr__label,
.hero-field .trajectory .tr__label{color:var(--on-dark-body)}

/*
 * ─── "TABLET KEEPS THE THREE COLUMNS. NOTHING TO DO." — THAT WAS WRONG. ───
 *
 * §8.2's tablet column assumed the 72px ceiling. It is unreachable: the cell
 * sizes the type, --container caps at 1240px, so `10cqi` tops out at 36.53px
 * even on a wide desktop. Below 1024 the three columns keep shrinking and the
 * lockup goes with them. Measured on index.html:
 *
 *      719px   to 34.00px   from 19.72px      (stacked)
 *      720px   to 18.70px   from 10.85px      (three columns)
 *      768px   to 20.30px   from 11.77px      <- iPad portrait
 *      900px   to 24.70px   from 14.33px
 *     1023px   to 28.80px   from 16.70px
 *
 * One pixel of viewport, 719 -> 720, dropped the `to` term by 45%, and from
 * 720 to ~840 the `from` term rendered SMALLER THAN ITS OWN 12px LABEL — the
 * caption out-sizing the term it captions. "A low term, a rising mark, a tall
 * term" is the whole device, and it inverted.
 *
 * The fix is not a new size, it is the system's own breakpoint: stack at
 * 1023, where the grids already collapse, and the squashed band stops
 * existing. Three columns then run only at >=1024, where `to` is 28.8-36.5px.
 * The mobile block's 34px rule now governs 0-1023 and the min() ceiling still
 * caps the stacked full-width cells, exactly as its note describes.
 *
 * NOT CHANGED: 10cqi / 5.8cqi stay. Raising them to reach §4's 40px floor was
 * considered and rejected — the note above measures 10cqi as the widest that
 * keeps `Guesswork -> Evidence` on ONE LINE, and a wrapped lockup is a worse
 * failure than a small one.
 */
@media (max-width:1023px){
  /* Three stacked rows, 96px each, hairline between (§8.2, mobile column).
     The dividers rotate from vertical to horizontal with the flow. */
  .trajectory__inner{grid-auto-flow:row;grid-auto-columns:auto}
  .tr-cell{
    min-height:96px;
    /* Keeps the 24px inline gutter that matches .container, and tightens the
       block padding because min-height is doing the work down here. */
    padding:var(--space-4) var(--space-5);
    font-size:34px;              /* §4, mobile column */
  }
  /* `box-shadow:none` is what the old `border-left:0` used to do — the
     vertical divider is a shadow now, so it has to be turned off the same
     way, at each of the two specificities that draw it. */
  .tr-cell + .tr-cell{border-left:0;box-shadow:none;border-top:1px solid var(--line)}
  .trajectory.trajectory--navy .tr-cell + .tr-cell,
  .section--navy .trajectory .tr-cell + .tr-cell,
  .hero-field .trajectory .tr-cell + .tr-cell{border-left:0;box-shadow:none;border-top-color:var(--line-dark)}
  .trajectory .tr__label{margin-top:12px}
}


/* ==========================================================================
   3. THE HERO FIELD — a navy ground with an optional photograph      §8
   ==========================================================================

   THE SINGLE MOST IMPORTANT STRUCTURAL DECISION IN THE DIRECTION:
   THE HERO IS A NAVY FIELD AND THE PHOTOGRAPH IS AN OPTIONAL LAYER IN IT.

   Nothing breaks when the photograph is absent, because the FIELD is the
   design and the photograph is an upgrade to it. Compare what this replaces:
   a right-hand column containing three em dashes, an empty four-line chart
   and the caption "Illustrative — no client data shown" — a written
   admission, in the fold, that there is nothing in it.

   The practical consequence is that THE PHOTO SHOOT IS NOT ON THE CRITICAL
   PATH TO LAUNCH. Ship on the field; upgrade to photography later; the
   layout, the type positions and the trajectory rule are identical either
   way, and no stock photograph is ever bundled as a stand-in.

   Markup (§8.1):

       <section class="hero-field">
         <div class="hero-field__frame">
           <picture class="hero-field__media">…</picture>   ONLY with a photo
           <span    class="hero-field__scrim"></span>       ONLY with a photo
           <svg     class="arrow-arch">…</svg>              ONLY without one
           <div class="container">
             <div class="hero-field__copy">…</div>
           </div>
           <figcaption class="plate">…</figcaption>         ONLY with a photo
         </div>
         <div class="trajectory">…</div>                    ALWAYS
       </section>

   Paint order is z-index, not source order: media 0 · arch 0 · scrim 1 ·
   copy 2 · plate 3. */

/* Full-bleed and navy. The section paints the ground itself, so it needs
   neither .section--navy nor .section--bleed to look right — but it accepts
   both without conflict. */
.hero-field{
  position:relative;
  width:100%;max-width:none;
  padding:0;
  background:var(--navy);
  color:var(--on-dark-body);
}

/* The photograph band. `overflow:hidden` is what CROPS the architectural
   arrow against the top and right edges — the crop is the whole point of
   that shape, not a side effect. It also clips the photograph to the frame.
   The frame paints --navy itself: that, and nothing else, is the entire
   no-photograph fallback. */
.hero-field__frame{
  position:relative;
  display:flex;align-items:center;
  min-height:clamp(520px,72vh,720px);
  overflow:hidden;
  background:var(--navy);
}

/* LAYER 0 — the photograph.
   `object-position:72% 42%` is load-bearing, not a default: when a narrow or
   short viewport crops the frame it eats the empty LEFT side, where the
   headline sits, rather than cutting faces off the right. Desktop takes the
   2:1 crop; below 900px a <source media="(max-width:900px)"> in the markup
   serves the separately art-directed 1:1 crop — a different photograph, not
   a CSS crop of the same one. */
.hero-field__media{
  position:absolute;inset:0;z-index:0;
  display:block;margin:0;
}
/* (0,1,1) — element+class, so it beats the base `img{height:auto}` at
   (0,0,1). Without this the photograph collapses to its intrinsic height
   inside an absolutely positioned <picture>.

   `.hero-field__img` is listed beside it (v1.8.1) because BOTH ways into this
   component emit it: template-parts/hero-field.php sets it on the <img> it
   hands to wp_get_attachment_image(), and ecomenable_get_team_hero_picture()
   in inc/images.php sets `img_class => 'hero-field__img'`. It was a name with
   no rule behind it, which only went unnoticed because the descendant selector
   happened to cover the same elements. It is (0,1,0), which still clears the
   base `img` rule at (0,0,1). */
.hero-field__media img,
.hero-field__img{
  width:100%;height:100%;
  object-fit:cover;object-position:72% 42%;
  display:block;border-radius:0;
}

/* LAYER 1 — the scrim. ONLY with a photograph.
   This is NOT decoration and it is the one gradient the direction permits
   outside the photographic grade: it guarantees Soft White clears 4.5:1 over
   the frame at every crop on every viewport, which is the single clear
   weakness in the reference hero this was measured against. The stops are
   §8.3 verbatim. rgba(14,27,43,…) is --navy in decimal — a permitted literal
   because it is derived from a token in :root, and the only kind there is. */
.hero-field__scrim{
  position:absolute;inset:0;z-index:1;
  pointer-events:none;
  background:linear-gradient(90deg,
    rgba(14,27,43,.94)  0%,
    rgba(14,27,43,.82) 32%,
    rgba(14,27,43,.34) 60%,
    rgba(14,27,43,0)   84%);
}

/* LAYER 1b — the architectural arrow. ONLY WITHOUT a photograph.
   The subordinate device: one arrow at 45°, ~1080px tall, cropped by two
   edges of its container, filled navy-on-navy at roughly a 6% step. It is
   SCENERY, NEVER CONTENT — it exists to give a navy band a ground when there
   is no photograph, and it appears EXACTLY ONCE PER PAGE, in the topmost
   slot that needs it (hero → team band → final CTA).

   FIELD CHECK BEFORE LAUNCH: --surface-dark (#13243A) on --navy (#0E1B2B) is
   a 6% step and may band on an over-saturated panel. If it does, add
   .arrow-arch--outline below rather than lifting the fill — an outlined
   arrow is arguably the better drawing anyway. */
.arrow-arch{
  position:absolute;z-index:0;
  top:-80px;right:-140px;
  width:auto;height:1080px;
  /* COLOUR, NOT FILL — and this is not interchangeable.
     inc/arrow.php draws every symbol as <path fill="currentColor">. A
     presentation attribute loses to any CSS rule, but it BEATS inheritance,
     and inside a <use> shadow tree inheritance is the only route in — so
     `fill` set here on the <svg> never reaches the path. The arrow then
     resolves currentColor against the inherited band colour and renders
     --on-dark-body light grey across the hero instead of a 6% navy step.
     Setting `color` feeds currentColor directly and keeps the sprite's
     one-drawing contract intact. `fill` stays as a fallback for any future
     non-<use> inlining of the same path. */
  color:var(--surface-dark);
  fill:var(--surface-dark);
  pointer-events:none;
}
/*
 * (0,2,0) — RAISED DELIBERATELY, and this one matters.
 *
 * inc/arrow.php emits the architectural cut as `class="ee-arrow
 * ee-arrow--arch"`, and .ee-arrow--arch sets `width:100%;height:auto` at
 * (0,1,0) — an exact TIE with .arrow-arch above. A tie between two rules in
 * two different files, one of them printed inline in wp_head, is decided by
 * whichever the browser saw last, which is a coin flip nobody would think to
 * check. The doubled class settles it on weight instead: wherever an element
 * carries both, this rule wins and the arrow is 1080px tall, not 100% wide.
 */
.ee-arrow.arrow-arch{width:auto;height:1080px}

/* The documented escape hatch if the 6% fill bands on real hardware.
   `fill:none` + a 1px stroke turns the same filled path into its outline —
   no second asset, no second symbol. (0,2,0) beats .arrow-arch at (0,1,0). */
.arrow-arch.arrow-arch--outline{
  fill:none;
  stroke:var(--line-dark);stroke-width:1px;
}

/* LAYER 2 — the type block. Cols 1–7 of 12 (58%), vertically centred.
   .container is the flex child that has to fill the frame. */
.hero-field > .hero-field__frame > .container,
.hero-field .hero-field__frame > .container{
  position:relative;z-index:2;
  width:100%;
}
.hero-field__copy{
  max-width:58%;min-width:0;
  padding:var(--space-8) 0;
}

/* Colour on the field. All (0,2,0), which is what they need to be:
   `.display` is (0,1,0), the h1–h4 rule is (0,0,1), and `.eyebrow` is
   (0,1,0) — a bare class here would tie or lose. */
.hero-field h1,
.hero-field .display{color:var(--on-dark)}
.hero-field .eyebrow{color:var(--lime)}
.hero-field .lead-xl{color:var(--on-dark-body);max-width:48ch}
.hero-field .micro{color:var(--on-dark-body)}
/* `.hero-field .lime{color:var(--lime)}` is already set in the type scale
   block at the head of this file. The ONE lime keyword in the H1 lives
   there, once per page. Nothing is restated here. */

/* The §8.3 vertical rhythm: eyebrow 20 H1 24 sub 32 CTA 14 micro.
   Every one of these is (0,2,0) or better and needs to be — the elements are
   <p> and <span>, so `p{margin:0 0 var(--space-4)}` (0,0,1) and
   `p:last-child{margin-bottom:0}` (0,1,1) both reach them. */
.hero-field__copy .eyebrow{margin-bottom:20px}
.hero-field__copy .display,
.hero-field__copy h1{margin-bottom:24px}
.hero-field__copy .lead-xl{margin-bottom:32px}
.hero-field__copy .hero__ctas{margin:0 0 14px;gap:var(--space-5)}
.hero-field__copy .micro{margin:0}

/*
 * The hero secondary action is a TEXT LINK, not a second button (§6, and §12
 * "Two equally-weighted buttons in the hero — rejected"). One lime button and
 * one underlined link makes the primary action unambiguous.
 *
 * This is done by RESTYLING .btn--secondary in place rather than by adding a
 * new class, so no template has to change and the global component — which 52
 * templates use on white bands where the bordered form is still correct — is
 * untouched.
 *
 * (0,3,0) — RAISED DELIBERATELY. `.section--navy .btn--secondary` is (0,2,0),
 * and so is `.hero-field .btn--secondary`; a tie there would be settled by
 * source order the moment anyone put both classes on the hero section, which
 * §3.4 rule 4 arguably invites. The third class removes the question.
 */
.hero-field .hero-field__copy .btn--secondary{
  /* THE LOOK IS INTENDED, THE 16px HIT AREA IS NOT. `min-height:0;padding:0`
     gave a 131 x 16px control (312 x 16 at 375px) sitting beside a 54px
     primary. 44px of hit area with the padding cancelled by an equal negative
     margin: the underline, the baseline and the 24px gap to the button are
     all exactly where they were. */
  min-height:44px;padding:14px 0;margin:-14px 0;
  background:transparent;border:0;border-radius:0;
  color:var(--on-dark);font-weight:700;
  text-decoration:underline;
  text-decoration-thickness:1px;
  text-underline-offset:6px;
}
/* Hover moves the UNDERLINE to lime and leaves the label alone. Colour only —
   no lift, no box, no motion. */
.hero-field .hero-field__copy .btn--secondary:hover{
  color:var(--on-dark);
  text-decoration-color:var(--lime);
}

/*
 * THE NO-PHOTOGRAPH FALLBACK — §9.4 behaviour (a), "the field carries it".
 *
 * There is no `.hero-field--empty` class and there should not be one. The
 * frame already paints --navy, so removing <picture> from the template leaves
 * a designed navy hero with identical type positions and an identical
 * trajectory rule. NOTHING IS MISSING BECAUSE NOTHING WAS EVER REQUIRED.
 *
 * The two rules below are the only mechanism, and they make the state
 * self-correcting rather than something a template has to remember:
 *   · a scrim with no photograph under it is a flat 94% navy wash over navy,
 *     which mutes the headline for no reason — so it hides itself;
 *   · the architectural arrow is the ground of LAST resort, so it stands
 *     down the moment a photograph arrives to be the ground instead.
 *
 * :has() SETS THE SUPPORT FLOOR FOR THIS STYLESHEET. It used to be able to
 * point at the `.form-grid` rows in the Forms block and say it added nothing
 * new; those rows were deleted in v1.8.2 as dead CSS, so the only `:has()`
 * left in the file is these two rules and `.founder-band:not(:has(...))`.
 * That is a deliberate floor, not an accident: Safari 15.4+, Chrome/Edge 105+
 * and Firefox 121+. Everything it gates degrades to the pre-§8 state rather
 * than to a broken one — a browser without :has() shows the scrim over the
 * navy field and the architectural arrow behind the photograph, which is
 * muddy but legible, never blank. Both compute to (0,2,0): :not() and :has()
 * take the specificity of their argument.
 */
.hero-field__frame:not(:has(.hero-field__media)) .hero-field__scrim{display:none}
.hero-field__frame:has(.hero-field__media) .arrow-arch{display:none}

@media (max-width:1023px){
  .hero-field__frame{min-height:560px}      /* §8.2, tablet */
  .hero-field__copy{max-width:75%}          /* cols 1–9 of 12 */
}

/*
 * 900px and 767px are HERO-ONLY breakpoints and are deliberately not the
 * file's 1023/719 pair. Both are tied to something outside CSS:
 *   900px — the <source media="(max-width:900px)"> boundary where the markup
 *           swaps the 2:1 wide crop for the separately art-directed 1:1
 *           square. The scrim has to turn at the same pixel as the picture,
 *           or a landscape scrim sits over a square photograph.
 *   767px — §8.4's layout inversion, and the point at which the
 *           architectural arrow drops out entirely.
 * Do not "tidy" either of them to 1023/719.
 */
@media (max-width:900px){
  /* The square crop needs the scrim to run top-to-bottom, not left-to-right:
     the type sits below the photograph now, not beside it. §8.3 verbatim. */
  .hero-field__scrim{
    background:linear-gradient(180deg,
      rgba(14,27,43,.30)  0%,
      rgba(14,27,43,0)   28%,
      rgba(14,27,43,.88) 100%);
  }
}

@media (max-width:767px){
  /* The type fills the frame on its own down here; the arrow would only
     compete with it. */
  .arrow-arch{display:none}

  /*
   * §8.4 — the layout inverts and NOTHING IS LAYERED OVER ANYTHING. The
   * square photograph becomes a block at the top of the frame with the plate
   * flush to its bottom-right corner, and the copy runs beneath it at full
   * width. The CTA stays above the fold on a 390 × 844 screen.
   *
   * DEVIATION FROM §8.4, FLAGGED FOR THE TEMPLATE PASS: §8.4 orders the
   * mobile hero eyebrow → H1 → photograph → sub → button. That splits
   * .hero-field__copy either side of the photograph, which is a MARKUP
   * change (two copy blocks, or the H1 hoisted out) and cannot be done from
   * the stylesheet — CSS can reorder siblings, not divide one. What is built
   * here is the whole-block order: photograph, then all copy. If the
   * template later emits a second .hero-field__copy above the media, this
   * rule set already lays it out correctly with no CSS change.
   */
  /*
   * The frame becomes a two-row grid and NOTHING IS POSITIONED ABSOLUTELY
   * ANY MORE. Row 1 is the square photograph; the scrim and the plate are
   * placed into that same cell so they overlay the picture and only the
   * picture. Row 2 is the copy.
   *
   * This replaces the obvious approach — leaving the plate `position:
   * absolute` and offsetting it — which cannot work here: a percentage in
   * `top`/`bottom` resolves against the CONTAINING BLOCK's height, which is
   * now the whole frame (photograph + copy), not the photograph. There is no
   * expression for "the bottom of my sibling". Grid placement has one, and
   * it needs no magic number and no transform.
   */
  .hero-field__frame{
    display:grid;
    grid-template-columns:minmax(0,1fr);
    grid-template-rows:auto auto;
    min-height:0;
    overflow:hidden;
  }
  .hero-field__media{
    grid-area:1/1;
    position:relative;inset:auto;
    display:block;
    width:100%;max-height:460px;
    aspect-ratio:1/1;
    overflow:hidden;
  }
  /* Stretches to the photograph's cell, contributes no height of its own. */
  .hero-field__scrim{
    grid-area:1/1;
    position:relative;inset:auto;
  }
  /* Flush to the bottom-right corner of the PHOTOGRAPH, per §8.4. */
  .hero-field__frame > .plate{
    grid-area:1/1;
    position:relative;inset:auto;
    align-self:end;justify-self:end;
  }
  .hero-field__frame > .container{grid-area:2/1}
  .hero-field__copy{
    max-width:none;
    padding:var(--space-7) 0 var(--space-6);
  }
  .hero-field__copy .hero__ctas .btn{width:100%}
}


/* --------------------------------------------------------------------------
   3f. THE THREE TRUST LAYERS INSIDE .hero-field__copy            v1.9 · §8.3
   --------------------------------------------------------------------------

   template-parts/hero-field.php now renders, in this order: eyebrow, H1, lead,
   COVERAGE ROW, .hero__ctas + .micro, OPERATOR CALLOUT, GUARANTEE ROW. The
   three new rows are all driven by Customizer values and all render nothing
   when their field is cleared, so every rule below is reachable only when the
   template has actually written the element — there is no empty-chip state to
   style and no placeholder to suppress.

   NOTHING HERE IS A NEW LAYER. All three are children of .hero-field__copy,
   which is layer 2; neither :has() rule above is affected, because nothing
   added is a sibling of .hero-field__media / .hero-field__scrim / .arrow-arch.

   THE PAINTS ARE THE MEASURED ONES. Against --navy #0E1B2B:
     --on-dark-body #A8B4C2   8.24:1   coverage row, operator line
     --on-dark      #F5F7F9  16.16:1   guarantee statements
     --line-dark    #22334A   1.36:1   SEPARATOR RULES ONLY — never text
   --line-dark is the hairline this component already draws with: the
   .hero-field .trajectory rules above set its top and bottom edges in exactly
   this colour. No new pairing, no new decision.
   -------------------------------------------------------------------------- */

/*
 * The coverage row is built exactly like the white strip's .mp chips: a flex
 * row of 12px letterspaced caps with nothing drawn around them and nothing
 * drawn between them. There is deliberately no ::before separator — and it is
 * not a font problem, U+00B7 IS inside the Manrope subset unlike the arrow. It
 * is that a generated middot is content some screen readers announce, six
 * times over on this row. Gap does the separating.
 */
.hero-field__markets{
  display:flex;flex-wrap:wrap;align-items:center;
  gap:var(--space-3) var(--space-5);
  list-style:none;padding:0;
}
/* Specificity 0,2,0 — matched to the §8.3 rhythm block above, which sizes every
   child of the copy column at this weight (.hero-field__copy .lead-xl). A bare
   .hero-field__markets at (0,1,0) would still beat the UA <ul> margin, but it
   would sit outside the one block that owns this column's vertical rhythm and
   the next person to tune the fold would not find it. */
.hero-field__copy .hero-field__markets{margin:0 0 32px}
.hero-field__market{
  font-size:12px;font-weight:700;letter-spacing:.1em;text-transform:uppercase;
  color:var(--on-dark-body);   /* 8.24:1 on --navy */
  white-space:nowrap;
}

/*
 * OPERATOR ACCESS — a hairline and a paragraph, NOT a bordered box. .callout
 * exists and would have been the quick answer, but it paints --surface-dark
 * inside a border and §3.4's rule is rules between things rather than boxes
 * around them. The rule above this line is what separates the offer (button +
 * micro) from the relationship the offer buys.
 *
 * Specificity 0,2,0 throughout, and it has to be: p{margin:0 0 var(--space-4)}
 * is (0,0,1), p:last-child{margin-bottom:0} is (0,1,1) and .section--navy p
 * {color:var(--on-dark-body)} is (0,1,1) — a bare class here would tie with the
 * last two and win only on source order, which is not a decision, it is an
 * accident waiting for the file to be reordered.
 */
.hero-field .hero-field__operator{
  max-width:52ch;
  margin:var(--space-5) 0 0;
  padding-top:var(--space-4);
  border-top:1px solid var(--line-dark);
  font-size:15px;line-height:1.6;
  color:var(--on-dark-body);   /* 8.24:1 on --navy */
}

/*
 * THE GUARANTEES — same row construction as the coverage row, one register up:
 * sentence case at 13px in --on-dark rather than 12px letterspaced caps in
 * --on-dark-body. They are statements, not labels, and the register is what
 * tells the two rows apart at a glance — which is why neither needs a heading.
 */
.hero-field__guarantees{
  display:flex;flex-wrap:wrap;
  gap:var(--space-2) var(--space-6);
  list-style:none;
}
.hero-field .hero-field__guarantees{
  margin:var(--space-5) 0 0;
  padding:var(--space-4) 0 0;
  border-top:1px solid var(--line-dark);
}
.hero-field__guarantee{
  font-size:13px;font-weight:700;line-height:1.5;
  color:var(--on-dark);   /* 16.16:1 on --navy */
}

/*
 * Specificity 0,3,0 — out-ranks the (0,2,0) rule directly above it on weight
 * rather than on source order, because both live in the same block and blocks
 * get reordered.
 *
 * The two rows are independent — either can render without the other — so each
 * draws its own opening rule. When BOTH render, the operator callout has
 * already drawn one, and a second hairline 16px below it reads as a mistake
 * rather than as structure. The gap alone separates them in that case.
 */
.hero-field .hero-field__operator + .hero-field__guarantees{
  margin-top:var(--space-4);
  padding-top:0;
  border-top:0;
}

/*
 * 767px is this component's own breakpoint (§8.4's layout inversion), not the
 * file's 719px, so the fold's rhythm turns on the same pixel as the fold's
 * layout: the copy column goes full width there and both rows wrap onto two or
 * three lines, which needs the vertical steps to come in rather than the
 * horizontal ones to grow.
 *
 * A media query adds no specificity and these three rules are the same weight
 * as the ones they override, so they win on source order alone — this block
 * must stay AFTER them.
 */
@media (max-width:767px){
  .hero-field__copy .hero-field__markets{margin-bottom:var(--space-5)}
  .hero-field__markets{gap:var(--space-2) var(--space-4)}
  .hero-field__guarantees{gap:var(--space-2) var(--space-5)}
}


/* ==========================================================================
   4. THE PLATE — the only caption component on the site        §2 · §8.3 L3
   ==========================================================================

   A hard-edged Soft White rectangle, 0px radius, FLUSH TO THE BOTTOM-RIGHT
   CORNER of a photograph. Never floating, never inset, never shadowed. It
   replaces every badge, chip and floating card on the site.

   Markup:

       <figcaption class="plate">
         <span class="plate__index">01 / London</span>
         <span class="plate__name">The Ecom Enable team</span>
         <span class="plate__date">Photographed September 2026</span>
       </figcaption>

   Bottom-RIGHT, not bottom-left, for two reasons: the type column already
   occupies the bottom-left of the hero, and a museum label belongs beside
   its subject. That creates one photography constraint, carried into §9.3:
   NOTHING IMPORTANT IN THE BOTTOM-RIGHT 320 × 130px OF THE DELIVERED FRAME.

   The index is SEQUENTIAL ACROSS THE WHOLE SITE — 01, 02, 03 … — so the site
   reads as one catalogue rather than a set of pages. That is a content
   contract, not a CSS one; nothing here can enforce it.

   The date is load-bearing: it proves the photograph is of THIS business on a
   real day. Do not let it be dropped as "clutter".

   Its parent must be `position:relative`. .hero-field__frame,
   .team-member__media and .founder-band__portrait all are. */
.plate{
  position:absolute;right:0;bottom:0;z-index:3;
  width:300px;max-width:100%;
  margin:0;padding:20px;
  background:var(--soft-white);
  color:var(--navy);
  border:0;border-radius:0;box-shadow:none;
  /*
   * CENTRED — §4, "Nothing on this site is centred except the plate's
   * internal fields". That exception is written specifically for this
   * component, so it is taken at face value.
   *
   * FLAGGED: §2's ASCII drawing of the plate shows the three fields flush
   * left. §4's rule is the explicit one and a carve-out nobody writes by
   * accident, so it wins — but the two passages do disagree, and this single
   * declaration is the whole of the difference if the call goes the other
   * way in review.
   */
  text-align:center;
}

/* All three at (0,2,0). Required, not belt-and-braces: the plate sits on a
   navy field, so if a template emits any field as a <p> then
   `.section--navy p{color:var(--on-dark-body)}` (0,1,1) paints Soft White
   type on a Soft White ground — invisible — and `p:last-child` (0,1,1)
   collapses the gaps between the fields. */
.plate .plate__index{
  display:block;margin:0 0 var(--space-2);
  font-size:11px;font-weight:600;line-height:1.4;
  letter-spacing:.14em;text-transform:uppercase;
  color:var(--navy);
  font-variant-numeric:tabular-nums;font-feature-settings:'tnum' 1;
}
/* §2 specifies 11px / +.14em for the index; §4's scale table files it with
   the 12px / +.12em label family. §2 is the component-level spec and is what
   is built. Noted because the two documents disagree by one pixel. */

.plate .plate__name{
  display:block;margin:0 0 var(--space-1);
  font-size:20px;font-weight:700;line-height:1.25;letter-spacing:-.01em;
  color:var(--navy);
}

.plate .plate__date{
  display:block;margin:0;
  font-size:13px;font-weight:400;line-height:1.5;letter-spacing:0;
  color:var(--muted);
  font-variant-numeric:tabular-nums;font-feature-settings:'tnum' 1;
}

/* The plate is Soft White on every ground, including inside a navy band —
   it is a physical label sitting on the picture, not a themed panel. These
   restate the light values at (0,3,0) so the band rules cannot reach in. */
.section--navy .plate .plate__index,
.section--navy .plate .plate__name{color:var(--navy)}
.section--navy .plate .plate__date{color:var(--muted)}

@media (max-width:719px){
  .plate{width:260px;padding:16px}
  .plate .plate__name{font-size:19px}     /* §4, mobile column */
}


/* ==========================================================================
   5. FULL-BLEED PHOTOGRAPHY — REMOVED (v1.8.2)                     §9.1
   ==========================================================================

   `.media-full`, `.media-full--2x1`, `.media-full--16x9`, `.media-full--1x1`,
   `.media-full--4x5`, `.media-full--graded` and `.media-full .plate` lived
   here and are gone. A literal grep for `media-full` across all 60 PHP files
   returns zero: nothing in the theme has ever emitted the figure, so this was
   a component with no caller, carrying its own print rules and its own
   reduced-motion entry.

   §9.1 IS NOT WITHDRAWN, only its unused implementation. The rule it states —
   photographs are cut into the field, full-bleed, 0px radius, no border, no
   shadow, never inset in a card — is still enforced where photographs
   actually render: `.hero-field__frame` (§8.3), `.team-member__media` and
   `.founder-band__portrait`, all of which ground to `--navy` for the same
   reason, so what shows while the file decodes is the field and not a grey
   box.

   The one thing that died with the block is the NAVY BLACK POINT dissolve
   (`.media-full--graded::after`), a 22% linear-gradient into `--navy` for
   frames that have not been through the LUT yet. Re-author it against the
   real element on the day a template needs a full-bleed figure — the grade
   itself always belonged in the file, in post, not in CSS.

   The section number is kept so 4 → 6 does not read as a lost section.
   ========================================================================== */


/* ==========================================================================
   6. .ee-plate — the no-image fallback set                        §9.4
   ==========================================================================

   THE RULE THIS ENFORCES:

     A missing image never produces a grey box, a broken-image icon, a stock
     photo, or an empty gap. It produces either a designed brand element or
     nothing at all.

   Three behaviours, and only the third needs CSS:
     (a) THE FIELD CARRIES IT — hero and team band. The navy ground renders
         with the architectural arrow. Nothing is missing because nothing was
         ever required. No class needed; see .hero-field above.
     (b) HIDE THE BLOCK — proof screenshot, client logo wall. The section does
         not render at all. A fabricated chart is infinitely worse than no
         chart. Handled in the template; nothing here.
     (c) RENDER A BRAND PLATE — card grids, where the rhythm has to hold.
         That is this block.

   Zero bytes, never 404s, always sharp, and sized by the SAME aspect-ratio
   box the real photograph will occupy — so there is never a layout shift
   when the picture arrives later. */
.ee-plate{
  position:relative;display:block;
  width:100%;
  background:var(--navy);
  border:1px solid var(--line-dark);
  overflow:hidden;           /* 0px radius — no --radius-lg here, ever */
  /*
   * ADDED TO §9.4's SNIPPET, AND IT IS A FIX RATHER THAN A PREFERENCE.
   * .ee-plate__initials below sizes on `14cqi`. A `cq*` unit with no query
   * container above it does not fall back to the parent — it resolves
   * against the SMALL VIEWPORT, so a 200px tile in a three-up grid would set
   * its initials from the width of the window and render them enormous.
   * `container-type:inline-size` makes this element the container the unit
   * was written for. Without this line the fallback is broken at every size
   * except full-bleed.
   */
  container-type:inline-size;
}
.ee-plate--16x9{aspect-ratio:16/9}
.ee-plate--1x1{aspect-ratio:1/1}
.ee-plate--4x5{aspect-ratio:4/5}
/* 2x1 was in ecomenable_plate()'s $ratios map with no class to match, which
   is why the helper was emitting `style="aspect-ratio:…"` inline on every
   plate it renders. The class exists now, so the inline attribute is gone. */
.ee-plate--2x1{aspect-ratio:2/1}

/* The brand arrow at 6% lime, cropped by the corner.

   WHAT THIS ELEMENT IS. ecomenable_get_image_plate() in inc/images.php calls
   ecomenable_get_arrow( 'arch', 'arch', 'ee-plate__arrow' ), so it is an
   <svg class="ee-arrow ee-arrow--arch ee-plate__arrow"> holding a single
   <use href="#ee-arrow-arch">. It is NOT the sprite. The sprite is the one
   hidden host ecomenable_arrow_sprite() prints just after <body>, and that
   element wears .ee-arrow-sprite (see the arrow-cuts block above).

   `color`, NOT `fill`, AND THE DIFFERENCE IS VISIBLE. Every <path> inside the
   <symbol>s in ecomenable_arrow_sprite() carries fill="currentColor" as a
   presentation attribute on the path itself. Author CSS cannot select into a
   <use> shadow tree, and a presentation attribute on an element beats an
   inherited value, so a `fill` declared out here never reaches the path at
   all: the path goes on resolving currentColor against the `color` it
   inherits. .ee-plate sets a navy background and no colour, so the earlier
   `fill:var(--lime)` was inert and the mark rendered in --ink at 6% opacity
   on navy, which is invisible. `color` is the property currentColor is
   waiting for.

   `opacity` is untouched by any of that: it applies to this element, and so
   to the whole cloned group. */
.ee-plate .ee-plate__arrow{
  position:absolute;right:-8%;bottom:-14%;
  width:62%;height:auto;
  color:var(--lime);opacity:.06;
  pointer-events:none;
}

/* (0,2,0) — it is often a <span> inside an <a>, so `a{color:var(--ink)}` at
   (0,0,1) reaches it, and navy-on-navy is invisible. */
.ee-plate .ee-plate__label{
  position:absolute;left:var(--space-5);bottom:var(--space-5);z-index:1;
  margin:0;
  font:600 .75rem/1.4 var(--font-sans);
  letter-spacing:.12em;text-transform:uppercase;
  color:var(--lime);
}

/* The initials tile. A grid of these is a perfectly respectable look in its
   own right, which is the whole argument for choosing it over a grey box. */
.ee-plate .ee-plate__initials{
  position:absolute;inset:0;
  display:grid;place-items:center;
  margin:0;
  font:800 clamp(2rem,14cqi,4rem)/1 var(--font-sans);
  letter-spacing:-.02em;
  color:var(--soft-white);
  font-variant-numeric:tabular-nums;font-feature-settings:'tnum' 1;
}

/* The case-study variant: THE NUMBER BECOMES THE IMAGE. For a results-led
   agency that is arguably better than a product shot. Same box, same
   position as the initials, lime and tabular. */
.ee-plate .ee-plate__metric{
  position:absolute;inset:0;
  display:grid;place-items:center;
  margin:0;padding:var(--space-6);
  font:800 clamp(1.75rem,12cqi,3.5rem)/1 var(--font-sans);
  letter-spacing:-.03em;text-align:center;
  color:var(--lime);
  font-variant-numeric:tabular-nums;font-feature-settings:'tnum' 1;
}
/* The metric now renders through ecomenable_get_metric_html(), so this is a
   three-child lockup (value, arrow, value) rather than one text node. The grid
   above centres a single child; column flow keeps the three on one baseline
   instead of stacking them. No template calls the HTML plate today -- this is
   here so it is correct on the day one does. */
.ee-plate .ee-plate__metric{grid-auto-flow:column;gap:.12em;align-items:baseline}
.ee-plate .ee-plate__metric .metric__val{white-space:nowrap}
.ee-plate .ee-plate__metric .arrow{font-size:.5em}

/* NO PER-BAND BORDER VARIANT, DELIBERATELY — and the two rules that used to
   sit here (`.section .ee-plate` and `.section--navy .ee-plate`) are removed
   because they were redundant: both restated the base --line-dark under a
   comment claiming the white band needed --line instead.

   The comment was wrong, which is why the rules looked necessary. Every
   other object in this file needs a per-band edge because its FILL changes
   with the band. .ee-plate's fill never changes: it is always --navy, on
   every ground, because it is standing in for a photograph. A --line-dark
   hairline on a navy tile is correct on white and on navy alike, so the base
   rule is the whole story. */


/* ==========================================================================
   7. TEAM GRID AND FOUNDER BAND                       image-spec §2 · §3
   ==========================================================================

   STALE NOTE, CORRECTED. This block used to read "page-about.php has ZERO navy
   sections today and must have at least three: the hero, the founder band and
   the team grid band." Neither half is true any more. /about opens on the navy
   hero ecomenable_page_hero() emits and carries three further
   `section--navy section--bleed` bands: #amazon-first, #values and the closing
   CTA. The founder band (#founder) and the team grid (#proof) are the WHITE
   rungs between them, which is what THE FIELD's alternation asks for and what
   the credentials note further down this section already assumes ("band 2 of
   the About page on white"). Read the grounds off page-about.php's <section>
   classes, not off this paragraph.

   The two components below are what those bands need; the grounds come from
   .section--navy and .section--bleed, which already exist.

   NO CIRCLES. `border-radius:50%` on a headshot is the single most
   template-looking gesture available and it is rejected in writing (§12).
   All photographic masks on this site are rectangles. */

/* --- The team grid ------------------------------------------------------- */
/*
 * Three across, square, per image-spec §3: square is the only ratio that
 * guarantees a level bottom edge across every card however tall the name and
 * role run underneath, and portrait ratios in a three-up grid build a wall of
 * tall rectangles that dominates the section.
 */
.team-grid{
  display:grid;grid-template-columns:repeat(3,1fr);
  gap:var(--space-6) var(--space-5);
  list-style:none;margin:0;padding:0;
}
.team-member{margin:0;min-width:0}

/* `position:relative` so a .plate or an .ee-plate can sit in it. Navy ground
   so what shows while the photograph decodes is the field, not a grey box —
   the same reason .hero-field__frame has one. */
.team-member__media{
  position:relative;display:block;
  width:100%;aspect-ratio:1/1;
  margin:0 0 var(--space-4);
  background:var(--navy);
  overflow:hidden;
  border:0;border-radius:0;
}
/* (0,1,1) — beats `img{height:auto}`.
   `object-position:50% 32%` holds the eyeline at the 35–40% mark image-spec
   asks the photographer for, so a slightly loose frame crops off the chest
   rather than the top of the head. */
.team-member__media img{
  width:100%;height:100%;
  object-fit:cover;object-position:50% 32%;
  display:block;border-radius:0;
}

/* (0,2,0) — the name is usually an <h3> or a <p>, so both the h1–h4 margin
   reset (0,0,1) and `.section--navy h3` (0,1,1) reach it. */
.team-member .team-member__name{
  margin:0 0 2px;
  font-size:18px;font-weight:700;line-height:1.35;letter-spacing:-.005em;
  color:var(--ink);
}
.team-member .team-member__role{
  margin:0;
  font-size:14px;font-weight:400;line-height:1.5;
  color:var(--muted);
}

.section--navy .team-member .team-member__name{color:var(--on-dark)}
.section--navy .team-member .team-member__role{color:var(--on-dark-body)}
.section--navy .team-member__media{background:var(--navy-deep)}

/*
 * §9.1 rule 3 says every photograph gets a plate. THE TEAM GRID IS THE ONE
 * DOCUMENTED EXCEPTION, and it is a deliberate reading rather than an
 * oversight: the name and role sitting directly beneath each square ARE that
 * photograph's caption, and nine 300px museum labels stacked into a three-up
 * grid would bury the faces they are labelling. The plate stays where it
 * earns its keep — the full-bleed frames: hero, team band, founder portrait,
 * case-study hero. Flagged so the next reader knows it was decided, not
 * missed.
 */

/* --- The founder band ---------------------------------------------------- */
/*
 * Portrait left at 4:5, story right. 4:5 is the standard editorial person
 * ratio — head, shoulders and enough torso to read posture, without the dead
 * space above the head a 1:1 leaves in a tall column — and it centre-crops
 * cleanly to 1:1 for the author-box avatar, so one file feeds both slots.
 *
 * For an agency founded in 2022, the founder IS the credibility. This is one
 * of only three proof blocks that can be filled today with zero risk.
 */
.founder-band{
  display:grid;
  grid-template-columns:minmax(0,.85fr) minmax(0,1.15fr);
  gap:var(--space-8);
  align-items:start;
}
.founder-band__portrait{
  position:relative;display:block;
  width:100%;aspect-ratio:4/5;
  margin:0;
  background:var(--navy);
  overflow:hidden;
  border:0;border-radius:0;
}
/* (0,1,1) — beats `img{height:auto}`. */
.founder-band__portrait img{
  width:100%;height:100%;
  object-fit:cover;object-position:50% 28%;
  display:block;border-radius:0;
}
.founder-band__body{min-width:0;max-width:62ch}

/*
 * FALLBACK (b) — no portrait, so the two-column grid collapses and the story
 * runs full width. page-about.php already does the right thing by omitting
 * the .grid--2 class when there is no media; this makes the component do it
 * on its own, so the behaviour cannot be lost in a future template edit.
 *
 * (0,2,0): :has() takes the specificity of its argument, so this out-ranks
 * the base .founder-band rule at (0,1,0) on weight, not on source order.
 */
.founder-band:not(:has(.founder-band__portrait)){grid-template-columns:minmax(0,1fr)}
.founder-band:not(:has(.founder-band__portrait)) .founder-band__body{max-width:62ch}


/* --- Credentials, the story link on navy, and the action row (v1.9) -------
   template-parts/founder.php. The band is band 2 of the About page on white
   AND band 9 of the homepage on navy, so every colour below is declared twice.
   ------------------------------------------------------------------------ */

/*
 * Three text credentials under the byline. They are NOT chips with borders
 * round them: the rule is rules BETWEEN things rather than boxes AROUND them,
 * so the row carries one hairline above it and the items are divided by the
 * same 3px square .post-meta uses. That separator is also why this is a flex
 * row rather than an inline list — the ::before needs flex:0 0 auto to survive
 * a wrap.
 *
 * NOTHING HERE IS LIME, AND NOTHING HERE IS A BADGE. research/live-site-content
 * confirms no certificate, partner mark or verification link exists for this
 * business, so the credentials are text and only text — a drawn seal beside an
 * unverifiable string is fabricated proof. And the band's eyebrow is its one
 * accent: three lime labels immediately under it would spend the page's single
 * lime keyword three more times.
 */
.founder-band__creds{
  display:flex;flex-wrap:wrap;align-items:center;
  gap:var(--space-2) var(--space-4);
  list-style:none;margin:var(--space-5) 0 0;padding:var(--space-4) 0 0;
  border-top:1px solid var(--line);
}
/* --muted #5A6A7E on --bg #FFFFFF = 5.53:1. Body text needs 4.5:1. */
.founder-band__cred{
  display:inline-flex;align-items:center;gap:var(--space-2);
  margin:0;
  font-size:13px;font-weight:600;line-height:1.5;
  letter-spacing:.06em;text-transform:uppercase;
  color:var(--muted);
}
/* Decorative divider, never announced — a square, because there are no circles
   anywhere on this site (§6). Specificity 0,2,1: two classes plus the
   pseudo-element, which counts in the element column. */
.founder-band__cred + .founder-band__cred::before{
  content:'';flex:0 0 auto;
  width:3px;height:3px;border-radius:0;
  background:var(--line-strong);
  margin-right:var(--space-2);
}

/* On navy. (0,2,0) beats the base (0,1,0) on weight, not on source order.
   --on-dark-body #A8B4C2 on --navy #0E1B2B = 8.24:1. The hairline and the
   square stay --line-dark: both are decorative dividers, not text and not the
   boundary of a control, which is the one job --line-dark on navy still has. */
.section--navy .founder-band__creds{border-top-color:var(--line-dark)}
.section--navy .founder-band__cred{color:var(--on-dark-body)}
/* (0,3,1) — has to out-rank the base separator rule at (0,2,1). */
.section--navy .founder-band__cred + .founder-band__cred::before{background:var(--line-dark)}

/*
 * THE STORY LINK ON NAVY — a hazard this band creates by moving grounds, closed
 * here rather than left for someone to find.
 *
 * The story renders inside .entry-content, and .entry-content a at (0,1,1)
 * paints links --blue. --blue was repointed to the navy accent ramp (#0E1B2B),
 * which is correct on white — 16.16:1 — and invisible the moment this band runs
 * on the homepage's navy: navy on navy is 1:1. Nothing above catches it,
 * because until v1.9 .entry-content never sat on navy outside the legal
 * templates, which carry their own override.
 *
 * (0,3,1), so it out-ranks .entry-content a at (0,1,1) on weight rather than on
 * where this block happens to sit. Scoped to the founder band on purpose:
 * every other .entry-content on the site is on white and needs no touching.
 * --on-dark 16.16:1; --lime 13.54:1 on hover.
 */
.section--navy .founder-band__body .entry-content a{color:var(--on-dark)}
.section--navy .founder-band__body .entry-content a:hover{color:var(--lime)}

/* The action row rides on .hero__ctas, which already supplies the flex
   context, the wrap, the gap and the .hero__ctas .btn{width:100%} rule below
   767px. This adds ONE declaration, on a property .hero__ctas does not set, so
   the two never contest and there is no specificity note to write. */
.founder-band__actions{margin-top:var(--space-6)}

@media (max-width:1023px){
  /* Two across, not one: at 1023px a single column of square headshots is a
     column of 700px photographs. This is why the grid is not .grid--3. */
  .team-grid{grid-template-columns:repeat(2,1fr)}
  .founder-band{grid-template-columns:minmax(0,1fr);gap:var(--space-7)}
  .founder-band__portrait{max-width:420px}
}
@media (max-width:719px){
  /* Still two across, for the same reason. */
  .team-grid{grid-template-columns:repeat(2,1fr);gap:var(--space-5) var(--space-4)}
  .team-member .team-member__name{font-size:17px}
  .team-member .team-member__role{font-size:13.5px}
}
/* ==========================================================================
   ==========================================================================
   v1.8.1 — MARKUP / STYLESHEET RECONCILIATION  (APPEND-ONLY SECTION)

   Five agents built THE FIELD in parallel on disjoint files. Every file was
   valid and every colour bug was fixed, but the agents invented DIFFERENT
   NAMES FOR THE SAME COMPONENTS, so the markup and this stylesheet did not
   meet. This section closes the gap from the CSS side; the PHP side was moved
   onto the vocabulary already written here — never the other way round —
   because this file is where the geometry, the specificity arithmetic and the
   per-band colour work already live.

   WHAT MOVED IN THE TEMPLATES (recorded here so the pair can be re-checked):
     section-trajectory.php  .trajectory__row  -> .trajectory__inner
                             .trajectory__cell -> .tr-cell
                             p.tr > (from,arrow,to)  -> four REAL SIBLINGS
                             .trajectory--on-navy -> .trajectory--navy
     hero-field.php          .hero-field__arch    -> .arrow-arch
                             .hero-field__actions -> .hero__ctas
                             .hero-field--photo/--field  -> deleted (:has())
     founder.php             .founder__*  -> .founder-band__*
     team-grid.php           .team-grid__* -> .team-member__*

   HOUSE RULES, UNCHANGED: no @keyframes, no `animation`, no `transform` in
   any :hover/:focus/:active rule, transitions limited to color / background /
   border-color / outline-color at var(--dur-fast) (0s), tokens only, hard 0px
   radius. Nothing below contains the string `transform`, and nothing below
   introduces a transition. Every deliberately raised specificity is stated.
   ==========================================================================
   ========================================================================== */

/* ==========================================================================
   1. THE INTERIOR HERO FRAME — .page-hero on a field
   ==========================================================================

   inc/template-tags.php has documented this class since ecomenable_page_hero()
   was rebuilt on the field: "`page-hero` … is the hook that tells the
   stylesheet to use the shorter interior frame rather than the homepage
   hero's clamp(520px, 72vh, 720px)". NO SUCH RULE EXISTED. Sixteen templates
   call ecomenable_page_hero(), so every interior page — about, contact, faq,
   pricing, services, reviews, free-audit, thank-you, legal, both case-study
   taxonomies, the case-study archive, the marketplace and service templates
   and page.php — opened on a 720px homepage-sized navy field with one h1 and
   a lead in it. The homepage hero stopped being the biggest thing on the site.

   38vh / 280–420px is the interior notch: still unmistakably a field, still
   full-bleed navy, but it cannot be mistaken for the front page.
   ========================================================================== */

/*
 * (0,2,0) — RAISED DELIBERATELY, and both classes are needed.
 * `.hero-field__frame` is (0,1,0). So is `.hero-field__frame{min-height:560px}`
 * in the 1023px block above, which sits LATER in the file — a bare
 * `.page-hero` variant at (0,1,0) would tie with the base rule (source order)
 * and LOSE outright to the tablet rule. Two classes clears both on weight, in
 * every media query, without !important.
 *
 * ecomenable_page_hero() puts BOTH `hero-field--page` and `page-hero` on the
 * section. Either alone is enough; both are listed so an interior template
 * that hand-writes one of them still gets the interior frame.
 */
.hero-field--page .hero-field__frame,
.page-hero .hero-field__frame{min-height:clamp(280px,38vh,420px)}

/*
 * `.page-hero{padding:var(--section) 0 var(--space-6)}` up in the "Inner pages
 * / blog" block is STILL LIVE and must stay: eight templates use .page-hero as
 * a plain white section with no field under it (archive, author, category,
 * home, index, search, single, tag). On a field it must not apply — the frame
 * supplies its own rhythm — and it was already losing to `.hero-field
 * {padding:0}`, same (0,1,0), later in source. That is a source-order
 * accident, not a decision. (0,2,0) makes it a decision.
 */
.hero-field.page-hero{padding:0}

@media (max-width:767px){
  /* Mirrors `.hero-field__frame{min-height:0}` in the 767px block above, which
     my (0,2,0) rule would otherwise out-rank and re-impose 280px on. Down here
     the frame is a two-row grid and the copy sets the height, exactly as it
     does on the homepage. */
  .hero-field--page .hero-field__frame,
  .page-hero .hero-field__frame{min-height:0}
}

/* ==========================================================================
   2. .why-item__num — the numbering treatment that was never written
   ==========================================================================

   front-page.php emits `<span class="why-item__num" aria-hidden="true">01</span>`
   once per reason — 01 to 06 as of this writing, and the count is deliberately
   not restated below, because the reason list is content and grows — as the
   first child of `.why-item`, which is `grid-template-columns:26px 1fr`. The
   stylesheet had nothing for it, so every one of those unstyled 17px numbers
   sat in a 26px column that was cut for a 12.5px label.

   Matched to `.step__num` / `.card__num` / `.kicker__num`: 12.5px, weight 800,
   tabular figures, the same +.06em tracking as .kicker__num, and
   `line-height:1.5` so it sits on the same optical line as `.why-item .arrow`
   did and as the 18.5px h3 beside it.
   ========================================================================== */

/* (0,2,0) — scoped to its block per the house rule at the head of v1.5, so it
   cannot be reached by a future `.section--navy span` or an `a` rule. */
.why-item .why-item__num{
  font-size:12.5px;font-weight:800;line-height:1.5;
  color:var(--blue);letter-spacing:.06em;
  font-variant-numeric:tabular-nums;font-feature-settings:'tnum' 1;
}
/*
 * (0,3,0). NOT OPTIONAL: --blue was repointed to #0E1B2B in v1.7, which is
 * --navy itself, so on the navy WHY band these four numbers were 1.0:1 —
 * literally invisible. Same shape as the `.section--navy .step__num` fix in
 * v1.6, and the same value. #A8B4C2 on #0E1B2B = 8.24:1.
 */
.section--navy .why-item .why-item__num{color:var(--on-dark-body)}

/* ==========================================================================
   3. THE TEAM GRID — the column-count modifiers
   ==========================================================================

   template-parts/team-grid.php documents a `columns` arg of 2, 3 or 4 and
   used to express it by adding `grid grid--{n}` beside `.team-grid`. Two grid
   declarations on one element at the identical (0,1,0), resolved on source
   order — the fragile pattern this codebase has been bitten by three times.

   Three across stays the base rule and carries no modifier, for the same
   reason .trajectory has no cell-count class. */
.team-grid--2{grid-template-columns:repeat(2,1fr)}
.team-grid--4{grid-template-columns:repeat(4,1fr)}

/* The grid follows a section head, and `.team-grid{margin:0}` is a list reset
   that leaves only the h2's own 16px under it — every hand-built block on the
   About page adds var(--space-6) with an inline style, which a partial cannot.
   (0,1,1) — element+class beats `.team-grid` at (0,1,0), so the reset still
   holds everywhere the grid is NOT under a head. */
h2 + .team-grid,
h3 + .team-grid,
.lead-xl + .team-grid{margin-top:var(--space-6)}
@media (max-width:1023px){
  /* Both collapse to the two-up the base grid already uses here — a single
     column of square headshots is a column of 700px photographs. */
  .team-grid--2,
  .team-grid--4{grid-template-columns:repeat(2,1fr)}
}

/*
 * THE LINKED NAME. team-grid.php wraps the name in an <a> when the member's
 * profile page has content of its own, and `a{color:var(--ink)}` at (0,0,1)
 * targets that anchor DIRECTLY — inheritance from
 * `.team-member .team-member__name` never reaches it. On the navy team band
 * that is #0E1B2B on #0E1B2B, 1.0:1: every linked name invisible, every
 * unlinked name fine, which is the worst way for a bug like this to present.
 *
 * `color:inherit` at (0,3,1) tracks the heading in every band — light, tint
 * and navy — so no per-band anchor override is needed. Same device as
 * `.post-card .post-card__cat a`.
 */
.team-member .team-member__name a{color:inherit;text-decoration:none}
.team-member .team-member__name a:hover{color:inherit;text-decoration:underline}
/* (0,4,1) — the one place the linked name is allowed to differ from the
   unlinked one, because on navy an underline alone is a weak affordance. */
.section--navy .team-member .team-member__name a:hover{color:var(--lime)}

/* ==========================================================================
   4. THE FOUNDER BYLINE
   ==========================================================================

   founder.php sets the name and role as `.post-meta` / `.post-meta__item` —
   the existing component, already banded for navy — rather than the
   `.founder__byline*` names it used to invent, which had no rules at all.
   The only thing missing is the gap: `.post-meta{margin:0 0 var(--space-6)}`
   has no top margin, and the story above it ends on a `p:last-child` whose
   bottom margin is zeroed, so the byline butted the last line of the story.

   (0,2,0) — beats `.post-meta` at (0,1,0) on weight. */
.founder-band__body .post-meta{margin:var(--space-5) 0 0}

/* ==========================================================================
   5. .ee-plate--corner-N — the corner the fallback arrow is cropped by
   ==========================================================================

   ecomenable_get_image_plate() in inc/images.php has always emitted
   `ee-plate--corner-{0..3}`, chosen from the post ID so a grid of fallback
   tiles varies instead of repeating one drawing nine times. Nothing defined
   the four classes, so every tile cropped its arrow at the bottom-right and
   the `seed` argument did nothing.

   (0,3,0) — RAISED DELIBERATELY. `.ee-plate--corner-1 .ee-plate__arrow` would
   be (0,2,0), an exact tie with the base `.ee-plate .ee-plate__arrow`, decided
   by source order alone. The doubled class settles it on weight.

   Corner 0 is the base rule and is written out only so the set reads as a set;
   delete these four rules and the tiles fall back to it with nothing broken.
   ========================================================================== */
.ee-plate.ee-plate--corner-0 .ee-plate__arrow{right:-8%;bottom:-14%;left:auto;top:auto}
.ee-plate.ee-plate--corner-1 .ee-plate__arrow{left:-8%;bottom:-14%;right:auto;top:auto}
.ee-plate.ee-plate--corner-2 .ee-plate__arrow{right:-8%;top:-14%;left:auto;bottom:auto}
.ee-plate.ee-plate--corner-3 .ee-plate__arrow{left:-8%;top:-14%;right:auto;bottom:auto}

/* ==========================================================================
   6. .cta-band__action — the second column of the final CTA
   ========================================================================== */

/* front-page.php has always emitted this wrapper; it is the `auto` column of
   `.cta-band{grid-template-columns:1fr auto}`. With no rule the button and the
   micro line under it were two block boxes with the paragraph's default
   spacing between them and no alignment of their own.
   (0,2,0) — scoped to the band so it cannot leak. */
.cta-band .cta-band__action{
  display:flex;flex-direction:column;align-items:flex-start;
  gap:var(--space-3);
}
/* (0,3,0) — `.section--navy .micro` is (0,2,0) and sets colour only; this
   claims the margin `p{margin:0 0 var(--space-4)}` would otherwise add on top
   of the flex gap. */
.cta-band .cta-band__action .micro{margin:0}
@media (max-width:719px){
  .cta-band .cta-band__action{align-items:stretch}
  .cta-band .cta-band__action .btn{width:100%}
}

/* ==========================================================================
   7. NAVY COVERAGE — the last components that could land on a dark band
   ==========================================================================

   THE SHAPE OF THE BUG, ONCE MORE: --blue was repointed to #0E1B2B in v1.7,
   which IS --navy. Every `color:var(--blue)` and `color:var(--ink)` left
   without a `.section--navy` counterpart is therefore 1.0:1 on a navy band —
   not "low contrast", INVISIBLE — and --body (#2B3A4D) is 1.5:1, which is the
   same thing with extra steps. v1.6 swept .step / .why-item / .faq /
   .section__lead / .callout; this is the remainder.

   Each block below states the ratio it replaces and the ratio it lands on.
   ========================================================================== */

/* --- .entry-content on navy --------------------------------------------
   Newly reachable: template-parts/founder.php renders the founder story in
   `.entry-content`, and §7 puts the founder band on navy. Links were
   `var(--blue)` = 1.0:1, hover `var(--blue-dark)` = 2.04:1, blockquote and
   table headings `var(--ink)` = 1.0:1, and the row rule was --line (#DFE8F2),
   a bright white hairline across a navy band.
   All (0,2,1), which clears `.entry-content a` at (0,1,1). */
.section--navy .entry-content a{color:var(--on-dark)}                    /* 16.16:1 */
.section--navy .entry-content a:hover{color:var(--lime)}                 /* 13.54:1 */
.section--navy .entry-content blockquote{color:var(--on-dark)}           /* 16.16:1 */
.section--navy .entry-content th{color:var(--on-dark)}                   /* 16.16:1 */
.section--navy .entry-content th,
.section--navy .entry-content td{border-bottom-color:var(--line-dark)}
/* The blockquote's left rule is --line-strong now, not --lime (see the base
   rule): #C8D7E7 on #0E1B2B = 11.5:1, so nothing to override here either. */

/* --- The marketplace strip on navy --------------------------------------
   front-page.php ships this band on white, where it is correct. It is one
   Customizer-free template edit away from navy, and there it was invisible:
   `.mp` is `var(--blue)` (1.0:1), `.mp--primary` is `var(--ink)` (1.0:1) and
   the label is `var(--muted)` (3.14:1, which fails AA at 12px). The two
   hairlines were --line on navy — a white bar, not a hairline. */
.section--navy .mp{color:var(--on-dark-body)}                            /* 8.24:1  */
.section--navy .mp--primary{color:var(--on-dark)}                        /* 16.16:1 */
/* (0,3,0) — matches the base rule's own scoping, which is at (0,2,0) to beat
   `p:last-child`. */
.section--navy .marketplaces .marketplaces__label{color:var(--on-dark-body)}
.section--navy .mp-row{border-top-color:var(--line-dark);border-bottom-color:var(--line-dark)}
/* The label needs its own or it lands at --muted on navy = 1.36:1 — the exact
   unreadable pairing the line tokens produce on a dark band. On navy it shares
   its colour with the secondary channel names by design: the dark band has
   only two sanctioned text tokens, so the hierarchy there is carried entirely
   by the 3px size drop, the lighter weight and the wider tracking.
   (0,2,0) beats `.mp__label` at (0,1,0). */
.section--navy .mp__label{color:var(--on-dark-body)}                     /* 8.24:1  */

/* --- Form odds and ends on navy -----------------------------------------
   `input[type=number]` was the one control missing from the navy form-shell
   list, so a number field kept a white ground inside a navy panel. And a
   `.form-note` link outside a `.form-shell` — the `.form-row` variant — had
   no navy rule, leaving it at 1.0:1. */
.section--navy .form-shell input[type=number]{
  background:var(--navy-deep);border-color:var(--line-dark);color:var(--on-dark);
}
.section--navy .form-row .form-note a{color:var(--on-dark)}              /* 16.16:1 */
.section--navy .form-row .form-note a:hover{color:var(--lime)}           /* 13.54:1 */

/* --- v1.8.2 addendum: the three that were still open ---------------------
   A full re-audit of the 19 components named for the tint → navy conversion
   (.pricing-card, .review-card, .contact-detail, .form-shell, .service-row,
   .legal-content, .toc, .post-card, .cs-card, .author-box, .empty-state,
   .faq details/summary/.faq__body, .callout, .step/.steps, .filter-chip,
   .pagination, .archive-head, .breadcrumbs) found sixteen already complete:
   -- that list is the state at v1.8.2; .archive-head has been retired since,
   and its rules are gone --
   every one grounds to --surface-dark, hairlines to --line-dark and text to
   --on-dark / --on-dark-body, and every combination is in the palette table
   at the top of this file. Three were not, and each is fixed AT ITS OWN
   COMPONENT BLOCK rather than here, so the variant sits beside the rule it
   corrects:

     .section--navy .post-card:focus-within                --on-dark 14.58:1
     .section--navy .cs-card:focus-within                  --on-dark 14.58:1
     .section--navy .legal-content .legal-toc a            --on-dark 14.58:1
     .section--navy .entry-content .legal-toc a           (+ :hover, lime 12.22:1)

   All three were the SAME failure this section exists for — `var(--blue)` is
   #0E1B2B — and all three were additionally decided by SOURCE ORDER rather
   than weight, so each fix is written to out-rank its light-mode counterpart
   on specificity. Nothing else in the 19 is outstanding.
   ------------------------------------------------------------------------ */


/* ==========================================================================
   ==========================================================================
   v1.9 — THE LIVE-SITE MIGRATION  (APPEND-ONLY SECTION)

   Eleven agents rebuilt the offer, the six-market positioning, the operator
   story, the two forms and four calculators in parallel on disjoint files.
   Each wrote its rules to assets/css/parts/<name>.css rather than to this
   file, so that exactly one pair of eyes would see both sides of every
   class-name boundary before anything merged. That boundary is where this
   codebase has failed before — a partial emitted .trajectory__cell while this
   sheet defined .tr-cell, and the signature component of the whole design
   rendered as unstyled body text.

   THE BOUNDARY WAS CHECKED, IN BOTH DIRECTIONS. Every class emitted by the
   twenty-six PHP files written this run was extracted from the markup itself
   (not from the agents' own reports) and matched against a rule; every rule in
   every part file was matched back to something that emits it. One orphan
   survives and it is named in the notes below. Nothing was dead.

   WHERE THE RULES WENT. Six of the eight part files had a home in this sheet
   already and were spliced into it beside the component they extend, not
   appended here:
     hero-ladder      -> §3f, inside THE HERO FIELD
     marketplaces-cta -> the Marketplace row section, and the navy strip block
     services-index   -> the Services numbered-row section
     case-band        -> the Case study card section
     founder-about    -> §7, inside TEAM GRID AND FOUNDER BAND (credentials)
   What is left below is what genuinely had no home: the band-content rhythm
   hooks that replaced inline style="margin-*" attributes, the .record list,
   the audit offer, and the calculators. (The hand-rolled .ee-form was here
   too, and was removed as dead in v1.9.2 — see the tombstone at §4.)

   WHAT THE INTEGRATOR CHANGED, AND WHY (so the pair can be re-checked):

   1. .calc{margin-top:var(--space-7)} was declared identically in two part
      files (the /tools calculators and the pricing estimator both put
      class="calc" on their form). One copy survives, here.

   2. TAP TARGETS. Two controls shipped under the 44px floor and were corrected
      in place rather than by a later override, because an override on geometry
      is a second source of truth: the range inputs (a UA range box is ~16–20px
      tall, so the drag band was 16px across the full width) and the .ee-form
      radios and checkboxes. Only the range inputs remain — the .ee-form half
      was removed as dead in v1.9.2 (§4), and nothing on the front end emits a
      radio or a checkbox today.

   3. FOCUS ON RADIOS AND CHECKBOXES. `input:focus{outline:none}` at (0,1,1)
      beats the global `:focus-visible{outline:2px solid var(--ink)}` at
      (0,1,0), so it strips the ring off EVERY input. That is correct for a
      text field, which the same block re-indicates with a border colour and a
      3px shadow. A native radio can show neither — border-color does nothing
      to a UA-drawn control, and the 8% navy shadow measures 1.03:1 against the
      panel behind it. The two controls page-free-audit.php introduced had no
      focus indicator at all, and were given one at (0,3,1). Both that rule and
      the controls it covered are gone as of v1.9.2 (§4); the analysis is left
      here because it applies to any radio or checkbox added later.

   4. THREE CONTRAST FIGURES IN THE PART FILES WERE WRONG AND ARE CORRECTED
      HERE. --on-dark-body #A8B4C2 on --navy #0E1B2B is 8.24:1, not the 5.90:1
      the calculators part stated four times (5.90 is nobody's pairing; the
      7.44:1 in the forms part is the right number for the same ink on
      --surface-dark #13243A, and that one was correct). --ink on white is
      17.35:1, not 17.18:1. --ink on --bg-tint is 16.16:1, not 16.00:1 — and
      it could not have been anything else, because --ink IS --navy and
      --bg-tint IS --on-dark, so that pairing is the navy body ratio read
      backwards. --line on white is 1.24:1, not 1.16:1. Every one of them
      erred in the safe direction, and every one is the kind of number the
      next person quotes back, so they are fixed rather than left.

   5. .cs-band's scroll-margin-top was promoted out of the case-study band and
      onto `.section[id]` in the Layout section. The offset bug is not that
      band's; it is every id'd band's, and there was no global rule for it.

   ONE THING DELIBERATELY NOT CHANGED, AND IT IS A REAL DEFECT.
   `.section--navy .btn--secondary{border-color:var(--line-dark)}` in the
   Buttons section draws a control boundary at 1.36:1, under the 3:1 that WCAG
   1.4.11 requires of a UI component. It is pre-existing and site-wide, and the
   pricing estimator's "Update the estimate" button is a new usage of it, not a
   new instance of the bug. Repainting it --on-dark-body would take it to
   8.24:1 in one token, but it changes the look of every secondary button on
   every navy band and that is a design call, not an integration one. Flagged,
   not taken.

   HOUSE RULES, UNCHANGED: not one `transition`, `transform`, `animation` or
   `@keyframes` DECLARATION appears below — the only occurrences of any of
   those strings in this section are `text-transform:uppercase` and the prose
   you are reading, which is checkable with a grep rather than taken on trust.
   Tokens only, hard 0px radius, and no literal arrow character anywhere:
   U+2197 and U+2192 both appear zero times, because the one arrow this run
   draws comes from inc/arrow.php's SVG sprite. Every deliberately raised
   specificity is stated.
   ==========================================================================
   ========================================================================== */

/* ==========================================================================
   1. BAND-CONTENT RHYTHM — the inline style="margin-*" attributes, as classes
   ==========================================================================

   Seven inline margins came off <div>s and <ul>s inside bands this run: four
   in front-page.php and three in page-about.php. None was on a <section>, so
   none was the padding bug that put 0px above a band's content and 56px below
   in ten templates — but they are the same class of bug one level down, and as
   classes the rhythm is auditable in one place instead of seven.
   ========================================================================== */

/* (0,1,0), and that is enough: the only other rule setting a bottom margin on
   this element is the base `p{margin:0 0 var(--space-4)}` at (0,0,1), and
   .lead-xl deliberately carries no margin of its own. `p:last-child` never
   reaches it — the lead is followed by the rows it introduces, which is the
   whole reason this class exists. */
.home-lead{margin-bottom:var(--space-7)}

/* One step value for all three homepage row blocks, where the inline styles
   they replace used 48px on the why grid and 32px on the steps and the FAQ for
   no stated reason. The section head above them is identical in all three
   bands, so the step below it should be too. */
.home-rows{margin-top:var(--space-7)}

/* The figures sit further from the rows above them than the rows do from the
   head: they are a different kind of statement, and the extra step is what
   stops them reading as a seventh reason. */
.home-figures{margin-top:var(--space-8)}

/* The as-at date is not a footnote — it is the thing that makes the figures
   readable at all, so it sits tight under them rather than at the foot of the
   band. (The figures band itself renders nothing without one: see the stats
   gate. Ours fails silent, it never fails to zero.) */
.home-figures__note{margin-top:var(--space-4)}

/* A second titled block inside one band. page-about.php runs two inside band 2
   and two inside band 6, because an extra band either way would break the
   navy/white alternation and flip every band below it.

   Specificity 0,2,0 on the reset — a class plus a pseudo-class — which beats
   the base at (0,1,0). It matters when the block above it has rendered nothing
   (no team members, no verification rows): this then becomes the first thing
   in the band and must not push itself off the band's own padding. */
.section-block{margin-top:var(--space-7)}
.section-block:first-child{margin-top:0}

/* The gap between a band's heading/lead and the grid or step list beneath it.
   No specificity note, because there is no contest: .grid, .grid--2 and .steps
   set display, gap, columns and a counter-reset between them, and not one of
   them declares a margin. */
.band-body{margin-top:var(--space-6)}

/*
 * THE ONE COMPONENT .band-body CANNOT REACH ON ITS OWN.
 *
 * `.logo-wall{…margin:0…}` (Logo wall block) is a shorthand at (0,1,0), and so
 * is .band-body — a tie, settled by source order, which today happens to fall
 * this way only because the rhythm block sits later in the file than the logo
 * wall does. That is a silent dependency on where this section lives: move or
 * reorder it and the `<ul class="logo-wall band-body">` badge wall in
 * page-reviews.php snaps flush against its heading with nothing anywhere
 * reporting an error.
 *
 * (0,2,0) settles it on weight instead. One instance today, and the rule is
 * written for the class pair rather than for that page so a second use cannot
 * reintroduce the tie.
 *
 * Nothing else needs this: .review-grid declares no margin at all, so plain
 * .band-body reaches it uncontested (the `<div class="review-grid band-body">`
 * in page-reviews.php), as it does the uses in page-pricing.php and
 * page-about.php.
 */
.logo-wall.band-body{margin-top:var(--space-6)}

/*
 * The trailing action paragraph at the foot of a band — one button, no lead-in
 * (the "Read the full FAQ" link under page-pricing.php's FAQ list).
 *
 * (0,1,0) beats the base `p{margin:0 0 var(--space-4)}` at (0,0,1) on
 * margin-top, which is the declaration that matters. FOR THE RECORD, because
 * the shorthand looks like it is claiming more than it wins: its
 * margin-bottom:0 does NOT out-rank `p:last-child{margin-bottom:0}` at
 * (0,1,1) — but both declare 0, so there is no visible contest either way,
 * and the shorthand is kept because a one-sided margin here would be a lie
 * about what the rule controls.
 *
 * var(--space-5), matching `.calc-submit{margin:var(--space-5) 0 0}` in the
 * calculators section: the two are the same object — a lone control closing a
 * block — and they should not drift.
 */
.band-action{margin:var(--space-5) 0 0}


/* ==========================================================================
   2. .record — the dated hairline list
   ==========================================================================

   Two uses on the About page: the 2022–2026 journey keyed by year, and the
   "verifiable, not self-awarded" rows keyed by a word. ONE component rather
   than a .timeline and a .verify-list, because they are the same object — a
   fixed key column, a rule above every row, and no box anywhere.

   DELIBERATELY NOT .steps. .step__num carries `counter-increment` and prints
   its own decimal-leading-zero through ::before, so a year dropped into it
   renders after an invented sequence number.
   ========================================================================== */

.record{
  list-style:none;
  margin:var(--space-6) 0 0;padding:0;
}
/* 96px, not the 52px .step uses: four tabular digits at 14/800 need it, and
   "Ownership" needs more than four digits. */
.record__row{
  display:grid;grid-template-columns:96px minmax(0,1fr);
  gap:var(--space-5);
  margin:0;padding:var(--space-5) 0;
  border-top:1px solid var(--line);
}
.record__row:last-child{border-bottom:1px solid var(--line)}

/* --blue is repointed to the navy accent ramp, so this is 16.16:1 on white —
   the same treatment .step__num already gets. Tabular figures so 2022 and 2026
   occupy identical width and the column edge stays straight. */
.record__key{
  margin:0;
  font-size:14px;font-weight:800;line-height:1.6;letter-spacing:.02em;
  color:var(--blue);
  font-variant-numeric:tabular-nums;font-feature-settings:'tnum' 1;
}
.record__body{min-width:0}
.record__title{font-size:20px;margin:0 0 var(--space-2)}
.record__text{color:var(--body);font-size:16px;max-width:62ch;margin:0}   /* 11.57:1 */
.record__text + .record__text{margin-top:var(--space-3)}

/*
 * ON NAVY — three rules, and the restraint is the point.
 *
 *   .record__title is an <h3>, so `.section--navy h3{color:var(--on-dark)}` at
 *                  (0,2,0) already paints it 16.16:1.
 *   .record__text  is a <p>, so `.section--navy p{color:var(--on-dark-body)}`
 *                  at (0,1,1) already beats .record__text at (0,1,0) and
 *                  paints it 8.24:1.
 *
 * Restating either here would create a tie decided by source order for no
 * change in the rendered colour. What genuinely has to be said is the key
 * colour — --blue IS navy, so on a navy band it is invisible at 1:1 — and the
 * two hairlines, which stay in the line token because they carry nothing.
 */
.section--navy .record__key{color:var(--on-dark-body)}                   /* 8.24:1  */
.section--navy .record__row{border-top-color:var(--line-dark)}
.section--navy .record__row:last-child{border-bottom-color:var(--line-dark)}

@media (max-width:719px){
  /* The key stacks above its row rather than shrinking to a 96px gutter that
     eats half the phone's width. */
  .record__row{grid-template-columns:minmax(0,1fr);gap:var(--space-2)}
  .record__title{font-size:18px}
}


/* ==========================================================================
   3. THE AUDIT OFFER — page-free-audit.php, page-contact.php
   ==========================================================================

   Two rules govern everything in this block and the one after it:

     HAIRLINE ROWS, NOT CARDS. Nothing here draws a box. Every component
     divides with a 1px rule and grounds to the band it sits in, so a block can
     move from a white band to a navy one and only its colours change.

     NO MOTION. No transition, transform or animation is declared. --dur-fast
     is 0s today, which is exactly how three inert transitions survived two
     passes in this file unnoticed; the safeguard is not to write them.

   COLOUR — every pairing used, measured. NONE IS NEW: each is a token in the
   role it already holds elsewhere in this sheet. The one rule that matters is
   the one broken 34 times before — --line / --line-dark ARE NEVER TEXT.

     ON WHITE (--bg #FFFFFF)
       --ink        #0E1B2B   17.35:1   row terms, legends, option labels
       --body       #2B3A4D   11.57:1   row descriptions
       --muted      #5A6A7E    5.53:1   trust strip, "(required)"
     ON --bg-tint #F5F7F9 (the .form-shell ground on a white band)
       --ink        #0E1B2B   16.16:1   labels, legends
       --muted      #5A6A7E    5.15:1   "(required)"
     ON --navy #0E1B2B
       --on-dark      #F5F7F9  16.16:1  row terms, deliverable heading
       --on-dark-body #A8B4C2   8.24:1  row descriptions, trust strip
       --lime         #C6F432  13.54:1  accent-color on radios and checkboxes
     ON --surface-dark #13243A (the .form-shell ground on a navy band)
       --on-dark      #F5F7F9  14.58:1  labels, legends, option text
       --on-dark-body #A8B4C2   7.44:1  "(required)"

   FOCUS RINGS ARE NOT DECLARED WITH THE `outline` SHORTHAND ANYWHERE IN THIS
   BLOCK, except where the shorthand is restoring a ring the base rules removed
   (see §4). The umbrella `.section--navy :focus-visible{outline-color:
   var(--on-dark)}` at (0,2,0) must keep winning; a stray shorthand here would
   reset outline-color and re-impose --ink on the navy band, which is the
   invisible-ring bug the focus section documents at length.
   ========================================================================== */

/* --- The four audit checks, and the guarantees --------------------------- */

.audit-rows{
  margin:var(--space-6) 0 0;
  padding:0;
  list-style:none;
}
/* The 26px first column matches .why-item and .contact-detail exactly, so the
   arrow gutter lines up with every other arrow-led row in the theme rather
   than being a third measurement. */
.audit-rows__item{
  display:grid;grid-template-columns:26px 1fr;gap:var(--space-4);
  align-items:start;
  margin:0;padding:var(--space-5) 0;
  border-top:1px solid var(--line);
}
.audit-rows__item:last-child{border-bottom:1px solid var(--line)}
.audit-rows__item .arrow{font-size:19px;line-height:1.5;color:var(--blue)}
/* Block, so a term with no description under it still occupies its own line. */
.audit-rows__term{
  display:block;
  font-size:18.5px;font-weight:700;line-height:1.35;
  color:var(--ink);                                   /* 17.35:1 on white */
}
/* (0,1,0) beats nothing and needs to beat nothing — the base is
   `p{margin:0 0 var(--space-4)}` at (0,0,1), and `p:last-child{margin-bottom:0}`
   at (0,1,1) already zeroes the last one on a property this does not set.
   This only adds the gap under the term. */
.audit-rows__text{
  margin:var(--space-2) 0 0;
  color:var(--body);font-size:16px;                   /* 11.57:1 on white */
  max-width:62ch;
}

.section--navy .audit-rows__item{border-top-color:var(--line-dark)}
.section--navy .audit-rows__item:last-child{border-bottom-color:var(--line-dark)}
.section--navy .audit-rows__item .arrow{color:var(--lime)}
.section--navy .audit-rows__term{color:var(--on-dark)}        /* 16.16:1 */
.section--navy .audit-rows__text{color:var(--on-dark-body)}   /*  8.24:1 */

/* --- The trust strip -----------------------------------------------------
   The live site separates these with a typed bullet. This draws the separator
   as a border instead — same reason the arrow is an SVG sprite: a glyph the
   self-hosted Manrope subset does not carry falls through to whatever the OS
   supplies and renders at a different weight from the type beside it.

   The separator is on :not(:first-child), so when the turnaround item is
   absent (its Customizer value cleared) the strip closes up cleanly instead of
   ending on a dangling divider. */
.audit-trust{
  display:flex;flex-wrap:wrap;
  margin:var(--space-6) 0 0;
  padding:0;
  list-style:none;
  font-size:13px;line-height:1.5;
  color:var(--muted);                                 /* 5.53:1 on white */
}
.audit-trust__item{margin:0}
.audit-trust__item:not(:first-child){
  margin-left:var(--space-4);
  padding-left:var(--space-4);
  border-left:1px solid var(--line-strong);
}
.section--navy .audit-trust{color:var(--on-dark-body)}        /* 8.24:1 */
.section--navy .audit-trust__item:not(:first-child){border-left-color:var(--line-dark)}

/* --- The named deliverable ----------------------------------------------
   Hairlines top and bottom, not a panel. It sits in the right-hand column of
   the navy form band, opposite the form, and a second bordered panel beside
   the .form-shell would read as two competing boxes. */
.audit-deliverable{
  padding:var(--space-5) 0;
  border-top:1px solid var(--line);
  border-bottom:1px solid var(--line);
  margin:0 0 var(--space-6);
}
.section--navy .audit-deliverable{border-top-color:var(--line-dark);border-bottom-color:var(--line-dark)}

/* --- The booking iframe --------------------------------------------------
   This was an inline `style="border:…;background:…"` attribute on the iframe.
   Inline paint cannot be beaten by any stylesheet rule, so the navy band could
   never correct it, and it hard-coded --line — a near-white bar on navy, not a
   hairline. As a class the navy band fixes it. */
.audit-calendar{
  display:block;
  border:1px solid var(--line);
  background:var(--bg);
}
.section--navy .audit-calendar{border-color:var(--line-dark)}

/* --- Spacing, as classes rather than inline attributes ------------------- */
.audit-gap{margin-top:var(--space-6)}
/* (0,1,0), the same weight as .empty-state, so on `.empty-state.audit-proof`
   the winner is source order. .empty-state sets no margin of its own, so there
   is nothing to out-rank today — but if one is ever added, this rule has to
   move below it. */
.audit-proof{margin-top:var(--space-7)}
.audit-proof__more{margin:var(--space-5) 0 0}
/* The editor's own the_content() block at the foot of the contact band. */
.contact-copy{margin-top:var(--space-7)}

/* --- Step headings -------------------------------------------------------
   NOT A NEW COMPONENT — one added line on the existing .step. The steps on the
   audit page are h4 rather than h3 now, because the column above them opens on
   an h2 and the outline has to run h2 -> h3 -> h4 without skipping. This sheet
   styles `.step h3` only, so the h4 kept the base 18px (which is on the ladder
   and correct) but lost the step's own heading gap. (0,1,1). */
.step h4{margin-bottom:var(--space-2)}


/* ==========================================================================
   4. .ee-form — REMOVED (dead-code pass, v1.9.2)
   ==========================================================================

   The whole `.ee-form*` family is gone: .ee-form, __row, __req, __group,
   __legend, __options, __option, __check, their two `.section--navy
   .form-shell` overrides, the radio/checkbox sizing and focus rules, and the
   print rule that hid the block.

   WHY, AND WHY THE OLD COMMENT HERE WAS WRONG. It said these rules were
   "Rendered by page-free-audit.php and page-contact.php ONLY when no form
   shortcode is set". Neither file has emitted `.ee-form` since both
   destructive <form> blocks were replaced by the `.audit-rows` + mailto
   pattern; grep the theme for "ee-form" and there is not one hit outside this
   sheet. A later note in the same block conceded the rules were "dormant" but
   kept them "because whatever comes back must not come back 4px short" — and
   that reason cannot hold: this section's own header states that when a
   shortcode IS set "the plugin's markup renders instead and none of this
   applies". A form plugin ships its own class names, so these rules could
   never have applied to the thing they were being kept for.

   The section NUMBER is kept so §5 and the cross-references to it still line
   up. If a hand-rolled form is ever written again, it needs new rules written
   against its real markup, not these.
   ========================================================================== */
/* --- Narrow widths -------------------------------------------------------
   719px is this sheet's own breakpoint for .grid--2 / .grid--3 collapsing to a
   single column. The marketplace radio group that used to collapse here went
   with the .ee-form family; the audit trust row is what is left. */
@media (max-width:719px){
  .audit-trust__item:not(:first-child){
    margin-left:var(--space-3);
    padding-left:var(--space-3);
  }
}


/* ==========================================================================
   5. THE CALCULATORS
   template-parts/section-calculator.php · page-tools.php · page-pricing.php
   assets/js/calculators.js
   ==========================================================================

   THE SHAPE IS THE FIELD, NOT A WIDGET. Every instinct for a calculator is a
   card: a raised panel, a coloured result chip, a green/amber/red pill.
   DIRECTION §2 forbids all three. So a calculator is two columns divided by a
   single vertical hairline, with each result on its own horizontal hairline
   row. There is no fill anywhere below except on the input controls, which
   need one to read as controls.

   TWO PREFIXES, AND THEY ARE NOT A MISTAKE — YET.
     .calc-*   the retainer estimator on page-pricing.php (single hyphen)
     .calc__*  the four calculators on the homepage and /tools (BEM element)
   They are two vocabularies for a related object, written by two agents who
   could not see each other's file, and consolidating them is a real job that
   needs ownership of both templates. It is NOT half-done here. What IS done:
   the shared root `.calc` is declared once (both files shipped an identical
   `margin-top:var(--space-7)`), and `.calc [hidden]` is scoped to that shared
   root so it covers both subtrees, which is correct for both.

   CONTRAST — every pairing, measured against its own ground:
     on NAVY #0E1B2B
       --on-dark      #F5F7F9  16.16:1  labels, values, verdicts, read-outs
       --on-dark-body #A8B4C2   8.24:1  notes, hints, scale captions, ticks
       --lime         #C6F432  13.54:1  slider accent, focus ring
       --line-dark    #22334A   1.36:1  DECORATIVE RULES ONLY — never text, and
                                        never the boundary of a control; every
                                        input border on navy uses
                                        --on-dark-body so it clears 3:1
     on WHITE #FFFFFF
       --ink          #0E1B2B  17.35:1  labels, values, verdicts, read-outs
       --body         #2B3A4D  11.57:1  the stated maths
       --muted        #5A6A7E   5.53:1  notes, hints, scale captions, ticks
       --line         #DFE8F2   1.24:1  decorative rules only, as above

   Nothing is drawn in --danger or --success. #E5484D measures 4.43:1 on navy
   and 3.91:1 on white, both under the body floor, and a verdict carried by
   colour alone fails anyone who cannot see it — every verdict below is a
   sentence whose words carry the meaning. The headline figure is deliberately
   NOT lime: §3.1 spends lime on the arrow, the action and one hero keyword, so
   size and weight carry the emphasis instead, unlike the live site.
   ========================================================================== */

/* The shared root. ONE declaration for both vocabularies — the duplicate is
   dropped, and it moved nothing because the two were byte-identical. */
.calc{margin-top:var(--space-7)}

/*
 * `hidden` is how calculators.js hides a guarded row (`data-calc-when`) and how
 * the estimator hides its no-JS apply button. The UA stylesheet's
 * `[hidden]{display:none}` is display-weight only, so ANY rule that sets
 * display on a hidden element silently re-shows it — `.calc__result
 * {display:flex}` is exactly such a rule and the ROI row uses both.
 * (0,2,0) beats every single-class rule in this block, so the guard holds no
 * matter what is added later. Do not lower it.
 */
.calc [hidden]{display:none}


/* --- 5a · THE RETAINER ESTIMATOR, page-pricing.php band 3 (navy) --------- */

.calc-grid{
  display:grid;grid-template-columns:1fr 1fr;
  gap:var(--space-8);align-items:start;
}
.calc-field{min-width:0}
/* (0,1,0) over the base `label` at (0,0,1) — this only adds spacing; weight,
   size and block display all come from the base rule and stay in one place. */
.calc-field__label{margin-bottom:var(--space-3)}

/* The read-out is the INPUT restated, so it sits one rung below the answer:
   26px here against 42px on the total. Both are on the type ladder and the gap
   between them is what tells you which number is the result. */
.calc-readout{
  display:block;margin:0 0 var(--space-3);
  font-size:26px;font-weight:800;line-height:1.1;letter-spacing:-.022em;
  color:var(--ink);
  font-variant-numeric:tabular-nums;font-feature-settings:'tnum' 1;
}

/*
 * THE SLIDER IS THE BROWSER'S OWN CONTROL AND STAYS THAT WAY.
 *
 * Drawing it by hand means -webkit-slider-runnable-track,
 * -webkit-slider-thumb and -moz-range-track — three pseudo-elements with no
 * shared source of truth, each needing its own contrast check per browser, and
 * a thumb re-centred by hand every time the track height moves. `accent-color`
 * recolours the fill and the thumb in one declaration, keeps the native
 * keyboard behaviour, and cannot animate. The unfilled track stays the UA's
 * own grey, which reads on both grounds.
 *
 * INTEGRATOR (v1.9): the height was 24px and is now 44px. A range input's
 * target is its whole box, and 24px is under the 44px floor — this is the one
 * dimension of a slider a visitor has to hit before they can drag it. The
 * track stays where the UA centres it, so nothing moves except the hit area.
 */
.calc-range{
  display:block;width:100%;height:44px;margin:0;padding:0;
  background:transparent;
  accent-color:var(--ink);
}
/* (0,2,0), which TIES with the umbrella `.section--navy :focus-visible` at
   (0,2,0) and wins on source order because this block is below it — and the
   shorthand would then re-impose --ink on navy. The (0,3,0) line in the navy
   group settles it on weight instead, which is why that line is not optional. */
.calc-range:focus-visible{outline:2px solid var(--ink);outline-offset:4px}

/* The scale is a legend, not a set of pointers — the exact figure is in the
   read-out, which is why the markup has this aria-hidden. */
.calc-ticks{
  display:flex;justify-content:space-between;gap:var(--space-2);
  margin:var(--space-2) 0 0;padding:0;list-style:none;
}
.calc-ticks__item{
  font-size:12px;letter-spacing:.04em;white-space:nowrap;
  color:var(--muted);                                   /* 5.53:1, safe at 12px */
  font-variant-numeric:tabular-nums;font-feature-settings:'tnum' 1;
}

/* The no-JS apply button. The script sets `hidden` on it once it has bound to
   the slider. (0,2,0) — a class plus an attribute — so no later display rule at
   (0,1,0) can bring back a control that does nothing. */
.calc-submit{margin:var(--space-5) 0 0}
.calc-submit[hidden]{display:none}

/* --- The output — hairline rows, no box --------------------------------- */
.calc-out{margin:0;border-top:1px solid var(--line)}
.calc-out__row{
  display:flex;flex-wrap:wrap;justify-content:space-between;align-items:baseline;
  gap:var(--space-4);
  padding:var(--space-4) 0;
  border-bottom:1px solid var(--line);
}
.calc-out__label{min-width:0;font-weight:700;font-size:15.5px;color:var(--ink)}
.calc-out__note{
  display:block;margin-top:2px;
  font-weight:400;font-size:13px;line-height:1.5;color:var(--muted);
}
.calc-out__value{
  font-weight:800;font-size:20px;letter-spacing:-.02em;white-space:nowrap;
  color:var(--ink);
  font-variant-numeric:tabular-nums;font-feature-settings:'tnum' 1;
}
/* Emphasis is a heavier EDGE, never a lift — the total row is the only line in
   the group whose rule is drawn in ink rather than in the hairline colour.
   That edge carries meaning, so it is --ink (17.35:1) on white and --on-dark
   (16.16:1) on navy, both far past the 3:1 a component boundary needs. */
.calc-out__row--total{
  padding-top:var(--space-5);padding-bottom:var(--space-5);
  border-bottom-color:var(--ink);
}
.calc-out__total{display:inline-flex;align-items:baseline;gap:2px;white-space:nowrap}
/* 42px desktop, 26px floor: both on the ladder, and the clamp is allowed to
   pass through the 26–40px hole on its way down. */
.calc-out__value--total{
  font-size:clamp(26px,4vw,42px);line-height:1;letter-spacing:-.03em;
}
.calc-out__unit{font-size:15px;font-weight:700;color:var(--muted)}
.calc-note{
  margin:var(--space-5) 0 0;
  font-size:13.5px;line-height:1.55;color:var(--muted);max-width:62ch;
}

/* Navy ground — colour only. Every selector is (0,2,0) against a base at
   (0,1,0), except the two noted at their rule. */
.section--navy .calc-field__label{color:var(--on-dark)}      /* (0,2,0) over `label` (0,0,1) */
.section--navy .calc-readout{color:var(--on-dark)}
.section--navy .calc-range{accent-color:var(--lime)}
/* (0,3,0) — see the note on .calc-range:focus-visible above. */
.section--navy .calc-range:focus-visible{outline-color:var(--lime)}
.section--navy .calc-ticks__item{color:var(--on-dark-body)}
.section--navy .calc-out{border-top-color:var(--line-dark)}
.section--navy .calc-out__row{border-bottom-color:var(--line-dark)}
.section--navy .calc-out__label{color:var(--on-dark)}
.section--navy .calc-out__note{color:var(--on-dark-body)}
.section--navy .calc-out__value{color:var(--on-dark)}
.section--navy .calc-out__row--total{border-bottom-color:var(--on-dark)}
.section--navy .calc-out__unit{color:var(--on-dark-body)}
.section--navy .calc-note{color:var(--on-dark-body)}

/* --- The published facts — entry price, term, and the base/rate when they
       are published as ranges the estimator refuses to average. ----------- */
.estimator-facts{
  max-width:820px;                 /* matches .faq, so the two hairline stacks
                                      on this page share one measure */
  margin:var(--space-7) 0 0;padding:0;
  border-top:1px solid var(--line);
}
.estimator-facts__row{
  display:flex;flex-wrap:wrap;justify-content:space-between;align-items:baseline;
  gap:var(--space-4);
  padding:var(--space-4) 0;
  border-bottom:1px solid var(--line);
}
/* margin:0 is load-bearing on the <dd>: the UA gives it margin-inline-start:40px
   and the row would sit indented against every other hairline on the page. */
.estimator-facts__label{margin:0;font-weight:700;font-size:15.5px;color:var(--ink)}
.estimator-facts__value{
  margin:0;text-align:right;
  font-weight:800;font-size:18px;color:var(--ink);
  font-variant-numeric:tabular-nums;font-feature-settings:'tnum' 1;
}
.section--navy .estimator-facts{border-top-color:var(--line-dark)}
.section--navy .estimator-facts__row{border-bottom-color:var(--line-dark)}
.section--navy .estimator-facts__label{color:var(--on-dark)}
.section--navy .estimator-facts__value{color:var(--on-dark)}

/* No colour declaration: on navy `.section--navy p` at (0,1,1) already paints
   this --on-dark-body and out-ranks a (0,1,0) class rule, so declaring a colour
   here would be a rule that never applies on the only ground it uses. */
.estimator-enterprise{margin:var(--space-5) 0 0;max-width:62ch;font-size:16px}

.estimator-cta{margin:var(--space-6) 0 0}
/* (0,2,0) over `.micro` (0,1,0) — the offer's micro-copy belongs to the button
   above it, not to the band. */
.estimator-cta + .micro{margin-top:var(--space-3)}

/* --- What every retainer covers — band 4, which is WHITE and permanently so.
       There is deliberately no .section--navy override for this list: the band
       cannot be navy without breaking the ladder, and a rule that can never
       match is a rule the next person has to disprove. ------------------- */
.estimator-incl{
  max-width:820px;
  margin:var(--space-6) 0 0;padding:0;list-style:none;
  border-top:1px solid var(--line);
}
.estimator-incl__item{
  position:relative;
  padding:var(--space-4) 0 var(--space-4) 28px;
  border-bottom:1px solid var(--line);
  font-size:16px;line-height:1.55;color:var(--body);
}
/* The same hairline marker as .pricing-card__list and .cs-checklist — list
   markers are rules, not arrows, sitewide (§5). Offset by the row's own top
   padding so it lands on the first line rather than on the gap above it. */
.estimator-incl__item::before{
  content:'';position:absolute;left:0;top:calc(var(--space-4) + .78em);
  width:14px;height:1px;background:var(--blue);
}

@media (max-width:899px){
  .calc-grid{grid-template-columns:1fr;gap:var(--space-7)}
}
@media (max-width:719px){
  /* Five figures do not fit across a phone. Dropping the even ticks leaves the
     floor, the midpoint and the ceiling — still a legend, still honest, and it
     beats five overlapping labels or a horizontal scrollbar under a slider. */
  .calc-ticks__item:nth-child(even){display:none}
}
@media (max-width:479px){
  .calc-out__row,
  .estimator-facts__row{flex-direction:column;align-items:flex-start;gap:var(--space-2)}
  .estimator-facts__value{text-align:left}
}


/* --- 5b · THE FOUR CALCULATORS, homepage band 5 and /tools -------------- */

.calc__grid{
  display:grid;
  grid-template-columns:1fr;
  gap:var(--space-7);
}
.calc__controls{min-width:0}
.calc__results{min-width:0}

@media (min-width:900px){
  .calc__grid{
    grid-template-columns:1.05fr .95fr;
    gap:var(--space-8);
  }
  /* The one vertical rule in the component. Decorative, so --line is correct:
     it separates two regions, it does not bound a control. */
  .calc__results{
    border-left:1px solid var(--line);
    padding-left:var(--space-7);
  }
}

/* Each .calc__field is a 3-row grid so a slider can sit under its own label
   with the live value right-aligned on the label's line, WITHOUT a wrapper div
   around the pair. Every child is pinned explicitly: auto-placement would put
   the range input at row 1 column 2 (it follows the label in the DOM) and drop
   the value to row 2, which is the opposite of the intent. */
.calc__field{
  display:grid;
  grid-template-columns:1fr auto;
  column-gap:var(--space-4);
  align-items:baseline;
  margin-bottom:var(--space-5);
}
.calc__label{
  grid-column:1;grid-row:1;
  display:block;
  margin:0 0 var(--space-2);
  font-size:13px;
  font-weight:700;
  line-height:1.4;
  letter-spacing:.01em;
  /* (0,1,0) beats the global `label{…}` at (0,0,1) — that rule sets 14px and a
     7px margin site-wide and is right for a contact form, not for a dense
     control stack. */
  color:var(--ink);
}
.section--navy .calc__label{color:var(--on-dark)}   /* 16.16:1 */

.calc__output{
  grid-column:2;grid-row:1;
  font-size:17px;
  font-weight:800;
  letter-spacing:-.02em;
  text-align:right;
  color:var(--ink);
  /* The value under a moving slider is the one number on the page guaranteed
     to change every frame the thumb travels. Without tabular figures the
     digits reflow and the whole row twitches. */
  font-variant-numeric:tabular-nums;
  font-feature-settings:'tnum' 1;
}
.section--navy .calc__output{color:var(--on-dark)}

.calc__range{
  grid-column:1/-1;grid-row:2;
  width:100%;
  /* INTEGRATOR (v1.9): 44px added. A UA range box is ~16–20px tall, so the
     drag target was a 16px band and under the floor — the same correction
     .calc-range takes above, and the same value, because it is the same
     control on two pages. Row 3 holds the scale, so nothing collides. */
  height:44px;
  margin:0;
  /* The track is left to the UA on purpose. A hand-drawn track would need a
     3:1 boundary against BOTH grounds, and the two candidates that read as
     brand (--line, --line-dark) measure 1.24:1 and 1.36:1 against them. The UA
     track already clears it on white and on navy; `accent-color` recolours only
     the filled portion and the thumb, which are the parts that carry meaning.
     Lime is legitimate here: §3.1 allows it for "the action", and a slider
     thumb is the action. */
  accent-color:var(--lime);
}
.calc__input{
  grid-column:1/-1;grid-row:2;
  /* Typed digits jitter the same way slider read-outs do. */
  font-variant-numeric:tabular-nums;
  font-feature-settings:'tnum' 1;
}

/*
 * ON NAVY THE INPUT LOSES ITS WHITE FILL.
 *
 * The global control block paints `background:var(--bg)` with a --line-strong
 * border, which on a navy band is a white rectangle: a box, on a site whose
 * whole rule is rules-not-boxes. Transparent with a hairline keeps the field
 * aesthetic and still reads as a control.
 *
 * SPECIFICITY IS LOAD-BEARING. `input[type=number]{…}` is (0,1,1), so a plain
 * `.calc__input` at (0,1,0) LOSES to it regardless of source order. (0,3,0)
 * settles it without an !important and without depending on where this block
 * sits in the file.
 *
 * The border is --on-dark-body (8.24:1), NOT --line-dark (1.36:1). A control
 * boundary needs 3:1 and --line-dark does not come close — that is the exact
 * failure this section's header warns about.
 */
.section--navy .calc .calc__input{
  background:transparent;
  border-color:var(--on-dark-body);
  color:var(--on-dark);
}
.section--navy .calc .calc__input::placeholder{color:var(--on-dark-body)}

/*
 * FOCUS. The global `input:focus` sets `border-color:var(--ink)`, which on navy
 * is navy on navy — the ring disappears entirely on three of the seven fields
 * on /tools. (0,4,0) against (0,1,1). The ring is a box-shadow because that is
 * what the rest of the theme's controls already use; it is an accessibility
 * indicator, not the elevation §2 bans. The lime BORDER is the indicator that
 * carries the contrast (13.54:1); the 25% shadow only widens it.
 */
.section--navy .calc .calc__input:focus{
  border-color:var(--lime);
  box-shadow:0 0 0 3px rgba(198,244,50,.25);
}

/* Range inputs sit outside the global control block, so they carry no focus
   style at all until here. 4px offset, matching .calc-range:focus-visible
   above — the same control on two pages must not have two focus rings.
   (0,2,0), tying with the navy umbrella and winning on source order; the
   (0,3,0) line beneath settles the navy case on weight. */
.calc__range:focus-visible{outline:2px solid var(--ink);outline-offset:4px}
.section--navy .calc__range:focus-visible{outline-color:var(--lime)}

.calc__scale{
  grid-column:1/-1;grid-row:3;
  display:flex;
  justify-content:space-between;
  margin:var(--space-2) 0 0;
  font-size:12px;
  color:var(--muted);            /* 5.53:1 — safe at 12px */
  font-variant-numeric:tabular-nums;
  font-feature-settings:'tnum' 1;
}
.section--navy .calc__scale{color:var(--on-dark-body)}   /* 8.24:1 */

/* Two fields side by side above the phone breakpoint. Below it they stack,
   because a 50px-tall number field in half a 375px viewport is not a control
   anybody can hit. */
.calc__row{
  display:grid;
  /* WIDTH:100% IS LOAD-BEARING, NOT TIDINESS.
     This row is a block-level grid and its parent is a <fieldset>. A fieldset
     lays its children out inside an anonymous content box, and Chrome does not
     resolve `width:auto` on a GRID child against that box -- the row computed to
     0px inside a 327px fieldset, both fields piled up at its right edge at their
     75px min-content width, and the overflow pushed the whole document sideways:
     411px of scroll in a 375px viewport, i.e. the homepage scrolled horizontally
     on every phone. The block children of the same fieldset (legend, .calc__note)
     were unaffected, which is what makes this a grid-in-fieldset quirk rather
     than a sizing mistake. `display:flow-root` on the fieldset does NOT fix it;
     a definite width on the row does. */
  width:100%;
  grid-template-columns:1fr;
  column-gap:var(--space-4);
}
@media (min-width:560px){
  .calc__row{grid-template-columns:1fr 1fr}
}
.calc__field--half{margin-bottom:var(--space-5)}

/* --- The assumptions group ---------------------------------------------- */
.calc__group{
  margin:var(--space-6) 0 0;
  padding:var(--space-5) 0 0;
  border:0;
  border-top:1px solid var(--line);
  min-inline-size:0;    /* fieldsets carry a UA min-width:min-content */
}
.section--navy .calc__group{border-top-color:var(--line-dark)}
/*
 * `float:left;width:100%` is not decoration — a <legend> is placed inside the
 * fieldset's block-start border box by the UA, so with the border-top above it
 * would sit ON the hairline. Floating it takes it out of that special
 * placement and makes it an ordinary block.
 */
.calc__legend{
  float:left;
  width:100%;
  margin:0 0 var(--space-4);
  padding:0;
  font-size:12px;
  font-weight:700;
  letter-spacing:.14em;
  text-transform:uppercase;
  color:var(--muted);
}
.section--navy .calc__legend{color:var(--on-dark-body)}
.calc__group::after{content:"";display:block;clear:both}

/* --- Results ------------------------------------------------------------ */
.calc__results-title{
  margin:0 0 var(--space-3);
  font-size:12px;
  font-weight:700;
  letter-spacing:.14em;
  text-transform:uppercase;
  color:var(--muted);
}
.section--navy .calc__results-title{color:var(--on-dark-body)}

/* The visibility unit for `data-calc-when="ready"`. It deliberately does NOT
   become a flex or grid container: it exists only so the guard can hide the
   whole figure stack in one attribute, and a display value here would be one
   more thing for `.calc [hidden]` to out-rank. */
.calc__figures{display:block}

.calc__result{
  display:flex;
  flex-wrap:wrap;
  justify-content:space-between;
  align-items:baseline;
  gap:var(--space-2) var(--space-4);
  margin:0;
  padding:var(--space-4) 0;
  border-top:1px solid var(--line);
}
.section--navy .calc__result{border-top-color:var(--line-dark)}

.calc__result-label{
  font-size:14px;
  line-height:1.45;
  color:var(--muted);
  max-width:34ch;
}
.section--navy .calc__result-label{color:var(--on-dark-body)}

.calc__result-value{
  font-size:20px;
  font-weight:800;
  letter-spacing:-.02em;
  white-space:nowrap;
  color:var(--ink);
  font-variant-numeric:tabular-nums;
  font-feature-settings:'tnum' 1;
}
.section--navy .calc__result-value{color:var(--on-dark)}

/*
 * The headline figure. ORDERED AFTER .calc__result ON PURPOSE: both are
 * (0,1,0), so source order is what strips the hairline and the flex layout off
 * the lead row. Moving this block above the one it overrides re-boxes it.
 */
.calc__result--lead{
  display:block;
  padding:0;
  border-top:0;
}
.calc__result--lead .calc__result-value{
  font-size:clamp(40px,5.5vw,64px);
  line-height:1.02;
  letter-spacing:-.03em;
  white-space:normal;
}

.calc__verdict{
  margin:var(--space-5) 0 0;
  padding:var(--space-4) 0 0;
  border-top:1px solid var(--line);
  font-size:17px;
  font-weight:700;
  line-height:1.45;
  color:var(--ink);
}
.section--navy .calc__verdict{border-top-color:var(--line-dark);color:var(--on-dark)}

.calc__hint{
  margin:var(--space-4) 0 0;
  font-size:15px;
  line-height:1.55;
  color:var(--muted);
  max-width:52ch;
}
.section--navy .calc__hint{color:var(--on-dark-body)}

.calc__note{
  margin:var(--space-4) 0 0;
  font-size:13.5px;
  line-height:1.6;
  color:var(--muted);          /* 5.53:1 — holds at this size */
  max-width:62ch;
}
.section--navy .calc__note{color:var(--on-dark-body)}   /* 8.24:1 */

/* --- The stated maths ---------------------------------------------------
   Not a footnote — it is the reason the page can be trusted with JavaScript
   switched off. The formulas are readable prose, so a visitor can run their own
   numbers on paper. Styled to be read, not to be skipped. */
.calc__maths{
  margin-top:var(--space-7);
  padding-top:var(--space-5);
  border-top:1px solid var(--line);
}
.section--navy .calc__maths{border-top-color:var(--line-dark)}
/* (0,1,1) beats the global `h3` at (0,0,1). */
.calc__maths h3{
  margin:0 0 var(--space-3);
  font-size:12px;
  font-weight:700;
  letter-spacing:.14em;
  text-transform:uppercase;
  color:var(--muted);
}
.section--navy .calc__maths h3{color:var(--on-dark-body)}
.calc__maths ul{
  margin:0;
  padding:0;
  list-style:none;
}
.calc__maths li{
  margin:0;
  padding:var(--space-3) 0;
  border-top:1px solid var(--line);
  font-size:14.5px;
  line-height:1.6;
  color:var(--body);
  max-width:78ch;
}
.calc__maths li:first-child{border-top:0;padding-top:0}
.section--navy .calc__maths li{border-top-color:var(--line-dark);color:var(--on-dark-body)}

/* --- The band's call to action ------------------------------------------ */
.calc__cta{
  display:flex;
  flex-wrap:wrap;
  align-items:center;
  gap:var(--space-3) var(--space-5);
  margin-top:var(--space-7);
}
/* The micro line is a sibling of the button here, not stacked beneath it, so
   its site-wide top margin would push the row out of alignment. (0,2,0) over
   `.micro` (0,1,0). */
.calc__cta .micro{margin:0}


/* ==========================================================================
   Print
   Navigation, CTAs and anything marked .no-print drop out; the body reflows
   to a single readable column with real page breaks. Tokens only — --ink on
   --bg prints as near-black on white.
   ========================================================================== */
@media print{
  .no-print,
  .site-header,.main-nav,.nav-toggle,.skip-link,.site-footer,
  .cta-band,.section--cta,
  .share-row,.filter-bar,.pagination,.next-prev,
  .hero__ctas,.btn,
  .post-card__media,.cs-card__media{
    display:none!important;
  }

  html,body{
    background:var(--bg)!important;
    color:var(--ink)!important;
    font-size:11.5pt;line-height:1.5;
  }
  .container{max-width:none;padding:0}
  .section,.page-hero,.cs-hero{padding:0 0 18pt!important}

  /* Dark and tinted bands print as plain white */
  .section--navy{background:var(--bg)!important;color:var(--ink)!important}
  .section--navy h1,.section--navy h2,.section--navy h3,.section--navy h4,
  .section--navy p,.section--navy li,
  .section--navy .breadcrumbs .breadcrumbs__item,
  .section--navy .post-card .post-card__excerpt,
  .section--navy .cs-results .cs-result__label,
  .section--navy .legal-content{color:var(--ink)!important}

  h1,h2,h3,h4{color:var(--ink)!important;page-break-after:avoid;break-after:avoid}
  p,li,blockquote{orphans:3;widows:3}
  .entry-content,.legal-content,.section__lead{max-width:none}

  /* Cards keep a hairline and never straddle a page break */
  .card,.post-card,.cs-card,.review-card,.pricing-card,.testimonial,
  .author-box,.toc,.legal-toc,.form-shell,.empty-state,.cs-proof,
  .logo-wall,.logo-wall__item,.next-prev__item,.service-row,.callout{
    background:var(--bg)!important;
    border-color:var(--line-strong)!important;
    box-shadow:none!important;
    page-break-inside:avoid;break-inside:avoid;
  }
  .cs-results,.stats,.grid,.review-grid,.pricing-grid,.logo-wall{page-break-inside:avoid;break-inside:avoid}

  /* Links: readable, with the destination spelled out for real URLs only */
  a{color:var(--ink)!important;text-decoration:underline}
  .entry-content a[href^="http"]::after,
  .legal-content a[href^="http"]::after{
    content:" (" attr(href) ")";
    font-size:.85em;color:var(--muted);word-break:break-all;
  }

  /* Wide content can spill on paper — let it wrap instead of clipping */
  .toc,.legal-toc,.legal-content .wp-block-table,.entry-content .wp-block-table,
  .legal-content pre,.entry-content pre{overflow:visible!important}
  .legal-toc ul,.legal-toc ol{columns:1}
  .legal-content pre,.entry-content pre{white-space:pre-wrap;word-wrap:break-word}

  img{max-width:100%!important}
  @page{margin:16mm}
}

/* ==========================================================================
   Print — the v1.8 components
   ==========================================================================

   A SECOND @media print block rather than edits inside the first one. Both
   are legitimate CSS; this one is chosen because it sits LAST in the file, so
   every declaration here wins any specificity tie with the block above it
   without needing !important to say so — and because it keeps the v1.8
   components' print behaviour beside nothing but itself, so removing the
   whole v1.8 section later is one contiguous delete.

   The governing idea is the same as the original print block: the navy ground
   is a screen device. On paper it is ink on white, and everything whose only
   job was to make type legible against a photograph or a dark field has no
   job left. ========================================================================== */
@media print{
  /* Scenery, scrims and dissolves: all three exist to solve a problem paper
     does not have, and all three would print as large flat areas of ink. */
  .hero-field__scrim,
  .arrow-arch,
  .ee-plate__arrow{
    display:none!important;
  }

  /* The field becomes the page. */
  .hero-field,
  .hero-field__frame,
  .trajectory,
  .team-member__media,
  .founder-band__portrait,
  .ee-plate{
    background:var(--bg)!important;
    color:var(--ink)!important;
    min-height:0!important;
  }
  .hero-field__frame{display:block!important;overflow:visible!important}
  .hero-field__copy{max-width:none!important;padding:0!important}

  /* Every colour the two dark variants set has to come back to ink. The
     originals are (0,3,0); !important is what settles it rather than a
     fourth class, because this is a media-query override and not a cascade
     the rest of the file has to live with. */
  .hero-field h1,.hero-field .display,.hero-field .eyebrow,
  .hero-field .lead-xl,.hero-field .micro,.hero-field .lime,
  .trajectory .tr__from,.trajectory .tr__arrow,
  .trajectory .tr__to,.trajectory .tr__label,
  .team-member .team-member__name,.team-member .team-member__role,
  .ee-plate .ee-plate__label,.ee-plate .ee-plate__initials,
  .ee-plate .ee-plate__metric{
    color:var(--ink)!important;
  }

  /* Hairlines print, and they are the whole component — so they have to be
     dark enough to survive a laser printer's dot gain. */
  .trajectory,
  .trajectory .tr-cell + .tr-cell{
    border-color:var(--line-strong)!important;
  }

  /* The plate is a physical label. It keeps its edge and never straddles a
     page break; it just stops being absolutely positioned over a picture. */
  .plate{
    position:static!important;
    width:auto!important;
    padding:var(--space-3) 0 0!important;
    background:transparent!important;
    text-align:left!important;
    page-break-inside:avoid;break-inside:avoid;
  }
  .plate .plate__index,.plate .plate__name{color:var(--ink)!important}

  /* Cells and members are units of meaning — never split one across pages. */
  .tr-cell,.team-member,.founder-band__portrait{
    page-break-inside:avoid;break-inside:avoid;
  }

  /* Grids that are three-up on screen are two-up on A4 and nothing is
     centred. */
  .team-grid{grid-template-columns:repeat(2,1fr)!important}
  .founder-band{grid-template-columns:minmax(0,1fr)!important}
  .trajectory__inner{padding:0!important}

  /* --- v1.9 components ---------------------------------------------------
     A .record row is a short dated fact — exactly the thing that must not be
     split across a page break. The calculators and the two hand-rolled forms
     print as their prose: the stated maths and the printed worked example are
     the parts that survive without a browser, and the controls are not.
     .founder-band__actions and .calc__cta are calls to action, which the first
     print block already drops everywhere else. */
  .record__row,
  .audit-rows__item,
  .estimator-facts__row,
  .calc-out__row{page-break-inside:avoid;break-inside:avoid}

  .founder-band__actions,.calc__cta,.calc__range,.calc-range,.calc-submit,.audit-calendar{display:none}

  /* Hairlines print dark enough to survive a laser printer's dot gain, the
     same correction the trajectory takes above. */
  .record__row,
  .audit-rows__item,
  .audit-deliverable,
  .calc-out,
  .calc-out__row,
  .estimator-facts,
  .estimator-facts__row,
  .estimator-incl,
  .estimator-incl__item,
  .calc__result,
  .calc__maths,
  .calc__maths li,
  .cs-band__more,
  .cs-band__empty,
  .founder-band__creds,
  .hero-field .hero-field__operator,
  .hero-field .hero-field__guarantees{
    border-color:var(--line-strong)!important;
  }

  /* Two columns become one on A4 — there is no vertical rule to divide. */
  .calc__grid,.calc-grid{grid-template-columns:minmax(0,1fr)!important}
  .calc__results{border-left:0!important;padding-left:0!important}
}
