/*
Theme Name: Burt Foundation
Theme URI: https://www.burtfoundation.org
Author: Jacob Starr + Legal Web Design
Author URI: https://www.legalwebdesign.com
Description: Custom block theme for the Nathan B. and Florence R. Burt Foundation. Navy + Amber design system; every page section is a content-only-locked pattern so editors can change text and images without touching layout. The grant portal is a separate app and is only linked, never embedded.
Version: 1.0.0
Requires at least: 6.6
Tested up to: 7.0
Requires PHP: 7.4
License: GPL-2.0-or-later
License URI: https://www.gnu.org/licenses/gpl-2.0.html
Text Domain: burt-foundation
*/

/* ==========================================================================
   Design tokens live in theme.json. This file carries what it can't express:
   pseudo-elements, hover/focus states, component chrome, and motion.
   All custom classes are bf-* namespaced and used inside locked patterns.
   ========================================================================== */

/* ---------- Base niceties ---------- */

body { -webkit-font-smoothing: antialiased; overflow-x: clip; }

h1, h2, h3, h4 { overflow-wrap: anywhere; text-wrap: balance; }

/* Amber is the brand's warmth — let it show up in the small moments too. */
::selection { background: var(--wp--preset--color--accent); color: var(--wp--preset--color--ink); }
main ul li::marker { color: var(--wp--preset--color--accent); }

/* The signature link hover — thick amber underline, slightly offset — applies
   to every text link on the site (nav pills and buttons have their own states). */
main a:not(.wp-block-button__link), .bf-footer a, footer a {
	text-underline-offset: 0.2em;
	transition: text-decoration-color 160ms cubic-bezier(0.22,1,0.36,1), color 160ms cubic-bezier(0.22,1,0.36,1);
}
main a:not(.wp-block-button__link):hover { color: var(--wp--preset--color--ink); }
main a:not(.wp-block-button__link):hover, .bf-footer a:hover, footer a:hover {
	text-decoration: underline;
	text-decoration-color: var(--wp--preset--color--accent);
	text-decoration-thickness: 2px;
}

/* Signature heading underline (the hero/mission motif), reusable anywhere:
   wrap words in <mark class="bf-hl"> */
mark.bf-hl, .bf-hl {
	background: none; color: inherit;
	text-decoration: underline;
	text-decoration-color: var(--wp--preset--color--accent);
	text-decoration-thickness: 0.08em;
	text-underline-offset: 0.14em;
}

/* Centered chip variant (for centered bands like the CTA) */
.bf-eyebrow--center { display: flex !important; margin-inline: auto; }

/* Skip link (a11y) */
.bf-skip {
	position: absolute; left: -9999px; top: 0; z-index: 100;
	background: var(--wp--preset--color--ink); color: var(--wp--preset--color--canvas);
	padding: 10px 18px; border-radius: 0 0 12px 0; font-weight: 600; text-decoration: none;
}
.bf-skip:focus { left: 0; }

/* ---------- Eyebrow chip ---------- */

/* Chips are always SOLID — no alpha washes. Light surfaces: amber tint + ink.
   Dark bands: full amber + ink (the "gold chip"). Both read as deliberate. */
.bf-eyebrow {
	display: inline-flex; align-items: center; gap: 0.5rem;
	font-size: var(--wp--preset--font-size--micro) !important;
	font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase;
	padding: 6px 14px; border-radius: 999px; white-space: nowrap;
	width: fit-content;
	/* On WHITE — light amber chip + navy text. 12.09:1 AAA */
	background: var(--wp--preset--color--accent-tint);
	color: var(--wp--preset--color--ink);
}
.bf-eyebrow::before {
	content: ""; width: 6px; height: 6px; border-radius: 50%; flex: none;
	background: var(--wp--preset--color--accent);
	animation: bf-pulse 2.4s cubic-bezier(0.4, 0, 0.6, 1) infinite;
}
@keyframes bf-pulse {
	0%, 100% { opacity: 1;   transform: scale(1); }
	50%      { opacity: 0.4; transform: scale(0.7); }
}
@media (prefers-reduced-motion: reduce) { .bf-eyebrow::before { animation: none; } }

/* On LIGHT BLUE — gold chip + navy text. 6.68:1 AA. */
.bf-on-light .bf-eyebrow, .bf-eyebrow--on-light {
	background: var(--wp--preset--color--accent);
	color: var(--wp--preset--color--ink);
}
.bf-on-light .bf-eyebrow::before, .bf-eyebrow--on-light::before { background: var(--wp--preset--color--ink); }

/* On LIGHT AMBER — gold chip + navy text. 6.68:1 AA. */
.bf-on-gold .bf-eyebrow {
	background: var(--wp--preset--color--accent);
	color: var(--wp--preset--color--ink);
}
.bf-on-gold .bf-eyebrow::before { background: var(--wp--preset--color--ink); }

/* On NAVY — light amber chip + navy text. 12.09:1 AAA */
.bf-on-dark .bf-eyebrow, .bf-eyebrow--on-dark {
	background: var(--wp--preset--color--accent-tint);
	color: var(--wp--preset--color--ink);
}
.bf-on-dark .bf-eyebrow::before, .bf-eyebrow--on-dark::before { background: var(--wp--preset--color--ink); }

/* CTA button hovers gold with navy text, exactly like the hero button. */
.bf-on-gold .wp-block-button__link:hover {
	background: var(--wp--preset--color--accent) !important;
	color: var(--wp--preset--color--ink) !important;
}

/* ---------- Buttons (extends theme.json element styles) ---------- */

.wp-block-button__link { transition: background 160ms cubic-bezier(0.22,1,0.36,1), color 160ms cubic-bezier(0.22,1,0.36,1), transform 160ms cubic-bezier(0.22,1,0.36,1); }
.wp-block-button__link:active { transform: scale(0.97); }

/* Hover pairs are EXPLICIT (background + text together, always AA) — never rely
   on a background swap alone. Primary: navy -> amber w/ ink text. */
.wp-block-button:not([class*="is-style-"]) .wp-block-button__link:hover {
	background: var(--wp--preset--color--accent);
	color: var(--wp--preset--color--ink);
}

