/* =========================================================================
   AlexDesigns — supplemental styles
   Only what theme.json can't express. Tokens come from the generated
   --wp--preset--* custom properties (color / font-family / spacing).
   Brand rule: blue = primary/motion, teal = AI only, navy/paper = surfaces.
   ========================================================================= */

/* Sticky-header scroll offset: anchor-link navigation lands below the header.
   Measured from the rendered header: 0.7rem×2 padding + ~28px content ≈ 50px;
   64px adds breathing room so the first line of the target is never clipped. */
html { scroll-padding-top: 64px; }

:root {
	--ad-line: 1px solid var(--wp--preset--color--line);
	--ad-line-soft: 1px solid var(--wp--preset--color--line-soft);
	--ad-navy-border: 1px solid var(--wp--preset--color--navy-border);
	--ad-ease: 180ms ease;
	/* DESIGN-STANDARDS spacing scale (one token set, applied site-wide). */
	--ad-section-y: clamp(32px, 3vw, 48px);
	--section-py: var(--ad-section-y);
	--block-gap: 24px;
	--head-gap: 14px;
	--eyebrow-gap: 8px;
	--col-gap: 48px;
	/* Technology badge / pill tokens (see §3d, DESIGN-AUDIT.md). */
	--ad-badge-pad: 0.375rem 0.75rem;   /* 6px 12px */
	--ad-badge-radius: 999px;
	--ad-badge-font: 0.78rem;           /* ≈12.5px */
	--ad-badge-feat-bg: #ECFBF8;
	--ad-badge-feat-color: #0B3F39;
	--ad-badge-feat-border: #9BE7DC;
	/* 2026-07-10 (Alex's sitewide button request): "slightly rounded corners and a little bit
	   of raised bevel — flat but still raised and clean, so you can tell they're actually
	   buttons." Every real button on the site had border-radius:2px (near-sharp) and
	   box-shadow:none (measured live, not assumed) — completely flush with the page, no
	   tactile cue at all. Shared tokens so every button uses the identical treatment, not a
	   dozen near-duplicate hand-tuned shadows: --ad-btn-shadow is a soft outer shadow (the
	   "raised off the page" read) plus a faint inset top highlight (the "bevel" — a sliver of
	   lighter edge along the top, like light catching a slightly domed surface) without going
	   skeuomorphic/gradient-heavy. --ad-btn-shadow-hover deepens the outer shadow on hover,
	   paired with each button's own existing hover lift (translateY) where already present. */
	--ad-btn-radius: 8px;
	--ad-btn-shadow: 0 1px 2px rgba(11, 18, 32, 0.14), 0 1px 0 0 rgba(255, 255, 255, 0.22) inset;
	--ad-btn-shadow-hover: 0 4px 10px rgba(11, 18, 32, 0.18), 0 1px 0 0 rgba(255, 255, 255, 0.22) inset;
}
@media (max-width: 781px) {
	:root { --ad-section-y: 32px; --section-py: 32px; --block-gap: 20px; }
	html  { scroll-padding-top: 52px; } /* 0.45rem×2 padding + ~28px content */
}

/* ----- Base niceties --------------------------------------------------- */
body { -webkit-font-smoothing: antialiased; text-rendering: optimizeLegibility; }
:where(a) { transition: color var(--ad-ease), border-color var(--ad-ease); }
/* Headings break only at word boundaries — never mid-word, never hyphenated. text-wrap:balance
   evens out the lines and prevents a lone orphan word (gracefully ignored where unsupported). */
:where(h1, h2, h3), .wp-block-heading { overflow-wrap: break-word; word-break: normal; hyphens: none; text-wrap: balance; }
/* Body copy: prevent single-word orphans on the last line (no effect where unsupported). */
:where(.ad-section p, main p) { text-wrap: pretty; }

/* Visible focus everywhere (a11y). */
:where(a, button, input, textarea, select, [tabindex]):focus-visible {
	outline: 2px solid var(--wp--preset--color--primary);
	outline-offset: 2px;
	border-radius: 2px;
}

/* ----- Eyebrow ---------------------------------------------------------
   2026-07-09 (Item B1, sitewide typography pass): unified to MATCH
   .oi-hero-eyebrow__topic (the OI hero eyebrow, later in this file) exactly — same display
   font-family, 700 weight, 1.1 line-height, -0.02em tracking, primary color, no uppercase
   transform — EXCEPT font-size, which is 25% smaller than the reference's own
   calc(display/2): calc(display / 2 * 0.75) = display * 0.375. Exact values at the display
   token's 3.6rem base: reference 1.8rem (28.8px), this 1.35rem (21.6px); with the token's
   fluid range (2.15–4rem): reference 1.075–2rem, this 0.80625–1.5rem. Replaces the previous
   mono/0.75rem/uppercase/0.16em/muted treatment. One shared rule — no per-page overrides.
   The existing color-modifier classes below (--warm/--teal/--on-navy) and the dark-section
   overrides (.ad-dark .ad-eyebrow, .ad-bg-navy .ad-eyebrow) still win on color, unchanged —
   light-on-navy sections keep their legible eyebrow color. text-transform: none is explicit
   (not just omitted) so nothing upstream can leave uppercase applied. */
.ad-eyebrow {
	font-family: var(--wp--preset--font-family--display);
	font-size: calc(var(--wp--preset--font-size--display) * 0.375);
	letter-spacing: -0.02em;
	text-transform: none;
	color: var(--wp--preset--color--primary);
	font-weight: 700;
	line-height: 1.1;
}
.ad-eyebrow--warm { color: var(--wp--preset--color--accent-warm); }
.ad-eyebrow--teal { color: var(--wp--preset--color--accent-teal); }
.ad-eyebrow--on-navy { color: var(--wp--preset--color--mono-on-navy); }

/* Eyebrow with a leading 26x1px rule. */
.ad-eyebrow--ruled { display: inline-flex; align-items: center; gap: 0.75rem; }
.ad-eyebrow--ruled::before {
	content: ""; width: 26px; height: 1px; background: currentColor; opacity: 0.6; flex: none;
}

/* ----- Visible breadcrumb trail (Task 1, structural — reuses --muted/--primary/--ink only) --- */
.ad-breadcrumb {
	font-family: var(--wp--preset--font-family--mono);
	font-size: var(--wp--preset--font-size--eyebrow);
	color: var(--wp--preset--color--muted);
	max-width: var(--wp--style--global--wide-size);
	margin-inline: auto;
	padding: 1rem clamp(22px, 5vw, 48px) 0;
}
.ad-breadcrumb ol { display: flex; flex-wrap: wrap; align-items: center; list-style: none; margin: 0; padding: 0; gap: 0.4rem; }
.ad-breadcrumb li { display: flex; align-items: center; gap: 0.4rem; }
.ad-breadcrumb a { color: var(--wp--preset--color--muted); text-decoration: none; border-bottom: 1px solid transparent; }
.ad-breadcrumb a:hover { color: var(--wp--preset--color--primary); border-bottom-color: var(--wp--preset--color--primary); }
.ad-breadcrumb__current { color: var(--wp--preset--color--ink); font-weight: 600; }
.ad-breadcrumb__sep { opacity: 0.5; }
/* OI breadcrumb context override -- templates/oi-page.html places .ad-breadcrumb inside
   .oi-breadcrumb-wrap (2026-07-09, feature/oi-overview-hero-rail-refinements: moved out of
   .oi-hero-wrap / <main> entirely, to a template-level position before <main>, matching
   single.html/page.html's real convention -- see the template's own comment for the full
   "excessive gap above the breadcrumb" root-cause account). .oi-breadcrumb-wrap is ITSELF
   already a WordPress "wide"-constrained, auto-centered group (needed so the breadcrumb's
   left edge matches the content column), so .ad-breadcrumb's own max-width+margin-inline:auto
   above (load-bearing on single.html/page.html, which render breadcrumbs with NO wrapper at
   all) would double-constrain here exactly like it did inside the old .oi-hero-wrap (D8) --
   same fix, renamed selector: neutralize the breadcrumb's own centering, let the wrapper be
   the only thing controlling width/position. Scoped to this one context; every other
   template's breadcrumb (no wrapper) is untouched. */
/* 2026-07-09 (Item B2): padding-inline: 0 added to this override. Measured live (Playwright,
   ol text edge, not the element box): on how-we-work/single.html (no wrapper), .ad-breadcrumb's
   own content-box max-width + auto-margin + clamp() padding math lands the breadcrumb TEXT
   exactly at the wide/logo edge (100px at 1440w, 22px at 390w) — that's the canonical
   placement. Inside .oi-breadcrumb-wrap the wrapper already provides that inset, so the
   component's own clamp() padding-inline double-counted and pushed the text 22-48px right of
   the logo/H1 (bcText=148 vs logo=100 at 1440w). The prior sweep missed it by measuring the
   element box edge, which the wrapper aligns, instead of the text edge, which the padding
   offsets. Top padding (1rem) is kept — that vertical gap matches every other template. */
.oi-breadcrumb-wrap .ad-breadcrumb { max-width: none; margin-inline: 0; padding-inline: 0; }
/* 2026-07-09 -- real fix for the width-dependent breadcrumb detachment reported after the D12/
   D13 passes (both only checked 375/390/1024/1280/1424px; the bug only shows above ~1336px).
   ROOT CAUSE, confirmed by sweeping every 40px from 320px to 1920px and comparing against the
   header logo (the site's actual left-edge reference, not just the H1): .oi-breadcrumb-wrap's
   OWN `align="wide"` never centers it at all, because WordPress's auto-generated
   ".is-layout-constrained > .alignwide { max-width: ... }" rule only fires when the block's
   PARENT carries `is-layout-constrained` -- .oi-hero-grid's parent is <main>, which does; this
   wrapper's parent is the bare template root, which doesn't. So .oi-breadcrumb-wrap silently
   rendered full-bleed (rect.left === 0) the whole time, with ONLY its has-global-padding
   clamp(22px,5vw,48px) padding holding the breadcrumb text in from the edge -- that padding
   caps at 48px and stops growing, while the real wide-aligned content (H1, logo) keeps
   growing its inset past ~1336px viewport (max-width:1240px + true auto-centering). Below
   1336px the two formulas coincidentally produce the same numbers (both bottom out at 48px),
   which is exactly why every prior pass's 5-checkpoint sweep (375/390/1024/1280/1424, all
   under 1336px) reported it fixed.
   FIX: give the wrapper the real centering math directly -- NOT a hand-rolled duplicate:
   width: calc(100% - 2 * clamp(...)) + max-width:wideSize + margin:auto is the exact formula
   this codebase already uses for other elements outside a constrained-layout context, so this
   reuses it rather than inventing a third variant. padding is explicitly zeroed since the
   width formula does the insetting now -- leaving has-global-padding's own padding active
   would double-count it. Verified: diff between this wrapper's rendered left edge and the H1/
   logo's left edge is 0px at every 40px step from 320px to 1920px, not just the 5 checkpoints. */
.oi-breadcrumb-wrap {
	width: calc(100% - 2 * clamp(22px, 5vw, 48px));
	max-width: var(--wp--style--global--wide-size);
	margin: 0 auto;
	padding: 0;
	box-sizing: border-box;
}
/* Below ~480px, "Home / Optimization Intelligence / [Topic Label]" cannot fit on one line at
   any readable font-size for the longer topic labels (e.g. "Conversion Rate Optimization",
   "AI Marketing Systems") -- measured: ~65 characters needed vs. ~331px/12px-mono available
   at 375px, no font-size reduction gets there without going illegibly small. Drop the middle
   "Optimization Intelligence" crumb + its separator at these widths -- that context is
   already shown one section above in the sticky .oi-topnav dropdown, so nothing is lost, and
   "Home / [Topic]" always fits on one line. :not(:last-child) so this never touches the OI
   hub's own 2-item breadcrumb ("Home / Optimization Intelligence" -- there, item 2 IS the
   last item, the current page, and must stay). Flagged to Alex as a design call, not silently
   decided -- see docs/DECISIONS.md D8. */
@media (max-width: 479px) {
	.oi-breadcrumb-wrap .ad-breadcrumb li:nth-child(2):not(:last-child) { display: none; }
}

/* ----- Sitemap page list (Task 2, structural — reuses --line/--ink/--primary only) ----------- */
.ad-sitemap-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.5rem; }
.ad-sitemap-list li { border-bottom: 1px solid var(--wp--preset--color--line); padding-bottom: 0.5rem; }
.ad-sitemap-list a { color: var(--wp--preset--color--ink); text-decoration: none; display: inline-flex; align-items: center; min-height: 44px; }
.ad-sitemap-list a:hover { color: var(--wp--preset--color--primary); }
.ad-sitemap-list__empty { color: var(--wp--preset--color--muted); border-bottom: none; }
@media (min-width: 700px) {
	.ad-sitemap-list--two-col { grid-template-columns: 1fr 1fr; column-gap: 2rem; }
}

/* ----- Section rhythm + hairline dividers ------------------------------ */
.ad-section { padding-block: var(--ad-section-y); }
.ad-section--tight { padding-block: clamp(16px, 1.8vw, 24px); }
/* wwd-why bottom and wwd-caps top sit closer together */
.wwd-why { padding-bottom: clamp(16px, 1.8vw, 24px); }
.wwd-caps { padding-top: clamp(16px, 1.8vw, 24px); }
/* wwd-why: tighten card margin so cards sit closer to the intro text */
.wwd-why .wwd-cards { margin-top: 1rem; }
.ad-divide-top { border-top: var(--ad-line); }
.ad-divide-bottom { border-bottom: var(--ad-line); }

/* ----- Left-edge alignment (ui-standards §3) --------------------------- */
/* Constrained sections live inside <main layout:default> which doesn't center them —
   they fill full <main> width. Center them at wideSize (1240px) so their left edge
   matches the logo's left edge. AlignFull/alignwide sections are excluded because they
   intentionally escape to full width.
   The FAQ block is raw PHP (no is-layout-constrained) and gets the same treatment
   via .ad-faq below. */
.wp-block-group.is-layout-constrained.ad-section:not(.alignfull):not(.alignwide) {
	max-width: var(--wp--style--global--wide-size);
	margin-inline: auto;
}
/* FAQ is raw PHP (no is-layout-constrained so WP doesn't add the body padding).
   Match the section content left edge: same max-width + same horizontal padding. */
.ad-faq {
	max-width: var(--wp--style--global--wide-size);
	margin-inline: auto;
	padding-inline: clamp(22px, 5vw, 48px);
}
/* Override WP's child-centering (margin-inline:auto at contentSize 720px) so all
   text children start at the section's left edge = logo's left edge.
   Specificity (0,3,0,0) beats WP's generated rule (0,1–2,0,0). */
.wp-block-group.is-layout-constrained.ad-section > :not(.alignfull):not(.alignwide) {
	margin-left: 0 !important;
}
/* Full-bleed (alignfull) sections have WP's body padding (clamp(22px,5vw,48px)) but
   no wideSize centering offset. Expand padding-inline to absorb both so content starts
   at the same left edge as in constrained sections: max(0,(100vw−wideSize)/2) + bodyPad.
   Specificity (0,4,0,0) + !important beats WP's has-global-padding (0,1,0,0). */
.wp-block-group.alignfull.is-layout-constrained.ad-section {
	padding-inline: calc(max(0px, (100vw - var(--wp--style--global--wide-size)) / 2) + clamp(22px, 5vw, 48px)) !important;
}

/* ----- Text link with underline that warms on hover ------------------- */
.ad-textlink {
	display: inline-flex; align-items: center; gap: 0.4rem;
	min-height: 44px;
	font-weight: 600; text-decoration: none;
	border-bottom: 1px solid var(--wp--preset--color--line);
	padding-bottom: 2px;
}
.ad-textlink:hover { border-bottom-color: var(--wp--preset--color--primary); }

/* ----- Cards ----------------------------------------------------------- */
.ad-card {
	background: var(--wp--preset--color--card);
	border: var(--ad-line);
	border-radius: var(--wp--custom--radius--card);
	box-shadow: var(--wp--preset--shadow--whisper);
}
.ad-card--pad { padding: clamp(1.25rem, 3vw, 2rem); }

/* ----- Pill chips (check + label) -------------------------------------- */
.ad-chips { display: flex; flex-wrap: wrap; gap: 0.625rem; }
.ad-chip {
	display: inline-flex; align-items: center; gap: 0.45rem;
	background: var(--wp--preset--color--card);
	border: var(--ad-line); border-radius: 2px;
	padding: 0.5rem 0.8rem;
	font-size: 1rem; font-weight: 500; color: var(--wp--preset--color--ink);
}
.ad-chip svg { width: 16px; height: 16px; color: var(--wp--preset--color--primary); flex: none; }

/* ----- Technology badge pills (canonical two-variant system, §3d) ------
   .ad-badge-group  — wrapping container (tinted card, max-width constrained)
   .ad-badge        — base: white pill, gray outline (standard tools)
   .ad-badge--feat  — featured: teal fill, solid teal border (AI platforms)
   .ad-badge--bespoke — bespoke: teal fill, dashed teal border (custom/proprietary)
   These replace all inline cap-badges styles sitewide. */
.ad-badge-inner { display: flex; flex-wrap: wrap; gap: 0.44rem; }
.ad-badge-group {
	background: var(--wp--preset--color--surface);
	border: 1px solid var(--wp--preset--color--line);
	border-radius: 12px; padding: 1rem;
	margin-top: 1.5rem; max-width: 62rem;
	box-sizing: border-box;
}
.ad-badge {
	display: inline-block;
	padding: var(--ad-badge-pad); border-radius: var(--ad-badge-radius);
	background: var(--wp--preset--color--card);
	border: 1px solid var(--wp--preset--color--line);
	font-size: var(--ad-badge-font); font-weight: 500; color: var(--wp--preset--color--ink);
	white-space: nowrap;
}
.ad-badge--feat {
	background: var(--ad-badge-feat-bg);
	border-color: var(--ad-badge-feat-border);
	color: var(--ad-badge-feat-color);
}
.ad-badge--bespoke {
	background: var(--ad-badge-feat-bg);
	border: 1px dashed var(--ad-badge-feat-border);
	color: var(--ad-badge-feat-color);
}

/* ----- Capability "includes" chips (WHAT YOU GET sections) ------------- */
.ad-incl-group {
	background: var(--wp--preset--color--paper);
	border: 1px solid var(--wp--preset--color--line);
	border-radius: var(--wp--custom--radius--card-lg); padding: 1.4rem 1.5rem;
	margin-top: 1.5rem; max-width: 62rem;
}
.ad-incl-label {
	font-family: var(--wp--preset--font-family--mono); font-size: 0.66rem;
	letter-spacing: 0.12em; text-transform: uppercase;
	color: var(--wp--preset--color--muted); margin: 0 0 0.75rem;
}
.ad-incl-chips { display: flex; flex-wrap: wrap; gap: 0.5rem; }
.ad-incl-chip {
	display: inline-block;
	font-size: 0.82rem; font-weight: 500;
	padding: 0.38rem 0.8rem; border-radius: 999px;
	background: var(--wp--preset--color--surface);
	color: var(--wp--preset--color--slate);
	border: 1px solid var(--wp--preset--color--line);
}

/* Ecosystem grid (wwd-ecosystem.php) */
.wwd-badges { box-sizing: border-box; margin-top: 1.75rem; }
.ad-eco-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 1rem; }
.ad-eco-cat { background: var(--wp--preset--color--surface); border: 1px solid var(--wp--preset--color--line); border-radius: 12px; padding: 1rem; }
.ad-eco-label { font-size: 0.84rem; font-weight: 700; margin: 0 0 0.75rem; color: var(--wp--preset--color--ink); }
.ad-eco-chips { display: flex; flex-wrap: wrap; gap: 0.44rem; }
/* --muted (#667080) is 4.41:1 on this card's --surface background — just under WCAG AA's
   4.5:1 for small text. --slate reads slightly darker but is the theme's next token up and
   passes with real margin (7.9:1) — same fix pattern as the figure-CSS contrast pass. */
.ad-badge-note { font-size: 0.69rem; color: var(--wp--preset--color--slate); margin-top: 0.62rem; line-height: 1.45; }

