/* =========================================================
   TREWO — Design tokens
   ========================================================= */
:root {
	/* Exact brand colors from the TREWO logo. */
	--color-primary: #b5121b;
	--color-primary-dark: #880e14;
	--color-primary-tint: #f8e7e8;
	--color-accent: #a91e64;
	--color-ink: #1f1b1b;
	--color-body: #545454;
	--color-grey: #808083;
	--color-grey-light: #ededed;
	--color-white: #ffffff;
	--color-cream: #fbf8f5;
	--color-sand: #f4eee3;

	/* Finalised type: Zodiak (titles), General Sans (body), Clash Grotesk (labels) */
	--font-display: "Zodiak", Georgia, serif;
	--font-body: "General Sans", Helvetica, Arial, sans-serif;
	--font-label: "Clash Grotesk", Helvetica, Arial, sans-serif;

	--container-width: clamp(1280px, 88vw, 1600px);
	--gutter: 24px;
	--radius: 12px;
	--radius-sm: 8px;

	--section-space: 112px;
	--section-space-mobile: 64px;

	--header-height: 100px;
}

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

html {
	scroll-behavior: smooth;
}

body {
	margin: 0;
	font-family: var(--font-body);
	color: var(--color-body);
	background: var(--color-white);
	-webkit-font-smoothing: antialiased;
	-moz-osx-font-smoothing: grayscale;
	text-rendering: optimizeLegibility;
	overflow-x: hidden;
}

img,
svg {
	display: block;
	max-width: 100%;
}

a {
	color: inherit;
	text-decoration: none;
}

ul {
	list-style: none;
	margin: 0;
	padding: 0;
}

h1,
h2,
h3,
h4,
p {
	margin: 0;
}

button {
	font: inherit;
	cursor: pointer;
}

.skip-link {
	position: absolute;
	left: -9999px;
	top: 0;
	background: var(--color-primary);
	color: var(--color-white);
	padding: 12px 20px;
	z-index: 999;
}

.skip-link:focus {
	left: 12px;
	top: 12px;
}

section[id] {
	scroll-margin-top: var(--header-height);
}

/* =========================================================
   Layout utilities
   ========================================================= */

/* Spacing and alignment helpers. These exist for one specific reason: the page
   templates were carrying dozens of style="margin-top: 32px" attributes for
   spacing that is genuinely one-off — a photo grid under a heading, a prose
   block set centred — and which does not earn a named component class each.
   The scale is only the values the pages actually use; add to it rather than
   reaching for a style attribute. */
.u-mt-4 { margin-top: 4px; }
.u-mt-8 { margin-top: 8px; }
.u-mt-18 { margin-top: 18px; }
.u-mt-24 { margin-top: 24px; }
.u-mt-28 { margin-top: 28px; }
.u-mt-32 { margin-top: 32px; }
.u-mt-40 { margin-top: 40px; }
.u-mt-48 { margin-top: 48px; }
.u-mt-56 { margin-top: 56px; }

.u-text-center { text-align: center; }

/* Portrait-heavy flyers and photographs crop from the top rather than the
   centre, so faces and headlines survive the frame. */
.u-object-top { object-position: top center; }

.container {
	width: 100%;
	max-width: var(--container-width);
	margin-inline: auto;
	padding-inline: var(--gutter);
}

.section {
	padding-block: var(--section-space);
}

.section--alt {
	background: var(--color-cream);
}

.section--dark {
	background: var(--color-ink);
	color: rgba(255, 255, 255, 0.85);
}

.section--dark .section__title {
	color: var(--color-white);
}

/* Brand red ground. Kept as its own modifier rather than folded into
   .section--dark: the inversions below are the same idea, but the accents that
   read on ink (maroon buttons, maroon links) have to become white here, since
   they would vanish into the background. */
.section--red {
	background: var(--color-primary);
	color: rgba(255, 255, 255, 0.92);
}

.section--red .section__title,
.section--red .eyebrow {
	color: var(--color-white);
}

.section__header {
	display: flex;
	align-items: flex-end;
	justify-content: space-between;
	gap: 24px;
	margin-bottom: 48px;
}

.section__title {
	font-family: var(--font-display);
	font-weight: 300;
	text-transform: capitalize;
	letter-spacing: -0.01em;
	font-size: clamp(34px, 4.6vw, 56px);
	line-height: 1.02;
	margin-top: 14px;
	max-width: 100%;
}

.section__title--center {
	max-width: none;
	text-align: center;
	margin-inline: auto;
}

/* Lets the source text's own casing show through (e.g. "the"/"of"/"to"
   kept lowercase in a title) instead of the default per-word capitalize. */
.section__title--as-written {
	text-transform: none;
}

/* Same lighter, centered "statement" treatment as .mission-band__statement,
   for use on light (not dark) sections. */
.section__title--statement {
	font-family: var(--font-display);
	font-weight: 300;
	text-transform: none;
	font-size: clamp(24px, 3.2vw, 40px);
	line-height: 1.3;
	text-align: center;
	max-width: 900px;
	margin-inline: auto;
	color: var(--color-ink);
}

/* A section title pressed into service as a heading inside a media row:
   smaller, left aligned and flush, since the row itself supplies the spacing
   and the column already sets the measure. */
.section__title--inline {
	font-size: clamp(24px, 2.8vw, 32px);
	text-align: left;
	margin: 0;
}

/* When the source heading is a full sentence rather than a short title,
   drop it out of the large display-title treatment into readable prose
   size instead. */
.section__title--sentence {
	text-transform: none;
	max-width: 760px;
	font-size: clamp(22px, 2.6vw, 28px);
	line-height: 1.4;
	font-weight: 300;
}

/* Caps treatment for a sentence-length heading (client request). Uppercase
   needs three compensations at this size or it reads as shouting rather than
   as a title: caps have no descenders so the leading tightens, they measure
   larger than lowercase at the same point size so it steps down, and light
   display weights go spindly in caps so it steps up to 400 with a little
   tracking to keep the letterforms apart. Applied via a class so the heading
   text itself stays verbatim. */
.section__title--caps {
	text-transform: uppercase;
	font-size: clamp(19px, 2.15vw, 24px);
	line-height: 1.32;
	font-weight: 400;
	letter-spacing: 0.03em;
}

/* Client: match .roofs-kitchen-letter__signatures p exactly — that rule
   itself sets only weight/color and inherits the rest from .page-prose p and
   body, so this copies all of it explicitly rather than relying on the same
   inheritance chain (this heading sits outside .page-prose). Overrides the
   caps/display treatment above: back to the body sans, sentence case, and
   prose size instead of an uppercase display heading. */
.roofs-solar-title {
	font-family: var(--font-body);
	text-transform: uppercase;
	font-size: 16px;
	line-height: 1.6;
	font-weight: 600;
	letter-spacing: normal;
	color: var(--color-ink);
}

.eyebrow {
	display: inline-block;
	font-family: var(--font-label);
	font-size: 15px;
	font-weight: 600;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: var(--color-primary);
}

.eyebrow + .btn {
	margin-top: 20px;
}

.section--dark .eyebrow {
	color: rgb(255 255 255);
}

.eyebrow--light {
	color: var(--color-white);
}

.eyebrow--center {
	display: block;
	text-align: center;
}

/* =========================================================
   Buttons & links
   ========================================================= */
.btn {
	position: relative;
	overflow: hidden;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 8px;
	font-family: var(--font-body);
	font-weight: 600;
	font-size: 13px;
	text-transform: uppercase;
	letter-spacing: 0.05em;
	padding: 14px 30px;
	border-radius: 999px;
	border: 1px solid transparent;
	transition: background-color 0.2s ease, color 0.2s ease, border-color 0.2s ease, transform 0.2s ease;
	white-space: nowrap;
}

.btn:hover {
	transform: translateY(-1px);
}

.btn__ripple {
	position: absolute;
	border-radius: 50%;
	background: currentColor;
	opacity: 0.32;
	transform: scale(0);
	animation: btn-ripple 0.6s ease-out;
	pointer-events: none;
}

@keyframes btn-ripple {
	to {
		transform: scale(1);
		opacity: 0;
	}
}

@media (prefers-reduced-motion: reduce) {
	.btn__ripple {
		display: none;
	}
}

.btn--lg {
	padding: 16px 32px;
	font-size: 14px;
}

.btn--primary {
	background: var(--color-primary);
	color: var(--color-white);
}

.btn--primary:hover {
	background: var(--color-primary-dark);
}

.btn--ghost {
	background: transparent;
	color: var(--color-white);
	border-color: rgba(255, 255, 255, 0.6);
}

.btn--ghost:hover {
	background: rgba(255, 255, 255, 0.12);
	border-color: var(--color-white);
}

.btn--white {
	background: var(--color-white);
	color: var(--color-primary);
}

.btn--white:hover {
	background: var(--color-primary-tint);
}

.link-arrow {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	font-weight: 600;
	font-size: 13px;
	text-transform: uppercase;
	letter-spacing: 0.04em;
	color: var(--color-primary);
	white-space: nowrap;
}

.link-arrow::after {
	content: "\2192";
	transition: transform 0.2s ease;
}

.link-arrow:hover::after {
	transform: translateX(4px);
}

/* Circular "MORE" — sits centred at the bottom of a section. */
.section-more {
	display: flex;
	justify-content: center;
	margin-top: 52px;
}

.more-link {
	position: relative;
	z-index: 0;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 88px;
	height: 88px;
	border-radius: 50%;
	border: 1px solid var(--color-primary);
	color: var(--color-primary);
	font-family: var(--font-body);
	font-weight: 600;
	font-size: 13px;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	transition: background-color 0.25s ease, color 0.25s ease;
}

.more-link:hover {
	background: var(--color-primary);
	color: var(--color-white);
}

/* Hover ripple: two rings emanate outward from the button edge, staggered,
   sitting behind it (hidden under the fill, visible as they spread past). */
.more-link::before,
.more-link::after {
	content: "";
	position: absolute;
	inset: 0;
	z-index: -1;
	border-radius: 50%;
	border: 1.5px solid var(--color-primary);
	opacity: 0;
	pointer-events: none;
}

.more-link:hover::before,
.more-link:hover::after {
	animation: more-ripple 1.9s cubic-bezier(0.22, 0.61, 0.36, 1) infinite;
}

.more-link:hover::after {
	animation-delay: 0.95s;
}

@keyframes more-ripple {
	0% {
		transform: scale(1);
		opacity: 0.55;
	}
	80% {
		opacity: 0;
	}
	100% {
		transform: scale(1.85);
		opacity: 0;
	}
}

/* On dark/maroon sections, invert the outline + ripple colour. */
.section--dark .more-link,
.donate-cta .more-link {
	border-color: rgba(255, 255, 255, 0.6);
	color: var(--color-white);
}

.section--dark .more-link::before,
.section--dark .more-link::after,
.donate-cta .more-link::before,
.donate-cta .more-link::after {
	border-color: rgba(255, 255, 255, 0.8);
}

.section--dark .more-link:hover,
.donate-cta .more-link:hover {
	background: var(--color-white);
	color: var(--color-primary);
	border-color: var(--color-white);
}

@media (prefers-reduced-motion: reduce) {
	.more-link:hover::before,
	.more-link:hover::after {
		animation: none;
	}
}

/* =========================================================
   Placeholder media
   ========================================================= */
.ph-media {
	--ph-ratio: 16/9;
	aspect-ratio: var(--ph-ratio);
	width: 100%;
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: 10px;
	background: linear-gradient(135deg, var(--color-primary-tint), var(--color-grey-light));
	border-radius: var(--radius);
	color: var(--color-primary);
	overflow: hidden;
}

.ph-media__label {
	font-size: 12px;
	font-weight: 600;
	letter-spacing: 0.04em;
	text-align: center;
	padding-inline: 16px;
	color: var(--color-grey);
}

.ph-media--photo {
	background: var(--color-grey-light);
}

.ph-media--photo img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
}

/* Scoped to the Imagination Ball feature photo only — was previously on
   the shared .ph-media--photo img rule, which also affected every other
   photo on the site (e.g. the Our Outreach cards). */
.imagination-feature__media .ph-media--photo img {
	object-position: 60%;
}

/* =========================================================
   Ripple accent — decorative brand motif, reused across sections
   (see trewo_ripple() in inc/template-tags.php)
   ========================================================= */
.ripple-accent {
	position: absolute;
	pointer-events: none;
	z-index: -1;
	will-change: transform;
	/* Peak crest opacity, read by the GSAP ripple loop. Was 0.22, which the
	   client saw as barely-there rings. */
	--ripple-opacity: 0.38;
}

/* Client feedback: the ripples should be larger — then pulled back, since 1.35x
   overpowered the tighter sections. Settled at ~1.18x of the original
   200 / 340 / 480. The corner offsets below are percentages of the accent's own
   box, so they grow with it and the crest still bleeds off the section edge
   rather than sitting in from it. */
.ripple-accent--sm {
	width: 235px;
	height: 235px;
}

.ripple-accent--md {
	width: 400px;
	height: 400px;
}

.ripple-accent--lg {
	width: 565px;
	height: 565px;
}

.ripple-accent--top-left {
	top: -15%;
	left: -12%;
}

.ripple-accent--top-right {
	top: -15%;
	right: -12%;
}

.ripple-accent--bottom-left {
	bottom: -15%;
	left: -12%;
}

.ripple-accent--bottom-right {
	bottom: -15%;
	right: -12%;
}

.ripple-accent--primary {
	color: var(--color-primary);
}

.ripple-accent--light {
	color: var(--color-white);
	--ripple-opacity: 0.5;
}

.ripple-accent__svg {
	width: 100%;
	height: 100%;
	overflow: visible;
}

/* WebGL water surface (main.js). It tints itself from `color`, which the
   --primary / --light modifiers already set for the SVG's currentColor
   strokes, so both treatments stay on the same brand colour. */
.ripple-accent canvas {
	position: absolute;
	inset: 0;
	display: block;
	width: 100%;
	height: 100%;
	pointer-events: none;
	/* On a pale section the water has to DARKEN to be seen — its highlight is
	   white, which is invisible against cream. Multiply turns the crests into
	   shading, which is how ripples actually read on a light surface, and
	   leaves the white specular neutral. */
	mix-blend-mode: multiply;
}

/* On dark sections the opposite is true: the water is light on dark, so it
   should add light rather than subtract it. */
.ripple-accent--light canvas {
	mix-blend-mode: screen;
}

/* Once the water surface is live the line rings would double up. */
.ripple-accent.is-webgl .ripple-accent__svg {
	display: none;
}

/* The wave motion itself is driven by GSAP (see "Water ripples" in main.js)
   so the rings can decelerate, thin and decay the way a real wave front
   does — none of which a single CSS keyframe curve can express.

   What stays here is the resting state: calm concentric rings. That is what
   shows if the GSAP CDN fails, and what reduced-motion users keep. */
.ripple-accent__svg circle {
	transform-box: fill-box;
	transform-origin: center;
	opacity: var(--ripple-opacity);
}

/* =========================================================
   Header
   ========================================================= */
.site-header {
	position: sticky;
	top: 0;
	z-index: 100;
	background: var(--color-cream);
	border-bottom: 1px solid var(--color-grey-light);
	transition: transform 0.3s ease;
}

/* Sits below the WP admin toolbar (logged-in users) instead of being
   painted over by it — WP adds .admin-bar to <body> when it's showing. */
body.admin-bar .site-header {
	top: 32px;
}

@media screen and (max-width: 782px) {
	body.admin-bar .site-header {
		top: 46px;
	}
}

.site-header.header--hidden {
	transform: translateY(-100%);
}

.site-header__inner {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 24px;
}

.site-logo {
	display: inline-flex;
	align-items: center;
}

.site-logo__img {
	height: 100px;
	width: auto;
}

.site-logo--footer .site-logo__img {
	height: 80px;
}

.site-header__actions {
	display: flex;
	align-items: center;
	gap: 20px;
}

/* Hamburger + "Menu" trigger — used at all breakpoints; with 7 top-level
   items in a condensed uppercase font, a horizontal bar wraps ungracefully,
   so we always route through the full-screen overlay nav below instead. */
.nav-toggle {
	display: flex;
	align-items: center;
	justify-content: flex-end;
	gap: 10px;
	border: none;
	background: transparent;
	/* 44px minimum: the icon itself is only 26x18, which is a small target to
	   hit with a thumb. The negative margin keeps the extra padding from
	   shifting the button away from the header's right edge. */
	min-width: 44px;
	min-height: 44px;
	padding: 10px;
	margin-right: -10px;
}

.nav-toggle__label {
	font-family: var(--font-display);
	font-size: 14px;
	font-weight: 600;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: var(--color-ink);
}

.nav-toggle__icon {
	display: block;
	width: 26px;
	height: 18px;
	position: relative;
}

.nav-toggle__icon span,
.nav-toggle__icon span::before,
.nav-toggle__icon span::after {
	content: "";
	position: absolute;
	left: 0;
	right: 0;
	height: 2px;
	background: var(--color-primary);
	transition: transform 0.2s ease, opacity 0.2s ease;
}

.nav-toggle__icon span {
	top: 8px;
}

.nav-toggle__icon span::before {
	top: -8px;
}

.nav-toggle__icon span::after {
	top: 8px;
}

body.nav-is-open .nav-toggle__icon span {
	background: transparent;
}

body.nav-is-open .nav-toggle__icon span::before {
	top: 0;
	transform: rotate(45deg);
}

body.nav-is-open .nav-toggle__icon span::after {
	top: 0;
	transform: rotate(-45deg);
}

/* =========================================================
   Full-screen nav overlay
   ========================================================= */
/* Client note: "this drop down menu should be just a box - not cover the whole
   page". So .nav-overlay is now only the dim backdrop; the menu itself is a
   compact card anchored under the Menu button (.nav-overlay__panel). */
.nav-overlay {
	position: fixed;
	inset: 0;
	z-index: 200;
	background: rgba(26, 20, 22, 0.25);
	visibility: hidden;
	opacity: 0;
	transition: opacity 0.25s ease, visibility 0.25s ease;
}

body.nav-is-open .nav-overlay {
	visibility: visible;
	opacity: 1;
}

body.nav-is-open {
	overflow: hidden;
}

/* The box itself: anchored to the Menu button's corner, sized to its content
   rather than the viewport. It grows from the top-right so the motion reads
   as coming OUT of the button that opened it. */
.nav-overlay__panel {
	position: absolute;
	top: calc(var(--header-height) + 8px);
	right: max(20px, calc((100% - var(--container-width)) / 2 + var(--gutter)));
	z-index: 1;
	width: min(370px, calc(100vw - 32px));
	max-height: calc(100vh - var(--header-height) - 40px);
	overflow: hidden auto;
	padding: 12px;
	background: var(--color-cream);
	border: 1px solid rgba(31, 27, 27, 0.08);
	border-radius: 18px;
	box-shadow:
		0 28px 60px -16px rgba(26, 20, 22, 0.32),
		0 8px 20px -10px rgba(26, 20, 22, 0.2);
	isolation: isolate;
	transform-origin: top right;
	transform: translateY(-10px) scale(0.96);
	opacity: 0;
	transition:
		transform 0.32s cubic-bezier(0.22, 1, 0.36, 1),
		opacity 0.2s ease;
}

body.nav-is-open .nav-overlay__panel {
	transform: translateY(0) scale(1);
	opacity: 1;
}

body.admin-bar .nav-overlay__panel {
	top: calc(var(--header-height) + 40px);
}

/* Left-aligned rows inside the box — right-aligned giant type made sense
   across a full screen, but reads as broken in a 340px card. */
/* Client: menu text should be slightly larger. Nudged from 18px/13px-14px
   padding rather than a bigger jump — the panel is sized to its content
   (min(370px, 100vw - 32px)), and "Webinar Outreach Wing" is already close to
   that width at this weight, so a larger step would start wrapping the
   longest labels to two lines. */
.nav-overlay__list a {
	display: flex;
	align-items: center;
	justify-content: flex-start;
	text-align: left;
	gap: 12px;
	padding: 14px 16px;
	border-radius: 11px;
	font-family: var(--font-display);
	font-weight: 400;
	text-transform: uppercase;
	letter-spacing: 0.025em;
	font-size: 19px;
	line-height: 1.25;
	color: var(--color-ink);
	transition: background-color 0.2s ease, transform 0.2s ease, color 0.2s ease;
}

/* Marker: an actual ripple — thin concentric rings (the brand motif at
   small scale), gently growing on hover. */
.nav-overlay__list a::before {
	content: "";
	flex: none;
	width: 13px;
	height: 13px;
	background: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 40 40' fill='none'%3E%3Ccircle cx='20' cy='20' r='6' stroke='%23b5121b' stroke-width='1.4'/%3E%3Ccircle cx='20' cy='20' r='12' stroke='%23b5121b' stroke-width='1.4'/%3E%3Ccircle cx='20' cy='20' r='18' stroke='%23b5121b' stroke-width='1.4'/%3E%3C/svg%3E") no-repeat center / contain;
	transition: transform 0.3s ease;
}

.nav-overlay__list a:hover {
	background: rgba(181, 18, 27, 0.07);
	transform: translateX(3px);
	color: var(--color-primary);
}

.nav-overlay__list a:hover::before {
	transform: scale(1.15);
}

.nav-overlay__footer {
	margin-top: 32px;
	display: flex;
	align-items: center;
	justify-content: flex-end;
	gap: 24px;
}

.nav-overlay .social-links a {
	border-color: rgba(31, 27, 27, 0.2);
	color: var(--color-ink);
}

.nav-overlay .social-links a:hover {
	border-color: var(--color-primary);
	color: var(--color-white);
}

/* =========================================================
   Hero — full-screen featured-section slider
   (full-bleed photo behind a maroon gradient field; each slide
   features one section of the site: copy left, photo mosaic right)
   ========================================================= */
/* =========================================================
   Ripple banner — the homepage's opening full-screen section
   Client: a big animated ripple at the top centre with the organization
   name across it and the tagline under, on the artwork background; the
   welcome/imagination-ball/webinars/roofs slider then follows BELOW it.
   So this is a section in front of .hero, not a change to it.

   The ripple is .ripple-banner__water, registered next to .hero__rings in
   main.js and in the shared resting-state rules above — same water surface
   as every other ripple on the site, only bigger and centred.
   ========================================================= */
.ripple-banner {
	position: relative;
	display: flex;
	align-items: center;
	justify-content: center;
	width: 100%;
	min-height: calc(100vh - var(--header-height));
	min-height: calc(100dvh - var(--header-height));
	padding: 64px 0;
	overflow: hidden;
	isolation: isolate;
	color: var(--color-white);
	background: rgb(26, 20, 22);
}

.ripple-banner__bg {
	position: absolute;
	inset: 0;
	z-index: -2;
}

.ripple-banner__bg img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
}

/* Centred rather than left-weighted like .hero__bg::after: this section's
   copy sits in the middle of the frame, not in one column, so the shade has
   to be where the text is. An even wash plus a deeper pool in the centre —
   enough contrast for white type without flattening the artwork to grey at
   the edges. */
.ripple-banner__bg::after {
	content: "";
	position: absolute;
	inset: 0;
	background:
		radial-gradient(
			ellipse 70% 60% at 50% 50%,
			rgba(26, 20, 22, 0.68) 0%,
			rgba(26, 20, 22, 0.34) 60%,
			rgba(26, 20, 22, 0.12) 100%
		),
		linear-gradient(rgba(26, 20, 22, 0.3), rgba(26, 20, 22, 0.3));
}

.ripple-banner__inner {
	position: relative;
	display: flex;
	align-items: center;
	justify-content: center;
	width: 100%;
}

/* Square and centred, sized off the viewport's shorter side so the ripple
   stays a circle in the frame rather than an ellipse the copy sits inside. */
.ripple-banner__water {
	position: absolute;
	top: 50%;
	left: 50%;
	width: min(860px, 92vmin);
	height: min(860px, 92vmin);
	transform: translate(-50%, -50%);
	pointer-events: none;
	z-index: 0;
}

.ripple-banner__copy {
	position: relative;
	z-index: 1;
	text-align: center;
	max-width: 940px;
	margin-inline: auto;
}

.ripple-banner__title {
	font-family: var(--font-display);
	font-weight: 300;
	font-size: clamp(38px, 6vw, 82px);
	line-height: 1.04;
	letter-spacing: -0.01em;
	color: var(--color-white);
	text-wrap: balance;
}

/* The short rule under the headline in the client's reference banner. */
.ripple-banner__rule {
	display: block;
	width: 132px;
	height: 3px;
	margin: 30px auto 0;
	border-radius: 2px;
	background: var(--color-primary);
}

.ripple-banner__tagline {
	margin: 28px auto 0;
	max-width: 760px;
	font-size: clamp(17px, 1.9vw, 22px);
	line-height: 1.55;
	color: rgba(255, 255, 255, 0.92);
}

@media (max-width: 640px) {
	.ripple-banner {
		padding: 48px 0;
		min-height: calc(100svh - var(--header-height));
	}

	.ripple-banner__rule {
		width: 96px;
		margin-top: 22px;
	}
}

.hero {
	position: relative;
	display: flex;
	flex-direction: column;
	justify-content: center;
	width: 100%;
	/* Cap how tall the hero (and the mosaic photo, which fills its full
	   height) can get on very tall screens — past this it stopped looking
	   intentional and just left empty maroon space below the photo. */
	min-height: min(calc(100vh - var(--header-height)), 900px);
	min-height: min(calc(100dvh - var(--header-height)), 900px);
	color: var(--color-white);
	overflow: hidden;
	isolation: isolate;
	padding: 52px 0 56px;
}

/* Photo layer sits below the corner ripples (z -1), which in turn sit
   below the in-flow slide content — all inside the hero's own stacking
   context (isolation above). */
.hero__bg {
	position: absolute;
	inset: 0;
	z-index: -2;
}

.hero__bg img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
}

/* Left-weighted dark scrim so the colourful background art shows through on
   the right while the headline stays legible on the left. */
.hero__bg::after {
	content: "";
	position: absolute;
	inset: 0;
	background: linear-gradient(
		100deg,
		rgba(26, 20, 22, 0.78) 0%,
		rgba(26, 20, 22, 0.45) 45%,
		rgba(26, 20, 22, 0.12) 100%
	);
}

/* Fills the hero's content box so the tab nav below can be pinned to the
   bottom of the section rather than floating directly under the copy. */
.hero__inner {
	width: 100%;
	display: flex;
	flex-direction: column;
	flex: 1;
}

/* Slides stack in the same grid cell; the container keeps the height of
   the tallest slide so the layout never jumps between slides.

   flex: 1 makes it absorb whatever vertical slack the hero has, which is
   what pushes .hero__nav down to the bottom edge. The slide inside is
   still align-items: center, so the copy stays vertically centred in the
   taller area instead of riding the top. */
.hero__slides {
	display: grid;
	flex: 1;
	/* Keeps the slide row at its natural height and centres it in the
	   stretched track, so only the nav moves. Without this the row would
	   stretch and the stacked tablet layout (copy over mosaic) would pull
	   apart to fill the extra height. */
	align-content: center;
}

.hero__slide {
	grid-area: 1 / 1;
	display: grid;
	grid-template-columns: minmax(0, 1fr) minmax(0, 640px);
	gap: 56px;
	align-items: center;
	opacity: 0;
	visibility: hidden;
	transition: opacity 0.6s ease, visibility 0.6s ease;
	pointer-events: none;
}

.hero__slide.is-active {
	opacity: 1;
	visibility: visible;
	pointer-events: auto;
}

.hero__eyebrow {
	font-family: var(--font-label);
	font-weight: 700;
	font-size: 15px;
	letter-spacing: 0.14em;
	text-transform: uppercase;
	color: var(--color-white);
	margin-bottom: 18px;
}

.hero__title {
	font-family: var(--font-display);
	font-weight: 300;
	text-transform: capitalize;
	font-size: clamp(40px, 5.2vw, 70px);
	line-height: 1.06;
	letter-spacing: -0.005em;
	/* Inert unless a slide's title has a literal line break in it (see the
	   Webinars slide) — preserves that break without affecting titles that
	   don't have one. */
	white-space: pre-line;
}

/* Show the title exactly as written instead of auto-capitalizing every
   word — e.g. "Open to everyone" wants a lowercase "to". */
.hero__title--as-written {
	text-transform: none;
}

.hero__highlight {
	display: inline-flex;
	align-items: center;
	gap: 14px;
	margin-top: 22px;
	padding: 14px 0;
	border-top: 1px solid rgba(255, 255, 255, 0.22);
	border-bottom: 1px solid rgba(255, 255, 255, 0.22);
	color: var(--color-white);
	font-size: 21px;
	font-weight: 600;
	line-height: 1.3;
}

.hero__highlight svg {
	flex: none;
	color: var(--color-white);
}

.hero__text {
	font-size: 20px;
	line-height: 1.5;
	color: var(--color-white);
	max-width: 600px;
	margin-top: 22px;
}

.hero__pill {
	display: inline-flex;
	align-items: center;
	gap: 10px;
	border: 1px solid rgba(255, 255, 255, 0.45);
	border-radius: 999px;
	padding: 10px 20px;
	font-size: 13px;
	font-weight: 500;
	letter-spacing: 0.02em;
	margin-top: 22px;
}

.hero__pill svg {
	flex: none;
	opacity: 0.85;
}

.hero__actions {
	display: flex;
	gap: 16px;
	margin-top: 32px;
	flex-wrap: wrap;
}

/* Scaled with the rest of the hero copy block so the CTAs don't read as
   undersized next to the larger headline and body text. Scoped to the hero
   because .btn--lg is shared with other sections. */
.hero__actions .btn--lg {
	padding: 18px 36px;
	font-size: 16px;
}

/* Photo cluster — three photos of mixed shape arranged over concentric
   ripple rings (the brand motif), instead of IRC's straight columns. */
.hero__mosaic {
	/* Positioned relative to .hero itself (not .hero__inner) so it spans
	   the section's true top/bottom edges, ignoring .hero's own padding —
	   client feedback: the photo should touch the edges of the hero
	   section on desktop, not sit inside a padded, fixed-height box.

	   Horizontally it starts exactly where .hero__slide's own grid would
	   have put its second (640px) column — same maths as the container
	   bleed on --container-width, plus the fixed column width — and
	   extends to .hero's true right edge. Anchoring the left edge there
	   (instead of spanning the full section width) is what stops it from
	   ever reaching under the copy text, and avoids the dead gap between
	   the copy column and the photo that a flat width cap left behind.

	   container-type lets the ring below size itself in cqh units off
	   this box's height. Tablet/mobile breakpoints put it back in flow as
	   a small centred box.

	   It's purely decorative (aria-hidden in the markup) and must never
	   sit in front of the copy or nav tabs: pointer-events:none plus a
	   negative z-index (matching the ripple accents' layer) guarantee it
	   never blocks clicks, since becoming position:absolute otherwise
	   makes it paint above the static in-flow copy/nav regardless of
	   DOM order. */
	position: absolute;
	top: 0;
	bottom: 0;
	right: 0;
	left: calc(( 100vw + min(100vw, var(--container-width)) ) / 2 - var(--gutter) - 640px);
	z-index: -1;
	pointer-events: none;
	container-type: size;
}

.hero__rings {
	position: absolute;
	top: 50%;
	/* Centred on the photo card, which now fills .hero__mosaic exactly —
	   see .hero__mosaic-card--1. Sized in cqh (relative to the mosaic's
	   height) so the ring scales with the section's height the same way
	   the card does. */
	right: -12.5cqh;
	transform: translateY(-50%);
	width: 125cqh;
	height: 125cqh;
	pointer-events: none;
}

/* Same water-drop ripple behind the hero photos, driven by GSAP (see
   main.js). The rings share one full-size box and travel outward from the
   centre; the rules here are only the calm resting state, used when GSAP is
   unavailable and for reduced motion. */
/* Colour and strength of the WebGL water surface (main.js). Warm white rather
   than the reference reel's cyan — this sits on the maroon hero, and neon blue
   would fight the brand. `color` is the tint; --ripple-strength its opacity. */
.hero__rings,
.ripple-banner__water {
	color: #ffece4;
	--ripple-strength: 0.85;
}

.hero__rings canvas,
.ripple-banner__water canvas {
	position: absolute;
	inset: 0;
	display: block;
	width: 100%;
	height: 100%;
	pointer-events: none;
	/* Light water on the dark maroon hero — add light, don't subtract it. */
	mix-blend-mode: screen;
}

/* Once the WebGL surface is live the line rings are redundant. */
.hero__rings.is-webgl span,
.ripple-banner__water.is-webgl span {
	display: none;
}

.hero__rings span,
.ripple-banner__water span {
	position: absolute;
	inset: 0;
	border: 1.5px solid rgba(255, 255, 255, 0.55);
	border-radius: 50%;
	transform-origin: center;
	opacity: 0.5;
}

.hero__rings span:nth-child(1),
.ripple-banner__water span:nth-child(1) {
	transform: scale(1);
}

.hero__rings span:nth-child(2),
.ripple-banner__water span:nth-child(2) {
	transform: scale(0.79);
}

.hero__rings span:nth-child(3),
.ripple-banner__water span:nth-child(3) {
	transform: scale(0.58);
}

.hero__rings span:nth-child(4),
.ripple-banner__water span:nth-child(4) {
	transform: scale(0.38);
}

.hero__rings span:nth-child(5),
.ripple-banner__water span:nth-child(5) {
	transform: scale(0.2);
}

/* One big square photo, centred over the animated ripple rings. */
.hero__mosaic-card {
	position: absolute;
	overflow: hidden;
	aspect-ratio: 1;
	box-shadow: 0 16px 34px rgba(0, 0, 0, 0.3);
}

.hero__mosaic-card img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	/* Per-slide crop point, supplied by the template as --mosaic-pos when a
	   slide needs one (see template-parts/hero.php); centred otherwise. */
	object-position: var(--mosaic-pos, center);
	display: block;
}

.hero__mosaic-card--1 {
	/* Fill .hero__mosaic exactly — that box is already sized to start at
	   the grid column boundary and end at the section's right edge (see
	   .hero__mosaic above), so there's no need to re-derive a width or
	   cap it here; it can never reach under the copy text or leave a gap
	   before the photo starts. object-fit: cover on the img handles the
	   resulting (usually non-square) crop.

	   Overrides the shared .hero__mosaic-card's aspect-ratio: 1 — left in
	   place, that fought with inset: 0 and could leave the card short of
	   the section's true bottom edge instead of actually filling it. */
	inset: 0;
	aspect-ratio: auto;
}

