/**
 * Global Base Styles — Kds
 */

*,
*::before,
*::after {
	box-sizing: border-box;
}

/* ── Smooth Scroll ──────────────────────────────────────────────────────────── */

html {
	scroll-behavior: smooth;
}

@media (prefers-reduced-motion: reduce) {
	html {
		scroll-behavior: auto;
	}
}

body {
	font-family: var(--kd-font-body);
	font-size: var(--kd-size-body);
	font-weight: var(--kd-fw-body);
	line-height: var(--kd-lh-body);
	color: var(--kd-color-body);
	background-color: var(--kd-color-base);
	-webkit-font-smoothing: antialiased;
}

img,
video {
	max-width: 100%;
	height: auto;
	display: block;
}

a {
	color: var(--kd-color-primary);
	transition: color var(--kd-transition-fast);
}

a:hover {
	color: var(--kd-color-secondary);
}

/* ── Announcement Bar (Customizer → Announcement Bar; printed by kds_print_announcement_bar) ── */

.kd-announcement-bar {
	background-color: var(--kd-color-banner-bg);
	text-align: center;
	font-size: 1rem;
	font-weight: 700;
	color: var(--kd-color-base);
	width: 100%;
	min-height: 2.75rem; /* grows when the text wraps on small screens */
	display: flex;
	align-items: center;
	justify-content: center;
	padding: 0.625rem var(--kd-edge-pad);
}

.kd-announcement-bar p {
	margin: 0;
	line-height: 1.4;
}

.kd-announcement-bar a {
	color: inherit;
	text-decoration: underline;
	text-underline-offset: 0.1875rem;
}

/* ── Buttons ───────────────────────────────────────────────────────────────── */

.wp-block-button__link,
.kd-btn {
	display: inline-block;
	font-family: var(--kd-font-heading);
	font-size: var(--kd-size-btn);
	font-weight: var(--kd-fw-heading);
	text-transform: uppercase;
	letter-spacing: 0.2px;
	border-radius: var(--kd-radius-pill);
	padding: 0.85em 1.75em;
	transition:
		background-color var(--kd-transition-base),
		color var(--kd-transition-base),
		border-color var(--kd-transition-base);
	cursor: pointer;
	text-decoration: none;
	border: 3px solid transparent;
	line-height: 1.2;
	min-inline-size: var(--kd-btn-min-w);
	text-align: center;
}

/* Header / mobile-panel CTAs and the text-link style size to their label, not
   the button floor. */
.kd-header-cta,
.kd-header-donate,
.kd-mobile-cta,
.wp-block-button.is-style-text-link {
	--kd-btn-min-w: 0;
}

/* Primary button (fill) — purple → indigo hover */
.wp-block-button:not(.is-style-outline):not(.is-style-text-link)
	.wp-block-button__link {
	background-color: var(--kd-btn-bg);
	color: var(--kd-btn-fg);
	border-color: var(--kd-btn-bg);
}

.wp-block-button:not(.is-style-outline):not(.is-style-text-link)
	.wp-block-button__link:hover {
	background-color: var(--kd-btn-bg-hover);
	border-color: var(--kd-btn-bg-hover);
	color: var(--kd-btn-fg);
}

/* Secondary button (outline) — 3px purple, stays outlined → indigo on hover */
.wp-block-button.is-style-outline .wp-block-button__link {
	background-color: transparent;
	color: var(--kd-btn-outline);
	border-color: var(--kd-btn-outline);
	border-width: 3px;
}

.wp-block-button.is-style-outline .wp-block-button__link:hover {
	background-color: transparent;
	color: var(--kd-btn-outline-hover);
	border-color: var(--kd-btn-outline-hover);
}

/* Inverted outline button — white on purple bands (header donate, footer subscribe) */
.kd-btn-invert .wp-block-button__link,
.kd-btn-invert.is-style-outline .wp-block-button__link {
	background-color: transparent;
	color: var(--kd-color-base);
	border-color: var(--kd-color-base);
	border-width: 3px;
}

.kd-btn-invert .wp-block-button__link:hover,
.kd-btn-invert.is-style-outline .wp-block-button__link:hover {
	background-color: var(--kd-color-base);
	color: var(--kd-color-primary);
	border-color: var(--kd-color-base);
}

/* Text link button */
.wp-block-button.is-style-text-link .wp-block-button__link {
	background: none;
	border: none;
	border-radius: 0;
	padding: 0;
	color: var(--kd-btn-link);
	font-family: var(--wp--preset--font-family--heading);
	font-weight: 900;
	font-size: 1.125rem;
	text-transform: uppercase;
	text-decoration: underline;
	text-decoration-color: var(--kd-btn-link);
	text-decoration-thickness: 3px;
	text-underline-offset: 8px;
	letter-spacing: 0.02em;
	display: inline-flex;
	align-items: center;
	gap: 0.5rem;
}

.wp-block-button.is-style-text-link .wp-block-button__link:hover {
	background: none;
	color: var(--kd-btn-link-accent);
	text-decoration-color: var(--kd-btn-link-accent);
}

/* Buttons on the interior hero (dark) — invert to light; no per-section recolor */
.kd-hero-interior
	.wp-block-button:not(.is-style-outline)
	.wp-block-button__link {
	background-color: var(--kd-btn-fg);
	color: var(--kd-btn-bg);
	border-color: var(--kd-btn-fg);
}
.kd-hero-interior
	.wp-block-button:not(.is-style-outline)
	.wp-block-button__link:hover {
	background-color: color-mix(
		in srgb,
		var(--kd-btn-fg) 88%,
		var(--kd-btn-bg)
	);
	border-color: color-mix(in srgb, var(--kd-btn-fg) 88%, var(--kd-btn-bg));
	color: var(--kd-btn-bg);
}
.kd-hero-interior .wp-block-button.is-style-outline .wp-block-button__link {
	background-color: transparent;
	color: var(--kd-btn-fg);
	border-color: var(--kd-btn-fg);
}
.kd-hero-interior
	.wp-block-button.is-style-outline
	.wp-block-button__link:hover {
	background-color: var(--kd-btn-fg);
	color: var(--kd-btn-bg);
	border-color: var(--kd-btn-fg);
}