/* Cap page sections: What You Get, One Capability, Related Reading */
/* .cap-twocol — What You Get + The Technology side-by-side row */
.cap-twocol { display: grid; grid-template-columns: 1fr 1fr; gap: var(--col-gap, 48px); align-items: start; }
.cap-twocol .ad-eyebrow { margin: 0; }
.cap-twocol h2.wp-block-heading { margin-bottom: 0.5rem; }
.cap-twocol p { margin: 0.75rem 0 0; }
@media (max-width: 768px) {
    .cap-twocol { grid-template-columns: 1fr; gap: 0; }
    .cap-twocol__col + .cap-twocol__col { border-top: var(--ad-line); padding-top: var(--ad-section-y); margin-top: var(--ad-section-y); }
}
/* .cap-includes — 5 standard cap pages */
.cap-includes .wwd-chips { display: flex; flex-wrap: wrap; gap: .5rem; margin-top: 1.5rem; max-width: 62rem; }
.cap-includes .wwd-chip { font-size: .82rem; font-weight: 500; padding: .4rem .85rem; border-radius: 999px; background: var(--wp--preset--color--surface); color: var(--wp--preset--color--slate); border: 1px solid var(--wp--preset--color--line); }
.cap-includes .wwd-chips__lbl { font-family: var(--wp--preset--font-family--mono); font-size: .66rem; letter-spacing: .12em; text-transform: uppercase; color: var(--wp--preset--color--muted); }
.cap-includes .cap-incard { background: var(--wp--preset--color--paper); border: 1px solid var(--wp--preset--color--line); border-radius: var(--wp--custom--radius--card-lg); padding: 1.4rem 1.5rem; margin-top: 1.5rem; max-width: 62rem; }
.cap-includes .cap-incard .wwd-chips { margin-top: .75rem; }
/* .capx-incl — experimentation + ai-marketing cap pages */
.capx-incl { background: var(--wp--preset--color--paper); border: 1px solid var(--wp--preset--color--line); border-radius: var(--wp--custom--radius--card-lg); padding: 1.4rem 1.5rem; margin-top: 1.5rem; max-width: 62rem; }
.capx-incl .capx-lbl { font-family: var(--wp--preset--font-family--mono); font-size: .66rem; letter-spacing: .12em; text-transform: uppercase; color: var(--wp--preset--color--muted); margin: 0 0 .75rem; }
.capx-incl .capx-chips { display: flex; flex-wrap: wrap; gap: .5rem; }
.capx-incl .capx-chip,
.capx-incl .wwd-chip { font-size: .82rem; font-weight: 500; padding: .36rem .8rem; border-radius: 999px; background: var(--wp--preset--color--surface); color: var(--wp--preset--color--slate); border: 1px solid var(--wp--preset--color--line); }
/* .cap-xlink — related capabilities grid (5 standard pages) */
.cap-xlink .cap-xgrid { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 1rem; margin-top: 1.75rem; }
.cap-xlink .cap-xcard { display: flex; flex-direction: column; gap: .4rem; background: var(--wp--preset--color--card); border: 1px solid var(--wp--preset--color--line); border-radius: var(--wp--custom--radius--card-lg); padding: 1.25rem 1.35rem; text-decoration: none; transition: border-color .15s ease, transform .15s ease; }
.cap-xlink .cap-xcard:hover { border-color: var(--wp--preset--color--primary); transform: translateY(-2px); }
.cap-xlink .cap-xcard__title { display: flex; align-items: center; justify-content: space-between; font-weight: 600; font-size: 1.05rem; color: var(--wp--preset--color--ink); }
.cap-xlink .cap-xcard__title svg { width: 18px; height: 18px; color: var(--wp--preset--color--primary); flex: none; }
.cap-xlink .cap-xcard__desc { font-size: .9rem; line-height: 1.5; color: var(--wp--preset--color--muted); }
/* .capx-xgrid — related capabilities grid (experimentation + ai-marketing) */
.capx-xgrid { display: grid; grid-template-columns: repeat(auto-fill, minmax(260px, 1fr)); gap: 1rem; margin-top: 1.75rem; }
.capx-xcard { display: block; background: var(--wp--preset--color--card); border: 1px solid var(--wp--preset--color--line); border-radius: var(--wp--custom--radius--card-lg); padding: 1.25rem 1.35rem; text-decoration: none; transition: border-color .15s ease, transform .15s ease; }
.capx-xcard:hover { border-color: var(--wp--preset--color--primary); transform: translateY(-2px); }
.capx-xcard__top { display: flex; align-items: center; justify-content: space-between; gap: .75rem; }
.capx-xcard__title { font-family: var(--wp--preset--font-family--display); font-weight: 600; font-size: 1.05rem; color: var(--wp--preset--color--ink); }
.capx-xcard__arrow { flex: none; color: var(--wp--preset--color--primary); }
.capx-xcard__desc { margin: .4rem 0 0; font-size: .88rem; line-height: 1.45; color: var(--wp--preset--color--muted); }
/* .cap-reading — related reading list (5 standard pages) */
.cap-reading .cap-readlist { list-style: none; margin: 1.5rem 0 0; padding: 0; max-width: 62rem; }
.cap-reading .cap-readlist li { border-top: 1px solid var(--wp--preset--color--line); }
.cap-reading .cap-readlist li:last-child { border-bottom: 1px solid var(--wp--preset--color--line); }
.cap-reading .cap-readlist a { display: flex; align-items: center; justify-content: space-between; gap: 1rem; padding: 1rem .25rem; text-decoration: none; color: var(--wp--preset--color--ink); font-weight: 600; font-size: 1.05rem; transition: color .15s ease; }
.cap-reading .cap-readlist a:hover { color: var(--wp--preset--color--primary); }
.cap-reading .cap-readlist svg { width: 18px; height: 18px; color: var(--wp--preset--color--primary); flex: none; }
/* .capx-read — related reading cards (experimentation + ai-marketing) */
.capx-read { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 1rem; margin-top: 1.5rem; }
.capx-readcard { display: flex; align-items: center; justify-content: space-between; gap: 1rem; background: var(--wp--preset--color--card); border: 1px solid var(--wp--preset--color--line); border-radius: 14px; padding: 1.25rem 1.4rem; text-decoration: none; transition: border-color .15s ease; }
.capx-readcard:hover { border-color: var(--wp--preset--color--primary); }
.capx-readcard span { font-weight: 600; color: var(--wp--preset--color--ink); font-size: 1.02rem; }
.capx-readcard svg { flex: none; color: var(--wp--preset--color--primary); }
/* .capx-quote — testimonial in dark section (experimentation) */
.capx-quote { margin: 2.25rem 0 0; max-width: 48rem; border-left: 3px solid var(--wp--preset--color--teal-on-navy); padding: 0.25rem 0 0.25rem 1.25rem; }
.capx-quote blockquote { margin: 0; font-size: 1.15rem; line-height: 1.5; color: var(--wp--preset--color--light-text); }
.capx-quote figcaption { margin-top: 0.65rem; font-family: var(--wp--preset--font-family--mono); font-size: 0.72rem; letter-spacing: 0.1em; color: var(--wp--preset--color--muted-on-navy); text-transform: uppercase; }

/* Trust row (icon + label, dot dividers) */
.ad-trust { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem 1rem; color: var(--wp--preset--color--slate); font-size: 1rem; }
.ad-trust__item { display: inline-flex; align-items: center; gap: 0.5rem; }
.ad-trust__item svg { width: 18px; height: 18px; color: var(--wp--preset--color--muted); }

