/* ==========================================================================
   Ulicny — components
   Each block below maps 1:1 to an ACF field group in docs/02-templates.md.
   Section comments name the group, so the port is mechanical.
   ========================================================================== */

/* --- Header ------------------------------------------------------ header.php */

.site-header {
  position: fixed;
  inset: 0 0 auto 0;
  z-index: 50;
  /* the comp leaves ~3.5% of page width above the logo */
  padding-block: clamp(1rem, 3vw, 3rem);
  transition: background var(--dur-fast) var(--ease-soft),
              padding    var(--dur-fast) var(--ease-soft);
}
/* No hairline under the stuck header. It used to carry
   box-shadow: 0 1px 0 rgba(255,255,255,.12) - a 1px row of navy + 12% white
   (rgb 47,100,142 against 18,78,126) drawn straight across the hero and the
   page heads, which the client read as a seam where two navy areas meet. At
   90% / 110% browser zoom it smeared across two rows. The header is the same
   token navy as the band under it, so without the hairline the top of every
   page is one solid colour, at page top and once stuck. */
.site-header.is-stuck {
  background: var(--c-navy);
  padding-block: var(--sp-3);
}

.site-header__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-8);
}

/* Real logo, recoloured white. The comp sets it at ~0.10 of page width. */
.site-logo { display: block; line-height: 0; }
.site-logo img {
  width: clamp(122px, 10vw, 168px);
  height: auto;
}

.site-nav ul {
  display: flex;
  /* Was --sp-6 (24px) flat. The floor keeps 24px at the 900px breakpoint,
     where the row is tightest, and opens up on wider screens. */
  gap: clamp(1.5rem, 2.2vw, 2.25rem);
  margin: 0;
  padding: 0;
  list-style: none;
}
.site-nav a {
  color: var(--c-white);
  font-family: var(--ff-display);
  /* 1rem = 16px. rem rather than a hard px so it still respects a browser
     font-size preference. The mobile overlay overrides this below. */
  font-size: 1rem;
  font-weight: 600;
  letter-spacing: var(--ls-eyebrow);
  text-transform: uppercase;
  text-decoration: none;
  padding-block: var(--sp-2);
  transition: color var(--dur-fast) var(--ease-out);
}
/* Colour alone marks the current page — the comp has NO underline. A lime rule
   under the active item sat at a different height from the header's own bottom
   edge, which read as two misaligned lines. */
.site-nav a:hover,
.site-nav a[aria-current="page"] { color: var(--c-lime); }

.nav-toggle { display: none; }
/* Drawer chrome only exists below the desktop breakpoint. */
.site-nav__head,
.site-nav__contact,
.nav-backdrop { display: none; }

@media (max-width: 899px) {
  .nav-toggle {
    position: relative;
    display: block;
    width: 44px; height: 44px;
    margin-right: -10px;              /* bars' ink on the gutter, not the box */
    background: none; border: 0; cursor: pointer;
    color: var(--c-white);
  }

  /* Three drawn bars, not the ☰ character. The glyph's weight and bar spacing
     are whatever the font decides, and Manrope's is thin and cramped at this
     size; these are 22x2 with a real 7px rhythm. The middle bar IS the
     element; the outer two are its pseudo-elements. The toggle no longer
     folds into a cross: the drawer carries its own close button, top-right,
     and the toggle sits under the backdrop while the drawer is open. */
  .nav-toggle__bars,
  .nav-toggle__bars::before,
  .nav-toggle__bars::after {
    position: absolute;
    left: 50%;
    width: 22px;
    height: 2px;
    margin-left: -11px;
    border-radius: 2px;
    background: currentColor;
  }
  .nav-toggle__bars { top: 50%; margin-top: -1px; }
  .nav-toggle__bars::before { content: ""; top: -7px; }
  .nav-toggle__bars::after  { content: ""; top:  7px; }

  /* --- Drawer --- */
  /* Slides in from the left and stops short of the full width, so a strip of
     the page stays visible behind the backdrop - it reads as a layer over the
     site rather than a new page, and tapping that strip closes it. */
  .site-nav {
    position: fixed;
    inset: 0 auto 0 0;
    z-index: 3;
    width: min(86vw, 400px);
    display: flex;
    flex-direction: column;
    padding: clamp(1rem, 3vw, 1.5rem) clamp(1.5rem, 5vw, 2.5rem) clamp(1.5rem, 5vw, 2.5rem);
    overflow-y: auto;
    overscroll-behavior: contain;
    background: var(--c-navy);
    box-shadow: 24px 0 64px rgba(3, 18, 40, 0.45);
    transform: translateX(-100%);
    visibility: hidden;
    /* visibility steps at the END of a transition, so a plain
       `visibility var(--dur-base)` left the panel unfocusable for 600ms after
       opening - and .focus() on a hidden element silently does nothing. It
       flips instantly on the way in, and waits for the slide on the way out. */
    transition: transform var(--dur-base) var(--ease-out),
                visibility 0s linear var(--dur-base);
  }
  .site-nav.is-open {
    transform: none;
    visibility: visible;
    transition: transform var(--dur-base) var(--ease-out),
                visibility 0s linear 0s;
  }

  .site-nav__head {
    display: flex;
    align-items: center;
    justify-content: space-between;
    min-height: 44px;
    margin-bottom: clamp(2rem, 7vh, 3.5rem);
  }
  .site-nav__logo { display: block; line-height: 0; }
  .site-nav__logo img { width: 122px; height: auto; }

  /* Drawn cross, same 22x2 stroke as the hamburger bars. */
  .site-nav__close {
    position: relative;
    flex: none;
    width: 44px; height: 44px;
    margin-right: -10px;
    background: none; border: 0; cursor: pointer;
    color: var(--c-white);
    transition: color var(--dur-fast) var(--ease-out);
  }
  .site-nav__close::before,
  .site-nav__close::after {
    content: "";
    position: absolute;
    left: 50%; top: 50%;
    width: 22px; height: 2px;
    margin: -1px 0 0 -11px;
    border-radius: 2px;
    background: currentColor;
    transform: rotate(45deg);
  }
  .site-nav__close::after { transform: rotate(-45deg); }
  .site-nav__close:hover { color: var(--c-lime); }

  .site-nav ul { flex-direction: column; gap: 0; }
  .site-nav li + li { border-top: 1px solid rgba(255, 255, 255, 0.12); }
  .site-nav a { font-size: var(--fs-md); }
  .site-nav ul a { display: block; padding-block: 1rem; }

  /* Links follow the drawer in, a beat behind it and one after another. */
  .site-nav li {
    opacity: 0;
    transform: translateX(-16px);
    transition: opacity var(--dur-fast) var(--ease-out),
                transform var(--dur-base) var(--ease-out);
  }
  .site-nav.is-open li { opacity: 1; transform: none; }
  .site-nav.is-open li:nth-child(1) { transition-delay: 120ms; }
  .site-nav.is-open li:nth-child(2) { transition-delay: 170ms; }
  .site-nav.is-open li:nth-child(3) { transition-delay: 220ms; }
  .site-nav.is-open li:nth-child(4) { transition-delay: 270ms; }

  /* Contact pinned to the foot of the drawer - the same two lines the footer
     carries, so nothing new is being said. */
  .site-nav__contact {
    display: flex;
    flex-direction: column;
    align-items: flex-start;
    margin-top: auto;
    padding-top: var(--sp-8);
  }
  .site-nav .site-nav__contact a {
    font-family: var(--ff-body, inherit);
    font-size: 0.9375rem;
    font-weight: 400;
    letter-spacing: 0;
    text-transform: none;
    color: var(--c-panel-copy);
    padding-block: 0.6rem;
  }
  .site-nav .site-nav__contact a:hover { color: var(--c-lime); }

  .nav-backdrop {
    display: block;
    position: fixed;
    inset: 0;
    z-index: 2;
    background: rgba(6, 24, 46, 0.6);
    opacity: 0;
    visibility: hidden;
    transition: opacity var(--dur-base) var(--ease-out),
                visibility 0s linear var(--dur-base);
  }
  .nav-backdrop.is-open {
    opacity: 1;
    visibility: visible;
    transition: opacity var(--dur-base) var(--ease-out),
                visibility 0s linear 0s;
  }
}

/* Phones held sideways are ~390px tall, and at the portrait spacing the two
   contact links fell below the fold. The drawer does scroll, but the whole
   menu should be visible at once, so the rhythm tightens on short screens. */
@media (max-width: 899px) and (max-height: 500px) {
  .site-nav { padding-block: 0.75rem 1rem; }
  .site-nav__head { margin-bottom: 0.75rem; }
  .site-nav ul a { padding-block: 0.55rem; }
  .site-nav__contact { flex-direction: row; gap: var(--sp-6); padding-top: var(--sp-4); }
  .site-nav .site-nav__contact a { padding-block: 0.5rem; }
}

@media (prefers-reduced-motion: reduce) {
  .site-nav,
  .site-nav li,
  .nav-backdrop { transition: none !important; }
}

/* --- Hero -------------------------------------------------- ACF: `hero` */

.hero {
  display: flex;
  align-items: flex-end;
  min-height: var(--hero-h);
  padding-top: var(--sp-24);
  padding-bottom: var(--hero-pb);
  background: var(--c-navy);
  color: var(--c-white);
}
/* The comp sets the hero eyebrow in SENTENCE case - only the parallax panels
   use uppercase. .u-eyebrow uppercases by default, so undo it here. */
.hero__eyebrow {
  color: var(--c-white);
  /* containing block for the typewriter caret */
  position: relative;
  /* 23ch = ~452px at this size. "…and design" measures 429px and "…design by"
     469px, so the break lands after "design", as it does in the comp.
     Manrope’s 0 advance is 0.658em, so ch is wider here than it looks. */
  max-width: 23ch;
  text-transform: none;
  letter-spacing: 0;
}
/* The caret is created and removed by motion.js, never authored in the
   markup. Absolute, so it has zero effect on line breaking - the point of
   the whole approach is that the eyebrow's two lines never move. Cyan
   because that is the colour of the answer it is waiting for. */
.type-caret {
  position: absolute;
  top: 0;
  left: 0;
  width: max(2px, 0.075em);
  background: var(--c-cyan);
  pointer-events: none;
  will-change: transform;
}

.hero__title {
  margin-top: var(--sp-4);
  color: var(--c-cyan);
  max-width: 16ch;
}

/* --- Intro + 30th lockup ------------------------------ ACF: `intro` block */

/* Measured off the comp, as fractions of CONTENT width:
     body column 0.62 | gap 0.15 | lockup column 0.23
   The lead is NOT inside the left column - it spans the full width above
   both, which is why it sits in its own element. */