/* Gold secondary button — hover deepens to amber with WHITE text (5.02:1). */
.is-style-bf-accent .wp-block-button__link {
	background: var(--wp--preset--color--accent);
	color: var(--wp--preset--color--ink);
}
.is-style-bf-accent .wp-block-button__link:hover {
	background: var(--wp--preset--color--ink);
	color: var(--wp--preset--color--canvas);
}
/* Outline button */
.is-style-bf-outline .wp-block-button__link {
	background: transparent;
	color: var(--wp--preset--color--ink);
	border: 1.5px solid var(--wp--preset--color--ink);
	padding-top: 10.5px; padding-bottom: 10.5px;
}
.is-style-bf-outline .wp-block-button__link:hover {
	background: var(--wp--preset--color--accent);
	border-color: var(--wp--preset--color--accent);
	color: var(--wp--preset--color--ink);
}
/* White button for dark bands */
.is-style-bf-on-dark .wp-block-button__link {
	background: var(--wp--preset--color--canvas);
	color: var(--wp--preset--color--ink);
}
.is-style-bf-on-dark .wp-block-button__link:hover {
	background: var(--wp--preset--color--accent);
	color: var(--wp--preset--color--ink);
}

/* Arrow affordance inside button text: <span class="bf-arrow">↗</span> */
.bf-arrow { display: inline-block; transition: transform 160ms cubic-bezier(0.22,1,0.36,1); }
.wp-block-button__link:hover .bf-arrow, a:hover .bf-arrow { transform: rotate(45deg); }

/* ==========================================================================
   VERTICAL RHYTHM — one source of truth for the whole site.
   Every chip->heading, heading->body and body->action gap comes from here.
   Do not add per-section spacing overrides; change these three values instead.
   ========================================================================== */
:root {
	--bf-gap-chip:   16px;  /* eyebrow chip / accent line  -> heading */
	--bf-gap-text:   24px;  /* heading -> body, body -> body */
	--bf-gap-action: 32px;  /* last text -> button row */
}

/* chip (or accent line) to whatever follows it — everywhere, no exceptions.
   The scoped selectors are needed so this beats the stack rules below, which
   are more specific and also !important. */
.bf-eyebrow + *,
.bf-accent-line + *,
.bf-hero__stack > .bf-eyebrow + *,
.cta > .bf-eyebrow + *,
.bf-on-gold > .bf-eyebrow + *,
.quote > .bf-eyebrow + *,
.quote > .bf-accent-line + *,
.section-head > .bf-eyebrow + * { margin-top: var(--bf-gap-chip) !important; }

/* text rhythm inside every stacked block */
.bf-hero__stack > * + *,
.cta > * + *,
.bf-on-gold > * + *,
.quote > * + *,
.section-head > * + * { margin-top: var(--bf-gap-text) !important; }

/* the action always sits a step further out */
.bf-hero__stack > .wp-block-buttons,
.cta > .wp-block-buttons,
.bf-on-gold > .wp-block-buttons { margin-top: var(--bf-gap-action) !important; }

.bf-hero__stack .wp-block-buttons, .cta .wp-block-buttons { gap: var(--wp--preset--spacing--40); }

/* ---------- Accent line (section marker) ---------- */

.bf-accent-line {
	border: 0 !important; height: 4px !important; width: 56px !important;
	background: var(--wp--preset--color--accent) !important;
	border-radius: 999px; opacity: 1 !important;
	margin: 0 0 var(--wp--preset--spacing--40) !important;
}
.bf-on-dark .bf-accent-line { background: var(--wp--preset--color--accent) !important; }

/* ---------- Cards ---------- */

.bf-card {
	background: var(--wp--preset--color--canvas);
	border: 1px solid var(--wp--preset--color--hairline);
	border-radius: 24px;
}
.bf-card--lift { transition: transform 200ms cubic-bezier(0.22,1,0.36,1), box-shadow 200ms cubic-bezier(0.22,1,0.36,1), border-color 200ms cubic-bezier(0.22,1,0.36,1); }
@media (hover: hover) and (pointer: fine) {
	.bf-card--lift:hover { transform: translateY(-4px); box-shadow: 0 18px 40px -24px rgba(22,41,79,0.35); border-color: var(--wp--preset--color--accent); }
}
/* Equal-height cards in a columns row: card fills the column, body area grows. */
.wp-block-column > .bf-card--fill { height: 100%; display: flex; flex-direction: column; align-items: stretch; text-align: left; }
.bf-card--fill > .wp-block-group:last-child { flex: 1; }
/* Any card alone in a column matches its tallest sibling (grantee cards etc.) */
.wp-block-columns:not(.bf-timeline) > .wp-block-column > .bf-card { height: 100%; text-align: left; }
.bf-card--fill, .bf-card--fill * { text-align: left !important; }
/* WP's constrained layout puts margin-inline:auto on children. Inside a flex
   column those auto margins beat align-items and centre the block, so a short
   heading floats to the middle. Kill them. */
.bf-card--fill > *, .bf-feature-card > * {
	margin-left: 0 !important; margin-right: 0 !important;
	align-self: stretch;
}

/* Hero: image column stretches to match the text column's height. */
.bf-hero.wp-block-columns { align-items: stretch; }
.bf-hero .wp-block-column:last-child { display: flex; }
.bf-hero .wp-block-column:last-child .wp-block-image { flex: 1; display: flex; margin: 0; }
.bf-hero .wp-block-column:last-child img { height: 100%; width: 100%; object-fit: cover; }
@media (max-width: 781px) {
	.bf-hero .wp-block-column:last-child img { aspect-ratio: 16/10; height: auto; }
}

/* ---------- KPI numerals (amber on dark bands) ---------- */

.bf-stat-num {
	font-family: var(--wp--preset--font-family--display) !important;
	font-weight: 800;
	font-size: clamp(2.5rem, 1.5rem + 4vw, 4rem) !important;
	letter-spacing: -0.03em; line-height: 1;
	color: var(--wp--preset--color--accent);
}
.bf-on-dark .bf-muted, .bf-on-dark-muted { color: rgba(255,255,255,0.72); }