/* Tabs + arrows below the slides */
.hero__nav {
	display: flex;
	align-items: center;
	gap: 28px;
	/* Sits at the bottom of the section (.hero__slides takes the slack
	   above it); this stays as the minimum breathing room for when the
	   slide copy is tall enough to push the hero past its min-height. */
	margin-top: 48px;
	flex: none;
	/* Cap it to the same width the grid always reserves for the copy
	   column (container width minus the 640px image column and its 56px
	   gap — see .hero__slide) so a long tab label wraps onto a second
	   line instead of running under the photo, which sits behind
	   everything on the right from here down. Reset on tablet/mobile,
	   below, where the mosaic goes back to a small stacked box. */
	max-width: calc(100% - 640px - 56px);
}

.hero__tabs {
	display: flex;
	flex-wrap: wrap;
	gap: 6px 26px;
}

.hero__tab {
	appearance: none;
	background: transparent;
	border: none;
	border-bottom: 2px solid transparent;
	cursor: pointer;
	font-family: var(--font-display);
	font-weight: 600;
	font-size: 13px;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: var(--color-white);
	padding: 6px 0;
	transition: color 0.2s ease, border-color 0.2s ease;
}

.hero__tab:hover {
	color: var(--color-white);
}

.hero__tab.is-active {
	color: var(--color-white);
	border-color: var(--color-white);
}

.hero__arrows {
	display: flex;
	gap: 10px;
	margin-left: auto;
}

/* The hero stacks well before the shared 1023px breakpoint. Its desktop
   layout reserves a fixed 640px photo column plus a 56px gap, so between
   1024px and ~1180px the copy column is squeezed to about 280px and the
   headline breaks into a narrow ribbon beside the photo. Stacking from
   1180px keeps a readable measure at every width. */
@media (max-width: 1180px) {
	/* Client: no top padding once the slide stacks — the photograph leads and
	   runs flush to the header on tablet as well as phone. */
	.hero {
		padding: 0 0 48px;
	}

	/* Content starts at the top of the section rather than being centred in
	   it, which is what lets the photo actually meet the header edge; the
	   slack collects below, above the tabs. */
	.hero__slides {
		align-content: start;
	}

	/* align-content:start matters as much as the column count here: all four
	   slides share one grid cell and stretch to the tallest of them, and
	   without this the leftover height was distributed into a shorter slide's
	   own rows — which pushed its photograph down from the top edge by ~48px
	   even with the section's padding at zero. */
	.hero__slide {
		grid-template-columns: 1fr;
		align-content: start;
		gap: 28px;
	}

	.hero__nav {
		max-width: none;
	}

	/* Below the desktop layout the mosaic goes back to being an in-flow,
	   centred box instead of a section-edge-to-edge overlay, so every
	   property the desktop rules above changed needs an explicit reset here —
	   position, sizing basis and the ring/card offsets all assumed the
	   section-spanning box otherwise.

	   Client, twice over: the photograph leads (order:-1 puts it above the
	   copy the moment the slide stacks, on tablet as well as phone), and every
	   slide shows in the same frame. The frame is this box — one fixed 4:3
	   ratio — rather than the old 500px-tall container holding a square card,
	   which framed each photograph differently depending on its own
	   proportions. */
	.hero__mosaic {
		order: -1;
		position: relative;
		inset: auto;
		container-type: normal;
		/* Full width at every stacked size, not just on phones (client): the
		   negative inline margin cancels .container's gutter so the band runs
		   edge to edge. The height cap is what keeps that honest — a 4:3 band
		   across a 1180px tablet would stand 885px tall and swallow the
		   screen, so past ~640px wide the frame simply crops wider instead of
		   growing taller. Every slide still shares one frame at any given
		   width. */
		width: calc(100% + var(--gutter) * 2);
		max-width: none;
		/* Height is set directly rather than by aspect-ratio + max-height:
		   with an auto width those two fight each other, and the box was
		   shrinking its width to satisfy the ratio instead of staying full
		   bleed. 75vw is 4:3 at phone widths; past 800px the cap takes over
		   and the frame crops wider rather than growing taller.

		   Cap raised from 480px to 600px for tablets (client). The mosaic
		   photographs are close to square — the first is 1348x1167, a ratio of
		   1.15 — so on a 768px iPad the image covers at 665px tall. At the old
		   480px cap that discarded 185px, ~28% of the frame, half of it off
		   the top where the subject's head is; at 600px only 65px goes, about
		   10%. Matching the image exactly would mean a 665px band, which is
		   most of an iPad's screen before a word of copy appears. */
		height: min(75vw, 600px);
		margin-inline: calc(var(--gutter) * -1);
		overflow: hidden;
	}

	/* Client: hidden on mobile and tablet. The photograph fills the frame at
	   these sizes so the rings sat behind it unseen anyway — and display:none
	   stops main.js from running a WebGL water surface nobody can see, which
	   is battery a phone should not be spending. */
	.hero__rings {
		display: none;
	}

	/* Fills the frame instead of sitting as a centred square inside it, so
	   the crop is identical from slide to slide (object-fit: cover on the
	   image does the rest). */
	.hero__mosaic-card--1 {
		inset: 0;
		width: auto;
		height: auto;
		aspect-ratio: auto;
		transform: none;
	}

	/* Whatever the frame still has to trim comes off the bottom rather than
	   being split evenly top and bottom: in all four photographs the people
	   are in the upper half. A slide can still override this with
	   --mosaic-pos, exactly as on desktop. */
	.hero__mosaic-card img {
		object-position: var(--mosaic-pos, center 35%);
	}
}

/* =========================================================
   Shared carousel controls (hero slider + programs carousel)
   ========================================================= */

.carousel-arrow {
	display: flex;
	align-items: center;
	justify-content: center;
	flex: none;
	width: 40px;
	height: 40px;
	border-radius: 50%;
	border: 1px solid rgba(255, 255, 255, 0.35);
	background: transparent;
	color: var(--color-white);
	transition: background-color 0.2s ease, border-color 0.2s ease;
}

.carousel-arrow:hover {
	background: rgba(255, 255, 255, 0.15);
	border-color: var(--color-white);
}

.carousel-arrow--dark {
	border-color: rgba(31, 27, 27, 0.2);
	color: var(--color-primary);
}

.carousel-arrow--dark:hover {
	background: var(--color-primary-tint);
	border-color: var(--color-primary);
}

.programs__dots {
	display: flex;
	align-items: center;
	justify-content: center;
	gap: 10px;
	margin-top: 32px;
}

.carousel-dot {
	width: 9px;
	height: 9px;
	border-radius: 50%;
	border: 1px solid rgba(255, 255, 255, 0.6);
	background: transparent;
	padding: 0;
	transition: background-color 0.2s ease, transform 0.2s ease;
}

.carousel-dot.is-active {
	background: var(--color-white);
	transform: scale(1.2);
}

.carousel-dot--dark {
	border-color: rgba(181, 18, 27, 0.4);
}

.carousel-dot--dark.is-active {
	background: var(--color-primary);
}

/* =========================================================
   Stats
   ========================================================= */
.stats {
	position: relative;
	overflow: hidden;
	isolation: isolate;
	/* Was a flat 200px. Fluid, so the band keeps its generous desktop
	   proportions but does not put 400px of empty ink around three numbers on
	   a phone. */
	padding-block: clamp(72px, 12vw, 200px);
}

.stats .section__title {
	font-size: clamp(38px, 5.2vw, 64px);
}

/* Black-and-white photo behind the impact numbers, dimmed with the same
   ink tone as the rest of the dark section so the stats stay legible. */
.stats__bg {
	position: absolute;
	inset: 0;
	z-index: -2;
}

.stats__bg img {
	/* Oversized + repositioned so the parallax drift in main.js (GSAP
	   ScrollTrigger, scrubbed to the scrollbar) has buffer room to move
	   the image within without ever exposing an edge — .stats itself
	   clips anything that spills past its bounds. */
	position: absolute;
	top: -15%;
	left: 0;
	width: 100%;
	height: 130%;
	object-fit: cover;
	object-position: top center;
	display: block;
	filter: grayscale(1);
}

.stats__bg::after {
	content: "";
	position: absolute;
	inset: 0;
	background: var(--color-ink);
	opacity: 0.8;
}

.stats__grid {
	margin-top: 56px;
	display: grid;
	grid-template-columns: repeat(3, 1fr);
}

.stat {
	text-align: center;
	padding: 0 20px;
	border-left: 2px solid var(--color-primary);
}

.stat:first-child {
	border-left: none;
}

.stat__number {
	display: block;
	font-family: var(--font-display);
	font-weight: 700;
	letter-spacing: -0.01em;
	font-size: clamp(40px, 5.2vw, 64px);
	color: var(--color-white);
}

.stat__label {
	display: block;
	margin-top: 10px;
	font-size: 15px;
	color: rgb(255 255 255);
	text-transform: uppercase;
	letter-spacing: 0.08em;
	font-weight: 600;
}

/* =========================================================
   Mission
   ========================================================= */
.mission {
	position: relative;
	overflow: hidden;
	isolation: isolate;
}

.mission__grid {
	display: grid;
	grid-template-columns: 0.85fr 1fr;
	gap: 64px;
	align-items: start;
}

.mission__text {
	margin-top: 20px;
	font-size: 18px;
	line-height: 1.4;
	color: #555556;
	max-width: 540px;
}

.mission__content > * + * {
	display: block;
}

.mission__body {
	margin-top: 22px;
	max-width: 600px;
}

.mission__body p {
	margin: 0 0 16px;
	font-size: 16px;
	line-height: 1.5;
	color: var(--color-body);
}

.mission__quote {
	margin: 24px 0 0;
	padding-left: 20px;
	border-left: 3px solid var(--color-primary);
	font-size: 18px;
	font-style: italic;
	line-height: 1.5;
	color: #555556;
}

.mission__quote cite {
	display: block;
	margin-top: 12px;
	font-family: var(--font-label);
	font-style: normal;
	font-weight: 700;
	font-size: 13px;
	letter-spacing: 0.02em;
	color: var(--color-ink);
}

/* =========================================================
   Imagination Ball — flagship-event feature (split photo/color panel)
   ========================================================= */
.imagination-feature {
	display: grid;
	grid-template-columns: 1.15fr 1fr;
	min-height: 620px;
}

.imagination-feature__media {
	position: relative;
	overflow: hidden;
}

.imagination-feature__media .ph-media {
	--ph-ratio: auto;
	height: 100%;
	border-radius: 0;
}

.imagination-feature__panel {
	position: relative;
	overflow: hidden;
	isolation: isolate;
	background: var(--color-primary);
	color: var(--color-white);
	padding: 64px max(56px, calc((100% - var(--container-width) * 0.42) / 2)) 64px 56px;
	display: flex;
	flex-direction: column;
	justify-content: center;
}

/* Badge is a client-supplied graphic (imagination-badge.png) instead of an
   HTML-built medal — just position/size it.

   Sits on the photo (bottom-left) rather than in the red panel: at the size
   the client asked for it collided with the panel headline, and the photo's
   lower-left is dark, empty stage floor, so the gold reads cleanly there.
   Anchored inside .imagination-feature__media so it follows the photo when
   the layout stacks, instead of drifting onto the panel. */
.imagination-feature__badge {
	position: absolute;
	left: 40px;
	bottom: 40px;
	z-index: 2;
	width: 175px;
	height: 175px;
	filter: drop-shadow(0 6px 18px rgba(0, 0, 0, 0.45));
}

.imagination-feature__badge img {
	width: 100%;
	height: 100%;
	object-fit: contain;
	display: block;
}

.imagination-feature__title {
	position: relative;
	font-family: var(--font-display);
	font-weight: 300;
	text-transform: capitalize;
	letter-spacing: -0.005em;
	font-size: clamp(30px, 3.4vw, 46px);
	line-height: 1.05;
	margin-top: 14px;
}

.imagination-feature__tagline {
	position: relative;
	margin-top: 16px;
	font-size: 18px;
	line-height: 1.45;
	color: var(--color-white);
}

.imagination-feature__details {
	position: relative;
	margin-top: 28px;
}

.imagination-feature__detail {
	display: flex;
	align-items: flex-start;
	gap: 14px;
	padding-block: 16px;
	border-bottom: 1px solid rgba(255, 255, 255, 0.22);
}

.imagination-feature__detail:first-child {
	padding-top: 0;
}

.imagination-feature__detail:last-child {
	border-bottom: none;
	padding-bottom: 0;
}

.imagination-feature__detail-icon {
	flex: none;
	display: flex;
	align-items: center;
	justify-content: center;
	width: 36px;
	height: 36px;
	border-radius: 50%;
	border: 1.5px solid rgba(255, 255, 255, 0.6);
	margin-top: 2px;
}

.imagination-feature__detail-body {
	display: flex;
	flex-direction: column;
	gap: 3px;
}

.imagination-feature__detail-body strong {
	font-family: var(--font-display);
	font-weight: 600;
	text-transform: uppercase;
	letter-spacing: 0.08em;
	font-size: 12.5px;
	color: var(--color-white);
	margin-bottom: 3px;
}

.imagination-feature__detail-body span {
	font-size: 16px;
	font-weight: 600;
	line-height: 1.45;
}

.imagination-feature__detail-sub {
	font-size: 14px !important;
	font-weight: 500 !important;
	color: var(--color-white);
}

.imagination-feature__proof {
	position: relative;
	margin-top: 24px;
	font-size: 16px;
	font-weight: 600;
	color: var(--color-white);
}

/* Groups the CTAs, flyer link and fine print so they sit at the bottom of
   the panel while the title block stays at the top — margin-top: auto eats
   the panel's free space (and so overrides its justify-content: center).

   flow-root, not plain block: it establishes a BFC so .__actions' own
   margin-top can't collapse out through this wrapper, which would defeat
   the auto margin. Keeping it flow-root rather than flex also leaves every
   child's existing layout untouched — .__poster stays shrink-to-fit
   inline-flex instead of stretching the full panel width. */
.imagination-feature__footer {
	position: relative;
	display: flow-root;
	margin-top: auto;
}

.imagination-feature__actions {
	position: relative;
	display: flex;
	gap: 16px;
	flex-wrap: wrap;
	margin-top: 28px;
}

/* Client asked twice for these larger — first to match .hero__actions'
   scaled-up treatment (16px), then explicitly bigger again ("much larger").
   Now the largest buttons on the site, on purpose: this panel's headline runs
   up to 46px, so even the hero's 16px CTA still read small standing next to
   it. Scoped here rather than changed on .btn--lg itself, which is shared by
   every other CTA button on the site. */
.imagination-feature__actions .btn--lg {
	padding: 22px 44px;
	font-size: 19px;
	letter-spacing: 0.04em;
}

/* Client: as large as this text can go. Pushed from 13px to 18px — the panel
   comfortably fits the longest line (the charity registration number) at this
   size without an awkward mid-word wrap; stepped back down on phones (below)
   where the panel narrows a lot more than it does at tablet/desktop. */
.imagination-feature__fineprint {
	position: relative;
	margin-top: 20px;
	font-size: 18px;
	font-weight: 500;
	line-height: 1.55;
	color: var(--color-white);
}

.imagination-feature__fineprint-heading {
	display: block;
	font-weight: 600;
	margin-bottom: 8px;
}

/* Imagination Ball inner page reuses .imagination-feature verbatim; only the
   photo's crop point needs its own tuning (the homepage rule above is tuned
   for the cheque-presentation photo, this one for the 2026 hero art). */
.imagination-feature--page .ph-media--photo img {
	object-position: 40% 45%;
}

/* Flyer button — client feedback: the old bare thumbnail-plus-label sitting
   next to the Get Tickets / Sponsorship Package pills read as odd, unstyled
   leftover content rather than a third action, and using the busy flyer
   artwork itself as a tiny icon just looked cluttered. .btn/.btn--ghost/
   .btn--lg (all in the markup already) supply the same pill chrome as its
   siblings; this just adds the pointer cursor a <span> doesn't get for free
   — the icon is a plain line-svg, sized the same as the detail icons above. */
.imagination-feature__poster {
	cursor: pointer;
}

/* =========================================================
   Programs — carousel + parallax ripple backdrop
   ========================================================= */
.programs {
	position: relative;
	overflow: hidden;
	isolation: isolate;
}

/* "20 Years of Service" badge (client-supplied graphic), moved here from the
   homepage's Imagination Ball feature. Sized up and pulled down over the
   carousel below via the negative margin — a placeholder scale/position
   (client: "for now") while the final treatment is decided. */
.programs__badge {
	flex: none;
	align-self: center;
	width: 200px;
	height: 200px;
	filter: drop-shadow(0 8px 18px rgba(31, 27, 27, 0.18));
	margin-bottom: -90px;
	z-index: 1;
}

.programs__badge img {
	width: 100%;
	height: 100%;
	object-fit: contain;
	display: block;
}

/* Arrows overlay the slider instead of sitting beside it, so the carousel
   itself runs the full width of the container edge to edge.

   --visible lives here rather than on .programs__carousel so it inherits to
   BOTH the carousel (where the JS reads it) and the arrows (which need it to
   work out where the card image ends). */
.programs__viewport {
	--visible: 3;
	position: relative;
	margin-top: 48px;
	/* Lets the arrows below measure against this element's WIDTH via cqw.
	   A percentage in `top` would resolve against its height instead. */
	container-type: inline-size;
}

.programs__carousel {
	overflow: hidden;
}

/* Vertically centred on the card's PHOTO rather than the whole card — the
   media is 4/3 of the card width, so its half-height is cardWidth * 3/4 / 2,
   i.e. * 0.375. Centring on the full card would drop the arrows into the
   title/excerpt text below the image.

   Measured in cqw (1% of .programs__viewport's width), NOT %: a percentage
   in `top` resolves against the containing block's HEIGHT, which put the
   arrows near the top of the photos instead of their centre. */
.programs__arrow {
	position: absolute;
	z-index: 3;
	top: calc(((100cqw - (var(--visible) - 1) * 28px) / var(--visible)) * 0.375);
	transform: translateY(-50%);
	width: 44px;
	height: 44px;
	/* Solid, because it now sits over photography — the shared .carousel-arrow
	   is a white outline on transparent, built for dark sections. */
	background: var(--color-white);
	border-color: transparent;
	color: var(--color-ink);
	box-shadow: 0 6px 20px -6px rgba(31, 27, 27, 0.35);
}

.programs__arrow:hover {
	background: var(--color-primary);
	border-color: transparent;
	color: var(--color-white);
}

.programs__arrow.carousel-arrow--prev {
	left: 16px;
}

.programs__arrow.carousel-arrow--next {
	right: 16px;
}

.programs__track {
	display: flex;
	gap: 28px;
	transition: transform 0.5s ease;
}

.program-card {
	flex: 0 0 calc((100% - (var(--visible) - 1) * 28px) / var(--visible));
	min-width: 0;
}

.program-card__media {
	position: relative;
	display: block;
}

.program-card__title {
	font-family: var(--font-display);
	font-weight: 300;
	text-transform: capitalize;
	letter-spacing: -0.005em;
	font-size: 23px;
	margin-top: 20px;
}

.program-card__title a {
	color: inherit;
	text-decoration: none;
	transition: color 0.2s ease;
}

.program-card__title a:hover,
.program-card__title a:focus-visible {
	color: var(--color-primary);
}

.program-card__excerpt {
	margin-top: 10px;
	font-size: 15px;
	line-height: 1.4;
	color: var(--color-grey);
}

.program-card .link-arrow {
	margin-top: 16px;
}

/* Static grid variant of .program-card — used on the /our-outreach/
   landing page instead of the homepage's auto-advancing carousel. */
.programs-grid {
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	gap: 48px 28px;
}

.programs-grid .program-card {
	flex: none;
}

/* =========================================================
   Events — Webinar Outreach Wing (6 x 2 grid)
   ========================================================= */
/* WOW pink, sampled from the O of the WOW logo (it is literally one of the
   ring's three dominant colours). Gives the Webinar Outreach Wing its own
   identity colour, since WOW is effectively a sub-brand with its own mark.
   All copy inside goes white — the ink grey only reaches 3.06:1 on this
   pink and would fail AA, while white sits at 5.57:1. */
.events {
	position: relative;
	overflow: hidden;
	isolation: isolate;
	background: #c52163;
}

.events .section__title {
	color: var(--color-white);
}

/* The logo can't sit directly on this background: a quarter of its opaque
   pixels are this exact pink (the O ring), so they would dissolve into it.
   A white chip keeps the mark's real colours intact and matches the tile
   treatment used on the partners wall. */
.events__badge {
	background: var(--color-white);
	border-radius: 16px;
	padding: 14px 18px;
}

/* Red on this pink is muddy (1.23:1 apart in luminance) — invert to a white
   outline that fills white on hover, with the pink returning as the label. */
.events .more-link {
	border-color: rgba(255, 255, 255, 0.7);
	color: var(--color-white);
}

.events .more-link:hover {
	background: var(--color-white);
	color: #c52163;
}

.events__lockup {
	display: flex;
	align-items: center;
	gap: 30px;
}

.events__badge {
	flex: none;
	display: flex;
	align-items: center;
	justify-content: center;
}

.events__logo {
	display: block;
	width: auto;
	height: 150px;
}

.events__intro {
	margin-top: 16px;
	max-width: 560px;
	font-size: 16px;
	line-height: 1.4;
	color: rgba(255, 255, 255, 0.92);
}

.events__grid {
	display: grid;
	grid-template-columns: repeat(6, 1fr);
	gap: 24px 20px;
}

.webinar-card {
	position: relative;
}

.webinar-card__thumb {
	position: relative;
	display: block;
	width: 100%;
	padding: 0;
	border: none;
	background: transparent;
	border-radius: var(--radius);
	overflow: hidden;
	cursor: pointer;
}

.webinar-card__thumb .ph-media {
	transition: transform 0.3s ease;
}

.webinar-card__thumb:hover .ph-media {
	transform: scale(1.04);
}

.webinar-card__play {
	position: absolute;
	inset: 0;
	display: flex;
	align-items: center;
	justify-content: center;
	margin: auto;
	width: 44px;
	height: 44px;
	border-radius: 50%;
	background: rgba(31, 27, 27, 0.55);
	color: var(--color-white);
	opacity: 0.9;
	transition: background-color 0.2s ease, opacity 0.2s ease, transform 0.2s ease;
}

.webinar-card__play svg {
	margin-left: 2px;
}

.webinar-card__thumb:hover .webinar-card__play {
	background: var(--color-primary);
	opacity: 1;
	transform: scale(1.1);
}

/* Webinar Outreach Wing page — tight image-only grid matching the
   homepage's density. Title/speaker/Play/Read-Feedback live in a maroon
   overlay that's hidden until hover/focus, so browsing stays scannable. */
.wow-tight-grid {
	margin-top: 40px;
	display: grid;
	grid-template-columns: repeat(6, 1fr);
	gap: 20px;
}

/* Closing lines under the webinar grid — the YouTube subscribe prompt and the
   donor thank-you, both client copy. Ruled off from the grid above so they
   read as the section signing off rather than as another caption under the
   last row of cards. */
.wow-webinars-outro {
	margin-top: 48px;
	padding-top: 36px;
	border-top: 1px solid var(--color-grey-light);
	text-align: center;
}


/* The thank-you is the section's last word, so it gets the display face and a
   short red rule under it rather than being another line of body copy. */
.wow-webinars-outro__thanks {
	position: relative;
	margin-top: 30px;
	padding-bottom: 18px;
	font-family: var(--font-display);
	font-weight: 400;
	font-size: clamp(21px, 2.4vw, 28px);
	line-height: 1.3;
	color: var(--color-ink);
}

.wow-webinars-outro__thanks::after {
	content: "";
	position: absolute;
	left: 50%;
	bottom: 0;
	width: 56px;
	height: 3px;
	border-radius: 2px;
	transform: translateX(-50%);
	background: var(--color-primary);
}

.webinar-card__overlay {
	position: absolute;
	inset: 0;
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	text-align: center;
	padding: 16px;
	border-radius: var(--radius);
	background: rgba(136, 14, 20, 0.88);
	opacity: 0;
	transition: opacity 0.2s ease;
	pointer-events: none;
}

.webinar-card:hover .webinar-card__overlay,
.webinar-card:focus-within .webinar-card__overlay {
	opacity: 1;
	pointer-events: auto;
}

.webinar-card__title {
	font-family: var(--font-display);
	font-weight: 400;
	font-size: 15px;
	line-height: 1.25;
	color: var(--color-white);
}

.webinar-card__title sup {
	font-family: var(--font-label);
	color: rgba(255, 255, 255, 0.8);
	cursor: help;
}

.webinar-card__person {
	margin-top: 3px;
	font-family: var(--font-label);
	font-weight: 700;
	font-size: 10px;
	letter-spacing: 0.05em;
	text-transform: uppercase;
	color: rgba(255, 255, 255, 0.8);
}

.webinar-card__actions {
	margin-top: 12px;
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 8px;
}

.webinar-card__play-btn {
	display: inline-flex;
	align-items: center;
	gap: 6px;
	padding: 7px 16px;
	border: none;
	border-radius: 999px;
	background: var(--color-white);
	color: var(--color-primary);
	font-family: var(--font-body);
	font-weight: 700;
	font-size: 11.5px;
	letter-spacing: 0.03em;
	text-transform: uppercase;
	cursor: pointer;
	transition: transform 0.15s ease;
}

.webinar-card__play-btn:hover {
	transform: scale(1.05);
}

/* Client: "CLICK the Webinar to watch it." That instruction has to be true, so
   the Play pill's hit area is stretched over the whole poster. Two details make
   it work: the pseudo-element covers the overlay's box (inset: 0 on the thumb),
   and pointer-events is re-enabled here — the overlay itself is
   pointer-events: none until hover, which on a touch screen never happens, so
   without this the posters could not be played on a phone at all. */
.webinar-card__play-btn {
	pointer-events: auto;
}

.webinar-card__play-btn::after {
	content: "";
	position: absolute;
	inset: 0;
	border-radius: var(--radius);
}

/* The hand-holding line under "Our Webinars". */
/* A note, not a control. This was a maroon pill with a play icon, which read
   as a button — it is not clickable, it only explains that the posters below
   are. Plain muted text says the same thing without inviting a click. */
.wow-webinars-hint {
	margin-top: 12px;
	color: var(--color-body);
	font-family: var(--font-label);
	font-size: 14px;
	font-weight: 400;
	letter-spacing: 0.01em;
}

.webinar-card__feedback-btn {
	border: none;
	background: transparent;
	padding: 0;
	font-family: var(--font-body);
	font-weight: 600;
	font-size: 11px;
	letter-spacing: 0.04em;
	text-transform: uppercase;
	color: var(--color-white);
	text-decoration: underline;
	text-underline-offset: 2px;
	cursor: pointer;
}

/* Content popup — any [data-modal-target] trigger clones its matching
   hidden #id panel into this shared white modal instead of scrolling the
   page or using a per-card <details> dropdown (see the content-modal IIFE
   in main.js). Used by the Webinar page's "Read Feedback" cards and the
   People page's "Read More" bios. */
.content-modal {
	position: fixed;
	inset: 0;
	z-index: 300;
	display: flex;
	align-items: center;
	justify-content: center;
	padding: 24px;
	background: rgba(31, 27, 27, 0.7);
	opacity: 0;
	visibility: hidden;
	transition: opacity 0.25s ease, visibility 0.25s ease;
}

.content-modal.is-open {
	opacity: 1;
	visibility: visible;
}

.content-modal__panel {
	position: relative;
	width: min(90vw, 640px);
	max-height: 84vh;
	overflow-y: auto;
	padding: 44px 36px;
	background: var(--color-white);
	border-radius: var(--radius);
	box-shadow: 0 24px 64px rgba(0, 0, 0, 0.35);
}

.content-modal__close {
	position: absolute;
	top: 16px;
	right: 16px;
	display: flex;
	align-items: center;
	justify-content: center;
	width: 36px;
	height: 36px;
	border-radius: 50%;
	border: 1px solid var(--color-grey-light);
	background: transparent;
	color: var(--color-ink);
	transition: background-color 0.2s ease, border-color 0.2s ease;
}

.content-modal__close:hover {
	background: var(--color-grey-light);
	border-color: var(--color-grey);
}

.content-modal__body .wow-feedback-entry__title {
	font-family: var(--font-display);
	font-weight: 400;
	font-size: 24px;
	padding-right: 30px;
}

.content-modal__body .testimonial__quote {
	margin: 16px 0 0;
	padding-left: 16px;
	border-left: 2px solid var(--color-grey-light);
	font-size: 16px;
	line-height: 1.6;
}

.content-modal__body .testimonial__quote cite {
	display: block;
	margin-top: 6px;
	font-style: normal;
	font-family: var(--font-label);
	font-weight: 700;
	font-size: 12px;
	letter-spacing: 0.03em;
	text-transform: uppercase;
	color: var(--color-primary);
}

/* Person bio content rendered inside the modal (photo + name + role + full
   bio text) */
.content-modal__bio-photo {
	width: 140px;
	height: 140px;
	border-radius: 50%;
	object-fit: cover;
	object-position: top center;
	margin-bottom: 18px;
}

.content-modal__body .person__name {
	font-size: 22px;
	padding-right: 30px;
}

.content-modal__body .person__role {
	margin-top: 6px;
}

.content-modal__body .person__bio,
.content-modal__body p,
.content-modal__body li {
	margin-top: 14px;
	font-size: 15.5px;
	line-height: 1.65;
	color: var(--color-body);
}

.content-modal__body ul {
	margin-top: 14px;
	padding-left: 18px;
	list-style: disc;
}

.content-modal__body li {
	margin-top: 8px;
}

/* Featured video row (Women's Day Celebration / About TREWO / Empowering
   Women) — small enough (3 items) that titles stay visible above the
   thumbnail rather than needing the hover treatment. */
/* auto-fit rather than a hard repeat(3): the container tops out at three
   tracks anyway, but empty tracks collapse, so the two remaining videos share
   the row evenly instead of leaving a hole where the retired third card was. */
.wow-video-grid {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(300px, 1fr));
	gap: 32px 28px;
}

.wow-video-card .webinar-card__title {
	margin-bottom: 14px;
	font-size: 19px;
	color: var(--color-ink);
}

/* Client: the play badge was not visible on these two videos. The shared badge
   is dark translucent, which disappears into a dim photograph, so on this page
   it is brand red by default and larger, with a white ring and a shadow to
   hold it off the image whatever the frame behind it looks like. Hover keeps a
   state of its own by going darker rather than by turning red. */
.wow-video-card .webinar-card__play {
	width: 58px;
	height: 58px;
	background: var(--color-primary);
	color: var(--color-white);
	opacity: 1;
	border: 2px solid rgba(255, 255, 255, 0.9);
	box-shadow: 0 6px 20px rgba(31, 27, 27, 0.35);
}

.wow-video-card .webinar-card__play svg {
	width: 22px;
	height: 22px;
}

.wow-video-card .webinar-card__thumb:hover .webinar-card__play {
	background: var(--color-primary-dark);
	transform: scale(1.08);
}

/* Women's Outreach Wing dated archive — 3-column, fluid height per image
   (these flyers are portraits, not a fixed ratio), and the hover-zoom clips
   to the image's own box so the shadow never looks mismatched. Clicking
   opens the lightbox showing the hi-res original via data-full. */
.wow-archive-title {
	margin-top: 56px;
	font-family: var(--font-display);
	font-weight: 300;
	font-size: clamp(24px, 3vw, 32px);
	line-height: 1.1;
	color: var(--color-ink);
}

.wow-archive-grid {
	margin-top: 40px;
	display: grid;
	grid-template-columns: repeat(6, 1fr);
	gap: 16px;
}

.wow-archive-title + .wow-archive-grid {
	margin-top: 24px;
}

.wow-archive-item {
	margin: 0;
	position: relative;
	overflow: hidden;
	border-radius: 14px;
	box-shadow: 0 10px 26px rgba(0, 0, 0, 0.1);
}

.wow-archive-item__img {
	display: block;
	width: 100%;
	height: auto;
	cursor: zoom-in;
	transition: transform 0.45s ease;
}

.wow-archive-item:hover .wow-archive-item__img {
	transform: scale(1.06);
}

.wow-archive-item__year {
	position: absolute;
	top: 12px;
	left: 12px;
	margin: 0;
	padding: 5px 12px;
	border-radius: 999px;
	background: var(--color-primary);
	color: var(--color-white);
	font-family: var(--font-label);
	font-weight: 700;
	font-size: 13px;
	letter-spacing: 0.04em;
	pointer-events: none;
}


/* =========================================================
   Gallery — infinite marquee
   ========================================================= */
/* Photo background (client trial) with a dark tint so the heading, arrows
   and "More" button — all switched to white below — stay readable over it. */
/* Fireworks photo behind the gala photos for the celebration feel. The scrim
   is graded rather than flat: heaviest at the top so the white heading stays
   legible over the burst up there, lightest at the bottom so the fireworks
   actually read behind and around the photo marquee. The photo is a night shot
   that is already near-black, so the tint is much lighter than the illustrated
   background it replaced — anything heavier erases the burst entirely. */
.gallery {
	position: relative;
	background-image:
		linear-gradient(
			rgba(20, 16, 26, 0.55) 0%,
			rgba(20, 16, 26, 0.3) 38%,
			rgba(20, 16, 26, 0.18) 100%
		),
		url("../images/gallery-bg-fireworks.jpg");
	background-size: cover;
	background-position: center;
	background-repeat: no-repeat;
}

.gallery .eyebrow {
	color: var(--color-white);
}

.gallery .section__title {
	color: var(--color-white);
}

.gallery .carousel-arrow--dark {
	border-color: rgba(255, 255, 255, 0.35);
	color: var(--color-white);
}

.gallery .carousel-arrow--dark:hover {
	background: rgba(255, 255, 255, 0.15);
	border-color: var(--color-white);
}

.gallery .more-link {
	border-color: rgba(255, 255, 255, 0.6);
	color: var(--color-white);
}

.gallery .more-link::before,
.gallery .more-link::after {
	border-color: rgba(255, 255, 255, 0.8);
}

.gallery .more-link:hover {
	background: var(--color-white);
	color: var(--color-primary);
	border-color: var(--color-white);
}

.gallery__controls {
	display: flex;
	align-items: center;
	gap: 16px;
	flex: none;
}

.gallery__marquee {
	margin-top: 48px;
	overflow: hidden;
	width: 100vw;
	position: relative;
	left: 50%;
	margin-left: -50vw;
}