/* The comp wraps the lead at 0.766 W (≈1103px at a 1440 viewport), breaking
   after "…of the ways we". Measured at this size: that line is 48.4ch and
   adding "interact," pushes it to 55.1ch, so 51ch puts the break where the
   comp puts it. */
.intro__lead { max-width: 51ch; }

.intro__grid {
  display: grid;
  gap: var(--sp-12);
  align-items: start;
  margin-top: clamp(2rem, 5.5vw, 5rem);
}
@media (min-width: 900px) {
  .intro__grid {
    grid-template-columns: 62.1% 22.9%;   /* the remaining 15% is the gap */
    justify-content: space-between;
    gap: var(--sp-8);
  }
}
.intro__body { max-width: var(--measure); }
.intro__body p + p { margin-top: var(--sp-4); }

/* The comp centres the lockup at 0.807 W. Left-aligned inside its column and
   capped, so its own centre lands there — centring it in the full column put
   it at 0.847 W. This affects the homepage intro too, which shares the part. */
.anniversary {
  text-align: center;
  /* Sized to its own widest line rather than a fixed cap. A hard max-width
     was overflowed above 1680px, where the type keeps growing to its clamp
     maxima - and text overflowing a centred block spills right, dragging its
     visual centre off the numeral. max-content can never overflow. */
  width: max-content;
  max-width: 100%;
  margin-inline: auto;              /* centred when the columns stack */
}
@media (min-width: 900px) {
  .anniversary { margin-inline: 0 auto; }   /* column start once side by side */
}
/* 30th lockup — every value measured off the comp (p.3) as a fraction of
   page width W. "CELEBRATING" and "YEARS" are a SLAB serif; the "30" is a
   geometric sans (same treatment as the Who-we-are stat numerals), NOT a
   serif. All three are tracked to roughly equal width (~0.12 W). */

/* No letter-spacing compensation on these two: measured, the centring is
   already correct without it. margin-right:-0.2em pushed them ~5px right and
   text-indent:0.2em ~13px right. */
.anniversary__label {
  font-family: var(--ff-slab);
  font-weight: 700;
  font-size: clamp(min(0.8rem, 5vw), 1.45vw, 1.5rem);   /* comp cap 0.0104 W */
  line-height: 0.8;                           /* box hugs the caps */
  color: var(--c-lockup-label);
  text-transform: uppercase;
  /* comp width 0.1218 W. 0.2em overflowed the 185px lockup box, and text that
     overflows a centred block spills right, shifting its visual centre. */
  letter-spacing: 0.08em;
}

.anniversary__number {
  display: block;
  font-family: var(--ff-display);              /* geometric sans, not serif */
  font-weight: 400;
  font-size: clamp(min(4rem, 22vw), 10.25vw, 11rem);      /* comp cap 0.0769 W */
  line-height: 0.8;
  letter-spacing: 0.01em;
  margin-right: -0.01em;
  margin-top: 0.05em;                          /* comp gap 0.177 x cap30 */
  color: var(--c-lockup-num);
}

.anniversary__years {
  font-family: var(--ff-slab);
  font-weight: 700;
  font-size: clamp(min(1.4rem, 9vw), 3vw, 3.25rem);      /* comp cap 0.0216 W */
  line-height: 0.8;
  color: var(--c-lockup-years);
  text-transform: uppercase;
  letter-spacing: 0.13em;                      /* comp width 0.1250 W */
  margin-top: 0.42em;                          /* comp gap 0.198 x cap30 */
}

.anniversary__tag {
  /* Sans and UPRIGHT in the comp - it was italic serif here. */
  font-family: var(--ff-body);
  font-style: normal;
  font-size: clamp(0.875rem, 1.28vw, 1.25rem);
  line-height: 1.3;
  color: var(--c-ink);
  margin-top: 1.15em;                          /* more air than the comp (0.344 x cap30) */
}

.anniversary .u-pill { margin-top: 1.25em; }   /* more air than the comp (0.240 x cap30) */

/* --- Parallax panels ------------------------ ACF: `parallax_panels` repeater */

.panels { background: var(--c-navy); }

.panel {
  position: relative;
  overflow: hidden;                 /* required: contains the parallax layer */
  isolation: isolate;
  padding-block: clamp(4rem, 10vw, 9rem);
  color: var(--c-white);
}
/* No dividing border - the panels are solid navy. The comp also puts a short
   white tick at the bottom-left of each; removed at the client's request. */

/* Optional per-panel background image, parallaxed at 0.88.
   Oversized so the translate never exposes an edge. */
.panel__bg {
  position: absolute;
  inset: -12% 0;
  z-index: -1;
  background-size: cover;
  background-position: center;
  opacity: 0.28;
  will-change: transform;
}

/* The comp breaks this after "DESIGN". Constrain so the break lands there
   rather than carrying "BY" up onto the first line. */
.panel__eyebrow { color: var(--c-white); max-width: 29ch; }
.panel__title   { margin-top: var(--sp-3); color: var(--c-cyan); font-size: var(--fs-3xl); }
/* The comp sets the panel body in a PALE CYAN (#C1EBF8), not white — measured
   from the stroke cores, b-r = 68 against the eyebrow's 14. This is specific
   to the parallax panels: the navy page-heads on Who we are / How we work
   measure pure white. */
.panel__body {
  margin-top: var(--sp-6);
  max-width: 46ch;
  line-height: var(--lh-copy);
  color: var(--c-panel-copy);
}
.panel .u-pill  { margin-top: var(--sp-8); }

/* --- Conversation band ------------------- ACF (Theme Options): `conversation` */

/* Every value measured off the comp (p.3) as a fraction of page width W.
   The band is asymmetric: much more air below than above. */
.conversation {
  /* The full-bleed CYAN bar belongs to THIS section, not to the panels above
     it. Confirmed in the comp: all four page mocks carry it, including the
     three that have no parallax panels. Measured 0.0045–0.0059 W tall. */
  border-top: clamp(4px, 0.5vw, 8px) solid var(--c-cyan);
  padding-top: clamp(2rem, 4.2vw, 4rem);      /* comp 0.0425 W */
  padding-bottom: clamp(4rem, 9.9vw, 9rem);   /* comp 0.0994 W */
}
.conversation__title {
  color: var(--c-blue);
  font-size: var(--fs-md);                    /* comp 0.0256 W */
  font-weight: 700;
  line-height: 1.2;
}
.conversation__body {
  margin-top: clamp(1.5rem, 2.95vw, 2.75rem); /* comp gap 0.0433 W */
  /* comp body column 0.5224 W. ch scales with the font; vw would over-widen
     on large screens. */
  max-width: 55ch;
  /* marketing leading, not the long-form 1.7 it was inheriting */
  line-height: var(--lh-copy);
}
.conversation .u-pill { margin-top: clamp(1.25rem, 2.4vw, 2.25rem); }  /* comp 0.0297 W */

/* --- Footer ------------------------------------------------------ footer.php */

.site-footer {
  background: var(--c-charcoal);
  color: var(--c-white);
  /* The footer runs SMALLER than body copy. Measured off the comp: text is
     0.0132 W (~19px at 1440), not the 0.016 W of --fs-base. It was
     inheriting --fs-base and reading far too large. */
  font-size: clamp(0.875rem, 1.32vw, 1.25rem);
  line-height: 1.4;
}
.site-footer a { color: var(--c-white); text-decoration: none; }
.site-footer a:hover { color: var(--c-lime); }

.site-footer__grid {
  display: grid;
  gap: var(--sp-12);
}
@media (min-width: 900px) {
  /* comp column starts: 0.059 / 0.355 / 0.664 W - i.e. equal thirds, not a
     wider third column. */
  .site-footer__grid { grid-template-columns: repeat(3, 1fr); gap: var(--sp-8); }
}

.footer-phonetic {
  font-family: var(--ff-serif);
  font-size: var(--fs-md);
  margin-bottom: clamp(1.25rem, 3vw, 2.5rem);   /* comp 0.0545 W */
}
/* It works as the footer's logo. --fs-md bottoms out at its 20px floor on
   every screen under ~820px, so on phones and tablets it read as a caption.
   Below the desktop breakpoint it gets its own size: 26px on a phone, 28px
   on a tablet. The desktop size is the comp's and stays. min() keeps the
   floor from doubling under browser text zoom. */
@media (max-width: 899px) {
  .footer-phonetic { font-size: clamp(min(1.625rem, 9vw), 3.65vw, 1.75rem); }
}

.site-footer ul { margin: 0; padding: 0; list-style: none; }
.site-footer li + li { margin-top: 0.25rem; }   /* comp pitch 0.0213 W */

.footer-heading {
  font-family: var(--ff-display);
  font-size: inherit;                 /* comp: same size as the column text */
  font-weight: 700;
  letter-spacing: var(--ls-eyebrow);
  text-transform: uppercase;
  margin-bottom: 0.15rem;
}
/* FAQ is the one heading that is also a link. It inherits the heading's look
   rather than the footer link's, so the column still reads as headings and
   items — the underline on hover is the only thing that gives it away. */
.footer-heading a {
  color: inherit;
  text-decoration: none;
  padding-block: var(--sp-2);          /* keeps the 24px target of its siblings */
}
.footer-heading a:hover { text-decoration: underline; text-underline-offset: 0.2em; }
.footer-col + .footer-col { margin-top: 0.5rem; }   /* comp pitch 0.0240 W */

/* The comp breaks this after "…delivered to your". Measured at this size that
   line is 29.3ch and adding "inbox," takes it to 34.2ch, so 31ch puts the
   break where the comp puts it. */
.subscribe__intro { max-width: 31ch; }

.subscribe__form {
  display: flex;
  flex-wrap: wrap;
  gap: clamp(0.5rem, 1.04vw, 1rem);   /* comp 0.0104 W */
  margin-top: var(--sp-4);
}
/* comp: 103x45 at 1440 (0.0713 W x 0.0313 W). The global pill padding made
   it ~130px, which pushed it onto its own line. */
.subscribe__form .u-pill {
  min-height: clamp(38px, 3.13vw, 46px);
  padding-inline: clamp(0.875rem, 2.2vw, 2rem);
}

.subscribe__input {
  /* comp: 292x44 at 1440 = 0.2027 W. A large flex-basis makes the row WRAP
     (wrapping is decided on the basis, before shrinking), so keep the basis
     small and cap the grown width instead. */
  flex: 1 1 170px;
  max-width: clamp(180px, 19.8vw, 285px);
  min-height: clamp(38px, 3.3vw, 48px);   /* comp 0.0329 W */
  padding: var(--sp-2) var(--sp-4);
  border: 1px solid rgba(255, 255, 255, 0.35);
  border-radius: 999px;
  background: var(--c-white);
  color: var(--c-ink);
  font: inherit;
  font-size: var(--fs-sm);
}