/* ---------- Cycle status card ----------
   A proper brand card: rounded 24, surface-2 fill, no border hacks. The status
   dot lives in a solid amber chip so the "live status" read is intentional. */

.bf-cycle {
	border-radius: 24px;
	background: var(--wp--preset--color--surface);
}


/* ---------- Process steps ---------- */

/* The amber rule line is part of the identity (from the design test) — it stays
   amber on light AND dark bands; only the numeral color adapts for contrast. */
.bf-step { border-top: 2px solid var(--wp--preset--color--accent-tint); padding-top: 1rem; }
.bf-on-light .bf-step, main > .wp-block-group:not(.bf-on-dark) .bf-step { border-top-color: var(--wp--preset--color--accent); }
.bf-step-num {
	font-family: var(--wp--preset--font-family--display) !important;
	font-weight: 800; font-size: var(--wp--preset--font-size--h3) !important;
	letter-spacing: -0.02em;
	color: var(--wp--preset--color--primary);
}
/* On dark/vivid bands the numerals go amber (AA there, not on light) */
.bf-on-dark .bf-step-num { color: var(--wp--preset--color--accent); }

/* ---------- Timeline strip ----------
   Continuous rail; dots sit ON it. Hover lights the node and draws amber along
   the segment to its right. Date sits tight to its event label. */

.bf-timeline { position: relative; }
.bf-timeline::before {
	content: ""; position: absolute; left: 6px; right: 6px; top: 5px;
	height: 2px; border-radius: 2px;
	background: var(--wp--preset--color--hairline);
}
.bf-milestone { position: relative; padding-top: 1.5rem; }
.bf-milestone::before {
	content: ""; position: absolute; top: 0; left: 0; z-index: 2;
	width: 12px; height: 12px; border-radius: 50%;
	background: var(--wp--preset--color--accent);
	box-shadow: 0 0 0 3px var(--wp--preset--color--canvas);
	transition: transform 200ms cubic-bezier(0.22,1,0.36,1);
}
.bf-milestone::after {
	content: ""; position: absolute; top: 5px; left: 6px; z-index: 1;
	height: 2px; width: 0; border-radius: 2px;
	background: var(--wp--preset--color--accent);
	transition: width 420ms cubic-bezier(0.22,1,0.36,1);
}
/* kill inherited block gap so the date hugs its event */
.bf-milestone > * { margin-top: 0 !important; }
.bf-milestone > * + * { margin-top: 4px !important; }

@media (hover: hover) and (pointer: fine) {
	.bf-milestone:hover::before { transform: scale(1.35); }
	.bf-milestone:hover::after { width: calc(100% + var(--wp--preset--spacing--50)); }
	/* the last node has no column gap after it, so its segment stops at the
	   rail's end instead of overshooting */
	.bf-timeline > .wp-block-column:last-child .bf-milestone:hover::after,
	.bf-milestone:last-child:hover::after { width: calc(100% - 12px); }
	.bf-milestone:hover .bf-milestone-date { color: var(--wp--preset--color--ink); }
}
.bf-milestone-date {
	font-size: var(--wp--preset--font-size--micro) !important;
	font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase;
	color: var(--wp--preset--color--ink);
	transition: color 200ms cubic-bezier(0.22,1,0.36,1);
}
@media (max-width: 781px) {
	.bf-timeline::before { display: none; }
	.bf-milestone { padding-top: 0; padding-left: 1.75rem; }
	.bf-milestone::before { top: 4px; }
	.bf-milestone::after { display: none; }
}

/* ---------- Eligibility checklist ---------- */

.bf-check { display: flex; gap: 0.75rem; align-items: flex-start; }
.bf-check::before {
	content: "✓"; flex: none;
	display: grid; place-items: center;
	width: 24px; height: 24px; margin-top: 2px; border-radius: 50%;
	background: var(--wp--preset--color--accent);
	color: var(--wp--preset--color--ink);
	font-size: 0.8rem; font-weight: 700;
}

/* ---------- Avatars (initials until photos arrive) ---------- */

.bf-avatar {
	width: 72px; height: 72px; border-radius: 50%;
	background: var(--wp--preset--color--surface-2);
	display: grid; place-items: center; flex: none;
}
/* Photo variant — same footprint as the initials disc, so a board member with
   a portrait and one without sit at exactly the same size in the same row. */
.bf-avatar-photo {
	width: 72px; height: 72px; margin: 0 !important; flex: none;
}
.bf-avatar-photo img {
	width: 72px; height: 72px; border-radius: 50%; object-fit: cover; display: block;
}
.bf-member-card .bf-avatar-photo,
.bf-member-card .bf-avatar-photo img { width: 56px; height: 56px; }
.bf-avatar p {
	margin: 0 !important;
	font-family: var(--wp--preset--font-family--display);
	font-weight: 700; font-size: 1.25rem; letter-spacing: -0.02em;
	color: var(--wp--preset--color--primary);
}
.bf-member-name { font-family: var(--wp--preset--font-family--display); font-weight: 700; margin-bottom: 0 !important; }
.bf-member-mini .bf-member-name + p { margin-top: 2px !important; }

/* ---------- Board grid ---------- */

.bf-member figcaption, .bf-member .bf-member-name { font-family: var(--wp--preset--font-family--display); font-weight: 700; }
.bf-member .wp-block-image img, .bf-member-photo img { border-radius: 24px; aspect-ratio: 1; object-fit: cover; }
@media (hover: hover) and (pointer: fine) {
	.bf-member .wp-block-image img { transition: transform 320ms cubic-bezier(0.22,1,0.36,1); }
	.bf-member:hover .wp-block-image img { transform: scale(1.03); }
}

/* ---------- FAQ (core/details) ---------- */

.bf-faq details {
	border-bottom: 1px solid var(--wp--preset--color--hairline);
	padding: 0;
	margin: 0 !important; /* kill blockGap so every row's rhythm is identical */
}
.bf-faq summary {
	list-style: none; cursor: pointer;
	padding: 1.25rem 0;
	display: flex; justify-content: space-between; gap: 1.5rem; align-items: center;
	font-family: var(--wp--preset--font-family--display);
	font-weight: 600; font-size: var(--wp--preset--font-size--h3);
	letter-spacing: -0.02em; line-height: 1.3;
}
/* Sticky section head beside the long list */
.bf-faq-aside, .bf-sticky-aside { position: sticky; top: 96px; }
.bf-faq summary::-webkit-details-marker { display: none; }
/* The "+" is a fixed box with the glyph optically centred, so it rotates about
   its own centre instead of hinging off the baseline. */