/* ══════════════════════════════════════════════════════════════════════════════
   SITE HEADER — two-tier nav (indigo top-strip + purple main bar, logo overlap)
   Built from Figma Navigation component (258:2625). Dropdown + mobile-menu
   styling is a designer TODO — structure here, restyle on delivery.
   ══════════════════════════════════════════════════════════════════════════════ */

/* Sticky lives on the template-part WRAPPER, not .kd-site-header.
   The wrapper (header.wp-block-template-part) is the direct child of
   .wp-site-blocks (full page height), so sticky has room to travel. Stickying
   .kd-site-header itself fails — its parent (the wrapper) is only as tall as the
   header, so there's no travel range (the containing-block trap). Offset by the
   WP admin-bar height for logged-in users; resolves to 0 in production. The
   `header` type selector (plus :has) targets only this wrapper — never the
   footer's `footer.wp-block-template-part`. */
header.wp-block-template-part:has(.kd-site-header) {
	position: sticky;
	top: var(--wp-admin--admin-bar--height, 0px);
	z-index: var(--kd-z-header);
}

.kd-site-header {
	position: relative;
	z-index: var(--kd-z-header);
	width: 100%;
}

/* No vertical gap between the two tiers (kill WP flow block-gap) */
.kd-site-header > * {
	margin-block: 0 !important;
}

/* Shared horizontal padding aligns both tiers to the content column (token) */
.kd-topbar,
.kd-mainbar {
	padding-left: var(--kd-edge-pad) !important;
	padding-right: var(--kd-edge-pad) !important;
}

/* Tier 1 — indigo secondary strip */
.kd-topbar {
	/* The top strip stays DARK while the main bar is white, so it needs the
	   inverse link colour. --kd-nav-link is scoped here rather than globally so
	   each band carries its own contrast-correct value. */
	--kd-nav-link: var(--kd-color-base);
	color: var(--kd-color-base);
	background-color: var(--kd-color-secondary);
	/* Smooth collapse when the header compacts on scroll — animate height/padding/
	   opacity instead of an abrupt display:none (which jumped the header ~46px and
	   caused the scroll glitch). max-height sits just above the strip's natural 46px. */
	overflow: hidden;
	max-height: 3rem;
	transition:
		max-height var(--kd-transition-base),
		padding-block var(--kd-transition-base),
		opacity var(--kd-transition-base),
		visibility 0s;
}

.kd-topbar .kd-topnav {
	min-height: 0;
}

/* Secondary menu (top strip) aligns to the right edge of the content column */
.kd-topbar .kd-navmount--secondary,
.kd-menu-wrap--secondary {
	display: flex;
	justify-content: flex-end;
}

/* Tier 2 — purple main bar */
.kd-mainbar {
	/* White nav bar. The starter's default header is a light bar under a dark
	   top strip — deliberately neutral so a client re-skin is a token change,
	   not a rewrite. Link colour comes from --kd-nav-link (contrast). */
	background-color: var(--kd-color-base);
	border-bottom: 1px solid var(--kd-color-neutral-300);
	min-height: var(--kd-mainbar-height);
	gap: 1.5rem;
	position: relative;
}

/* Logo — sits left, pushes the nav cluster right; overflows the bar a touch */
.kd-site-header .kd-site-logo.wp-block-site-logo {
	margin: 0 auto 0 0;
}

.kd-site-header .kd-site-logo img,
.kd-site-header .kd-site-logo .custom-logo {
	width: 110px;
	height: auto;
	max-height: none;
	display: block;
}

/* ── Brand badge (header) — circular logo overflows the bar into the hero ─────
   Desktop: absolutely placed against the (position:relative) mainbar so it hangs
   below the purple bar without growing it, and paints above the hero. The left
   offset matches the bar's content-column padding so it aligns with the content.
   Mobile: contained inside the bar (see the ≤768px override below). */
.kd-site-header .kd-brand-badge {
	/* Inline logo, sized to sit INSIDE the bar. The 2x overflowing badge this
	   replaced was a the community Celebrates flourish, not a starter default —
	   it depended on that project's circular mark and forced a taller header. */
	position: relative;
	display: flex;
	align-items: center;
	line-height: 0;
}

/* Pin the brand to the LEFT edge of the bar.

   .kd-mainbar is justify-content:flex-end, which was correct while the badge was
   position:absolute and therefore out of flow — only the menu and actions were
   being pushed right. Once the badge became a normal flex item it was dragged
   right along with them and ended up sitting 483px past the bar's content start,
   directly against the menu. `margin-inline-end:auto` puts the brand hard left
   while leaving the menu + actions right-aligned as a group. */
.kd-site-header .kd-brand-badge {
	margin-inline-end: auto;
}

.kd-site-header .kd-brand-badge img {
	display: block;
	width: 44px; /* sits comfortably inside the 84px bar */
	height: auto;
	/* Asset is a transparent-background badge (no white card), so no clip needed;
	   the drop-shadow follows the badge's own alpha shape. */
	filter: drop-shadow(0 6px 14px rgba(0, 0, 0, 0.18));
	transition:
		width var(--kd-transition-base),
		filter var(--kd-transition-base);
}

/* ── Sticky-shrink on scroll ──────────────────────────────────────────────────
   JS (navigation.js) adds body.kd-header-scrolled past a small scroll threshold.
   The secondary strip collapses and the overflowing badge shrinks back INTO the
   main bar, so the header docks as a compact bar at the top. The sub-nav (if any)
   then sticks directly beneath it — see assets/css/patterns/anchor-nav.css. */
body.kd-header-scrolled .kd-topbar {
	max-height: 0;
	padding-block: 0 !important; /* override the inline 10px so it fully collapses */
	opacity: 0;
	visibility: hidden; /* drop the secondary links from the tab order once hidden */
	/* delay visibility:hidden until the collapse finishes so the links stay
	   reachable during the animation; reverses instantly on expand */
	transition:
		max-height var(--kd-transition-base),
		padding-block var(--kd-transition-base),
		opacity var(--kd-transition-base),
		visibility 0s var(--kd-transition-base);
}