/* ----- Hero experiment card (illustrative) ----------------------------- */
.ad-exp { padding: 1.25rem 1.4rem; }
.ad-exp__head { display: flex; align-items: center; justify-content: space-between; gap: 1rem; margin-bottom: 1rem; }
.ad-exp__label { display: inline-flex; align-items: center; gap: 0.5rem; white-space: nowrap; font-family: var(--wp--preset--font-family--mono); font-size: 0.7rem; letter-spacing: 0.14em; text-transform: uppercase; color: var(--wp--preset--color--muted); }
/* AI teal for small text-on-light is darkened to clear WCAG AA 4.5:1 (decorative teal stays bright). */
.ad-tag-illustrative { white-space: nowrap; font-family: var(--wp--preset--font-family--mono); font-size: 0.62rem; letter-spacing: 0.12em; text-transform: uppercase; color: #0A7060; background: color-mix(in srgb, var(--wp--preset--color--accent-teal) 12%, transparent); padding: 0.2rem 0.5rem; border-radius: 2px; }
.ad-exp__row { font-size: 1rem; color: var(--wp--preset--color--muted); margin-bottom: 1rem; }
.ad-meter { margin-bottom: 0.85rem; }
.ad-meter__top { display: flex; justify-content: space-between; font-size: 1rem; margin-bottom: 0.4rem; }
.ad-meter__name { font-weight: 600; color: var(--wp--preset--color--ink); }
.ad-meter__val { font-family: var(--wp--preset--font-family--mono); color: var(--wp--preset--color--slate); }
.ad-meter__track { height: 8px; border-radius: 999px; background: var(--wp--preset--color--surface); overflow: hidden; }
.ad-meter__fill { height: 100%; border-radius: 999px; background: var(--wp--preset--color--muted); }
.ad-meter__fill--primary { background: var(--wp--preset--color--primary); }
.ad-exp__foot { display: flex; align-items: baseline; gap: 0.6rem; border-top: var(--ad-line-soft); padding-top: 1rem; margin-top: 0.25rem; }
.ad-exp__stat { font-family: var(--wp--preset--font-family--display); font-weight: 700; font-size: 2rem; color: var(--wp--preset--color--accent-warm); white-space: nowrap; flex: none; }
.ad-exp__statnote { font-size: 0.85rem; color: var(--wp--preset--color--muted); }

/* ----- Stat band (track record) ---------------------------------------- */
.ad-statband { display: grid; grid-template-columns: repeat(4, 1fr); border-block: var(--ad-line); }
.ad-statband__cell { padding: 1.5rem 1rem; }
.ad-statband__cell + .ad-statband__cell { border-left: var(--ad-line); }
.ad-statband__num { font-family: var(--wp--preset--font-family--display); font-weight: 700; font-size: clamp(2rem, 5vw, 2.875rem); color: var(--wp--preset--color--ink); line-height: 1; }
.ad-statband__num .ad-plus { color: var(--wp--preset--color--accent-warm); }
.ad-statband__label { font-size: 0.9rem; color: var(--wp--preset--color--muted); margin-top: 0.5rem; }
@media (max-width: 781px) {
	.ad-statband { grid-template-columns: repeat(2, 1fr); }
	.ad-statband__cell:nth-child(3) { border-left: 0; }
	.ad-statband__cell:nth-child(n+3) { border-top: var(--ad-line); }
}

/* ----- Author bio hero (templates/author.html) -------------------------- */
.ad-author-bio__title { font-size: var(--wp--preset--font-size--medium); color: var(--wp--preset--color--slate); margin-top: 0.5rem; }
.ad-author-bio__title a { color: inherit; text-decoration: underline; text-underline-offset: 0.15em; }
.ad-author-bio__credentials { font-size: var(--wp--preset--font-size--medium); color: var(--wp--preset--color--muted); margin-top: 0.6rem; max-width: 640px; }

/* ----- Capability rows (link list with trailing arrow, hover) ---------- */
.ad-cap { display: block; text-decoration: none; padding: 1.25rem 0; border-top: var(--ad-line-soft); }
.ad-cap:first-child { border-top: 0; }
.ad-cap__head { display: flex; align-items: center; gap: 0.7rem; }
.ad-cap__icon { width: 24px; height: 24px; color: var(--wp--preset--color--primary); flex: none; }
.ad-cap__icon--ai { color: var(--wp--preset--color--accent-teal); }
.ad-cap__title { font-family: var(--wp--preset--font-family--display); font-weight: 600; font-size: 1.19rem; color: var(--wp--preset--color--ink); margin: 0; }
.ad-cap__arrow { margin-left: auto; width: 18px; height: 18px; color: var(--wp--preset--color--muted); transition: transform var(--ad-ease), color var(--ad-ease); }
.ad-cap__desc { color: var(--wp--preset--color--muted); font-size: 1rem; margin: 0.4rem 0 0; padding-left: calc(24px + 0.7rem); }
.ad-cap:hover .ad-cap__title { color: var(--wp--preset--color--primary); }
.ad-cap:hover .ad-cap__arrow { transform: translate(2px, -2px); color: var(--wp--preset--color--primary); }

/* ----- Contrast card (one-off vs ongoing) ------------------------------ */
.ad-contrast { display: grid; grid-template-columns: 1fr 1fr; }
.ad-contrast__col { padding: clamp(1.1rem, 3vw, 1.75rem); }
.ad-contrast__col:first-child { border-right: var(--ad-line); }
.ad-contrast__head { display: flex; align-items: center; gap: 0.55rem; font-family: var(--wp--preset--font-family--display); font-weight: 600; font-size: 1.05rem; color: var(--wp--preset--color--ink); }
.ad-contrast__head svg { width: 20px; height: 20px; flex: none; }
.ad-contrast__head--no svg { color: var(--wp--preset--color--muted); }
.ad-contrast__head--yes svg { color: var(--wp--preset--color--accent-teal); }
.ad-contrast__body { color: var(--wp--preset--color--muted); margin-top: 0.6rem; font-size: 1rem; }
@media (max-width: 600px) {
	.ad-contrast { grid-template-columns: 1fr; }
	.ad-contrast__col:first-child { border-right: 0; border-bottom: var(--ad-line); }
}

/* ----- Fit check checklists -------------------------------------------- */
.ad-fit { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.85rem; }
.ad-fit li { display: grid; grid-template-columns: 20px 1fr; gap: 0.6rem; color: var(--wp--preset--color--slate); font-size: 1rem; }
.ad-fit svg { width: 18px; height: 18px; margin-top: 2px; }
.ad-fit--good svg { color: var(--wp--preset--color--accent-teal); }
.ad-fit--not svg { color: var(--wp--preset--color--muted); }

/* ----- Dark sections (framework, footer) ------------------------------- */
.ad-dark { background: var(--wp--preset--color--navy); color: var(--wp--preset--color--light-text); }
.ad-dark--deep { background: var(--wp--preset--color--navy-deep); }
.ad-dark :where(h1, h2, h3) { color: #fff; }
.ad-dark a { color: var(--wp--preset--color--light-text); }
.ad-dark a:hover { color: #fff; }
.ad-dark .ad-eyebrow { color: var(--wp--preset--color--mono-on-navy); }

/* ----- Pulse dot (Currently) ------------------------------------------- */
.ad-dot { width: 9px; height: 9px; border-radius: 999px; background: var(--wp--preset--color--accent-teal); display: inline-block; }
.ad-dot--pulse { animation: ad-pulse 2s ease-in-out infinite; }
@keyframes ad-pulse { 0%, 100% { opacity: 1; transform: scale(1); } 50% { opacity: 0.4; transform: scale(0.8); } }
/* Reduced-motion accommodation (deploy-verify QA pass, 2026-07-06) — every other animation in
   this stylesheet is already gated behind prefers-reduced-motion; this one was the one flagged
   gap (docs/DEPLOY-AND-PUBLISH-RUNBOOK.md's "Standing status" note). Static dot, full opacity —
   still conveys "live" via its color/label, just without the motion a reduced-motion user asked
   to avoid. */
@media (prefers-reduced-motion: reduce) {
	.ad-dot--pulse { animation: none; opacity: 1; transform: none; }
}

/* ----- Diagrams (flywheel + curve) ------------------------------------- */
.ad-figure { margin: 0; }
.ad-figure svg { display: block; width: 100%; height: auto; }
.ad-figcaption { font-size: 0.9rem; color: var(--wp--preset--color--muted); margin-top: 0.75rem; }
/* Flywheel: circular diagram at every breakpoint (changed 2026-07-06 — was hidden under 640px
   in favor of a text-only fallback; the SVG scales via width:100%/height:auto and stays within
   the same 440px cap used on desktop, so it renders at a comparable, legible size on mobile
   too). .ad-flywheel__stack (below) stays in the HTML as the always-present AEO text mirror per
   its own docstring, just no longer visually swapped in at narrow widths. */
.ad-flywheel__circle { display: block; }
.ad-flywheel__stack { display: none; }

/* ----- Contact form ----------------------------------------------------- */
/* Single column, label above each field, ~20px between fields (DESIGN-STANDARDS). */
.ad-form { display: grid; gap: 1.25rem; }
.ad-form__grid { display: grid; grid-template-columns: 1fr; gap: 1.25rem; }
.ad-field { display: grid; gap: var(--eyebrow-gap, 8px); }
/* [hidden] companion: .ad-field's display:grid would otherwise defeat the hidden attribute, so
   the reveal-on-"Other" field (start-main.php [data-start-other]) rendered on cold load.
   See docs/ui-standards.md §1 — the specificity rule Check A enforces. */
.ad-field[hidden] { display: none; }
.ad-field > label { font-size: 0.92rem; font-weight: 600; color: var(--wp--preset--color--ink); }
.ad-field input, .ad-field textarea {
	font: inherit; color: var(--wp--preset--color--ink);
	background: var(--wp--preset--color--card);
	border: 1px solid #E3E8F0;
	border-radius: 10px; padding: 0.8rem 0.95rem; width: 100%; min-height: 48px;
	/* subtle inset bevel so each clearly reads as a clickable input */
	box-shadow: inset 0 1px 2px rgba(11, 18, 32, 0.05);
	transition: border-color var(--ad-ease), box-shadow var(--ad-ease);
}
.ad-field textarea { min-height: 130px; resize: vertical; }
.ad-field input::placeholder, .ad-field textarea::placeholder { color: var(--wp--preset--color--muted); }
.ad-field input:hover, .ad-field textarea:hover { border-color: #CFD8E3; }
.ad-field input:focus, .ad-field textarea:focus {
	outline: none; border-color: var(--wp--preset--color--primary);
	box-shadow: 0 0 0 3px color-mix(in srgb, var(--wp--preset--color--primary) 18%, transparent), inset 0 1px 2px rgba(11, 18, 32, 0.04);
}
.ad-field--error input, .ad-field--error textarea { border-color: var(--wp--preset--color--accent-warm); }
.ad-field__error { font-size: 0.82rem; color: var(--wp--preset--color--accent-warm); }
.ad-form__note { display: inline-flex; align-items: center; gap: 0.4rem; font-size: 0.88rem; color: var(--wp--preset--color--muted); }
.ad-form__note svg { width: 15px; height: 15px; }
/* Honeypot — visually hidden but present in DOM (no display:none so bots fill it). */
.ad-hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }
.ad-form__success { background: color-mix(in srgb, var(--wp--preset--color--accent-teal) 10%, var(--wp--preset--color--paper)); border: 1px solid color-mix(in srgb, var(--wp--preset--color--accent-teal) 35%, transparent); border-radius: 4px; padding: 1rem 1.15rem; color: var(--wp--preset--color--ink); }

/* "What happens next" numbered steps */
.ad-steps { list-style: none; margin: 0; padding: 0; display: grid; gap: 1.1rem; }
.ad-steps li { display: grid; grid-template-columns: 28px 1fr; gap: 0.75rem; }
.ad-steps__n { width: 24px; height: 24px; border-radius: 999px; background: color-mix(in srgb, var(--wp--preset--color--primary) 12%, transparent); color: var(--wp--preset--color--primary); font-size: 0.8rem; font-weight: 600; display: grid; place-items: center; }
.ad-steps__t { font-weight: 600; color: var(--wp--preset--color--ink); }
.ad-steps__d { color: var(--wp--preset--color--slate); font-size: 1rem; margin-top: 0.15rem; }

/* ----- CTA panel (solid blue) ------------------------------------------ */
.ad-cta { background: #2353D4; background: var(--wp--preset--color--primary); border-radius: 4px; color: #fff; }
.ad-cta :where(h2) { color: #fff; }
.ad-cta__sub { color: var(--wp--preset--color--cta-subcopy); }
.ad-cta__note { display: inline-flex; align-items: center; gap: 0.4rem; color: var(--wp--preset--color--cta-subcopy); font-size: 0.9rem; }
.ad-cta__note svg { width: 15px; height: 15px; }
/* 2026-07-10 (Alex's sitewide button request): box-shadow bevel added directly here — radius
   already comes from theme.json's styles.elements.button.border.radius (now 8px, was 2px),
   but box-shadow isn't reliably portable through theme.json's element styles across WP
   versions, so it's set explicitly for the one real class every core button block renders
   (.wp-block-button__link), covering every wp:buttons instance sitewide in one rule. */
.wp-block-button__link { box-shadow: var(--ad-btn-shadow); transition: background var(--ad-ease), color var(--ad-ease), box-shadow var(--ad-ease), transform var(--ad-ease); }
.wp-block-button__link:hover { box-shadow: var(--ad-btn-shadow-hover); transform: translateY(-1px); }
.wp-block-button__link:active { box-shadow: var(--ad-btn-shadow); transform: translateY(0); }
.ad-cta .wp-block-button__link, .ad-cta .ad-btn-invert { background: #fff; color: var(--wp--preset--color--primary); }
.ad-cta .wp-block-button__link:hover, .ad-cta .ad-btn-invert:hover { background: #eef1f4; color: var(--wp--preset--color--primary-hover); }

/* ----- Article category eyebrow color coding --------------------------- */
.ad-cat { font-family: var(--wp--preset--font-family--mono); font-size: 0.7rem; letter-spacing: 0.14em; text-transform: uppercase; }
.ad-cat a { text-decoration: none; color: var(--wp--preset--color--muted); }
.ad-cat a:hover { color: var(--wp--preset--color--ink); }
.ad-cat--experimentation { color: var(--wp--preset--color--primary); }
.ad-cat--data { color: var(--wp--preset--color--accent-warm); }
.ad-cat--ai { color: var(--wp--preset--color--accent-teal); }

/* ----- Header / brand / nav -------------------------------------------- */
/* Sticky header: the template-part WRAPPER is the sticky element, because its parent is
   the full-height .wp-site-blocks. The inner .ad-header can't stick on its own — its
   containing block (the wrapper) is only header-height, so it unsticks the instant you
   scroll past it. Pinning the wrapper keeps the nav fixed for the whole page scroll. */
.wp-site-blocks > header.wp-block-template-part { position: sticky; top: 0; z-index: 50; }
.ad-header { backdrop-filter: saturate(140%) blur(10px); background: rgba(248,250,251,0.82) !important; z-index: 50; }
/* Desktop header: 3-column grid (logo | nav, centered | search+CTA+hamburger) so the primary
   nav sits centered in the header instead of clustered against the right edge. Explicit
   grid-column on each child (not relying on auto-placement) so the layout stays correct on
   mobile even though .ad-nav-desktop is display:none there (an auto-placed item would
   otherwise shift .ad-header__right into the empty middle column). !important overrides the
   block editor's own inline flex layout styles for this specific instance.
   2026-07-06 FIX (feat/oi-rail-and-hero, found during this pass's own scroll-gate verification,
   unrelated to this pass's own changes): the grid rule below had no min-width guard, so it
   applied at 360px too — even with .ad-nav-desktop hidden, the "auto 1fr auto" track sizing let
   .ad-header__right's own min-content width push the grid past 360px (Check B: +15px on every
   page with the standard header, including several this pass never touched). This centering
   only matters once .ad-nav-desktop is actually visible (>=1002px as of 2026-07-10, see Part
   H2's own comment near .ad-nav-desktop for why this moved from 783px) — scoping the grid
   override to that width restores the original, already-correct flex behavior on mobile/tablet. */
@media (min-width: 1002px) {
	.ad-header__inner.is-layout-flex { display: grid !important; grid-template-columns: auto 1fr auto; align-items: center; }
	.ad-header__inner > .ad-brand { grid-column: 1; }
	.ad-header__inner > .ad-nav-desktop { grid-column: 2; justify-self: center; }
	.ad-header__inner > .ad-header__right { grid-column: 3; }
}
.ad-brand { min-height: 44px; align-items: center; text-decoration: none; }
.ad-brand__mark { line-height: 0; }
/* 2026-07-14 (Alex): the "AlexDesigns" wordmark must never wrap to two lines at any width -
   white-space:nowrap on the site-title block (theme.json sets its font-size/weight; this file is
   the right place for a plain CSS behavior rule) keeps it on one line even if the header row gets
   tight; flex-shrink:0 stops the flex layout from compressing the brand box to force a wrap. */
.wp-block-site-title, .wp-block-site-title a { white-space: nowrap; flex-shrink: 0; }
/* Header right cluster: search + CTA(s) + hamburger */
.ad-header__right { display: flex; align-items: center; gap: 1.5rem; }
.ad-brand a { display: inline-flex; align-items: center; min-height: 44px; }
/* 2026-07-10 (Part H2 — nav must never wrap before the mobile breakpoint takes over). Real
   measurement (Playwright, live nav): the 4-group desktop nav wrapped to 2 lines across the
   ENTIRE 783-1003px range, not just near a boundary — the deficit between content width and
   available space was a near-constant ~135-150px through that whole band, not a gradient a
   pure vw-scaled clamp could close gracefully. Tried compression alone first; closing that
   full deficit required font-size/padding/gap cuts aggressive enough to start hurting
   legibility below ~1000px. Final fix is BOTH pieces together: compress moderately (this rule
   + the .ad-nav__grouphead rule below, 1002-1149px) AND move the desktop-nav/hamburger
   switchover from 783px to 1002px — exactly the width where the compressed nav genuinely fits
   on one line, not an arbitrary round number. This is narrower than jumping straight to
   ~1024px with no compression (which would've pushed a wider band of ordinary laptop widths
   into the mobile nav for no reason) and doesn't require crushing the label text to the point
   of hurting readability. See the @media (max-width: 1001px) block further down for the
   matching switchover. */
.ad-nav-desktop { display: flex; align-items: center; gap: 0.5rem; }
/* Measured (Playwright, real content width vs available column width): the deficit causing
   the wrap is a near-constant ~135-145px across the ENTIRE 783-1100px range, not a gradient
   that eases as the viewport widens — a fine vw-scaled clamp (tried first) barely closed it.
   A flat, larger reduction across this whole band is what actually fits; it recovers to full
   size at 1100px, where the deficit itself resolves on its own (available width outgrows the
   font-size-clamped nav's max content width). */
@media (min-width: 1002px) and (max-width: 1149px) {
	/* 2026-07-14 (Alex): gap:0 read as nav links "crammed together with no space between them" -
	   restored a small minimum gap. The 2026-07-14 font-size revert (1.0625rem -> 1rem, see the
	   .ad-nav__grouphead a rule below) narrows every link in this band too, freeing up the room
	   this needed; re-measured (Playwright) at 0.3rem the nav still fits on one line across the
	   full 1002-1149px range - no wrap regression. */
	.ad-nav-desktop { gap: 0.3rem; }
}

/* Nav dropdown groups — desktop: hover/focus-within (or keyboard-toggled .is-open) opens
   an anchored panel; drawer: the same markup becomes a JS accordion (panel starts
   [hidden]). The group label stays a real link to the hub page in both variants.
   2026-07-10 (Part H1): background/padding/radius moved from the bare `<a>` (below) to THIS
   wrapper — .ad-nav__grouphead is the real visual pill now, containing both the label link
   and the caret button, so hover/active backgrounds enclose them as one shape. Previously the
   background lived only on `.ad-nav-desktop a`, which covers just the label's own padding
   box — the caret (a sibling <button>, not inside the <a>) rendered OUTSIDE that background
   entirely, exactly the "caret escapes its highlight box" bug Alex flagged. */
.ad-nav-desktop .ad-nav__group { position: relative; display: inline-flex; }
.ad-nav-desktop .ad-nav__grouphead {
	display: inline-flex;
	align-items: center;
	padding: 6px 6px 6px 10px;
	border-radius: 6px;
	transition: color var(--ad-ease), background var(--ad-ease);
}
.ad-nav-desktop .ad-nav__grouphead:hover { background: var(--wp--preset--color--surface); }
.ad-nav-desktop .ad-nav__grouphead.is-current { background: rgba(35, 83, 212, 0.09); }
.ad-nav-desktop .ad-nav__grouphead a {
	color: var(--wp--preset--color--slate);
	/* 2026-07-11: bumped 1rem -> 1.0625rem (+1px) — a tasteful bump per Alex's ask, left at the
	   low end of the requested +1-2px range so it doesn't reopen the 783-1149px wrap this same
	   band was compressed to avoid (see the .ad-nav-desktop comment above and the compressed-band
	   rule just below, which is deliberately left at its own smaller size for that reason).
	   NOTE 2026-07-14: this base value is overridden at every real viewport by
	   assets/css/components/cta-min-height.css's own .ad-nav-desktop .ad-nav__grouphead a rules
	   (that file loads after this one on purpose, so nav/CTA size tuning never has to touch this
	   protected file — see its docblock). The actual nav-link-size-vs-CTA fix Alex asked for
	   2026-07-14 lives there, not here; this base value is intentionally left as-is. */
	font-size: 1.0625rem;
	font-weight: 500;
	text-decoration: none;
	transition: color var(--ad-ease);
}
/* 783-1099px: same flat-reduction rationale as the .ad-nav-desktop gap rule above (measured
   constant ~140px deficit across this whole band, not a gradient) — shrink padding + font-size
   together rather than one alone, so no single property has to do all the work. */
@media (min-width: 1002px) and (max-width: 1149px) {
	.ad-nav-desktop .ad-nav__grouphead { padding: 6px 0 6px 3px; }
	.ad-nav-desktop .ad-nav__grouphead a { font-size: 0.72rem; }
	/* 2026-07-11: -6px -> -2px — measured (live, Playwright) at -6px the caret glyph sat only
	   ~1px from the compressed label's right edge, tighter than the ~4-6px gap the primary
	   (>=1150px) breakpoint already has; -2px lines the two bands up at ~5px without reopening
	   the wrap this whole compressed band exists to avoid. */
	.ad-nav-desktop .ad-nav__caret { margin-left: -2px; }
}
.ad-nav-desktop .ad-nav__grouphead:hover a { color: var(--wp--preset--color--ink); }
.ad-nav-desktop .ad-nav__grouphead a.is-current { color: var(--wp--preset--color--primary); font-weight: 600; }
/* padding 7px + margin-left -1px: grows the invisible hit area to the WCAG 2.5.8 24x24px
   touch-target minimum (12px icon was only 20x16px) without visually shifting the caret
   relative to the label text — this button has no visible fill/border of its own now (the
   grouphead wrapper carries the background), so the larger box is inert until clicked/tapped.
   margin-left changed from -9px to -1px: that more-negative value was compensating for the
   caret sitting in its own unstyled box outside the label's background; now that both share
   one padding box (6px right padding on the grouphead itself), -9px overlapped the caret icon
   under the label's last letter — re-measured, -1px is the correct value for equal-feeling
   label-to-caret spacing inside the shared pill. */
.ad-nav-desktop .ad-nav__caret { display: inline-flex; align-items: center; background: none; border: 0; padding: 7px; margin-left: -1px; color: var(--wp--preset--color--muted); cursor: pointer; transition: transform var(--ad-ease), color var(--ad-ease); }
.ad-nav-desktop .ad-nav__group:hover .ad-nav__caret,
.ad-nav-desktop .ad-nav__group.is-open .ad-nav__caret { transform: rotate(180deg); color: var(--wp--preset--color--ink); }
.ad-nav-desktop .ad-nav__sub { position: absolute; top: calc(100% + 8px); left: 0; min-width: 240px; margin: 0; padding: 0.45rem; list-style: none; background: var(--wp--preset--color--paper); border: 1px solid var(--wp--preset--color--line); border-radius: 10px; box-shadow: 0 12px 32px rgba(11, 18, 32, 0.10); opacity: 0; visibility: hidden; transform: translateY(4px); transition: opacity 0.16s ease, transform 0.16s ease, visibility 0.16s; z-index: 80; }
.ad-nav-desktop .ad-nav__group:hover .ad-nav__sub,
.ad-nav-desktop .ad-nav__group:focus-within .ad-nav__sub,
.ad-nav-desktop .ad-nav__group.is-open .ad-nav__sub { opacity: 1; visibility: visible; transform: translateY(0); }
.ad-nav-desktop .ad-nav__sub li { list-style: none; }
/* color/font-weight/text-decoration restored explicitly here (Part H1): previously inherited
   from a shared `.ad-nav-desktop a` base rule that also carried the top-level pill's
   padding/background — that rule is now scoped to `.ad-nav__grouphead a` only (H1's fix), so
   the dropdown-menu links need their own copy of the cosmetic-only properties they always had. */
.ad-nav-desktop .ad-nav__sub a { display: block; padding: 0.5rem 0.75rem; font-size: 0.9rem; border-radius: 7px; white-space: nowrap; color: var(--wp--preset--color--slate); font-weight: 500; text-decoration: none; transition: color var(--ad-ease), background var(--ad-ease); }
.ad-nav-desktop .ad-nav__sub a:hover { color: var(--wp--preset--color--ink); background: var(--wp--preset--color--surface); }
.ad-nav-desktop .ad-nav__sub a.is-current { color: var(--wp--preset--color--primary); background: rgba(35, 83, 212, 0.09); font-weight: 600; }
.ad-nav-desktop .ad-nav__sub[hidden] { display: none; }
.ad-nav__ext { display: inline-block; margin-left: 0.3em; font-size: 0.85em; color: var(--wp--preset--color--muted); }
@media (prefers-reduced-motion: reduce) {
	.ad-nav-desktop .ad-nav__sub, .ad-nav-desktop .ad-nav__caret { transition: none; }
}
/* CTA buttons in the header (shared look) */
.ad-cta-desktop, .ad-cta-mobile, .ad-nav-drawer__cta { background: #2353D4; background: var(--wp--preset--color--primary); color: #fff !important; border: 0; border-radius: var(--ad-btn-radius); box-shadow: var(--ad-btn-shadow); font-weight: 600; text-decoration: none; white-space: nowrap; display: inline-flex; align-items: center; justify-content: center; transition: background var(--ad-ease), box-shadow var(--ad-ease), transform var(--ad-ease); }
.ad-cta-desktop:hover, .ad-cta-mobile:hover, .ad-nav-drawer__cta:hover { background: var(--wp--preset--color--primary-hover); box-shadow: var(--ad-btn-shadow-hover); transform: translateY(-1px); }
.ad-cta-desktop:active, .ad-cta-mobile:active, .ad-nav-drawer__cta:active { transform: translateY(0); box-shadow: var(--ad-btn-shadow); }
.ad-cta-desktop { padding: 0.6rem 1.1rem; font-size: 1rem; }
.ad-cta-mobile { display: none; }
.ad-nav-toggle { display: none; align-items: center; justify-content: center; width: 44px; height: 44px; padding: 0; border: 0; background: transparent; color: var(--wp--preset--color--ink); cursor: pointer; }
.ad-nav-toggle:focus-visible, .ad-nav-drawer__panel :focus-visible { outline: 2px solid var(--wp--preset--color--primary); outline-offset: 2px; }

/* 2026-07-10 (Part H2): the mobile/hamburger nav takes over up to 1001px now, not 781px —
   real measurement found the desktop nav (4 dropdown groups) wrapping to 2 lines across the
   entire 783-999px range even after compressing it as far as legible (see the .ad-nav-desktop
   comment above). Rather than crush the label text further, the switchover point moved up to
   exactly where the compressed nav genuinely fits on one line — this two-part fix (compress +
   raise the switch point) avoids both the wrap bug and an oversized jump that would push
   ~250px of ordinary laptop-width viewports into mobile nav for no reason. The compact-bar
   styling below (padding/CTA/toggle) is unchanged in kind, just active over a wider range. */
@media (max-width: 1001px) {
	/* Compact mobile bar (~56px); logo left, CTA + hamburger far right */
	.ad-header { padding-top: 0.45rem !important; padding-bottom: 0.45rem !important; }
	.ad-nav-desktop, .ad-cta-desktop { display: none !important; }
	html.js .ad-search-toggle { display: inline-flex !important; }
	.ad-cta-mobile { display: inline-flex; padding: 0.45rem 0.95rem; font-size: 0.9rem; min-height: 44px; }
	.ad-nav-toggle { display: inline-flex; }
	.ad-header__right { gap: 0.6rem; }
}

/* Mobile slide-in drawer (right side, matching the hamburger).
   ROBUST OPEN STATE: the panel is SOLID + on-screen and the scrim is opaque whenever the
   drawer is SHOWN. The toggle JS opens by setting drawer.hidden=false and closes via a
   240ms setTimeout -> hidden=true (NOT transitionend), so visibility is driven by [hidden]
   alone — we do NOT gate it on the JS-added .is-open class. If that class is delayed or
   missing, the menu must still be opaque and readable, never a see-through overlay (the bug). */
.ad-nav-drawer[hidden] { display: none; }
.ad-nav-drawer { position: fixed; inset: 0; z-index: 200; } /* above the sticky header (z 50) + all page content */
.ad-nav-drawer__scrim { position: fixed; inset: 0; background: rgba(11, 18, 32, 0.6); } /* opaque backdrop whenever shown */
.ad-nav-drawer__panel {
	position: fixed; top: 0; right: 0; bottom: 0; z-index: 1; /* above the scrim */
	width: min(340px, 88vw);
	background: #0B1220; color: #E6EDF6;            /* SOLID navy panel — never transparent */
	box-shadow: -8px 0 30px rgba(0, 0, 0, 0.4);
	padding: 1.1rem 1.3rem 1.6rem; display: flex; flex-direction: column;
}
.ad-nav-drawer__close { align-self: flex-end; background: transparent; border: 0; color: #9FB0C8; cursor: pointer; padding: 0.4rem; line-height: 0; }
.ad-nav-drawer__close:hover { color: #fff; }
/* Search box inside the flyout — same "s"-param GET action as the header search modal
   (reaches WP's native search results), styled for the drawer's dark navy ground rather
   than reusing .ad-search-form's light-card colors. */
.ad-nav-drawer__search { display: flex; align-items: center; gap: 0.5rem; margin: 0.75rem 0 0.25rem; padding: 0.5rem 0.6rem; background: rgba(255, 255, 255, 0.06); border: 1px solid rgba(255, 255, 255, 0.14); border-radius: 8px; }
.ad-nav-drawer__search-input { flex: 1; min-width: 0; border: 0; outline: none; background: transparent; color: #E6EDF6; font-family: var(--wp--preset--font-family--body); font-size: 1rem; padding: 0.3rem 0; }
.ad-nav-drawer__search-input::placeholder { color: #8A97AD; }
.ad-nav-drawer__search-submit { flex: none; display: inline-flex; align-items: center; justify-content: center; width: 36px; height: 36px; padding: 0; border: 0; border-radius: 6px; background: transparent; color: #9FB0C8; cursor: pointer; }
.ad-nav-drawer__search-submit:hover { color: #fff; background: rgba(255, 255, 255, 0.1); }
.ad-nav-drawer__links { display: flex; flex-direction: column; gap: 0; margin-top: 0.25rem; }
.ad-nav-drawer__links a { color: #E6EDF6; font-size: 1.15rem; font-weight: 600; text-decoration: none; padding: 0.9rem 0.25rem; border-bottom: 1px solid rgba(255, 255, 255, 0.1); }
.ad-nav-drawer__links a:hover { color: #fff; }
/* Drawer dropdown groups render as accordions: hub link + caret button on one row,
   sub-list collapsed via [hidden] until toggled. */
.ad-nav-drawer__links .ad-nav__group { border-bottom: 1px solid rgba(255, 255, 255, 0.1); }
.ad-nav-drawer__links .ad-nav__grouphead { display: flex; align-items: center; justify-content: space-between; }
.ad-nav-drawer__links .ad-nav__grouphead a { border-bottom: none; flex: 1 1 auto; }
.ad-nav-drawer__links .ad-nav__caret { background: none; border: 0; padding: 0.9rem 0.4rem; color: #8A97AD; cursor: pointer; transition: transform 0.15s ease; }
.ad-nav-drawer__links .ad-nav__group.is-open .ad-nav__caret { transform: rotate(180deg); }
.ad-nav-drawer__links .ad-nav__sub { list-style: none; margin: 0 0 0.5rem; padding: 0 0 0 0.85rem; }
.ad-nav-drawer__links .ad-nav__sub[hidden] { display: none; }
.ad-nav-drawer__links .ad-nav__sub a { display: block; font-size: 1rem; font-weight: 500; color: #B7C3D6; border-bottom: none; padding: 0.45rem 0.25rem; }
.ad-nav-drawer__links .ad-nav__sub a:hover { color: #fff; }
@media (prefers-reduced-motion: reduce) { .ad-nav-drawer__links .ad-nav__caret { transition: none; } }
.ad-nav-drawer__links a.is-current { color: #fff; padding-left: 0.75rem; border-left: 3px solid var(--wp--preset--color--primary); }
.ad-nav-drawer__cta { margin-top: auto; padding: 0.9rem; font-size: 1rem; }
body.ad-nav-open { overflow: hidden; }

/* ----- Search: trigger + modal + results ------------------------------- */
/* Trigger is hidden until JS is present, so there's never a dead control. */
.ad-search-toggle { display: none; align-items: center; justify-content: center; width: 40px; height: 40px; padding: 0; border: 0; background: transparent; color: var(--wp--preset--color--slate); border-radius: 4px; cursor: pointer; }
html.js .ad-search-toggle { display: inline-flex; }
.ad-search-toggle:hover { color: var(--wp--preset--color--ink); background: var(--wp--preset--color--surface); }
.ad-search-toggle:focus-visible { outline: 2px solid var(--wp--preset--color--primary); outline-offset: 2px; }

.ad-search-modal[hidden] { display: none; }
.ad-search-modal { position: fixed; inset: 0; z-index: 100; display: flex; align-items: flex-start; justify-content: center; padding: clamp(1rem, 8vh, 7rem) 1rem 1rem; }
.ad-search-modal__backdrop { position: fixed; inset: 0; background: rgba(11,18,32,0.55); backdrop-filter: blur(3px); }
.ad-search-modal__dialog { position: relative; width: min(640px, 100%); display: flex; align-items: center; gap: 0.75rem; background: var(--wp--preset--color--card); border: 1px solid var(--wp--preset--color--line); border-radius: 8px; box-shadow: var(--wp--preset--shadow--card); padding: 1rem 1.1rem; }
.ad-search-form { display: flex; align-items: center; gap: 0.6rem; flex: 1; min-width: 0; }
.ad-search-form__icon { color: var(--wp--preset--color--muted); flex: none; }
.ad-search-form__input { flex: 1; min-width: 0; border: 0; outline: none; background: transparent; color: var(--wp--preset--color--ink); font-family: var(--wp--preset--font-family--body); font-size: 1.125rem; padding: 0.5rem 0; }
.ad-search-form__submit { flex: none; background: #2353D4; background: var(--wp--preset--color--primary); color: #fff; border: 0; border-radius: var(--ad-btn-radius); box-shadow: var(--ad-btn-shadow); font-weight: 600; padding: 0.6rem 1.1rem; cursor: pointer; transition: background var(--ad-ease), box-shadow var(--ad-ease), transform var(--ad-ease); }
.ad-search-form__submit:hover { background: var(--wp--preset--color--primary-hover); box-shadow: var(--ad-btn-shadow-hover); transform: translateY(-1px); }
.ad-search-modal__close { flex: none; background: transparent; border: 0; color: var(--wp--preset--color--muted); cursor: pointer; padding: 0.35rem; border-radius: 4px; line-height: 0; }
.ad-search-modal__close:hover { color: var(--wp--preset--color--ink); background: var(--wp--preset--color--surface); }
.ad-search-modal__dialog :focus-visible { outline: 2px solid var(--wp--preset--color--primary); outline-offset: 2px; }
body.ad-search-open { overflow: hidden; }
@media (prefers-reduced-motion: no-preference) {
	.ad-search-modal:not([hidden]) .ad-search-modal__dialog { animation: ad-search-pop 160ms ease-out; }
	@keyframes ad-search-pop { from { opacity: 0; transform: translateY(-6px); } to { opacity: 1; transform: none; } }
}

.ad-search-results .wp-block-post-title { margin-top: 1.9rem; margin-bottom: 0.35rem; }
.ad-search-results .wp-block-post-date { color: var(--wp--preset--color--muted); font-size: 0.9rem; }

/* ----- Footer ---------------------------------------------------------- */
.ad-footer__list { list-style: none; margin: 0; padding: 0; }
.ad-footer__list a { text-decoration: none; display: inline-flex; align-items: center; min-height: 44px; }
.ad-footer .ad-eyebrow { margin-bottom: 0.75rem; }
.ad-footer__eyebrow-spacer { visibility: hidden; pointer-events: none; }
.ad-footer__social-link { display: flex; align-items: center; gap: 0.4rem; margin-top: 0.25rem; min-height: 44px; font-size: var(--wp--preset--font-size--small); color: var(--wp--preset--color--mono-on-navy); text-decoration: none; width: fit-content; }
.ad-footer__social-link:hover { color: #ffffff; }
.ad-footer__cta-btn {
	display: inline-block;
	margin-top: 1.25rem;
	padding: 0.7rem 1.2rem;
	border: 1px solid rgba(255, 255, 255, 0.3);
	border-radius: 6px;
	color: #ffffff;
	text-decoration: none;
	font-size: 0.92rem;
	font-weight: 500;
	letter-spacing: -0.01em;
	transition: border-color 0.18s ease, background 0.18s ease;
}
.ad-footer__cta-btn:hover {
	border-color: rgba(255, 255, 255, 0.65);
	background: rgba(255, 255, 255, 0.06);
	color: #ffffff;
}
.ad-footer__bottom {
	display: flex;
	flex-direction: column;
	gap: 0.85rem;
	border-top: 1px solid var(--wp--preset--color--navy-border);
	margin-top: 2.5rem;
	padding-top: 1.75rem;
}
.ad-footer__nav {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 0.15rem 0.55rem;
}
.ad-footer__nav a { font-size: var(--wp--preset--font-size--small); color: var(--wp--preset--color--mono-on-navy); text-decoration: none; display: inline-flex; align-items: center; min-height: 44px; }
.ad-footer__nav a:hover { color: #ffffff; }
.ad-footer__nav span { font-size: var(--wp--preset--font-size--small); color: var(--wp--preset--color--navy-border); }
.ad-footer__legal {
	display: flex;
	flex-wrap: wrap;
	justify-content: space-between;
	align-items: center;
	gap: 0.5rem 1rem;
}
.ad-footer__legal p { margin: 0; font-size: var(--wp--preset--font-size--small); color: var(--wp--preset--color--mono-on-navy); }
.ad-footer__legal a { color: var(--wp--preset--color--mono-on-navy); text-decoration: none; display: inline-flex; align-items: center; min-height: 44px; }
.ad-footer__legal a:hover { color: #ffffff; }

/* ----- Flywheel HTML mirror (always in the DOM for AEO, not visually shown — see the
   circular-diagram rule above) ------------------------------------------- */
.ad-flywheel__stack { display: none; list-style: none; margin: 1.5rem 0 0; padding: 0; counter-reset: fw; max-width: 30rem; }
.ad-flywheel__stack li { position: relative; padding: 0.9rem 0 0.9rem 0; border-left: 2px solid var(--wp--preset--color--navy-border); margin-left: 14px; padding-left: 1.5rem; color: var(--wp--preset--color--muted-on-navy); }
.ad-flywheel__stack li strong { color: #fff; font-family: var(--wp--preset--font-family--display); font-weight: 600; }
.ad-fw__n { font-family: var(--wp--preset--font-family--mono); font-size: 0.7rem; color: var(--wp--preset--color--mono-on-navy); margin-right: 0.6rem; }
.ad-fw__ai { display: inline-block; margin-left: 0.4rem; font-family: var(--wp--preset--font-family--mono); font-size: 0.68rem; color: var(--wp--preset--color--teal-on-navy); border: 1px solid color-mix(in srgb, var(--wp--preset--color--teal-on-navy) 50%, transparent); border-radius: 3px; padding: 0.05rem 0.35rem; }
.ad-flywheel__return { border-left: 2px dashed var(--wp--preset--color--navy-border) !important; color: var(--wp--preset--color--teal-on-navy) !important; font-family: var(--wp--preset--font-family--mono); font-size: 0.72rem; }

/* ----- Compounding curve legend ---------------------------------------- */
.ad-curve__legend { list-style: none; margin: 1rem 0 0; padding: 0; display: flex; flex-wrap: wrap; gap: 0.5rem 1.5rem; font-size: 0.92rem; color: var(--wp--preset--color--slate); }
.ad-curve__legend li { display: inline-flex; align-items: center; gap: 0.5rem; }
.ad-curve__legend strong { color: var(--wp--preset--color--ink); }
.ad-curve__swatch { width: 18px; height: 3px; border-radius: 2px; flex: none; }
.ad-curve__swatch--system { background: var(--wp--preset--color--primary); height: 4px; }
.ad-curve__swatch--oneoff { background: var(--wp--preset--color--muted); background-image: repeating-linear-gradient(90deg, var(--wp--preset--color--muted) 0 5px, transparent 5px 9px); background-color: transparent; }

/* ----- How We Work: stage list ----------------------------------------- */
.ad-stage { padding: 1.4rem 0; border-top: var(--ad-line); }
.ad-stage__head { display: flex; align-items: baseline; gap: 0.75rem; }
.ad-stage__n { font-family: var(--wp--preset--font-family--mono); font-size: 0.8rem; color: var(--wp--preset--color--primary); }
.ad-stage__name { font-family: var(--wp--preset--font-family--display); font-weight: 600; font-size: 1.25rem; color: var(--wp--preset--color--ink); margin: 0; }
.ad-stage__ai { font-family: var(--wp--preset--font-family--mono); font-size: 0.62rem; letter-spacing: 0.1em; text-transform: uppercase; color: #0A7060; border: 1px solid color-mix(in srgb, #0A7060 45%, transparent); border-radius: 3px; padding: 0.1rem 0.4rem; }
.ad-stage__desc { color: var(--wp--preset--color--muted); margin: 0.5rem 0 0; font-size: 1rem; }

/* ----- How We Work: the rhythm (week cards) ---------------------------- */
.ad-weeks { display: grid; grid-template-columns: repeat(4, 1fr); gap: 1.5rem; }
.ad-weeks--3 { grid-template-columns: repeat(3, 1fr); }
.ad-week { border-top: 2px solid var(--wp--preset--color--primary); padding-top: 1rem; }
.ad-week__label { font-family: var(--wp--preset--font-family--mono); font-size: 0.72rem; letter-spacing: 0.12em; text-transform: uppercase; color: var(--wp--preset--color--muted); display: flex; align-items: center; gap: 0.4rem; }
.ad-week__label svg { width: 16px; height: 16px; color: var(--wp--preset--color--primary); }
.ad-week__title { font-family: var(--wp--preset--font-family--display); font-weight: 600; font-size: 1.1rem; color: var(--wp--preset--color--ink); margin: 0.6rem 0 0.4rem; }
.ad-week__body { color: var(--wp--preset--color--muted); font-size: 1rem; margin: 0; }
@media (max-width: 781px) { .ad-weeks { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 480px) { .ad-weeks { grid-template-columns: 1fr; } }

/* ----- Reduced motion -------------------------------------------------- */
@media (prefers-reduced-motion: reduce) {
	*, *::before, *::after { animation-duration: 0.001ms !important; animation-iteration-count: 1 !important; transition-duration: 0.001ms !important; scroll-behavior: auto !important; }
}

/* ----- Testimonials (template-driven page) ----------------------------- */
.ad-tfeatured { background: var(--wp--preset--color--navy); border-radius: 8px; padding: clamp(1.5rem, 4vw, 2.75rem); margin: 0 0 2rem; display: grid; gap: 1.25rem; }
.ad-tfeatured__quote { margin: 0; border: 0; padding: 0; font-family: var(--wp--preset--font-family--serif); font-size: clamp(1.25rem, 1rem + 1.4vw, 1.6rem); line-height: 1.42; color: #fff; }
.ad-tfeatured__author { display: flex; align-items: center; gap: 0.85rem; }
.ad-tfeatured__name { display: block; font-weight: 600; color: #fff; }
.ad-tfeatured__role { color: var(--wp--preset--color--muted-on-navy); font-size: 0.9rem; }

.ad-tcards { display: grid; grid-template-columns: repeat(2, 1fr); gap: 1.5rem; }
@media (max-width: 720px) { .ad-tcards { grid-template-columns: 1fr; } }
.ad-tcard { display: flex; flex-direction: column; gap: 1.1rem; background: var(--wp--preset--color--card); border: 1px solid var(--wp--preset--color--line); border-radius: 5px; box-shadow: var(--wp--preset--shadow--whisper); padding: 1.5rem 1.6rem; }
.ad-tcard__quote { margin: 0; border: 0; padding: 0; color: var(--wp--preset--color--slate); font-size: 1.02rem; line-height: 1.55; }
.ad-tcard__author { display: flex; align-items: center; gap: 0.75rem; margin-top: auto; }
.ad-tcard__name { display: block; font-weight: 600; color: var(--wp--preset--color--ink); }
.ad-tcard__role { color: var(--wp--preset--color--muted); font-size: 0.85rem; }
/* --muted on --surface is 4.41:1 — under WCAG AA's 4.5:1 for this initials text. Even though
   the avatar is aria-hidden (the name is announced from the adjacent text), sighted low-vision
   visitors still read these initials, so contrast still matters. --slate passes at 7.9:1. */
.ad-tcard__avatar { flex: none; width: 44px; height: 44px; border-radius: 999px; background: var(--wp--preset--color--surface); color: var(--wp--preset--color--slate); font-size: 0.85rem; font-weight: 700; letter-spacing: 0.02em; display: grid; place-items: center; }
.ad-tfeatured .ad-tcard__avatar { background: var(--wp--preset--color--navy-border); color: var(--wp--preset--color--logo-on-navy); }
.ad-tcta { margin-top: 2.5rem; }

/* ----- About: hero (text + portrait) + photo slots --------------------- */
.ad-about-hero { display: grid; grid-template-columns: 1.5fr 1fr; gap: clamp(1.5rem, 4vw, 3rem); align-items: center; }
@media (max-width: 781px) { .ad-about-hero { grid-template-columns: 1fr; gap: 1.5rem; } }
img.ad-about-portrait, img.ad-about-secondary { width: 100%; height: auto; border-radius: 8px; display: block; }
.ad-about-secondary { margin: 2rem 0; }
.ad-photo-slot { display: grid; place-items: center; text-align: center; background: var(--wp--preset--color--surface); border: 1px dashed #9AA7B6; border-radius: 8px; color: var(--wp--preset--color--muted); font-family: var(--wp--preset--font-family--mono); font-size: 0.72rem; letter-spacing: 0.08em; text-transform: uppercase; line-height: 1.7; padding: 1rem; }
.ad-about-hero__photo .ad-photo-slot.ad-about-portrait { aspect-ratio: 4 / 5; }
.ad-photo-slot.ad-about-secondary { aspect-ratio: 3 / 2; margin: 2rem 0; }

/* ----- In-content article images: cap to the reading column ------------- */
/* Raster visuals inserted into an article's post content (figure.wp-block-image
   / its <img>) must stay within the text column and never render absurdly tall.
   Scoped to .wp-block-post-content so the built SVG diagrams (.wwd-fig /
   .ad-figure, which manage their own width) are left untouched. WordPress core
   already emits loading="lazy" + decoding="async" on content images; these rules
   only govern size and reflow. */
/* Every article figure is a proper figure BLOCK, not a floating decoration: a numbered
   mono eyebrow (CSS counter — no content edits needed), the graphic, and a real caption,
   all inside a bordered tint card, centered and capped to the reading column. Caption +
   eyebrow use slate (not muted) — muted fails 4.5:1 on the tint ground. */
.article-content { counter-reset: adfig; }
.article-content :where(figure.wp-block-image) {
	counter-increment: adfig;
	max-width: min(100%, 760px);
	margin: 2rem auto;
	height: auto;
	background: var(--wp--preset--color--tint);
	border: 1px solid var(--wp--preset--color--line);
	border-radius: var(--wp--custom--radius--card-lg);
	padding: 1rem 1.1rem 0.9rem;
}
.article-content :where(figure.wp-block-image)::before {
	content: "Figure " counter(adfig, decimal-leading-zero);
	display: block;
	font-family: var(--wp--preset--font-family--mono);
	font-size: 0.67rem;
	letter-spacing: 0.14em;
	text-transform: uppercase;
	color: var(--wp--preset--color--slate);
	margin-bottom: 0.7rem;
}
.article-content :where(figure.wp-block-image) > img,
.article-content > :where(img) {
	display: block;
	max-width: 100%;
	height: auto;
	/* Keep a tall/portrait image from dominating the viewport; aspect ratio
	   is preserved because width stays intrinsic and height is auto. */
	max-height: 70vh;
	width: auto;
	margin-inline: auto;
	border-radius: var(--wp--custom--radius--card);
}
.article-content :where(figure.wp-block-image) figcaption {
	max-width: 760px;
	margin: 0.7rem auto 0;
	text-align: center;
	font-size: 0.85rem;
	color: var(--wp--preset--color--slate);
}
@media (max-width: 781px) {
	/* On mobile, full column width and a tighter height ceiling so images
	   reflow cleanly instead of pushing text far down the page. */
	.article-content :where(figure.wp-block-image) { max-width: 100%; }
	.article-content :where(figure.wp-block-image) > img,
	.article-content > :where(img) { max-height: 60vh; }
}

/* Legacy-Safari fallback (Safari <14 drops :where() rules wholesale, killing the image
   cap; <14.1 lacks margin-inline). Values identical to the modern rules above, so this
   changes nothing in current browsers — it only restores the cap where :where() dies. */
.article-content figure.wp-block-image { max-width: 760px; max-width: min(100%, 760px); margin-left: auto; margin-right: auto; }
.article-content figure.wp-block-image > img { display: block; max-width: 100%; height: auto; margin-left: auto; margin-right: auto; }
.article-content img { max-width: 100%; height: auto; }

/* ----- Figure overflow guard (audit P1; sub-pass 1) -------------------------
   Some generated .wwd-fig figures use fixed multi-column grids + large inner
   padding (e.g. pgfig-cap-ai-systems-catalog: a 4-col grid in a wrap with 44px
   side padding) that don't collapse on mobile and push the page wider than the
   viewport. Constrain them so no figure causes horizontal scroll. !important is
   needed to beat the per-figure id-scoped rules; sub-pass 2 hoists these rules to
   class selectors and drops the !important. */
.wwd-fig { max-width: 100%; }
@media (max-width: 640px) {
	.wwd-fig .grid { grid-template-columns: repeat(2, 1fr) !important; }
	.wwd-fig .wrap { padding-left: 18px !important; padding-right: 18px !important; }
}
@media (max-width: 400px) {
	.wwd-fig .grid { grid-template-columns: 1fr !important; }
}

/* ----- Reusable section backgrounds + bullets (built for the content pass; NOT applied yet) */
.ad-bg-white { background: #FFFFFF; }
.ad-bg-tint  { background: #F7F9FC; }
.ad-bg-navy  { background: #0B1220; color: var(--wp--preset--color--light-text); }
.ad-bg-navy :where(h1, h2, h3) { color: #fff; }
.ad-bg-navy .ad-eyebrow { color: var(--wp--preset--color--mono-on-navy); }
.ad-bullets { list-style: none; margin: var(--block-gap) 0 0; padding: 0; display: grid; gap: 0.7rem; }
.ad-bullets li { display: grid; grid-template-columns: 18px 1fr; gap: 0.6rem; color: var(--wp--preset--color--slate); font-size: 1rem; }
.ad-bullets li svg { width: 16px; height: 16px; margin-top: 3px; color: var(--wp--preset--color--primary); flex: none; }
/* Wrapping chip set — chips never overflow a single row. */
.ad-chips--wrap { display: flex; flex-wrap: wrap; gap: 0.5rem; }

/* ----- Figure caption/label contrast (audit P1; ground-aware) ---------------
   Figure caption/label text (.sub / .tlab) is the design muted #8A97AD, which is
   2.82:1 on LIGHT figure grounds (fails WCAG AA). Use a darker muted that clears
   >=4.5:1 on both white and the #F7F9FC tint, applied to light-ground figures ONLY.
   The one dark-ground figure whose .sub sits inside a navy .wrap
   (#pf-cap-ai-systems-catalog) is excluded, so its text stays the bright muted and
   does not regress on navy. theme.css-only (no figure files touched); !important
   beats the per-figure id-scoped color rule. Sub-pass-2 hoist will systematize this. */
:root { --ad-fig-muted-light: #5C6878; } /* >=4.5:1 on #FFFFFF and #F7F9FC */
.wwd-fig .tlab { color: var(--ad-fig-muted-light) !important; }
.wwd-fig:not(#pf-cap-ai-systems-catalog) .sub { color: var(--ad-fig-muted-light) !important; }

/* ----- Figure + input box model (mobile horizontal-scroll fix) --------------
   The inlined figures lost their source *{box-sizing:border-box} during generation, so
   width:100% containers (.wrap) overflowed by their padding (~14px), the testimonials
   .feat flex (its .q has max-width:62ch) couldn't shrink (~194px), and the contact inputs
   overflowed by padding (~10px). Restore the box model + let flex/grid children shrink so
   no figure or field pushes the page wider than the mobile viewport. */
.wwd-fig, .wwd-fig *, .wwd-fig *::before, .wwd-fig *::after { box-sizing: border-box; }
.wwd-fig .wrap, .wwd-fig .feat, .wwd-fig .grid { max-width: 100%; }
.wwd-fig .grid > *, .wwd-fig .feat, .wwd-fig .feat > * { min-width: 0; }
.ad-field input, .ad-field textarea { box-sizing: border-box; }

/* ----- Figure CSS hoist (docs/BACKLOG.md P1, first slice) -------------------
   scripts/inline_wwd_figures.py / inline_page_figures.py scope every source
   visual's CSS under a per-figure #id, so byte-identical declarations were
   duplicated once per figure that used them (measured across all 38 figures:
   these 5 selectors repeat 8-26 times each, ~190KB of per-figure inline CSS
   totalled before this hoist). Hoisted here as .wwd-fig-scoped class rules;
   the inliner now skips emitting an exact match so future regenerations stay
   in sync. Deliberately does NOT touch the #id-scoped display/margin/max-width
   wrapper boilerplate or any figure's own distinct .eyebrow/.wrap variant (those
   carry extra properties, e.g. font-size/color/background, and are NOT
   duplicates) — the wrapper rule specifically interacts with the mobile
   overflow-guard rules above (max-width:100% vs the per-figure 1200px, plus
   !important cascade), which its own comment already flags as a distinct,
   not-yet-done "sub-pass 2" — bundling that into this pass would risk
   reintroducing the mobile horizontal-scroll bug that guard fixed. */
.wwd-fig text { font-family: var(--sans); }
.wwd-fig svg { display: block; width: 100%; height: auto; }
.wwd-fig .viz { width: 100%; max-width: 1200px; margin: 0 auto; font-family: var(--sans); }
.wwd-fig .eyebrow { font-family: var(--mono); font-weight: 500; letter-spacing: .22em; }
.wwd-fig .wrap { width: 100%; max-width: 1200px; margin: 0 auto; padding: 8px 4px; }

/* ----- Figure CSS consolidation, pgfig-*.php slice (Task 3) -----------------
   Read all 32 pgfig-*.php <style> blocks: the --sans/--mono custom-property
   pair is the ONLY remaining rule that's genuinely 100%-identical across
   every single file (verified: exact same value, zero variance, 32/32).
   Hoisted here so var(--sans)/var(--mono) above (and any figure-local use)
   still resolves via normal inheritance once each file's own declaration is
   removed. Everything else found duplicated-looking was deliberately left
   alone as a real, reported exception, not silently forced into a shared
   rule:
   - The --navy/--card/--surface/--ink/--muted/--hair/--blue/--teal/--alert
     custom-property SETS vary by figure (dark-ground vs light-ground token
     combinations, several distinct --muted values) — these correspond to
     real design intent (which background a figure renders on), and touch
     the unresolved two-palette-drift question in docs/BACKLOG.md/
     DECISIONS.md. Not this pass's call to make.
   - An 8-file ".eyebrow{...font-size:13px;color:var(--blue)}" full variant
     looked shareable at first glance, but is NOT safe to hoist as a second
     global ".wwd-fig .eyebrow" rule: the 24 OTHER figures use the shorter
     3-property .eyebrow rule above, and a same-specificity, later-declared
     rule would leak font-size/color onto all of them too — a real visual
     regression, not just extra bytes. Doing this safely needs a dedicated
     modifier class added to each of those 8 figures' own markup (not a
     CSS-only change), out of scope for a "consolidate the <style> blocks"
     pass. Flagged, not done. */
.wwd-fig { --sans: "Hanken Grotesk", ui-sans-serif, system-ui, sans-serif; --mono: "JetBrains Mono", ui-monospace, monospace; }

/* ----- Figure CSS consolidation, pgfig-*.php slice (Task 3, sub-pass 2) -----
   The #id-scoped "display:block;margin:2.25rem auto;max-width:1200px" wrapper rule
   (verified byte-identical across all 32 pgfig-*.php figures) was deliberately left
   out of the first pass because of its ID selector's specificity (1,0,0) vs the
   Figure overflow guard's ".wwd-fig{max-width:100%}" (0,1,0) above — an ID always
   wins over a class regardless of source order, so that guard rule already has
   ZERO effect on any figure's outer max-width today; it only ever fires on the
   .grid/.wrap DESCENDANT selectors below it, which use !important and don't
   overlap these three properties.
   A first attempt hoisted this to a bare ".wwd-fig{...}" rule and proved it via
   visual:diff — home/capability/article passed at ~0%, but "about" (the one page
   whose 7 pgfig-about-* figures sit directly inside a WP is-layout-constrained
   group) came back 108px shorter, reproducibly (confirmed via a revert-and-recapture
   isolation test, not assumed). Root cause, found by walking document.styleSheets
   for every rule actually matching one of the shrunk figures: WordPress's own
   global-styles reset ":root :where(.is-layout-constrained) > :last-child
   {margin-block-end:0}" (and its is-layout-flow twin) matches any pgfig-about-*
   figure that's the sole/last child of its content group — which most of them
   are. ":last-child" is a real pseudo-class (unlike the zero-cost ":where()" it
   sits outside of), so this selector's specificity is (0,2,0) — one whole tier
   above a bare class rule, and even above "figure.wwd-fig" (0,1,1), which a
   first fix attempt tried and which still lost. The old ID-scoped rule's
   (1,0,0) had always unconditionally beaten this regardless. Fixed with
   !important on these three properties — the same idiom the Figure overflow
   guard above already uses for the identical reason (beating a per-figure/
   context rule whose exact specificity isn't worth chasing further up the
   tier ladder). Re-verified clean afterward (0 regression, all 4 baseline
   pages incl. "about", see docs/measurement/UI-STRUCTURE-IMPROVEMENTS-FINDINGS.md,
   Task 3 sub-pass 2). */
figure.wwd-fig { display: block !important; margin: 2.25rem auto !important; max-width: 1200px !important; }

/* ----- Part-1 export visuals: shared motion + responsive wrappers -----------
   motion.css (reduced-motion-gated dashed "thread" animation, used by the
   network-of-specialists + system visuals) + box model for inlined HTML partials
   (the comparison table) so they never overflow the mobile viewport. */
@media (prefers-reduced-motion: no-preference) {
	.thread { stroke-dasharray: 4 6; animation: ad-dash 2.6s linear infinite; }
	@keyframes ad-dash { to { stroke-dashoffset: -40; } }
}

/* Personalization Engine — hero token swap. Opacity-only fade (no layout properties → CLS-safe),
   gated to no-preference so reduced-motion gets an instant swap. JS toggles inline opacity; this
   just supplies the transition. See assets/js/personalization.js + docs/ui-standards.md §1. */
@media (prefers-reduced-motion: no-preference) {
	[data-personalization-token] { transition: opacity 200ms ease; }
}
.ad-cmp, .ad-cmp * { box-sizing: border-box; }
.ad-cmp { max-width: 100%; }
.ad-cmp [style*="grid-template-columns"] { max-width: 100%; }

/* ----- Articles index — horizontal cards (thumb left, text right; stack on mobile) ----- */
.ad-artcard { display: flex; gap: 1.5rem; align-items: flex-start; border-top: 1px solid var(--wp--preset--color--line); padding: 1.75rem 0; margin: 0; }
.wp-block-post:first-child .ad-artcard { border-top: 0; }
.ad-artcard__thumb { flex: 0 0 190px; max-width: 190px; margin: 0; }
.ad-artcard__thumb a, .ad-artcard__thumb svg { display: block; width: 100%; height: auto; }
.ad-artcard__thumb svg { border-radius: 10px; border: 1px solid var(--wp--preset--color--line); }
.ad-artcard__body { flex: 1 1 auto; min-width: 0; margin: 0; }
.ad-artcard__body > * { margin-top: 0; }
.ad-artcard__body .ad-cat { margin-bottom: 0.35rem; }
@media (max-width: 680px) {
	.ad-artcard { flex-direction: column; gap: 0.9rem; }
	.ad-artcard__thumb { flex: none; max-width: 100%; width: 100%; }
}
/* Category-archive header hero — the capability's signature capfig (DESIGN-STANDARDS §3:
   centered, capped, viewBox-scaled so zero layout shift; inline SVG so nothing to lazy-load). */
.ad-cap-hero { margin: 1.25rem auto 0; max-width: min(100%, 760px); min-width: 0; }
.ad-cap-hero svg { display: block; width: 100%; height: auto; }
/* Standardized to the one width scale DESIGN-STANDARDS.md §3 documents (min(100%,760px)) —
   was the lone 520px outlier vs. .article-content figures and .ad-cap-hero, both already 760.
   No template currently applies this class (dead rule today), so the change is zero-risk. */
.ad-post-thumb { margin: 0 0 1.75rem; max-width: min(100%, 760px); }
.ad-post-thumb svg { display: block; width: 100%; height: auto; border-radius: 12px; border: 1px solid var(--wp--preset--color--line); }

/* ----- Single post layout — editorial typography system (2026-07-03) -----------------
   Body copy runs on Hanken Grotesk (the site's own body sans — already self-hosted,
   zero new font requests) instead of the thin Spectral serif. One vertical rhythm:
   1.25rem between flow blocks, 2.75rem before H2 sections, tight heading leading,
   ~70ch measure, 1.62 body line-height. */
.ad-single__body { min-width: 0; }
.ad-single__body .wp-block-post-title { font-size: clamp(1.9rem, 3.5vw, 2.6rem); line-height: 1.13; letter-spacing: -0.015em; margin-bottom: 0; text-wrap: balance; }
.ad-single__body .wp-block-post-date,
.ad-single__body .wp-block-post-author-name { font-size: var(--wp--preset--font-size--small); color: var(--wp--preset--color--muted); }
.ad-single__body .article-content { font-family: var(--wp--preset--font-family--body); font-size: 1.125rem; color: var(--wp--preset--color--ink); }
.ad-single__body .article-content > * { max-width: 70ch; }
.ad-single__body .article-content p { line-height: 1.62; margin-top: 1.25rem; margin-bottom: 0; }
/* Content hierarchy: display face, tight leading, decisive size steps (H2 > H3 > H4). */
.ad-single__body .article-content h2 { font-size: 1.6rem; font-weight: 700; margin: 2.75rem 0 0; font-family: var(--wp--preset--font-family--display); line-height: 1.22; letter-spacing: -0.012em; text-wrap: balance; }
.ad-single__body .article-content h3 { font-size: 1.25rem; font-weight: 600; margin: 2rem 0 0; font-family: var(--wp--preset--font-family--display); line-height: 1.3; }
.ad-single__body .article-content h4 { font-size: 1.06rem; font-weight: 600; margin: 1.6rem 0 0; font-family: var(--wp--preset--font-family--display); line-height: 1.35; }
.ad-single__body .article-content h2 + p,
.ad-single__body .article-content h3 + p,
.ad-single__body .article-content h4 + p { margin-top: 0.65rem; }
/* Lists: markers outside so wrapped lines align under the TEXT, tabular numbers on
   ordered markers, consistent inter-item spacing. */
.ad-single__body .article-content ul,
.ad-single__body .article-content ol { font-size: inherit; line-height: 1.62; padding-inline-start: 1.6rem; margin: 1.25rem 0 0; }
.ad-single__body .article-content li { margin-top: 0.55rem; padding-inline-start: 0.2rem; }
.ad-single__body .article-content li > ul,
.ad-single__body .article-content li > ol { margin-top: 0.55rem; }
.ad-single__body .article-content ol li::marker { font-variant-numeric: tabular-nums; font-weight: 600; color: var(--wp--preset--color--slate); }
.ad-single__body .article-content ul li::marker { color: var(--wp--preset--color--primary); }
/* Pull-quote treatment: upright, larger, display face — reads as an intentional
   editorial device, not default italic. */
.ad-single__body .article-content blockquote { border-left: 3px solid var(--wp--preset--color--primary); background: var(--wp--preset--color--tint); border-radius: 0 var(--wp--custom--radius--card) var(--wp--custom--radius--card) 0; padding: 1.1rem 1.4rem; margin: 2rem 0 0; color: var(--wp--preset--color--ink); font-style: normal; }
.ad-single__body .article-content blockquote p { font-family: var(--wp--preset--font-family--display); font-size: 1.2rem; line-height: 1.5; margin: 0; }
.ad-single__body .article-content blockquote p + p { margin-top: 0.75rem; }
.ad-single__body .article-content blockquote cite { display: block; margin-top: 0.6rem; font-size: 0.85rem; font-style: normal; color: var(--wp--preset--color--slate); }
/* In-content links: visible affordance without noise. */
.ad-single__body .article-content a { color: var(--wp--preset--color--primary); text-decoration: underline; text-decoration-thickness: 1px; text-underline-offset: 0.16em; text-decoration-color: color-mix(in srgb, var(--wp--preset--color--primary) 45%, transparent); transition: text-decoration-color 0.15s ease; }
.ad-single__body .article-content a:hover { text-decoration-color: var(--wp--preset--color--primary); }
/* Tables: usable at every width — real borders, compact type, horizontal scroll inside
   the figure wrapper instead of the page. */
.ad-single__body .article-content figure.wp-block-table { margin: 2rem 0 0; overflow-x: auto; max-width: 70ch; }
.ad-single__body .article-content table { width: 100%; border-collapse: collapse; font-size: 1rem; line-height: 1.5; }
.ad-single__body .article-content th { font-family: var(--wp--preset--font-family--display); font-weight: 600; text-align: left; }
.ad-single__body .article-content th,
.ad-single__body .article-content td { padding: 0.55rem 0.75rem; border: 1px solid var(--wp--preset--color--line); }
/* Code: mono on tint, scrolls inside its own box. */
.ad-single__body .article-content pre { margin: 1.5rem 0 0; padding: 1rem 1.15rem; background: var(--wp--preset--color--tint); border: 1px solid var(--wp--preset--color--line); border-radius: var(--wp--custom--radius--card); font-family: var(--wp--preset--font-family--mono); font-size: 0.875rem; line-height: 1.55; overflow-x: auto; }
.ad-single__body .article-content :not(pre) > code { font-family: var(--wp--preset--font-family--mono); font-size: 0.875em; background: var(--wp--preset--color--tint); border: 1px solid var(--wp--preset--color--line); border-radius: 4px; padding: 0.1em 0.35em; }
/* Section divider: quiet hairline, consistent rhythm (no phantom gaps). */
.ad-single__body .article-content hr,
.ad-single__body .article-content .wp-block-separator { border: 0; border-top: 1px solid var(--wp--preset--color--line); max-width: 70ch; margin: 2.5rem auto 1.25rem; opacity: 1; }
/* Embedded media: container-bound, fixed aspect so nothing shifts, rounded like cards. */
.ad-single__body .article-content .wp-block-embed { margin: 2rem 0 0; max-width: 70ch; }
.ad-single__body .article-content .wp-block-embed iframe,
.ad-single__body .article-content video { display: block; width: 100%; max-width: 100%; aspect-ratio: 16 / 9; height: auto; border: 0; border-radius: var(--wp--custom--radius--card); }
/* Bare content images (outside figures) stay centered and column-bound. */
.ad-single__body .article-content img { max-width: 100%; height: auto; }

/* ----- Optimization Intelligence section chrome (render-layer, not canonical copy) ----- */
/* .oi-breadcrumb was a single "back to hub" link baked into post_content by
   scripts/render_oi_pages.py's chrome_breadcrumb() — not a real breadcrumb trail. Superseded
   2026-07-08 by a genuine alexdesigns/breadcrumbs block in templates/oi-page.html (Home >
   Optimization Intelligence > [page]). Hidden rather than deleted for the same reason as
   .oi-subnav above: baked into already-pushed post_content, and this pass makes no WordPress
   content writes. chrome_breadcrumb() is no longer called for any future push. */
.oi-breadcrumb { display: none; }
/* Scoped under .ad-single__body .article-content (3 classes) — NOT just .oi-breadcrumb /
   .oi-cta__ctxlink / .oi-cta__secondary a (1-2 classes) — so these OI-specific link colors
   reliably beat the generic prose-link rule below (.ad-single__body .article-content a, 2
   classes + a tag), which OI pages also match since they render inside .article-content too.
   Confirmed via Lighthouse on staging (2026-07-03): the under-specified versions were losing
   that cascade, silently rendering the primary blue link color on the dark CTA background —
   a real 2.84:1 contrast failure (needs 4.5:1) on .oi-cta__ctxlink and .oi-cta__secondary a. */
.ad-single__body .article-content .oi-breadcrumb a { color: var(--wp--preset--color--muted); text-decoration: none; }
.ad-single__body .article-content .oi-breadcrumb a:hover { color: var(--wp--preset--color--primary); }
.ad-single__body .article-content .oi-cta { margin: 3rem 0 0; max-width: 70ch; }
.oi-cta__context { margin: 0.85rem 0 0; }
.ad-single__body .article-content .oi-cta__ctxlink { color: #E6EDF6; font-weight: 600; text-decoration: underline; text-underline-offset: 0.16em; }
.ad-single__body .article-content .oi-cta__ctxlink:hover { color: #ffffff; }
.oi-cta__secondary { margin: 1rem 0 0; }
.ad-single__body .article-content .oi-cta__secondary a { color: var(--wp--preset--color--mono-on-navy); font-size: 0.9rem; text-decoration: none; }
.ad-single__body .article-content .oi-cta__secondary a:hover { color: #ffffff; }
.ad-single__body .article-content .oi-section-nav { margin: 2.5rem 0 0; max-width: 70ch; border-top: 1px solid var(--wp--preset--color--line); padding-top: 1.5rem; }
.oi-section-nav ul { list-style: none; margin: 0.75rem 0 0; padding: 0; }
.oi-section-nav li { border-top: 1px solid var(--wp--preset--color--line); }
.oi-section-nav li:first-child { border-top: none; }
.oi-section-nav a { display: inline-flex; align-items: center; min-height: 44px; color: var(--wp--preset--color--slate); font-weight: 500; text-decoration: none; }
.oi-section-nav a:hover { color: var(--wp--preset--color--primary); }

/* Former persistent OI subnav (§16 Part 2) — was a sticky bar INSIDE post_content (buried
   below the H1, confined to the 70ch article column instead of sitting under the global
   header). SUPERSEDED 2026-07-08 (feat/wpc-oi-section-layout-consistency) by the
   template-level .oi-topnav component (templates/oi-page.html + the alexdesigns/oi-section-nav
   block in functions.php), which renders directly below the header on every OI page. This
   selector is CSS-hidden rather than deleted: the markup itself is baked into already-pushed
   post_content (scripts/oi_topic_registry.py's render_subnav(), still present in already-live/
   drafted pages) and this pass makes no WordPress content writes — hiding it here is the
   correct theme-only way to suppress the now-duplicate element without touching WP content.
   scripts/oi_topic_registry.py's render_subnav() and its two callers no longer emit this markup
   for any FUTURE push, so this hidden rule is a bridge for existing content only, not a
   permanent fixture. Scoped the same 3-class-deep way as the CTA rules above for the same
   cascade-specificity reason (confirmed 2026-07-03 Lighthouse finding) — display:none needs to
   win the same way color/background overrides did. */
.ad-single__body .article-content .oi-subnav {
	display: none;
}
.oi-subnav__list {
	display: flex;
	gap: 0.25rem;
	list-style: none;
	margin: 0;
	padding: 0.5rem 0;
	overflow-x: auto; /* scrolls INSIDE the subnav strip only — never the page body */
	-webkit-overflow-scrolling: touch;
	scrollbar-width: thin;
}
.oi-subnav__item { flex: 0 0 auto; }
.oi-subnav__link {
	display: inline-flex;
	align-items: center;
	min-height: 44px; /* touch-target minimum, matches .oi-section-nav a above */
	padding: 0.4rem 0.85rem;
	border-radius: var(--wp--custom--radius--pill, 999px);
	color: var(--wp--preset--color--slate);
	font-weight: 500;
	font-size: 0.9rem;
	text-decoration: none;
	white-space: nowrap;
}
.oi-subnav__link:hover { color: var(--wp--preset--color--primary); }
.oi-subnav__link:focus-visible { outline: 2px solid var(--wp--preset--color--primary); outline-offset: 2px; }
.oi-subnav__link--current {
	color: var(--wp--preset--color--primary);
	background: var(--wp--preset--color--tint);
	font-weight: 700;
}

/* ----- OI mobile section nav — .oi-mobile-nav (2026-07-09, feature/oi-right-rail-shell) -----
   MOBILE-ONLY now. Desktop OI navigation moved to the right rail's sticky "IN THIS SECTION"
   card (.oi-section-nav below) per the Claude Design right-rail-shell handoff — this
   supersedes the 2026-07-09 (feat/oi-shell-standardization) horizontal desktop bar +
   Topics-dropdown pattern, which is fully removed (not hidden) here. Rendered in-flow inside
   <main>, after the hero (templates/oi-page.html), not as a template-level sibling of it —
   the old desktop bar needed that position to sit directly under the header; the mobile
   accordion doesn't. Non-sticky by design (the handoff's own stated preference: "prefer
   non-sticky mobile" — a compact collapsed control could be made sticky later without
   crowding the viewport, but isn't by default here). */
.oi-mobile-nav { display: none; } /* desktop: hidden entirely — .oi-section-nav in the rail is the nav */
.oi-mobile-nav__inner {
	max-width: 1240px;
	margin: 0 auto;
	padding: 0.6rem clamp(22px, 5vw, 48px);
}
.oi-mobile-nav__toggle {
	display: flex;
	width: 100%;
	align-items: center;
	justify-content: space-between;
	gap: 0.5rem;
	background: var(--wp--preset--color--paper);
	border: 1px solid var(--wp--preset--color--line);
	border-radius: var(--wp--custom--radius--card);
	padding: 0.7rem 0.9rem;
	cursor: pointer;
	text-align: left;
}
.oi-mobile-nav__toggle-label {
	font-family: var(--wp--preset--font-family--mono);
	font-size: 0.7rem;
	font-weight: 600;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: var(--wp--preset--color--muted);
}
.oi-mobile-nav__toggle-current {
	flex: 1 1 auto;
	font-weight: 600;
	color: var(--wp--preset--color--ink);
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
}
.oi-mobile-nav__toggle svg { transition: transform 0.15s ease; flex: 0 0 auto; }
.oi-mobile-nav__toggle[aria-expanded="true"] svg { transform: rotate(180deg); }
.oi-mobile-nav__toggle:focus-visible { outline: 2px solid var(--wp--preset--color--primary); outline-offset: 2px; }
.oi-mobile-nav__list {
	display: none; /* collapsed by default; opened via [aria-expanded="true"] + list below */
	flex-direction: column;
	list-style: none;
	margin: 0.35rem 0 0;
	padding: 0;
	border: 1px solid var(--wp--preset--color--line);
	border-radius: var(--wp--custom--radius--card);
	overflow: hidden;
}
.oi-mobile-nav__toggle[aria-expanded="true"] + .oi-mobile-nav__list { display: flex; }
.oi-mobile-nav__item { border-top: 1px solid var(--wp--preset--color--line); }
.oi-mobile-nav__item:first-child { border-top: 0; }
.oi-mobile-nav__group-label {
	padding: 0.5rem 0.9rem 0.25rem;
	font-family: var(--wp--preset--font-family--mono);
	font-size: 0.65rem;
	font-weight: 600;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: var(--wp--preset--color--muted);
	border-top: 1px solid var(--wp--preset--color--line);
}
.oi-mobile-nav__link {
	display: block;
	min-height: 44px;
	display: flex;
	align-items: center;
	padding: 0.55rem 0.9rem;
	color: var(--wp--preset--color--slate);
	font-weight: 500;
	text-decoration: none;
}
.oi-mobile-nav__link:hover { color: var(--wp--preset--color--primary); }
.oi-mobile-nav__link:focus-visible { outline: 2px solid var(--wp--preset--color--primary); outline-offset: -2px; }
.oi-mobile-nav__link--current { color: var(--wp--preset--color--primary); font-weight: 700; background: var(--wp--preset--color--paper); }
@media (max-width: 782px) {
	/* 2026-07-10 (Alex's request): sticky on mobile now — was deliberately non-sticky per the
	   original handoff's stated preference (see this block's own comment above), reversed on
	   Alex's explicit instruction this pass. top offset = the real measured mobile header
	   height at this breakpoint (Playwright, getBoundingClientRect on the live header at
	   390px — 73.75px, NOT the desktop 68px other sticky elements on this page use, and NOT
	   an earlier 56px guess this comment used to state before that measurement caught it).
	   Needs its own opaque background (paper, matching the page background) since content
	   scrolls underneath it once sticky — without one the sticky bar would look see-through. */
	.oi-mobile-nav {
		display: block;
		position: sticky;
		top: var(--ad-header-height-mobile, 74px);
		z-index: 40;
		background: var(--wp--preset--color--paper);
	}
}

/* ----- OI right rail: two zones (2026-07-09, feature/oi-right-rail-shell) -----------------
   .oi-right-rail itself is NOT sticky — a fully-sticky rail was tried in an earlier pass and
   created footer-overlap/viewport-height problems as the context stack grew (Alex's explicit,
   final decision). Only .oi-rail-nav-sticky (Zone 1, the "IN THIS SECTION" card) is
   position:sticky; .oi-rail-context-stack (Zone 2, System View/Problems Solved/current-
   discipline/start-here/related-disciplines) stays in normal static flow below it. Desktop
   only — no right rail renders on mobile at all (the column collapses via .oi-layout's own
   existing mobile stack rules); .oi-mobile-nav above is mobile's entire OI-nav surface.

   TWO real bugs found and fixed testing this, both about height, not just position:
   1. The handoff's own suggested concept CSS put align-self:start on .oi-right-rail — tested
      it directly: it makes the WP column (.oi-layout__rail) shrink to the rail's own short
      content height instead of stretching to match .oi-layout__main. NOT used here; no
      align-self override at all, so the column keeps flexbox's default stretch behavior.
   2. That alone wasn't enough — confirmed via getBoundingClientRect() that even with the
      COLUMN correctly stretched to main's full height, .oi-right-rail (a block-level child of
      a block-level column) still only took its own natural content height, not its parent's
      stretched height, so the sticky nav's positioning context (its own immediate parent)
      still ended early and it scrolled away mid-page regardless. height:100% below makes
      .oi-right-rail actually fill that already-stretched column, giving .oi-rail-nav-sticky
      room to stay stuck for the real, full scroll range. Verified: nav visible at multiple
      scroll depths on a long page, correctly un-sticks and scrolls away only once the actual
      bottom of the (now tall) rail column is reached — never overlapping the footer. */
.oi-right-rail { height: 100%; }
.oi-rail-nav-sticky {
	position: sticky;
	/* Real measured .ad-header height (68px, Playwright getBoundingClientRect, 2026-07-09) +
	   the repo's own --wp--preset--spacing--50 token (1.5rem/24px) -- matches the handoff's
	   suggested "site-header-height + space-6" shape using this repo's real values instead of
	   the handoff's placeholder --site-header-height/--space-6 vars, which don't exist here. */
	top: calc(68px + var(--wp--preset--spacing--50, 1.5rem));
	max-height: calc(100vh - 68px - 48px);
	overflow: auto;
	z-index: 5;
}
.oi-rail-context-stack {
	position: static;
	margin-top: var(--wp--preset--spacing--60, 2rem); /* repo's real "space-8"-equivalent token, 32px */
}
.oi-section-nav {
	background: var(--wp--preset--color--paper);
	border: 1px solid var(--wp--preset--color--line);
	border-radius: var(--wp--custom--radius--card);
	padding: 1rem;
}
.oi-section-nav__label {
	margin: 0 0 0.6rem;
	font-family: var(--wp--preset--font-family--mono);
	font-size: 0.68rem;
	font-weight: 600;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	color: var(--wp--preset--color--muted);
}
.oi-section-nav__list { list-style: none; margin: 0; padding: 0; }
.oi-section-nav__item { margin: 0; }
.oi-section-nav__group-label {
	padding: 0.6rem 0.5rem 0.3rem;
	font-family: var(--wp--preset--font-family--mono);
	font-size: 0.62rem;
	font-weight: 600;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: var(--wp--preset--color--muted);
}
.oi-section-nav__group-label--active { color: var(--wp--preset--color--primary); }
.oi-section-nav__link {
	display: block;
	padding: 0.45rem 0.5rem;
	border-radius: var(--wp--custom--radius--card);
	color: var(--wp--preset--color--slate);
	font-weight: 500;
	font-size: 0.9rem;
	text-decoration: none;
	min-height: 40px;
	display: flex;
	align-items: center;
}
.oi-section-nav__link:hover { background: var(--wp--preset--color--tint, var(--wp--preset--color--paper)); color: var(--wp--preset--color--primary); }
.oi-section-nav__link:focus-visible { outline: 2px solid var(--wp--preset--color--primary); outline-offset: -2px; }
.oi-section-nav__link--current {
	color: var(--wp--preset--color--primary);
	background: var(--wp--preset--color--base, #fff);
	font-weight: 700;
}
@media (max-width: 782px) {
	.oi-right-rail { display: none; } /* mobile: .oi-mobile-nav is the entire OI-nav surface */
}

/* ----- OI hero hierarchy + two-column rail (feat/oi-rail-and-hero, 2026-07-06) ---------
   Hero eyebrow sits above the page H1 (templates/oi-page.html's oi-hero-wrap group). Wrap
   itself is wide-aligned (1240px, matching .oi-layout below — 2026-07-08 consistency fix; it
   was previously a narrower, independently-centered 760px box, so its left edge did NOT match
   the body grid's left edge, a real misalignment).
   2026-07-09: the "> * { max-width: 70ch }" reading-width rule this comment used to describe
   is REPLACED, not just deleted, with an explicit "> * { max-width: none }" reset below.
   .oi-hero-wrap's only 3 direct children today (breadcrumb, this topic label, the H1) are a
   nav trail, a one-line label, and a heading; none is prose that benefits from a 70-character
   reading-width cap, and at the breadcrumb/label's small font size 70ch resolved to a much
   narrower pixel width than at the H1's large font size (where it was already a no-op) --
   combined with the layout's auto-margin centering, that is what produced the desktop-only
   left-indent on the breadcrumb and eyebrow. Simply DELETING the 70ch rule (tried first) was
   not enough: it had been the thing WINNING the cascade over WordPress's own auto-generated
   ".is-layout-constrained > :where(...)" rule (max-width: content-size, margin-left: auto,
   same specificity, earlier source order) -- removing it with nothing to replace it exposed
   THAT rule instead, which newly constrained the H1 to 720px and centered it (verified via a
   real render, not assumed: this second bug only showed up once actually rendered, exactly
   the kind of thing a computed-style-only check would miss). This explicit reset closes that
   gap for all 3 children at once. If a future prose child is ever added directly here, give
   IT its own scoped max-width -- don't reintroduce a blanket 70ch (or any) cap on `> *`. */
/* 2026-07-10 (Alex's mobile-order request): rebuilt as a real CSS Grid with named areas —
   eyebrow, callout, and H1 are now three independent direct children of .oi-hero-grid (the
   .oi-hero-wrap grouping div is gone from the template), because the desktop and mobile
   orders now genuinely DIFFER: mobile is eyebrow -> callout -> H1 (matching the dropdown-
   before-hero sequence above), desktop keeps the original "H1+eyebrow together on the left,
   callout beside them on the right" look. A flex layout can't express two different child
   ORDERS at two breakpoints without a `order:` property per item per breakpoint (fragile,
   easy to get wrong); grid-template-areas states each layout directly and is what this
   codebase already reaches for when a real 2D layout is needed (see .oi-content-footer). */
.oi-hero-grid {
	display: grid;
	grid-template-areas: "eyebrow" "callout" "h1";
	gap: 1rem;
	align-items: start;
}
/* Same D8-class reset the old .oi-hero-wrap needed: WP's auto-generated is-layout-constrained
   rule (max-width: content-size, margin-inline: auto) targets ANY direct, non-align child of a
   constrained group, so it would otherwise fight the grid-area placement below. */
.oi-hero-grid > * { max-width: none; margin-inline: 0; }
@media (min-width: 783px) {
	.oi-hero-grid {
		grid-template-columns: 1fr 340px;
		grid-template-areas: "eyebrow callout" "h1 callout";
		gap: 0 2.5rem;
	}
}
.oi-hero-grid > .oi-hero-eyebrow__topic { grid-area: eyebrow; }
.oi-hero-grid > .oi-hero-callout { grid-area: callout; }
.oi-hero-grid > .wp-block-post-title { grid-area: h1; margin: 0; }
/* Hero "Problems Solved" callout (Items 1–3, D13/D14; grid-placed 2026-07-10) — rendered by
   alexdesigns/oi-hero-problems-callout, a grid item of .oi-hero-grid above (no independent
   width/centering math needed — it inherits the grid's real content-column left edge, which is
   what fixes the old mobile left-alignment bug: the previous standalone version used its own
   viewport-relative clamp() inset instead of the shared content-column edge).
   "Digital note" treatment: dashed border (not solid — reads as an annotation/aside, matching
   the site's existing dashed-border convention for supplementary/non-primary elements, e.g.
   .ad-photo-slot) + a background tint distinct from the page background (page bg =
   --color--paper per theme.json; this uses --color--surface, a second, slightly deeper tint,
   so the callout visibly separates from the page instead of blending into it). */
.oi-hero-callout {
	width: 100%;
	max-width: 360px;
	margin: 0;
	padding: 1.1rem 1.4rem;
	background: var(--wp--preset--color--surface);
	border: 1px dashed var(--wp--preset--color--line);
	border-radius: var(--wp--custom--radius--card);
	box-sizing: border-box;
}
.oi-hero-callout p, .oi-hero-callout ul { margin: 0; }
.oi-hero-callout .oi-rail__label { margin-bottom: 0.5rem; }
/* 2026-07-09 (Item 1): body/bullets weren't given their own font-size before, so they
   inherited the page's normal body/medium size (~1.06rem) -- too large for a compact
   note-style aside next to the H1. Reuses 0.9rem/0.85rem directly, not new arbitrary values --
   these are the SAME sizes .oi-rail__body/.oi-rail__bullets already use elsewhere in this file
   for the identical "compact rail card" role, so this callout now matches the rest of the
   design system's existing note-scale convention instead of inventing a fourth size. Both stay
   well above the ~12px accessible-text floor (0.85rem = 13.6px at the 16px root). */
.oi-hero-callout__body { color: var(--wp--preset--color--slate); font-size: 0.9rem; line-height: 1.55; }
.oi-hero-callout__bullets { list-style: none; padding: 0; display: flex; flex-direction: column; gap: 0.35rem; font-size: 0.85rem; line-height: 1.5; }
.oi-hero-callout__bullets li { color: var(--wp--preset--color--slate); padding-left: 1rem; position: relative; }
.oi-hero-callout__bullets li::before { content: "→"; position: absolute; left: 0; color: var(--wp--preset--color--primary); }
/* Mobile: full width so its left edge matches the hero/content column exactly (inherited from
   the grid, no per-element math), max-width reset since the desktop 360px cap doesn't apply
   when it's stacked full-width. */
@media (max-width: 782px) {
	.oi-hero-callout { max-width: none; }
}
.oi-hero-eyebrow__topic {
	margin: 0 0 0.5rem;
	font-family: var(--wp--preset--font-family--display);
	font-weight: 700;
	font-size: calc(var(--wp--preset--font-size--display) / 2);
	line-height: 1.1;
	letter-spacing: -0.02em;
	color: var(--wp--preset--color--primary);
}

/* ----- OI visual system (2026-07-09, branch feature/oi-visual-system-implementation) ----
   Wrapper for every figure from this pass -- centered, capped per the placement doc's own
   rule (CLAUDE-CODE-PLACEMENT.md: "max-width:min(100%,760px); margin:2rem auto"). The SVGs
   themselves already carry width:100%/max-width inline (same convention as every other OI
   figure in design/visuals/oi/), this is the outer figure wrapper's rhythm only. */
.ad-figure--oi-visual { max-width: min(100%, 760px); margin: 2rem auto; width: 100%; }
.ad-figure--oi-visual svg { display: block; width: 100%; height: auto; }

/* Origin photo hero -- ONE responsive component (manifest §3). Real HTML/CSS caption, never
   baked into the image. 2026-07-09: shrunk from a large ~520px centered hero to a small
   float-right portrait (Alex's direct instruction) -- standard editorial float, text wraps
   left/below at desktop. Falls back to a normal small centered image at mobile (≤640px, the
   same breakpoint the component's own responsive <picture> source already uses) since a
   float-right treatment doesn't read well at narrow widths and there's no room for text to
   wrap beside it. */
.origin-hero {
	position: relative;
	max-width: 320px;
	border-radius: 16px;
	overflow: hidden;
	float: right;
	margin: 0 0 1.5rem 2rem;
}
@media (max-width: 640px) {
	.origin-hero { float: none; max-width: 260px; margin: 1.5rem auto; }
}
.origin-hero--wide { max-width: 100%; float: none; margin: 2rem auto; }
.origin-hero img { display: block; width: 100%; height: auto; }
.origin-hero figcaption {
	position: absolute; inset: auto 0 0 0; padding: 24px; color: #fff;
	font-family: var(--wp--preset--font-family--body);
	background: linear-gradient(rgba(11, 18, 32, 0), rgba(11, 18, 32, .82));
}
.origin-hero .eyebrow {
	display: block; font-family: var(--wp--preset--font-family--mono); font-size: 12px;
	letter-spacing: 2px; color: #E6EDF6; margin-bottom: 6px;
}
.origin-hero b { display: block; font-size: 30px; line-height: 1.05; font-weight: 700; }
.origin-hero .ai { color: #2DD4BF; }

/* Animation -- optional, CSS-only, prefers-reduced-motion-gated (manifest §4). Delivered
   SVGs are static; these hook classes are already baked onto the correct rim/path element
   in the 6 approved-to-animate figures only -- never diagnostics, AI Helps, the photo,
   proof strip, request flow, or report preview. Per-hook dasharray values are each figure's
   OWN measured geometry, not a single shared number: oml-rim's rim is r=150 (circumference
   ≈943); the other four circle rims are r=170 (≈1068); cc-sys is a cubic-bezier path,
   numerically measured at ≈692 (the design handoff's own CSS sample used a single shared
   1069 for all five circle+path hooks -- wrong for oml-rim and for cc-sys specifically;
   corrected here from each figure's actual geometry, not copied forward). */
.rim-rlpl, .rim-cdpal, .rim-ecll, .rim-aisrl {
	stroke-dasharray: 1068; stroke-dashoffset: 1068; animation: oi-draw 2.4s ease .15s forwards;
}
.oml-rim { stroke-dasharray: 943; stroke-dashoffset: 943; animation: oi-draw 2.4s ease .15s forwards; }
.cc-sys { stroke-dasharray: 692; stroke-dashoffset: 692; animation: oi-draw 2.6s ease .2s forwards; }
@keyframes oi-draw { to { stroke-dashoffset: 0; } }
@media (prefers-reduced-motion: reduce) {
	.rim-rlpl, .rim-cdpal, .rim-ecll, .rim-aisrl, .oml-rim, .cc-sys { animation: none; stroke-dashoffset: 0; }
}

/* Two-column OI layout: main content (left) + sticky rail (right). templates/oi-page.html's
   .oi-layout is a core wp:columns block — only the sticky/order/reading-width behavior below
   is custom; the responsive column-stacking itself is core WP behavior (isStackedOnMobile). */
/* min-width: 0 on BOTH flex items, not just the rail — flex items default to min-width: auto,
   so without this the whole column refuses to shrink below its widest descendant's min-content
   size (here: .oi-subnav's un-wrapped 8-item list) instead of letting that element's OWN
   overflow-x: auto do its job. Found live (2026-07-06): omitting this on .oi-layout__main let
   the subnav's ~706px intrinsic width push the entire mobile layout wide, a real horizontal-
   scroll regression the subnav's own CSS comment explicitly says should never happen. */
.oi-layout__main { min-width: 0; }
.oi-layout__main .article-content { max-width: 70ch; }
/* Anchor targets (H2s) inside OI content need scroll-margin-top so a clicked in-page anchor
   doesn't land underneath the combined sticky header (68px) + sticky OI subnav (87px, real
   measured heights, Playwright getBoundingClientRect, 2026-07-09) = 155px. Desktop only —
   the subnav collapses to an accordion on mobile so its sticky height there is just the
   compact toggle bar, not the full 87px; 155px is a safe upper-bound offset on mobile too
   (worst case the heading lands slightly lower than strictly necessary, never hidden).
   2026-07-09 (feature/oi-right-rail-shell): was 155px (header 68px + the old STACKED
   horizontal subnav's 87px) — that subnav no longer sits above the content column at all
   (moved into the side rail column; content and rail are side-by-side, not stacked), so
   content H2s only need to clear the global header now. */
.oi-layout__main .article-content h2 { scroll-margin-top: 88px; }
.oi-layout__rail {
	min-width: 0;
}
/* 2026-07-09 (feature/oi-right-rail-shell): the whole-column sticky rule that used to live
   here is REMOVED — Alex's explicit, final decision is that only .oi-rail-nav-sticky (inside
   .oi-right-rail, which this column wraps) is sticky, not this column itself. See the
   ".oi-right-rail" rule block above (near .oi-mobile-nav) for the current sticky
   implementation. */
/* Mobile/tablet (below WP core's own columns-stack breakpoint): 2026-07-09 (feature/oi-
   right-rail-shell) — the rail is no longer shown at all on mobile (.oi-mobile-nav in the
   content flow is the entire mobile OI-nav surface; the handoff is explicit: "No right rail
   on mobile"). Previously the rail reflowed to stacked cards above the main column; that
   reorder logic is removed along with it — .oi-layout__rail collapses to nothing rather than
   an empty column with leftover margin. */
@media (max-width: 782px) {
	/* flex-wrap: nowrap is load-bearing, not incidental: WP core's own .is-layout-flex class
	   ships flex-wrap: wrap (for its desktop columns-wrap behavior). Combined with
	   flex-direction: column here, "wrap" lets the two items wrap into a SECOND column
	   side-by-side instead of stacking into one — found live (2026-07-06): this produced a
	   ~2x-width horizontal-scroll regression (main + rail rendering as two side-by-side
	   columns, each refusing to shrink below its own content's width) that min-width: 0 alone
	   did not fix, because the real cause was the wrap axis, not item shrinking. */
	.oi-layout.wp-block-columns { flex-direction: column; flex-wrap: nowrap; }
	.oi-layout__main { width: 100%; }
	.oi-layout__rail { display: none; }
}

.oi-rail__title {
	font-family: var(--wp--preset--font-family--mono);
	font-size: 0.67rem;
	letter-spacing: 0.14em;
	text-transform: uppercase;
	color: var(--wp--preset--color--muted);
	margin: 0 0 0.65rem;
}
.oi-rail-nav__list { list-style: none; margin: 0 0 2rem; padding: 0; }
.oi-rail-nav__item { border-top: 1px solid var(--wp--preset--color--line); }
.oi-rail-nav__item:first-child { border-top: none; }
.oi-rail-nav__link {
	display: flex;
	align-items: center;
	min-height: 44px;
	color: var(--wp--preset--color--slate);
	font-weight: 500;
	text-decoration: none;
}
.oi-rail-nav__link:hover { color: var(--wp--preset--color--primary); }
.oi-rail-nav__link:focus-visible { outline: 2px solid var(--wp--preset--color--primary); outline-offset: 2px; }
.oi-rail-nav__link--current { color: var(--wp--preset--color--ink); font-weight: 700; }

.oi-rail-nav--foundation .oi-rail-nav__divider {
	border: none;
	border-top: 1px solid var(--wp--preset--color--line);
	margin: 0 0 1.5rem;
}

/* OI Overview intro link to The AlexDesigns Story (2026-07-09, feature/oi-right-rail-shell) —
   compact editorial callout, quiet by design: reuses .oi-rail__label for the "Start Here"
   mono-uppercase tag, a subtle border/background (real tokens), no large CTA-block treatment.
   Rendered by scripts/render_oi_pages.py's chrome_origin_story_callout(). */
.oi-hub-origin-callout {
	margin: 1.5rem 0 2rem;
	padding: 1rem 1.25rem;
	background: var(--wp--preset--color--paper);
	border: 1px solid var(--wp--preset--color--line);
	border-left: 3px solid var(--wp--preset--color--primary);
	border-radius: var(--wp--custom--radius--card);
}
.oi-hub-origin-callout p { margin: 0; }
.oi-hub-origin-callout .oi-rail__label { margin-bottom: 0.35rem; }
.oi-hub-origin-callout a { color: var(--wp--preset--color--primary); font-weight: 600; }

.oi-rail__card { margin: 0 0 2rem; }
.oi-rail__card:last-child { margin-bottom: 0; }
.oi-rail__label {
	font-family: var(--wp--preset--font-family--mono);
	font-size: 0.67rem;
	letter-spacing: 0.14em;
	text-transform: uppercase;
	color: var(--wp--preset--color--muted);
	margin: 0 0 0.5rem;
}
.oi-rail__body { margin: 0; font-size: 0.9rem; line-height: 1.55; color: var(--wp--preset--color--slate); }
.oi-rail__bullets { margin: 0.5rem 0 0; padding: 0 0 0 1.1rem; font-size: 0.85rem; line-height: 1.5; color: var(--wp--preset--color--slate); }
.oi-rail__links { list-style: none; margin: 0; padding: 0; }
.oi-rail__links li { border-top: 1px solid var(--wp--preset--color--line); padding: 0.55rem 0; }
.oi-rail__links li:first-child { border-top: none; }
.oi-rail__links a { color: var(--wp--preset--color--ink); font-weight: 500; text-decoration: none; }
.oi-rail__links a:hover { color: var(--wp--preset--color--primary); }
.oi-rail__note { display: block; font-size: 0.78rem; color: var(--wp--preset--color--muted); margin-top: 0.15rem; }

/* ----- OI content-footer (2026-07-09, feat/ad-oi-content-footer; refined 2026-07-10, Part F)
   The former right-rail Current Discipline Card + Related disciplines modules, relocated to
   the bottom of the main content column as one 2-column icon block (Alex's instruction, both
   modules confirmed). Same data, new presentation: side-by-side at desktop, stacked below WP
   core's 782px columns breakpoint (the same breakpoint every other 2-col element on these
   pages already uses).
   2026-07-10 (F1/F3 — Alex's live-review feedback: icon didn't align with its title, and the
   section read as "text and boxes hanging there" rather than a designed block):
   - F1 root cause: the icon sat beside the WHOLE text column (label+body stacked) with
     align-items:flex-start. The 22px icon is taller than the small mono label line, so
     top-aligning the icon against the *column* left it visually low/overhanging past the
     title instead of centered on it. Fixed by splitting each card into its own header row
     (icon + label, align-items:center — the two same-scale elements that should actually
     align) with the body/links flowing full-width below that row, not beside it.
   - F3: per DESIGN-STANDARDS.md's own documented pattern ("layered cards on tinted grounds",
     not flat/thin) — each column is now its OWN white card (--color--card) with a hairline
     border + the card radius token, sitting on the section's --color--surface tint. That
     layering (tint ground -> white card -> icon/title header -> body) is what makes it read
     as one designed block instead of loose items; previously only the outer wrapper had a
     background and the two columns had no boundary of their own. Icons: the site's existing
     inline line-icon convention (viewBox 24, stroke currentColor, 1.9 weight — nav caret,
     .cap-xcard, .ad-cta__note), primary color, in a small tinted roundel (echoes the guardrail
     -gate glyph-in-circle convention from the OI Visual System, scaled down for body content)
     rather than a bare floating icon. margin-block keeps clear separation from the body text
     above and the dark CTA band below (the filter inserts this immediately before that band).
   Deliberately NOT the dashed digital-note treatment (reserved for the hero aside — two dashed
   boxes would dilute what dashed means on these pages). */
.oi-content-footer {
	display: grid;
	grid-template-columns: 1fr 1fr;
	gap: 1.5rem;
	margin: 3rem 0;
	padding: 1.5rem;
	background: var(--wp--preset--color--surface);
	border: 1px solid var(--wp--preset--color--line);
	border-radius: var(--wp--custom--radius--cardLg, var(--wp--custom--radius--card));
	box-sizing: border-box;
}
.oi-content-footer__col {
	min-width: 0;
	background: var(--wp--preset--color--card, #fff);
	border: 1px solid var(--wp--preset--color--line);
	border-radius: var(--wp--custom--radius--card);
	padding: 1.25rem;
	box-sizing: border-box;
}
.oi-content-footer__head { display: flex; align-items: center; gap: 0.6rem; margin: 0 0 0.85rem; }
.oi-content-footer__icon {
	flex: none;
	width: 30px;
	height: 30px;
	display: flex;
	align-items: center;
	justify-content: center;
	border-radius: 50%;
	background: var(--wp--preset--color--tint, var(--wp--preset--color--surface));
	color: var(--wp--preset--color--primary);
}
.oi-content-footer__icon svg { display: block; width: 16px; height: 16px; }
/* F1 fix: WordPress's own flow-layout child-spacing rule (post_content's default
   "add margin-block-start to every block child but the first") was winning a specificity tie
   against a bare `.oi-content-footer__label { margin: 0 }` — this content is injected into
   post_content via the_content filter, so it inherits that flow context. Measured directly
   (getBoundingClientRect): that stray ~20px top margin pushed the label's line-box down,
   putting its vertical center ~10px below the icon's — the actual "icon doesn't align with
   its title" bug, not a flex alignment issue (align-items:center on .oi-content-footer__head
   was already correct). Root cause found precisely via the CSSOM (walked document.styleSheets
   for every rule actually matching the label): `.ad-single__body .article-content p` was the
   real winner — 2 classes + 1 element (0,2,1) ties a 2-class-only reset (0,2,0) at the class
   tier, then wins outright at the element tier. `.oi-content-footer .oi-content-footer__head >
   .oi-content-footer__label` (3 classes, 0,3,0) beats it cleanly at the class tier instead of
   guessing with !important. */
.oi-content-footer .oi-content-footer__head > .oi-content-footer__label {
	font-family: var(--wp--preset--font-family--mono);
	font-size: 0.67rem;
	letter-spacing: 0.14em;
	text-transform: uppercase;
	color: var(--wp--preset--color--muted);
	margin: 0;
	margin-block-start: 0;
	margin-block-end: 0;
	line-height: 1.3;
}
.oi-content-footer__body { margin: 0; font-size: 0.9rem; line-height: 1.55; color: var(--wp--preset--color--slate); }
.oi-content-footer__bullets { margin: 0.6rem 0 0; padding: 0; list-style: none; display: flex; flex-direction: column; gap: 0.5rem; }
.oi-content-footer__bullets li {
	display: flex;
	gap: 0.5rem;
	font-size: 0.9rem;
	line-height: 1.5;
	color: var(--wp--preset--color--slate);
}
.oi-content-footer__bullets li::before {
	content: "";
	flex: none;
	width: 5px;
	height: 5px;
	margin-top: 0.55em;
	border-radius: 50%;
	background: var(--wp--preset--color--primary);
}
.oi-content-footer__links { list-style: none; margin: 0.4rem 0 0; padding: 0; }
.oi-content-footer__links li { border-top: 1px solid var(--wp--preset--color--line); padding: 0.55rem 0; }
.oi-content-footer__links li:first-child { border-top: none; padding-top: 0; }
.oi-content-footer__links a { color: var(--wp--preset--color--ink); font-weight: 500; text-decoration: none; }
.oi-content-footer__links a:hover { color: var(--wp--preset--color--primary); }
.oi-content-footer__note { display: block; font-size: 0.78rem; color: var(--wp--preset--color--muted); margin-top: 0.15rem; }
@media (max-width: 782px) {
	.oi-content-footer { grid-template-columns: 1fr; }
}

/* ----- OI Related Articles (2026-07-10, Part G) -------------------------------------------
   3-card row below .oi-content-footer, before the CTA band. Same 782px stacking breakpoint as
   every other 2/3-col element on these pages. Image-left card layout per the dispatch's own
   spec; no established "article card with photo fallback" pattern exists elsewhere in this
   theme to match (checked search.html, sidebar-related, random-articles — none render images),
   so the fallback (icon-in-tint) is built fresh from existing tokens, not copied from a prior
   pattern that doesn't exist. */
.oi-related-articles { margin: 2.5rem 0 3rem; }
.oi-related-articles__heading {
	font-family: var(--wp--preset--font-family--display);
	font-weight: 700;
	font-size: 1.3rem;
	line-height: 1.2;
	color: var(--wp--preset--color--ink);
	margin: 0 0 1.1rem;
}
.oi-related-articles__grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1.25rem; }
.oi-related-articles__card {
	display: flex;
	gap: 0.85rem;
	align-items: flex-start;
	padding: 1rem;
	background: var(--wp--preset--color--card, #fff);
	border: 1px solid var(--wp--preset--color--line);
	border-radius: var(--wp--custom--radius--card);
	text-decoration: none;
	min-width: 0;
}
.oi-related-articles__card:hover { border-color: var(--wp--preset--color--primary); }
.oi-related-articles__media { flex: none; width: 64px; height: 64px; border-radius: var(--wp--custom--radius--card); overflow: hidden; background: var(--wp--preset--color--surface); }
.oi-related-articles__media img { display: block; width: 100%; height: 100%; object-fit: cover; }
.oi-related-articles__placeholder { display: flex; align-items: center; justify-content: center; width: 100%; height: 100%; color: var(--wp--preset--color--muted); }
.oi-related-articles__placeholder svg { width: 24px; height: 24px; }
.oi-related-articles__body { min-width: 0; display: flex; flex-direction: column; gap: 0.35rem; }
.oi-related-articles__title { font-weight: 600; font-size: 0.92rem; line-height: 1.35; color: var(--wp--preset--color--ink); }
.oi-related-articles__excerpt { margin: 0; font-size: 0.8rem; line-height: 1.45; color: var(--wp--preset--color--muted); }
@media (max-width: 782px) {
	.oi-related-articles__grid { grid-template-columns: 1fr; }
}

.oi-rail-cta { background: var(--wp--preset--color--tint); border-radius: var(--wp--custom--radius--card); padding: 1.25rem; }
.oi-rail-cta .oi-rail__label { color: var(--wp--preset--color--ink); font-size: 0.95rem; text-transform: none; letter-spacing: normal; font-family: var(--wp--preset--font-family--body); font-weight: 700; }
.oi-rail-cta__btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-height: 44px;
	margin-top: 0.85rem;
	padding: 0.6rem 1.1rem;
	border-radius: var(--wp--custom--radius--pill, 999px);
	background: var(--wp--preset--color--primary);
	color: #ffffff;
	font-weight: 600;
	text-decoration: none;
	box-shadow: var(--ad-btn-shadow);
	transition: background var(--ad-ease), box-shadow var(--ad-ease), transform var(--ad-ease);
}
.oi-rail-cta__btn:hover { background: var(--wp--preset--color--primary-hover, var(--wp--preset--color--primary)); box-shadow: var(--ad-btn-shadow-hover); transform: translateY(-1px); }
.oi-rail-cta__btn:focus-visible { outline: 2px solid var(--wp--preset--color--ink); outline-offset: 2px; }
.oi-rail-cta__secondary { margin: 0.75rem 0 0; text-align: center; font-size: 0.82rem; }
.oi-rail-cta__secondary a { color: var(--wp--preset--color--muted); text-decoration: underline; }
.oi-rail-cta__secondary a:hover { color: var(--wp--preset--color--ink); }

/* Revenue Leak Report gated-deliverable disclosure (feat/oi-report-lead-magnet, 2026-07-07) —
   scripts/render_report_deliverable.py wraps the artifact's own proof-safety disclosure
   sentence (data_source: illustrative/live) in this class so it's always visually distinct from
   the report's findings, never mistaken for one. */
.ad-report-disclosure {
	background: var(--wp--preset--color--tint);
	border: 1px solid var(--wp--preset--color--line);
	border-radius: var(--wp--custom--radius--card);
	padding: 0.85rem 1.1rem;
	font-size: 0.88rem;
	color: var(--wp--preset--color--slate);
}

/* ----- OI image slots (hero visual + guardrail-gate visual) -----------
   scripts/oi_image_slots.py — public mode hides an unregistered slug entirely (the server
   never emits the wrapper markup when the slug isn't in APPROVED_VISUALS), so this CSS only
   ever has to handle a slot that DOES render: either an approved page (public) or any page
   in preview mode (labeled pending). Visual source: the 2026-07-05 Claude Design import
   ("Optimization Intelligence image direction" — OI Visuals.dc.html + RuleGate.dc.html). */
.ad-single__body .article-content .oi-visual-slot { margin: 0; }
.oi-visual-slot svg { display: block; width: 100%; height: auto; }

/* IMPLEMENTATION.md's wrapper/centering contract, as its own ad-figure modifier so the
   existing bare .ad-figure (flywheel/curve, margin:0) is untouched. */
.ad-single__body .article-content .ad-figure--oi-hero,
.ad-single__body .article-content .ad-figure--oi-gate {
	display: block;
	margin: clamp(1.5rem, 3vw, 2rem) auto;
	width: 100%;
	max-width: 760px;
}

/* Tinted-ground card every hero visual sits inside (locked rule, review packet §1) — dark
   variant for the hub (matches its own navy hero background), light for the other 3. */
.oi-hero-card {
	border-radius: 20px;
	padding: 18px;
	box-sizing: border-box;
}
.oi-hero-card--dark {
	background: linear-gradient(180deg, #101A30, #0B1220);
	border: 1px solid #2A3650;
}
.oi-hero-card--light {
	background: linear-gradient(180deg, #F7F9FC, #EDF0F5);
	border: 1px solid #E3E8F0;
}
.oi-hero-card svg + svg { margin-top: 8px; }

/* RuleGate: two real orientations exist (not one scaled down) — CSS toggles which renders,
   at the design's own ~480px breakpoint (review packet §2, "used under ~480px"). */
.oi-rulegate__orientation--v { display: none; }
@media (max-width: 480px) {
	.oi-rulegate__orientation--h { display: none; }
	.oi-rulegate__orientation--v { display: block; }
}

/* Preview-mode-only label — never present in a public render (the server omits it
   entirely once a slug is approved), so no risk of this leaking to a live visitor. */
.oi-visual-slot--preview-pending { position: relative; }
.oi-visual-slot__preview-label {
	margin: 0 0 0.5rem;
	font-family: "JetBrains Mono", monospace;
	font-size: 0.7rem;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: var(--wp--preset--color--primary);
	text-align: center;
}

/* Experimentation hero's pulsing "LIVE" dot (review packet §3, item 5) — the only motion
   in this visual set; gated behind prefers-reduced-motion, defaults to fully static. */
@media (prefers-reduced-motion: no-preference) {
	.oi-hero-card .tv-pulse { animation: oi-tv-pulse 1.6s ease-in-out infinite; transform-origin: center; }
}
@keyframes oi-tv-pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.3; } }

/* ----- Post bottom CTA ------------------------------------------------ */
.ad-post-cta {
	background: var(--wp--preset--color--navy);
	border-radius: 14px;
	padding: 2.5rem 2.75rem;
	margin-top: 3.5rem;
}
.ad-post-cta h2 { color: #ffffff; font-size: 1.75rem; line-height: 1.2; margin: 0.75rem 0 0; }
.ad-post-cta__body { color: var(--wp--preset--color--muted-on-navy); font-size: 1rem; font-family: var(--wp--preset--font-family--body); line-height: 1.65; margin: 0.85rem 0 0; max-width: 48ch; }
.ad-post-cta__btn {
	display: inline-block;
	margin-top: 1.5rem;
	padding: 0.75rem 1.5rem;
	background: #2353D4;
	background: var(--wp--preset--color--primary);
	color: #ffffff;
	border-radius: var(--ad-btn-radius);
	box-shadow: var(--ad-btn-shadow);
	text-decoration: none;
	font-family: var(--wp--preset--font-family--body);
	font-size: 1rem;
	font-weight: 600;
	letter-spacing: -0.01em;
	transition: background 0.18s ease, transform 0.15s ease, box-shadow 0.18s ease;
}
.ad-post-cta__btn:hover { background: color-mix(in srgb, var(--wp--preset--color--primary) 85%, #000); color: #ffffff; transform: translateY(-1px); box-shadow: var(--ad-btn-shadow-hover); }
/* Regression fix (2026-07-05): .ad-post-cta__btn (1 class, specificity 0,1,0) was losing both
   color:#fff AND text-decoration:none to the generic prose-link rule above
   (.ad-single__body .article-content a, 0,2,1: color: primary blue; text-decoration: underline)
   — every button using this component renders inside that wrapper (both regular article
   end-of-post CTAs and the OI pages), so the label text silently matched the button's own blue
   background AND picked up a blue underline, on every one of them, on every state. The
   2026-07-03 pass fixed this exact collision for this CTA's sibling elements (.oi-breadcrumb a,
   .oi-cta__ctxlink, .oi-cta__secondary a, see the comment above) by re-scoping under
   .ad-single__body .article-content (3 classes, 0,3,0) but missed the primary button itself.
   Same fix, same pattern, extended to default/hover/focus so every interactive state reliably
   beats the generic rule regardless of source order. */
.ad-single__body .article-content .ad-post-cta__btn,
.ad-single__body .article-content .ad-post-cta__btn:visited {
	color: #ffffff;
	text-decoration: none;
}
.ad-single__body .article-content .ad-post-cta__btn:hover,
.ad-single__body .article-content .ad-post-cta__btn:focus,
.ad-single__body .article-content .ad-post-cta__btn:active {
	color: #ffffff;
	text-decoration: none;
}
.ad-post-cta__btn:focus-visible { outline: 2px solid #ffffff; outline-offset: 2px; }

/* executive-summary card — between the title/meta header and the article body */
.ad-exec-summary { background: var(--wp--preset--color--paper); border: 1px solid var(--wp--preset--color--line); border-left: 3px solid var(--wp--preset--color--primary); border-radius: var(--wp--custom--radius--card); padding: 1.5rem 1.75rem; margin: 0 0 2.25rem; }
.ad-exec-summary .ad-eyebrow { margin: 0 0 0.85rem; }
.ad-exec-summary ul { margin: 0; padding-left: 1.25rem; }
.ad-exec-summary li { color: var(--wp--preset--color--slate); font-size: 1rem; line-height: 1.6; }
.ad-exec-summary li + li { margin-top: 0.6rem; }

/* mid-article capability callout — lighter surface than the dark end-of-article CTA, for
   an "educational, not salesy" tone at the ~1/3-through insertion point */
.ad-post-cta--inline { background: var(--wp--preset--color--paper); border: 1px solid var(--wp--preset--color--line); border-radius: var(--wp--custom--radius--card-lg); padding: 1.75rem 2rem; margin: 2.5rem 0; }
.ad-post-cta--inline h2 { color: var(--wp--preset--color--ink); }
.ad-post-cta--inline .ad-post-cta__body { color: var(--wp--preset--color--slate); }

/* end-of-article related-articles grid — .cap-xcard/.capx-readcard's bordered
   hover-lift recipe, reused verbatim */
.ad-related-end { margin-top: 3.5rem; }
.ad-related-end__grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1.5rem; margin-top: 1.25rem; min-width: 0; align-items: stretch; }
.ad-related-end__card { display: flex; flex-direction: column; height: 100%; border: 1px solid var(--wp--preset--color--line); border-radius: var(--wp--custom--radius--card-lg); overflow: hidden; text-decoration: none; color: inherit; min-width: 0; transition: border-color 0.15s ease, transform 0.15s ease; }
.ad-related-end__card:hover { border-color: var(--wp--preset--color--primary); transform: translateY(-2px); }
/* media slot: fixed 16:9 box (zero layout shift), image covers it; an SVG fallback icon
   fills the same box so image-less posts keep equal card heights */
.ad-related-end__media { display: block; aspect-ratio: 16 / 9; overflow: hidden; border-bottom: 1px solid var(--wp--preset--color--line); }
.ad-related-end__media > img, .ad-related-end__media > svg { display: block; width: 100%; height: 100%; object-fit: cover; }
.ad-related-end__img { display: block; width: 100%; height: 100%; object-fit: cover; }
.ad-related-end__body { display: flex; flex-direction: column; flex: 1 1 auto; gap: 0.45rem; padding: 1rem 1.15rem 1.15rem; min-width: 0; }
.ad-related-end__cat { display: block; font-family: var(--wp--preset--font-family--mono); font-size: 0.64rem; letter-spacing: 0.12em; text-transform: uppercase; color: var(--wp--preset--color--slate); }
.ad-related-end__title { display: block; font-family: var(--wp--preset--font-family--display); font-size: 1rem; font-weight: 600; color: var(--wp--preset--color--ink); line-height: 1.35; }
.ad-related-end__foot { display: flex; align-items: baseline; justify-content: space-between; gap: 0.5rem; margin-top: auto; padding-top: 0.5rem; }
.ad-related-end__meta { display: block; font-size: 0.78rem; color: var(--wp--preset--color--muted); }
.ad-related-end__arrow { color: var(--wp--preset--color--primary); font-size: 1rem; transition: transform 0.15s ease; }
.ad-related-end__card:hover .ad-related-end__arrow { transform: translateX(3px); }
@media (max-width: 960px) {
	.ad-related-end__grid { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 781px) {
	.ad-related-end__grid { grid-template-columns: 1fr; }
}

.ad-single__sidebar { position: sticky; top: 5.5rem; align-self: start; min-width: 0; border-left: 1px solid var(--wp--preset--color--line); padding-left: 2rem; }

/* sidebar labels */
.ad-sidebar__label { font-family: var(--wp--preset--font-family--mono); font-size: 0.67rem; letter-spacing: 0.14em; text-transform: uppercase; color: var(--wp--preset--color--muted); margin: 0 0 0.65rem; }

/* capability links */
.ad-sidebar__caplinks { list-style: none; margin: 0; padding: 0; }
.ad-sidebar__caplinks li { border-top: 1px solid var(--wp--preset--color--line); }
.ad-sidebar__caplinks a { display: flex; align-items: center; gap: 0.55rem; padding: 0.55rem 0; text-decoration: none; color: var(--wp--preset--color--slate); font-size: 0.85rem; font-weight: 500; transition: color 0.15s; }
.ad-sidebar__caplinks a:hover { color: var(--wp--preset--color--primary); }
.ad-sidebar__caplinks a svg { flex-shrink: 0; color: var(--wp--preset--color--muted); transition: color 0.15s; }
.ad-sidebar__caplinks a:hover svg { color: var(--wp--preset--color--primary); }

/* related articles */
.ad-sidebar__related .wp-block-post-template { list-style: none; margin: 0; padding: 0; }
.ad-sidebar__art { padding: 0.7rem 0; border-top: 1px solid var(--wp--preset--color--line); }
.ad-sidebar__art:last-child { border-bottom: 1px solid var(--wp--preset--color--line); }
.ad-sidebar__art .wp-block-post-title { font-size: 0.88rem; line-height: 1.4; margin: 0.2rem 0 0; }
.ad-sidebar__art .wp-block-post-title a { text-decoration: none; color: var(--wp--preset--color--ink); font-weight: 500; }
.ad-sidebar__art .wp-block-post-title a:hover { color: var(--wp--preset--color--primary); }
.ad-sidebar__art .ad-cat { font-size: 0.62rem; }

@media (max-width: 960px) {
	.ad-single__sidebar { position: static; align-self: auto; border-left: none; border-top: 1px solid var(--wp--preset--color--line); padding-left: 0; padding-top: 2rem; }
	.ad-sidebar__caplinks { display: grid; grid-template-columns: 1fr 1fr; }
}

/* reading-progress bar — sibling of the header, see parts/reading-progress.html */
.ad-progress { position: fixed; top: 0; left: 0; width: 100%; height: 3px; background: transparent; z-index: 60; }
.ad-progress__fill { width: 100%; height: 100%; background: var(--wp--preset--color--primary); transform: scaleX(0); transform-origin: left; }

/* sidebar capabilities accordion — collapsed by default (the TOC was removed 2026-07-03) */
.ad-sidebar__acc-toggle { display: flex; align-items: center; justify-content: space-between; gap: 0.5rem; width: 100%; background: var(--wp--preset--color--paper); border: 1px solid var(--wp--preset--color--line); border-radius: var(--wp--custom--radius--card); padding: 0.6rem 1rem; font-family: var(--wp--preset--font-family--mono); font-size: 0.72rem; letter-spacing: 0.06em; text-transform: uppercase; color: var(--wp--preset--color--ink); cursor: pointer; }
.ad-sidebar__acc-toggle svg { flex-shrink: 0; transition: transform 0.15s ease; }
.ad-sidebar__acc-toggle[aria-expanded="true"] svg { transform: rotate(180deg); }
.ad-sidebar__acc-panel { border: 1px solid var(--wp--preset--color--line); border-top: none; padding: 0.15rem 1rem; }
.ad-sidebar__acc-panel[hidden] { display: none; }
.ad-sidebar__acc-panel .ad-sidebar__caplinks li:first-child { border-top: none; }

/* Who We Help / What We Don't Do templates (WP-2B / WP-2B.2, unpublished) - proof-slot
   placeholder, obviously not real content */
.wwh-proof-slot { border: 1px dashed var(--wp--preset--color--line); border-radius: var(--wp--custom--radius--card); padding: 2rem; text-align: center; }
.wwh-proof-slot__label { color: var(--wp--preset--color--muted); font-family: var(--wp--preset--font-family--mono); font-size: 0.8rem; letter-spacing: 0.02em; margin: 0; }

/* Practitioner Lessons band - repeatable lesson-card grid, each card a link to its own
   Practitioner Lesson page (2026-07-11) */
.wwh-lesson-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 1rem; margin-top: 1.75rem; }
.wwh-lesson-card { display: flex; flex-direction: column; gap: 0.4rem; background: var(--wp--preset--color--card); border: 1px solid var(--wp--preset--color--line); border-radius: var(--wp--custom--radius--card-lg); padding: 1.25rem 1.35rem; text-decoration: none; transition: border-color .15s ease, transform .15s ease; }
.wwh-lesson-card:hover { border-color: var(--wp--preset--color--primary); transform: translateY(-2px); }
.wwh-lesson-card__title { font-weight: 600; font-size: 1.05rem; color: var(--wp--preset--color--ink); margin: 0; }
.wwh-lesson-card__excerpt { font-size: 0.9rem; line-height: 1.5; color: var(--wp--preset--color--muted); margin: 0; }

/* What We Don't Do template (WP-2B.2, unplaced) - repeatable exclusion-card grid */
.wwh-exclusion-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); gap: 1rem; }
.wwh-exclusion-card { display: flex; flex-direction: column; gap: 0.4rem; background: var(--wp--preset--color--card); border: 1px solid var(--wp--preset--color--line); border-radius: var(--wp--custom--radius--card-lg); padding: 1.25rem 1.35rem; }
.wwh-exclusion-card__heading { font-weight: 600; font-size: 1.05rem; color: var(--wp--preset--color--ink); margin: 0; }
.wwh-exclusion-card__body { font-size: 0.9rem; line-height: 1.5; color: var(--wp--preset--color--muted); margin: 0; }

/* Who We Help pages (feat/who-we-help-pages-build) - visible author/editorial note (proof-assets.md
   §12 G-07: a blocked claim gets a visible note, never a silent drop or an invented figure) */
.wwh-note { font-style: italic; font-size: 0.9rem; line-height: 1.5; color: var(--wp--preset--color--muted); border-left: 3px solid var(--wp--preset--color--line); padding-left: 1rem; margin: 1rem 0 0; }

/* Who We Help visual system (AD Lane 2, 2026-07-11) - hub pathway grid: bordered two-column
   split card, per docs/design/who-we-help-visual-system/who-we-help.dc.html, built from
   existing tokens (--card/--line/--primary/--muted/--ink), not the prototype's inline hex. */
.wwh-pathway-list { display: flex; flex-direction: column; gap: clamp(1.25rem, 2.5vw, 1.75rem); margin-top: 2.25rem; }
.wwh-pathway-card { display: flex; flex-wrap: wrap; background: var(--wp--preset--color--card); border: 1px solid var(--wp--preset--color--line); border-radius: var(--wp--custom--radius--card-lg); overflow: hidden; }
.wwh-pathway-card__main { flex: 1 1 460px; min-width: 0; padding: clamp(1.5rem, 3vw, 2.5rem); border-right: 1px solid var(--wp--preset--color--line); }
.wwh-pathway-card__num { font-family: var(--wp--preset--font-family--display); font-weight: 800; color: var(--wp--preset--color--muted); font-size: 1rem; }
.wwh-pathway-card__title { font-family: var(--wp--preset--font-family--display); font-size: clamp(1.3rem, 2.1vw, 1.6rem); font-weight: 800; color: var(--wp--preset--color--ink); margin: 0.15rem 0 0; }
.wwh-pathway-card__lede { font-size: 1rem; font-weight: 700; color: var(--wp--preset--color--ink); margin: 1.25rem 0 0; }
.wwh-pathway-card__body { font-size: 1.0625rem; line-height: 1.6; color: var(--wp--preset--color--slate); margin: 0.6rem 0 0; max-width: 50ch; }
.wwh-pathway-card__link { display: inline-flex; align-items: center; gap: 0.5rem; margin-top: 1.5rem; }
.wwh-pathway-card__specialists { flex: 1 1 280px; min-width: 0; padding: clamp(1.5rem, 3vw, 2.5rem); background: var(--wp--preset--color--surface); }
.wwh-pathway-card__specialists-label { font-size: 0.75rem; font-weight: 700; letter-spacing: 0.05em; text-transform: uppercase; color: var(--wp--preset--color--muted); margin: 0 0 0.85rem; }
.wwh-pathway-card__specialists ul { list-style: none; margin: 0; padding: 0; display: flex; flex-direction: column; gap: 0.25rem; }
.wwh-pathway-card__specialists a { display: flex; align-items: center; padding: 0.7rem 0.6rem; border-radius: var(--wp--custom--radius--card); color: var(--wp--preset--color--ink); font-weight: 600; text-decoration: none; transition: background .15s ease; }
.wwh-pathway-card__specialists a:hover { background: var(--wp--preset--color--card); }

/* Stat trio - reused USABLE figures (proof-assets.md §3), no page restriction */
.wwh-stat-trio { display: flex; flex-wrap: wrap; gap: 1.1rem 2.75rem; margin: 1rem 0 0; }
.wwh-stat-trio__num { font-family: var(--wp--preset--font-family--display); font-weight: 800; font-size: 1.9rem; color: var(--wp--preset--color--ink); line-height: 1; }
.wwh-stat-trio__label { font-size: 0.85rem; color: var(--wp--preset--color--muted); margin-top: 0.25rem; }

/* Cause/effect reframe panel ("the visible metric isn't the real problem") */
.wwh-reframe-panel { margin-top: 2rem; background: var(--wp--preset--color--surface); border: 1px solid var(--wp--preset--color--line); border-radius: var(--wp--custom--radius--card-lg); padding: clamp(1.35rem, 3vw, 2.25rem); }
.wwh-reframe-row { display: flex; flex-wrap: wrap; align-items: center; gap: 0.6rem 0.75rem; padding: 1rem 0; border-top: 1px solid var(--wp--preset--color--line); }
.wwh-reframe-row:first-of-type { border-top: 0; }
.wwh-reframe-row__metric { flex: 1 1 200px; font-family: var(--wp--preset--font-family--display); font-weight: 700; color: var(--wp--preset--color--ink); font-size: 1.05rem; }
.wwh-reframe-row__arrow { flex: none; color: var(--wp--preset--color--primary); font-weight: 800; }
.wwh-reframe-row__cause { flex: 1 1 260px; color: var(--wp--preset--color--accent-teal); font-weight: 600; }

/* FAQ accordion (native details/summary - no JS dependency) */
.wwh-faq { border-top: 1px solid var(--wp--preset--color--line); }
.wwh-faq details { border-bottom: 1px solid var(--wp--preset--color--line); }
.wwh-faq summary { cursor: pointer; list-style: none; display: flex; justify-content: space-between; align-items: center; gap: 1rem; padding: 1.1rem 0; font-family: var(--wp--preset--font-family--display); font-weight: 700; font-size: 1.05rem; color: var(--wp--preset--color--ink); }
.wwh-faq summary::-webkit-details-marker { display: none; }
.wwh-faq summary::after { content: "+"; flex: none; color: var(--wp--preset--color--primary); font-weight: 800; font-size: 1.3rem; }
.wwh-faq details[open] summary::after { content: "\2212"; }
.wwh-faq p { margin: 0 0 1.25rem; font-size: 1rem; line-height: 1.6; color: var(--wp--preset--color--slate); max-width: 72ch; }

/* Compact single-lesson highlight (pillar/specialist pages) - reuses .wwh-lesson-card visuals */
.wwh-lesson-highlight { max-width: 640px; margin-top: 1.5rem; }

/* Mobile button sizing (Alex-authorized, 2026-07-13, chore/mobile-button-sizing): on mobile
   only, real site buttons/CTAs render at a 30px visual height with a 6px radius. Overriding
   --ad-btn-radius inside the query covers every consumer of that token (.ad-cta-desktop/
   -mobile, .ad-nav-drawer__cta, .ad-search-form__submit, .ad-post-cta__btn) in one place; the
   remaining selectors (.wp-block-button__link, .ad-footer__cta-btn, .oi-rail-cta__btn) don't
   read the token and get the radius set directly.

   Accessibility: shrinking the visual chrome to 30px would put real buttons under WCAG 2.2 SC
   2.5.8's 24x24px minimum and well under the 44px tap-target used elsewhere on this site
   (.oi-rail-cta__btn already sets min-height:44px for this reason). Each selector below gets
   `position:relative` + a `::before` overlay sized to 44px (transparent, no visual change) so
   the real hit area stays >=44px tall while only the painted box shrinks to 30px. Clicks on a
   ::before's rendered box are dispatched to the host element, so this genuinely extends the tap
   target rather than just look bigger.

   .oi-rail-cta__btn is a deliberate pill (border-radius:999px, min-height:44px already) - folded
   into the same 30px/6px treatment for site-wide consistency per this ruling; flagging the shape
   change (pill -> 6px-radius rect) for Alex's awareness, not reverting without a call.

   Excluded (not "buttons" or would break under a 30px cap): .ad-nav-toggle, .ad-search-toggle,
   .ad-nav-drawer__search-submit (icon-only), .oi-mobile-nav__toggle, .ad-sidebar__acc-toggle
   (all toggles/hamburgers, not CTAs); the EOA experience/stage/problem nodes and its sticky CTA
   (assets/css/components/eoa-*.css - out of scope, feat/eoa-hero-full-replacement territory);
   .oi-cta__ctxlink / .oi-cta__secondary a (plain underlined text links, not button-shaped);
   .wwh-mockup__cta / .wwh-example__cta (decorative <span> inside illustrated device mockups,
   not real interactive site CTAs - resizing them would distort the mockup art); native form
   fields (text inputs/selects). Real form-submit buttons living in a page's own inline <style>
   (.ct2-submit in contact.php, .hq__back/.hq__next/.hq__submit in home-quiz.php and its
   quiz-backup-quiz.php backup pattern) get the same treatment inline at their own source, since
   an external stylesheet rule can lose the cascade to same-specificity inline <style> that
   renders later in the document. */
@media (max-width: 781px) {
	:root { --ad-btn-radius: 6px; }

	a.wp-block-button__link,
	button.wp-block-button__link,
	.ad-cta-desktop,
	.ad-cta-mobile,
	.ad-nav-drawer__cta,
	.ad-search-form__submit,
	.ad-post-cta__btn,
	.ad-footer__cta-btn,
	.oi-rail-cta__btn {
		position: relative;
		box-sizing: border-box;
		height: 30px;
		min-height: 0;
		line-height: 28px; /* 30px box minus a hairline for optical centering with no explicit border */
		padding-top: 0;
		padding-bottom: 0;
		border-radius: 6px;
	}
	a.wp-block-button__link::before,
	button.wp-block-button__link::before,
	.ad-cta-desktop::before,
	.ad-cta-mobile::before,
	.ad-nav-drawer__cta::before,
	.ad-search-form__submit::before,
	.ad-post-cta__btn::before,
	.ad-footer__cta-btn::before,
	.oi-rail-cta__btn::before {
		content: "";
		position: absolute;
		left: 0;
		right: 0;
		top: 50%;
		height: 44px;
		transform: translateY(-50%);
	}
}