/* The "+" is DRAWN, not typed. A text glyph carries its own font metrics and
   is not optically centred in its em box, so rotating it looks like a hinge.
   Two gradient bars are perfectly symmetrical and rotate about true centre. */
.bf-faq summary::after {
	content: "";
	flex: none;
	width: 32px; height: 32px;
	box-sizing: border-box;
	border-radius: 50%;
	color: var(--wp--preset--color--ink);
	background-image:
		linear-gradient(currentColor, currentColor),
		linear-gradient(currentColor, currentColor);
	background-size: 13px 2.5px, 2.5px 13px;
	background-position: center center, center center;
	background-repeat: no-repeat;
	background-color: transparent;
	transform-origin: 50% 50%;
	transition: transform 240ms cubic-bezier(0.22,1,0.36,1), background-color 160ms cubic-bezier(0.22,1,0.36,1);
}
.bf-faq details[open] summary::after { transform: rotate(45deg); }
.bf-faq summary:hover::after { background-color: var(--wp--preset--color--accent-tint); }

.bf-faq details > :not(summary) { max-width: 54ch; color: var(--wp--preset--color--ink-muted); }
.bf-faq details > p { padding: 0 0 1.25rem; margin: 0 !important; }
@media (prefers-reduced-motion: no-preference) {
	.bf-faq details[open] > p { animation: bf-answer 240ms cubic-bezier(0.22,1,0.36,1); }
	@keyframes bf-answer { from { opacity: 0; transform: translateY(-4px); } to { opacity: 1; transform: none; } }
}

/* ---------- Header (floating pill nav) ---------- */

.bf-nav {
	position: sticky; top: 1rem; z-index: 50;
	background: rgba(255, 255, 255, 0.82);
	-webkit-backdrop-filter: blur(12px); backdrop-filter: blur(12px);
	border: 1px solid var(--wp--preset--color--hairline);
	border-radius: 999px;
}
.bf-nav .wp-block-navigation a {
	padding: 8px 16px; border-radius: 999px;
	color: var(--wp--preset--color--ink); text-decoration: none;
	transition: background 160ms cubic-bezier(0.22,1,0.36,1);
}
.bf-nav .wp-block-navigation a:hover { background: var(--wp--preset--color--surface); text-decoration: none; color: var(--wp--preset--color--ink); }
/* Apply pill in the nav: gold -> deep amber + white on hover (5.02:1) */
.bf-nav .wp-block-button__link:hover { background: var(--wp--preset--color--ink); color: var(--wp--preset--color--canvas); }
.bf-nav .wp-block-navigation a:focus-visible { outline: 2px solid var(--wp--preset--color--primary); outline-offset: 2px; }
/* current-page indicator */
.bf-nav .wp-block-navigation .current-menu-item > a { background: var(--wp--preset--color--surface); }

/* ---------- Mobile nav overlay ----------
   backdrop-filter makes .bf-nav a containing block for fixed-position
   descendants, so WP's full-screen overlay was resolving inset:0 against the
   pill rather than the viewport — the menu opened as a clipped sliver inside a
   40px rounded bar. Dropping the filter while the menu is open hands the
   overlay back to the viewport. (sticky alone does not do this; only
   transform / filter / backdrop-filter / will-change / contain do.) */

.bf-nav:has(.wp-block-navigation__responsive-container.is-menu-open) {
	-webkit-backdrop-filter: none;
	        backdrop-filter: none;
	background: transparent;
	border-color: transparent;
}

.wp-block-navigation__responsive-container.is-menu-open {
	background: var(--wp--preset--color--canvas);
	padding: clamp(20px, 6vw, 32px);
}

/* The menu is a short list, so sit it just below the header rather than
   centring it in a tall empty screen. */
.wp-block-navigation__responsive-container.is-menu-open
	.wp-block-navigation__responsive-container-content {
	align-items: stretch;
	justify-content: flex-start;
	padding-top: clamp(64px, 14vh, 120px);
	width: 100%;
}

/* The nav block is configured to justify right for the desktop pill, and that
   layout rule follows it into the overlay — items end up shrink-wrapped and
   flushed to the right edge. Force a plain left-aligned column here. */
.bf-nav .wp-block-navigation__responsive-container.is-menu-open
	.wp-block-navigation__responsive-container-content
	.wp-block-navigation__container {
	flex-direction: column;
	align-items: stretch;
	justify-content: flex-start;
	gap: 0;
	width: 100%;
}

/* Each item is itself a flex column, and the block's right-justification lands
   on it as align-items:flex-end — that, not the list, is what was shrink-
   wrapping the links against the right edge. */
.bf-nav .wp-block-navigation__responsive-container.is-menu-open
	.wp-block-navigation__responsive-container-content
	.wp-block-navigation-item {
	width: 100%;
	align-items: stretch;
	border-bottom: 1px solid var(--wp--preset--color--hairline);
}
.wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-item:last-child {
	border-bottom: 0;
}

/* Full-width rows at display size: comfortably past the 44px minimum target,
   and the whole row is tappable rather than just the word. */
/* Matched at the same depth as core's own overlay rule, which sets padding:0
   at (0,4,0) and beats anything shorter. */
.bf-nav .wp-block-navigation__responsive-container.is-menu-open
	.wp-block-navigation__responsive-container-content
	.wp-block-navigation-item__content {
	/* Block fills the row on its own; width:100% here would add the horizontal
	   padding on top of the full width and push the row off screen. */
	display: block;
	/* Text is inset, but the rules above stay full-bleed — same language as the
	   section dividers down the page. */
	padding: 18px clamp(20px, 6vw, 32px);
	border-radius: 0;
	font-family: var(--wp--preset--font-family--display);
	font-size: clamp(1.5rem, 7vw, 2rem);
	font-weight: 700;
	letter-spacing: -0.02em;
	color: var(--wp--preset--color--ink);
}