.gallery__track {
	position: relative;
	display: flex;
	align-items: center;
	gap: 20px;
	width: max-content;
	padding-inline: var(--gutter);
	will-change: transform;
}

.gallery__item {
	flex: none;
	height: 400px;
}

/* Fixed height, auto width — preserves each photo's natural aspect ratio
   instead of cropping it into a uniform box. */
.gallery__item img {
	height: 100%;
	width: auto;
	display: block;
	border-radius: var(--radius);
	cursor: zoom-in;
}

/* =========================================================
   Lightbox
   ========================================================= */
.lightbox {
	position: fixed;
	inset: 0;
	z-index: 300;
	display: flex;
	align-items: center;
	justify-content: center;
	background: rgba(15, 12, 12, 0.94);
	opacity: 0;
	visibility: hidden;
	transition: opacity 0.3s ease, visibility 0.3s ease;
}

.lightbox.is-open {
	opacity: 1;
	visibility: visible;
}

body.lightbox-is-open {
	overflow: hidden;
}

.lightbox__image {
	max-width: 86vw;
	max-height: 84vh;
	border-radius: var(--radius-sm);
	box-shadow: 0 24px 64px rgba(0, 0, 0, 0.45);
}

.lightbox__close,
.lightbox__nav {
	position: absolute;
	display: flex;
	align-items: center;
	justify-content: center;
	border-radius: 50%;
	border: 1px solid rgba(255, 255, 255, 0.3);
	background: transparent;
	color: var(--color-white);
	transition: background-color 0.2s ease, border-color 0.2s ease;
}

.lightbox__close:hover,
.lightbox__nav:hover {
	background: rgba(255, 255, 255, 0.12);
	border-color: var(--color-white);
}

.lightbox__close {
	top: 24px;
	right: 24px;
	width: 44px;
	height: 44px;
}

.lightbox__nav {
	top: 50%;
	transform: translateY(-50%);
	width: 52px;
	height: 52px;
}

.lightbox__nav--prev {
	left: 24px;
}

.lightbox__nav--next {
	right: 24px;
}

@media (max-width: 767px) {
	.lightbox__close {
		top: 14px;
		right: 14px;
		width: 38px;
		height: 38px;
	}

	.lightbox__nav {
		width: 40px;
		height: 40px;
	}

	.lightbox__nav--prev {
		left: 10px;
	}

	.lightbox__nav--next {
		right: 10px;
	}
}

/* =========================================================
   Video lightbox (Webinar Outreach Wing)
   ========================================================= */
.video-lightbox {
	position: fixed;
	inset: 0;
	z-index: 300;
	display: flex;
	align-items: center;
	justify-content: center;
	background: rgba(15, 12, 12, 0.94);
	opacity: 0;
	visibility: hidden;
	transition: opacity 0.3s ease, visibility 0.3s ease;
}

.video-lightbox.is-open {
	opacity: 1;
	visibility: visible;
}

.video-lightbox__frame {
	position: relative;
	width: min(90vw, 960px);
	aspect-ratio: 16 / 9;
	background: #000;
	border-radius: var(--radius-sm);
	overflow: hidden;
	box-shadow: 0 24px 64px rgba(0, 0, 0, 0.45);
}

.video-lightbox__iframe {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	border: none;
}

.video-lightbox__close {
	position: absolute;
	top: 24px;
	right: max(24px, calc((100% - var(--container-width)) / 2 + var(--gutter)));
	display: flex;
	align-items: center;
	justify-content: center;
	width: 44px;
	height: 44px;
	border-radius: 50%;
	border: 1px solid rgba(255, 255, 255, 0.3);
	background: transparent;
	color: var(--color-white);
	transition: background-color 0.2s ease, border-color 0.2s ease;
}

.video-lightbox__close:hover {
	background: rgba(255, 255, 255, 0.12);
	border-color: var(--color-white);
}

@media (max-width: 767px) {
	.video-lightbox__close {
		top: 14px;
		right: 14px;
		width: 38px;
		height: 38px;
	}
}

/* =========================================================
   Partners
   ========================================================= */
.partners {
	position: relative;
	overflow: hidden;
	isolation: isolate;
	/* True black, as asked for — deliberately not var(--color-ink) (#1f1b1b),
	   which the other dark sections use and which reads as warm grey next to
	   the white logo tiles. */
	background: #000;
}

.partners .section__title {
	color: var(--color-white);
}

/* Even grid rather than a wrapping flex row: the client asked for the logos
   to be the same size instead of some sitting larger than others, and equal
   tracks are the only way to get that from source files whose artwork sizes
   and proportions all differ. */
.partners__strip {
	margin-top: 40px;
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(190px, 1fr));
	gap: 16px;
}

/* Each logo sits on a white tile. The supplied files are a mix: 7 are
   artwork on an opaque white background (they would show as bright boxes
   straight on black) and 8 more are dark artwork on transparency (they
   would all but disappear on black). A white tile is what lets every logo
   keep its true brand colours — which is the actual request — while the
   section itself reads black. */
.partner-logo {
	display: flex;
	align-items: center;
	justify-content: center;
	height: 104px;
	background: var(--color-white);
	border-radius: 12px;
}

.partner-logo img {
	height: 100%;
	max-width: 100%;
	width: auto;
	object-fit: contain;
}

/* =========================================================
   Donate CTA
   ========================================================= */
.donate-cta {
	position: relative;
	overflow: hidden;
	isolation: isolate;
	background: var(--color-primary);
	color: var(--color-white);
	/* Floor lowered from 120px: on a phone the band was taller than the copy
	   inside it. */
	padding-block: clamp(84px, 16vw, 200px);
}

.donate-cta__bg {
	position: absolute;
	inset: 0;
	z-index: -2;
	/* Carries the brand red itself rather than borrowing the section's. The
	   z-index above makes this element its own stacking context, so the
	   multiply on the image below can only blend with what is painted inside
	   here — without this fill it would have nothing to blend against. */
	background: var(--color-primary);
}

.donate-cta__bg img {
	/* Oversized + repositioned so the parallax drift in main.js (GSAP
	   ScrollTrigger, scrubbed to the scrollbar) has buffer room to move
	   the image within without ever exposing an edge — .donate-cta itself
	   clips anything that spills past its bounds. */
	position: absolute;
	top: -15%;
	left: 0;
	width: 100%;
	height: 130%;
	object-fit: cover;
	object-position: center;
	display: block;

	/* Duotone, not a scrim. The artwork is red brushwork on near-white paper,
	   so an opacity tint could never win: heavy enough for white type to pass
	   AA over the paper and the hands disappear — the exact note the old photo
	   picked up from the client. Multiplying against the band's own red instead
	   means the paper ground resolves to roughly --color-primary (it blends
	   into the section, carrying only its paper grain) while the red hands drop
	   to a deep oxblood, ~12:1 under white type. The white contour lines drawn
	   over the hands survive as bright red linework. */
	mix-blend-mode: multiply;
	filter: contrast(1.08) saturate(1.12);
}

/* No blend support: fall back to the flat tint this replaced, heavy enough to
   keep white type legible over bare paper. */
@supports not (mix-blend-mode: multiply) {
	.donate-cta__bg img {
		filter: none;
	}

	.donate-cta__bg::after {
		background: linear-gradient(120deg, rgba(136, 14, 20, 0.86) 0%, rgba(181, 18, 27, 0.74) 55%, rgba(136, 14, 20, 0.82) 100%);
	}
}

/* With the duotone doing the contrast work, this layer is free to shape the
   band instead: a vignette that seals the edges into the sections above and
   below, and settles the eye on the centred copy. Nothing here is load-bearing
   for legibility. */
.donate-cta__bg::after {
	content: "";
	position: absolute;
	inset: 0;
	background:
		radial-gradient(115% 85% at 50% 42%, rgba(136, 14, 20, 0) 0%, rgba(122, 12, 18, 0.3) 58%, rgba(74, 7, 11, 0.72) 100%),
		linear-gradient(180deg, rgba(74, 7, 11, 0.38) 0%, rgba(136, 14, 20, 0) 34%, rgba(136, 14, 20, 0) 62%, rgba(74, 7, 11, 0.45) 100%);
}

.donate-cta__inner {
	position: relative;
	z-index: 1;
	text-align: center;
	max-width: 850px;
	margin-inline: auto;
}

.donate-cta__title {
	font-family: var(--font-display);
	font-weight: 300;
	text-transform: capitalize;
	letter-spacing: -0.01em;
	font-size: clamp(34px, 4.6vw, 56px);
	line-height: 1.05;
	/* Wide and soft — reads as depth against the linework passing behind the
	   type, never as an outline. */
	text-shadow: 0 2px 28px rgba(58, 4, 8, 0.5);
}

/* The second sentence carries the ask, so it steps to the warm off-white the
   rest of the site uses for paper. Against the red it reads a shade softer
   than the first line without breaking the single-colour discipline — still
   ~6.5:1, comfortably past AA. */
.donate-cta__title-em {
	color: var(--color-sand);
}

/* Pure white, not the 85% white that read as grey to the client, and a
   step up in size — they explicitly offered the point-size increase. */
.donate-cta__text {
	margin-top: 18px;
	font-size: clamp(19px, 2.2vw, 24px);
	line-height: 1.5;
	color: var(--color-white);
	text-shadow: 0 1px 18px rgba(58, 4, 8, 0.55);
	text-wrap: pretty;
}

.donate-cta__inner .btn {
	margin-top: 32px;
	/* Lifts the white button off a field that is now genuinely textured
	   underneath it rather than flat tint. */
	box-shadow: 0 12px 32px rgba(48, 3, 6, 0.32);
}

.donate-cta__inner .btn:hover {
	box-shadow: 0 16px 40px rgba(48, 3, 6, 0.38);
}

/* =========================================================
   Footer
   ========================================================= */
/* =========================================================
   YouTube subscribe ticker
   Sits between the donate CTA (a photo band) and the near-black footer, so
   it takes the brand red: it needs to read as its own strip rather than as
   the top edge of the footer. The belt itself is driven by GSAP in main.js
   — everything here is the resting state, which is what shows for reduced
   motion or if the CDN fails.
   ========================================================= */
.yt-ticker {
	position: relative;
	overflow: hidden;
	background: var(--color-primary);
	color: var(--color-white);
	padding-block: 16px;
}

/* max-content so the two runs lay out at their true width side by side
   rather than being squeezed into the viewport — the -50% translate in
   main.js depends on the track being exactly twice one run. */
.yt-ticker__track {
	display: flex;
	width: max-content;
	will-change: transform;
}

.yt-ticker__run {
	display: flex;
	align-items: center;
}

.yt-ticker__item {
	display: inline-flex;
	align-items: center;
	gap: 14px;
	padding-inline: 26px;
	white-space: nowrap;
}

/* Divider between repeats, so the message reads as a repeating item on a
   belt instead of one run-on sentence. */
.yt-ticker__item::after {
	content: "";
	margin-left: 26px;
	width: 5px;
	height: 5px;
	border-radius: 50%;
	background: rgba(255, 255, 255, 0.45);
}

.yt-ticker__text {
	font-family: var(--font-label);
	font-size: 15px;
	font-weight: 600;
	letter-spacing: 0.04em;
	text-transform: uppercase;
}

/* White plate behind the mark: the YouTube glyph is only recognisable in
   its own colours, and red-on-red would vanish into the band. */
.yt-ticker__icon {
	flex: none;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 46px;
	height: 32px;
	border-radius: 8px;
	background: var(--color-white);
	color: var(--color-primary);
	transition: transform 0.2s ease, box-shadow 0.2s ease;
}

.yt-ticker__icon svg {
	width: 26px;
	height: 26px;
}

.yt-ticker__icon:hover,
.yt-ticker__icon:focus-visible {
	transform: scale(1.1);
	box-shadow: 0 6px 18px rgba(0, 0, 0, 0.28);
}

@media (max-width: 640px) {
	.yt-ticker__text {
		font-size: 13px;
	}

	.yt-ticker__item {
		gap: 11px;
		padding-inline: 18px;
	}

	.yt-ticker__item::after {
		margin-left: 18px;
	}

	.yt-ticker__icon {
		width: 40px;
		height: 28px;
	}

	.yt-ticker__icon svg {
		width: 22px;
		height: 22px;
	}
}

.site-footer {
	position: relative;
	overflow: hidden;
	background: rgb(20, 20, 19);
	color: rgb(255, 255, 255);
}

.site-footer__inner {
	display: grid;
	grid-template-columns: 1fr 0.85fr 1.15fr;
	gap: 48px;
	padding-block: 72px;
}

.site-footer__tagline {
	margin-top: 16px;
	font-size: 14px;
	max-width: 340px;
	line-height: 1.6;
}

.site-footer__meta {
	display: flex;
	flex-direction: column;
	gap: 10px;
	margin-top: 24px;
}

.site-footer__meta li {
	display: flex;
	align-items: center;
	gap: 10px;
	font-size: 13px;
	color: rgb(255, 255, 255);
}

.site-footer__meta svg {
	flex: none;
	color: rgba(255, 255, 255, 0.4);
}

.site-footer__meta a {
	transition: color 0.2s ease;
}

.site-footer__meta a:hover {
	color: var(--color-white);
}

/* HealthLIT handles sit inside the footer contact list, between the email and
   the charity number, per the client's note. Set as its own panel so the four
   handles read as one block instead of loose lines under the email address —
   the mark is typeset, since the theme has no HealthLIT logo file. */
.site-footer__meta li.site-footer__healthlit {
	display: block;
	margin-block: 6px;
}

.hl-card {
	max-width: 340px;
	padding: 16px 18px 14px;
	border: 1px solid rgba(255, 255, 255, 0.09);
	border-radius: var(--radius-sm);
	background:
		linear-gradient(135deg, rgba(150, 100, 210, 0.10), rgba(70, 170, 225, 0.07) 60%, rgba(255, 255, 255, 0) 90%),
		rgba(255, 255, 255, 0.02);
}

.hl-card__mark {
	display: block;
	margin-bottom: 14px;
	font-size: 20px;
	line-height: 1;
}

.hl-card__mark-a {
	font-family: var(--font-display);
	font-weight: 500;
	color: #c2a0e6;
}

.hl-card__mark-b {
	font-family: var(--font-label);
	font-weight: 600;
	letter-spacing: 0.03em;
	color: #6ac7f0;
}

.hl-card__links {
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	gap: 10px 12px;
}

.hl-social {
	display: flex;
	align-items: center;
	gap: 9px;
	min-width: 0;
}

.hl-social__icon {
	display: flex;
	align-items: center;
	justify-content: center;
	flex: none;
	width: 28px;
	height: 28px;
	border-radius: 50%;
	border: 1px solid rgba(255, 255, 255, 0.16);
	color: rgba(255, 255, 255, 0.75);
	transition: color 0.2s ease, border-color 0.2s ease, background-color 0.2s ease;
}

.hl-social__text {
	display: grid;
	min-width: 0;
}

.hl-social__net {
	font-family: var(--font-label);
	font-size: 9px;
	font-weight: 500;
	letter-spacing: 0.12em;
	text-transform: uppercase;
	color: rgba(255, 255, 255, 0.42);
}

.hl-social__handle {
	font-size: 12.5px;
	line-height: 1.35;
	color: rgba(255, 255, 255, 0.92);
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
	transition: color 0.2s ease;
}

.hl-social:hover .hl-social__icon,
.hl-social:focus-visible .hl-social__icon {
	color: rgb(20, 20, 19);
	border-color: #6ac7f0;
	background: #6ac7f0;
}

.hl-social:hover .hl-social__handle,
.hl-social:focus-visible .hl-social__handle {
	color: var(--color-white);
}

@media (max-width: 900px) {
	.hl-card__links {
		grid-template-columns: 1fr;
	}
}

.social-links {
	display: flex;
	gap: 12px;
	margin-top: 20px;
}

.social-links a {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 36px;
	height: 36px;
	border-radius: 50%;
	border: 1px solid rgba(255, 255, 255, 0.25);
	color: rgba(255, 255, 255, 0.85);
	transition: background-color 0.2s ease, border-color 0.2s ease;
}

.social-links a:hover {
	background: var(--color-primary);
	border-color: var(--color-primary);
}

.site-footer__heading {
	font-family: var(--font-display);
	font-size: 22px;
	font-weight: 600;
	letter-spacing: 0.02em;
	text-transform: uppercase;
	color: var(--color-white);
	margin-bottom: 20px;
}

.site-footer__heading--connect {
	margin-top: 32px;
}

.site-footer__list {
	display: grid;
	grid-template-columns: 1fr;
	row-gap: 14px;
}

.site-footer__nav a {
	font-size: 15px;
	color: rgb(255, 255, 255);
	transition: color 0.2s ease;
}

.site-footer__nav a:hover {
	color: var(--color-white);
}

/* =========================================================
   Footer — contact form
   ========================================================= */
.site-footer__form {
	margin-top: 4px;
}

/* The wrapper holds either CF7's <form> or the inactive-plugin fallback; the
   column layout goes on whichever form element is actually rendered. */
.site-footer__form form {
	display: flex;
	flex-direction: column;
	gap: 14px;
}

.site-footer__form input,
.site-footer__form textarea {
	width: 100%;
	background: rgba(255, 255, 255, 0.06);
	border: 1px solid rgba(255, 255, 255, 0.16);
	border-radius: var(--radius-sm);
	padding: 12px 16px;
	color: var(--color-white);
	font-family: var(--font-body);
	font-size: 14px;
	transition: border-color 0.2s ease, background-color 0.2s ease;
}

.site-footer__form textarea {
	resize: vertical;
	min-height: 96px;
}

.site-footer__form input::placeholder,
.site-footer__form textarea::placeholder {
	color: rgba(255, 255, 255, 0.4);
}

.site-footer__form input:focus,
.site-footer__form textarea:focus {
	outline: none;
	border-color: var(--color-primary);
	background: rgba(255, 255, 255, 0.09);
}

.site-footer__consent {
	display: flex;
	align-items: flex-start;
	width: 100%;
	gap: 10px;
	font-size: 12.5px;
	line-height: 1.5;
	color: rgb(255, 255, 255);
}

.site-footer__consent span {
	flex: 1;
	min-width: 0;
}

.site-footer__consent input[type="checkbox"],
.site-footer__form input[type="checkbox"] {
	appearance: none;
	flex: none;
	width: 18px;
	height: 18px;
	margin: 1px 0 0;
	border: 1px solid rgba(255, 255, 255, 0.35);
	border-radius: 4px;
	background: rgba(255, 255, 255, 0.06);
	position: relative;
	cursor: pointer;
	transition: background-color 0.2s ease, border-color 0.2s ease;
}

.site-footer__consent input[type="checkbox"]:hover,
.site-footer__form input[type="checkbox"]:hover {
	border-color: rgba(255, 255, 255, 0.6);
}

.site-footer__consent input[type="checkbox"]:checked,
.site-footer__form input[type="checkbox"]:checked {
	background: var(--color-primary);
	border-color: var(--color-primary);
}

.site-footer__consent input[type="checkbox"]:checked::after,
.site-footer__form input[type="checkbox"]:checked::after {
	content: "";
	position: absolute;
	left: 5px;
	top: 1px;
	width: 5px;
	height: 9px;
	border: solid var(--color-white);
	border-width: 0 2px 2px 0;
	transform: rotate(45deg);
}

.site-footer__consent input[type="checkbox"]:focus-visible,
.site-footer__form input[type="checkbox"]:focus-visible {
	outline: 2px solid var(--color-primary);
	outline-offset: 2px;
}

.site-footer__form .btn {
	align-self: flex-start;
	margin-top: 4px;
}

/* ---------------------------------------------------------
   Contact Form 7 — footer form
   CF7 wraps every field in its own spans and appends a status message. These
   rules flatten that back onto the theme's field styling; the plugin's default
   stylesheet is written for a light background, so the dark footer needs its
   own colours for the response and validation text.
   --------------------------------------------------------- */
.site-footer__form .wpcf7 {
	margin: 0;
}

.site-footer__form .wpcf7-form p {
	margin: 0;
}

/* Field wrappers must not break the flex column. */
.site-footer__form .wpcf7-form-control-wrap {
	display: block;
	width: 100%;
}

.site-footer__form .wpcf7-form-control-wrap[data-name="consent"] {
	margin-top: 2px;
}

/* Submit button — CF7 renders an <input type="submit">, so the .btn padding
   applies but the flex alignment has to be restated. */
.site-footer__form .wpcf7-submit {
	width: auto;
	align-self: flex-start;
	margin-top: 4px;
	cursor: pointer;
}

/* Consent checkbox: [acceptance] nests label > input + span. */
.site-footer__form .wpcf7-acceptance .wpcf7-list-item {
	margin: 0;
}

.site-footer__form .wpcf7-acceptance label {
	display: flex;
	align-items: flex-start;
	gap: 10px;
	font-size: 12.5px;
	line-height: 1.5;
	color: rgb(255, 255, 255);
	cursor: pointer;
}

.site-footer__form .wpcf7-list-item-label {
	flex: 1;
	min-width: 0;
}

/* Status and validation messages. */
.site-footer__form .wpcf7-response-output {
	margin: 4px 0 0;
	padding: 10px 14px;
	border-radius: var(--radius-sm);
	border: 1px solid rgba(255, 255, 255, 0.25);
	font-size: 13px;
	line-height: 1.5;
	color: rgb(255, 255, 255);
}

.site-footer__form .wpcf7 form.sent .wpcf7-response-output {
	border-color: rgba(120, 220, 150, 0.6);
	background: rgba(120, 220, 150, 0.12);
}

.site-footer__form .wpcf7 form.invalid .wpcf7-response-output,
.site-footer__form .wpcf7 form.unaccepted .wpcf7-response-output,
.site-footer__form .wpcf7 form.failed .wpcf7-response-output,
.site-footer__form .wpcf7 form.aborted .wpcf7-response-output {
	border-color: rgba(255, 140, 140, 0.65);
	background: rgba(181, 18, 27, 0.22);
}

.site-footer__form .wpcf7-not-valid-tip {
	display: block;
	margin-top: 6px;
	font-size: 12px;
	color: rgb(255, 158, 158);
}

.site-footer__form .wpcf7-not-valid {
	border-color: rgba(255, 140, 140, 0.75) !important;
}

.site-footer__form .wpcf7-spinner {
	margin: 0 0 0 12px;
	background-color: rgba(255, 255, 255, 0.55);
}

.site-footer__bottom {
	border-top: 1px solid rgba(255, 255, 255, 0.12);
}

.site-footer__bottom-inner {
	display: flex;
	align-items: center;
	justify-content: space-between;
	padding-block: 24px;
	font-size: 13px;
	color: rgb(255, 255, 255);
}

/* =========================================================
   Inner pages — reusable page hero + content blocks
   ========================================================= */
.page-hero {
	position: relative;
	overflow: hidden;
	isolation: isolate;
	display: flex;
	align-items: center;
	min-height: 200px;
	padding: 80px 0 64px;
	color: var(--color-white);
}

/* Extra bottom padding so the overlapping .subnav--on-hero bar (pulled up
   via negative margin, see below) has room to sit inside the hero's own
   background instead of over the title/intro text. */
.page-hero--has-subnav {
	padding-bottom: 96px;
}

.page-hero__bg {
	position: absolute;
	inset: 0;
	z-index: -2;
}

.page-hero__bg img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
}

.page-hero__bg::after {
	content: "";
	position: absolute;
	inset: 0;
	background: linear-gradient(100deg, rgba(26, 20, 22, 0.86) 0%, rgba(26, 20, 22, 0.64) 55%, rgba(26, 20, 22, 0.44) 100%);
}

.page-hero__inner {
	position: relative;
}

.page-hero__eyebrow {
	color: rgba(255, 255, 255, 0.72);
}

.page-hero__title {
	font-family: var(--font-display);
	font-weight: 300;
	font-size: clamp(38px, 5vw, 64px);
	line-height: 1.04;
	margin-top: 14px;
}

.page-hero__intro {
	margin-top: 18px;
	max-width: 660px;
	font-size: 18px;
	line-height: 1.5;
	color: rgba(255, 255, 255, 0.88);
}

/* Client: the Resources hero's intro line was wrapping narrow, reading like
   a paragraph column instead of a wide banner line. Scoped to this page's
   body class (via its template) rather than changed on .page-hero__intro
   itself, which every other inner-page hero on the site also uses. */
.page-template-page-templatesresources-php .page-hero__intro {
	max-width: none;
}

/* Rich text block (page.php + prose sections) */
.page-prose {
	max-width: 760px;
}

/* Footnote inside a prose column — a source credit or aside that should read
   a step quieter than the body copy around it. */
.page-prose .prose-note {
	font-size: 14.5px;
}

/* Centers a single-column reading measure (page-prose, callout, pull-quote
   siblings) inside a full-width .container — for essay-style pages where
   the prose isn't already constrained by a media-row sibling. */
.prose-column {
	max-width: 760px;
	margin-inline: auto;
}

.prose-column + .prose-column,
.prose-column + .callout,
.callout + .prose-column {
	margin-top: 24px;
}

.page-prose + .page-prose {
	margin-top: 32px;
}

.page-prose p {
	margin: 0 0 18px;
	font-size: 17px;
	line-height: 1.6;
	color: var(--color-body);
}

.page-prose h2 {
	font-family: var(--font-display);
	font-weight: 300;
	text-transform: capitalize;
	font-size: clamp(28px, 3.4vw, 40px);
	line-height: 1.1;
	margin: 40px 0 16px;
}

.page-prose h2:first-child {
	margin-top: 0;
}

.page-prose h3 {
	font-family: var(--font-label);
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 0.06em;
	font-size: 15px;
	color: var(--color-primary);
	margin: 32px 0 12px;
}

.page-prose ul {
	margin: 0 0 18px;
	padding-left: 20px;
	list-style: disc;
}

.page-prose li {
	margin-bottom: 8px;
	font-size: 17px;
	line-height: 1.6;
	color: var(--color-body);
}

.page-prose li:last-child {
	margin-bottom: 0;
}

.page-prose a:not(.btn) {
	color: var(--color-primary);
	text-decoration: underline;
	text-underline-offset: 2px;
}

/* Roofs for the Roofless — Vision / Mission side-by-side lists */
.roofs-vm-grid {
	display: grid;
	grid-template-columns: 1fr 1fr;
	gap: 56px;
}

.roofs-vm-grid .page-prose {
	margin-top: 18px;
	max-width: none;
}

/* Two-column intro (lead statement + supporting copy) */
.about-intro__grid {
	display: grid;
	grid-template-columns: 0.9fr 1.1fr;
	gap: 56px;
	align-items: start;
}

.about-intro__lead {
	font-family: var(--font-display);
	font-weight: 300;
	text-transform: capitalize;
	font-size: clamp(26px, 3vw, 36px);
	line-height: 1.15;
	color: var(--color-ink);
}

.about-intro__body p {
	margin: 0 0 16px;
	font-size: 16px;
	line-height: 1.6;
	color: var(--color-body);
}

.about-intro__quote {
	margin: 22px 0 0;
	padding-left: 20px;
	border-left: 3px solid var(--color-primary);
	font-size: 18px;
	font-style: italic;
	line-height: 1.5;
	color: #555556;
}

.about-intro__quote cite {
	display: block;
	margin-top: 12px;
	font-family: var(--font-label);
	font-style: normal;
	font-weight: 700;
	font-size: 13px;
	letter-spacing: 0.02em;
	color: var(--color-ink);
}

/* Vertical timeline */
.timeline {
	margin-top: 48px;
	position: relative;
	padding-left: 28px;
	border-left: 2px solid var(--color-grey-light);
	max-width: 720px;
}

.timeline__item {
	position: relative;
	padding-bottom: 34px;
}

.timeline__item:last-child {
	padding-bottom: 0;
}

.timeline__item::before {
	content: "";
	position: absolute;
	left: -35px;
	top: 4px;
	width: 14px;
	height: 14px;
	border-radius: 50%;
	background: var(--color-primary);
	box-shadow: 0 0 0 4px var(--color-primary-tint);
}

.timeline__year {
	font-family: var(--font-label);
	font-weight: 700;
	font-size: 13px;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var(--color-primary);
}

.timeline__title {
	font-family: var(--font-display);
	font-weight: 400;
	font-size: 21px;
	margin-top: 4px;
}

.timeline__text {
	margin-top: 6px;
	font-size: 15px;
	line-height: 1.5;
	color: var(--color-body);
	max-width: 560px;
}

/* People grid — profile cards (photo/avatar + name, role, bio, read-more) */
.people-grid {
	margin-top: 40px;
	display: grid;
	grid-template-columns: repeat(2, 1fr);
	gap: 24px;
}

.person--lg {
	display: flex;
	gap: 24px;
	align-items: flex-start;
	padding: 30px;
	border: 1px solid var(--color-primary);
	border-radius: var(--radius);
	transition: box-shadow 0.25s ease, transform 0.25s ease;
}

.person--lg:hover {
	box-shadow: 0 18px 40px rgba(31, 27, 27, 0.08);
	transform: translateY(-2px);
}

.person__avatar {
	flex: none;
	width: 108px;
	height: 108px;
	border-radius: 50%;
	background: var(--color-primary-tint);
	color: var(--color-primary);
	display: flex;
	align-items: center;
	justify-content: center;
	font-family: var(--font-display);
	font-weight: 400;
	font-size: 34px;
}

.person__body {
	flex: 1;
	min-width: 0;
}

.person__name {
	font-family: var(--font-display);
	font-weight: 400;
	font-size: 19px;
	line-height: 1.2;
}

.person--lg .person__name {
	font-size: 20px;
}

.person__role {
	margin-top: 4px;
	font-family: var(--font-label);
	font-weight: 600;
	font-size: 11.5px;
	letter-spacing: 0.05em;
	text-transform: uppercase;
	color: var(--color-primary);
}

.person__bio {
	margin-top: 12px;
	font-size: 15px;
	line-height: 1.6;
	color: var(--color-body);
}

.person__more-btn {
	margin-top: 10px;
	display: inline-flex;
	align-items: center;
	gap: 6px;
	padding: 0;
	border: none;
	background: transparent;
	cursor: pointer;
	font-family: var(--font-body);
	font-weight: 600;
	font-size: 12px;
	letter-spacing: 0.05em;
	text-transform: uppercase;
	color: var(--color-primary);
	text-decoration: underline;
	text-underline-offset: 2px;
}

.people-block + .people-block {
	margin-top: 48px;
}

.people-block__heading {
	font-family: var(--font-label);
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 0.06em;
	font-size: 14px;
	color: var(--color-primary);
	padding-bottom: 12px;
	border-bottom: 1px solid var(--color-grey-light);
}

/* Committee lists (compact). The People Behind TREWO page has moved off these
   onto the portrait roster (.committee-board) further down; what remains here
   is still used by the I.M.P.A.C.T. page's "Also part of the team" list. */
.committee__title {
	font-family: var(--font-display);
	font-weight: 400;
	font-size: 20px;
	margin-bottom: 10px;
}

.committee__list li {
	padding: 10px 0;
	font-size: 15px;
	line-height: 1.4;
	color: var(--color-body);
	border-bottom: 1px solid var(--color-grey-light);
}

.committee__list li:last-child {
	border-bottom: none;
}

/* Obituary — quiet, respectful tribute panel */
.obituary {
	display: flex;
	gap: 32px;
	align-items: center;
	max-width: 860px;
	margin-inline: auto;
}

.obituary__photo {
	flex: none;
	width: 250px;
	height: 250px;
	border-radius: 50%;
	object-fit: cover;
	object-position: top center;
}

.obituary__content p {
	margin-top: 14px;
	font-size: 16px;
	line-height: 1.7;
	color: rgba(255, 255, 255, 0.85);
}

/* =========================================================
   TREWO Committees — portrait roster
   Client asked for a face beside every name and a better-looking section
   than the plain masonry name lists this replaced. Each committee is a
   full-width panel (rosters run from 1 to 22 people, so side-by-side panels
   would never line up) with its members as portrait cards; anyone whose
   photo hasn't arrived yet keeps their slot with an initials avatar so the
   grid stays even while the client fills the gaps in.
   ========================================================= */
.committee-board {
	margin-top: 48px;
	display: grid;
	gap: 56px;
}

/* The red tick that used to sit before the committee name was removed at the
   client's request; the rule under the heading is enough to separate one
   roster from the next. */
.committee-panel__head {
	display: flex;
	align-items: center;
	padding-bottom: 14px;
	border-bottom: 1px solid var(--color-grey-light);
}

.committee-panel__title {
	font-family: var(--font-display);
	font-weight: 400;
	font-size: clamp(21px, 2.2vw, 27px);
	line-height: 1.2;
	color: var(--color-ink);
}

/* Six per row at most (client). auto-fill was letting the widest container
   (1600px) fit nine or ten across, which shrank the portraits to thumbnails
   and made a long roster read as a contact sheet. A fixed count keeps the
   faces at a usable size and, since every committee uses the same track
   count, the rosters line up with each other down the page. */
.committee-people {
	margin-top: 32px;
	display: grid;
	grid-template-columns: repeat(6, minmax(0, 1fr));
	gap: 36px 20px;
	align-items: start;
}

.committee-person {
	text-align: center;
}

.committee-person__photo,
.committee-person__avatar {
	width: 108px;
	height: 108px;
	border-radius: 50%;
	margin-inline: auto;
	display: block;
	transition: transform 0.25s ease, box-shadow 0.25s ease;
}

.committee-person__photo {
	object-fit: cover;
	object-position: top center;
	background: var(--color-grey-light);
}

.committee-person__avatar {
	display: flex;
	align-items: center;
	justify-content: center;
	background: var(--color-primary-tint);
	color: var(--color-primary);
	font-family: var(--font-display);
	font-weight: 400;
	font-size: 30px;
}

.committee-person:hover .committee-person__photo,
.committee-person:hover .committee-person__avatar {
	transform: translateY(-3px);
	box-shadow: 0 12px 26px rgba(31, 27, 27, 0.14);
}

/* The gap under the portrait lives on .committee-person__id now, so a Chair's
   red plate starts below the photo rather than swallowing the space. */
.committee-person__id {
	margin-top: 14px;
}

.committee-person__name {
	font-family: var(--font-display);
	font-weight: 400;
	font-size: 16px;
	line-height: 1.25;
	color: var(--color-ink);
}

.committee-person__role {
	margin-top: 5px;
	font-family: var(--font-label);
	font-weight: 600;
	font-size: 11px;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var(--color-primary);
}