.site-footer__legal {
  /* No divider rule: the comp has none. This border was invented. */
  margin-top: clamp(2rem, 6.2vw, 5.5rem);   /* comp 0.0617 W */
  font-size: clamp(0.75rem, 1.03vw, 0.9375rem);   /* comp 0.0103 W */
  opacity: 0.7;
}

/* --- Social — X removed, LinkedIn retained per the appendix ---------------- */
.social { display: flex; gap: var(--sp-4); margin-top: var(--sp-6); }
.social a {
  display: grid; place-items: center;
  width: 36px; height: 36px;
  border: 1px solid rgba(255, 255, 255, 0.35);
  border-radius: 50%;
}
.social a:hover { border-color: var(--c-lime); }

/* Helpers referenced by index.html (kept out of inline styles so they port
   cleanly into template files). */
.intro__paras { margin-top: var(--sp-8); }
.site-footer__inner {
  /* comp: 0.0385 W top, 0.0256 W bottom - it was --section-y (128px) both
     sides, which left a large dead area under the copyright. */
  padding-top: clamp(1.5rem, 3.2vw, 3rem);   /* measured ink lands at 0.0385 W */
  padding-bottom: clamp(1.5rem, 2.56vw, 2.5rem);
}

/* --- Pill chevron -------------------------------------------------------- */
.pill__chev { display: inline-block; }

/* --- Panel depth layer --------------------------------------------------- */
/* The comp's panels are flat navy with no photography, so there is nothing
   for "parallax panels of information" to act on. This is a soft tonal wash
   that trails the scroll — it reads as depth without inventing imagery.
   ⚠️ DESIGN DECISION, not in the comp. Flag it on the 17th.
   If a `background_image` is supplied per row, it layers behind this. */
.panel__glow {
  position: absolute;
  inset: -25% -10%;
  z-index: -1;
  pointer-events: none;
  /* Removed: the radial wash read as a gradient, and the client wants plain
     navy only. The layer stays so an optional background_image still
     parallaxes behind it. */
  background: none;
  will-change: transform;
}

/* Panels need a stacking context for the negative z-index layers to sit
   behind the copy but in front of the section ground. */
.panel > .u-wrap { position: relative; z-index: 1; }

/* --- Page head --------------------------------- shared: parts/page-head.php */
/* The comp uses this same band on Who we are, Our clients, How we work and
   Our thinking: navy, heading bottom-left, intro copy bottom-right. Shorter
   than the homepage hero. Build it once as a template part. */

.page-head {
  display: flex;
  align-items: flex-end;
  /* The comp makes this the SAME height as the homepage hero (0.56 W), not a
     shorter band. It was 52vh - viewport-HEIGHT relative - which gave 468px at
     1440x900 against the comp’s ~806px. */
  min-height: var(--hero-h);
  padding-top: var(--sp-24);
  /* NOT --hero-pb. The band is the same height as the homepage hero, but the
     comp sets its heading 0.0500 W above the bottom edge against the hero's
     0.0569 W - the smaller type sits closer to the floor. */
  padding-bottom: clamp(1.75rem, 4.18vw, 4.25rem);
  background: var(--c-navy);
  color: var(--c-white);
}
.page-head__grid {
  display: grid;
  gap: var(--sp-8);
  align-items: end;
}
@media (min-width: 900px) {
  /* comp: body column starts at 0.50 W and runs to 0.96 W */
  .page-head__grid {
    grid-template-columns: 46% 50%;
    justify-content: space-between;
    gap: var(--sp-6);
  }
}
.page-head__title {
  color: var(--c-cyan);
  /* comp cap 0.0283 W -> ~54px at 1440 */
  /* One step DOWN from the homepage hero. The hero stays the largest type on
     the site; section heads sit under it. The width still lets the comp break
     land - "TACTICAL SUPPORT" fits one line, "STRATEGIC & TACTICAL" does not. */
  font-size: clamp(min(1.75rem, 13vw), 3.77vw, 3.55rem);
  /* Measured, not inherited: the comp sets the two lines 0.0462 W apart, and
     --lh-snug gave 0.0389 - tight enough that the two lines read as one mass. */
  line-height: 1.22;
  max-width: 20ch;
  text-wrap: wrap;
}
.page-head__intro {
  /* comp 0.0174 W ≈ 25px at 1440 - it was inheriting --fs-base (23px), so the
     rag sat ~50px short of the right margin. */
  font-size: clamp(min(1rem, 5vw), 1.74vw, 1.625rem);
  /* Comp line pitch is 0.0224 W. --lh-copy (1.45) gives 0.0250 - 12% loose,
     which put the nine lines ~37px taller than the comp at 1440. */
  line-height: 1.29;
}
/* comp: 0.0432 W between the last line of one paragraph and the first of the
   next, against a 0.0224 W line pitch - so the gap itself is 0.0208 W, not the
   16px of --sp-4. */
.page-head__intro > p + p { margin-top: 1.2em; }

/* --- FAQ ----------------------------------------------- page-faq.php ---- */
/* The comp does not design this page — p.5 col.5 is the 30th mock with an
   annotation box on it. Built from the brief instead: a long-form page whose
   VALUE IS ITS STRUCTURE, because it is aimed at AI retrieval. So the styling
   does one job — make a deep heading hierarchy legible at a glance:
   section title > question > answer, each a clear step apart. */

/* Constrain the CHILDREN, not the wrap. A max-width on `.u-wrap` centres the
   whole column, which puts the text a third of the way across the page — the
   post template left-aligns its long-form to the content edge and this should
   match it. */
.faq__col > * { max-width: 46rem; }

.faq__intro {
  margin: 0;
  max-width: 34ch;
  color: var(--c-blue);
  font-size: var(--fs-md);
  font-weight: 600;
  line-height: var(--lh-snug);
  letter-spacing: var(--ls-heading);
}
.faq__intro a { color: inherit; text-underline-offset: 0.18em; }

/* Contents, deliberately NOT a sticky rail — the post template dropped its
   left rail at the client's request, and a sidebar here would read as putting
   it back. A plain ruled list at the top of the column does the same job. */
.faq__contents {
  margin-top: clamp(2rem, 4vw, 3.5rem);
  padding: clamp(1.25rem, 2vw, 1.75rem) 0;
  border-top: 1px solid var(--c-rule);
  border-bottom: 1px solid var(--c-rule);
}
.faq__contents-title {
  margin: 0 0 var(--sp-4);
  color: var(--c-ink-soft);
  font-family: var(--ff-display);
  font-size: clamp(0.75rem, 0.9vw, 0.875rem);
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}
.faq__contents ol {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-3) var(--sp-8);
  margin: 0;
  padding: 0;
  list-style: none;
  counter-reset: faq;
}
.faq__contents li { counter-increment: faq; }
.faq__contents a {
  /* inline-block + padding, because these are NAVIGATION. An inline link's box
     is its font's content area — 21px at this size — regardless of
     line-height, which is under the 24px minimum. The links inside the answer
     prose below are exempt: WCAG 2.5.8 excludes targets in a sentence. */
  display: inline-block;
  padding-block: var(--sp-2);
  color: var(--c-blue);
  font-family: var(--ff-display);
  font-size: clamp(0.9375rem, 1.2vw, 1.125rem);
  font-weight: 600;
  text-decoration: none;
}
.faq__contents a::before {
  content: counter(faq) ".";
  margin-right: 0.45em;
  color: var(--c-ink-soft);
  font-weight: 400;
}
.faq__contents a:hover { color: var(--c-navy); text-decoration: underline; text-underline-offset: 0.18em; }

.faq__section {
  /* clears the fixed header when a contents link jumps here */
  scroll-margin-top: clamp(5rem, 9vw, 8rem);
  margin-top: clamp(3rem, 6.5vw, 6rem);
}
.faq__section-title {
  margin: 0 0 clamp(1.5rem, 2.6vw, 2.5rem);
  padding-bottom: var(--sp-4);
  border-bottom: 2px solid var(--c-blue);
  color: var(--c-blue);
  font-family: var(--ff-display);
  font-size: clamp(1.375rem, 2.2vw, 2.1rem);
  font-weight: 600;
  line-height: 1.2;
  letter-spacing: var(--ls-heading);
}

.faq__item + .faq__item {
  margin-top: clamp(1.75rem, 3vw, 2.75rem);
  padding-top: clamp(1.75rem, 3vw, 2.75rem);
  border-top: 1px solid var(--c-rule);
}
.faq__q {
  margin: 0 0 var(--sp-4);
  color: var(--c-navy);
  font-family: var(--ff-display);
  font-size: clamp(1.0625rem, 1.5vw, 1.4375rem);
  font-weight: 600;
  line-height: 1.3;
  letter-spacing: var(--ls-heading);
  text-wrap: balance;
}
.faq__a p,
.faq__a ul {
  margin: 0;
  font-size: clamp(0.9375rem, 1.32vw, 1.25rem);
  line-height: var(--lh-body);
  color: var(--c-ink);
}
/* `*` contributes nothing to specificity, so `.faq__a > * + *` is (0,1,0) and
   loses to `.faq__a p` at (0,1,1) — the reset above would win and the answers
   would run together with no gap. Each pair is named so it outranks it. */
.faq__a p + p,
.faq__a p + ul,
.faq__a ul + p { margin-top: var(--sp-4); }
.faq__a ul { padding-left: 1.2em; }
.faq__a li + li { margin-top: var(--sp-3); }
.faq__a a { color: var(--c-blue); text-underline-offset: 0.18em; }
/* A link that IS the whole sentence has no surrounding text to be exempted
   by, so it gets a real target. The links sitting inside a paragraph of prose
   do not — padding those would break the leading. */
.faq__more { display: inline-block; padding-block: var(--sp-2); }

/* An unanswered question, marked as such on the page rather than quietly
   filled with something plausible. */
.faq__todo {
  padding-left: var(--sp-4);
  border-left: 2px solid var(--c-rule);
  color: var(--c-ink-soft);
  font-style: italic;
}

.faq__note {
  margin-top: clamp(3rem, 6vw, 5.5rem);
  padding: clamp(1.25rem, 2.4vw, 2.25rem);
  background: var(--c-surface-alt);
  border-left: 3px solid var(--c-blue);
}
.faq__note p {
  margin: 0;
  color: var(--c-ink-soft);
  font-size: clamp(0.875rem, 1.1vw, 1.0625rem);
  line-height: 1.6;
}
.faq__note p + p { margin-top: var(--sp-4); }
/* `.faq__note p` is (0,2,1) because of the type selector, so a bare
   `.faq__note-title` at (0,1,0) loses the colour. Matched shape, not
   !important — the same trap the post body hit. */
.faq__note p.faq__note-title {
  color: var(--c-blue);
  font-family: var(--ff-display);
  font-weight: 700;
}

