/**
 * OUF utilities
 *
 * Design tokens — colour, spacing, width, type — live in theme.json and arrive
 * here as --wp--preset--* custom properties. Only add rules to this file that
 * theme.json cannot express: brand shapes, repeated lockups, scroll behaviour.
 *
 * Loaded on the front end and in the editor, so what you build in the editor is
 * what ships. See ouf_enqueue_styles() and ouf_editor_style() in functions.php.
 */

/* -----------------------------------------------------------------------------
 * 1. Local tokens
 * -------------------------------------------------------------------------- */

:root {
	--ouf-header-h: 5.5rem; /* sticky header height — drives the anchor offset */
	--ouf-measure: 47.5rem; /* 760px, a comfortable prose width */
	--ouf-radius: 0.25rem;
	--ouf-radius-lg: 0.75rem;
	--ouf-radius-btn: 0.45rem; /* every button on the site, whoever renders it */
	--ouf-angle: 4.5rem; /* horizontal run of the hero panel's angled edge */
	--ouf-hero-foot: 2.5rem; /* navy band drawn beneath the banner */
	--ouf-footer-rule-h: 2.75rem; /* mist band above the footer */
	--ouf-icon-size: 3rem; /* section heading icons */
	/* Banner height, and through --ouf-panel-h the chevron's scale and the logo's
	   position. Tied to viewport width as well as capped at the design's 620px:
	   the shape is sized from height while the headline is placed by width, and
	   holding the height fixed is what let the two collide around 1250px. The vw
	   term governs the whole range down to the 900px collapse. */
	--ouf-hero-h: clamp(24rem, 43vw, 38.75rem);
	--ouf-hairline: color-mix(in srgb, currentColor 20%, transparent);
}

.hidden {
	display: none !important;
}

/* -----------------------------------------------------------------------------
 * 2. Layout
 * -------------------------------------------------------------------------- */

/* Vertical rhythm shared by every band, so sections never drift apart. Bands butt
   straight up against each other — each supplies its own padding, and the page's
   default block gap would otherwise show as a white seam between them. */
.ouf-section,
.ouf-hero {
	margin-block-start: 0;
}

.ouf-section {
	padding-block: var(--wp--preset--spacing--70);
}

.ouf-section--tight {
	padding-block: var(--wp--preset--spacing--60);
}

/* Hold prose to a readable measure inside an otherwise wide band. */
.ouf-narrow {
	max-width: var(--ouf-measure);
}

/* Bullets sit on the text's left edge instead of the browser's 40px indent. The
   padding that remains is the marker's own width, so the list copy still hangs
   clear of it and wrapped lines stay aligned.

   The tighter top margin keeps a list attached to the line that introduces it —
   the page's default block gap reads as a break between two separate things.

   Query Loops are excluded: core renders those as an unstyled <ul>, and the
   marker allowance here would indent every post away from its heading. */
.ouf-section :is(ul, ol):not(.wp-block-post-template) {
	margin-block-start: var(--wp--preset--spacing--20);
	margin-inline-start: 0;
	padding-inline-start: 1.15em;
}

/* -----------------------------------------------------------------------------
 * 3. Header and footer strips
 * -------------------------------------------------------------------------- */

/* The navy strip rides along as you scroll, so the anchor nav stays reachable.
   The banner's white chevron crosses over it — see .ouf-hero::before. */
.ouf-header {
	position: sticky;
	top: 0;
	z-index: 100;
	background-color: var(--wp--preset--color--navy);
}

/* The banner's chevron sits at 101 and its headline at 102 so the shape can
   cross the nav strip. Those would bury the open mobile menu, so the header
   steps above them for as long as it is open — the banner keeps its own
   stacking the rest of the time. See ouf-nav.js. */
.ouf-menu-open .ouf-header {
	z-index: 200;
}

/* Both menus come from wp_nav_menu(), which renders a plain <ul>. */
.ouf-menu {
	display: flex;
	flex-wrap: wrap;
	gap: var(--wp--preset--spacing--50);
	margin: 0;
	padding: 0;
	list-style: none;
}

.ouf-menu a {
	color: inherit;
	text-decoration: none;
}

.ouf-menu a:where(:hover, :focus-visible) {
	text-decoration: underline;
	text-decoration-thickness: 2px;
	text-underline-offset: 0.4em;
}