/* Scrolled state: the logo already sits inside the bar, so nothing to resize. */
body.kd-header-scrolled .kd-site-header .kd-brand-badge img {
	width: 38px;
}

@media (max-width: 768px) {
	/* Mobile — keep it simple: contained inside the bar, no overflow */
	.kd-site-header .kd-brand-badge {
		position: static;
		left: auto;
		transform: none;
		margin-right: auto; /* pushes search/donate/hamburger to the right */
		align-self: center;
	}
	.kd-site-header .kd-brand-badge img {
		width: auto;
		height: 52px; /* fits inside the 72px mobile bar */
		filter: none;
	}
}

/* ── Classic menus on the bands (Appearance → Menus) ────────────────────────── */

.kd-menu-wrap {
	display: flex;
}

.kd-menu {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--kd-nav-gap);
	margin: 0;
	padding: 0;
	list-style: none;
	font-family: var(--kd-nav-font);
	font-weight: var(--kd-nav-weight);
	font-size: var(--kd-nav-size);
}

.kd-menu a {
	color: var(
		--kd-nav-link
	) !important; /* beats the global link colour on the light bar */
	text-decoration: none;
	display: inline-flex;
	align-items: center;
	gap: 0.3rem;
	line-height: 1.2;
	transition: opacity var(--kd-transition-fast);
}

.kd-menu > li > a:hover,
.kd-menu > li > a:focus-visible {
	opacity: var(--kd-nav-link-hover-opacity);
	color: var(--kd-nav-link);
}

/* Desktop dropdowns (li.menu-item-has-children) */
.kd-menu--primary .menu-item-has-children {
	position: relative;
}

/* Decorative "has children" caret. No-JS ONLY — once navigation.js runs, the
   disclosure button carries its own chevron and this would be a second one.
   Kept rather than deleted so the fallback still signals that a submenu exists. */
.kd-menu--primary .menu-item-has-children > a::after {
	content: "";
	width: 0.5em;
	height: 0.5em;
	border-right: 2px solid currentColor;
	border-bottom: 2px solid currentColor;
	transform: rotate(45deg) translateY(-1px);
	margin-left: 0.15rem;
	transition: transform var(--kd-transition-fast);
}

.kd-menu--primary.is-js .menu-item-has-children > a::after {
	content: none;
}

.kd-menu--primary .sub-menu {
	position: absolute;
	top: 100%;
	left: 0;
	margin: 0;
	padding: 0.5rem 0;
	list-style: none;
	min-width: var(--kd-dropdown-min-width);
	background: var(--kd-dropdown-bg);
	border-radius: var(--kd-dropdown-radius);
	box-shadow: var(--kd-dropdown-shadow);
	opacity: 0;
	visibility: hidden;
	transform: translateY(8px);
	transition:
		opacity var(--kd-transition-fast),
		transform var(--kd-transition-fast),
		visibility var(--kd-transition-fast);
	z-index: var(--kd-z-overlay);
}

/* No-JS fallback: hover/focus-within alone reveal the dropdown. Kept so the nav
   still works if navigation.js fails to load. */
.kd-menu--primary .menu-item-has-children:hover > .sub-menu,
.kd-menu--primary .menu-item-has-children:focus-within > .sub-menu {
	opacity: 1;
	visibility: visible;
	transform: translateY(0);
}

/* ── Dropdown disclosure button (inc/nav-dropdown.php) ──────────────────────
   Once navigation.js marks the menu `.is-js`, visibility is driven ONLY by
   `.is-open`, which the script sets in the same breath as `aria-expanded`.
   That single source of truth is the point: with the CSS-only rules above still
   live, hovering would reveal a submenu whose aria-expanded still said "false",
   so the announced state would lie to assistive tech. These are (0,5,0) against
   the (0,4,0) hover/focus-within rules above, so they win on specificity, not
   on source order. */
.kd-menu--primary.is-js .menu-item-has-children:hover > .sub-menu,
.kd-menu--primary.is-js .menu-item-has-children:focus-within > .sub-menu {
	opacity: 0;
	visibility: hidden;
	transform: translateY(8px);
}

.kd-menu--primary.is-js .menu-item-has-children.is-open > .sub-menu {
	opacity: 1;
	visibility: visible;
	transform: translateY(0);
}

.kd-submenu-toggle {
	display: none; /* revealed by JS — useless without the script */
	align-items: center;
	justify-content: center;
	/* 24px minimum target (WCAG 2.5.8 Target Size, Minimum) */
	inline-size: 1.5rem;
	block-size: 1.5rem;
	padding: 0;
	margin-inline-start: 0.25rem;
	border: 0;
	border-radius: var(--kd-radius-sm, 4px);
	background: transparent;
	color: currentColor;
	cursor: pointer;
	vertical-align: middle;
}

.kd-menu--primary.is-js .kd-submenu-toggle {
	display: inline-flex;
}

.kd-submenu-toggle__icon {
	transition: transform var(--kd-transition-fast);
}

.kd-submenu-toggle[aria-expanded="true"] .kd-submenu-toggle__icon {
	transform: rotate(180deg);
}

.kd-submenu-toggle:focus-visible {
	outline: 2px solid currentColor;
	outline-offset: 2px;
}

@media (prefers-reduced-motion: reduce) {
	.kd-submenu-toggle__icon {
		transition: none;
	}
}

.kd-menu--primary .sub-menu a {
	display: block;
	padding: 0.5rem 1.25rem;
	color: var(--kd-dropdown-link);
	font-weight: 500;
	white-space: nowrap;
}

.kd-menu--primary .sub-menu a:hover,
.kd-menu--primary .sub-menu a:focus-visible {
	color: var(--kd-dropdown-link-hover);
	opacity: 1;
}

/* ── Header actions — search + donate + hamburger ───────────────────────────── */

.kd-header-actions {
	gap: 1.25rem;
}

/* Collapse the core search block to an icon button, centered on the bar */
.kd-header-search {
	display: flex;
	align-items: center;
	margin: 0;
}