/* --- Case studies ------------------------- page-case-study-*.php (PHASE 2) */
/* Comp p.5, columns 2-4. All three pages are identical but for one word, and
   all three reuse the HOMEPAGE PANEL treatment for the hero — which is the
   point of them: each panel lands on its own page and finishes its sentence.

   Measured off the comp, as fractions of page width W:
     hero band     0 -> 0.3146      eyebrow y 0.1525, pitch 0.0248
     headline      y 0.2145, cap 0.0543
     body band     0.3165 -> 1.0734,  lead ink 0.3651
     left column   0.0505 -> ~0.50   right column starts 0.577
     cards band    1.0763 -> 1.5033,  cards 0.2803 W at 9:8, gap 0.0285 */

.case-hero {
  display: flex;
  align-items: flex-end;
  min-height: clamp(13rem, 31.46vw, 34.8rem);
  padding-top: var(--sp-24);
  /* comp leaves 0.0458 W under the headline ink */
  padding-bottom: clamp(1.5rem, 3.9vw, 4rem);
  background: var(--c-navy);
  color: var(--c-white);
}
.case-hero__eyebrow {
  color: var(--c-white);
  /* SMALLER than --fs-eyebrow: the comp sets this at cap 0.0114 W (~23px at
     1440) against the eyebrow token's 30px, and tracks it wider. */
  font-size: clamp(0.8125rem, 1.583vw, 1.5rem);
  letter-spacing: 0.17em;
  /* comp line pitch 0.0248 W against a 0.0114 W cap — 1.57, much looser than
     --lh-snug. Two lines of tracked uppercase need the air. */
  line-height: 1.57;
  /* Two lines, breaking after "design" as the comp does. At 26ch it took
     three, which pushed the whole bottom-aligned block up 44px. */
  max-width: 34ch;
}
.case-hero__title {
  margin-top: var(--sp-4);
  color: var(--c-cyan);
  /* comp cap 0.0543 W — the panel size, not the page-head size */
  font-size: var(--fs-3xl);
}

/* The comp's white band runs to 0.7579 W — a third of it empty below the
   copy, because the aside content that would fill it does not exist yet.
   Matched at first; the client asked for it balanced instead, so the band
   keeps --u-band's symmetric padding and will grow on its own once the aside
   is written. */
.case-body__grid {
  display: grid;
  gap: clamp(2rem, 5vw, 4.5rem);
}
@media (min-width: 900px) {
  /* comp: the copy column ends at ~0.50 W and the aside starts at 0.577 W */
  .case-body__grid {
    grid-template-columns: 52% 41.4%;
    justify-content: space-between;
    align-items: start;
    gap: var(--sp-8);
  }
}
/* Grid children default to min-width:auto, which lets a long unbroken word
   push the column wider than its track. */
.case-body__main,
.case-aside { min-width: 0; }

.case-body__copy { margin-top: clamp(1.5rem, 3.2vw, 3rem); }
.case-body__copy p + p { margin-top: var(--sp-4); }

.case-aside__title {
  margin: 0;
  color: var(--c-blue);
  font-family: var(--ff-display);
  font-size: var(--fs-md);
  font-weight: 600;
  line-height: var(--lh-snug);
  letter-spacing: var(--ls-heading);
}
/* A short rule over a tracked label — the same opening move the featured lead
   on the blog uses, so the two read as one system. */
.case-aside__eyebrow {
  position: relative;
  margin: 0 0 var(--sp-6);
  padding-top: var(--sp-5);
  color: var(--c-blue);
  font-family: var(--ff-display);
  font-size: clamp(0.75rem, 0.95vw, 0.9375rem);
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}
.case-aside__eyebrow::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  width: clamp(2.5rem, 4vw, 4rem);
  height: 3px;
  background: var(--c-blue);
}

.case-aside__lead,
.case-aside__note {
  max-width: 40ch;
  color: var(--c-ink-soft);
  font-size: clamp(0.875rem, 1.05vw, 1rem);
  line-height: 1.55;
}
.case-aside__lead { margin: var(--sp-5) 0 0; }
.case-aside__note { margin: var(--sp-5) 0 0; }

/* The brief's three lines, quoted, as a ruled list with a status column.
   The status is the point: two are built, one is the gap, and putting that in
   its own column makes it scannable instead of buried in a paragraph. */
.case-aside__list {
  margin: clamp(1.5rem, 2.4vw, 2.25rem) 0 0;
  padding: 0;
  list-style: none;
  border-top: 1px solid var(--c-rule);
}
.case-aside__list li {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--sp-4);
  padding-block: clamp(0.7rem, 1.1vw, 1rem);
  border-bottom: 1px solid var(--c-rule);
}
.case-aside__item {
  color: var(--c-ink);
  font-size: clamp(0.875rem, 1.05vw, 1rem);
  line-height: 1.4;
}
.case-aside__state {
  flex: none;
  color: var(--c-blue);
  font-family: var(--ff-display);
  /* floor was 0.625rem — 10px, under the 11px readability floor the audit
     enforces, and it hit that floor on every screen below 1080px. */
  font-size: clamp(min(0.75rem, 4vw), 0.85vw, 0.8125rem);
  font-weight: 700;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  white-space: nowrap;
}
.case-aside__state--open { color: var(--c-ink-soft); }

.case-articles {
  background: var(--c-navy);
  color: var(--c-white);
  /* comp: heading ink 0.0438 W below the band top, 0.0877 W under the cards */
  padding-top: clamp(2rem, 5.2vw, 6rem);
  padding-bottom: clamp(2.5rem, 7.4vw, 8.5rem);
}
.case-articles__title {
  margin: 0 0 clamp(1.5rem, 3.4vw, 3.25rem);
  font-family: var(--ff-display);
  font-size: clamp(1.125rem, 1.9vw, 1.85rem);
  font-weight: 600;
  letter-spacing: var(--ls-heading);
}

/* --- 30th Celebration ------------------------------- page-30-years.php -- */
/* Comp p.5, column 1. The whole page is navy from the header to the
   conversation band, the lockup is centred near the top, and everything else
   sits in a column of 0.63 W - narrower than the site's usual 0.899 W. */

.celebration { background: var(--c-navy); color: var(--c-white); }

.celebration__hero {
  /* comp: CELEBRATING's ink starts 0.2007 W down the page */
  padding-top: clamp(7rem, 20.15vw, 35rem);
  padding-bottom: clamp(3rem, 8vw, 9rem);
  text-align: center;
}

/* The comp's content column, centred: 0.1795 W -> 0.8073 W. */
.celebration__col {
  max-width: 62.9vw;
  min-width: 0;
}
@media (max-width: 1100px) { .celebration__col { max-width: none; } }

.celebration__block { padding-block: clamp(2.5rem, 6vw, 7rem); }
.celebration__block--alt { padding-block: clamp(3rem, 7.5vw, 9rem); }

.celebration__eyebrow {
  color: var(--c-cyan);
  margin-bottom: clamp(1.5rem, 3vw, 3rem);
}

/* Inverted, and about 1.86x the homepage lockup — measured, not eyeballed:
   comp cap heights are 0.0176 / 0.1429 / 0.0388 W against 0.0104 / 0.0769 /
   0.0216 on the homepage. */
.anniversary--hero { margin-inline: auto; }
.anniversary--hero .anniversary__label {
  color: var(--c-white);
  font-size: clamp(min(1rem, 7vw), 2.30vw, 2.45rem);
  letter-spacing: 0.23em;
}
.anniversary--hero .anniversary__number {
  color: var(--c-white);
  font-size: clamp(min(6rem, 30vw), 19.1vw, 20rem);
  /* comp gap CELEBRATING ink -> 30 ink is 0.0257 W here, against 0.0194 at
     the shared rule's 0.05em. Scoped, so the homepage lockup is untouched. */
  margin-top: 0.083em;
  /* The shared rule cancels the numerals' trailing letter-space with
     margin-right:-0.01em. At 1.4px on the homepage that is invisible; at this
     size it is 2.75px, and it makes the glyphs overflow .anniversary's
     max-content box — a real 3px spill above 1280px. Dropping it moves the
     measured centre by about a pixel (0.4969 -> 0.4962 W against the comp's
     0.4993), which is well inside the noise. */
  margin-right: 0;
}
.anniversary--hero .anniversary__years {
  color: var(--c-white);
  font-size: clamp(min(1.6rem, 8vw), 5.03vw, 5.4rem);
  letter-spacing: 0.30em;
  margin-top: 0.56em;                          /* comp gap 0.0286 W */
}
.anniversary--hero .anniversary__tag {
  color: var(--c-cyan);
  font-size: clamp(min(1rem, 5vw), 1.74vw, 1.625rem);
  font-weight: 600;
  margin-top: 1.1em;
}

/* --- The film ----------------------------------------------------------- */

.video { margin: 0; }
.video__player {
  display: block;
  width: 100%;
  height: auto;
  aspect-ratio: 16 / 9;
  /* was a one-off darker hex; the deep token is within 6/255 of it and keeps
     every navy in tokens.css. Only visible as letterbox behind the poster. */
  background: var(--c-navy-deep);
  /* A hairline rather than a shadow: the page is already navy on navy, and a
     shadow on a dark ground reads as smudge. */
  outline: 1px solid rgba(255, 255, 255, 0.22);
  outline-offset: -1px;
}
.video__caption {
  margin-top: var(--sp-4);
  color: var(--c-panel-copy);
  font-size: clamp(0.875rem, 1.1vw, 1.0625rem);
  line-height: 1.5;
  max-width: 52ch;
}

/* --- Timeline ------------------------ ACF: `timeline` repeater --------- */
/* Premium comes from type and structure, not motion: the spec keeps this to
   one restrained reveal per entry and rules out scroll-scrubbing by name.

   Desktop: the year gets its own column, set large and LIGHT (Manrope is a
   variable face, 200-800), so the dates read as the spine of the page and
   the 600-weight titles do the talking beside them. The rule runs between
   the two columns, marker to marker, and every marker is centred on its
   year's line so year, marker and title share one axis.
   Phones and tablets: one column, rule on the left, year above the title.

   --tl-x    where the rule sits
   --tl-yfs  year font-size - the marker and title are aligned to it
   --tl-tfs  title font-size                                                  */

.timeline {
  --tl-x: 7px;                      /* ring sits inside the column, not on the gutter */
  --tl-gap: clamp(1.75rem, 7vw, 2.5rem);
  --tl-yfs: clamp(2.25rem, 10vw, 3rem);
  --tl-tfs: clamp(1.25rem, 5.2vw, 1.5rem);
  position: relative;
  list-style: none;
  margin: 0;
  padding: 0;
}

.timeline__item {
  position: relative;
  padding: 0 0 clamp(3rem, 7vw, 6.5rem) calc(var(--tl-x) + var(--tl-gap));
}
.timeline__item:last-child { padding-bottom: 0; }