/* Primary nav: uppercase and tracked out, per the design. */
.ouf-nav--primary {
	font-weight: 500;
	letter-spacing: 0.08em;
	text-transform: uppercase;
}

/* Policy links read as one line separated by bullets. */
.ouf-nav--footer .ouf-menu {
	gap: var(--wp--preset--spacing--30);
}

.ouf-nav--footer .menu-item {
	display: flex;
	align-items: center;
	gap: var(--wp--preset--spacing--30);
}

.ouf-nav--footer .menu-item + .menu-item::before {
	content: '\2022';
	opacity: 0.55;
}

.ouf-footer-logo img {
	height: auto;
}

/* Mist band that separates the page from the navy footer. Deliberately empty —
   it's a rule, not content, so it carries no text and is hidden from assistive
   tech in the pattern. */
.ouf-footer-rule {
	height: var(--ouf-footer-rule-h);
}

/* The footer part butts up against the content, so the mist band reads as a
   deliberate rule rather than a gap in the page background. */
.wp-site-blocks > footer.wp-block-template-part {
	margin-block-start: 0;
}

/* Small screens: the primary menu collapses behind a toggle. */
.ouf-nav-toggle {
	display: none;
	padding: 0.25rem;
	border: 0;
	background: none;
	color: inherit;
	cursor: pointer;
}

@media (width < 768px) {
	.ouf-nav-toggle {
		display: inline-flex;
	}

	.ouf-nav--primary {
		position: absolute;
		inset-inline: 0;
		top: 100%;
		z-index: 1;
		padding: var(--wp--preset--spacing--40);
		background-color: var(--wp--preset--color--navy);
	}

	.ouf-nav--primary[data-open='false'] {
		display: none;
	}

	.ouf-nav--primary .ouf-menu {
		flex-direction: column;
		gap: var(--wp--preset--spacing--40);
	}
}

/* One radius across every button, whether it comes from core, from a pattern or
   from the form plugin — they sit near each other on the page and any difference
   reads as a mistake. */
:is(.wp-element-button, .wp-block-button__link, .ouf-person-more, .ouf-nav-toggle, .frm-fluent-form .ff-btn-submit) {
	border-radius: var(--ouf-radius-btn);
}

/* Buttons the theme draws itself, rather than core's .wp-element-button. The
   browser's focus ring boxes them in after a click, so it's suppressed there and
   replaced with a deliberate one for keyboard users — dropping it outright would
   leave tabbing through the tabs impossible to follow. */
:is(.ouf-tabs [role='tab'], .ouf-person-more, .ouf-bio-close, .ouf-nav-toggle):focus {
	outline: none;
}

:is(.ouf-tabs [role='tab'], .ouf-person-more, .ouf-bio-close, .ouf-nav-toggle):focus-visible {
	outline: 2px solid currentColor;
	outline-offset: 3px;
}

/* style.css outlines anything focused inside .wp-site-blocks, keyed off :focus
   rather than :focus-visible — so clicking a link leaves a ring behind it. This
   drops it for pointer focus only; the ring still appears when the element was
   reached by keyboard, which is the case that needs it. Written without :where()
   so it carries enough specificity to beat that rule. */
.wp-site-blocks *:focus:not(:focus-visible) {
	outline: none;
}

/* Block themes don't ship the classic visually-hidden helper. */
.screen-reader-text {
	position: absolute;
	width: 1px;
	height: 1px;
	overflow: hidden;
	clip-path: inset(50%);
	white-space: nowrap;
}

/* -----------------------------------------------------------------------------
 * 4. Components
 * -------------------------------------------------------------------------- */

/* The icon + heading lockup that opens each band. The icon is the first item in
   the row, so its left edge lines up with the copy below at every width. */
.ouf-section-heading {
	display: flex;
	align-items: flex-end;
	gap: 0.75rem;
	margin-block-end: var(--wp--preset--spacing--40);
}

.ouf-section-heading figure {
	flex: none;
	margin: 0;
}

.ouf-section-heading :is(img, svg) {
	width: var(--ouf-icon-size);
	height: auto;
}

.ouf-section-heading .wp-block-heading {
	margin: 0;
	font-size: clamp(1.75rem, 2.4vw, 2.25rem);
	font-weight: 700;
}