/* Chairs (and Co-Chairs) — the client asked for these to sit on the brand red
   so they read as the head of each roster at a glance. This replaces an
   earlier treatment of a red ring plus a red band ruled under the name; a
   filled card carries further down a long grid than a 4px rule did.

   The portrait stays the same diameter as everyone else's, so the faces still
   line up across the row — only the ground behind the chair changes. */
/* Chairs (and Co-Chairs) — brand red behind the name and title only, so the
   portrait itself matches every other member and the row still reads as one
   set of faces. Replaces an earlier version that filled the whole card, which
   made a Chair look like a different kind of thing rather than the head of
   the same roster. */
.committee-person--lead .committee-person__id {
	padding: 12px 10px 14px;
	border-radius: var(--radius-sm);
	background: var(--color-primary);
}

.committee-person--lead .committee-person__name {
	font-size: 17px;
	font-weight: 500;
	color: var(--color-white);
}

.committee-person--lead .committee-person__role {
	margin-top: 5px;
	font-size: 11.5px;
	font-weight: 700;
	letter-spacing: 0.08em;
	color: rgba(255, 255, 255, 0.92);
}

@media (max-width: 900px) {
	.committee-board {
		gap: 44px;
	}

	.committee-people {
		grid-template-columns: repeat(4, minmax(0, 1fr));
		gap: 28px 16px;
	}

	.committee-person__photo,
	.committee-person__avatar {
		width: 88px;
		height: 88px;
	}

	.committee-person__avatar {
		font-size: 24px;
	}

	.committee-person__name {
		font-size: 15px;
	}

	.committee-person--lead .committee-person__name {
		font-size: 17px;
	}
}

@media (max-width: 560px) {
	.committee-people {
		grid-template-columns: repeat(3, minmax(0, 1fr));
	}
}

/* =========================================================
   Falls Prevention Circuit — Trillium Health Partners
   Client-supplied copy, set as one reading column. An earlier version split
   it two-up with the offer list in a white panel; that invented an emphasis
   the client's own text does not have, and left a large gap beneath the
   shorter prose column. Plain prose is both more faithful and better set.
   ========================================================= */
/* This section renders a ripple accent (trewo_ripple in the template) and had
   no base rule of its own, so it was missing the containment every other
   ripple-bearing section has. .ripple-accent is position:absolute with
   right:-12%, so with no positioned ancestor it resolved against the initial
   containing block and hung off the right edge of the document — the extra
   horizontal scroll on the homepage. position + overflow keeps it inside the
   band, and isolation matches the siblings so its negative z-index cannot
   escape behind the page background. */
.falls-prevention {
	position: relative;
	overflow: hidden;
	isolation: isolate;
}

/* The full container is 1600px, and this heading is long enough to run
   almost all of it as a single line of 56px display type — far past a
   comfortable measure. Capped so it breaks into two balanced lines, and
   stepped down slightly since it is a sentence rather than a short title. */
.falls-prevention .section__title {
	max-width: 900px;
	margin-inline: auto;
	font-size: clamp(30px, 3.6vw, 46px);
	text-wrap: balance;
}

.falls-prevention__prose {
	max-width: 760px;
	margin: 40px auto 0;
}

.falls-prevention__prose p + p {
	margin-top: 18px;
}

/* list-style:none and padding-left:0 both override .page-prose ul, which
   sets a disc marker and an indent — without them the native bullet renders
   alongside the drawn one below and every row shows two dots. */
.falls-prevention__list {
	margin: 18px 0 0;
	padding-left: 0;
	list-style: none;
	display: grid;
	gap: 12px;
}

/* No marker at all (client) — neither the native disc nor a drawn dot. The
   rows are separated by the grid gap instead. */
.falls-prevention__list li {
	margin-bottom: 0;
	font-size: 16px;
	line-height: 1.7;
	color: var(--color-body);
}

.falls-prevention__list + p {
	margin-top: 22px;
}

/* Carousel — four across, arrows overlaid so the strip runs the full width
   of the container. Fifteen photographs as a flat grid made this one of the
   longest scrolls on the homepage. */
.falls-prevention__carousel {
	position: relative;
	margin-top: 52px;
}

.falls-prevention__arrow {
	position: absolute;
	top: 50%;
	z-index: 2;
	transform: translateY(-50%);
	background: var(--color-white);
	border-color: var(--color-white);
	color: var(--color-primary);
	box-shadow: 0 6px 20px rgba(31, 27, 27, 0.28);
}

.falls-prevention__arrow:hover:not(:disabled) {
	background: var(--color-primary);
	border-color: var(--color-primary);
	color: var(--color-white);
}

.falls-prevention__arrow[data-carousel-prev] {
	left: 14px;
}

.falls-prevention__arrow[data-carousel-next] {
	right: 14px;
}

.falls-prevention__arrow:disabled {
	opacity: 0;
	pointer-events: none;
}

.falls-prevention__track {
	width: 100%;
	display: flex;
	gap: 20px;
	overflow-x: auto;
	scroll-snap-type: x mandatory;
	scrollbar-width: none;
	padding-bottom: 4px;
}

.falls-prevention__track::-webkit-scrollbar {
	display: none;
}

.falls-prevention__slide {
	flex: 0 0 calc((100% - 60px) / 4);
	margin: 0;
	scroll-snap-align: start;
}

/* A fixed ratio here, unlike the IMPACT strip: this set is a mix of shapes,
   so without one the row would step up and down in height as you scroll. */
.falls-prevention__slide img {
	width: 100%;
	aspect-ratio: 4/3;
	object-fit: cover;
	display: block;
	border-radius: var(--radius);
	cursor: pointer;
	transition: transform 0.25s ease, box-shadow 0.25s ease;
}

.falls-prevention__slide img:hover,
.falls-prevention__slide img:focus-visible {
	transform: translateY(-3px);
	box-shadow: 0 18px 40px -20px rgba(31, 27, 27, 0.45);
}

@media (max-width: 900px) {
	.falls-prevention__slide {
		flex: 0 0 calc((100% - 20px) / 2);
	}
}

@media (max-width: 640px) {
	.falls-prevention__slide {
		flex: 0 0 88%;
	}
}

/* =========================================================
   IMPACT Media Care Package
   The client's photo/video/brochure set for schools and partners.
   ========================================================= */

/* Arrows overlay the photographs (client) rather than sitting beside them, so
   the strip runs the full width of the container instead of losing ~100px to
   two gutters. */
.impact-media__carousel {
	position: relative;
	margin-top: 44px;
}

.impact-media__arrow {
	position: absolute;
	top: 50%;
	z-index: 2;
	transform: translateY(-50%);
	/* Solid plate, not the shared translucent treatment: these sit on top of
	   photographs, where a bordered outline disappears against whatever
	   happens to be behind it. */
	background: var(--color-white);
	border-color: var(--color-white);
	color: var(--color-primary);
	box-shadow: 0 6px 20px rgba(31, 27, 27, 0.28);
}

.impact-media__arrow:hover:not(:disabled) {
	background: var(--color-primary);
	border-color: var(--color-primary);
	color: var(--color-white);
}

.impact-media__arrow[data-carousel-prev] {
	left: 14px;
}

.impact-media__arrow[data-carousel-next] {
	right: 14px;
}

/* Disabled at the ends by the carousel script. Faded out entirely rather than
   dimmed, since a ghosted plate floating over a photo reads as a smudge. */
.impact-media__arrow:disabled {
	opacity: 0;
	pointer-events: none;
}

.impact-media__track {
	width: 100%;
	display: flex;
	gap: 20px;
	overflow-x: auto;
	scroll-snap-type: x mandatory;
	scrollbar-width: none;
	padding-bottom: 4px;
}

.impact-media__track::-webkit-scrollbar {
	display: none;
}

/* Three across on desktop, so a frame is big enough to read faces while the
   partial fourth makes it obvious the strip continues. */
.impact-media__slide {
	flex: 0 0 calc((100% - 40px) / 3);
	margin: 0;
	scroll-snap-align: start;
}

/* Shown whole, not cropped (client): this set is all one size, so a fixed
   aspect-ratio box bought nothing and only trimmed the frames. Natural height
   keeps every slide the same height anyway. */
.impact-media__slide img {
	width: 100%;
	height: auto;
	display: block;
	border-radius: var(--radius);
	cursor: pointer;
	transition: transform 0.25s ease, box-shadow 0.25s ease;
}

.impact-media__slide img:hover,
.impact-media__slide img:focus-visible {
	transform: translateY(-3px);
	box-shadow: 0 18px 40px -20px rgba(31, 27, 27, 0.45);
}

/* Full container width (client). Note the clips are 480x854 portrait, so at
   this width each one renders tall and is upscaled well past its native size
   — an earlier cap avoided that. Left uncapped as requested. */
.impact-media__row {
	margin: 40px 0 0;
	width: 100%;
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	gap: 24px;
}

.impact-media__video {
	margin: 0;
}

/* 9/16 matches the source exactly, so nothing is cropped — declared rather
   than left to intrinsic sizing so the row reserves its height before
   metadata loads and the page does not jump. object-fit: contain is the
   safety net: a replacement clip of a different shape letterboxes inside the
   frame instead of being cut. */
.impact-media__video video {
	width: 100%;
	height: auto;
	aspect-ratio: 9 / 16;
	display: block;
	border-radius: var(--radius);
	background: var(--color-ink);
	object-fit: contain;
}

/* Brand red (client). It is the section's single call to action sitting on a
   cream ground, so the red both marks it as the thing to click and stops it
   reading as another white panel among the photographs above. The whole row
   is the link — there is only one action here. */
.impact-media__brochure {
	margin-top: 32px;
	display: flex;
	align-items: center;
	gap: 20px;
	padding: 22px 26px;
	background: var(--color-primary);
	border: 1px solid var(--color-primary);
	border-radius: var(--radius);
	color: var(--color-white);
	transition: background-color 0.2s ease, border-color 0.2s ease, box-shadow 0.2s ease, transform 0.2s ease;
}

.impact-media__brochure:hover,
.impact-media__brochure:focus-visible {
	background: var(--color-primary-dark);
	border-color: var(--color-primary-dark);
	box-shadow: 0 18px 40px -24px rgba(31, 27, 27, 0.5);
	transform: translateY(-2px);
}

/* Inverted against the red — a tinted circle would all but vanish on it. */
.impact-media__brochure-icon {
	flex: none;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 52px;
	height: 52px;
	border-radius: 50%;
	background: var(--color-white);
	color: var(--color-primary);
}

.impact-media__brochure-text {
	flex: 1;
	min-width: 0;
}

.impact-media__brochure-title {
	display: block;
	font-family: var(--font-display);
	font-weight: 400;
	font-size: 19px;
	color: var(--color-white);
}

.impact-media__brochure-note {
	display: block;
	margin-top: 3px;
	font-size: 14px;
	color: rgba(255, 255, 255, 0.85);
}

.impact-media__brochure-cta {
	flex: none;
	font-family: var(--font-label);
	font-weight: 600;
	font-size: 12px;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: var(--color-white);
}

@media (max-width: 900px) {
	.impact-media__slide {
		flex: 0 0 calc((100% - 20px) / 2);
	}

	.impact-media__row {
		gap: 16px;
	}
}

@media (max-width: 640px) {
	.impact-media__slide {
		flex: 0 0 88%;
	}

	.impact-media__row {
		grid-template-columns: 1fr;
	}

	.impact-media__brochure {
		flex-wrap: wrap;
		gap: 14px;
		padding: 18px;
	}
}

/* Donate page — the wrapper around the plugin's form. The form styles itself
   (see the plugin's assets/donation-form.css, which reads this theme's tokens);
   these rules only handle the page around it. */
.donate-form-section__fallback {
	max-width: 700px;
	margin-inline: auto;
	text-align: center;
	font-size: 17px;
	line-height: 1.7;
	color: var(--color-body);
}

/* The heading is a short question, not a display statement — capped and
   balanced so it breaks into two even lines rather than one long line and a
   stray word. */
.donate-alt__title {
	max-width: 820px;
	margin-inline: auto;
	font-size: clamp(28px, 3.4vw, 44px);
	text-wrap: balance;
}

.donate-alt__inner {
	max-width: 720px;
	margin-inline: auto;
	text-align: center;
}

.donate-alt__text {
	margin-top: 18px;
	font-size: 17px;
	line-height: 1.7;
	color: var(--color-body);
}

.donate-alt__text a {
	color: var(--color-primary);
	text-decoration: underline;
	text-underline-offset: 3px;
}

.donate-alt__charity {
	margin-top: 22px;
	font-family: var(--font-label);
	font-weight: 600;
	font-size: 12.5px;
	letter-spacing: 0.05em;
	text-transform: uppercase;
	color: var(--color-grey);
}

/* Pull-quote band */
.quote-band {
	position: relative;
	overflow: hidden;
	isolation: isolate;
	background: var(--color-cream);
	padding-block: 72px;
}

/* Bottom margin added (client: the section after the italic quote sat too
   close). The quote previously had none — the only gap came from whatever
   followed it, which was 32px and too tight under a ~29px italic line. This
   collapses with the next element's own margin, so it sets a floor rather
   than stacking on top of it. */
.pull-quote {
	position: relative;
	margin: 0 auto 56px;
	max-width: 760px;
	text-align: center;
}

.pull-quote::before {
	content: "\201C";
	display: block;
	font-family: var(--font-display);
	font-size: 72px;
	line-height: 0.6;
	color: var(--color-primary);
	margin-bottom: 8px;
}

.pull-quote p {
	font-family: var(--font-display);
	font-weight: 300;
	font-style: italic;
	font-size: clamp(21px, 2.6vw, 29px);
	line-height: 1.45;
	color: var(--color-ink);
}

.pull-quote cite {
	display: block;
	margin-top: 18px;
	font-family: var(--font-label);
	font-style: normal;
	font-weight: 700;
	font-size: 12.5px;
	letter-spacing: 0.05em;
	text-transform: uppercase;
	color: var(--color-primary);
}

.creative-gallery {
	margin-top: 28px;
	display: grid;
	grid-template-columns: repeat(6, 1fr);
	gap: 16px;
}

.creative-gallery img {
	width: 100%;
	aspect-ratio: 3 / 4;
	object-fit: cover;
	border-radius: 12px;
	cursor: zoom-in;
	transition: transform 0.3s ease, box-shadow 0.3s ease;
}

.creative-gallery img:hover {
	transform: translateY(-4px);
	box-shadow: 0 16px 30px rgba(0, 0, 0, 0.12);
}

/* Client-added gallery (template-parts/gallery-section.php)

   Deliberately not .creative-gallery: that is a six-across grid of 3/4 crops
   built for David Innis's posters. A set the client adds later could be three
   landscape photographs or thirty portrait ones, so this grid fills to fit and
   needs no breakpoints of its own. */
.gallery-block {
	margin-top: 28px;
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
	gap: 16px;
}

.gallery-block__img {
	width: 100%;
	height: 100%;
	aspect-ratio: 4 / 3;
	object-fit: cover;
	border-radius: 12px;
	cursor: zoom-in;
	transition: transform 0.3s ease, box-shadow 0.3s ease;
}

.gallery-block__img:hover {
	transform: translateY(-4px);
	box-shadow: 0 16px 30px rgba(0, 0, 0, 0.12);
}

.gallery-block__intro {
	max-width: 720px;
	margin: 12px auto 0;
	text-align: center;
	color: var(--color-muted, #5b6570);
}

@media (max-width: 600px) {
	.gallery-block {
		grid-template-columns: repeat(auto-fill, minmax(150px, 1fr));
		gap: 12px;
	}
}

/* Sticky sub-navigation (About cluster) */
.subnav {
	position: sticky;
	top: var(--header-height);
	z-index: 90;
	background: var(--color-primary);
	border-bottom: 1px solid var(--color-primary-dark);
	transition: top 0.3s ease;
}

/* In-page subnav anchors (Mission / History on the About page) need extra
   scroll offset so the target lands below the sticky subnav too, not just
   the header. */
#mission,
#History {
	scroll-margin-top: calc(var(--header-height) + 64px);
}

body.admin-bar #mission,
body.admin-bar #History {
	scroll-margin-top: calc(var(--header-height) + 96px);
}

@media screen and (max-width: 782px) {
	body.admin-bar #mission,
	body.admin-bar #History {
		scroll-margin-top: calc(var(--header-height) + 110px);
	}
}

.subnav__inner {
	display: flex;
	flex-wrap: wrap;
	gap: 6px 8px;
}

.subnav__link {
	position: relative;
	padding: 16px 18px;
	font-family: var(--font-display);
	font-weight: 400;
	font-size: 13px;
	letter-spacing: 0.04em;
	text-transform: none;
	color: var(--color-white);
	white-space: nowrap;
	transition: color 0.2s ease;
}

.subnav__link--caps {
	text-transform: uppercase;
	font-weight: 700;
	color: var(--color-white);
}

.subnav__link--caps::after {
	transform: scaleX(1);
}

.subnav__link::after {
	content: "";
	position: absolute;
	left: 18px;
	right: 18px;
	bottom: -1px;
	height: 2px;
	background: var(--color-primary);
	transform: scaleX(0);
	transition: transform 0.2s ease;
}

.subnav__link:hover {
	color: var(--color-white);
}

.subnav__link.is-active {
	color: var(--color-white);
	font-weight: 700;
}

.subnav__link.is-active::after {
	transform: scaleX(1);
}

/* Sits inside a .page-hero--has-subnav, pulled up over the hero's own
   bottom padding instead of appearing as a separate solid bar below it.
   A dark translucent tint (not fully transparent) rather than plain maroon
   — keeps the white text readable both while resting on the hero photo and
   once stuck under the header after scrolling past it. */
.subnav--on-hero {
	position: relative;
	top: auto;
	margin-top: -50px;
	background: transparent;
	border-top: 1px solid rgba(255, 255, 255, 0.35);
	border-bottom: 1px solid rgba(255, 255, 255, 0.35);
}

/* On a phone the five links wrap onto two rows, and the -50px pull only lifts
   the first of them onto the hero photograph — the second row landed on the
   white section below, where white type on white is invisible. That was the
   "menu not visible" the client reported.

   Client: no background of its own, it should keep sitting on the hero. So
   the bar is pulled up by its full two-row height instead, and the hero gets
   the matching bottom padding to hold it. The two numbers belong together —
   the padding must exceed the pull, or the bar rides up over the title. */
@media (max-width: 767px) {
	.subnav--on-hero {
		margin-top: -104px;
	}

	.page-hero--has-subnav {
		padding-bottom: 128px;
	}

	.subnav__inner {
		gap: 0 6px;
	}
}

/* Two-column media + text row (reusable on inner pages) */
.media-row {
	display: grid;
	grid-template-columns: 1fr 1fr;
	gap: 56px;
	align-items: center;
}

.media-row--reverse .media-row__media {
	order: 2;
}

.media-row__media img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	border-radius: 16px;
	display: block;
}

/* Author credit — a small round portrait beside a name. Its own block rather
   than a .media-row carrying five inline overrides (a narrower measure, its
   own column widths, a circular crop) that had nothing to do with a media
   row's two-column layout. */
.author-card {
	display: grid;
	grid-template-columns: 96px 1fr;
	align-items: center;
	gap: 20px;
	max-width: 640px;
	margin-inline: auto;
}

.author-card__photo img {
	width: 100%;
	aspect-ratio: 1;
	object-fit: cover;
	border-radius: 50%;
	display: block;
}

.author-card__label {
	margin-bottom: 4px;
}

.author-card__name {
	font-family: var(--font-display);
	font-size: 20px;
	color: var(--color-ink);
}

/* Promotional posters/flyers carry their own text — never crop them. */
.media-row__media--contain img {
	object-fit: contain;
	background: var(--color-cream);
}

.media-row__body p {
	margin: 0 0 16px;
	font-size: 16px;
	line-height: 1.6;
	color: var(--color-body);
}

/* This colour is set explicitly above, so it does not inherit the light text
   the red ground establishes — it has to be overridden by name. */
.section--red .media-row__body p {
	color: rgba(255, 255, 255, 0.92);
}

.section--red .media-row__body p a {
	color: var(--color-white);
}

.media-row__body p a {
	color: var(--color-primary);
	text-decoration: underline;
	text-underline-offset: 2px;
}

/* Colored band variant of .media-row — a statement line + CTA on a solid
   accent background (Upcoming Event page "Fundraising" intro). */
.media-row--band {
	position: relative;
	overflow: hidden;
	isolation: isolate;
	background: var(--color-accent);
	border-radius: var(--radius);
	padding: clamp(40px, 5vw, 64px);
}

.media-row--band .media-row__body p {
	font-family: var(--font-display);
	font-weight: 300;
	font-size: clamp(24px, 2.6vw, 32px);
	line-height: 1.35;
	color: var(--color-white);
}

/* =========================================================
   Upcoming Events page
   ========================================================= */

/* Full-bleed pink: the colour runs edge to edge and the padding lives on the
   section, rather than a rounded pink card floating inside the container. */
.events-band {
	background: var(--color-accent);
	color: var(--color-white);
	padding-block: clamp(64px, 7vw, 104px);
}

.events-band__inner {
	display: grid;
	grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
	align-items: center;
	gap: clamp(40px, 6vw, 88px);
}

.events-band__text {
	font-family: var(--font-display);
	font-weight: 300;
	font-size: clamp(26px, 3vw, 40px);
	line-height: 1.3;
	color: var(--color-white);
	margin-bottom: 32px;
}

.events-band__media img {
	width: 100%;
	height: auto;
	display: block;
	border-radius: var(--radius);
	box-shadow: 0 30px 70px -28px rgba(0, 0, 0, 0.45);
}

/* Poster is the reason to visit this page, so it is given real size — the old
   card capped it at 420px, which the client read as too small. */
.events-poster__frame {
	max-width: 720px;
	margin: 0 auto;
	background: var(--color-white);
	border: 1px solid rgba(31, 27, 27, 0.08);
	border-radius: var(--radius);
	padding: 20px;
	box-shadow: 0 30px 70px -34px rgba(31, 27, 27, 0.4);
}

.events-poster__frame img {
	width: 100%;
	height: auto;
	display: block;
	border-radius: 6px;
}

.upcoming-event__grid {
	display: grid;
	grid-template-columns: repeat(2, 1fr);
	gap: 32px;
	max-width: 900px;
	margin: 40px auto 0;
	align-items: start;
}

/* Wraps one flyer with its own buttons. The column is a grid with the frame
   on an auto row and the actions pinned to the end, so the two cards' button
   rows line up with each other even when one flyer has two buttons and the
   other has one. */
.upcoming-event__item {
	display: grid;
	grid-template-rows: auto 1fr;
	height: 100%;
}

.upcoming-event__actions {
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	align-items: start;
	gap: 12px;
	margin-top: 22px;
}

/* Flyers arrive at different native sizes, so each one gets a fixed-ratio
   frame (object-fit: contain) instead of being shown at natural size —
   keeps both cards the same height in the row no matter the source image's
   own aspect ratio. */
.upcoming-event__frame {
	aspect-ratio: 3/4;
	margin: 0;
	background: var(--color-white);
	border: 1px solid rgba(31, 27, 27, 0.08);
	border-radius: var(--radius);
	padding: 16px;
	box-shadow: 0 30px 70px -34px rgba(31, 27, 27, 0.4);
}

.upcoming-event__frame img {
	width: 100%;
	height: 100%;
	object-fit: contain;
	display: block;
	border-radius: 6px;
	cursor: pointer;
}

@media (max-width: 640px) {
	.upcoming-event__grid {
		grid-template-columns: 1fr;
		max-width: 420px;
	}
}

/* Same background-photo technique as .donate-cta__bg: .section--red is the
   base fill, this layer sits behind the content, and the ::after tint keeps
   the white title and poster frame legible over whatever photo is used. */
.upcoming-event {
	position: relative;
	overflow: hidden;
	isolation: isolate;
}

.upcoming-event__bg {
	position: absolute;
	inset: 0;
	z-index: -2;
}

.upcoming-event__bg img {
	position: absolute;
	top: -15%;
	left: 0;
	width: 100%;
	height: 130%;
	object-fit: cover;
	object-position: center;
	display: block;
}

.events-poster__actions {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: center;
	gap: 16px;
	margin-top: 36px;
}

@media (max-width: 767px) {
	.events-band__inner {
		grid-template-columns: 1fr;
	}

	/* Collage first on a phone — it carries the section on a small screen. */
	.events-band__media {
		order: -1;
	}
}

/* =========================================================
   Resources on Wellness — landing + subpages
   ========================================================= */

/* Landing page category features: a roomier variant of .media-row so the
   four alternating rows feel like the page's main event rather than a
   repeat of the standard inner-page split. */
.media-row--premium {
	gap: 72px;
	padding-block: 8px;
}

.media-row--premium .media-row__media img {
	border-radius: 22px;
	aspect-ratio: 4 / 3;
}

.media-row--premium .media-row__body .eyebrow {
	margin-bottom: 10px;
}

.media-row--premium .media-row__body h2 {
	font-family: var(--font-display);
	font-weight: 300;
	font-size: clamp(28px, 3.2vw, 40px);
	line-height: 1.1;
	color: var(--color-ink);
	margin-bottom: 16px;
}

.media-row--premium .media-row__body p {
	font-size: 17px;
	line-height: 1.65;
}

/* WOW "About Us" letter — two text columns + a photo column, image moves
   above the text on narrower screens (see the 1023px breakpoint below). */

/* The salutation sits above the grid, not inside the first column. As that
   column's opening <p> it pushed the letter's first line a whole line lower
   than "Our team…" at the top of the next column, which the client flagged as
   misaligned. Lifted out, both columns start on the same line and the greeting
   still reads as the opening of the letter. */
/* "Dear Friends," opening the letter, set at the letter's own measure so it
   lines up with the first column beneath it. */
.wow-about__salutation {
	max-width: 1000px;
	margin: 0 auto 20px;
	font-size: 16.5px;
	line-height: 1.7;
	color: var(--color-body);
}

/* The YouTube channel and trewo.org were already anchors in the letter, but
   the global reset (a { color: inherit; text-decoration: none }) left them
   looking like plain body text, so nobody could tell they were clickable.
   Brand red and underlined here — break-word because the bare URLs are long
   enough to overflow the narrow two-column measure on a phone. */
.wow-about__cols a {
	color: var(--color-primary);
	text-decoration: underline;
	text-underline-offset: 3px;
	text-decoration-thickness: 1px;
	overflow-wrap: break-word;
	transition: color 0.2s ease;
}

.wow-about__cols a:hover,
.wow-about__cols a:focus-visible {
	color: var(--color-primary-dark);
	text-decoration-thickness: 2px;
}

/* Compact resource cards — link-outs, downloads, teasers with thin or
   low-resolution source imagery that don't earn a full media-row. */
.resource-grid {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
	gap: 28px;
	margin-top: 32px;
}

.resource-grid--2up {
	grid-template-columns: repeat(auto-fit, minmax(320px, 1fr));
}

/* Fixed three-up, rather than the base grid's auto-fit, so the row stays at
   three regardless of how many cards the section holds. */
.resource-grid--3up {
	grid-template-columns: repeat(3, 1fr);
}

@media (max-width: 1023px) {
	.resource-grid--3up {
		grid-template-columns: repeat(2, 1fr);
	}
}

@media (max-width: 767px) {
	.resource-grid--3up {
		grid-template-columns: 1fr;
	}
}

.resource-card {
	display: flex;
	flex-direction: column;
	background: var(--color-white);
	border: 1px solid rgba(31, 27, 27, 0.08);
	border-radius: var(--radius);
	overflow: hidden;
	transition: border-color 0.2s ease, transform 0.2s ease, box-shadow 0.2s ease;
}

a.resource-card:hover {
	border-color: rgba(181, 18, 27, 0.3);
	transform: translateY(-3px);
	box-shadow: 0 16px 32px -20px rgba(31, 27, 27, 0.35);
}

.resource-card__media {
	aspect-ratio: 16 / 10;
	background: var(--color-cream);
}

.resource-card__media img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
}

/* Framed variant — photo sits on a white field with a thin outline instead
   of bleeding to the card edges, so images with their own borders/whitespace
   (vaccine vials, source screenshots) don't get cropped by object-fit:cover. */
.resource-card__media--contain {
	background: var(--color-white);
	border: 1px solid rgba(31, 27, 27, 0.12);
	padding: 14px;
}

.resource-card__media--contain img {
	object-fit: contain;
}

.resource-card__body {
	padding: 24px;
	display: flex;
	flex-direction: column;
	gap: 8px;
	flex: 1;
}

.resource-card__eyebrow {
	font-family: var(--font-label);
	font-weight: 700;
	font-size: 11.5px;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var(--color-primary);
}

.resource-card__title {
	font-family: var(--font-display);
	font-size: 19px;
	font-weight: 500;
	line-height: 1.3;
	color: var(--color-ink);
}

.resource-card__text {
	font-size: 14.5px;
	line-height: 1.55;
	color: var(--color-body);
}

.resource-card__meta {
	margin-top: auto;
	padding-top: 8px;
	display: flex;
	align-items: center;
	gap: 6px;
	font-family: var(--font-label);
	font-weight: 600;
	font-size: 12.5px;
	letter-spacing: 0.03em;
	color: var(--color-primary);
}

.resource-card__meta svg {
	flex: none;
	transition: transform 0.2s ease;
}

a.resource-card:hover .resource-card__meta svg {
	transform: translate(2px, -2px);
}

/* Event photo + CTA card (Upcoming Event page) — same footprint as
   .resource-card but the whole card isn't a link, so the button(s) live
   in their own row under the photo. */
.event-card {
	display: flex;
	flex-direction: column;
	background: var(--color-white);
	border: 1px solid rgba(31, 27, 27, 0.08);
	border-radius: var(--radius);
	overflow: hidden;
}

.event-card--solo {
	max-width: 420px;
	margin-inline: auto;
}

.event-card__actions {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: center;
	gap: 16px;
	padding: 24px;
}

/* Highlight / takeaway box — key points, helplines, pull-out tips. */
.callout {
	background: var(--color-white);
	border-left: 3px solid var(--color-primary);
	border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
	padding: 22px 26px;
	box-shadow: 0 1px 3px rgba(31, 27, 27, 0.06);
}

.callout--dark {
	background: var(--color-ink);
	border-left-color: var(--color-primary);
	color: var(--color-white);
}

.callout__title {
	font-family: var(--font-display);
	font-weight: 500;
	font-size: 19px;
	line-height: 1.3;
	margin-bottom: 8px;
	color: var(--color-ink);
}

.callout--dark .callout__title {
	color: var(--color-white);
}

.callout p:not(.callout__title) {
	margin: 0 0 10px;
	font-size: 15px;
	line-height: 1.6;
	color: var(--color-body);
}

.callout--dark p:not(.callout__title) {
	color: rgba(255, 255, 255, 0.82);
}

.callout p:last-child {
	margin-bottom: 0;
}

.callout ul {
	margin: 0;
	padding-left: 18px;
	display: flex;
	flex-direction: column;
	gap: 6px;
}

.callout li {
	font-size: 15px;
	line-height: 1.5;
	color: var(--color-body);
}

.callout--dark li {
	color: rgba(255, 255, 255, 0.82);
}

/* ---------- Helpline band (full-bleed black) --------------------------- */
.helpline-band {
	background: var(--color-ink);
	color: var(--color-white);
	padding-block: clamp(56px, 6vw, 84px);
}

.helpline-band__inner {
	max-width: 720px;
	margin-inline: auto;
	text-align: center;
}

.helpline-band__icon {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 52px;
	height: 52px;
	border-radius: 50%;
	background: rgba(255, 255, 255, 0.1);
	color: var(--color-white);
	margin-bottom: 22px;
}

.helpline-band__title {
	font-family: var(--font-display);
	font-weight: 400;
	font-size: clamp(24px, 2.6vw, 32px);
	line-height: 1.25;
	color: var(--color-white);
	margin: 0 0 14px;
}

.helpline-band__text {
	margin: 0 auto;
	max-width: 620px;
	font-size: 17px;
	line-height: 1.6;
	color: rgba(255, 255, 255, 0.82);
}

.helpline-band__text strong {
	color: var(--color-white);
}

/* The number is the point of the whole band, so it gets the most weight. */
.helpline-band__phone {
	margin: 26px 0 0;
	font-family: var(--font-display);
	font-size: clamp(30px, 3.6vw, 44px);
	line-height: 1.1;
}

.helpline-band__phone a {
	color: var(--color-white);
	text-decoration: none;
}

.helpline-band__phone a:hover {
	text-decoration: underline;
}

.helpline-band__link {
	margin: 14px 0 0;
	font-size: 16px;
}

.helpline-band__link a {
	color: rgba(255, 255, 255, 0.82);
	text-decoration: underline;
	text-underline-offset: 3px;
}

.helpline-band__link a:hover {
	color: var(--color-white);
}

.callout-grid {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
	gap: 20px;
	margin-top: 24px;
}

.callout-grid--2up {
	grid-template-columns: repeat(2, 1fr);
}

@media (max-width: 767px) {
	.callout-grid--2up {
		grid-template-columns: 1fr;
	}
}

/* Q&A card (COVID News webinar recap) — the questions and their combined
   answer used to sit in two side-by-side callouts, which read oddly since
   one held two questions and the other a single merged answer. Now both
   live in one card: questions on top, answer below a divider. */
.qa-card {
	display: flex;
	flex-direction: column;
	gap: 20px;
}

.qa-card__questions {
	display: flex;
	flex-direction: column;
	gap: 12px;
}

.callout p.qa-card__q {
	display: flex;
	align-items: flex-start;
	gap: 10px;
	margin: 0;
	font-family: var(--font-display);
	font-weight: 500;
	font-size: 17px;
	line-height: 1.4;
	color: var(--color-ink);
}

.qa-card__q-mark {
	flex: none;
	display: flex;
	align-items: center;
	justify-content: center;
	width: 24px;
	height: 24px;
	margin-top: 2px;
	border-radius: 50%;
	background: var(--color-primary);
	color: var(--color-white);
	font-family: var(--font-label);
	font-weight: 700;
	font-size: 11px;
}

.qa-card__answer {
	padding-top: 18px;
	border-top: 1px solid rgba(31, 27, 27, 0.1);
}

.qa-card__answer p:last-child {
	margin-bottom: 0;
}

/* =========================================================
   Imagination Ball — 2025 recap, ported 1:1 from the client-
   approved reference layout (see "Imagination Ball 2025 Recap
   - Standalone.html") with this theme's own fonts/tokens in
   place of the reference's. Scoped to its own wrapper so the
   shared .about-intro__quote / .page-prose styles elsewhere
   are untouched. Photos are trewo_placeholder() slots until
   the client supplies the real ones.
   ========================================================= */