/* The rule: drawn per entry, from this marker's centre to the next one's, so
   it starts and ends ON a marker instead of trailing off above the first or
   below the last. The next entry's marker paints over the join. */
.timeline__item:not(:last-child)::after {
  content: "";
  position: absolute;
  left: var(--tl-x);
  top: calc(var(--tl-yfs) / 2);
  bottom: calc(var(--tl-yfs) / -2);
  width: 1px;
  transform: translateX(-0.5px);
  background: rgba(255, 255, 255, 0.24);
}

/* Marker: a ring on the navy, with a faint halo. */
.timeline__item::before {
  content: "";
  position: absolute;
  z-index: 1;
  left: var(--tl-x);
  top: calc(var(--tl-yfs) / 2);
  width: 13px;
  height: 13px;
  margin: -6.5px 0 0 -6.5px;
  box-sizing: border-box;
  border: 2px solid var(--c-cyan);
  border-radius: 50%;
  background: var(--c-navy);
  box-shadow: 0 0 0 6px rgba(120, 224, 255, 0.08);
}
/* The last entry is the present - 2026 - so its marker is lit. */
.timeline__item:last-child::before {
  width: 15px;
  height: 15px;
  margin: -7.5px 0 0 -7.5px;
  background: var(--c-cyan);
  box-shadow: 0 0 0 7px rgba(120, 224, 255, 0.14),
              0 0 28px rgba(120, 224, 255, 0.55);
}

.timeline__year {
  margin: 0;
  color: var(--c-cyan);
  font-family: var(--ff-display);
  font-size: var(--tl-yfs);
  font-weight: 300;
  line-height: 1;
  letter-spacing: -0.03em;
  font-variant-numeric: tabular-nums lining-nums;
}
/* An entry with no confirmed year shows a dash, and it steps back rather than
   competing with the real dates. ACF: empty `year` field -> this modifier. */
.timeline__year--tbc { color: rgba(120, 224, 255, 0.38); }

.timeline__title {
  margin: clamp(0.75rem, 1.4vw, 1.1rem) 0 0;
  color: var(--c-white);
  font-family: var(--ff-display);
  font-size: var(--tl-tfs);
  font-weight: 600;
  line-height: 1.2;
  letter-spacing: var(--ls-heading);
}
.timeline__body {
  margin: var(--sp-3) 0 0;
  max-width: 46ch;
  color: var(--c-panel-copy);
  font-size: clamp(0.9375rem, 1.25vw, 1.1875rem);
  line-height: var(--lh-body);
}

@media (min-width: 900px) {
  .timeline {
    --tl-gap: clamp(2.5rem, 4vw, 4.5rem);
    /* The year column is sized FROM the year: four tabular digits at weight
       300 and -0.03em measure 2.37em, so 2.5em always holds them. A % of the
       list width did not - the year scales with the viewport, the list with
       its column, and from 1280px up the digits overran into the gap. */
    --tl-x: calc(var(--tl-yfs) * 2.5 + var(--tl-gap));
    --tl-yfs: clamp(3.25rem, 5.4vw, 5.75rem);
    --tl-tfs: clamp(1.5rem, 2.25vw, 2.25rem);
  }
  .timeline__item {
    display: grid;
    grid-template-columns: 1fr;
    align-content: start;
  }
  /* Year pulled out into the column left of the rule, set flush to it. */
  .timeline__year {
    position: absolute;
    top: 0;
    left: 0;
    width: calc(var(--tl-x) - var(--tl-gap));
    text-align: right;
  }
  /* Title centred on the year's line - the same axis as the marker. */
  .timeline__title {
    margin-top: calc((var(--tl-yfs) - var(--tl-tfs) * 1.2) / 2);
  }
}

/* --- Blog archive --------------------------- home.php / archive.php ----- */
/* ⚠️ The comp does not design this page. Page 4 gives the head and the word
   BLOG, then an annotation. Everything here is built from the written brief -
   "simplify, get rid of a bunch of stuff, the type hierarchy is kind of
   clunky" - in the language the rest of the site already establishes. */

/* The comp's head for this page is SHORTER than the others: 0.3147 W against
   0.5623 W, and it carries no intro column.
   .page-head--no-intro takes the same height: a head whose optional intro is
   empty is the same case as this one - a title alone - and the full 0.56 W
   band around a single heading is mostly empty navy. */
.page-head--short,
.page-head--no-intro {
  min-height: clamp(13rem, 31.47vw, 34.8rem);
  /* comp leaves 0.0440 W under the title ink here, against 0.0500 W on the
     tall heads - the band is shorter, so the type sits closer to its floor. */
  padding-bottom: clamp(1.5rem, 3.63vw, 3.7rem);
}

/* The comp puts a "BLOG" label here, 0.0783 W below the navy band. Dropped at
   the client's request — the page head already says "Our thinking" and the
   label repeated it. Without that anchor the band goes back to the site's
   standard section rhythm (--section-y) rather than the measured offset. */

/* Section labels — "All articles", "Keep reading". Sized from the comp's
   BLOG: cap 0.0179 W, in --c-blue. */
.section-label {
  color: var(--c-blue);
  font-family: var(--ff-display);
  font-size: clamp(1.25rem, 2.38vw, 2.2rem);
  font-weight: 600;
  letter-spacing: var(--ls-eyebrow);
  text-transform: uppercase;
  margin: 0 0 clamp(1.5rem, 3.5vw, 3.5rem);
}

/* --- Featured lead ------------------------------------------------------ */
/* An editorial split rather than a big card: photo on one side, copy on the
   other, set on the type scale the rest of the site uses and closed with the
   same lime pill. The hierarchy IS the feature — a featured section that lays
   out like the grid below it is just the top row again, and the new tag buys
   nothing. */

.flead {
  display: grid;
  gap: clamp(1.5rem, 3vw, 4rem);
  color: inherit;
  text-decoration: none;
}
@media (min-width: 900px) {
  .flead {
    grid-template-columns: 57% 1fr;
    align-items: center;
    gap: clamp(2rem, 5vw, 5.5rem);
  }
}
.flead__media {
  display: block;
  overflow: hidden;
  background: var(--c-navy);
  /* A real ratio, so the photo is composed rather than cropped to whatever
     height the column next to it happens to be. */
  aspect-ratio: 3 / 2;
}
.flead__media img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 700ms var(--ease-out);
}
.flead:hover .flead__media img,
.flead:focus-visible .flead__media img { transform: scale(1.03); }

.flead__body { display: block; }

/* A short rule above the label — the one piece of ornament on the page, and
   it is what makes the block read as a feature rather than a first row. */
.flead__eyebrow {
  display: block;
  position: relative;
  padding-top: var(--sp-6);
  color: var(--c-blue);
  font-family: var(--ff-display);
  font-size: clamp(0.75rem, 0.95vw, 0.9375rem);
  font-weight: 700;
  letter-spacing: 0.16em;
  text-transform: uppercase;
}
.flead__eyebrow::before {
  content: "";
  position: absolute;
  top: 0;
  left: 0;
  width: clamp(2.5rem, 4vw, 4rem);
  height: 3px;
  background: var(--c-blue);
}
.flead__title {
  margin: var(--sp-4) 0 0;
  color: var(--c-blue);
  font-family: var(--ff-display);
  font-size: clamp(1.5rem, 2.85vw, 2.75rem);
  font-weight: 600;
  line-height: 1.16;
  letter-spacing: var(--ls-heading);
  text-wrap: balance;
}
.flead:hover .flead__title,
.flead:focus-visible .flead__title { color: var(--c-navy); }
.flead__meta {
  display: block;
  margin-top: var(--sp-4);
  color: var(--c-ink-muted);
  font-size: clamp(0.8125rem, 1.02vw, 1rem);
}
.flead .u-pill { margin-top: clamp(1.5rem, 2.4vw, 2.25rem); }

/* --- Featured pair, and the related row on a post ----------------------- */

.featured {
  display: grid;
  gap: clamp(1.5rem, 3vw, 2.75rem);
}
.featured--pair { margin-top: clamp(2.5rem, 5.5vw, 6rem); }
@media (min-width: 700px) {
  .featured--pair { grid-template-columns: repeat(2, 1fr); gap: clamp(1.5rem, 3.4vw, 3.5rem); }
}

.fcard {
  display: block;
  color: inherit;
  text-decoration: none;
  min-width: 0;
}
.fcard__media {
  display: block;
  overflow: hidden;              /* clips the hover scale */
  background: var(--c-navy);     /* holds the space before the image decodes */
  aspect-ratio: 16 / 9;
}
.fcard__media img {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform var(--dur-slow, 600ms) var(--ease-out);
}
.fcard:hover .fcard__media img,
.fcard:focus-visible .fcard__media img { transform: scale(1.03); }

.fcard__title {
  margin: var(--sp-3) 0 0;
  color: var(--c-blue);
  font-family: var(--ff-display);
  font-size: clamp(1.125rem, 1.65vw, 1.6rem);
  font-weight: 600;
  line-height: 1.25;
  letter-spacing: var(--ls-heading);
  text-wrap: balance;
}
.fcard:hover .fcard__title,
.fcard:focus-visible .fcard__title { color: var(--c-navy); }

.fcard__meta {
  margin: var(--sp-3) 0 0;
  color: var(--c-ink-muted);
  font-size: clamp(0.8125rem, 1.02vw, 1rem);
  line-height: 1.4;
}
.fcard__meta > span,
.fcard__meta > time { white-space: nowrap; }

/* --- Archive tools: category filter + search ---------------------------- */
/* Filters left, search right, on one row that wraps to two on a phone. */

.archive-tools {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-4) var(--sp-8);
  margin-bottom: clamp(1.75rem, 3.2vw, 3rem);
}
.filters {
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-2);
}
.filter {
  min-height: 40px;
  padding: var(--sp-2) var(--sp-4);
  border: 1px solid var(--c-rule);
  border-radius: 999px;
  background: transparent;
  color: var(--c-ink-muted);
  font-family: var(--ff-display);
  font-size: clamp(0.8125rem, 0.95vw, 0.9375rem);
  font-weight: 600;
  line-height: 1.2;
  cursor: pointer;
  transition: color var(--dur-fast) var(--ease-out),
              border-color var(--dur-fast) var(--ease-out),
              background var(--dur-fast) var(--ease-out);
}
.filter:hover { color: var(--c-blue); border-color: var(--c-blue); }
/* The active filter is filled, not outlined — the one state that has to read
   at a glance. Lime stays reserved for the CTA pill. */
.filter.is-active,
.filter[aria-pressed="true"] {
  background: var(--c-navy);
  border-color: var(--c-navy);
  color: var(--c-white);
}