.kd-header-search .wp-block-search__inside-wrapper {
	display: flex;
	align-items: center;
	border: none;
	padding: 0;
	height: auto;
}

.kd-header-search .wp-block-search__button {
	display: flex;
	align-items: center;
	justify-content: center;
	background: transparent;
	border: none;
	color: var(--kd-color-base);
	min-width: auto;
	min-height: 0;
	height: 24px;
	padding: 0;
	margin: 0;
	line-height: 0;
}

.kd-header-search .wp-block-search__button svg {
	display: block;
}

.kd-header-search .wp-block-search__button svg {
	width: 24px;
	height: 24px;
	fill: var(--kd-color-base);
}

.kd-header-search .wp-block-search__button:hover {
	opacity: var(--kd-nav-link-hover-opacity);
}

.kd-header-donate .wp-block-button__link {
	padding: 0.5em 1.5em;
	font-size: 1.0625rem;
	white-space: nowrap;
}

/* Tighter donate on phones so it sits cleanly beside search + hamburger */
@media (max-width: 768px) {
	.kd-header-donate .wp-block-button__link {
		padding: 0.4em 1.1em;
		font-size: 0.9rem;
		border-width: 2px;
	}
	.kd-header-actions {
		gap: 0.75rem;
	}
}

/* ── Hamburger (mobile only) ────────────────────────────────────────────────── */

.kd-hamburger {
	display: none; /* shown ≤ breakpoint */
	flex-direction: column;
	justify-content: center;
	gap: 5px;
	width: 42px;
	height: 42px;
	padding: 8px;
	background: none;
	border: none;
	cursor: pointer;
}

.kd-hamburger__bar {
	display: block;
	width: var(--kd-burger-width);
	height: var(--kd-burger-bar-height);
	background: var(--kd-burger-bar);
	border-radius: 2px;
	transition:
		transform var(--kd-transition-base),
		opacity var(--kd-transition-base);
}

.kd-hamburger[aria-expanded="true"] .kd-hamburger__bar:nth-child(1) {
	transform: translateY(7.5px) rotate(45deg);
}
.kd-hamburger[aria-expanded="true"] .kd-hamburger__bar:nth-child(2) {
	opacity: 0;
}
.kd-hamburger[aria-expanded="true"] .kd-hamburger__bar:nth-child(3) {
	transform: translateY(-7.5px) rotate(-45deg);
}

/* ── Off-canvas mobile panel (slides in from the right) ─────────────────────── */

.kd-mobile-overlay {
	position: fixed;
	inset: 0;
	background: var(--kd-mobile-overlay-bg);
	opacity: 0;
	visibility: hidden;
	transition:
		opacity var(--kd-mobile-transition),
		visibility var(--kd-mobile-transition);
	z-index: var(--kd-z-mobile-overlay);
}

.kd-mobile-overlay.is-open {
	opacity: 1;
	visibility: visible;
}

.kd-mobile-panel {
	/* Dark panel: same reasoning as .kd-topbar — the nav link token is scoped
	   per band so each surface carries its own contrast-correct value. The
	   panel is always in the DOM (transform-hidden), so an unscoped token here
	   silently ships navy-on-navy links. */
	--kd-nav-link: var(--kd-color-base);
	position: fixed;
	top: 0;
	right: 0;
	bottom: 0;
	width: var(--kd-mobile-panel-width);
	max-width: var(--kd-mobile-panel-max);
	background: var(--kd-mobile-panel-bg);
	color: var(--kd-mobile-panel-fg);
	padding: var(--kd-mobile-panel-pad);
	box-shadow: var(--kd-mobile-panel-shadow);
	transform: translateX(100%);
	/* visibility, not just transform: a transform-hidden element is still
	   focusable. `inert` (set in PHP + toggled in JS) is the primary mechanism;
	   this is the fallback when JS has not run. */
	visibility: hidden;
	transition:
		transform var(--kd-mobile-transition),
		visibility var(--kd-mobile-transition);
	z-index: var(--kd-z-mobile-panel);
	overflow-y: auto;
	-webkit-overflow-scrolling: touch;
}

.kd-mobile-panel.is-open {
	transform: translateX(0);
	visibility: visible;
}

/* Keep the panel (and its ✕) clear of the WP admin bar when logged in —
   the bar is 32px on desktop, 46px at the ≤782px breakpoint. */
.admin-bar .kd-mobile-panel {
	top: 32px;
}

@media screen and (max-width: 782px) {
	.admin-bar .kd-mobile-panel {
		top: 46px;
	}
}

.kd-mobile-close {
	position: absolute;
	top: 1.75rem;
	right: 1.25rem;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 44px;
	height: 44px;
	background: rgba(255, 255, 255, 0.12);
	border: none;
	border-radius: 50%;
	color: var(--kd-mobile-panel-fg);
	cursor: pointer;
	padding: 0;
	line-height: 0;
	z-index: 2;
	transition: background-color var(--kd-transition-fast);
}

.kd-mobile-close:hover,
.kd-mobile-close:focus-visible {
	background: rgba(255, 255, 255, 0.22);
}

/* The panel's ✕ is the close control while open — hide the hamburger so the two
   don't collide at the top-right corner (the burger sits in the header and was
   painting over / next to the panel's close button). */
body.kd-nav-open .kd-hamburger {
	opacity: 0;
	pointer-events: none;
}

.kd-mobile-panel__inner {
	margin-top: 4rem;
}

.kd-menu--mobile {
	flex-direction: column;
	align-items: stretch;
	gap: 0;
	width: 100%;
	font-size: 1.1rem;
}

.kd-menu--mobile li {
	width: 100%;
	border-bottom: 1px solid rgba(255, 255, 255, 0.18);
}

.kd-menu--mobile a {
	color: var(--kd-mobile-panel-fg);
	display: block;
	padding: 0.85rem 0;
	width: 100%;
}

/* Parent row is the whole tap target (expands; does not navigate on mobile) */
.kd-menu--mobile .menu-item-has-children > a {
	position: relative;
	padding-right: 1.75rem;
	cursor: pointer;
}