/* Current page. Marked with a gold rule rather than gold text: on white, gold
   is 2.15:1 and light amber is worse — neither can carry type. Same reason the
   eyebrow chips put navy text on an amber ground instead of the reverse. */
.bf-nav .wp-block-navigation__responsive-container.is-menu-open
	.wp-block-navigation__responsive-container-content
	.current-menu-item > .wp-block-navigation-item__content {
	background: transparent;
	color: var(--wp--preset--color--ink);
	box-shadow: inset 4px 0 0 0 var(--wp--preset--color--accent);
}

/* Close control: WP ships it small and unstyled. */
.wp-block-navigation__responsive-container-close {
	top: clamp(20px, 6vw, 32px);
	right: clamp(20px, 6vw, 32px);
	width: 44px;
	height: 44px;
	display: flex;
	align-items: center;
	justify-content: center;
	border-radius: 999px;
	color: var(--wp--preset--color--ink);
	background: var(--wp--preset--color--surface);
}
.wp-block-navigation__responsive-container-close svg { width: 22px; height: 22px; }

/* ---------- Apply: pill on desktop, menu row on mobile ----------
   The nav bar is a three-up flex row (title · menu · Apply) justified
   space-between. On mobile the menu collapses to a single hamburger, which
   left it stranded in the dead centre of the bar between the title and the
   Apply pill. And with the overlay covering the screen, Apply was unreachable
   for as long as the menu was open — on a site whose whole job is routing
   people to the portal.

   So the two swap at the breakpoint: below 600px the pill is hidden and the
   menu carries an Apply row; above it, the pill returns and the menu drops the
   duplicate. Matched by href rather than position, so reordering the menu
   cannot quietly break it. */

/* Core switches the overlay in at 600px. That leaves 600–781px showing the
   full bar, where the gaps bottom out at 24px and the pill reads as crammed.
   Hold the overlay all the way to 782px — the same breakpoint every column in
   the theme stacks at, so navigation and layout go single-column together. */
@media (min-width: 600px) and (max-width: 781px) {
	.bf-nav .wp-block-navigation__responsive-container:not(.hidden-by-default):not(.is-menu-open) { display: none; }
	.bf-nav .wp-block-navigation__responsive-container-open:not(.always-shown) { display: flex; }
}

@media (min-width: 782px) {
	.bf-nav .wp-block-navigation-item:has(a[href*="app.burtfoundation.org"]) { display: none; }
}

@media (max-width: 781px) {
	/* Leaves title · hamburger, so the hamburger sits hard right where it reads
	   as a control rather than floating mid-bar. */
	.bf-nav > .wp-block-buttons { display: none; }

	.bf-nav .wp-block-navigation__responsive-container.is-menu-open
		.wp-block-navigation-item:has(a[href*="app.burtfoundation.org"]) {
		border-bottom: 0;
		/* Inset to the same gutter as the link text above it. The rules are
		   full-bleed; a button touching both bezels just looks unfinished. */
		margin: 24px clamp(20px, 6vw, 32px) 0;
		width: auto;
	}
	.bf-nav .wp-block-navigation__responsive-container.is-menu-open
		.wp-block-navigation__responsive-container-content
		a[href*="app.burtfoundation.org"] {
		background: var(--wp--preset--color--primary);
		color: var(--wp--preset--color--canvas);
		border-radius: 999px;
		text-align: center;
	}
}

/* Hamburger: give it a real target and match the pill. Scoped below 782px —
   core hides this button above 600px with `display:none`, and an unscoped
   `display:flex` here outranks it and leaves a hamburger sat in the desktop
   pill next to the full menu. */
@media (max-width: 781px) {
	.bf-nav .wp-block-navigation__responsive-container-open {
		width: 44px;
		height: 44px;
		display: flex;
		align-items: center;
		justify-content: center;
		border-radius: 999px;
		color: var(--wp--preset--color--ink);
	}
	.bf-nav .wp-block-navigation__responsive-container-open svg { width: 26px; height: 26px; }
}

/* News grid: the query grid stretches the <li> it generates, but not the card
   inside it, so two posts of different excerpt lengths end up as cards of
   different heights sitting on a shared row. */
.wp-block-post-template > li > .bf-card { height: 100%; }

/* ---------- Grant cycle card on mobile ----------
   The buttons sit in a narrow right-justified column for the desktop layout.
   Stacked on a phone that justification survives, so two pills of different
   widths end up ragged against the right edge of a left-aligned card. Full
   width and in the card's own alignment instead — and the primary action gets
   a full-width tap target, which is what it deserves on the one card people
   actually come back to check. */
@media (max-width: 781px) {
	.bf-cycle .wp-block-buttons {
		width: 100%;
		justify-content: flex-start;
		gap: 10px;
	}
	.bf-cycle .wp-block-button { width: 100%; }
	.bf-cycle .wp-block-button__link { display: block; width: 100%; text-align: center; }
}

/* ---------- Footer ---------- */

.bf-footer a { color: var(--wp--preset--color--canvas); text-decoration: none; }
.bf-footer a:hover { color: var(--wp--preset--color--accent); text-decoration: none; }
/* Plain-text column labels, baseline-aligned with the brand row — not chips. */
.bf-footer .bf-footer-legal-row { grid-column: 1 / -1; width: 100%; }
.bf-footer .bf-footer-label {
	font-size: var(--wp--preset--font-size--micro) !important;
	font-weight: 600; letter-spacing: 0.06em; text-transform: uppercase;
	color: var(--wp--preset--color--accent);
	margin: 0.35rem 0 0.85rem !important;
}

/* ---------- Gravity Forms (brand skin, scoped to the form slot) ----------
   Styles apply the moment GF is installed — no restyling pass needed. */

/* Gravity Forms 3.x ships an "orbital" theme driven entirely by CSS custom
   properties, and those outrank ordinary declarations — a plain
   `border-radius` on .gform_button loses to GF's own `--gf-local-radius`.
   Setting the variables instead is both how the framework is meant to be
   customised and far less brittle: the brand values then flow through every
   state GF generates (hover, focus, disabled, error) rather than us chasing
   each one and missing some. */