.archive-search { flex: 0 1 16rem; }
.archive-search__input {
  width: 100%;
  min-height: 40px;
  padding: var(--sp-2) var(--sp-4);
  border: 1px solid var(--c-rule);
  border-radius: 999px;
  background: var(--c-surface);
  color: var(--c-ink);
  font-family: var(--ff-body);
  font-size: clamp(0.875rem, 1vw, 1rem);
}
.archive-search__input::placeholder { color: var(--c-ink-muted); }
.archive-search__input:focus-visible { border-color: var(--c-blue); outline-offset: 1px; }

.archive-empty {
  margin: clamp(2rem, 4vw, 3.5rem) 0 0;
  color: var(--c-ink-muted);
  font-size: var(--fs-base);
}
.archive-empty .filter { margin-left: var(--sp-3); }

/* --- Archive tiles ------------------------------------------------------ */
/* The live site's card layout, toned down: ONE navy scrim on every tile
   instead of a different colour per card, a single type size, and no author
   line (every post is Jeanie's). The gradient is stronger at the foot, where
   the type sits, and lighter at the head so the photograph still reads. */

.tile-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(15rem, 100%), 1fr));
  gap: clamp(1rem, 1.7vw, 1.75rem);
  list-style: none;
  margin: 0;
  padding: 0;
}
@media (min-width: 900px) { .tile-grid { grid-template-columns: repeat(3, 1fr); } }

/* Explicit, because .tile carries its own display and would otherwise beat
   the UA sheet's [hidden] rule when the filter hides a card. */
.tile[hidden] { display: none; }

.tile a {
  position: relative;
  display: block;
  overflow: hidden;
  aspect-ratio: 16 / 9;
  background: var(--c-navy);
  color: var(--c-white);
  text-decoration: none;
}
.tile img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform 700ms var(--ease-out);
}
.tile a::after {
  content: "";
  position: absolute;
  inset: 0;
  /* Flat navy, not a gradient: the client wants plain blue only. The navy
     comes from the token, so it follows --c-navy. */
  background: color-mix(in srgb, var(--c-navy) 82%, transparent);
  transition: opacity var(--dur-base) var(--ease-out);
}
.tile a:hover img,
.tile a:focus-visible img { transform: scale(1.04); }
.tile a:hover::after,
.tile a:focus-visible::after { opacity: 0.86; }

.tile__body {
  position: absolute;
  inset: auto 0 0 0;
  z-index: 1;
  display: block;
  padding: clamp(1rem, 1.5vw, 1.5rem);
}
.tile__title {
  display: block;
  font-family: var(--ff-display);
  font-size: clamp(0.9375rem, 1.18vw, 1.1875rem);
  font-weight: 600;
  line-height: 1.3;
  letter-spacing: var(--ls-heading);
}
.tile__meta {
  display: block;
  margin-top: var(--sp-2);
  color: var(--c-panel-copy);
  font-size: clamp(0.75rem, 0.88vw, 0.875rem);
  line-height: 1.4;
}

/* The case-study variant: taller card (comp 9:8, against 16:9 on the
   archive), title sitting in the middle rather than at the foot, and a credit
   row pinned to the bottom — byline left, reading time in a chip on the
   right. Same tile, three declarations different. */
/* comp: cards 0.2803 W with a 0.0285 W gap, which is wider than the archive's */
.tile-grid--three {
  grid-template-columns: repeat(auto-fill, minmax(min(15rem, 100%), 1fr));
  gap: clamp(1rem, 2.85vw, 3.1rem);
}
@media (min-width: 900px) { .tile-grid--three { grid-template-columns: repeat(3, 1fr); } }

.tile--credit a {
  display: flex;
  flex-direction: column;
  justify-content: center;
  aspect-ratio: 9 / 8;
}
.tile--credit .tile__body {
  position: static;
  /* Two rows: the title centres in whatever space is left, the credit line
     sits on the floor. Flex with margin-top:auto pinned the credit correctly
     but left the title jammed against the top edge — the comp has it around
     the middle. */
  display: grid;
  grid-template-rows: 1fr auto;
  flex: 1;
  padding: clamp(1.1rem, 1.8vw, 1.75rem);
}
.tile--credit .tile__title { align-self: center; }
.tile--credit .tile__title {
  font-size: clamp(1rem, 1.32vw, 1.375rem);
  line-height: 1.28;
}
.tile__credit {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--sp-3);
  margin-top: auto;
  padding-top: clamp(1rem, 2vw, 2rem);
}
.tile__by {
  color: var(--c-white);
  font-family: var(--ff-display);
  font-size: clamp(0.6875rem, 0.82vw, 0.8125rem);
  font-weight: 600;
}
.tile__read {
  flex: none;
  padding: 0.35em 0.85em;
  border-radius: 999px;
  background: rgba(255, 255, 255, 0.18);
  color: var(--c-white);
  font-family: var(--ff-display);
  font-size: clamp(0.6875rem, 0.82vw, 0.8125rem);
  font-weight: 600;
  white-space: nowrap;
}

.pagination {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--sp-4);
  margin-top: clamp(2rem, 4vw, 4rem);
  font-family: var(--ff-display);
  font-weight: 600;
}
.pagination a { color: var(--c-blue); text-decoration: none; padding: var(--sp-2); }
.pagination a:hover { color: var(--c-navy); }
.pagination__current {
  color: var(--c-ink);
  padding: var(--sp-2);
  border-bottom: 2px solid var(--c-lime);
}
.pagination__next { margin-left: auto; letter-spacing: 0.06em; }

/* --- Single post ------------------------------------------- single.php -- */

.post-hero {
  position: relative;
  display: flex;
  align-items: flex-end;
  min-height: clamp(20rem, 42vw, 46rem);
  padding-top: var(--sp-24);
  padding-bottom: clamp(2rem, 5vw, 5rem);
  /* The site navy's darker step, on client request: this hero should read
     darker than the flat navy bands, even under a bright photo. */
  background: var(--c-navy-deep);
  color: var(--c-white);
  overflow: hidden;
}
.post-hero__img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* A FIXED scrim, not a tint baked into the photo. The live post darkens the
     image so far that the people in it are barely legible, and the amount
     varies per upload; a constant overlay keeps the type contrast predictable
     whatever the editor uploads.
     0.15 over --c-navy-deep (was 0.42 over --c-navy): the client asked for
     a darker hero, the same blue with the photo only as texture. */
  opacity: 0.15;
}
.post-hero__inner { position: relative; z-index: 1; }
.post-hero__cat {
  color: var(--c-cyan);
  font-size: clamp(0.8125rem, 1.05vw, 1.0625rem);
  letter-spacing: 0.14em;
}
.post-hero__title {
  margin: var(--sp-4) 0 0;
  max-width: 20ch;
  font-family: var(--ff-display);
  font-size: clamp(min(1.75rem, 13vw), 3.77vw, 3.55rem);
  font-weight: var(--wt-display);
  line-height: 1.15;
  letter-spacing: var(--ls-heading);
  text-wrap: balance;
}
.post-hero__meta {
  margin: var(--sp-6) 0 0;
  color: var(--c-cyan);
  font-size: clamp(0.875rem, 1.1vw, 1.0625rem);
}

/* Post body. "Clunky" is fixed with FEWER sizes and more space, per the
   templates doc - three sizes total, one measure, generous top margins. */
.post-body .u-wrap > * { max-width: var(--measure); }
.post-body p,
.post-body ul,
.post-body ol {
  font-size: var(--fs-base);
  line-height: var(--lh-body);
  margin-block: 0 var(--sp-6);
}
.post-body ul, .post-body ol { padding-left: 1.2em; }
.post-body li + li { margin-top: var(--sp-3); }
.post-body h2 {
  font-family: var(--ff-display);
  font-size: var(--fs-xl);
  font-weight: 600;
  line-height: 1.2;
  letter-spacing: var(--ls-heading);
  color: var(--c-blue);
  margin: var(--sp-16) 0 var(--sp-6);
}
.post-body h3 {
  font-family: var(--ff-display);
  font-size: var(--fs-md);
  font-weight: 600;
  line-height: 1.3;
  letter-spacing: var(--ls-heading);
  color: var(--c-navy);
  margin: var(--sp-12) 0 var(--sp-4);
}
.post-body > .u-wrap > *:first-child { margin-top: 0; }
.post-body a { color: var(--c-blue); }

/* Figures break the measure — they are the "occasional graphic", and if they
   sit inside the text column they read as an illustration of one paragraph
   rather than a break in the article. 56rem was NARROWER than the 68ch
   measure, so the first version did the opposite of this comment. */
/* `.post-body .u-wrap > *` is (0,2,0) and would beat a plain `.post-body
   figure` (0,1,1) whatever the source order, so this has to match the same
   shape to win. */
.post-body .u-wrap > figure {
  max-width: min(100%, 64rem);
  margin: var(--sp-12) 0;
}
.post-body figure img { display: block; width: 100%; height: auto; }
.post-body figcaption {
  margin-top: var(--sp-3);
  color: var(--c-ink-muted);
  font-size: clamp(0.8125rem, 1.02vw, 1rem);
  line-height: 1.5;
}

/* The existing posts open with a boxed Overview. It is editor markup, not a
   widget, so it survives the simplification. */
.callout {
  background: #DCEBF7;
  padding: clamp(1.25rem, 2.4vw, 2.25rem);
  margin-bottom: var(--sp-8);
}
/* Scoped, because `.post-body h2` carries a type selector and would otherwise
   outrank a bare `.callout__title` and push this heading 64px down inside its
   own box. */
.post-body .callout__title {
  margin: 0 0 var(--sp-4);
  padding-bottom: var(--sp-3);
  border-bottom: 1px solid color-mix(in srgb, var(--c-navy) 25%, transparent);
  color: var(--c-blue);
  font-family: var(--ff-display);
  font-size: clamp(1.125rem, 1.65vw, 1.6rem);
  font-weight: 600;
  letter-spacing: var(--ls-heading);
}
.callout ul { margin: 0; }

.featured--related { grid-template-columns: repeat(auto-fit, minmax(min(15rem, 100%), 1fr)); }
@media (min-width: 800px) { .featured--related { grid-template-columns: repeat(3, 1fr); } }

/* --- Client logo grid ------------------- ACF: `client_logos` repeater (15) */
/* Measured off the comp at 4x, everything as a fraction of page width W:
     5 equal columns across the content width (0.0505 -> 0.9495 W)
     row centres 0.6868 / 0.8084 / 0.9322 W  ->  even pitch 0.1227 W
     band runs 0.5623 -> 1.0843 W
   Fixed row pitch with the logos centred in it, NOT auto rows: the three rows
   hold very different shapes (a square Schwab, a 7:1 BlackRock wordmark) and
   auto rows would put the pitch at the mercy of whichever logo is tallest. */