.kd-menu--mobile .menu-item-has-children > a::after {
	content: "";
	position: absolute;
	right: 0.35rem;
	top: 50%;
	width: 0.55em;
	height: 0.55em;
	border-right: 2px solid currentColor;
	border-bottom: 2px solid currentColor;
	transform: translateY(-70%) rotate(45deg);
	transition: transform var(--kd-transition-fast);
}

.kd-menu--mobile .menu-item-has-children.is-expanded > a::after {
	transform: translateY(-30%) rotate(-135deg);
}

.kd-menu--mobile .sub-menu {
	list-style: none;
	margin: 0;
	padding: 0 0 0.5rem 1rem;
	display: none;
}

.kd-menu--mobile .menu-item-has-children.is-expanded > .sub-menu {
	display: block;
}

.kd-menu--mobile .sub-menu li {
	border-bottom: none;
}

.kd-menu--mobile .sub-menu a {
	padding: 0.5rem 0;
	font-size: 1rem;
	opacity: 0.92;
}

.kd-menu--mobile-secondary {
	margin-top: 1rem;
	font-size: 1rem;
	opacity: 0.85;
}

.kd-mobile-cta {
	margin-top: 1.75rem;
}

.kd-btn-invert-solid {
	display: inline-block;
	background: var(--kd-color-base);
	color: var(--kd-color-primary);
	border-radius: var(--kd-radius-pill);
	padding: 0.7em 2em;
	font-family: var(--kd-font-heading);
	font-weight: 900;
	font-size: var(--kd-size-btn);
	text-transform: uppercase;
	letter-spacing: 0.2px;
	text-decoration: none;
}

/* Lock body scroll while the panel is open */
body.kd-nav-open {
	overflow: hidden;
}

/* Admin-only "assign a menu" hint when a location is empty */
.kd-nav-empty a {
	color: var(--kd-color-base);
	font-size: 0.85rem;
	opacity: 0.8;
	text-decoration: underline;
}

/* ── Nav responsive switch ──────────────────────────────────────────────────── */

@media (max-width: 768px) {
	/* hide desktop primary nav + indigo strip; show hamburger */
	.kd-menu-wrap--primary,
	.kd-topbar {
		display: none;
	}
	.kd-hamburger {
		display: flex;
	}
}

/* ══════════════════════════════════════════════════════════════════════════════
   SITE FOOTER — purple band (Figma Footer component 177:3795)
   ══════════════════════════════════════════════════════════════════════════════ */

.kd-site-footer {
	background-color: var(--kd-color-contrast);
	color: var(--kd-color-base);
	padding-left: var(--kd-edge-pad) !important;
	padding-right: var(--kd-edge-pad) !important;
}

.kd-site-footer a {
	color: var(--kd-color-base);
}

.kd-site-footer a:hover {
	color: var(--kd-color-base);
	opacity: 0.8;
}

.kd-site-footer .kd-footer-heading {
	color: var(--kd-color-base);
	margin-top: 0;
}

.kd-footer-columns {
	align-items: flex-start;
}

.kd-footer-col p {
	color: var(--kd-color-base);
	max-width: var(--kd-footer-measure);
}

.kd-footer-logo img,
.kd-footer-logo .custom-logo {
	width: 84px;
	height: auto;
}

.kd-footer-tagline {
	font-size: 1rem;
}

/* Footer link menu — right-aligned column (classic menu) */
.kd-menu-wrap--footer {
	justify-content: flex-end;
}

.kd-menu--footer {
	flex-direction: column;
	align-items: flex-end;
	gap: 0.35rem;
	font-family: var(--kd-font-body);
	font-weight: 400;
	font-size: 1rem;
}

.kd-menu--footer a {
	color: var(--kd-color-base);
	text-decoration: none;
}

.kd-menu--footer a:hover {
	text-decoration: underline;
	opacity: 0.9;
}

/* Social icon menu — pink circles per spec (#E770A8), indigo on hover */
.kd-social-wrap {
	margin-top: var(--kd-space-md);
	display: flex;
	justify-content: flex-end;
}

.kd-social-menu {
	display: flex;
	gap: 0.5rem;
	margin: 0;
	padding: 0;
	list-style: none;
}

.kd-social-menu .kd-social-item a {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 44px;
	height: 44px;
	border-radius: 50%;
	background: var(--kd-color-accent);
	color: var(--kd-color-base);
	transition: background-color var(--kd-transition-fast);
}

.kd-social-menu .kd-social-item a svg {
	width: 24px;
	height: 24px;
	fill: currentColor;
}

.kd-social-menu .kd-social-item a:hover {
	background: var(--kd-color-secondary);
}

/* Pink divider — extra classes out-specify core's .has-background.is-style-wide
   rule (which otherwise forces the separator height). */
.kd-site-footer .kd-footer-divider.wp-block-separator.has-background {
	border: none;
	height: 3px;
	background-color: var(--kd-color-accent);
	opacity: 1;
	max-width: none;
	width: 100%;
}

.kd-footer-copyright {
	color: var(--kd-color-base);
	opacity: 0.85;
	margin: 0;
}

/* ── Focus Indicators (Accessibility) ───────────────────────────────────────── */

*:focus-visible {
	outline: 3px solid var(--kd-color-primary);
	outline-offset: 2px;
}

/* Buttons — rounded focus ring */
.wp-block-button__link:focus-visible {
	outline: 3px solid var(--kd-color-primary);
	outline-offset: 3px;
	border-radius: var(--kd-radius-pill);
}

/* On the dark bands, focus ring switches to white for contrast. The main bar is
   white, so it is deliberately NOT in this list (white ring on white). */
.kd-announcement-bar :focus-visible,
.kd-topbar :focus-visible,
.kd-site-footer :focus-visible {
	outline-color: var(--kd-color-base);
}

/* Remove default outline on mouse click */
:focus:not(:focus-visible) {
	outline: none;
}

/* ── Section Spacing ───────────────────────────────────────────────────────── */

/* Owl selector: one --kd-section-gap margin between every pair of stacked
   .entry-content children — groups AND the cover-based CTA band. Applied once,
   regardless of whether the adjacent section is plain or banded/colored.
   First child gets no margin-top (top of page is handled by hero / no-hero
   clearance tokens, which are left untouched). */