.ouf-section-heading--center {
	justify-content: center;
}

/* Photographs sit on a white mat against the coloured bands. */
.ouf-framed img {
	border: 0.15rem solid var(--wp--preset--color--white);
}

/* --- Member organisations ------------------------------------------------ */

/* The block sits on the mist band as a white card, the same as the other insets
   on the page. */
.ouf-partners {
	padding: var(--wp--preset--spacing--40);
	border-radius: var(--ouf-radius-lg);
	background-color: var(--wp--preset--color--white);
}

.ouf-partners .wp-block-heading {
	margin-block: 0 var(--wp--preset--spacing--30);
}

.ouf-partner-grid .wp-block-post-template {
	gap: var(--wp--preset--spacing--30);
}

/* The whole card is white. A tinted logo panel looked wrong against the logos
   that carry their own white background, so the two zones are separated by a
   rule instead. Built from the post itself rather than a gallery figure, so
   nothing here fights core's photo sizing. */
.ouf-partner-grid .wp-block-post {
	display: flex;
	flex-direction: column;
	overflow: hidden;
	border: 1px solid var(--wp--preset--color--mist);
	border-radius: var(--ouf-radius-lg);
	background-color: var(--wp--preset--color--white);
}

.ouf-partner-logo {
	display: flex;
	align-items: center;
	justify-content: center;
	min-height: 7rem;
	margin: 0;
	padding: var(--wp--preset--spacing--20);
}

/* A shared height rather than a shared width: it is what makes a wide wordmark
   and a square badge read as the same size, whatever their proportions. */
.ouf-partner-logo img {
	width: 70%;
	height: auto;
	max-width: 100%;
	object-fit: fit;
}

/* Grows to fill the card so the links line up across the row however long the
   names run — the same trick as the Leadership buttons. */
.ouf-partner-body {
	display: flex;
	flex: 1;
	flex-direction: column;
	gap: var(--wp--preset--spacing--20);
	padding: var(--wp--preset--spacing--30);
	border-block-start: 1px solid var(--wp--preset--color--mist);
}

.ouf-partner-name {
	margin: 0;
	color: var(--wp--preset--color--navy);
	font-weight: 700;
	line-height: 1.25;
}

/* Blue rather than the amber accent: amber on white is about 2:1 and would fail
   contrast for body-sized text. */
.ouf-partner-link {
	margin-block-start: auto;
	color: var(--wp--preset--color--blue);
	font-size: var(--wp--preset--font-size--small);
	text-decoration: none;
}

.ouf-partner-link::after {
	content: ' \1F862';
}

.ouf-partner-link:where(:hover, :focus-visible) {
	text-decoration: underline;
}

/* --- Why we exist -------------------------------------------------------- */

/* Rail-track artwork behind the navy band. */
.ouf-band-tracks {
	background-image: url('../images/rail-tracks.svg');
	background-position: center top;
	background-repeat: no-repeat;
	background-size: cover;
}

/* The map sits on white so its own labelling stays legible over the navy. */
.ouf-map-card {
	padding: var(--wp--preset--spacing--40);
	border-radius: var(--ouf-radius-lg);
	background-color: var(--wp--preset--color--white);
}

.ouf-map-title {
	margin-block: 0 var(--wp--preset--spacing--30);
	font-weight: 700;
}

/* Vision statement: title on the left, flag and statement on the right. */
.ouf-vision {
	display: grid;
	grid-template-columns: minmax(10rem, 1fr) auto 2fr;
	align-items: center;
	gap: var(--wp--preset--spacing--40);
	padding: var(--wp--preset--spacing--50);
	border-radius: var(--ouf-radius);
}

.ouf-vision > * {
	margin-block: 0;
}

.ouf-vision-title {
	font-weight: 300;
	line-height: 1.1;
}

.ouf-vision-icon {
	align-self: center;
}

@media (width < 768px) {
	.ouf-vision {
		grid-template-columns: 1fr;
		justify-items: start;
	}
}

/* --- Leadership ---------------------------------------------------------- */

/* Tabs share the heading row, so they sit across from the title. The row is
   allowed to wrap so they can drop below it when there isn't width for both. */
.ouf-leadership .ouf-section-heading {
	flex-wrap: wrap;
}