.client-logos {
  background: var(--c-white);
  /* 0.1245 W to the first row centre, 0.1521 W from the last centre to the
     end of the band, less half a row each. */
  padding-top: clamp(2rem, 6.32vw, 11.25rem);
  padding-bottom: clamp(2.75rem, 9.08vw, 16.15rem);
}
.logo-grid {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  grid-auto-rows: clamp(4.5rem, 12.27vw, 13.6rem);
  align-items: center;
  justify-items: center;
  list-style: none;
  margin: 0;
  padding: 0;
}
.logo {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 100%;
  /* --logo-w is per-logo, set in the markup from the comp - see the note
     there. The fallback keeps a logo visible if the field is ever empty.
     No padding here: --logo-w is a percentage of the COLUMN, and padding on
     the cell silently shrank every logo by the same 6%. */
}
.logo img {
  display: block;
  width: var(--logo-w, 70%);
  height: auto;
  /* Some of these are 15-year-old raster files. Cap the height so a tall mark
     cannot break the row pitch even if its width field is wrong. */
  max-height: 100%;
  object-fit: contain;
}

/* Five across needs roughly 900px to stay legible; below that the logos would
   be smaller than the type around them. */
@media (max-width: 899px) {
  .logo-grid { grid-template-columns: repeat(3, 1fr); }
}
@media (max-width: 559px) {
  .logo-grid { grid-template-columns: repeat(2, 1fr); }
}

/* --- Testimonial --------------------------- ACF: `testimonial` group ---- */
/* Navy band. Comp, as fractions of W from the top of the band:
     quote mark ink 0.0813, body first line 0.1238, attribution 0.2193,
     band ends 0.3304. */

.testimonial {
  background: var(--c-navy);
  color: var(--c-white);
  padding-top: clamp(2.4rem, 9.85vw, 17.5rem);
  padding-bottom: clamp(2.5rem, 9.15vw, 16.3rem);
}
.testimonial__quote { margin: 0; }
.testimonial__mark {
  /* The opening quote of the pull quote, not a decorative flourish: it is the
     only cyan on the band and it marks where the quote starts. */
  color: var(--c-cyan);
  font-family: var(--ff-display);
  font-weight: 800;
  /* Calibrated to ink: the comp mark measures 0.0254 W wide, 0.0194 W tall.
     Sized by measuring the rendered glyph, not by reasoning from an em value
     - a quote mark's ink is a small and very font-specific slice of its
     font-size. */
  font-size: clamp(3.25rem, 7.93vw, 8.8rem);
  /* The glyph sits high in its em box, so most of a normal line box is empty
     space UNDER the ink. 0.25 collapses that dead space; the gap to the quote
     below is then set by the margin, where it can be measured. */
  line-height: 0.25;
  /* comp: 0.0239 W from the bottom of the mark's ink to the top of the quote */
  margin: 0 0 0.03em;
}
.testimonial__body {
  /* Pale cyan, the same body colour the panels use - not white. */
  color: var(--c-panel-copy);
  /* comp 0.0189 W ≈ 27px at 1440, with a line pitch of 0.0246 W. The comp
     runs body copy at ~1.3 leading; --lh-copy (1.45) is looser than the comp
     everywhere it appears, and at 1.45 this quote fitted on two lines where
     the comp takes three. */
  font-size: clamp(1.25rem, 1.945vw, 2.16rem);
  line-height: 1.30;
  /* The comp's measure: its lines rag at 0.9195 W, inside the 0.9495 W content
     edge, which is what puts "incididunt" at the end of the first line. */
  max-width: 97.5%;
  margin: 0;
}
.testimonial__cite {
  margin-top: 1.2em;
  color: var(--c-white);
  font-weight: 700;
  /* Tracked to WIDTH: the comp line measures 0.2550 W ink-to-ink. Size alone
     reached that width only by overshooting the cap height. */
  font-size: clamp(0.9375rem, 1.40vw, 1.55rem);
  letter-spacing: 0.03em;
  font-style: normal;
}

/* --- Capability matrix ----------------- ACF: `approach_steps` / `capabilities` */
/* Three groups, each a list of terms. Strategy is terms only; Content and
   Design are term + description. One repeater handles both — leave the
   description empty and it renders as a plain term. */

.capability__grid {
  display: grid;
  gap: var(--sp-12);
}
@media (min-width: 900px) {
  /* comp: columns start at 0.0507 / 0.3572 / 0.6629 W and run to 0.9485 — so
     0.2856 W wide with a 0.0209 W gutter. --sp-16 (64px) was more than twice
     the comp's gutter, which narrowed every column and made the Design list
     wrap a line early on nearly every entry. */
  .capability__grid {
    grid-template-columns: repeat(3, 1fr);
    gap: clamp(1.5rem, 2.09vw, 2.3rem);
  }
}

.cap-group__title {
  font-size: var(--fs-md);
  font-weight: 700;
  color: var(--c-blue);
  /* comp: 0.0552 W from the heading's ink to the first item's, against a
     0.0239 W cap — --sp-6 left it 19px tight. */
  margin-bottom: clamp(1.5rem, 3.0vw, 3.1rem);
}
.cap-group ul { margin: 0; padding: 0; list-style: none; }

/* The LI carries the type, not the spans inside it. An li left at --fs-base
   with --lh-body sets a 39px strut that every line box in it inherits — so
   the description was led at 39px however small its own font-size was. Comp
   pitch is 0.0179 W (25.8px at 1440); this was 51% looser than the comp.

   comp: item text 0.01375 W (~19.8px at 1440), pitch 0.0179 W -> 1.30 */
.cap-group li {
  font-size: clamp(0.9375rem, 1.375vw, 1.3rem);
  line-height: 1.30;
}
/* comp: 0.0350 W between the first lines of consecutive entries, against a
   0.0179 W pitch — so ~0.0171 W of clear space, near enough --sp-6. */
.cap-group li + li { margin-top: var(--sp-6); }

.cap-term {
  font-weight: 600;
  color: var(--c-ink);
}
/* Same size as the term, and the comp is explicit about it — bold and regular
   of ONE size, not two sizes. Only the weight and the colour change. */
.cap-desc { color: var(--c-ink-soft); }

/* Terms with no description sit on their own line at body weight. */
.cap-group--terms li { font-weight: 600; }
/* comp: 0.0302 W item to item, tighter than the described entries above. */
.cap-group--terms li + li { margin-top: 1.1rem; }

/* --- Diagram slot ------------------------------- ACF: `diagrams` (flexible) */
/* The comp marks this area "Content to come. Diagrams/text/graphics", and the
   4-D method is where the absorbed UTools material lands (`utools_content`).
   Rendered as a visible placeholder so the gap is obvious rather than hidden. */

.diagram-slot {
  display: grid;
  place-items: center;
  min-height: clamp(220px, 34vw, 380px);
  padding: var(--sp-8);
  border: 1px solid rgba(255, 255, 255, 0.5);
  text-align: center;
  color: var(--c-white);
}
.diagram-slot p {
  font-family: var(--ff-display);
  font-size: var(--fs-md);
  line-height: var(--lh-snug);
  max-width: 20ch;
}
.method__label {
  margin-bottom: var(--sp-8);
  color: var(--c-white);
}

/* --- 4-D method block ---------------------------------------------------- */
/* Deliberately NOT reusing .panel: that carries the homepage's decorative
   left tick, which would be unexplained here. Same ground, same depth layer,
   no borrowed ornament. */
.method {
  position: relative;
  overflow: hidden;
  isolation: isolate;
  padding-block: clamp(4rem, 10vw, 9rem);
  background: var(--c-navy);
  color: var(--c-white);
}
.method > .u-wrap { position: relative; z-index: 1; }

/* --- Pill glyph ---------------------------------------------------------- */
/* The comp's CTA is three chevrons, letter-spaced, on the lime pill. */
.pill__chev {
  /* Negative: the three chevrons should read as ONE arrow, not three marks.
     Manrope’s side bearings on › leave a visible gap even at 0. */
  letter-spacing: -0.08em;
  /* negative tracking removes trailing space, so the nudge flips sign */
  margin-right: 0.08em;
  /* The comp sets these at 0.143 of the pill height, which is weak as an
     affordance - deliberately larger here. */
  font-size: clamp(1.125rem, 1.75vw, 1.75rem);
  /* Light, not bold. The size carries the affordance; the thin stroke keeps
     it elegant, and the comp’s own chevrons are thin. 700 read as blunt. */
  font-weight: 400;
  line-height: 1;
}

/* --- Stat row ----------------------------------- ACF: `stats` repeater (3) */
/* Sits inside the navy page-head band on Who we are. Numerals are LIGHT
   weight in the comp - the contrast against the heavy display face is the
   point, so do not bold these. */

.stats {
  display: grid;
  gap: var(--sp-8);
  margin-top: clamp(3rem, 8vw, 7rem);
}
@media (min-width: 700px) {
  /* Solved from the comp: three equal columns of 0.2484 W with 0.0741 W gaps.
     That is a much larger gap than it looks - it is what pushes column 3 to
     start at 0.697 W and finish flush with the content right edge (0.951 W),
     aligned with the header. A smaller gap leaves it short of the margin. */
  .stats {
    grid-template-columns: repeat(3, 1fr);
    gap: clamp(1.5rem, 7.41vw, 8rem);
  }
}
.stat__num {
  font-family: var(--ff-display);
  font-size: clamp(2.75rem, 5vw, 4rem);
  font-weight: 300;
  line-height: 1;
  letter-spacing: -0.01em;
  color: var(--c-cyan);
}
.stat__desc {
  margin-top: var(--sp-4);
  /* comp: text spans 0.223 W and the copy sets in three lines, breaking after
     "…veteran writers,". At --fs-sm (15px) the text was far too small and
     stopped 0.055 W short of where the comp puts it. */
  max-width: 24ch;
  font-size: clamp(0.9375rem, 1.46vw, 1.375rem);
  font-weight: 600;          /* semibold in the comp, not regular */
  line-height: 1.4;
}

/* --- Office map ------------------------------------- ACF: `offices_map` */
/* ⚠️ PLACEHOLDER ARTWORK, extracted from the PDF comp at native resolution.
   It is a designed asset and should be supplied as SVG - see README. */

.offices {
  background: var(--c-navy);
  /* The page-head above is also navy, so the two bands read as one. Its
     bottom padding already provides the separation - doubling it here just
     opens dead space. */
  padding-top: 0;
}
.offices__figure { margin: 0; }
.offices__figure img {
  width: 100%;
  max-width: 980px;
  margin-inline: auto;
}
.offices__caption {
  margin-top: var(--sp-6);
  text-align: center;
  font-size: var(--fs-sm);
  color: rgba(255, 255, 255, 0.7);
}

/* --- Leadership bio ------------------------------------ ACF: `leadership` */