.entry-content > * + * {
	margin-block-start: var(--kd-section-gap);
}

/* Zero the trailing margin only. The owl above (--kd-section-gap, specificity
   0,1,0) already beats WP's zero-specificity :where(.is-layout-constrained) > * + *
   block-gap, so the inter-section gap is exactly --kd-section-gap. Do NOT switch
   this to `margin-block:0` — `.entry-content > .wp-block-group` is (0,2,0) and
   would override the owl's margin-block-start, collapsing every gap to zero. */
.entry-content > .wp-block-group {
	margin-block-end: 0;
}

/* Plain sections: no vertical padding — the margin-gap is the only space.
   Banded sections set their own padding-block in their pattern partials. */
.kd-section {
	padding-block: 0;
}

/* Interior-hero pages: <main> has blockGap:0 and the owl above skips the first
   child, so the first content section would butt directly against the hero.
   Give it one rhythm unit of separation below the hero.

   Applies under BOTH heroes, but keyed on what the first child actually is
   rather than on which hero precedes it. A full-bleed (.alignfull) band is
   meant to run flush to the hero — that was the original reason home was
   excluded wholesale. Any ordinary constrained section is not, and was landing
   with 0px against the hero because the section-rhythm owl selector
   (> * + *) skips the first child by design. */
main:has(.kd-hero-interior) .entry-content > :first-child,
main:has(.kd-hero-home) .entry-content > :first-child:not(.alignfull) {
	margin-block-start: var(--kd-section-gap);
}

.entry-content > .wp-block-group > *:first-child {
	margin-top: 0;
}

.entry-content > .wp-block-group > *:last-child {
	margin-bottom: 0;
}

/* Single post bodies are PROSE, not sections: the owl above is a page-section
   rhythm (120px), wrong between paragraphs. Scoped to .kd-single (the single
   templates' main element); specificity (0,2,0) beats the (0,1,0) owl. */
.kd-single .entry-content > * + * {
	margin-block-start: var(--kd-space-md);
}

/* Headings in a post body still breathe more than a paragraph does. */
.kd-single .entry-content > :is(h2, h3, h4) {
	margin-block-start: var(--kd-space-lg);
}

/* Fallback singles (e.g. partner: templates/single.html) have no body-h2
   rule of their own; without this their content h2s take the 50px section scale.
   (0,2,1) beats the theme.json h2 default; no !important. */
.kd-single__body .wp-block-post-content h2 {
	font-size: var(--kd-size-h2);
	line-height: 1.2;
}

/* Trailing space before the footer. The owl only spaces BETWEEN siblings, so a
   plain final section landed flush against the footer. :not(.alignfull) is
   load-bearing: full-bleed bands must keep butting the footer. Specificity
   (0,3,0) beats the (0,2,0) rule that zeroes margin-block-end on every
   .wp-block-group child; a last child has no following sibling, so it can never
   double up with the owl's margin-block-start. */
.entry-content > :last-child:not(.alignfull) {
	margin-block-end: var(--kd-section-gap);
}

/* ...but single bodies are prose: their wrapper already carries its own bottom
   padding, so the page-section gap would stack ~120px of dead space on it.
   Same specificity (0,3,0) as the rule above; order decides. */
.kd-single .entry-content > :last-child {
	margin-block-end: 0;
}

/* Section header → content gap. The container carries the reading measure so
   display titles can breathe; the tighter cap lives on the lead alone. */
.kd-section-header {
	margin-bottom: 65px !important;
	max-width: var(--kd-measure-reading);
	margin-left: auto;
	margin-right: auto;
}

.kd-section-header h2 {
	margin-bottom: var(--kd-gap-tight) !important;
}

.kd-section-header p {
	margin-top: 0 !important;
}

/* ── Kill WP default 24px margin between site-level blocks ───────────────── */

.wp-site-blocks > * {
	margin-block-start: 0;
}

/* ── Interior Page Hero ────────────────────────────────────────────────────── */

.kd-hero-interior {
	width: 100%;
	align-items: flex-start !important; /* top-anchor content vertically (cover cross-axis) */
	min-height: var(
		--kd-hero-interior-min
	) !important; /* beat the cover's inline min-height */
	/* Default background, in precedence order:
	     Featured Image  >  --kd-hero-banner  >  hero-gradient.svg
	   --kd-hero-banner is set per context by inc/hero-banner.php; with no mapping
	   it is never set and the var() falls through to the gradient. A Featured Image
	   still wins: the cover paints it as an <img> over this background. */
	background-color: var(--kd-color-contrast);
	background-image: var(--kd-hero-banner, url("../images/hero-gradient.svg"));
	background-position: center;
	background-size: cover;
	background-repeat: no-repeat;
	/* Match the header/footer band: edge-pad gutter; the inner caps at content-max. */
	padding-inline: var(--kd-edge-pad) !important;
	padding-top: var(
		--kd-hero-content-top
	) !important; /* breadcrumb 50px below the badge */
}

/* No Featured Image → show the brand gradient clean (kill the dark legibility wash). */
.kd-hero-interior:not(:has(img)) .wp-block-cover__background {
	background: transparent !important;
	opacity: 1 !important;
}

/* Featured Image set → keep the left-to-right wash so white text stays legible. */
.kd-hero-interior:has(img) .wp-block-cover__background {
	background: linear-gradient(
		to right,
		rgba(0, 0, 0, 0.6) 0%,
		rgba(0, 0, 0, 0.35) 50%,
		transparent 100%
	) !important;
	opacity: 1 !important;
}

/* Hero content aligns to the same gutter + max-width as the rest of the site. */
.kd-hero-interior .wp-block-cover__inner-container {
	max-width: var(--kd-content-max);
	margin: 0 auto;
	width: 100%;
}

.kd-hero-interior .wp-block-post-title {
	font-family: var(--kd-font-heading);
	font-weight: var(--kd-fw-heading);
	font-size: var(--kd-size-banner);
	color: var(--kd-color-base);
	line-height: var(--kd-lh-tight);
	margin-top: var(--kd-space-sm);
	margin-bottom: 0;
}