.ouf-tabs {
	display: flex;
	flex-wrap: wrap;
	gap: var(--wp--preset--spacing--40);
	margin-inline-start: var(--wp--preset--spacing--40);
}

/* Three long group names plus the title need roughly 1024px. Below that the tabs
   take a line of their own rather than being squeezed into a column beside it. */
@media (width < 1024px) {
	.ouf-tabs {
		flex-basis: 100%;
		margin-inline-start: 0;
		margin-block-start: var(--wp--preset--spacing--30);
	}
}

.ouf-tabs [role='tab'] {
	padding: 0 0 0.3em;
	border: 0;
	border-bottom: 3px solid transparent;
	background: none;
	color: var(--wp--preset--color--navy);
	font: inherit;
	font-size: var(--wp--preset--font-size--medium);
	cursor: pointer;
}

.ouf-tabs [role='tab'][aria-selected='true'] {
	border-bottom-color: currentColor;
	font-weight: 700;
}

.ouf-people {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(11rem, 1fr));
	gap: var(--wp--preset--spacing--50);
	text-align: center;
}

/* The hidden attribute only carries display:none from the UA stylesheet, which
   the grid above outranks — without this, every panel stays on screen. */
.ouf-people[hidden] {
	display: none;
}

/* A column so the button can be pushed to the foot of the card. Grid stretches
   every card in a row to the same height, so the buttons then line up however
   many lines a name or job title runs to. */
.ouf-person {
	display: flex;
	flex-direction: column;
	margin: 0;
}

/* Mist sits behind the portrait so cut-out PNGs read against it rather than
   letting the slate band show through the transparency. */
.ouf-person .ouf-avatar img {
	max-width: 11rem;
	margin-inline: auto;
	border: 0.2rem solid var(--wp--preset--color--white);
	background-color: var(--wp--preset--color--mist);
}

.ouf-person-name {
	margin-block: 0.85rem 0.4rem;
	font-size: var(--wp--preset--font-size--large);
	font-weight: 700;
	line-height: 1.2;
}

.ouf-person-role {
	margin-block: 0 var(--wp--preset--spacing--40);
	color: var(--wp--preset--color--navy);
	font-size: var(--wp--preset--font-size--medium);
}

.ouf-person-more {
	align-self: center;
	margin-block-start: auto;
	padding: 0.5em 1.1em;
	border: 0;
	border-radius: var(--ouf-radius-btn);
	background-color: var(--wp--preset--color--blue);
	color: var(--wp--preset--color--white);
	font: inherit;
	font-size: var(--wp--preset--font-size--medium);
	letter-spacing: 0.08em;
	text-transform: uppercase;
	cursor: pointer;
}

.ouf-person-more:where(:hover, :focus-visible) {
	background-color: var(--wp--preset--color--navy);
}

/* Bio dialog. showModal() supplies the focus trap and Escape handling. */
dialog.ouf-bio {
	max-width: min(38rem, calc(100vw - 2rem));
	padding: var(--wp--preset--spacing--50);
	border: 0;
	border-radius: var(--ouf-radius-lg);
	background-color: var(--wp--preset--color--white);
	color: var(--wp--preset--color--navy);
	text-align: start;
}

dialog.ouf-bio::backdrop {
	background-color: rgb(14 40 84 / 0.7);
}

.ouf-bio-close {
	float: inline-end;
	padding: 0 0.25rem;
	border: 0;
	background: none;
	color: inherit;
	font-size: 1.75rem;
	line-height: 1;
	cursor: pointer;
}

/* Inset card — Looking ahead, Why the Corridor matters, resource tiles. */
.ouf-card {
	padding: var(--wp--preset--spacing--40);
	border-radius: var(--ouf-radius-lg);
}

/* Circular portrait. Forced square regardless of the source image, so the radius
   reads as a circle rather than an oval. height:auto is needed because WordPress
   emits a height attribute, which would otherwise defeat aspect-ratio. */
.ouf-avatar img {
	display: block;
	width: 100%;
	height: auto;
	aspect-ratio: 1;
	border-radius: 50%;
	object-fit: cover;
}

/* --- News, resources and contact ----------------------------------------- */

/* Rules between the three columns, as drawn. Only between — a leading border on
   the first column would hang off the edge of the band. */