.bio__name {
  /* comp line pitch 37px at 1440 -> ~30px at --lh-snug, not --fs-md (35px) */
  font-size: clamp(1.25rem, 2.1vw, 2rem);
  font-weight: 700;
  color: var(--c-blue);
  line-height: var(--lh-snug);
  /* no margin-bottom: the grid row-gap owns the space below. Having both gave
     64px where the comp wants ~36px. */
  margin-bottom: 0;
}
.bio__body {
  /* Long-form copy runs SMALLER than the marketing blocks: the comp line pitch
     is 0.0224 W (32px at 1440), which is ~19px at --lh-body 1.7. Inheriting
     --fs-base (23px) made it 22% loose. */
  font-size: clamp(0.9375rem, 1.32vw, 1.25rem);
  max-width: var(--measure);
}
.bio__body p + p { margin-top: var(--sp-4); }

/* Structural BEM blocks. No styling of their own - they exist so the markup
   reads as one unit per ACF row, and so the class audit stays clean. */
.stat { }
.bio  { }


/* --- Pinned panels ------------------------------------------------------- */
/* The section PINS in place and the content swaps between INSTITUTIONS /
   ADVISORS / INVESTORS as you scroll — the viewport holds still while the
   panel changes, rather than panels sliding over one another.

   Default (no JS, reduced motion) is plain stacked sections in normal flow.
   The pinned layout is applied by motion.js via .is-pinned, so a script
   failure can never leave three panels piled on one another.
   ?panels=classic keeps the trailing-background reading.                     */

.panels {
  position: relative;
  background: var(--c-navy);
}

.panels .panel {
  position: relative;
  background: var(--c-navy);
  padding-block: clamp(4rem, 10vw, 9rem);
}

/* --- Pinned mode (JS only) --- */
.panels.is-pinned {
  height: 100vh;
  overflow: hidden;
}
.panels.is-pinned .panel {
  position: absolute;
  inset: 0;
  min-height: 0;
  display: flex;
  align-items: center;
  padding-block: 0;
}
/* All three occupy the same space, so the stacking scrim has nothing to mark. */
.panels.is-pinned .panel__scrim { display: none; }

.panel__scrim { display: none; }

/* Fallback reading — plain flow, background layer trails the scroll. */
.panels--classic .panel {
  position: relative;
  min-height: 0;
  display: block;
  padding-block: clamp(4rem, 10vw, 9rem);
}


/* --- Touch targets -------------------------------------------------------- */
/* The comp is desktop-only, so mobile sizing is our call. Below the tablet
   breakpoint every interactive element gets the 44px minimum from the
   accessibility floor in docs/03-design-tokens.md — footer links measured
   19px tall, which is not tappable.

   Padding does the work rather than font-size, so the type scale is untouched.
   The list margin is dropped because the padding now provides the rhythm. */

/* At every width, footer links clear the 24px WCAG 2.5.8 minimum. The padding
   replaces the list margin so the comp's 0.0213 W pitch is preserved rather
   than added to. */
.site-footer a {
  display: inline-block;
  padding-block: 0.16rem;
}
.site-footer li + li { margin-top: 0; }

@media (max-width: 899px) {
  /* touch: the full 44px floor */
  .site-footer a { padding-block: 0.8rem; }

  .subscribe__input,
  .subscribe__form .u-pill { min-height: 44px; }

  .site-logo { padding-block: 0.35rem; }
}

/* Pointer devices do not need the 44px floor, but the nav still benefits from
   a comfortable hit area. */
@media (min-width: 900px) {
  .site-nav a { padding-block: var(--sp-3); }
}

/* --- Stats band ----------------------------- ACF: `stats` repeater (Who we are) */
/* A separate navy band BELOW the page head, not part of it. Measured off the
   comp: the hero band ends at 0.5617 W and the stat numerals begin at
   0.6957 W, so the gap above is ~0.134 W. The map then starts at ~0.99 W,
   which is the ~0.172 W below.

   Keeping the stats inside .page-head made its min-height cover both blocks
   and pushed the heading off the hero line. */
.stats-band {
  background: var(--c-navy);
  color: var(--c-white);
  padding-top: clamp(3rem, 13.4vw, 12rem);
  padding-bottom: clamp(3rem, 20.5vw, 18rem);   /* map top lands at 0.994 W */
  /* The page head and this band are two navy sections that meet at a
     fractional y at 90% / 110% zoom: each background is anti-aliased there,
     so white showed through as one lighter row (a visible seam). Painting 1px
     of navy upward over the join closes it. A shadow, not a margin, so no
     layout moves. */
  box-shadow: 0 -1px 0 var(--c-navy);
}
.stats-band .stats { margin-top: 0; }

/* --- Office map (interactive) --------------------- ACF: `offices` repeater */
/* The dotted silhouette is a real SVG (assets/img/us-map-dots.svg, ~5.5kb
   gzipped) traced from the comp artwork — 2184 dots on the original grid, so
   it stays crisp at any size instead of being a raster.

   Pins, leader lines and labels are DOM, positioned as percentages of the
   plot, so the labels are selectable, translatable text rather than baked
   pixels, and each office can highlight on hover.

   Every position below was measured off the comp. Both `top` and `height`
   on an absolutely positioned child resolve against the container height,
   which is what lets the leader lines be expressed purely in percentages. */

.office-map { margin: 0; }

.office-map__plot {
  position: relative;
  width: 100%;
  max-width: 980px;
  margin-inline: auto;
  aspect-ratio: 1160 / 730;          /* the comp artwork's ratio */
  background: url('../img/us-map-dots.svg') center / contain no-repeat;
}

.office-map__pins { position: absolute; inset: 0; margin: 0; padding: 0; list-style: none; }

/* Each .office spans the whole plot so its dot, line and label can all be
   positioned in percentages of the container. That means they overlap, and
   without this the topmost one in DOM order (New York) would swallow every
   hover anywhere on the map. Only the dot and label are hit targets. */
.office { position: absolute; inset: 0; pointer-events: none; }
.office__dot, .office__label { pointer-events: auto; }

.office__dot {
  position: absolute;
  left: var(--x);
  top: var(--y);
  width: clamp(9px, 1.5%, 16px);
  aspect-ratio: 1;
  transform: translate(-50%, -50%);
  border-radius: 50%;
  background: var(--c-white);
  transition: box-shadow var(--dur-fast) var(--ease-out);
}
/* the NY/NJ marker is ringed in the comp — one pin, two labels */
.office--ringed .office__dot {
  box-shadow: 0 0 0 3px var(--c-navy), 0 0 0 5px var(--c-white);
}

.office__line {
  position: absolute;
  left: var(--x);
  top: var(--line-top);
  height: var(--line-h);
  width: 1px;
  background: rgba(255, 255, 255, 0.75);
}

.office__label {
  position: absolute;
  left: var(--label-x, var(--x));
  top: var(--label-y);
  transform: translateX(var(--label-shift, -50%));
  white-space: nowrap;
  /* "San Francisco / Bay Area" is the only two-line label, and the comp
     centres its lines on each other (centres differ by 0.34%, left edges by
     2.68%). Single-line labels are unaffected. */
  text-align: center;
  font-size: clamp(0.75rem, 1.4vw, 1.125rem);
  font-weight: 600;
  line-height: 1.25;
  color: var(--c-lime);
  transition: color var(--dur-fast) var(--ease-out);
}
.office--right .office__label { transform: translateY(-50%); }

/* Hover highlight only — these are informational, not controls, so they are
   not focusable. The list is fully readable without any of it. */
.office:hover .office__dot { box-shadow: 0 0 0 6px rgba(255, 255, 255, 0.22); }
.office--ringed:hover .office__dot {
  box-shadow: 0 0 0 3px var(--c-navy), 0 0 0 5px var(--c-white),
              0 0 0 10px rgba(255, 255, 255, 0.22);
}
.office:hover .office__label { color: var(--c-white); }

@media (prefers-reduced-motion: reduce) {
  .office__dot, .office__label { transition: none; }
}

/* Below the breakpoint the plot gets small and the labels collide, so the
   map becomes a plain graphic with the offices listed beneath it. */
@media (max-width: 700px) {
  .office__line, .office__label { display: none; }
  .office-map__list {
    display: flex;
    flex-wrap: wrap;
    gap: var(--sp-2) var(--sp-6);
    margin-top: var(--sp-6);
    padding: 0;
    list-style: none;
    color: var(--c-lime);
    font-weight: 600;
  }
}
@media (min-width: 701px) { .office-map__list { display: none; } }

/* --- Bio grid ------------------------------------ ACF: `leadership` (Who we are) */
/* Two columns, TWO rows. The lockup belongs to the body row, not the heading
   row: the comp starts it 63px BELOW the body's first line, level with the
   copy. Sharing a single row with a .bio wrapper aligned it to the heading
   instead, putting it 115px too high. */
.bio-grid { display: grid; row-gap: clamp(1.5rem, 2.5vw, 2.5rem); }

@media (min-width: 900px) {
  .bio-grid {
    /* Wider than the homepage intro grid: the comp runs the bio copy out to
       0.631 W, which 62.1% cannot reach. The lockup column is unchanged -
       space-between keeps it anchored right. */
    grid-template-columns: 64.5% 22.9%;
    justify-content: space-between;
    column-gap: var(--sp-8);
  }
  .bio__name   { grid-column: 1; grid-row: 1; }
  .bio__body   { grid-column: 1; grid-row: 2; }
  /* Row 2 = the body row, so the lockup aligns with the body’s FIRST LINE.
     Measured in the comp: lockup top is 7px ABOVE the body top (the slab caps
     of "CELEBRATING" sit a little higher than the body x-height) - i.e. level.
     It is 63px below the HEADING top, which is a different measurement and
     must not be applied as an offset here. */
  /* No vertical nudge here: the lockup must sit exactly as it does on the
     homepage, and grid-row 2 already puts it on the body row. An 18px offset
     was added at one point from a Range-based measurement, which reads LINE
     BOXES rather than glyph ink - with line-height 0.8 on the label those
     differ by about that much, so it "corrected" a problem that did not
     exist and pushed this page 20px out of step with the homepage. */
  .bio-grid .anniversary { grid-column: 2; grid-row: 2; }
}

/* --- Intrinsic minimums ------------------------------------------------- */
/* A grid or flex item's automatic minimum size is its MIN-CONTENT width, so a
   track can be pushed wider than its own container by a single long word -
   and `overflow-wrap: break-word` does not help, because it deliberately does
   not reduce min-content size. `min-width: 0` lets the track take its
   fr share and leaves the wrapping to overflow-wrap, which then has a real
   line box to break against. No effect at the sizes the comp was measured at;
   it only stops the blowout once type is enlarged or the column is tiny. */
.page-head__grid > *,
.intro__grid > *,
.case-body__grid > *,
.capability__grid > * { min-width: 0; }