.kd-hero-subtitle {
	margin-top: 2rem;
	max-width: 36rem;
}

/* Sticky footer — the wrapper fills the viewport so the footer sits at the bottom
   on short pages. `main` grows to take the slack; the hero keeps its own height
   (it's min-height, not flex-stretched), so hero sections are unaffected. */
.wp-site-blocks {
	display: flex;
	flex-direction: column;
	min-height: 100vh;
}

.wp-site-blocks > main {
	flex: 1 0 auto;
}

/* Pages WITHOUT a hero (no-hero pages, CPT archives, posts) get top clearance so
   content doesn't collide with the badge that overflows the bar. Hero templates
   are auto-exempt — the badge is meant to spill onto the hero. */
.wp-site-blocks > main:not(:has(.kd-hero-interior)):not(:has(.kd-hero-home)) {
	padding-top: var(--kd-no-hero-top);
}

/* ── Breadcrumb ──────────────────────────────────────────────────────────── */

.kd-breadcrumb {
	/* Defaults to ink so the trail reads on no-hero pages; flipped to white
	   inside the interior hero (below). */
	--kd-breadcrumb-ink: var(--kd-color-contrast);
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: 0.5rem;
	font-size: 1.125rem;
	line-height: 1;
	color: var(--kd-breadcrumb-ink);
}

/* Crumb names never break mid-name; the trail wraps (whole crumbs) only if the
   links themselves don't fit. */
.kd-breadcrumb__home,
.kd-breadcrumb__sep,
.kd-breadcrumb__link {
	flex: none;
	white-space: nowrap;
}

.kd-breadcrumb__home {
	color: var(--kd-breadcrumb-ink);
	opacity: 0.7;
	display: flex;
	align-items: center;
	text-decoration: none;
	transition: opacity 0.2s ease;
}

.kd-breadcrumb__home:hover {
	opacity: 1;
	color: var(--kd-breadcrumb-ink);
}

.kd-breadcrumb__sep {
	opacity: 0.7;
	display: flex;
	align-items: center;
}

.kd-breadcrumb__link {
	color: var(--kd-breadcrumb-ink);
	opacity: 0.7;
	text-decoration: none;
	transition: opacity 0.2s ease;
}

.kd-breadcrumb__link:hover {
	opacity: 1;
	color: var(--kd-breadcrumb-ink);
}

.kd-breadcrumb__current {
	opacity: 0.9;
}

/* Phones: one row, the current crumb is a single line with an ellipsis (the full
   title is the H1 right below). */
@media (max-width: 767.98px) {
	.kd-breadcrumb {
		flex-wrap: nowrap;
	}

	.kd-breadcrumb__current {
		flex: 1 1 0;
		min-width: 3.5em; /* always visible; the middle links shrink to make room */
		overflow: hidden;
		text-overflow: ellipsis;
		white-space: nowrap;
		line-height: 1.3; /* the trail's line-height:1 clips descenders */
	}

	/* Middle links may shrink (ellipsis) so a deep trail stays on one row. */
	.kd-breadcrumb__link {
		flex: 0 1 auto;
		min-width: 2em;
		overflow: hidden;
		text-overflow: ellipsis;
	}
}

/* Inside the interior hero the trail sits on a dark band — flip to white. */
.kd-hero-interior .kd-breadcrumb {
	--kd-breadcrumb-ink: var(--kd-color-base);
}

/* ══════════════════════════════════════════════════════════════════════════════
   RESPONSIVE — Tablet (≤1024px)
   ══════════════════════════════════════════════════════════════════════════════ */

@media (max-width: 1024px) {
	/* Typography — scale down headings. Plain h2 is NOT listed: it is the fluid
	   section-title preset (theme.json), which scales itself; the 28px exceptions
	   (.kd-prose, tier/card/band headings) stay put by design. */
	h1,
	.has-huge-font-size {
		font-size: 2.5rem !important;
	}
	.has-xx-large-font-size {
		font-size: 1.6rem !important;
	}
	h3,
	.has-x-large-font-size {
		font-size: 1.35rem !important;
	}

	/* Header gutter override removed — the base .kd-topbar/.kd-mainbar rule
	   already pads with --kd-edge-pad. The hardcoded 24px that used to live
	   here diverged from the body's clamp gutter (7.64vw → 78px @1024, 59px
	   @768), so the logo and Donate button stopped lining up with the content
	   column through the whole 768–1024 band. One token, every band. */

	.kd-site-header .kd-site-logo img,
	.kd-site-header .kd-site-logo .custom-logo {
		width: 90px;
	}

	/* Footer — brand full width, other two columns side by side */
	.kd-footer-columns {
		flex-wrap: wrap !important;
		gap: var(--kd-space-lg) !important;
	}

	.kd-footer-columns > .kd-footer-col--brand {
		flex-basis: 100% !important;
	}

	.kd-footer-columns > .kd-footer-col--newsletter,
	.kd-footer-columns > .kd-footer-col--links {
		flex-basis: calc(50% - var(--kd-space-lg) / 2) !important;
	}

	/* (footer gutter override removed — the base .kd-site-footer rule already
	   pads with --kd-edge-pad, which tracks the body gutter at every width.
	   The fixed 24px here put the footer 54px outside the body column @1024.) */

	/* Hero — reduce min-height on tablet */
	.wp-block-cover {
		min-height: 50vh !important;
	}

	/* Buttons — slightly smaller on tablet */
	.wp-block-button__link,
	.kd-btn {
		padding: 0.7em 1.5em;
		font-size: 1rem;
	}
}

/* ══════════════════════════════════════════════════════════════════════════════
   RESPONSIVE — Mobile (≤768px)
   ══════════════════════════════════════════════════════════════════════════════ */