@media (width >= 768px) {
	.ouf-closing-cols > .wp-block-column + .wp-block-column {
		padding-inline-start: var(--wp--preset--spacing--50);
		border-inline-start: 1px solid color-mix(in srgb, var(--wp--preset--color--slate) 60%, transparent);
	}
}

.ouf-closing-cols :is(.ouf-news, .ouf-resources) :is(h3, .wp-block-post-title) {
	margin-block: 0.2em;
	font-weight: 700;
	line-height: 1.25;
}

.ouf-closing-cols :is(.ouf-news, .ouf-resources) a {
	color: inherit;
	text-decoration: none;
}

.ouf-closing-cols :is(.ouf-news, .ouf-resources) a:where(:hover, :focus-visible) {
	text-decoration: underline;
}

.ouf-closing-cols .wp-block-post-date {
	margin-block: 0;
	color: var(--wp--preset--color--blue);
}

.ouf-closing-cols .wp-block-post-excerpt {
	margin-block-start: 0.35em;
}

/* Resource thumbnails keep the white mat used elsewhere on the page. */
.ouf-resources .wp-block-post-featured-image {
	margin-block-end: 0.5em;
}

.ouf-resources .wp-block-post-featured-image img {
	width: 100%;
	height: auto;
	border: 1px solid var(--wp--preset--color--mist);
}

/* --- Post banner --------------------------------------------------------- */

/* The image comes from the category, or the post's featured image. With neither,
   --flat leaves the slate background showing on its own, which reads as a
   deliberate treatment rather than a missing picture. */
.ouf-post-banner {
	display: flex;
	align-items: flex-end;
	min-height: 22rem;
	padding-block: var(--wp--preset--spacing--70);
	background-position: center;
	background-size: cover;
}

/* Keeps the title legible over whatever photograph a category carries. */
.ouf-post-banner:not(.ouf-post-banner--flat)::before {
	content: '';
	position: absolute;
	inset: 0;
	background-color: color-mix(in srgb, var(--wp--preset--color--navy) 65%, transparent);
}

.ouf-post-banner {
	position: relative;
}

.ouf-post-banner__inner {
	position: relative;
	width: 100%;
	max-width: var(--wp--style--global--content-size);
	margin-inline: auto;
}

.ouf-post-banner__eyebrow {
	margin-block: 0 0.35em;
	letter-spacing: 0.08em;
	text-transform: uppercase;
}

.ouf-post-banner__title {
	margin-block: 0;
	font-size: clamp(1.9rem, 3.5vw, 3rem);
	font-weight: 700;
	line-height: 1.15;
}

/* theme.json colours core/post-date blue for the listings on the front page.
   Over the banner image that reads as muddy, so it goes white here. */
.ouf-post-banner .ouf-post-banner__date {
	margin-block: 0.6em 0;
	color: var(--wp--preset--color--white);
}

/* --- Contact form -------------------------------------------------------- */

/* Fluent Forms ships its own light-blue palette. These rules bring it onto the
   theme's tokens, scoped to our bands so the plugin's admin previews and any
   other form on the site keep their own styling. */
.ouf-section .frm-fluent-form .ff-el-group {
	margin-block-end: var(--wp--preset--spacing--30);
}

/* The plugin sets label_placement to a class it doesn't itself style — it hides
   .ff-el-form-hide_label, the markup carries .ff-el-form-hide — so the labels
   render. Hidden visually rather than removed: a placeholder disappears the
   moment someone types, so the label has to stay for screen readers. */
.ouf-section .frm-fluent-form .ff-el-input--label {
	position: absolute;
	width: 1px;
	height: 1px;
	overflow: hidden;
	clip-path: inset(50%);
	white-space: nowrap;
}

.ouf-section .frm-fluent-form .ff-el-form-control {
	width: 100%;
	padding: 0.75em 0.9em;
	border: 0;
	border-radius: 0;
	background-color: var(--wp--preset--color--mist);
	color: var(--wp--preset--color--navy);
	font-family: inherit;
	font-size: var(--wp--preset--font-size--medium);
	line-height: 1.4;
	box-shadow: none;
}

.ouf-section .frm-fluent-form .ff-el-form-control::placeholder {
	color: color-mix(in srgb, var(--wp--preset--color--navy) 55%, transparent);
	opacity: 1;
}