.ib-recap-2025__eyebrow {
	display: flex;
	align-items: center;
	gap: 10px;
	margin-bottom: 20px;
}

.ib-recap-2025__eyebrow-rule {
	width: 32px;
	height: 1.5px;
	background: var(--color-primary);
}

.ib-recap-2025__eyebrow span:last-child {
	font-family: var(--font-label);
	font-size: 13px;
	font-weight: 600;
	letter-spacing: 0.14em;
	text-transform: uppercase;
	color: var(--color-primary);
}

.ib-recap-2025__title {
	font-family: var(--font-display);
	font-weight: 500;
	text-transform: none;
	font-size: clamp(32px, 4.4vw, 52px);
	line-height: 1.15;
	max-width: 820px;
	margin: 0 0 24px;
	color: var(--color-ink);
}

.ib-recap-2025__lede {
	font-size: 18px;
	line-height: 1.7;
	max-width: 640px;
	color: var(--color-body);
	margin: 0 0 56px;
}

/* 3/2 matches the cheque-presentation photo's own ratio. At the previous
   16/8 the object-fit: cover crop took ~25% off the height and cut the
   heads off the two men at the outer edges of the group. */
.ib-recap-2025__hero {
	position: relative;
	width: 100%;
	aspect-ratio: 3 / 2;
	border-radius: 4px;
	overflow: hidden;
	margin-bottom: 80px;
}

.ib-recap-2025__hero .ph-media {
	height: 100%;
}

.ib-recap-2025__hero .ph-media--photo img {
	cursor: zoom-in;
}

.ib-recap-2025__hero-caption {
	position: absolute;
	left: 0;
	right: 0;
	bottom: 0;
	padding: 28px 36px;
	background: linear-gradient(0deg, rgba(20, 10, 10, 0.7), rgba(20, 10, 10, 0));
	pointer-events: none;
}

.ib-recap-2025__hero-caption strong {
	display: block;
	color: var(--color-white);
	font-family: var(--font-display);
	font-size: 24px;
	font-weight: 500;
	letter-spacing: 0.01em;
}

.ib-recap-2025__hero-caption span {
	display: block;
	color: rgba(255, 255, 255, 0.85);
	font-size: 14px;
	margin-top: 4px;
}

.ib-recap-2025__stats {
	background: var(--color-ink);
	border-radius: 4px;
	padding: 56px 40px;
	margin-bottom: 88px;
	display: grid;
	grid-template-columns: repeat(3, 1fr);
}

.ib-recap-2025__stat {
	text-align: center;
	padding: 0 24px;
	border-right: 1px solid rgba(255, 255, 255, 0.22);
}

.ib-recap-2025__stat--last {
	border-right: none;
}

.ib-recap-2025__stat-value {
	display: block;
	font-family: var(--font-display);
	font-weight: 500;
	font-size: clamp(34px, 4.4vw, 52px);
	color: var(--color-white);
	line-height: 1;
}

.ib-recap-2025__stat-label {
	display: block;
	margin-top: 14px;
	font-family: var(--font-label);
	font-weight: 600;
	font-size: 13px;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	color: rgba(255, 255, 255, 0.85);
}

.ib-recap-2025__block {
	margin-bottom: 96px;
}

.ib-recap-2025__block--honours {
	margin-bottom: 80px;
}

/* Highlights / Honours & Awards / Special Recognition — brand red, full
   bleed (this is its own <section>, not a div boxed inside the cream
   section's .container, so the red runs edge to edge). Client: the earlier
   white-card treatment read as form fields, so there's no card here at
   all — plain white text/icons directly on the red. Rather than a divider
   between every single item, a single thin rule separates each whole
   block (Highlights, Honours & Awards) from the next. */
.ib-recap-2025-accent {
	background: var(--color-primary);
	padding-block: clamp(48px, 7vw, 80px);
}

.ib-recap-2025-accent .ib-recap-2025__block {
	margin-bottom: 56px;
	padding-bottom: 56px;
	border-bottom: 2px solid rgb(255 255 255);
}

.ib-recap-2025-accent .ib-recap-2025__block:last-child {
	margin-bottom: 0;
	padding-bottom: 0;
	border-bottom: none;
}

.ib-recap-2025-accent .ib-recap__label {
	color: var(--color-white);
}

.ib-recap-2025-accent .ib-highlights__item {
	background: transparent;
	box-shadow: none;
	border-radius: 0;
	padding: 0;
}

.ib-recap-2025-accent .ib-highlights__item:hover {
	transform: none;
	box-shadow: none;
}

.ib-recap-2025-accent .ib-highlights__text {
	color: var(--color-white);
}

.ib-recap-2025-accent .honour-card {
	background: transparent;
	box-shadow: none;
	border-radius: 0;
	padding: 0;
}

.ib-recap-2025-accent .honour-card:hover {
	transform: none;
	box-shadow: none;
}

.ib-recap-2025-accent .honour-card__title {
	color: var(--color-white);
}

.ib-recap-2025-accent .honour-card__name {
	color: rgba(255, 255, 255, 0.75);
}

.ib-recap-2025-accent .callout {
	background: transparent;
	box-shadow: none;
	border-radius: 0;
	border-left: none;
	padding: 0;
}

.ib-recap-2025-accent .callout__title {
	color: var(--color-white);
}

.ib-recap-2025-accent .callout p:not(.callout__title) {
	font-weight: 600;
	color: rgba(255, 255, 255, 0.82);
}

.ib-recap__label {
	font-family: var(--font-display);
	font-weight: 500;
	text-transform: none;
	letter-spacing: normal;
	font-size: clamp(22px, 2.4vw, 28px);
	line-height: 1.2;
	color: var(--color-ink);
	margin-bottom: 28px;
}

/* Quote card + companion photo, side by side. */
.ib-quote-row {
	display: grid;
	grid-template-columns: 1.1fr 0.9fr;
	gap: 56px;
	align-items: stretch;
	margin-bottom: 96px;
}

.ib-quote-row__media {
	border-radius: 4px;
	overflow: hidden;
	min-height: 280px;
}

/* Reversed variant — image first (left), quote second (right); DOM order is
   swapped in the markup to match, so this just keeps the same column
   proportions (text side wider) rather than mirroring them, and moves the
   quote's accent rule to its outer edge instead of the one facing the photo. */
.ib-quote-row--reverse {
	grid-template-columns: 0.9fr 1.1fr;
}

.ib-quote-row--reverse .ib-quote {
	border-left: none;
	border-right: 5px solid var(--color-primary);
}

.ib-quote-row__media .ph-media {
	height: 100%;
}

.ib-quote-row__media img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
	cursor: zoom-in;
}

.ib-quote {
	max-width: none;
	margin: 0;
	padding: 44px 40px;
	background: var(--color-white);
	border-left: 5px solid var(--color-primary);
	border-radius: var(--radius-sm);
	box-shadow: 0 10px 30px rgba(31, 27, 27, 0.08);
	display: flex;
	flex-direction: column;
	justify-content: center;
}

.ib-quote__mark {
	display: block;
	font-family: var(--font-display);
	font-size: 64px;
	line-height: 0.6;
	color: var(--color-primary);
	margin-bottom: 12px;
}

.ib-quote p {
	margin: 0 0 28px;
	font-family: var(--font-display);
	font-weight: 300;
	font-size: 21px;
	font-style: italic;
	line-height: 1.7;
	color: var(--color-ink);
}

.ib-quote cite {
	display: block;
	font-style: normal;
}

.ib-quote cite strong {
	display: block;
	font-family: var(--font-display);
	font-weight: 600;
	font-size: 16px;
	font-style: normal;
	color: var(--color-ink);
}

.ib-quote cite span {
	display: block;
	margin-top: 4px;
	font-size: 14px;
	line-height: 1.5;
	color: var(--color-body);
}

.ib-highlights {
	display: grid;
	grid-template-columns: 1fr 1fr;
	gap: 28px 48px;
}

.ib-highlights__item {
	display: flex;
	align-items: flex-start;
	gap: 16px;
	background: var(--color-white);
	border-radius: var(--radius-sm);
	padding: 22px 24px;
	box-shadow: 0 1px 3px rgba(31, 27, 27, 0.06);
	transition: transform 0.25s ease, box-shadow 0.25s ease;
}

.ib-highlights__item:hover {
	transform: translateY(-2px);
	box-shadow: 0 12px 24px rgba(31, 27, 27, 0.1);
}

.ib-highlights__text {
	font-family: var(--font-display);
	font-weight: 500;
	font-size: 19px;
	line-height: 1.3;
	color: var(--color-ink);
}

.honour-grid {
	display: grid;
	grid-template-columns: repeat(2, 1fr);
	gap: 32px 40px;
}

.honour-card {
	padding: 32px 28px;
	background: var(--color-white);
	border-radius: var(--radius-sm);
	box-shadow: 0 1px 3px rgba(31, 27, 27, 0.06);
	transition: transform 0.25s ease, box-shadow 0.25s ease;
}

.honour-card:hover {
	transform: translateY(-3px);
	box-shadow: 0 14px 28px rgba(31, 27, 27, 0.12);
}

.honour-card__title {
	font-family: var(--font-display);
	font-weight: 500;
	font-size: 19px;
	line-height: 1.3;
	color: var(--color-ink);
	margin-bottom: 8px;
}

.honour-card__name {
	font-size: 14px;
	font-weight: 600;
	line-height: 1.5;
	color: var(--color-body);
}

/* Gallery teaser — 5 thumbnails from the shared "ib-2025" lightbox group,
   the last one overlaid with a "+N" count so every 2025 photo (previously
   reachable from the milestone wall) stays one click away here instead.
   Mosaic layout: the first photo fills a 2x2 block, the other four sit
   beside it as a 2x2 grid of their own — auto-placement handles the fill
   since the first item is the only one with an explicit span. */
.ib-gallery-grid {
	display: grid;
	grid-template-columns: repeat(4, 1fr);
	grid-template-rows: repeat(2, 1fr);
	aspect-ratio: 2 / 1;
	gap: 16px;
}

.ib-gallery-grid__item {
	position: relative;
	border: 1px solid rgba(181, 18, 27, 0.35);
	border-radius: var(--radius-sm);
	overflow: hidden;
}

.ib-gallery-grid__item:first-child {
	grid-column: span 2;
	grid-row: span 2;
}

.ib-gallery-grid__item img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
	cursor: zoom-in;
	transition: transform 0.35s ease;
}

.ib-gallery-grid__item:hover img {
	transform: scale(1.06);
}

.ib-gallery-grid__item--more::after {
	content: "";
	position: absolute;
	inset: 0;
	z-index: 1;
	background: rgba(20, 10, 10, 0.55);
	pointer-events: none;
}

.ib-gallery-grid__more {
	position: absolute;
	inset: 0;
	z-index: 2;
	display: flex;
	align-items: center;
	justify-content: center;
	font-family: var(--font-display);
	font-weight: 500;
	font-size: 34px;
	color: var(--color-white);
	pointer-events: none;
}

.ib-gallery-grid__hidden {
	display: none;
}

.ib-recap__closing {
	max-width: 820px;
	margin-inline: auto;
	padding-top: 56px;
	border-top: 1px solid rgba(31, 27, 27, 0.12);
	text-align: center;
}

.ib-recap__closing p {
	margin: 0 0 32px;
	font-size: 16px;
	line-height: 1.8;
	color: var(--color-body);
}

/* Client: Dr Sudi's message moved above the gallery and "played up to give
   more prominence (larger font size and center of page)". As a footnote under
   the photographs it opened with a divider rule and sat at body size; leading
   the section it needs neither — the rule would fence it off from the heading
   above, and body size reads as caption rather than as the founder speaking.
   So: no rule, wider measure, and the message set at statement size. */
.ib-recap__closing--lead {
	max-width: 940px;
	padding-top: 0;
	border-top: 0;
	margin-bottom: 64px;
}

.ib-recap__closing--lead p {
	font-family: var(--font-display);
	font-weight: 300;
	font-size: clamp(21px, 2.5vw, 30px);
	line-height: 1.45;
	color: var(--color-ink);
	margin-bottom: 26px;
}

.ib-recap__closing--lead .ib-recap__closing-next {
	font-size: clamp(18px, 2vw, 23px) !important;
	font-weight: 500;
	color: var(--color-primary) !important;
}

/* font-family and font-weight are restated here, not just in the base
   .ib-recap__closing-sig rule below: ".ib-recap__closing--lead p" is a class
   plus an element, so it outranks a lone class and was winning both. The
   sign-off was therefore rendering in the display serif at weight 300 — a
   light serif at 14px caps, which is why it looked washed out even after the
   colour went to ink. Two classes here beats it. */
.ib-recap__closing--lead .ib-recap__closing-sig {
	font-family: var(--font-label);
	font-weight: 600;
	font-size: 14px !important;
	color: var(--color-ink);
}

.ib-recap__closing-next {
	display: block;
	font-family: var(--font-display);
	font-weight: 500;
	font-size: 24px !important;
	line-height: 1.3;
	color: var(--color-ink) !important;
	margin-bottom: 12px !important;
	white-space: nowrap;
}

/* Ink rather than brand red (client: it was not reading clearly enough).
   Red at 13px uppercase with wide tracking is a lot of small coloured type
   on cream — the near-black gives it the contrast a sign-off needs while the
   label face and caps keep it distinct from the message above. */
.ib-recap__closing-sig {
	font-family: var(--font-label);
	font-weight: 600;
	font-size: 13px !important;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	color: var(--color-ink) !important;
	margin-bottom: 0 !important;
}

/* Gala Committee group portrait, sitting directly under the 2026 feature
   panel. Held inside the container and given clear air above it (client), so
   it reads as its own moment on the page rather than as the red panel's
   footer. Rounded to match the other framed photographs on this page. */
.ib-committee-shot {
	display: block;
	padding-top: clamp(56px, 7vw, 96px);
}

.ib-committee-shot img {
	width: 100%;
	height: auto;
	display: block;
	border-radius: var(--radius);
	cursor: pointer;
}

@media (max-width: 640px) {
	.ib-committee-shot {
		padding-top: 40px;
	}
}

/* Falls therapy video CTA, between the two Trillium quotes. An inline Vimeo
   player was blank here — the video is unlisted, and unlisted videos are
   embeddable only on domains listed in Vimeo's privacy settings — so this is
   a poster that opens the video on Vimeo, which works regardless.

   The whole frame is one link rather than an icon and a button inside a card:
   with a still behind it, anything less than the full frame being clickable
   reads as broken.

   Generous margin top AND bottom (client): it sits between two quote rows,
   and without real air on both sides it read as part of whichever quote it
   happened to be nearer. */
.ib-video-cta {
	position: relative;
	display: block;
	max-width: 820px;
	margin: clamp(56px, 6vw, 84px) auto;
	border-radius: var(--radius);
	overflow: hidden;
	box-shadow: 0 24px 56px -30px rgba(31, 27, 27, 0.5);
	transition: transform 0.25s ease, box-shadow 0.25s ease;
}

.ib-video-cta:hover,
.ib-video-cta:focus-visible {
	transform: translateY(-3px);
	box-shadow: 0 30px 64px -30px rgba(31, 27, 27, 0.6);
}

.ib-video-cta__poster {
	width: 100%;
	height: auto;
	display: block;
}

/* Scrim gradient rather than a flat wash: the still is bright and busy in the
   upper half, so the shade deepens towards the middle where the label sits
   while the photograph still reads at the edges. */
.ib-video-cta__overlay {
	position: absolute;
	inset: 0;
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: 16px;
	padding: 24px;
	text-align: center;
	color: var(--color-white);
	background: radial-gradient(
			ellipse 80% 70% at 50% 50%,
			rgba(26, 20, 22, 0.72) 0%,
			rgba(26, 20, 22, 0.36) 70%,
			rgba(26, 20, 22, 0.2) 100%
		);
}

.ib-video-cta__icon {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 72px;
	height: 72px;
	border-radius: 50%;
	background: var(--color-white);
	color: var(--color-primary);
	/* Nudged right by a quarter of the triangle's width — a play glyph centred
	   on its bounding box always looks left-of-centre in a circle. */
	padding-left: 5px;
	box-shadow: 0 8px 26px rgba(0, 0, 0, 0.35);
	transition: transform 0.25s ease, background-color 0.25s ease, color 0.25s ease;
}

.ib-video-cta:hover .ib-video-cta__icon,
.ib-video-cta:focus-visible .ib-video-cta__icon {
	transform: scale(1.08);
	background: var(--color-primary);
	color: var(--color-white);
}

.ib-video-cta__title {
	font-family: var(--font-display);
	font-weight: 400;
	font-size: clamp(20px, 2.4vw, 28px);
	line-height: 1.3;
	color: var(--color-white);
	text-shadow: 0 2px 12px rgba(0, 0, 0, 0.45);
}

/* Styled as a button but rendered as a span — it sits inside the anchor that
   wraps the whole poster, and an anchor cannot contain another anchor. */
.ib-video-cta__btn {
	display: inline-flex;
	align-items: center;
	padding: 12px 26px;
	border: 1px solid rgba(255, 255, 255, 0.7);
	border-radius: 999px;
	font-family: var(--font-label);
	font-weight: 600;
	font-size: 13px;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	transition: background-color 0.25s ease, color 0.25s ease, border-color 0.25s ease;
}

.ib-video-cta:hover .ib-video-cta__btn,
.ib-video-cta:focus-visible .ib-video-cta__btn {
	background: var(--color-white);
	border-color: var(--color-white);
	color: var(--color-primary);
}

@media (max-width: 640px) {
	.ib-video-cta {
		margin-block: 44px;
	}

	.ib-video-cta__overlay {
		gap: 12px;
	}

	.ib-video-cta__icon {
		width: 56px;
		height: 56px;
	}

	.ib-video-cta__btn {
		padding: 10px 20px;
		font-size: 12px;
	}
}

/* Reference tables (e.g. the messaging-privacy hierarchy on Other Resources) */
.table-scroll {
	overflow-x: auto;
	border: 1px solid rgba(31, 27, 27, 0.1);
	border-radius: var(--radius-sm);
}

.data-table {
	width: 100%;
	border-collapse: collapse;
	font-size: 14px;
}

.data-table th,
.data-table td {
	padding: 10px 16px;
	text-align: left;
	white-space: nowrap;
	border-bottom: 1px solid rgba(31, 27, 27, 0.08);
}

.data-table th {
	font-family: var(--font-label);
	font-weight: 700;
	font-size: 11.5px;
	letter-spacing: 0.05em;
	text-transform: uppercase;
	color: var(--color-white);
	background: var(--color-primary);
}

.data-table tr:last-child td {
	border-bottom: none;
}

.data-table tr:nth-child(even) td {
	background: var(--color-cream);
}

/* Full-width banner photo (Webinar Outreach Wing header/outreach shots) */
/* The client's team collage is 1600x933 (ratio 1.71), where the banner it
   replaced was a shallow 1230x478 strip (2.57). Left to fill the container
   it would stand ~930px tall on a wide screen and swallow the viewport, so
   it is capped at 1200px and centred — about 700px tall, still a banner
   rather than a full page of photograph, and never upscaled past native. */
.wow-banner {
	width: 100%;
	max-width: 1200px;
	margin-inline: auto;
	border-radius: 18px;
	display: block;
	height: auto;
}

.wow-gift-teaser__btn {
	margin-top: 28px;
}

/* People with photos */
.person__photo {
	flex: none;
	width: 108px;
	height: 108px;
	aspect-ratio: 1;
	object-fit: cover;
	object-position: top center;
	border-radius: 50%;
	display: block;
}

/* Founders highlight */
.founders {
	display: grid;
	grid-template-columns: repeat(2, 1fr);
	gap: 40px;
	margin-top: 40px;
}

.founder {
	display: flex;
	gap: 20px;
	align-items: center;
}

.founder__photo {
	flex: none;
	width: 108px;
	height: 108px;
	border-radius: 50%;
	object-fit: cover;
	object-position: top center;
	background: var(--color-primary-tint);
}

.founder__name {
	font-family: var(--font-display);
	font-weight: 400;
	font-size: 22px;
}

.founder__role {
	margin-top: 4px;
	font-family: var(--font-label);
	font-weight: 700;
	font-size: 12px;
	letter-spacing: 0.05em;
	text-transform: uppercase;
	color: var(--color-primary);
}

.founder__note {
	margin-top: 8px;
	font-size: 14px;
	line-height: 1.5;
	color: var(--color-body);
}

/* Wall of Fame grid */
.wof-grid {
	margin-top: 44px;
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	gap: 30px 28px;
}

.wof__photo {
	width: 100%;
	aspect-ratio: 4 / 3;
	object-fit: cover;
	border-radius: 14px;
	display: block;
	box-shadow: 0 12px 30px rgba(0, 0, 0, 0.1);
}

.wof__name {
	margin-top: 14px;
	font-family: var(--font-display);
	font-weight: 400;
	font-size: 20px;
	text-transform: capitalize;
}

/* ---------- AGM photo essay ------------------------------------------- */

/* Every photograph in this set is 2048x1152 and none may be cropped, so the
   tile is a fixed 16/9 box and width alone decides height. That constraint
   sets the grid's one rule: all tiles in a row carry the same span, so every
   row is flush. Rhythm comes from alternating the row TYPE — three-up, two-up,
   full-bleed — which changes height between rows while keeping it identical
   within them. (A mixed 7+5 row was the first attempt; two different heights
   side by side read as a bug, not as composition.)

   Tight gutters on purpose: at this density the grid reads as a contact sheet
   of one afternoon, which is what the set actually is. Wide gutters would make
   twenty-two frames read as twenty-two separate events. */
.agm-essay .agm-gallery {
	margin-top: 52px;
	display: grid;
	grid-template-columns: repeat(12, 1fr);
	gap: clamp(12px, 1.4vw, 20px);
}

/* ---------- AGM committee-chair letters ---------------------------------
   The letters run several hundred words each and more chairs are coming, so
   the page shows a portrait card per chair and opens the letter in the site's
   shared content modal. Stacking six full letters down the page was the
   alternative, and it read as a wall of text.
   ------------------------------------------------------------------------ */
.chair-letters {
	margin-top: 48px;
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(0, 240px));
	justify-content: center;
	gap: 32px;
}

.chair-letter {
	text-align: center;
}

.chair-letter__photo {
	width: 148px;
	height: 148px;
	margin-inline: auto;
	border-radius: 50%;
	object-fit: cover;
	object-position: top center;
	display: block;
	background: var(--color-grey-light);
}

/* Fallback for a chair whose photograph has not arrived — Narinderpal Singh
   at the time of writing. Same initials treatment the People page uses, so a
   missing photo leaves a considered gap rather than a broken image. */
.chair-letter__avatar {
	width: 148px;
	height: 148px;
	margin-inline: auto;
	border-radius: 50%;
	display: flex;
	align-items: center;
	justify-content: center;
	background: var(--color-primary-tint);
	color: var(--color-primary);
	font-family: var(--font-display);
	font-weight: 400;
	font-size: 42px;
}

.content-modal__body .chair-letter-modal__avatar {
	flex: none;
	width: 76px;
	height: 76px;
	border-radius: 50%;
	display: flex;
	align-items: center;
	justify-content: center;
	background: var(--color-primary-tint);
	color: var(--color-primary);
	font-family: var(--font-display);
	font-weight: 400;
	font-size: 24px;
}

.chair-letter__committee {
	margin-top: 18px;
	font-family: var(--font-label);
	font-weight: 600;
	font-size: 11.5px;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: var(--color-primary);
}

.chair-letter__name {
	margin-top: 8px;
	font-family: var(--font-display);
	font-weight: 400;
	font-size: 21px;
	line-height: 1.2;
	color: var(--color-ink);
}

.chair-letter__role {
	margin-top: 4px;
	font-size: 14px;
	color: var(--color-body);
}

.chair-letter__btn {
	margin-top: 16px;
	padding: 10px 22px;
	border: 1px solid var(--color-primary);
	border-radius: 999px;
	background: transparent;
	font-family: var(--font-label);
	font-weight: 600;
	font-size: 12px;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var(--color-primary);
	transition: background-color 0.2s ease, color 0.2s ease;
}

.chair-letter__btn:hover,
.chair-letter__btn:focus-visible {
	background: var(--color-primary);
	color: var(--color-white);
}

/* ---- Inside the modal ---- */
.content-modal__body .chair-letter-modal__head {
	display: flex;
	align-items: center;
	gap: 18px;
	padding-bottom: 20px;
	margin-bottom: 22px;
	border-bottom: 1px solid var(--color-grey-light);
}

.content-modal__body .chair-letter-modal__photo {
	flex: none;
	width: 76px;
	height: 76px;
	border-radius: 50%;
	object-fit: cover;
	object-position: top center;
}

.content-modal__body .chair-letter-modal__committee {
	font-family: var(--font-label);
	font-weight: 600;
	font-size: 11px;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: var(--color-primary);
	margin: 0;
}

.content-modal__body .chair-letter-modal__name {
	margin: 4px 0 0;
	font-family: var(--font-display);
	font-weight: 400;
	font-size: 22px;
	line-height: 1.2;
	color: var(--color-ink);
}

.content-modal__body .chair-letter-modal__role {
	margin: 2px 0 0;
	font-size: 14px;
	color: var(--color-body);
}

.content-modal__body .chair-letter-modal__salutation {
	font-weight: 600;
	color: var(--color-ink);
}

/* The HealthLIT letter opens on a standalone welcome line rather than diving
   into prose; set larger so it reads as the opening it is. */
.content-modal__body .chair-letter-modal__lead {
	font-family: var(--font-display);
	font-weight: 400;
	font-size: 20px;
	line-height: 1.4;
	color: var(--color-ink);
}

.content-modal__body .chair-letter-modal__signoff {
	margin-top: 26px;
	padding-top: 18px;
	border-top: 1px solid var(--color-grey-light);
}

.content-modal__body .chair-letter-modal__signoff strong {
	font-family: var(--font-display);
	font-weight: 400;
	font-size: 18px;
	color: var(--color-ink);
}

.content-modal__body .chair-letter-modal__signoff span {
	font-family: var(--font-label);
	font-weight: 600;
	font-size: 11.5px;
	letter-spacing: 0.05em;
	text-transform: uppercase;
	color: var(--color-primary);
}

@media (max-width: 640px) {
	/* Client: two per row on a phone. auto-fit with a 200px track could only
	   ever fit one column in a 327px container, so the chairs ran one per
	   screen and the section became a very long scroll. Explicit 1fr tracks
	   instead, with the card's contents stepped down to suit a ~155px column —
	   the names are long ("Narinderpal Singh") and the button label has to
	   stay on one line. */
	.chair-letters {
		grid-template-columns: repeat(2, minmax(0, 1fr));
		gap: 30px 14px;
	}

	.chair-letter__photo,
	.chair-letter__avatar {
		width: 112px;
		height: 112px;
	}

	.chair-letter__committee {
		margin-top: 14px;
		font-size: 10.5px;
		letter-spacing: 0.06em;
	}

	.chair-letter__name {
		font-size: 18px;
	}

	.chair-letter__role {
		font-size: 13px;
	}

	.chair-letter__btn {
		margin-top: 12px;
		padding: 9px 14px;
		font-size: 11px;
		letter-spacing: 0.04em;
	}
}


.agm-gallery__item {
	position: relative;
	grid-column: span var(--agm-span, 4);
	margin: 0;
	border-radius: 14px;
	overflow: hidden;
	/* Holds the row's height before the photograph decodes, so a lazy-loaded
	   tile can never shift the mosaic under someone mid-scroll. */
	aspect-ratio: 16 / 9;
	background: var(--color-sand);
	box-shadow: 0 1px 2px rgba(31, 27, 27, 0.06);
	transition: box-shadow 0.4s cubic-bezier(0.22, 0.61, 0.36, 1);
}

.agm-gallery__img {
	width: 100%;
	height: 100%;
	display: block;
	object-fit: cover;
	cursor: pointer;
	/* The source is 16/9 and so is the box, so cover scales without ever
	   cutting into the frame — it is here to defend against a future upload
	   at another ratio, not to crop these. */
	transition: transform 0.7s cubic-bezier(0.22, 0.61, 0.36, 1), filter 0.5s ease;
}

.agm-gallery__item:hover {
	box-shadow: 0 18px 40px -18px rgba(31, 27, 27, 0.45);
}

.agm-gallery__item:hover .agm-gallery__img {
	transform: scale(1.045);
}

/* A maroon hairline drawn inside the tile on hover — the brand's own accent
   doing the work a heavy border would do badly. Kept on a pseudo-element so it
   never affects layout. */
.agm-gallery__item::after {
	content: "";
	position: absolute;
	inset: 0;
	border: 1px solid rgba(181, 18, 27, 0);
	border-radius: inherit;
	pointer-events: none;
	transition: border-color 0.4s ease;
}

.agm-gallery__item:hover::after {
	border-color: rgba(181, 18, 27, 0.55);
}

/* Affordance: the photographs open in the lightbox, and nothing else on the
   tile says so. Appears on hover, and on keyboard focus so it is not a
   pointer-only cue. */
.agm-gallery__zoom {
	position: absolute;
	top: 12px;
	right: 12px;
	width: 34px;
	height: 34px;
	display: grid;
	place-items: center;
	border-radius: 50%;
	background: rgba(255, 255, 255, 0.92);
	color: var(--color-primary);
	opacity: 0;
	transform: translateY(-6px) scale(0.9);
	pointer-events: none;
	transition: opacity 0.35s ease, transform 0.35s cubic-bezier(0.22, 0.61, 0.36, 1);
}

.agm-gallery__item:hover .agm-gallery__zoom,
.agm-gallery__img:focus-visible ~ .agm-gallery__zoom {
	opacity: 1;
	transform: translateY(0) scale(1);
}

.agm-gallery__img:focus-visible {
	outline: 3px solid var(--color-primary);
	outline-offset: -3px;
}

/* Two breakpoints, because the 12-column spans stop meaning anything once the
   tiles get narrow: a span-4 frame on a tablet is too small to read faces in.
   Tablet drops to a two-up with the feature frames still full-bleed; phones go
   single file, where 16/9 is the natural shape anyway. */
@media (max-width: 1023px) {
	.agm-essay .agm-gallery {
		grid-template-columns: repeat(2, 1fr);
	}

	.agm-gallery__item {
		grid-column: span 1;
	}

	.agm-gallery__item--wide {
		grid-column: span 2;
	}
}

@media (max-width: 600px) {
	.agm-essay .agm-gallery {
		grid-template-columns: 1fr;
		margin-top: 36px;
	}

	.agm-gallery__item,
	.agm-gallery__item--wide {
		grid-column: span 1;
	}

	/* Touch has no hover, so the affordance is always on. */
	.agm-gallery__zoom {
		opacity: 1;
		transform: none;
	}
}

/* AGM cards — three-up rather than the full-width horizontal bands these
   started as. Stacked bands gave each meeting a whole screen-width row for
   one date and one title, which read as padding; in a grid they read as what
   they are, a short list of records you scan rather than a feature you dwell
   on. Three rather than two (client) now that there are three meetings on
   record. */
.agm-list {
	margin-top: 44px;
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	gap: 32px;
}

.agm-card {
	display: flex;
	flex-direction: column;
	background: var(--color-cream);
	border-radius: 18px;
	overflow: hidden;
	transition: transform 0.4s cubic-bezier(0.22, 0.61, 0.36, 1), box-shadow 0.4s ease;
}

.agm-card:hover {
	transform: translateY(-6px);
	box-shadow: 0 22px 44px -22px rgba(31, 27, 27, 0.42);
}

/* These two archive photos are a square and a portrait. The ratio is fixed
   here so the two cards stay the same height, and the image is contained
   rather than cropped — each poster is shown whole, letterboxed against white
   the way a framed print is matted. */
.agm-card__media {
	aspect-ratio: 4 / 3;
	overflow: hidden;
	background: var(--color-white);
}

/* Now a lightbox trigger (client: open on click) — cursor + focus ring make
   that discoverable the same way the photo essay's mosaic tiles do. */
.agm-card__media img {
	width: 100%;
	height: 100%;
	object-fit: contain;
	object-position: center;
	display: block;
	cursor: pointer;
	transition: transform 0.7s cubic-bezier(0.22, 0.61, 0.36, 1);
}

.agm-card__media img:focus-visible {
	outline: 3px solid var(--color-primary);
	outline-offset: -3px;
}

.agm-card:hover .agm-card__media img {
	transform: scale(1.05);
}

.agm-card__body {
	padding: 28px 32px 32px;
	border-top: 3px solid var(--color-primary);
}

.agm-card__date {
	font-family: var(--font-label);
	font-weight: 700;
	font-size: 13px;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var(--color-primary);
}

.agm-card__title {
	font-family: var(--font-display);
	font-weight: 300;
	text-transform: capitalize;
	font-size: clamp(26px, 3vw, 34px);
	line-height: 1.1;
	margin-top: 8px;
}

/* Stats panel (WOW) */
.stats-panel {
	display: grid;
	gap: 2px;
	background: var(--color-grey-light);
	border-radius: 16px;
	overflow: hidden;
}

.stats-panel__item {
	background: var(--color-cream);
	padding: 26px 28px;
}

.stats-panel__number {
	display: block;
	font-family: var(--font-display);
	font-weight: 400;
	font-size: clamp(30px, 4vw, 44px);
	color: var(--color-primary);
	line-height: 1;
}

.stats-panel__label {
	display: block;
	margin-top: 8px;
	font-family: var(--font-label);
	font-weight: 700;
	font-size: 13px;
	letter-spacing: 0.04em;
	text-transform: uppercase;
	color: var(--color-body);
}

/* Testimonials */
/* Testimonial slider — one quote at a time. Slides are shown/hidden with
   display rather than crossfaded via absolute position, so the card's
   height always matches whichever quote is active instead of a fixed
   height sized to the longest one. */
.testimonial-slider {
	display: flex;
	align-items: center;
	gap: 20px;
	margin-top: 40px;
}

.testimonial-slider__arrow {
	margin-top: 0;
	background: var(--color-primary);
	border-color: var(--color-primary);
	color: var(--color-white);
}

.testimonial-slider__arrow:hover {
	background: var(--color-primary-dark);
	border-color: var(--color-primary-dark);
}

/* Client: these were hard to pick out. Unlike the "What People Are Saying"
   slider further down the page, this one sits over a photograph (only a 28%
   dark wash between the arrow and the image), so a plain red disc lands on
   whatever tone happens to be behind it. A white ring gives it a constant
   edge regardless of the photo, and the shadow lifts it off the background;
   the disc grows a little so the ring has room to read at a glance. Scoped
   to .wow-feedback — the other slider is on flat white, where a white ring
   would simply disappear. */