.bf-form-slot .gform_wrapper.gform-theme--orbital {
	/* Inputs */
	--gf-ctrl-radius: 12px;
	--gf-ctrl-border-color: var(--wp--preset--color--hairline);
	--gf-ctrl-border-color-focus: var(--wp--preset--color--primary);
	--gf-ctrl-bg-color: var(--wp--preset--color--canvas);
	--gf-ctrl-color: var(--wp--preset--color--ink);

	/* Submit — navy, going gold on hover, exactly like every other primary
	   button on the site. */
	--gf-ctrl-btn-radius: 999px;
	--gf-ctrl-btn-bg-color-primary: var(--wp--preset--color--primary);
	--gf-ctrl-btn-bg-color-hover-primary: var(--wp--preset--color--accent);
	--gf-ctrl-btn-bg-color-focus-primary: var(--wp--preset--color--accent);
	--gf-ctrl-btn-color-primary: var(--wp--preset--color--canvas);
	--gf-ctrl-btn-color-hover-primary: var(--wp--preset--color--ink);
	--gf-ctrl-btn-color-focus-primary: var(--wp--preset--color--ink);
	--gf-ctrl-btn-border-color-primary: var(--wp--preset--color--primary);
	--gf-ctrl-btn-border-color-hover-primary: var(--wp--preset--color--accent);
	--gf-ctrl-btn-border-color-focus-primary: var(--wp--preset--color--accent);
	--gf-ctrl-btn-font-family: var(--wp--preset--font-family--body);
	--gf-ctrl-btn-font-weight: 600;

	/* Labels */
	--gf-ctrl-label-color-primary: var(--wp--preset--color--ink);
	--gf-ctrl-label-font-family-primary: var(--wp--preset--font-family--body);
	--gf-ctrl-label-font-weight-primary: 600;
}

.bf-form-slot .gform_wrapper label.gfield_label {
	font-size: var(--wp--preset--font-size--small);
	font-weight: 600; color: var(--wp--preset--color--ink);
	margin-bottom: 6px;
}
.bf-form-slot .gform_wrapper input[type="text"],
.bf-form-slot .gform_wrapper input[type="email"],
.bf-form-slot .gform_wrapper input[type="tel"],
.bf-form-slot .gform_wrapper select,
.bf-form-slot .gform_wrapper textarea {
	font-family: var(--wp--preset--font-family--body);
	font-size: var(--wp--preset--font-size--medium);
	color: var(--wp--preset--color--ink);
	background: var(--wp--preset--color--canvas);
	border: 1.5px solid var(--wp--preset--color--hairline);
	border-radius: 12px;
	padding: 11px 14px; width: 100%;
	transition: border-color 160ms cubic-bezier(0.22,1,0.36,1), box-shadow 160ms cubic-bezier(0.22,1,0.36,1);
}
/* Focus ring. GF's framework styles focus through :where()-wrapped selectors
   that a plain border-color declaration does not reliably beat — a keyboard
   user was getting GF's default hairline, i.e. no visible focus at all, which
   fails WCAG 2.4.7. An outline is the reliable answer: it is not a border, so
   nothing in GF's control styling competes with it, and it matches the focus
   treatment used in the nav. Deliberately :focus rather than :focus-visible —
   in a text field you want to see where you are typing however you got there. */
.bf-form-slot .gform_wrapper.gform-theme--orbital input:focus,
.bf-form-slot .gform_wrapper.gform-theme--orbital textarea:focus,
.bf-form-slot .gform_wrapper.gform-theme--orbital select:focus,
.bf-form-slot .gform_wrapper input:focus,
.bf-form-slot .gform_wrapper textarea:focus,
.bf-form-slot .gform_wrapper select:focus {
	outline: 2px solid var(--wp--preset--color--primary);
	outline-offset: 2px;
	border-color: var(--wp--preset--color--primary);
}
.bf-form-slot .gform_wrapper .gfield { margin-bottom: 1rem; }

/* Gravity Forms ships red for required markers and validation, plus its own
   grey for descriptions. This site is five colours and red is deliberately not
   one of them — a red tertiary was trialled and dropped because navy + gold +
   red reads as the Colorado flag. Errors use the amber language instead:
   navy type on a light amber ground, which is also a stronger contrast than
   the red it replaces. */
.bf-form-slot .gform_wrapper .gfield_required,
.bf-form-slot .gform_wrapper .gfield_required_text,
.bf-form-slot .gform_wrapper .gfield_required * {
	color: var(--wp--preset--color--ink-muted);
	font-weight: 600;
}
.bf-form-slot .gform_wrapper .gfield_description,
.bf-form-slot .gform_wrapper .gform_description {
	color: var(--wp--preset--color--ink-muted);
}
.bf-form-slot .gform_wrapper .gfield_validation_message,
.bf-form-slot .gform_wrapper .validation_message,
.bf-form-slot .gform_wrapper .gform_validation_errors {
	background: var(--wp--preset--color--accent-tint);
	border: 1px solid var(--wp--preset--color--accent);
	border-radius: 12px;
	color: var(--wp--preset--color--ink);
	padding: 10px 14px;
	font-size: var(--wp--preset--font-size--small);
}
.bf-form-slot .gform_wrapper .gform_validation_errors > h2,
.bf-form-slot .gform_wrapper .gform_validation_errors * {
	color: var(--wp--preset--color--ink);
}
.bf-form-slot .gform_wrapper .gfield.gfield_error,
.bf-form-slot .gform_wrapper .gfield_error {
	background: transparent;
	border: none;
	padding-left: 0;
	padding-right: 0;
}
/* The error icon carries a 5% red wash of its own. Kept rather than hidden —
   an icon beside the message helps people scan which field failed — but
   recoloured, since red is not one of this site's five. */