/* Inset so focus doesn't nudge the field, since there's no border to swap out. */
.ouf-section .frm-fluent-form .ff-el-form-control:focus {
	outline: 2px solid var(--wp--preset--color--blue);
	outline-offset: -2px;
}

.ouf-section .frm-fluent-form textarea.ff-el-form-control {
	min-height: 9rem;
	resize: vertical;
}

/* Name and Surname share a row, as drawn. */
.ouf-section .frm-fluent-form .ff-t-container {
	display: flex;
	gap: var(--wp--preset--spacing--30);
}

.ouf-section .frm-fluent-form .ff-t-cell {
	flex: 1;
	padding: 0;
}

/* Fluent Forms prints an inline rule for the button —
   form.fluent_form_3 .ff-btn-submit:not(.ff_btn_no_style) — which outranks a
   plain class selector. Matching its shape is what lets the theme's colours
   through without resorting to !important. */
.ouf-section form.frm-fluent-form .ff-btn-submit:not(.ff_btn_no_style) {
	padding: 0.6em 1.7em;
	border: 0;
	border-radius: var(--ouf-radius-btn);
	background-color: var(--wp--preset--color--slate);
	color: var(--wp--preset--color--white);
	font-family: inherit;
	font-size: var(--wp--preset--font-size--medium);
	font-weight: 600;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	cursor: pointer;
}

.ouf-section form.frm-fluent-form .ff-btn-submit:not(.ff_btn_no_style):where(:hover, :focus-visible) {
	background-color: var(--wp--preset--color--blue);
}

/* Validation messages, in the theme's type rather than the plugin's. */
.ouf-section .frm-fluent-form :is(.error, .text-danger) {
	color: #b3261e;
	font-size: var(--wp--preset--font-size--medium);
}

.ouf-section .frm-fluent-form .ff-message-success {
	padding: var(--wp--preset--spacing--30);
	border-radius: var(--ouf-radius);
	background-color: var(--wp--preset--color--mist);
	color: var(--wp--preset--color--navy);
}

/* --- Current focus areas -------------------------------------------------- */

/* Desaturated beneath the slate wash — the two together are what flatten the
   photograph to the tone in the design. The overlay alone leaves the ore too warm. */
.ouf-focus .wp-block-cover__image-background {
	filter: grayscale(1);
}

/* One text flow set in two columns rather than two hand-split columns, so adding
   a bullet reflows the passage instead of stranding it on one side. */
.ouf-two-col {
	columns: 2;
	column-gap: var(--wp--preset--spacing--50);
}

.ouf-two-col > :first-child {
	margin-block-start: 0;
}

@media (width < 768px) {
	.ouf-two-col {
		columns: 1;
	}
}

/* Shrinks to the thumbnail rather than filling the column, so the caption
   centres under the image instead of under the column it sits in. */
.ouf-download {
	width: max-content;
	max-width: 100%;
}

.ouf-download-link {
	margin-block-start: var(--wp--preset--spacing--30);
	letter-spacing: 0.08em;
	text-transform: uppercase;
}

.ouf-download-link a {
	color: inherit;
}

/* --- Timeline ------------------------------------------------------------ */

/* Scrolls sideways when the years outrun the width. Native scrolling gives touch
   swipe, trackpad and keyboard for free; tabindex and a label are what make the
   overflowing content reachable without a mouse. */
.ouf-timeline {
	--ouf-pill-h: 2.5rem;
	--ouf-stem: 1.6rem;

	overflow-x: auto;
	padding-block-end: var(--wp--preset--spacing--30);
	scroll-snap-type: x mandatory;
	cursor: grab;

	/* The bar is replaced by drag-to-scroll in ouf-timeline.js. */
	scrollbar-width: none;
}

.ouf-timeline::-webkit-scrollbar {
	display: none;
}

/* Snapping fights a drag, so it stands down while one is in progress. */
.ouf-timeline.is-dragging {
	cursor: grabbing;
	scroll-snap-type: none;
	user-select: none;
}

/* max-content sizes the track to every entry rather than to the visible width,
   so the rule below reaches the far edge of the last card instead of stopping at
   the fold. Deliberately no min-width — stretching the track to the band would
   leave the rule running past the last card into empty space. */