.wow-feedback .testimonial-slider__arrow {
	width: 48px;
	height: 48px;
	border-width: 2px;
	border-color: var(--color-white);
	box-shadow: 0 4px 18px rgba(31, 27, 27, 0.4);
}

/* The chevron itself, scaled up from the shared 16px and drawn a touch
   heavier — the markup carries width/height as SVG attributes, which CSS
   overrides, so the icon size is set here rather than per template. */
.wow-feedback .testimonial-slider__arrow svg {
	width: 24px;
	height: 24px;
}

.wow-feedback .testimonial-slider__arrow svg path {
	stroke-width: 2.4;
}

.wow-feedback .testimonial-slider__arrow:hover {
	border-color: var(--color-white);
	box-shadow: 0 6px 22px rgba(31, 27, 27, 0.5);
}

.testimonial-slider__viewport {
	position: relative;
	flex: 1;
	min-width: 0;
	overflow: hidden;
}

.testimonial-slider__dots {
	display: flex;
	align-items: center;
	justify-content: center;
	gap: 10px;
	margin-top: 28px;
}

.testimonial {
	display: none;
	flex-direction: column;
	align-items: center;
	margin: 0 auto;
	max-width: 860px;
	padding: 48px 56px;
	background: var(--color-white);
	border: 1px solid var(--color-grey-light);
	border-radius: 20px;
	text-align: center;
}

.testimonial.is-active {
	display: flex;
}

.testimonial__photo {
	width: 72px;
	height: 72px;
	border-radius: 50%;
	object-fit: cover;
	margin-bottom: 24px;
	background: var(--color-primary-tint);
}

.testimonial__quote {
	margin: 0;
	max-width: 680px;
	font-family: var(--font-display);
	font-weight: 300;
	font-size: clamp(18px, 2.1vw, 23px);
	font-style: italic;
	line-height: 1.6;
	color: var(--color-ink);
}

.testimonial__topic {
	margin-top: 24px;
	font-family: var(--font-label);
	font-weight: 700;
	font-size: 12px;
	letter-spacing: 0.05em;
	text-transform: uppercase;
	color: var(--color-primary);
}

/* Feedback section — same background-photo technique as .donate-cta__bg.
   .section--ripple (already on the section) supplies the relative/overflow/
   isolation this depends on. The eyebrow/title sit directly on the photo
   (unlike the testimonial cards below them, which carry their own white
   background), so they go white-on-scrim rather than the usual dark ink. */
.wow-feedback__bg {
	position: absolute;
	inset: 0;
	z-index: -2;
}

.wow-feedback__bg img {
	position: absolute;
	top: -15%;
	left: 0;
	width: 100%;
	height: 130%;
	object-fit: cover;
	object-position: center;
	display: block;
}

.wow-feedback__bg::after {
	content: "";
	position: absolute;
	inset: 0;
	background: rgba(31, 27, 27, 0.28);
}

.wow-feedback .eyebrow,
.wow-feedback .section__title {
	text-shadow: 0 1px 3px rgba(0, 0, 0, 0.35);
}

.wow-feedback .section__title {
	color: var(--color-white);
}

/* Generic photo grid */
.photo-grid {
	display: grid;
	grid-template-columns: repeat(2, 1fr);
	gap: 20px;
}

.photo-grid img {
	width: 100%;
	aspect-ratio: 4 / 3;
	object-fit: cover;
	border-radius: 14px;
	display: block;
}

.photo-grid--gallery {
	grid-template-columns: repeat(3, 1fr);
	gap: 16px;
}

.photo-grid--gallery img {
	aspect-ratio: 1;
}

/* Year strip (gala history) */
.year-strip {
	margin-top: 40px;
	display: flex;
	flex-wrap: wrap;
	gap: 14px;
}

.year-chip {
	flex: 1 1 140px;
	padding: 18px 20px;
	background: var(--color-cream);
	border-radius: 12px;
}

.year-chip__year {
	display: block;
	font-family: var(--font-display);
	font-weight: 400;
	font-size: 26px;
	color: var(--color-primary);
}

.year-chip__note {
	display: block;
	margin-top: 4px;
	font-size: 13px;
	line-height: 1.4;
	color: var(--color-body);
}

/* Link cards (upcoming events / cross-links) */
.link-cards {
	margin-top: 40px;
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	gap: 24px;
}

.link-card {
	display: flex;
	flex-direction: column;
	padding: 30px 28px;
	background: var(--color-cream);
	border: 1px solid transparent;
	border-radius: 16px;
	transition: border-color 0.2s ease, transform 0.2s ease;
}

.link-card:hover {
	border-color: var(--color-primary);
	transform: translateY(-3px);
}

.link-card__eyebrow {
	font-family: var(--font-label);
	font-weight: 700;
	font-size: 12px;
	letter-spacing: 0.05em;
	text-transform: uppercase;
	color: var(--color-primary);
}

.link-card__title {
	margin-top: 10px;
	font-family: var(--font-display);
	font-weight: 400;
	font-size: 24px;
	line-height: 1.15;
	color: var(--color-ink);
}

.link-card__meta {
	margin-top: 12px;
	font-size: 14px;
	line-height: 1.5;
	color: var(--color-body);
}

.link-card__more {
	margin-top: 18px;
	font-family: var(--font-label);
	font-weight: 700;
	font-size: 13px;
	letter-spacing: 0.04em;
	text-transform: uppercase;
	color: var(--color-primary);
}

/* Flyer/photo strips (About story archive). Flyers keep their natural
   aspect ratio (fixed height, auto width, no crop) since they carry text
   that a crop would cut off. */
.story-strip {
	margin-top: 18px;
	display: flex;
	flex-wrap: wrap;
	gap: 14px;
}

.story-strip img {
	height: 220px;
	width: auto;
	max-width: 100%;
	border-radius: 10px;
	box-shadow: 0 10px 24px rgba(0, 0, 0, 0.1);
	display: block;
}

/* About opener — founders photo beside the tagline + inception block */
.about-opener__inception {
	display: flex;
	align-items: center;
	gap: 24px;
	max-width: 900px;
	margin: 50px auto;
}

/* Client-supplied gold plaque graphic, replacing the plain circled "2006"
   text marker. Decorative only (the heading right beside it already reads
   "Inception 2006"), so it stays aria-hidden with empty alt exactly like the
   span it replaces. Sized by height with width left to the image's own
   3:2 aspect ratio, and lifted off the page with a soft shadow so it reads as
   a mounted plate rather than a flat image sitting in the flex row. */
.about-opener__plaque {
	flex: none;
	display: block;
	height: 150px;
	width: auto;
	filter: drop-shadow(0 10px 18px rgba(31, 27, 27, 0.22));
}

.about-opener__subtitle {
	font-family: var(--font-label);
	font-weight: 700;
	font-size: 13px;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var(--color-primary);
}

.about-opener__inception p {
	margin: 8px 0 0;
	font-size: 16px;
	line-height: 1.6;
	color: var(--color-body);
}

.about-opener__photo {
	position: relative;
	margin-top: 36px;
}

.about-opener__photo img {
	position: relative;
	width: 100%;
	border-radius: 16px;
	display: block;
	box-shadow: 0 18px 40px rgba(0, 0, 0, 0.14);
}

/* Mission band (dark, ripple accent, editorial columns) */
.mission-band {
	position: relative;
	overflow: hidden;
	isolation: isolate;
}

.mission-band__statement {
	font-family: var(--font-display);
	font-weight: 300;
	font-size: clamp(24px, 3.2vw, 40px);
	line-height: 1.3;
	color: var(--color-white);
	margin: 20px auto 0;
	text-align: center;
	max-width: 900px;
}

.mission-band__cols {
	margin-top: 56px;
	display: grid;
	/* auto-fit, not repeat(3, …): the paragraphs are editable now, and two or
	   four should lay out as evenly as three. Identical to the old rule at
	   three. */
	grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
	gap: 36px;
}

/* Client: this was too hard to read — up from 15.5px. */
.mission-band__cols p {
	margin: 0;
	font-size: 18px;
	line-height: 1.6;
	color: rgba(255, 255, 255, 0.85);
	padding-top: 20px;
	border-top: 2px solid var(--color-primary);
}

.mission-band__quote {
	margin: 56px auto 0;
	max-width: 760px;
	text-align: center;
	font-family: var(--font-display);
	font-weight: 300;
	font-style: italic;
	font-size: clamp(20px, 2.4vw, 28px);
	line-height: 1.4;
	color: var(--color-white);
}

.mission-band__cite {
	margin: 16px auto 0;
	text-align: center;
	font-family: var(--font-label);
	font-weight: 600;
	font-size: 13px;
	letter-spacing: 0.05em;
	text-transform: uppercase;
	color: rgba(255, 255, 255, 0.7);
}

/* Story archive section + timeline variant */
.story-archive {
	position: relative;
	overflow: hidden;
	isolation: isolate;
	background: var(--color-primary);
	color: var(--color-white);
}

/* Everything inside this section was drawn in primary red on cream — on a red
   ground all of it would vanish, so the whole timeline inverts to white. */
.story-archive .eyebrow,
.story-archive .section__title--statement {
	color: var(--color-white);
}

/* The horizontal rail behind the row, and its two end markers. */
.story-archive .together-timeline__item::before {
	background: rgba(255, 255, 255, 0.45);
}

.story-archive .together-timeline__endpoint,
.story-archive .together-timeline__dot {
	background: var(--color-white);
	/* Ring matches the section colour so it masks the rail passing behind,
	   the same job the cream ring did on the light background. */
	box-shadow: 0 0 0 4px var(--color-primary);
}

.story-archive .together-timeline__year {
	color: var(--color-white);
}

.story-archive .together-timeline__text {
	max-width: 250px;
	color: rgba(255, 255, 255, 0.92);
}

/* Cream ring reads well against the red; the outer hairline was primary red
   and is now invisible, so it becomes a soft white instead. */
.story-archive .together-timeline__photo {
	box-shadow: 0 0 0 1px rgba(255, 255, 255, 0.35);
}

.story-archive .together-timeline__photo.ph-media--photo:hover,
.story-archive .together-timeline__photo.ph-media--photo:focus-visible {
	box-shadow:
		0 0 0 1px rgba(255, 255, 255, 0.55),
		0 14px 28px -10px rgba(26, 20, 22, 0.5);
}

.story-archive .carousel-arrow--dark {
	border-color: rgba(255, 255, 255, 0.4);
	color: var(--color-white);
}

.story-archive .carousel-arrow--dark:hover {
	background: rgba(255, 255, 255, 0.14);
	border-color: var(--color-white);
}

/* "Together We Can" programme timeline — 19 milestones is a long way to
   scroll as one straight vertical list, so this is a horizontal scroll-strip
   (arrow controls plus native drag/trackpad/scroll-snap) at every width.
   Phones scroll it by touch and lose the arrows; see the 767px block below. */
.together-timeline {
	/* The rail sits at the top of the track's padding, and the two endpoint
	   dots are positioned against the viewport OUTSIDE that track — so both
	   have to use the same figure or the dots drift off the line. One token,
	   overridden per breakpoint, keeps them in step. */
	--tl-pad-top: 44px;
	position: relative;
	display: flex;
	align-items: center;
	gap: 12px;
	/* 56px was carried by the "Together We Can" intro block that used to sit
	   between this and the section heading; that block is gone (client), so
	   the timeline takes the spacing on itself. */
	margin-top: 64px;
}

.together-timeline__arrow {
	position: relative;
	z-index: 2;
}

/* Non-scrolling box the same size as the track, holding the start/end dots.
   It exists purely so those dots have a containing block that stays put —
   see .together-timeline__endpoint below. */
.together-timeline__viewport {
	position: relative;
	flex: 1;
	min-width: 0;
}

.together-timeline__track {
	position: relative;
	width: 100%;
	overflow-x: auto;
	overflow-y: hidden;
	scroll-snap-type: x proximity;
	scrollbar-width: none;
	padding: var(--tl-pad-top) 0 28px;
	cursor: grab;
}

.together-timeline__track::-webkit-scrollbar {
	display: none;
}

/* Mouse click-drag scrolling (see main.js) — disables snap and text
   selection mid-drag so the strip tracks the pointer exactly. */
.together-timeline__track.is-dragging {
	cursor: grabbing;
	scroll-snap-type: none;
	user-select: none;
}

/* Desktop/tablet: hidden. A single element spanning "the whole rail" can't
   reliably measure the true scrollable width here — flex items with
   flex-shrink:0 overflow their container without ever growing its own box,
   so left:0/right:0 only ever spans the initially-visible screen, not all
   19 items. Each item draws its own full-width segment instead (below);
   since items sit edge-to-edge those segments join into one continuous
   line regardless of how many there are. Mobile's vertical line is a
   genuinely different, well-defined case (a normal block stack has a real
   total height), so it reuses this element — see the 767px override. */
.together-timeline__rail {
	display: none;
}

.together-timeline__list {
	position: relative;
	display: flex;
	margin: 0;
	padding: 0;
	list-style: none;
}

/* Exactly 4 per view (25% each, no explicit gap — spacing lives in each
   item's own padding-inline instead) so the photos can run bigger. */
.together-timeline__item {
	position: relative;
	flex: 0 0 25%;
	display: flex;
	flex-direction: column;
	align-items: center;
	text-align: center;
	padding-inline: 16px;
	scroll-snap-align: start;
}

.together-timeline__item::before {
	content: "";
	position: absolute;
	left: 0;
	right: 0;
	top: 5px;
	height: 1px;
	background: var(--color-primary);
}

/* Permanent start/end markers, pinned to the visible ends of the strip.
   These live in .together-timeline__viewport, OUTSIDE the scroll container.
   That placement is the whole fix: position:absolute inside an element with
   overflow:auto is still laid out against that element's content box, so it
   travels with the content as it scrolls — both dots drifted away with the
   strip. (An earlier attempt used position:sticky on a flex item inside the
   scrolling row, which failed for a different reason: sticky next to
   non-shrinking flex siblings loses its stuck range.) A sibling of the
   scroller has neither problem — it was never inside the scrolled box.

   top follows --tl-pad-top, the track's own top padding, which is what puts
   these dots on the same line as the rail. */
.together-timeline__endpoint {
	position: absolute;
	z-index: 3;
	top: var(--tl-pad-top);
	width: 10px;
	height: 10px;
	border-radius: 50%;
	background: var(--color-primary);
	box-shadow: 0 0 0 4px var(--color-cream);
}

.together-timeline__endpoint--start {
	left: 0;
}

.together-timeline__endpoint--end {
	right: 0;
}

/* Absolutely positioned (floats above the dot rather than sitting in normal
   flow) so the dot is always the item's first in-flow element — whether or
   not a row has a year, the dot lands on the rail at the exact same spot. */
.together-timeline__year {
	position: absolute;
	top: -26px;
	left: 0;
	right: 0;
	text-align: center;
	font-family: var(--font-label);
	font-weight: 700;
	font-size: 12px;
	letter-spacing: 0.02em;
	color: var(--color-primary);
	white-space: nowrap;
}

.together-timeline__dot {
	flex: none;
	width: 10px;
	height: 10px;
	margin-bottom: 14px;
	border-radius: 50%;
	background: var(--color-primary);
	box-shadow: 0 0 0 4px var(--color-cream);
}

.together-timeline__photo {
	flex: none;
	width: 168px;
	height: 168px;
	margin-bottom: 16px;
	border-radius: 50%;
	border: 3px solid var(--color-cream);
	box-shadow: 0 0 0 1px var(--color-primary);
}

/* Only real photos are lightbox triggers (placeholders aren't clickable),
   so the pointer cursor + hover scale are scoped to .ph-media--photo. */
.together-timeline__photo.ph-media--photo {
	cursor: pointer;
	transition: transform 0.25s ease, box-shadow 0.25s ease;
}

/* These are 1:1 circles cropping mostly landscape/portrait source photos, and
   the centre crop was cutting people's heads off (client flagged it on the
   2023 Health Literacy shot). Biasing to the top keeps faces in frame, since
   that is where they sit in almost every photo.

   Scoped to the timeline deliberately — .ph-media--photo img is shared by
   every photo on the site. */
.together-timeline__photo.ph-media--photo img {
	object-position: top center;
}

.together-timeline__photo.ph-media--photo:hover,
.together-timeline__photo.ph-media--photo:focus-visible {
	transform: scale(1.08);
	box-shadow: 0 0 0 1px var(--color-primary), 0 14px 28px -10px rgba(31, 27, 27, 0.4);
}

.together-timeline__text {
	margin: 0;
	font-size: 14px;
	line-height: 1.5;
	color: var(--color-body);
}

@media (max-width: 1023px) {
	.together-timeline__item {
		flex-basis: 33.333%;
	}

	.together-timeline__photo {
		width: 140px;
		height: 140px;
	}
}

@media (max-width: 767px) {
	/* Client: the strip stays horizontal on phones. It used to unroll into a
	   vertical rail here, which turned 19 milestones into the longest scroll
	   on the page; the track already scrolls natively by touch, so a phone
	   swipes through it exactly as a trackpad does on desktop. Two milestones
	   sit in view at a time, the second one half-shown so it is obvious there
	   is more to the right. */
	.together-timeline {
		--tl-pad-top: 38px;
	}

	/* Client: the arrows stay. They come out of the flex row and sit over the
	   strip instead, so the milestones still get the container's full width —
	   in a 375px row two 44px buttons and their gaps would have taken nearly a
	   third of it. Centred on the photographs: the track's top padding, plus
	   the 10px rail dot and its 14px margin, plus half a 128px photo. */
	.together-timeline__arrow {
		position: absolute;
		z-index: 3;
		top: calc(var(--tl-pad-top) + 24px + 64px);
		transform: translateY(-50%);
		/* Overlaid, so the thin outline the section gives these buttons is no
		   longer enough — half the time they sit over a photograph. A dark
		   disc behind them reads against both the red ground and the pictures. */
		background: rgba(26, 20, 22, 0.6);
		border-color: rgba(255, 255, 255, 0.65);
	}

	.together-timeline__arrow--prev {
		left: 0;
	}

	.together-timeline__arrow--next {
		right: 0;
	}

	.together-timeline__track {
		padding-bottom: 24px;
	}

	.together-timeline__item {
		flex-basis: 62%;
		padding-inline: 10px;
	}

	.together-timeline__photo {
		width: 128px;
		height: 128px;
		margin-bottom: 12px;
	}

	.together-timeline__text {
		font-size: 13px;
	}

	.story-archive .together-timeline__text {
		max-width: none;
	}
}

/* Milestone wall — the dated archive as a compact card grid (newest first).
   Thumbnails crop to a uniform tile; the full, uncropped image is one click
   away in the lightbox, which also pages through a card's extra photos. */
.milestones {
	margin-top: 40px;
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	gap: 36px 28px;
}

.milestone__thumb {
	position: relative;
	overflow: hidden;
	border-radius: 14px;
	box-shadow: 0 10px 26px rgba(0, 0, 0, 0.1);
}

.milestone__img {
	width: 100%;
	aspect-ratio: 4 / 3;
	object-fit: contain;
	display: block;
	cursor: zoom-in;
	transition: transform 0.45s ease;
}

.milestone__thumb::after {
	content: "";
	position: absolute;
	inset: 0;
	background: linear-gradient(180deg, transparent 45%, rgba(136, 14, 20, 0.55) 100%);
	opacity: 0;
	transition: opacity 0.3s ease;
	pointer-events: none;
}

.milestone__thumb:hover .milestone__img {
	transform: scale(1.06);
}

.milestone__thumb:hover::after {
	opacity: 1;
}

.milestone__year {
	position: absolute;
	top: 12px;
	left: 12px;
	z-index: 1;
	padding: 5px 12px;
	border-radius: 999px;
	background: var(--color-primary);
	color: var(--color-white);
	font-family: var(--font-label);
	font-weight: 700;
	font-size: 13px;
	letter-spacing: 0.04em;
	pointer-events: none;
}

.milestone__count {
	position: absolute;
	bottom: 12px;
	right: 12px;
	z-index: 1;
	padding: 5px 12px;
	border-radius: 999px;
	background: rgba(255, 255, 255, 0.92);
	color: var(--color-primary);
	font-family: var(--font-label);
	font-weight: 700;
	font-size: 12px;
	letter-spacing: 0.03em;
	pointer-events: none;
}

.milestone__zoom {
	position: absolute;
	top: 50%;
	left: 50%;
	transform: translate(-50%, -50%) scale(0.7);
	z-index: 1;
	display: flex;
	align-items: center;
	justify-content: center;
	width: 48px;
	height: 48px;
	border-radius: 50%;
	background: rgba(255, 255, 255, 0.92);
	color: var(--color-primary);
	opacity: 0;
	transition: opacity 0.3s ease, transform 0.3s ease;
	pointer-events: none;
}

.milestone__thumb:hover .milestone__zoom {
	opacity: 1;
	transform: translate(-50%, -50%) scale(1);
}

.milestone__hidden {
	display: none;
}

.milestone__title {
	margin-top: 14px;
	font-family: var(--font-display);
	font-weight: 400;
	font-size: 19px;
	line-height: 1.25;
	text-transform: capitalize;
}

/* Imagination Ball "Through the Years" — the milestone wall sits inside the
   page's dark/maroon band instead of a plain light section. Contain-fit
   thumbnails (posters with their own white background) need a card behind
   them here or the letterboxing would show raw maroon; everything else
   (year pill, hover zoom, lightbox) is unchanged. */
.milestones-band {
	position: relative;
	overflow: hidden;
	isolation: isolate;
}

.section--dark .milestone__thumb {
	background: var(--color-cream);
	padding: 10px;
	transition: transform 0.35s ease, box-shadow 0.35s ease;
}

.section--dark .milestone:hover .milestone__thumb {
	transform: translateY(-6px);
	box-shadow: 0 26px 50px -14px rgba(0, 0, 0, 0.5);
}

.section--dark .milestone__title {
	color: rgba(255, 255, 255, 0.92);
}

/* Decorative year-span rail under the section heading — a lightweight
   stand-in for a literal cross-card timeline, which can't stay aligned
   once the grid below wraps onto more than one row. */
.milestones-span {
	display: flex;
	align-items: center;
	gap: 16px;
	max-width: 320px;
	margin-top: 28px;
}

.milestones-span__year {
	font-family: var(--font-label);
	font-weight: 700;
	font-size: 13px;
	letter-spacing: 0.06em;
	color: var(--color-white);
	opacity: 0.85;
}

.milestones-span__line {
	position: relative;
	flex: 1;
	height: 1px;
	background: linear-gradient(90deg, rgba(255, 255, 255, 0.06), rgba(255, 255, 255, 0.5), rgba(255, 255, 255, 0.06));
}

.milestones-span__line::before,
.milestones-span__line::after {
	content: "";
	position: absolute;
	top: 50%;
	width: 6px;
	height: 6px;
	border-radius: 50%;
	background: var(--color-white);
	transform: translateY(-50%);
}

.milestones-span__line::before {
	left: 0;
}

.milestones-span__line::after {
	right: 0;
}

/* 2010 — the founding gala — called out as a full-width card instead of
   blending into the 3-up grid, with the poster shown larger alongside the
   existing "The first Imagination Gala" heading. */
.milestone--origin {
	grid-column: 1 / -1;
	display: grid;
	grid-template-columns: minmax(0, 340px) 1fr;
	gap: 32px;
	align-items: center;
	padding: 20px;
	border-radius: 20px;
	background: rgba(255, 255, 255, 0.05);
	border: 1px solid rgba(255, 255, 255, 0.2);
}

.milestone--origin .milestone__thumb {
	border-radius: 12px;
}

.milestone--origin__body {
	display: flex;
	flex-direction: column;
	gap: 14px;
}

.milestone--origin__icon {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 44px;
	height: 44px;
	border-radius: 50%;
	background: rgba(255, 255, 255, 0.12);
	color: var(--color-white);
}

.milestone--origin .milestone__title {
	margin-top: 0;
	font-size: clamp(24px, 2.8vw, 34px);
	font-weight: 300;
}

/* =========================================================
   Responsive
   ========================================================= */
@media (max-width: 1023px) {
	.about-intro__grid,
	.roofs-vm-grid {
		grid-template-columns: 1fr;
		gap: 28px;
	}

	.outreach-map__stats {
		grid-template-columns: repeat(2, 1fr);
	}

	.programs-grid {
		grid-template-columns: repeat(2, 1fr);
		gap: 40px 24px;
	}

	.wow-tight-grid {
		grid-template-columns: repeat(4, 1fr);
	}

	.wow-video-grid {
		grid-template-columns: repeat(2, 1fr);
	}

	.wow-archive-grid {
		grid-template-columns: repeat(3, 1fr);
	}

	.people-grid {
		grid-template-columns: 1fr;
	}

	.creative-gallery {
		grid-template-columns: repeat(3, 1fr);
	}

	.media-row {
		grid-template-columns: 1fr;
		gap: 32px;
	}

	.media-row--premium {
		gap: 28px;
	}

	.milestones {
		grid-template-columns: repeat(2, 1fr);
	}

	.mission-band__cols {
		grid-template-columns: 1fr;
		gap: 20px;
	}

	.media-row--reverse .media-row__media {
		order: 0;
	}

	.founders {
		grid-template-columns: 1fr;
		gap: 28px;
	}

	.wof-grid {
		grid-template-columns: repeat(2, 1fr);
	}

	/* Two-up cards go single file below the tablet breakpoint — side by side
	   they would leave the title wrapping over three or four lines. */
	.agm-list {
		grid-template-columns: 1fr;
		gap: 24px;
	}

	.agm-card__body {
		padding: 24px 24px 28px;
	}

	.testimonial {
		padding: 40px 36px;
	}

	.photo-grid--gallery {
		grid-template-columns: repeat(3, 1fr);
	}

	.imagination-feature {
		grid-template-columns: 1fr;
		min-height: 0;
	}

	/* Client: once the feature stacks, the photograph runs at its natural
	   height rather than being cropped into a fixed band. The desktop rule
	   sets height:100% because the photo has to match the height of the red
	   panel beside it; stacked there is nothing to match, so height:auto on
	   both the frame and the image lets the picture keep its own proportions.
	   With the box matching the image, object-fit has nothing left to crop. */
	.imagination-feature__media .ph-media {
		height: auto;
		/* aspect-ratio, not just --ph-ratio: trewo_image() writes the ratio as
		   an inline custom property (style="--ph-ratio:4/5"), which outranks
		   the stylesheet's --ph-ratio:auto. With the height released the box
		   was still holding a 4:5 frame while the photograph is 3:2, so it
		   letterboxed with an empty band above and below. Setting the real
		   property here sidesteps the inline value entirely. */
		aspect-ratio: auto;
	}

	.imagination-feature__media .ph-media--photo img {
		height: auto;
	}

	.imagination-feature__panel {
		padding: 48px 40px;
	}

	.ib-recap-2025__stats {
		padding: 44px 28px;
	}

	.ib-gallery-grid {
		gap: 12px;
	}

	.stats__grid {
		grid-template-columns: repeat(2, 1fr);
		row-gap: 40px;
	}

	.stat {
		border-left: none;
	}

	.stat:nth-child(2n) {
		border-left: 2px solid var(--color-primary);
	}

	.programs__viewport {
		--visible: 2;
	}

	/* The badge's -90px overhang is measured against its 200px desktop size;
	   scaled down here, the pull has to scale with it or it drags the
	   carousel up into the heading. */
	.programs__badge {
		width: 150px;
		height: 150px;
		margin-bottom: -56px;
	}

	.ripple-accent--lg {
		width: 425px;
		height: 425px;
	}

	.ripple-accent--md {
		width: 305px;
		height: 305px;
	}

	.events__grid {
		grid-template-columns: repeat(4, 1fr);
	}

	.gallery__item {
		height: 300px;
	}

	.mission__grid {
		grid-template-columns: 1fr;
		gap: 40px;
	}

	.mission__media {
		max-width: 420px;
	}

	.site-footer__inner {
		grid-template-columns: 1fr 1fr;
	}

	.site-footer__col--about {
		grid-column: 1 / -1;
	}

	.site-footer__col--about .site-footer__tagline {
		max-width: 480px;
	}
}

@media (max-width: 767px) {
	:root {
		--section-space: var(--section-space-mobile);
		--header-height: 72px;
	}

	.programs-grid {
		grid-template-columns: 1fr;
		gap: 36px;
	}

	.wow-tight-grid {
		grid-template-columns: repeat(2, 1fr);
		gap: 14px;
	}

	.wow-video-grid {
		grid-template-columns: 1fr;
	}

	.together-list-wrap {
		max-width: none;
	}

	.together-list__item {
		gap: 12px;
		padding-left: 66px;
	}

	.together-list__item::before {
		width: 60px;
	}

	.together-list__year {
		width: 60px;
		font-size: 10px;
	}

	.together-list__photo {
		width: 64px;
		height: 64px;
	}

	.wow-archive-grid {
		grid-template-columns: repeat(2, 1fr);
	}

	.people-grid {
		grid-template-columns: 1fr;
	}

	.person--lg {
		flex-direction: column;
	}

	.obituary {
		flex-direction: column;
		text-align: center;
		border-left: none;
		padding-left: 0;
		padding-top: 24px;
		border-top: 3px solid var(--color-primary);
	}

	.creative-gallery {
		grid-template-columns: repeat(2, 1fr);
	}

	.wof-grid {
		grid-template-columns: repeat(2, 1fr);
		gap: 22px 18px;
	}

	.testimonial-slider {
		gap: 10px;
	}

	.testimonial {
		padding: 32px 20px;
	}

	.testimonial__photo {
		width: 60px;
		height: 60px;
		margin-bottom: 18px;
	}

	.link-cards {
		grid-template-columns: 1fr;
	}

	.story-strip img {
		height: 150px;
	}

	.milestones {
		grid-template-columns: 1fr;
		gap: 28px;
	}

	.milestone--origin {
		grid-template-columns: 1fr;
	}

	.photo-grid,
	.photo-grid--gallery {
		grid-template-columns: repeat(2, 1fr);
	}

	/* Client: the copy sits under the plaque rather than beside it — at this
	   width the two side by side left the paragraph in a ~180px column. */
	.about-opener__inception {
		flex-direction: column;
		align-items: flex-start;
		gap: 18px;
		margin-block: 32px;
	}

	.about-opener__plaque {
		height: 110px;
	}

	.subnav__link {
		padding: 14px 12px;
		font-size: 12px;
	}

	.site-logo__img {
		height: 46px;
	}

	/* The header has no height of its own — it is exactly as tall as the logo
	   inside it. At 46px that left the real header ~47px while
	   --header-height still claimed 72px, and everything measured off that
	   token was out by 25px: the sticky subnav floated below the header with
	   a strip of page showing between them, anchor targets landed too low,
	   and the hero's 100dvh maths was short. This padding makes the element
	   the height the token says it is. */
	.site-header__inner {
		padding-block: 12px;
	}

	.site-header__actions {
		gap: 12px;
	}

	.nav-toggle__label {
		display: none;
	}

	.section__header {
		flex-direction: column;
		align-items: flex-start;
		gap: 12px;
	}

	/* Stacks under the heading at this width (.section__header goes column
	   above) rather than crowding beside it — sized down to match. The
	   overhang has to come down with it: at 76px tall the inherited -90px
	   pull was deeper than the badge itself, which dragged the carousel up
	   over it. */
	.programs__badge {
		width: 76px;
		height: 76px;
		margin-bottom: -18px;
	}

	.events__lockup {
		flex-direction: column;
		align-items: flex-start;
		gap: 18px;
	}

	.events__logo {
		height: 112px;
	}

	.imagination-feature__panel {
		padding: 40px 24px;
	}

	/* Panel is much narrower here than at tablet/desktop, so the 18px base
	   would start wrapping the charity number line awkwardly. */
	.imagination-feature__fineprint {
		font-size: 15px;
	}

	.imagination-feature__badge {
		left: 20px;
		bottom: 20px;
		width: 124px;
		height: 124px;
	}

	.honour-grid {
		grid-template-columns: 1fr;
	}

	.ib-highlights {
		grid-template-columns: 1fr;
	}

	.ib-recap-2025__hero {
		aspect-ratio: 4 / 3;
		margin-bottom: 56px;
	}

	.ib-recap-2025__stats {
		grid-template-columns: 1fr;
		row-gap: 24px;
		padding: 32px 24px;
		margin-bottom: 56px;
	}

	.ib-recap-2025__stat {
		border-right: none;
		border-bottom: 1px solid rgba(255, 255, 255, 0.22);
		padding: 0 0 24px;
	}

	.ib-recap-2025__stat--last {
		border-bottom: none;
		padding-bottom: 0;
	}

	.ib-recap-2025__block,
	.ib-recap-2025__block--honours {
		margin-bottom: 56px;
	}

	/* The one-line treatment above only has room on wider screens — back to
	   wrapping here so the sentence doesn't run off the edge of the phone. */
	.ib-recap__closing-next {
		white-space: normal;
	}

	.ib-gallery-grid {
		grid-template-columns: repeat(2, 1fr);
		grid-template-rows: auto;
		aspect-ratio: auto;
		gap: 8px;
	}

	.ib-gallery-grid__item:first-child {
		grid-column: span 2;
		grid-row: auto;
		aspect-ratio: 16 / 10;
	}

	.ib-gallery-grid__item:not(:first-child) {
		aspect-ratio: 1;
	}

	.ib-gallery-grid__more {
		font-size: 24px;
	}

	.ib-quote-row {
		grid-template-columns: 1fr;
		gap: 24px;
		margin-bottom: 56px;
	}

	.ib-quote-row__media {
		min-height: 220px;
	}

	.ib-quote {
		padding: 26px 24px;
	}

	.ib-quote p {
		font-size: 16px;
	}

	.stats__grid {
		grid-template-columns: 1fr;
	}

	.events__grid {
		grid-template-columns: repeat(2, 1fr);
	}

	.programs__viewport {
		--visible: 1;
	}

	.ripple-accent--lg {
		width: 285px;
		height: 285px;
	}

	.ripple-accent--md {
		width: 212px;
		height: 212px;
	}

	.ripple-accent--sm {
		width: 155px;
		height: 155px;
	}

	.stat {
		border-left: none !important;
		padding-inline: 0;
	}

	.gallery__item {
		height: 220px;
	}

	.site-footer__inner {
		grid-template-columns: 1fr;
	}

	.site-footer__bottom-inner {
		flex-direction: column;
		gap: 8px;
		text-align: center;
	}

	/* Top padding and the start alignment come from the stacked block above;
	   this only tightens the bottom. */
	.hero {
		padding: 0 0 40px;
	}

	.hero__text {
		font-size: 17px;
	}

	.hero__eyebrow {
		font-size: 13px;
	}

	.hero__highlight {
		font-size: 18px;
	}

	.hero__actions .btn--lg {
		padding: 16px 30px;
		font-size: 15px;
	}

	.imagination-feature__actions .btn--lg {
		padding: 18px 32px;
		font-size: 16px;
		letter-spacing: 0.03em;
	}

	.hero__nav {
		margin-top: 36px;
		gap: 18px;
	}

	.hero__tabs {
		gap: 4px 18px;
	}

	/* These four tabs are the only way to change slide once the arrows are
	   hidden below, so they have to be thumb-sized: 6px of padding on a 13px
	   label is a ~29px target. */
	.hero__tab {
		padding: 12px 0;
	}

	.hero__arrows {
		display: none;
	}

	/* Every remaining carousel control on a touch screen — the programmes and
	   falls-prevention strips — comes up to the 44px minimum. */
	.carousel-arrow {
		width: 44px;
		height: 44px;
	}

	/* auto-fill with a 190px minimum drops to a single column on a phone,
	   which turned fifteen sponsor logos into fifteen full-width tiles and one
	   of the longest scrolls on the page. Two columns, shorter tiles. */
	.partners__strip {
		grid-template-columns: repeat(2, 1fr);
		gap: 12px;
		margin-top: 32px;
	}

	.partner-logo {
		height: 84px;
		padding: 10px;
	}
}