.bf-form-slot .gform_wrapper .gform-icon--circle-error {
	background-color: transparent !important;
	color: var(--wp--preset--color--ink) !important;
}
.bf-form-slot .gform_wrapper .gfield_error input,
.bf-form-slot .gform_wrapper .gfield_error textarea { border-color: var(--wp--preset--color--accent); border-width: 2px; }
.bf-form-slot .gform_wrapper .gform_button {
	font-family: var(--wp--preset--font-family--body);
	font-weight: 600; font-size: var(--wp--preset--font-size--medium);
	color: var(--wp--preset--color--canvas);
	/* background-color, not `background: <gradient var>` — a gradient sets
	   background-image and leaves the underlying colour untouched, which is
	   how GF's blue was still showing through. */
	background-color: var(--wp--preset--color--primary);
	border: none; border-radius: 999px;
	padding: 12px 24px; cursor: pointer;
	transition: background 160ms cubic-bezier(0.22,1,0.36,1), color 160ms cubic-bezier(0.22,1,0.36,1), transform 160ms cubic-bezier(0.22,1,0.36,1);
}
.bf-form-slot .gform_wrapper .gform_button:hover { background: var(--wp--preset--color--accent); color: var(--wp--preset--color--ink); }
.bf-form-slot .gform_wrapper .gform_button:active { transform: scale(0.97); }
.bf-form-slot .gform_wrapper .gform_button:focus-visible { outline: 3px solid var(--wp--preset--color--primary); outline-offset: 3px; }
.bf-form-slot .gform_wrapper .gfield_validation_message,
.bf-form-slot .gform_wrapper .validation_message {
	color: var(--wp--preset--color--ink); font-size: var(--wp--preset--font-size--small); font-weight: 500;
	background: none; border: none; padding: 4px 0 0;
}
.bf-form-slot .gform_confirmation_message {
	font-size: var(--wp--preset--font-size--lead);
	color: var(--wp--preset--color--ink);
}

/* Story: the image column takes its height from the text column, not the other
   way round.

   `height:100%` on an <img> inside an auto-height flex container resolves to
   `auto`, so the picture's intrinsic height silently became the row height —
   fine while every photo was landscape and shorter than the copy, but a
   portrait image made the row taller than the text and left a gap beneath it.
   Taking the figure out of flow is the only way the image cannot vote on the
   height: the row is then sized purely by the text, and the picture fills
   whatever box that produces. */
.bf-story.wp-block-columns { align-items: stretch; }

@media (min-width: 782px) {
	.bf-story .wp-block-column:last-child { position: relative; align-self: stretch; }
	.bf-story .wp-block-column:last-child .wp-block-image {
		position: absolute;
		inset: 0;
		margin: 0;
	}
	.bf-story .wp-block-column:last-child img {
		width: 100%;
		height: 100%;
		object-fit: cover;
	}
}

/* Stacked, there is no text column to match, so the image keeps its own box. */
@media (max-width: 781px) {
	.bf-story .wp-block-column:last-child img { aspect-ratio: 4/3; height: auto; width: 100%; object-fit: cover; }
}

/* ---------- Board cards ---------- */

/* Featured cards (chair + ED): avatar/role left, bio right — never centered. */
.bf-feature-card, .bf-feature-card * { text-align: left !important; }
.bf-feature-card .wp-block-column { align-self: flex-start; }

.bf-member-card { text-align: left; }
.bf-member-card .bf-avatar { width: 56px; height: 56px; }
.bf-member-card .bf-avatar p { font-size: 1.05rem; }

/* ---------- Scroll reveals (added by reveal.js; no-JS/reduced-motion = visible) ---------- */

@media (prefers-reduced-motion: no-preference) {
	.bf-reveal { opacity: 0; transform: translateY(16px); transition: opacity 520ms cubic-bezier(0.22,1,0.36,1), transform 520ms cubic-bezier(0.22,1,0.36,1); }
	.bf-reveal.bf-in { opacity: 1; transform: none; }
	.bf-stagger > * { opacity: 0; transform: translateY(16px); transition: opacity 480ms cubic-bezier(0.22,1,0.36,1), transform 480ms cubic-bezier(0.22,1,0.36,1); transition-delay: var(--bf-d, 0ms); }
	.bf-stagger.bf-in > * { opacity: 1; transform: none; }
}

/* ---------- Image zoom + pan (class added by reveal.js on hover devices) ----------
   The figure is the frame and clips; the img is what moves. Panning the child
   rather than the frame keeps the rounded corner steady and avoids the hover
   flicker you get when the moving element is also the one being hovered. */

@media (hover: hover) and (pointer: fine) {
	.bf-pan { overflow: hidden; border-radius: 24px; }
	.bf-pan img {
		display: block;
		will-change: transform;
		transition: transform 460ms cubic-bezier(0.22,1,0.36,1);
	}
	/* While tracking the cursor, follow closely but not instantly — a little lag
	   gives the image weight, and it keeps the initial zoom from snapping. The
	   longer ease above is the settle back to rest on pointerleave. */
	.bf-pan.is-panning img { transition: transform 200ms cubic-bezier(0.22,1,0.36,1); }
}

/* Count-up rewrites these digits every frame — tabular figures stop the number
   from changing width as it climbs and nudging the layout. */
.bf-stat-num { font-variant-numeric: tabular-nums; }

/* ---------- Background rails ----------
   The layout is a set of floating cards, which can read as disconnected
   fragments. Faint full-height rules behind everything give them a common
   ground without competing for attention. Fixed, so they sit still while the
   content scrolls over them; masked at top and bottom so they fade out rather
   than colliding with the header and footer. */

.wp-site-blocks { position: relative; z-index: 1; }