.ouf-timeline-track {
	position: relative;
	display: flex;
	width: max-content;
	gap: var(--wp--preset--spacing--40);
	margin: 0;
	padding: 0;
	list-style: none;
}

/* The rule runs the full scrolling width, level with the connector nodes. */
.ouf-timeline-track::before {
	content: '';
	position: absolute;
	inset-inline: 0;
	top: calc(var(--ouf-pill-h) + var(--ouf-stem));
	border-top: 4px solid var(--wp--preset--color--slate);
}

/* Fixed width — the cards keep one size at every viewport and the track scrolls
   instead of the cards stretching. */
.ouf-milestone {
	display: flex;
	flex: 0 0 15rem;
	flex-direction: column;
	scroll-snap-align: start;
}

/* Every year carries the same slate; only the latest is picked out in amber, so
   the accent reads as "where we are now" rather than as a progression. The
   shortcode flags the last entry — see ouf_timeline_shortcode(). */
.ouf-year-pill {
	position: relative;
	display: flex;
	align-items: center;
	/* Centred over its card, so the stem drops down the middle of the entry. */
	align-self: center;
	height: var(--ouf-pill-h);
	margin: 0;
	padding-inline: 1.1em;
	border-radius: var(--ouf-radius-lg);
	background-color: var(--wp--preset--color--blue);
	color: var(--wp--preset--color--white);
	font-size: var(--wp--preset--font-size--x-large);
	font-weight: 700;
	letter-spacing: 0.02em;
}

/* The most recent year. Amber comes from theme.json, so it is also available in
   the editor's colour picker. */
.ouf-milestone.is-current .ouf-year-pill {
	background-color: var(--wp--preset--color--amber);
}

/* Stem and node hang off the pill rather than the item, so they stay centred
   under it whatever the label's width. */
.ouf-year-pill::after {
	content: '';
	position: absolute;
	inset-inline-start: 50%;
	top: 100%;
	height: calc(var(--ouf-stem) * 2);
	border-inline-start: 2px solid var(--wp--preset--color--slate);
}

/* The node sits where the stem meets the card, not where it crosses the rule. */
.ouf-year-pill::before {
	content: '';
	position: absolute;
	z-index: 1;
	inset-inline-start: 50%;
	top: calc(100% + var(--ouf-stem) * 2);
	width: 0.65rem;
	height: 0.65rem;
	border: 2px solid var(--wp--preset--color--slate);
	border-radius: 50%;
	background-color: var(--wp--preset--color--white);
	translate: -50% -50%;
}

.ouf-milestone-card {
	flex: 1;
	margin-block-start: calc(var(--ouf-stem) * 2);
	padding: var(--wp--preset--spacing--30);
	border: 1px solid color-mix(in srgb, var(--wp--preset--color--slate) 50%, transparent);
	border-radius: var(--ouf-radius-lg);
	background-color: var(--wp--preset--color--mist);
	font-size: var(--wp--preset--font-size--medium);
}

.ouf-milestone-card :is(ul, ol) {
	margin-block: 0;
}

/* -----------------------------------------------------------------------------
 * 5. Banner
 * -------------------------------------------------------------------------- */

/* The navy showing below the cover is the band drawn under the banner. The strip
   above it is the nav itself, which needs nothing from here.

   The chevron is sized from the banner height, not its width, so the logo has to
   be placed from the same figures rather than left to the column grid — the two
   drift apart otherwise. --ouf-logo-x is the mark's optical centre, x=260 of the
   shape's 1000-tall viewBox: right of the body's midpoint, because the shape
   widens towards the point at the height the mark sits. */
.ouf-hero {
	--ouf-panel-h: calc(var(--ouf-hero-h) + var(--ouf-hero-foot) / 2 + var(--ouf-header-h) / 2);
	--ouf-logo-x: calc(0.26 * var(--ouf-panel-h));

	position: relative;
	padding-bottom: var(--ouf-hero-foot);
}

/* The mark is out of flow, so the cover is the first in-flow child and its
   blockGap margin would otherwise collapse through and drop the whole banner. */
.ouf-hero-cover {
	min-height: var(--ouf-hero-h);
	margin-block-start: 0;
}