/* =========================================================
   Page enhancements — Roofs / Webinar Outreach Wing
   (read-more, tinted sections, vision/mission cards,
    video CTA, highlight card)
   ========================================================= */

/* Third section tone — soft warm sand/linen, sits between white and cream
   for feature bands without reading as pink. */
.section--sand {
	background: var(--color-sand);
}

/* Centered section header (eyebrow + title stacked, centred). */
.section__header--center {
	flex-direction: column;
	align-items: center;
	text-align: center;
}

.section__header--center .eyebrow {
	display: block;
}

/* ---------- Read more --------------------------------------------------- */
/*
 * Progressive enhancement: with no JS the full text is shown. main.js measures
 * each block and, only when it overflows the collapsed height, adds
 * .is-collapsible (clamp + fade + toggle). The fade colour tracks the section
 * background so it blends seamlessly.
 */
.readmore {
	--readmore-max: 320px;
	--readmore-fade: var(--color-white);
	position: relative;
}

.section--alt .readmore {
	--readmore-fade: var(--color-cream);
}

.section--sand .readmore {
	--readmore-fade: var(--color-sand);
}

/* The collapsed-state fade is a solid bar of the section's own background, so
   it has to follow the ground or it shows as a pale stripe across the red. */
.section--red .readmore {
	--readmore-fade: var(--color-primary);
}

.section--red .readmore.is-collapsible .readmore__content::after {
	color: rgba(255, 255, 255, 0.92);
}

/* Maroon-on-maroon would disappear, so the toggle inverts to a white outline
   and swaps its hover the other way round. */
.section--red .readmore__toggle {
	color: var(--color-white);
	border-color: rgba(255, 255, 255, 0.45);
}

.section--red .readmore__toggle:hover {
	background: var(--color-white);
	border-color: var(--color-white);
	color: var(--color-primary);
}

.readmore__content {
	position: relative;
}

.readmore.is-collapsible .readmore__content {
	max-height: var(--readmore-max);
	overflow: hidden;
}

.readmore.is-collapsible .readmore__content::after {
	content: "\2026";
	position: absolute;
	inset-inline: 0;
	bottom: 0;
	height: 32px;
	display: flex;
	align-items: flex-end;
	background: var(--readmore-fade);
	color: var(--color-body);
	font-size: 22px;
	line-height: 1;
	letter-spacing: 2px;
	pointer-events: none;
	transition: opacity 0.3s ease;
}

.readmore.is-expanded .readmore__content {
	max-height: none;
}

.readmore.is-expanded .readmore__content::after {
	opacity: 0;
}

.readmore__toggle {
	display: none;
	margin-top: 24px;
	align-items: center;
	gap: 9px;
	font-family: var(--font-label);
	font-weight: 500;
	font-size: 13px;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var(--color-primary);
	background: transparent;
	border: 1px solid rgba(181, 18, 27, 0.35);
	padding: 11px 26px;
	border-radius: 999px;
	transition: background-color 0.2s ease, color 0.2s ease, border-color 0.2s ease;
}

.readmore.is-collapsible .readmore__toggle {
	display: inline-flex;
}

.readmore__toggle:hover {
	background: var(--color-primary);
	border-color: var(--color-primary);
	color: var(--color-white);
}

.readmore__toggle-icon {
	transition: transform 0.25s ease;
}

.readmore.is-expanded .readmore__toggle-icon {
	transform: rotate(180deg);
}

/* ---------- Vision / Mission cards (Roofs) ------------------------------ */
.vm-grid {
	display: grid;
	grid-template-columns: 1fr 1fr;
	gap: 28px;
}

.vm-card {
	background: var(--color-white);
	border: 1px solid rgba(181, 18, 27, 0.12);
	border-radius: 22px;
	padding: 44px;
	box-shadow: 0 14px 40px rgba(31, 27, 27, 0.05);
}

.vm-card__head {
	display: flex;
	align-items: center;
	gap: 16px;
	margin-bottom: 20px;
}

.vm-card__icon {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	height: 58px;
	flex: none;
	border-radius: 16px;
	background: var(--color-sand);
	color: var(--color-primary);
}

.vm-card__title {
	font-family: var(--font-display);
	font-weight: 300;
	font-size: 30px;
	line-height: 1.05;
	color: var(--color-ink);
}

/* Mission reads as a checklist of commitments. */
.vm-list {
	display: grid;
	gap: 15px;
}

.vm-list li {
	position: relative;
	padding-left: 32px;
	font-size: 16px;
	line-height: 1.55;
	color: var(--color-body);
}

.vm-list li::before {
	content: "";
	position: absolute;
	left: 4px;
	top: 4px;
	width: 6px;
	height: 11px;
	border: solid var(--color-primary);
	border-width: 0 2px 2px 0;
	transform: rotate(45deg);
}

/* ---------- Our Outreach (WOW) — interactive world map ------------------ */
.outreach-map {
	background: var(--color-primary);
	color: var(--color-white);
}

/* The WebGL water surfaces (see main.js) are deliberately oversized here and
   pushed further off the section's corners, so what shows is the outer arc of
   a much bigger ripple bleeding in — the outreach idea framing the map rather
   than sitting under it. Kept off the map itself: a liquid surface behind the
   landmasses fights their shapes and the pins. */
.outreach-map .ripple-accent--lg {
	width: 780px;
	height: 780px;
	--ripple-strength: 0.6;
}

.outreach-map .ripple-accent--top-right {
	top: -26%;
	right: -16%;
}

.outreach-map .ripple-accent--bottom-left {
	bottom: -26%;
	left: -16%;
}

@media (max-width: 1023px) {
	.outreach-map .ripple-accent--lg {
		width: 495px;
		height: 495px;
	}
}

.outreach-map__header {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 16px;
	margin-bottom: 48px;
	text-align: center;
}

.outreach-map__title {
	font-family: var(--font-display);
	font-weight: 500;
	text-transform: none;
	font-size: clamp(36px, 4.6vw, 60px);
	line-height: 1.05;
	color: var(--color-white);
	margin: 0;
}

/* Up from 14px and no leading dot — client asked for both. Opacity raised too,
   since at 0.75 it was fading out against the red. */
.outreach-map__tag {
	display: flex;
	align-items: center;
	font-family: var(--font-label);
	font-weight: 600;
	font-size: 19px;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: rgba(255, 255, 255, 0.92);
}

.outreach-map__pills {
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	gap: 10px;
	margin-bottom: 36px;
}

.outreach-map__pill {
	display: inline-flex;
	align-items: center;
	gap: 8px;
	padding: 12px 20px;
	border-radius: 999px;
	background: rgba(255, 255, 255, 0.14);
	border: 1px solid rgba(255, 255, 255, 0.25);
	color: var(--color-white);
	font-family: var(--font-body);
	font-weight: 700;
	font-size: 14px;
	letter-spacing: 0.02em;
	cursor: pointer;
	transition: background-color 0.2s ease, color 0.2s ease, box-shadow 0.2s ease, border-color 0.2s ease;
}

.outreach-map__pill:hover {
	background: rgba(255, 255, 255, 0.22);
}

.outreach-map__pill.is-active {
	background: var(--color-white);
	color: var(--color-primary);
	border-color: transparent;
	box-shadow: 0 10px 20px -8px rgba(0, 0, 0, 0.25);
}

.outreach-map__frame {
	position: relative;
	margin-bottom: 40px;
}

.outreach-map__img {
	width: 100%;
	aspect-ratio: 924 / 424;
	display: block;
	object-fit: contain;
}

.outreach-map__pins {
	position: absolute;
	inset: 0;
	pointer-events: none;
}

/* Gold, and bigger. The old white-on-red pin was invisible against the map's
   own red ground — client couldn't see it at all. */
.outreach-map__pin {
	position: absolute;
	/* Each pin's coordinates come from the country list in the template as
	   --pin-x / --pin-y percentages; everything else about it is here. */
	left: var(--pin-x, 50%);
	top: var(--pin-y, 50%);
	transform: translate(-50%, -50%);
	width: 15px;
	height: 15px;
	border-radius: 50%;
	background: #f5b700;
	border: 2px solid rgba(255, 255, 255, 0.92);
	opacity: 0.95;
	cursor: pointer;
	pointer-events: auto;
	transition: transform 0.2s ease;
}

.outreach-map__pin:hover {
	transform: translate(-50%, -50%) scale(1.15);
}

.outreach-map__pin.is-active {
	width: 24px;
	height: 24px;
	background: #ffc733;
	border: 3px solid var(--color-white);
	opacity: 1;
	box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
	animation: outreach-map-pulse 1.8s ease-out infinite;
}

/* Pulse ring follows the pin to gold — it was red, which the red map swallowed. */
@keyframes outreach-map-pulse {
	0% { box-shadow: 0 0 0 0 rgba(245, 183, 0, 0.55); }
	70% { box-shadow: 0 0 0 18px rgba(245, 183, 0, 0); }
	100% { box-shadow: 0 0 0 0 rgba(245, 183, 0, 0); }
}

@media (prefers-reduced-motion: reduce) {
	.outreach-map__pin.is-active {
		animation: none;
	}
}

.outreach-map__stats {
	display: grid;
	grid-template-columns: repeat(4, 1fr);
	gap: 20px;
}

.outreach-map__stat {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: 18px;
	background: var(--color-white);
	border-radius: 20px;
	padding: 30px 28px;
	box-shadow: 0 16px 34px -22px rgba(60, 40, 20, 0.35);
}

.outreach-map__stat-icon {
	flex: none;
	display: flex;
	align-items: center;
	justify-content: center;
	width: 52px;
	height: 52px;
	border-radius: 14px;
	background: var(--color-primary-tint);
	color: var(--color-primary);
}

.outreach-map__stat-kicker {
	font-family: var(--font-label);
	font-weight: 800;
	font-size: 12px;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	color: var(--color-primary);
	margin: 0 0 8px;
}

.outreach-map__stat-text {
	margin: 0;
	font-size: 16px;
	line-height: 1.5;
	color: var(--color-ink);
}

.outreach-map__stat-number {
	font-size: 20px;
	font-weight: 800;
	color: var(--color-primary);
	margin-right: 8px;
}

/* ---------- Member cards (WOW Executive Committee / Ambassadors) ------- */

/* Lets a plain .section host a trewo_ripple() accent (same containment
   treatment as .partners). */
.section--ripple {
	position: relative;
	overflow: hidden;
	isolation: isolate;
}

/* WOW Ambassadors — the client's flyer-handover photo behind the cards. No
   positioning needed on the section itself: .section--ripple above already
   supplies the relative/overflow/isolation this depends on. */
.wow-ambassadors__bg {
	position: absolute;
	inset: 0;
	z-index: -2;
}

.wow-ambassadors__bg img {
	/* Oversized + repositioned so the parallax drift in main.js (GSAP
	   ScrollTrigger, scrubbed to the scrollbar) has buffer room to move
	   the image within without ever exposing an edge. */
	position: absolute;
	top: -15%;
	left: 0;
	width: 100%;
	height: 130%;
	object-fit: cover;
	object-position: center 45%;
	display: block;
}

/* A sand wash rather than a dark scrim: the names and the section title are
   set in ink here, so the ground has to stay light. Graded — densest through
   the middle where the cards sit, thinnest at the edges so the handover photo
   actually reads. Even at the thin end, ink holds ~7:1 over the photo's
   darkest pixels, so the whole band clears AA. */
.wow-ambassadors__bg::after {
	content: "";
	position: absolute;
	inset: 0;
	background: radial-gradient(
		120% 100% at 50% 50%,
		rgba(244, 238, 227, 0.9) 0%,
		rgba(244, 238, 227, 0.78) 60%,
		rgba(244, 238, 227, 0.62) 100%
	);
}

/* Fixed 4-up grid (client) rather than a centred wrapping row — with 7
   committee members and 6 ambassadors, flex-wrap was centring the leftover
   cards mid-row instead of aligning them under the first four. */
.member-grid {
	display: grid;
	grid-template-columns: repeat(4, 1fr);
	justify-content: center;
	justify-items: center;
	gap: 44px 36px;
	max-width: 880px;
	margin-inline: auto;
}

.member-card {
	width: 196px;
	max-width: 100%;
	text-align: center;
}

/* Four 196px cards plus gaps need ~892px; below that step down to 3.
   Declared here rather than in the shared 1023px block further up the file,
   which sits BEFORE the base rule and so would lose the cascade to it. */
@media (max-width: 1023px) {
	.member-grid {
		grid-template-columns: repeat(3, 1fr);
	}
}

.member-card__photo {
	width: 156px;
	height: 156px;
	border-radius: 50%;
	object-fit: cover;
	object-position: top center;
	margin-inline: auto;
	box-shadow: 0 0 0 1px rgba(181, 18, 27, 0.14), 0 14px 30px rgba(31, 27, 27, 0.12);
	transition: transform 0.35s ease, box-shadow 0.35s ease;
}

.member-card:hover .member-card__photo {
	transform: translateY(-4px) scale(1.04);
	box-shadow: 0 0 0 2px var(--color-primary), 0 18px 36px rgba(31, 27, 27, 0.16);
}

.member-card__name {
	margin-top: 18px;
	font-family: var(--font-display);
	font-weight: 400;
	font-size: 19px;
	line-height: 1.25;
	color: var(--color-ink);
}

/* Client: drop the red pill, set the role in italics instead. */
.member-card__role {
	display: block;
	margin-top: 6px;
	font-family: var(--font-display);
	font-style: italic;
	font-weight: 400;
	font-size: 15px;
	letter-spacing: 0.01em;
	color: var(--color-body);
}

/* ---------- Flyer distribution network (WOW) --------------------------- */

/* The opening Aeshna Roy line used to be set apart here as a centred display
   lead. The client asked for it to read as part of the paragraph run, so it is
   now just the first paragraph in the columns below and needs no rule of its
   own. */

/* Real multi-column text rather than two hand-split lists: the paragraphs
   balance themselves, so adding or reordering one can't leave a lopsided
   layout behind. */
.flyer-network__cols {
	max-width: 1000px;
	margin-inline: auto;
	column-count: 2;
	column-gap: 64px;
	column-rule: 1px solid var(--color-grey-light);
}

.flyer-network__cols p {
	margin: 0 0 20px;
	font-size: 16.5px;
	line-height: 1.7;
	color: var(--color-body);
	/* Keep each paragraph whole instead of splitting one across the fold. */
	break-inside: avoid;
}

.flyer-network__cols p:last-child {
	margin-bottom: 0;
}

/* The closing total is the payoff of the whole passage, so it steps back out
   to full width under a brand rule. */
.flyer-network__total {
	max-width: 780px;
	margin: 52px auto 0;
	padding-top: 30px;
	border-top: 2px solid var(--color-primary);
	text-align: center;
	font-family: var(--font-display);
	font-weight: 300;
	font-size: clamp(20px, 2.1vw, 25px);
	line-height: 1.45;
	color: var(--color-ink);
}

@media (max-width: 767px) {
	.flyer-network__cols {
		column-count: 1;
		column-rule: none;
	}

	.flyer-network__total {
		margin-top: 36px;
	}
}

/* ---------- Highlight card (WOW gift-in-lieu teaser) ------------------- */
.wow-gift-cta {
	position: relative;
	overflow: hidden;
	isolation: isolate;
	padding-block: clamp(100px, 14vw, 160px);
}

.wow-gift-cta__bg {
	position: absolute;
	inset: 0;
	z-index: -2;
}

.wow-gift-cta__bg img {
	/* Oversized + repositioned so the parallax drift in main.js (GSAP
	   ScrollTrigger, scrubbed to the scrollbar) has buffer room to move
	   the image within without ever exposing an edge. */
	position: absolute;
	top: -15%;
	left: 0;
	width: 100%;
	height: 130%;
	object-fit: cover;
	object-position: 78% 45%;
	display: block;
}

/* White card dropped (client) — the copy now sits directly on the dark
   photo, so everything inside inverts to white. */
.highlight-card {
	position: relative;
	z-index: 1;
	max-width: 880px;
	margin-inline: auto;
	text-align: center;
	padding: 60px 24px;
}

.highlight-card .eyebrow {
	color: var(--color-white);
}

.highlight-card__title {
	font-family: var(--font-display);
	font-weight: 300;
	font-size: clamp(22px, 2.6vw, 30px);
	line-height: 1.35;
	color: var(--color-white);
	margin: 16px auto 30px;
	max-width: 750px;
	/* The background is a photo, not a flat fill — a soft shadow keeps the
	   copy readable wherever the hands fall behind it. */
	text-shadow: 0 2px 14px rgba(0, 0, 0, 0.55);
}

.highlight-card .btn {
	margin-top: 0;
}

/* Top-align a media-row whose text column collapses (read-more): keeps the
   image pinned to the top so it doesn't recentre when the text expands. */
.media-row--top {
	align-items: start;
}

.wow-about-section {
	padding-bottom: 48px;
}

.wow-banner-section {
	padding-top: 48px;
	padding-bottom: 48px;
}

/* "Together We Can" banner opening the People page (client: full width). It
   runs edge to edge, so no container, no radius and no section padding. The
   height cap matters on wide displays: the artwork is 1900px across, and left
   to scale freely it would stand 800px tall on a 2560px screen and push the
   Advisory Board off the first view. Cropping is safe — the lettering sits
   dead centre, so cover trims only watercolour from top and bottom. */
.people-banner-section {
	padding: 0;
	/* Client: -2px, to close the hairline gap left under the subnav above. */
	margin-top: -2px;
}

.people-banner {
	display: block;
	width: 100%;
	height: auto;
	max-height: 380px;
	object-fit: cover;
}

@media (max-width: 767px) {
	.people-banner {
		max-height: 200px;
	}
}

.people-board-section {
	padding-top: 48px;
}

.wow-banner-figure {
	margin: 0;
}

.wow-banner-figure__caption {
	margin-top: 20px;
	text-align: center;
	font-family: var(--font-display);
	font-weight: 300;
	text-transform: capitalize;
	letter-spacing: -0.005em;
	font-size: clamp(24px, 2.8vw, 34px);
	line-height: 1.2;
	color: var(--color-ink);
}

/* ---------- WOW compact mission band ----------------------------------- */
.wow-mission-section {
	padding-block: 0;
}

.wow-mission {
	max-width: 820px;
	margin-inline: auto;
	display: flex;
	align-items: center;
	gap: 40px;
}

/* Circle crop and outline dropped (client) — the WOW logo is a wordmark on a
   transparent/white field, so a ring around it just fenced it in. */
.wow-mission__photo {
	width: 220px;
	height: 220px;
	max-width: 220px;
	flex: none;
	object-fit: contain;
	display: block;
}

.wow-mission__body {
	margin-top: 0;
}

.wow-mission__statement {
	margin-top: 12px;
	font-family: var(--font-display);
	font-weight: 300;
	font-size: 32px;
	line-height: 1.05;
	color: var(--color-ink);
}

@media (max-width: 767px) {
	.wow-mission {
		flex-direction: column;
		text-align: center;
		gap: 24px;
	}

	.outreach-map__stats {
		grid-template-columns: 1fr;
	}

	.outreach-map__stat {
		padding: 24px 22px;
	}

	.vm-grid {
		grid-template-columns: 1fr;
		gap: 20px;
	}

	.vm-card {
		padding: 32px 28px;
	}

	.highlight-card {
		padding: 44px 26px;
	}

	.member-grid {
		grid-template-columns: repeat(2, 1fr);
		gap: 32px 20px;
	}

	.member-card {
		width: 140px;
	}

	.member-card__photo {
		width: 116px;
		height: 116px;
	}

	.member-card__name {
		font-size: 16px;
	}
}

/* =========================================================
   Roofs for the Roofless — page redesign
   ========================================================= */

/* Photos on this page often carry their own white margins baked into the
   source file, which then vanish into the page's white background.
   Framing every photo in a light card + soft shadow fixes that regardless
   of what's baked into the image, and a gentle hover lift adds a bit of
   life to the photo grids. */
.roofs-page .media-row__media img,
.roofs-page .photo-grid img {
	border: 1px solid rgba(31, 27, 27, 0.1);
	box-shadow: 0 16px 36px -22px rgba(31, 27, 27, 0.35);
	transition: transform 0.25s ease, box-shadow 0.25s ease;
}

.roofs-page .photo-grid img:hover {
	transform: translateY(-4px);
	box-shadow: 0 20px 40px -20px rgba(31, 27, 27, 0.4);
}

/* Ron Cooke Balwadi — Joan Cooke's story set beside her photograph, above the
   balwadi photo grid. The prose column is the wider of the two: it carries two
   paragraphs, while the picture only has to be big enough to read faces. */
/* The heading lives in the left column (see roofs.php), so the row's two
   children start at the same line: the photograph's top edge is level with the
   title, not with the first paragraph. */
.balwadi-intro {
	display: grid;
	grid-template-columns: 1fr 0.72fr;
	align-items: start;
	gap: 48px;
	margin-bottom: 44px;
}

.balwadi-intro__title {
	margin-bottom: 20px;
}

.balwadi-intro__prose {
	font-size: 17px;
	line-height: 1.7;
	color: var(--color-body);
}

.balwadi-intro__prose p + p {
	margin-top: 16px;
}

.balwadi-intro__portrait {
	max-width: 460px;
	margin-left: auto;
}

.balwadi-intro__portrait img {
	width: 100%;
	height: auto;
	display: block;
	border-radius: 14px;
	box-shadow: 0 16px 38px -20px rgba(31, 27, 27, 0.45);
}

.balwadi-intro__portrait figcaption {
	margin-top: 12px;
	font-family: var(--font-label);
	font-size: 12px;
	font-weight: 500;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	color: var(--color-grey);
}

@media (max-width: 900px) {
	.balwadi-intro {
		grid-template-columns: 1fr;
		gap: 28px;
		margin-bottom: 36px;
	}

	.balwadi-intro__portrait {
		max-width: 520px;
		margin-left: 0;
	}
}

/* Same containment the other ripple-bearing sections have — this one carries
   a top-left ripple accent and had no base rule, so the accent escaped the
   section (see .falls-prevention for the same fix and why it matters). */
.roofs-legacy {
	position: relative;
	overflow: hidden;
	isolation: isolate;
}

/* Savithri's Vision — split-media opener above the legacy read-more. */
/* Copy leads, photograph centred beneath it (client) — was a side-by-side
   media row. */
.roofs-legacy__lead {
	max-width: 860px;
	margin-inline: auto;
	text-align: center;
}

.roofs-legacy__photo {
	margin: 40px auto 0;
	max-width: 1200px;
}

/* Simple crossfade slider — every slide shares the same 16/9 frame (the
   trewo_image() ratio below), so slide changes never resize this panel and
   there's no need for the height-morph the testimonial slider uses for its
   wildly varying quote lengths. Only one slide is ever in flow at a time
   (.roofs-legacy__slide toggles display via .is-active), so the arrows/dots
   are the only things absolutely positioned here. */
.roofs-legacy__slider {
	position: relative;
}

.roofs-legacy__slide {
	display: none;
}

.roofs-legacy__slide.is-active {
	display: block;
}

.roofs-legacy__slider-arrow {
	position: absolute;
	top: 50%;
	transform: translateY(-50%);
	z-index: 1;
	background: rgba(255, 255, 255, 0.85);
	backdrop-filter: blur(2px);
}

.roofs-legacy__slider-arrow--prev {
	left: 16px;
}

.roofs-legacy__slider-arrow--next {
	right: 16px;
}

.roofs-legacy__slider-dots {
	display: flex;
	align-items: center;
	justify-content: center;
	gap: 10px;
	margin-top: 20px;
}

/* Was clamp(32px, 4.2vw, 52px) — sized for the old half-width media row. Now
   that it runs centred across the full column it read as a headline and
   fought the section title above it. This keeps it a lead statement while
   landing at a comfortable ~65 characters per line. */
.roofs-legacy__statement {
	margin-top: 14px;
	font-family: var(--font-display);
	font-weight: 300;
	font-size: clamp(21px, 2.3vw, 30px);
	line-height: 1.4;
	color: var(--color-ink);
}

.roofs-legacy__more {
	margin-top: 56px;
}

/* Closing signature — a quiet divider + tightened line-height instead of
   the sign-off just running straight on from the last story paragraph. */
.roofs-legacy__signature {
	margin-top: 28px;
	padding-top: 20px;
	border-top: 1px solid rgba(31, 27, 27, 0.1);
}

.roofs-legacy__signature p {
	font-size: 14.5px;
	line-height: 1.6;
}

.roofs-legacy__signature p:first-child {
	font-style: italic;
	color: var(--color-body);
}

/* ---------- Roofs threshold band (rangoli + emblem) -------------------- */

/* Sits between the page hero and the founder section. Both edges are designed
   to dissolve: the top into the hero's dark scrim above, the bottom into the
   white ground of the founder section, so the photograph reads as part of the
   page rather than a rectangle dropped into it. */
.roofs-threshold {
	position: relative;
	overflow: hidden;
	isolation: isolate;
	display: grid;
	place-items: center;
	min-height: clamp(340px, 46vw, 620px);
	padding-block: clamp(56px, 8vw, 96px);
	background: rgb(16, 10, 8);
}

.roofs-threshold__bg {
	position: absolute;
	inset: 0;
	z-index: -2;
}

.roofs-threshold__bg img {
	/* Oversized for the same reason as the other parallax bands: the drift in
	   main.js needs buffer room so no edge is ever exposed. */
	position: absolute;
	top: -12%;
	left: 0;
	width: 100%;
	height: 124%;
	object-fit: cover;
	object-position: center 55%;
	display: block;
}

/* Two jobs, so two layers. The linear pass seals the band's top edge into the
   hero above and then holds an even scrim all the way down. The radial pass
   darkens the outer petals just enough that the emblem's outermost lines stay
   legible, while leaving the lit centre of the rangoli — the diyas — untouched.

   There is deliberately no bottom fade. It was lightening the petals and lamps
   that run to the bottom edge, and with the founder section below now on brand
   red, a light rim would read as a stray seam between two dark grounds rather
   than a transition. The band ends hard, the same way .roofs-vm-band and the
   donate CTA do. */
.roofs-threshold__bg::after {
	content: "";
	position: absolute;
	inset: 0;
	background:
		linear-gradient(
			180deg,
			rgba(16, 10, 8, 0.92) 0%,
			rgba(16, 10, 8, 0.32) 26%,
			rgba(16, 10, 8, 0.34) 100%
		),
		radial-gradient(70% 62% at 50% 52%, rgba(16, 10, 8, 0) 0%, rgba(16, 10, 8, 0.42) 100%);
}

.roofs-threshold__inner {
	position: relative;
	display: flex;
	justify-content: center;
}

/* The emblem arrives as black line art on a white JPEG, which cannot simply be
   laid over a dark photograph. Inverting it gives white lines on black, and
   screen then drops the black entirely — black is screen's identity — so only
   the linework survives, as light. No cut-out or transparent asset needed.
   A slight warm-up keeps the lines from reading as cold white against the
   diyas; note drop-shadow is deliberately NOT used, since the JPEG is fully
   opaque and would halo its own bounding box rather than the lines. */
.roofs-threshold__mark {
	position: relative;
	width: min(46vw, 440px);
	height: auto;
	display: block;
	filter: invert(1) sepia(0.32) saturate(1.15);
	mix-blend-mode: screen;
	opacity: 0.95;
}

/* The glow the drop-shadow can't give: a warm bloom painted behind the mark,
   as if the diyas were lighting the chalk from the floor up. */
.roofs-threshold__inner::before {
	content: "";
	position: absolute;
	top: 50%;
	left: 50%;
	width: min(70vw, 660px);
	aspect-ratio: 1;
	transform: translate(-50%, -50%);
	background: radial-gradient(circle, rgba(255, 168, 82, 0.28) 0%, rgba(255, 138, 60, 0.12) 45%, rgba(255, 138, 60, 0) 70%);
	pointer-events: none;
}

@media (max-width: 767px) {
	.roofs-threshold {
		min-height: 300px;
	}

	.roofs-threshold__mark {
		width: min(68vw, 300px);
	}
}

/* Vision & Mission — full-bleed parallax band with glass cards. */
.roofs-vm-band {
	position: relative;
	overflow: hidden;
	isolation: isolate;
	padding-block: clamp(110px, 14vw, 170px);
}

.roofs-vm-band__bg {
	position: absolute;
	inset: 0;
	z-index: -2;
}

.roofs-vm-band__bg img {
	/* Oversized + repositioned so the parallax drift in main.js has buffer
	   room to move within without ever exposing an edge — .roofs-vm-band
	   itself clips anything that spills past its bounds. */
	position: absolute;
	top: -15%;
	left: 0;
	width: 100%;
	height: 130%;
	object-fit: cover;
	object-position: center;
	display: block;
}

/* Client wanted the photo in full colour. The old scrim was doing two things
   that prevented that: it ran up to 0.88 opacity, and its middle stop was
   maroon, which cast the whole image red. Now a light, neutral darkening
   only — the cards below carry legibility instead of the scrim. */
.roofs-vm-band__bg::after {
	content: "";
	position: absolute;
	inset: 0;
	background: linear-gradient(120deg, rgba(31, 27, 27, 0.34) 0%, rgba(31, 27, 27, 0.2) 55%, rgba(31, 27, 27, 0.34) 100%);
}

.vm-grid--glass {
	position: relative;
	z-index: 1;
}

/* Cream at ~88% opacity (client) — the same frosted panel as
   .tb-roster-panel on the Trailblazers page — rather than the translucent
   black this used to be. Border reverts to the base .vm-card's maroon
   hairline (removed the white-tinted override that suited a dark card), and
   the shadow is a touch heavier than a plain white .vm-card's, since this one
   still needs to lift itself off a photo rather than a flat section colour.
   Text is NOT overridden here any more: base .vm-card__title/.vm-statement
   p/.vm-list already set ink/body/primary, which is exactly what reads on a
   light card — the old rules below forced everything to white for the dark
   background this replaces. */
.vm-card--glass {
	background: transparent;
	border: none;
	backdrop-filter: none;
	-webkit-backdrop-filter: none;
	box-shadow: none;
}

.vm-card--glass .vm-card__title,
.vm-card--glass .vm-list li {
	color: var(--color-white);
}

.vm-card--glass .vm-card__icon {
	background: transparent;
	color: var(--color-primary);
}

.vm-card--glass .vm-list li::before {
	border-color: var(--color-primary);
}

/* Video message card. Client: no background/border — this now reads as
   content sitting directly on the (unwashed) photo behind it, not a card, so
   the drop shadow that used to ground the card's edges is dropped with it;
   kept, it would just shadow an invisible rectangle. The heading below is set
   white for the same reason: nothing here supplies contrast anymore except
   the photo itself. */
.roofs-video-cta {
	max-width: 640px;
	margin-inline: auto;
	text-align: center;
	border-radius: 22px;
	padding: 30px;
}

.roofs-video-cta__icon {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	width: 60px;
	height: 60px;
	border-radius: 50%;
	background: var(--color-primary-tint);
	color: var(--color-primary);
	margin-bottom: 22px;
	text-decoration: none;
	transition: transform 0.2s ease, background-color 0.2s ease;
}

.roofs-video-cta:hover .roofs-video-cta__icon,
.roofs-video-cta__icon:hover,
.roofs-video-cta__icon:focus-visible {
	transform: scale(1.08);
	background: var(--color-primary);
	color: var(--color-white);
}

.roofs-video-cta .section__title--sentence {
	max-width: none;
	margin: 0 auto 28px;
	font-weight: 500;
	color: var(--color-white);
}

/* Video CTA section — relevant program photo as a parallax backdrop behind
   the white card (see .roofs-vm-band__bg above for the same technique). */
.roofs-video-section {
	position: relative;
	overflow: hidden;
	isolation: isolate;
	padding-top: 200px;
	padding-bottom: 200px;
}

.roofs-video-section__bg {
	position: absolute;
	inset: 0;
	z-index: -2;
}

.roofs-video-section__bg img {
	position: absolute;
	top: -15%;
	left: 0;
	width: 100%;
	height: 130%;
	object-fit: cover;
	/* Bottom-anchored (client) so the smile in the lower part of the photo
	   stays in frame — was center 30%, biased toward the top instead. */
	object-position: center bottom;
	display: block;
}

/* The Heather Hamlin Aged Care Day Centre letter — signature line, styled
   after the flyer's own side-by-side Chairman/Director credit. */
.roofs-kitchen-letter__signatures {
	margin-top: 32px;
	display: flex;
	flex-wrap: wrap;
	justify-content: space-between;
	gap: 20px 40px;
}

.roofs-kitchen-letter__signatures p {
	margin: 0;
	font-weight: 600;
	color: var(--color-ink);
}

.roofs-kitchen-letter__signatures span {
	display: block;
	margin-top: 2px;
	font-weight: 400;
	color: var(--color-body);
}

/* Placeholder cards standing in for the flyer's own "old"/"new" kitchen
   photos until the client supplies replacements. */