body::before {
	content: "";
	position: fixed;
	inset: 0;
	z-index: 0;
	pointer-events: none;

	/* One hairline per tile, tiled edge to edge across any viewport. Centring
	   the tile puts rails at ±150px, ±450px, ±750px … from the middle of the
	   page — half a step off the 1200px content edge, so a rail never lands on
	   a card border where it would read as a misaligned box rather than a grid.
	   Because it tiles from the centre outwards it just keeps going on
	   ultra-wide displays instead of stopping at the content width. */
	background-image: linear-gradient(
		to right,
		color-mix(in srgb, var(--wp--preset--color--ink) 7%, transparent) 0 1px,
		transparent 1px
	);
	background-size: 300px 100%;
	background-position: center top;
	background-repeat: repeat;

	-webkit-mask-image: linear-gradient(to bottom, transparent 0, #000 12%, #000 88%, transparent 100%);
	        mask-image: linear-gradient(to bottom, transparent 0, #000 12%, #000 88%, transparent 100%);
}

/* ---------- Section dividers ----------
   A hairline in the gap between every top-level section, full-bleed like the
   vertical rails so the two read as one grid. The gap between sections is a
   uniform 72px, so the line sits at -36px: dead centre, and never closer than
   36px to a rounded card edge — the collision that made rails on the content
   edge look like a misprint. Adds no spacing of its own. */

:root {
	/* Mirrors the blockGap between top-level sections (theme.json →
	   styles.spacing.blockGap). It is fluid, not fixed — at 1440px it resolves
	   to 72px but it shrinks to 40px on a phone, so a hardcoded half-gap would
	   put the divider almost on top of the preceding section at small widths.
	   Keep this expression identical to theme.json's. */
	--bf-section-gap: clamp(2.5rem, 5vw, 5rem);
}

.wp-block-post-content > * + * { position: relative; }

.wp-block-post-content > * + *::before {
	content: "";
	position: absolute;
	top: calc(var(--bf-section-gap) / -2);
	left: 50%;
	transform: translateX(-50%);
	width: 100vw;
	height: 1px;
	background: color-mix(in srgb, var(--wp--preset--color--ink) 7%, transparent);
	pointer-events: none;
}

/* The run of sections ends at the last one, so nothing closes it off against
   the footer — and the footer lives outside .wp-block-post-content, beyond the
   reach of the rule above. Hang a divider off the footer instead so the rhythm
   carries all the way down the page.

   The gap to the footer was three separate values stacked — main's bottom
   padding (64px), the site block gap (24px) and the footer's own top padding
   (24px) — totalling 112px against a 72px section gap, so the page visibly
   loosened right at the bottom. Collapse all three into one controlled gap so
   the last section sits exactly as far from the footer as every section sits
   from its neighbour, and the divider centres on the same value as the rest. */
.wp-site-blocks > main { padding-bottom: 0 !important; }

/* Note there are two nested <footer> elements: the template-part wrapper, and
   the group inside it that carries the padding from parts/footer.html. Both
   have to be zeroed or the inner one quietly adds its own 24px back. */
.wp-site-blocks > footer {
	position: relative;
	padding-top: 0 !important;
	margin-top: var(--bf-section-gap) !important;
}

.wp-site-blocks > footer > footer { padding-top: 0 !important; }

.wp-site-blocks > footer::before {
	content: "";
	position: absolute;
	top: calc(var(--bf-section-gap) / -2);
	left: 50%;
	transform: translateX(-50%);
	width: 100vw;
	height: 1px;
	background: color-mix(in srgb, var(--wp--preset--color--ink) 7%, transparent);
	pointer-events: none;
}

/* ---------- Editor parity ---------- */

.editor-styles-wrapper .bf-reveal, .editor-styles-wrapper .bf-stagger > * { opacity: 1 !important; transform: none !important; }
.editor-styles-wrapper::before { display: none; }
/* Dividers are full-bleed off a 100vw box; inside the editor canvas that would
   overflow the frame rather than the page. */
.editor-styles-wrapper .wp-block-post-content > * + *::before { display: none; }

/* ---------- Prose pages (privacy policy, sitemap) ----------
   Long-form text at a comfortable measure. These pages are read, not scanned,
   so they get generous line spacing and clear heading separation rather than
   the tighter rhythm the marketing sections use. */

.bf-prose { font-size: var(--wp--preset--font-size--medium); }
.bf-prose p { line-height: 1.75; }
.bf-prose h2 { margin-top: 2.5rem; }
.bf-prose h3 { margin-top: 1.75rem; }
.bf-prose ul, .bf-prose ol { padding-left: 1.25rem; line-height: 1.75; }
.bf-prose li + li { margin-top: 0.4rem; }

/* The HTML sitemap builds its own markup, so give it the site's list language
   rather than leaving it as browser defaults. */
.bf-sitemap ul { list-style: none; padding-left: 0; }
.bf-sitemap ul ul { padding-left: 1.25rem; margin-top: 0.4rem; }
.bf-sitemap li { margin-top: 0.5rem; }
.bf-sitemap a { color: var(--wp--preset--color--ink); text-decoration: none; }
.bf-sitemap a:hover {
	text-decoration: underline;
	text-decoration-color: var(--wp--preset--color--accent);
	text-decoration-thickness: 2px;
}
/* The plugin emits <h3> section headings at body size; give them the site's
   display face so "Pages" and "Posts" read as section headings rather than
   bold paragraphs. */
.bf-sitemap h2, .bf-sitemap h3 {
	font-family: var(--wp--preset--font-family--display);
	font-size: var(--wp--preset--font-size--h-3);
	font-weight: 700;
	letter-spacing: -0.02em;
	margin-top: 2.5rem;
	margin-bottom: 0.75rem;
}
.bf-sitemap > .lwd-html-sitemap > .lwd-html-sitemap-section:first-child h3 { margin-top: 0; }

/* ---------- Founders portrait ----------
   The one image on the site of specific, named people. It sits at card scale
   beside its caption rather than as a full-width band: at content width the
   portrait stood taller than any other element on the site and read as a
   poster rather than a section.

   The radius lives on the figure, not the image: the cursor pan scales the
   image past its frame, so whatever clips it has to be the frame — a radius on
   the image itself gets scaled out of view and the corners square off. */

.bf-portrait { overflow: hidden; margin: 0; border-radius: 24px; }
.bf-portrait img {
	display: block;
	width: 100%;
	aspect-ratio: 4 / 3;
	object-fit: cover;
	/* Both subjects sit above the vertical centre; a straight centre crop
	   trims the tops of their heads. */
	object-position: 50% 38%;
}

/* Image left, text right — the story block directly below runs the other way
   round, so the pair reads as an alternating rhythm instead of the same
   layout twice. */
@media (max-width: 781px) {
	.bf-portrait img { aspect-ratio: 3 / 2; }
}
}