/* The white chevron. Bleeds off the left edge and outranks the header so it can
   cross the nav. It starts and finishes halfway into the navy strips top and
   bottom, rather than covering either of them outright. */
.ouf-hero::before {
	content: '';
	position: absolute;
	z-index: 101;
	top: calc(var(--ouf-header-h) / -2);
	bottom: calc(var(--ouf-hero-foot) / 2);
	inset-inline-start: 0;
	width: 46%;
	background: url('../images/ouf-banner-panel.svg') no-repeat left center;
	background-size: auto 100%;
}

/* Core gives the cover's inner container its own stacking context, which would
   trap the logo and headline underneath the panel above. */
.ouf-hero .wp-block-cover__inner-container {
	z-index: auto;
}

.ouf-hero-content {
	position: relative;
	z-index: 102;
}

/* Pinned to the middle of the chevron's body, both axes, so it stays centred at
   any viewport width. Its offsets are measured from the cover, so the column it
   sits in must stay unpositioned — that column only exists to reserve width. */
.ouf-hero-logo {
	position: absolute;
	z-index: 102;
	top: calc(var(--ouf-panel-h) / 2 - var(--ouf-header-h) / 2);
	inset-inline-start: var(--ouf-logo-x);
	margin: 0;
	translate: -50% -50%;
}

/* Sized here rather than from a preset: core marks preset font sizes !important,
   which no rule of ours could override. */
.ouf-hero-title {
	font-size: clamp(4.5rem, 10vw, 9rem);
	line-height: 1;
	text-transform: uppercase;
}

.ouf-hero-content p {
	font-size: var(--wp--preset--font-size--large);
}

/* Second half of the headline: its own line beneath the first, in amber, and the
   ratio that squares the two lines off at the same width. Set in Barlow Condensed
   "UNLOCKING" advances 3.878em against 10.056em for "A STRATEGIC NATIONAL ASSET",
   so the smaller line wants 3.878 / 10.056 of the larger — near enough 0.386. In
   em rather than its own clamp, so the two stay locked at every width. Breaking
   with display rather than a <br> keeps the line where it belongs whoever edits
   the heading next. */
.ouf-hero-title__sub {
	display: block;
	color: var(--wp--preset--color--amber);
	font-size: 0.386em;
	line-height: 1.15;
}

/* Small, tight call to action, as drawn. Light on the photograph rather than the
   navy the theme gives buttons elsewhere — navy on a dark banner disappears. */
.ouf-btn-sm .wp-block-button__link {
	padding: 0.5em 1.1em;
	background-color: var(--wp--preset--color--slate);
	color: var(--wp--preset--color--white);
	font-size: var(--wp--preset--font-size--medium);
	letter-spacing: 0.08em;
	text-transform: uppercase;
}

.ouf-btn-sm .wp-block-button__link:where(:hover, :focus-visible) {
	background-color: var(--wp--preset--color--mist);
	color: var(--wp--preset--color--navy);
}

/* Below 900px the chevron becomes a faint full-width wash behind the headline,
   and the logo goes with it — there's no shape left to centre it on. Collapsing
   here rather than at the 768px tablet breakpoint keeps the panel and the
   headline from crowding each other in the range between. */
@media (width < 900px) {
	.ouf-hero::before {
		width: 100%;
		opacity: 0.08;
	}

	.ouf-hero-logo,
	.ouf-hero-panel {
		display: none;
	}
}

/* -----------------------------------------------------------------------------
 * 6. Brand shapes
 * -------------------------------------------------------------------------- */

/* White hero panel with an angled trailing edge. */
.ouf-clip-angle {
	clip-path: polygon(0 0, 100% 0, calc(100% - var(--ouf-angle)) 100%, 0 100%);
}

/* The angle eats too much width on a phone — square it off. */
@media (width < 768px) {
	.ouf-clip-angle {
		clip-path: none;
	}
}

/* -----------------------------------------------------------------------------
 * 6. Behaviour
 * -------------------------------------------------------------------------- */

@media (prefers-reduced-motion: no-preference) {
	html {
		scroll-behavior: smooth;
	}
}

/* Stop anchored bands from landing underneath the sticky header. */
[id] {
	scroll-margin-top: calc(var(--ouf-header-h) + var(--wp--preset--spacing--30));
}