.roofs-daily-life__grid {
	margin-top: 48px;
	align-items: start;
}

.roofs-daily-life__card {
	margin: 0;
}

.roofs-daily-life__card .ph-media {
	border-radius: 14px;
}

/* Mixed portrait (1200x1600) and landscape (1600x1200) sources, so a uniform
   4:3 cover crop is what keeps the rows straight — the lightbox opens each
   photo whole, so nothing is actually lost to the crop. */
.roofs-daily-life__card img {
	width: 100%;
	aspect-ratio: 4 / 3;
	object-fit: cover;
	object-position: center;
	display: block;
	border-radius: 14px;
	cursor: pointer;
}

.roofs-daily-life__caption {
	margin-top: 12px;
	font-family: var(--font-label);
	font-weight: 600;
	font-size: 13px;
	letter-spacing: 0.03em;
	text-align: center;
	color: var(--color-body);
}

@media (max-width: 767px) {
	.roofs-vm-band {
		padding-block: 80px;
	}
}

/* ---------- Lunch Programme letter (Roofs) ----------------------------- */
.roofs-lunch__letter {
	max-width: 780px;
	margin-inline: auto;
}

.roofs-lunch__signoff {
	margin-top: 36px;
	padding-top: 26px;
	border-top: 2px solid var(--color-primary);
}

.roofs-lunch__signoff p {
	margin: 0;
	font-size: 17px;
	line-height: 1.6;
	color: var(--color-body);
}

.roofs-lunch__signoff p + p {
	margin-top: 12px;
}

.roofs-lunch__signoff strong {
	font-size: 18px;
	color: var(--color-ink);
}

.roofs-lunch__signoff span {
	font-style: italic;
}

/* Six-column track: the five Food Program shots are all 4:3, so the first
   three take two columns each and the last two take three, filling both rows
   exactly rather than leaving a ragged orphan on the second row. */
.roofs-lunch__gallery {
	display: grid;
	grid-template-columns: repeat(6, 1fr);
	gap: 24px;
	margin-top: 64px;
}

/* In its own section the grid follows a .section__header, which already
   carries the gap below it — the 64px above was spacing it off the end of
   the letter it used to sit under. Zeroed so it lines up with the Breakfast
   grid directly above. */
.roofs-lunch-section .roofs-lunch__gallery {
	margin-top: 0;
}

/* ---------- NSDC exam results ------------------------------------------
   Its own full-bleed brand-red band under the classroom photographs (client).
   It was a quiet ruled-off note inside that section before; the result is the
   outcome those classrooms were built for, so it now carries the page for a
   moment rather than reading as a footnote.
   ------------------------------------------------------------------------ */
.roofs-nsdc {
	position: relative;
	overflow: hidden;
	isolation: isolate;
}

/* Wider than the 760px measure the stats and letter share — the heading is
   nine words now that NSDC is spelled out in full, and at 760px it broke over
   three lines. */
.roofs-nsdc__head {
	max-width: 920px;
	margin-inline: auto;
	text-align: center;
}

.roofs-nsdc__title {
	margin-top: 14px;
	font-family: var(--font-display);
	font-weight: 300;
	font-size: clamp(30px, 3.8vw, 48px);
	line-height: 1.1;
	letter-spacing: -0.01em;
	color: var(--color-white);
}

/* The three figures pulled out of Dr Dayalan's sentences. Separated by hairline
   rules rather than boxed into cards — on a red ground, three white panels
   would read as form fields, the same problem the Imagination Ball highlights
   band had. */
.roofs-nsdc__stats {
	margin: 52px auto 0;
	/* Same 760px measure as the heading above and the letter below. At 980px
	   the stat row overhung both, so the rule above the letter visibly failed
	   to line up with the ends of this row. */
	max-width: 760px;
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	gap: 28px;
}

.roofs-nsdc__stat {
	padding: 0 20px;
	text-align: center;
	border-left: 1px solid rgba(255, 255, 255, 0.28);
}

.roofs-nsdc__stat:first-child {
	border-left: 0;
}

.roofs-nsdc__stat-value {
	display: block;
	font-family: var(--font-display);
	font-weight: 300;
	font-size: clamp(46px, 6vw, 72px);
	line-height: 1;
	color: var(--color-white);
}

.roofs-nsdc__stat-label {
	display: block;
	margin-top: 12px;
	font-family: var(--font-label);
	font-weight: 600;
	font-size: 12px;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	line-height: 1.5;
	color: rgba(255, 255, 255, 0.85);
}

/* Dr Dayalan's own words, kept as correspondence beneath the figures. */
.roofs-nsdc__letter {
	max-width: 760px;
	margin: 56px auto 0;
	padding-top: 36px;
	border-top: 1px solid rgba(255, 255, 255, 0.28);
}

.roofs-nsdc__letter .page-prose p {
	color: rgba(255, 255, 255, 0.92);
}

.roofs-nsdc__letter .page-prose p + p {
	margin-top: 16px;
}

.roofs-nsdc__attribution {
	margin-top: 24px;
	font-family: var(--font-label);
	font-weight: 600;
	font-size: 13px;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var(--color-white);
}

@media (max-width: 780px) {
	.roofs-nsdc__stats {
		grid-template-columns: 1fr;
		gap: 0;
		max-width: 420px;
	}

	/* Stacked, the divider moves from the side to between the rows. */
	.roofs-nsdc__stat {
		padding: 26px 0;
		border-left: 0;
		border-top: 1px solid rgba(255, 255, 255, 0.28);
	}

	.roofs-nsdc__stat:first-child {
		padding-top: 0;
		border-top: 0;
	}

	.roofs-nsdc__letter {
		margin-top: 40px;
		padding-top: 28px;
	}
}


.roofs-lunch__shot {
	grid-column: span 2;
	margin: 0;
}

.roofs-lunch__shot:nth-child(4),
.roofs-lunch__shot:nth-child(5) {
	grid-column: span 3;
}

/* Uniform 3:2 thumbnails. Four of the five were cropped to 960x624 but
   lunch-2 is still 960x720, and at natural height that one ran taller than
   its neighbours and threw the row out. Cover crops the difference; the
   lightbox still opens the full uncropped image on click. */
.roofs-lunch__shot img {
	width: 100%;
	aspect-ratio: 3 / 2;
	object-fit: cover;
	object-position: center;
	display: block;
	border-radius: 14px;
	cursor: pointer;
	transition: transform 0.3s ease, box-shadow 0.3s ease;
}

.roofs-lunch__shot img:hover {
	transform: translateY(-4px);
	box-shadow: 0 22px 44px -20px rgba(31, 27, 27, 0.45);
}

@media (max-width: 1023px) {
	.roofs-lunch__gallery {
		grid-template-columns: repeat(2, 1fr);
		gap: 20px;
	}

	.roofs-lunch__shot,
	.roofs-lunch__shot:nth-child(4),
	.roofs-lunch__shot:nth-child(5) {
		grid-column: span 1;
	}
}

/* =========================================================
   Funding partner credit (Roofs — Shah Family Foundation)
   The Foundation's logo and the link to their site were removed at the
   client's request, so this is now prose introducing their photographs.
   Client: every paragraph here is set the same — one size, one family — and
   the quote uses .about-intro__quote, this page's existing treatment, rather
   than a style of its own. Held to a reading measure; the photo grid below
   runs full width, and copy set that wide is unreadable.
   ========================================================= */
.funder {
	max-width: 860px;
	margin-top: 32px;
	margin-bottom: 44px;
}

.funder p {
	font-family: var(--font-body);
	font-size: 17px;
	line-height: 1.7;
	color: var(--color-body);
}

.funder p + p {
	margin-top: 18px;
}

@media (max-width: 599px) {
	.roofs-lunch__gallery {
		grid-template-columns: 1fr;
	}
}

/* Youth Mental Health essay — many short content blocks in a row, each
   wrapped in its own .section for background banding. At the default
   112px section padding these stack into 224px gaps between blocks with
   barely any content, so this page gets a tighter rhythm. */
.ymh-page .section {
	padding-block: 56px;
}

.ymh-page .quote-band {
	padding-block: 56px;
}

/* ---------- Other Resources page --------------------------------------- */

/* Recipe ingredients/method — a full-width card of its own (see the photo +
   intro media-row above it), two columns instead of one run-on paragraph. */
.recipe-card {
	background: var(--color-white);
	border: 1px solid rgba(31, 27, 27, 0.08);
	border-radius: var(--radius);
	padding: 32px 36px;
}

.recipe-detail {
	display: grid;
	grid-template-columns: 1fr 1.2fr;
	gap: 32px;
}

.recipe-detail__heading {
	font-family: var(--font-label);
	font-weight: 700;
	font-size: 12.5px;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var(--color-primary);
	margin: 0 0 12px;
}

.recipe-detail__list {
	display: grid;
	gap: 8px;
	margin: 0;
	padding: 0;
	list-style: none;
}

.recipe-detail__list li {
	position: relative;
	padding-left: 16px;
	font-size: 14.5px;
	line-height: 1.5;
	color: var(--color-body);
}

.recipe-detail__list li::before {
	content: "";
	position: absolute;
	left: 0;
	top: 8px;
	width: 5px;
	height: 5px;
	border-radius: 50%;
	background: var(--color-primary);
}

.recipe-detail__steps {
	display: grid;
	gap: 14px;
	margin: 0;
	padding-left: 20px;
}

.recipe-detail__steps li {
	font-size: 14.5px;
	line-height: 1.6;
	color: var(--color-body);
	padding-left: 4px;
}

.recipe-detail__steps li::marker {
	font-family: var(--font-display);
	font-weight: 600;
	color: var(--color-primary);
}

/* Heart-risk factor groups — icon-led rows instead of stacked paragraphs. */
.factor-list {
	display: grid;
	gap: 16px;
	margin-top: 4px;
}

.factor-group {
	display: flex;
	align-items: flex-start;
	gap: 12px;
}

.factor-group__icon {
	flex: none;
	display: flex;
	align-items: center;
	justify-content: center;
	width: 34px;
	height: 34px;
	margin-top: 2px;
	border-radius: 50%;
	background: var(--color-primary-tint);
	color: var(--color-primary);
}

.factor-group__label {
	font-family: var(--font-label);
	font-weight: 700;
	font-size: 12px;
	letter-spacing: 0.04em;
	text-transform: uppercase;
	color: var(--color-ink);
	margin: 0 0 4px;
}

.factor-group__text {
	font-size: 14.5px;
	line-height: 1.55;
	color: var(--color-body);
	margin: 0;
}

/* Security tip cards — icon badge + a highlighted takeaway strip instead of
   a plain trailing bold sentence. */
.callout--tip {
	position: relative;
	padding-top: 26px;
}

.callout__icon {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 36px;
	height: 36px;
	margin-bottom: 14px;
	border-radius: 50%;
	background: var(--color-primary-tint);
	color: var(--color-primary);
}

.callout__takeaway {
	margin-top: 14px;
	padding: 10px 14px;
	background: var(--color-grey-light);
	border-radius: var(--radius-sm);
}

.callout .callout__takeaway p {
	margin: 0;
	font-size: 14px;
	line-height: 1.5;
	color: var(--color-ink);
}

/* Reference table — bold the term column so it reads like a key, not just
   another data cell. */
.data-table td:first-child {
	font-weight: 600;
	color: var(--color-ink);
}

/* Bio line under the security section — a quiet divider instead of relying
   purely on whitespace to separate it from the table above. */
/* ---------- COVID webinar recap (virus backdrop) ----------------------- */
.covid-recap {
	position: relative;
	overflow: hidden;
	isolation: isolate;
}

.covid-recap__bg {
	position: absolute;
	inset: 0;
	z-index: -1;
}

.covid-recap__bg img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	object-position: center;
	display: block;
}

/* Heavy cream veil: the artwork is a saturated red and everything above it is
   dark body copy, a pull quote and a white Q&A card. At full strength none of
   that would read, so the image works as a tint rather than a picture. */
.covid-recap__bg::after {
	content: "";
	position: absolute;
	inset: 0;
	background: linear-gradient(
		180deg,
		rgba(251, 248, 245, 0.86) 0%,
		rgba(251, 248, 245, 0.76) 45%,
		rgba(251, 248, 245, 0.86) 100%
	);
}

/* ---------- Section on black -------------------------------------------
   Wrapper scope that inverts a whole section without touching the shared
   components inside it (.callout, .data-table, .page-prose are all reused
   elsewhere on light backgrounds). */
.section--onblack {
	background: #000;
	color: var(--color-white);
}

.section--onblack .eyebrow,
.section--onblack h2,
.section--onblack h3,
.section--onblack .callout__title {
	color: var(--color-white);
}

.section--onblack .page-prose p,
.section--onblack .callout p:not(.callout__title) {
	color: rgba(255, 255, 255, 0.82);
}

.section--onblack .page-prose strong,
.section--onblack .callout strong {
	color: var(--color-white);
}

/* Cards lift off the black as translucent panels rather than white boxes. */
.section--onblack .callout {
	background: rgba(255, 255, 255, 0.06);
	border-left-color: var(--color-primary);
	box-shadow: none;
}

.section--onblack .callout__icon {
	background: rgba(255, 255, 255, 0.12);
	color: var(--color-white);
}

.section--onblack .callout__takeaway {
	background: rgba(255, 255, 255, 0.1);
}

.section--onblack .data-table th,
.section--onblack .data-table td {
	border-bottom-color: rgba(255, 255, 255, 0.14);
}

.section--onblack .data-table td {
	color: rgba(255, 255, 255, 0.82);
}

.section--onblack .data-table tr:nth-child(even) td {
	background: rgba(255, 255, 255, 0.05);
}

.section--onblack .bio-note {
	border-top-color: rgba(255, 255, 255, 0.16);
}

.section--onblack a {
	color: var(--color-white);
}

.bio-note {
	padding-top: 24px;
	border-top: 1px solid rgba(31, 27, 27, 0.1);
	text-align: center;
}

.bio-note p {
	font-size: 14px;
}

/* Haven app promo panel — replaces the ad-hoc dark callout used as an image
   placeholder with a proper promo card (ripple accent, badge, feature icons). */
.haven-promo {
	position: relative;
	overflow: hidden;
	isolation: isolate;
	height: 100%;
	min-height: 280px;
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	justify-content: center;
	gap: 14px;
	padding: 48px 40px;
	border-radius: 16px;
	background: linear-gradient(155deg, var(--color-ink) 0%, var(--color-primary-dark) 130%);
	color: var(--color-white);
}

.haven-promo__badge {
	position: relative;
	display: inline-flex;
	align-items: center;
	padding: 8px 18px;
	border-radius: 999px;
	background: rgba(255, 255, 255, 0.14);
	border: 1px solid rgba(255, 255, 255, 0.3);
	font-family: var(--font-label);
	font-weight: 700;
	font-size: 12px;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var(--color-white);
}

.haven-promo__name {
	position: relative;
	font-family: var(--font-display);
	font-weight: 300;
	font-size: clamp(28px, 3vw, 38px);
	line-height: 1.15;
	color: var(--color-white);
}

.haven-features {
	display: flex;
	flex-direction: column;
	gap: 14px;
	margin: 8px 0 0;
	padding: 0;
	list-style: none;
}

.haven-features__item {
	display: flex;
	align-items: flex-start;
	gap: 12px;
}

.haven-features__icon {
	flex: none;
	display: flex;
	align-items: center;
	justify-content: center;
	width: 28px;
	height: 28px;
	margin-top: 1px;
	border-radius: 50%;
	background: var(--color-primary-tint);
	color: var(--color-primary);
}

.haven-features__item span:last-child {
	font-size: 15px;
	line-height: 1.55;
	color: var(--color-body);
}

@media (max-width: 767px) {
	.recipe-card {
		padding: 24px 20px;
	}

	.recipe-detail {
		grid-template-columns: 1fr;
		gap: 24px;
	}
}

/* When a quote band directly follows another cream (.section--alt) section,
   the shared background turns the stacked paddings into one blank void with
   no seam to justify it — pull the top in tighter everywhere this happens,
   regardless of page. Placed last so it wins over any page-specific
   .quote-band padding-block tweak (e.g. .ymh-page) at equal specificity. */
.section--alt + .quote-band {
	padding-top: 24px;
}

/* ---------- Webinar Resources page (generic, reusable components) ------ */

/* Icon-fronted bullet list — replaces a plain <ul> with a checkmark badge
   per item, matching the icon-badge language used elsewhere on the site.
   Scoped as ".callout .check-list" (not just ".check-list") so it reliably
   beats the generic ".callout ul" rule regardless of source order. */
.callout .check-list {
	display: grid;
	gap: 10px;
	margin: 0;
	padding: 0;
	list-style: none;
}

.check-list li {
	display: flex;
	align-items: flex-start;
	gap: 10px;
	font-size: 14.5px;
	line-height: 1.5;
	color: var(--color-body);
}

.check-list__icon {
	flex: none;
	display: flex;
	align-items: center;
	justify-content: center;
	width: 20px;
	height: 20px;
	margin-top: 2px;
	border-radius: 50%;
	background: var(--color-primary-tint);
	color: var(--color-primary);
}

/* Percentage comparison bars — replaces a bare "label: N%" bullet list with
   a scannable bar-chart row. Bars grow in on scroll via GSAP (see main.js). */
.stat-compare {
	display: grid;
	gap: 16px;
	margin-top: 18px;
}

.stat-compare__row {
	display: grid;
	grid-template-columns: 170px 1fr auto;
	align-items: center;
	gap: 16px;
}

.stat-compare__label {
	font-family: var(--font-label);
	font-weight: 700;
	font-size: 12px;
	letter-spacing: 0.03em;
	text-transform: uppercase;
	color: var(--color-ink);
}

.stat-compare__track {
	position: relative;
	height: 8px;
	border-radius: 999px;
	background: rgba(31, 27, 27, 0.08);
	overflow: hidden;
}

.stat-compare__bar {
	position: absolute;
	inset: 0;
	width: var(--pct);
	border-radius: 999px;
	background: var(--color-primary);
}

.stat-compare__value {
	font-family: var(--font-display);
	font-weight: 500;
	font-size: 15px;
	color: var(--color-ink);
	text-align: right;
}

@media (max-width: 600px) {
	.stat-compare__row {
		grid-template-columns: 1fr;
		gap: 6px;
	}

	.stat-compare__value {
		text-align: left;
	}
}


/* =========================================================
   HealthLIT
   ========================================================= */

/* Opening statement — the client's first line, set alone. A short brand rule
   above it does the work an eyebrow would, without inventing a label. */
.healthlit-lead__statement {
	position: relative;
	max-width: 100%;
	margin-inline: auto;
	padding-top: 34px;
	text-align: center;
	font-family: var(--font-display);
	font-weight: 300;
	font-size: clamp(27px, 3.9vw, 46px);
	line-height: 1.18;
	letter-spacing: -0.01em;
	color: var(--color-ink);
	text-wrap: balance;
}

.healthlit-lead__statement::before {
	content: "";
	position: absolute;
	top: 0;
	left: 50%;
	width: 64px;
	height: 3px;
	transform: translateX(-50%);
	background: var(--color-primary);
}

/* Six paragraphs of letter. Two columns rather than one long measure — the
   same treatment the WOW flyer note uses, so the two chairs' letters read as
   the same kind of document. */
.healthlit-letter__cols,
.wow-about__cols {
	max-width: 1000px;
	margin-inline: auto;
	column-count: 2;
	column-gap: 64px;
	column-rule: 1px solid rgba(31, 27, 27, 0.1);
}

.healthlit-letter__cols p,
.wow-about__cols p {
	margin: 0 0 20px;
	font-size: 16.5px;
	line-height: 1.7;
	color: var(--color-body);
	text-wrap: pretty;
	/* A paragraph split across the fold would break the letter's voice. */
	break-inside: avoid;
}

.healthlit-letter__cols p:last-child,
.wow-about__cols p:last-child {
	margin-bottom: 0;
}

/* Sign-off. Sits under a brand rule at the letter's own width so it reads as
   the close of the letter rather than as a team card that happens to follow. */
.healthlit-sign,
.wow-sign {
	display: flex;
	align-items: center;
	justify-content: center;
	gap: 22px;
	max-width: 780px;
	margin: 52px auto 0;
	padding-top: 32px;
	border-top: 2px solid var(--color-primary);
}

.healthlit-sign__photo,
.wow-sign__photo {
	flex: none;
	width: 92px;
	height: 92px;
	border-radius: 50%;
	object-fit: cover;
	display: block;
	box-shadow: 0 0 0 1px rgba(181, 18, 27, 0.16), 0 12px 26px rgba(31, 27, 27, 0.12);
}

.healthlit-sign__body,
.wow-sign__body {
	text-align: left;
}

.healthlit-sign__salutation,
.wow-sign__salutation {
	font-family: var(--font-display);
	font-style: italic;
	font-size: 17px;
	color: var(--color-body);
}

.healthlit-sign__role,
.wow-sign__role {
	margin-top: 6px;
	font-family: var(--font-label);
	font-weight: 500;
	font-size: 12.5px;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var(--color-primary);
}

.healthlit-sign__name,
.wow-sign__name {
	font-family: var(--font-display);
	font-weight: 400;
	font-size: clamp(21px, 2.4vw, 26px);
	line-height: 1.2;
	color: var(--color-ink);
}

/* ---------- Video wall ------------------------------------------------- */

/* Three-up, and auto-fit rather than a hard repeat(3): the container tops out
   at three tracks anyway, so this degrades to two and then one on its own as
   the viewport narrows, and a tenth video would not need a media query. */
.healthlit-video-grid {
	margin-top: 52px;
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
	gap: 34px 26px;
}

/* A real <button>, so the video lightbox is reachable by keyboard and
   announced as a control — the play triangle alone would leave it a div. */
.healthlit-video {
	display: flex;
	flex-direction: column;
	gap: 14px;
	padding: 0;
	border: 0;
	background: none;
	text-align: left;
	color: inherit;
	font: inherit;
	cursor: pointer;
}

.healthlit-video__thumb {
	position: relative;
	display: block;
	aspect-ratio: 16 / 9;
	border-radius: 14px;
	overflow: hidden;
	/* Holds the row before the YouTube thumbnail arrives. */
	background: rgba(255, 255, 255, 0.08);
}

/* YouTube's hqdefault is a 4:3 frame with the 16:9 still letterboxed inside
   it. Cover in a 16/9 box crops those black bars back off, which is how the
   other video grids on the site handle the same file. */
.healthlit-video__thumb img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
	transition: transform 0.7s cubic-bezier(0.22, 0.61, 0.36, 1), opacity 0.4s ease;
}

.healthlit-video__play {
	position: absolute;
	top: 50%;
	left: 50%;
	width: 58px;
	height: 58px;
	transform: translate(-50%, -50%);
	display: grid;
	place-items: center;
	border-radius: 50%;
	background: var(--color-primary);
	color: var(--color-white);
	box-shadow: 0 10px 26px rgba(0, 0, 0, 0.45);
	transition: transform 0.35s cubic-bezier(0.22, 0.61, 0.36, 1), background-color 0.3s ease;
}

/* Optical centring: a triangle's visual mass sits left of its bounding box, so
   nudging it right is what makes it look centred in the circle. */
.healthlit-video__play svg {
	margin-left: 3px;
}

.healthlit-video:hover .healthlit-video__thumb img,
.healthlit-video:focus-visible .healthlit-video__thumb img {
	transform: scale(1.06);
	opacity: 0.82;
}

.healthlit-video:hover .healthlit-video__play,
.healthlit-video:focus-visible .healthlit-video__play {
	transform: translate(-50%, -50%) scale(1.12);
}

.healthlit-video__title {
	font-size: 16px;
	font-weight: 500;
	line-height: 1.45;
	color: rgba(255, 255, 255, 0.88);
	text-wrap: pretty;
	transition: color 0.3s ease;
}

.healthlit-video:hover .healthlit-video__title,
.healthlit-video:focus-visible .healthlit-video__title {
	color: var(--color-white);
}

.healthlit-video:focus-visible {
	outline: none;
}

.healthlit-video:focus-visible .healthlit-video__thumb {
	outline: 3px solid var(--color-white);
	outline-offset: 3px;
}

@media (max-width: 767px) {
	.healthlit-letter__cols,
	.wow-about__cols {
		column-count: 1;
		column-rule: none;
	}

	/* Stacked, because at phone width the portrait and the three signature
	   lines side by side leave neither enough room. */
	.healthlit-sign,
	.wow-sign {
		flex-direction: column;
		gap: 16px;
		margin-top: 36px;
		text-align: center;
	}

	.healthlit-sign__body,
	.wow-sign__body {
		text-align: center;
	}

	.healthlit-video-grid {
		margin-top: 36px;
		gap: 26px 20px;
	}
}


/* =========================================================
   TREWO Trailblazers + shared roster
   ========================================================= */

/* Prose above, photographs beneath it — not side by side. Four paragraphs
   against two stacked 3:2 frames left the text column ending halfway up an
   ever-taller photo column, with a large hole under the copy. Stacking the
   two blocks lets the prose take a comfortable measure and turns the
   photographs into a proper full-width pair. */
.tb-story__prose {
	max-width: 760px;
	margin-inline: auto;
}

.tb-story__prose p {
	margin: 0 0 18px;
	font-size: 17px;
	line-height: 1.7;
	color: var(--color-body);
	text-wrap: pretty;
}

.tb-story__prose p:last-child {
	margin-bottom: 0;
}

/* Two-up and equal width, so two frames of identical ratio render at
   identical height — the same rule the AGM mosaic runs on. */
.tb-story__media {
	margin-top: clamp(38px, 4.4vw, 60px);
	display: grid;
	grid-template-columns: repeat(2, 1fr);
	gap: clamp(16px, 2vw, 26px);
}

.tb-shot {
	margin: 0;
	border-radius: 16px;
	overflow: hidden;
	background: var(--color-sand);
	box-shadow: 0 1px 2px rgba(31, 27, 27, 0.06);
	transition: box-shadow 0.4s ease;
}

.tb-shot img {
	width: 100%;
	height: auto;
	display: block;
	transition: transform 0.7s cubic-bezier(0.22, 0.61, 0.36, 1);
}

.tb-shot:hover {
	box-shadow: 0 18px 40px -18px rgba(31, 27, 27, 0.4);
}

.tb-shot:hover img {
	transform: scale(1.03);
}

/* The fundraising figure, pulled out of the paragraph. Centred under the whole
   grid rather than inside the prose column, so it reads as the section's
   conclusion rather than as an aside. */
.tb-figure {
	max-width: 640px;
	margin: clamp(44px, 5vw, 68px) auto 0;
	padding-top: 30px;
	border-top: 2px solid var(--color-primary);
	text-align: center;
}

.tb-figure__value {
	font-family: var(--font-display);
	font-weight: 300;
	font-size: clamp(40px, 6.4vw, 76px);
	line-height: 1;
	letter-spacing: -0.02em;
	color: var(--color-primary);
}

.tb-figure__label {
	margin-top: 12px;
	font-size: clamp(15px, 1.7vw, 18px);
	line-height: 1.5;
	color: var(--color-body);
}

/* ---------- Leadership ------------------------------------------------- */

.tb-leads {
	margin-top: 52px;
	display: grid;
	grid-template-columns: repeat(2, minmax(0, 1fr));
	gap: clamp(20px, 2.6vw, 34px);
	max-width: 820px;
	margin-inline: auto;
}

.tb-lead-card {
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: 4px;
	padding: 36px 28px;
	text-align: center;
	/* Cream at ~88% opacity (client), not the solid --color-cream token used
	   elsewhere — this card now sits on the team section's photo, and a hint
	   of it coming through the card is the effect asked for. Written as a
	   literal value rather than the variable, which stays fully opaque for
	   every other (non-photo) use across the site. */
	background: #fbf8f5e0;
	border-radius: 18px;
	transition: transform 0.4s cubic-bezier(0.22, 0.61, 0.36, 1), box-shadow 0.4s ease;
}

.tb-lead-card:hover {
	transform: translateY(-5px);
	box-shadow: 0 20px 40px -20px rgba(31, 27, 27, 0.36);
}

.tb-lead-card__photo {
	width: 132px;
	height: 132px;
	border-radius: 50%;
	object-fit: cover;
	object-position: top center;
	margin-bottom: 14px;
	box-shadow: 0 0 0 1px rgba(181, 18, 27, 0.16), 0 14px 30px rgba(31, 27, 27, 0.12);
}

.tb-lead-card__role {
	font-family: var(--font-label);
	font-weight: 500;
	font-size: 12.5px;
	letter-spacing: 0.07em;
	text-transform: uppercase;
	color: var(--color-primary);
}

.tb-lead-card__name {
	font-family: var(--font-display);
	font-weight: 400;
	font-size: clamp(21px, 2.4vw, 27px);
	line-height: 1.2;
	color: var(--color-ink);
}

/* The co-chairs have no photograph between them, so this card balances the
   chair's card on type alone rather than on a placeholder face. */
.tb-lead-card--pair {
	gap: 2px;
}

.tb-lead-card--pair .tb-lead-card__role {
	margin-bottom: 10px;
}

.tb-lead-card__amp {
	font-family: var(--font-display);
	font-style: italic;
	font-size: 17px;
	line-height: 1.1;
	color: var(--color-primary);
}

.tb-team .section__title {
	text-shadow: 1px 1px 2px white;
}

/* Team section background photo (client). Same oversized+parallax technique
   as .wow-ambassadors__bg: no positioning needed on the section itself, since
   .section--ripple above already supplies the relative/overflow/isolation
   this depends on. */
.tb-team__bg {
	position: absolute;
	inset: 0;
	z-index: -2;
}

.tb-team__bg img {
	/* Oversized + repositioned so the parallax drift in main.js (GSAP
	   ScrollTrigger, scrubbed to the scrollbar) has buffer room to move
	   the image within without ever exposing an edge. */
	position: absolute;
	top: -15%;
	left: 0;
	width: 100%;
	height: 130%;
	object-fit: cover;
	object-position: center;
	display: block;
}

/* ---------- Roster (Trailblazers + Imagination Ball) -------------------- */

/* A name list, not a card grid. Both pages' teams arrive without photographs,
   and inventing placeholder portraits — for a list that is mostly children —
   would be worse than showing none. */
.roster {
	max-width: 940px;
	margin: clamp(44px, 5vw, 64px) auto 0;
}

.roster__title {
	font-family: var(--font-label);
	font-weight: 600;
	font-size: 13px;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: var(--color-primary);
	padding-bottom: 14px;
	border-bottom: 1px solid rgba(181, 18, 27, 0.22);
}

.roster__list {
	margin-top: 26px;
	padding: 0;
	list-style: none;
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
	gap: 14px 28px;
}

.roster__item {
	position: relative;
	padding-left: 20px;
	font-family: var(--font-display);
	font-weight: 400;
	font-size: 19px;
	line-height: 1.35;
	color: var(--color-ink);
}

/* The brand's ripple motif reduced to a single dot, so a plain list of names
   still carries the identity. */
.roster__item::before {
	content: "";
	position: absolute;
	left: 0;
	top: 0.62em;
	width: 7px;
	height: 7px;
	border-radius: 50%;
	background: var(--color-primary);
	opacity: 0.55;
}

/* A group of one shouldn't stretch a name across a full-width grid track
   (Imagination Ball's single-name Executive Committee / Chair groups). */
.roster--single .roster__list {
	grid-template-columns: minmax(0, max-content);
}

/* On the Trailblazers page, both rosters sit inside .tb-roster-panel (below)
   instead of directly on the team section's photo — one cream panel rather
   than a card or pill per name, which read as cluttered. Everywhere else
   .roster is used bare (e.g. Imagination Ball's team section) it stays a
   plain bulleted list on the section's own background, unaffected by this. */
.tb-roster-panel {
	margin-top: 64px;
	padding: 48px 44px;
	background: #fbf8f5e0;
	border-radius: 22px;
	max-width: 820px;
	margin-left: auto;
	margin-right: auto;
}

.tb-roster-panel .roster {
	margin-top: clamp(32px, 4vw, 44px);
}

.tb-roster-panel .roster:first-child {
	margin-top: 0;
}

@media (max-width: 600px) {
	.tb-leads {
		grid-template-columns: 1fr;
	}

	/* Single file only on phones — at tablet width the pair still reads. */
	.tb-story__media {
		grid-template-columns: 1fr;
	}

	.roster__list {
		grid-template-columns: 1fr;
	}
}

/* =========================================================
   404 page
   ========================================================= */
.not-found {
	position: relative;
	overflow: hidden;
	isolation: isolate;
	display: flex;
	align-items: center;
	text-align: center;
	min-height: 620px;
	padding-block: clamp(96px, 14vw, 160px);
}

.not-found__inner {
	position: relative;
	max-width: 640px;
	margin-inline: auto;
}

.not-found__code {
	font-family: var(--font-display);
	font-weight: 300;
	font-size: clamp(96px, 16vw, 180px);
	line-height: 0.9;
	color: var(--color-white);
	margin-top: 14px;
}

.not-found__title {
	font-family: var(--font-display);
	font-weight: 300;
	font-size: clamp(24px, 3vw, 34px);
	line-height: 1.2;
	color: var(--color-white);
	margin-top: 8px;
}

.not-found__text {
	max-width: 480px;
	margin: 18px auto 0;
	font-size: 16px;
	line-height: 1.6;
	color: rgba(255, 255, 255, 0.85);
}

.not-found__actions {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: center;
	gap: 16px;
	margin-top: 36px;
}

.not-found__links {
	margin-top: 56px;
	padding-top: 32px;
	border-top: 1px solid rgba(255, 255, 255, 0.25);
}

.not-found__links-label {
	font-family: var(--font-label);
	font-weight: 600;
	font-size: 12px;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: rgba(255, 255, 255, 0.7);
}

.not-found__link-list {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: center;
	gap: 12px 28px;
	margin-top: 16px;
	list-style: none;
	padding: 0;
}

.not-found__link-list a {
	font-family: var(--font-body);
	font-weight: 500;
	font-size: 15px;
	color: var(--color-white);
	text-decoration: underline;
	text-underline-offset: 3px;
	text-decoration-color: rgba(255, 255, 255, 0.4);
	transition: text-decoration-color 0.2s ease;
}

.not-found__link-list a:hover {
	text-decoration-color: var(--color-white);
}

@media (max-width: 640px) {
	.not-found {
		min-height: 520px;
	}

	.not-found__actions {
		flex-direction: column;
		align-items: stretch;
	}

	.not-found__link-list {
		flex-direction: column;
		gap: 12px;
	}
}