@media (max-width: 768px) {
	/* Typography — further scale-down */
	h1,
	.has-huge-font-size {
		font-size: 2.125rem !important;
	}
	.has-xx-large-font-size {
		font-size: 1.5rem !important;
	}
	h3,
	.has-x-large-font-size {
		font-size: 1.3rem !important;
	}

	/* Body text — slightly tighter line height */
	body {
		line-height: 1.6;
	}

	/* Hero — shorter on mobile */
	.wp-block-cover {
		min-height: 40vh !important;
	}

	/* (blanket `.wp-block-cover__inner-container` 24px padding removed — it stacked
	   on top of the interior hero's own --kd-edge-pad band padding, pushing the
	   H1 +24px off the body column, and under-padded the home hero + CTA band.
	   The gutter now lives at the BAND level: .kd-hero-interior pads with
	   --kd-edge-pad, .kd-hero-home pads its inner container with it, and the CTA
	   band pads itself in patterns/cta-band.css; every inner container stays at 0.) */

	/* Header — collapse top strip, keep main bar */
	.kd-mainbar {
		min-height: 72px;
	}

	.kd-site-header .kd-site-logo img,
	.kd-site-header .kd-site-logo .custom-logo {
		width: 80px;
	}

	/* Hide secondary strip links on small screens — they live in the overlay menu */
	.kd-topbar {
		display: none;
	}

	/* Footer — stack to a single column */
	.kd-footer-columns {
		flex-wrap: wrap !important;
		gap: var(--kd-space-lg) !important;
	}

	.kd-footer-columns > .kd-footer-col {
		flex-basis: 100% !important;
	}

	.kd-footer-col--links .kd-menu-wrap--footer,
	.kd-footer-col--links .kd-social-wrap {
		justify-content: flex-start !important;
	}

	.kd-footer-col--links .kd-menu--footer {
		align-items: flex-start !important;
	}

	/* (footer gutter override removed — see the ≤1024 note; base rule wins.) */

	/* Buttons — keep inline, slightly smaller */
	.wp-block-button__link,
	.kd-btn {
		padding: 0.65em 1.4em;
		font-size: 0.9375rem;
	}

	.kd-section-header {
		margin-bottom: 32px !important;
	}
}

/* ══════════════════════════════════════════════════════════════════════════════
   RESPONSIVE — Small phones (≤480px)
   ══════════════════════════════════════════════════════════════════════════════ */

@media (max-width: 480px) {
	h1,
	.has-huge-font-size {
		font-size: 1.85rem !important;
	}
	.has-xx-large-font-size {
		font-size: 1.4rem !important;
	}

	.kd-section-header {
		margin-bottom: var(--kd-space-sm) !important;
	}
}

/* ══════════════════════════════════════════════════════════════════════════════
   RESPONSIVE — Landscape orientation (short viewports)
   ══════════════════════════════════════════════════════════════════════════════ */

@media (max-height: 500px) and (orientation: landscape) {
	.wp-block-cover {
		min-height: 60vh !important;
	}
}

/* ── Link contrast on light surfaces ──────────────────────────────────────────
   Embolden Blue (#2383EB) on white measures 3.81:1 — it FAILS WCAG AA (4.5:1)
   for normal-size text. It passes AA Large (3:1), so it stays correct for
   buttons and large display text, but body-size links need a darker value.
   --kd-color-link is that value: Anchor Navy, 14.6:1 on white. Change this
   token, not the brand primary, if a client needs a different link colour. */
:root {
	--kd-color-link: var(--kd-color-contrast);
}

/* Specificity here is (0,3,1) — it beats any component's own `a { color }`
   (e.g. `.kd-link-band__label a` at (0,2,1)). Do NOT answer that with
   `!important`: a component that wants a different link colour re-points the
   token on its own root instead (`.kd-link-band { --kd-color-link: currentColor }`)
   and this rule then resolves to the component's value. */
.entry-content a:not(.wp-element-button):not([class*="kd-btn"]),
.kd-site-footer .kd-menu-wrap a,
.kd-card a {
	color: var(--kd-color-link);
}

/* ── Skip link (WCAG 2.4.1 Bypass Blocks) ─────────────────────────────────────
   With a two-tier nav plus a hero sub-nav, a keyboard user otherwise tabs
   through 15+ links before reaching content on EVERY page. Visually hidden
   until focused, then pinned top-left above everything. Relies on
   .screen-reader-text, which is defined below rather than borrowed from core's
   block-library stylesheet — the theme used that class in four places without
   ever defining it. */
.screen-reader-text {
	position: absolute;
	width: 1px;
	height: 1px;
	padding: 0;
	margin: -1px;
	overflow: hidden;
	clip-path: inset(50%);
	white-space: nowrap;
	border: 0;
}

.kd-skip-link:focus {
	position: fixed;
	top: 0.5rem;
	left: 0.5rem;
	z-index: calc(var(--kd-z-header) + 10);
	width: auto;
	height: auto;
	margin: 0;
	padding: 0.75rem 1.25rem;
	clip-path: none;
	overflow: visible;
	background: var(--kd-color-base);
	color: var(--kd-color-contrast);
	border-radius: var(--kd-radius-sm);
	box-shadow: 0 4px 14px rgb(0 0 0 / 25%);
	font-weight: 700;
	text-decoration: none;
}

/* Keep a phrase on one line without hard-coding a break. `&nbsp;` binds at every
   width and can push a mobile column into horizontal scroll; this releases
   below 600px, where a two-line phrase is correct anyway. */
.kd-nowrap {
	white-space: nowrap;
}

@media (max-width: 600px) {
	.kd-nowrap {
		white-space: normal;
	}
}

/* ── Spread columns ───────────────────────────────────────────────────────────
   WordPress columns distribute leftover width AFTER the last column rather than
   into the gap, so explicit column widths alone leave the last column sitting
   close to its neighbour instead of at the design's gutter. `space-between`
   moves that leftover into the gap. Add `kd-columns--spread` to a core/columns
   block whose columns carry explicit widths (e.g. a heading + form contact row). */
.kd-columns--spread {
	justify-content: space-between;
}

@media (max-width: 781px) {
	/* WP already stacks columns here; drop the override so the stacked blocks sit
	   flush rather than being pushed apart vertically. */
	.kd-columns--spread {
		justify-content: normal;
	}
}
