/*
Theme Name: Wakonda
Theme URI: https://github.com/abutterworth/wakonda-wp
Author: Wakonda Coop
Description: Classic theme for the Wakonda Coop site — a public marketing site plus a private shareholder section. Pairs with the Wakonda Core plugin, which supplies the Event post type, the shareholder role, and the access control.
Requires at least: 6.7
Tested up to: 7.1
Requires PHP: 8.2
Version: 0.24.1
License: GNU General Public License v2 or later
License URI: http://www.gnu.org/licenses/gpl-2.0.html
Text Domain: wakonda
Tags: one-column, block-patterns, custom-menu, editor-style, wide-blocks, translation-ready
*/

/* -------------------------------------------------------------------------
 * Tokens.
 *
 * The DELIVERED palette (Design, 2026-08-26): two hues and their tints —
 * Wakonda Green #20483d (with a 70% text tint) and Wakonda Tan #d8cfb3
 * (with 50/40% washes). theme.json holds them; every colour here routes
 * through these role tokens. Alpha tints are stored flattened on paper —
 * opaque values keep AA math and layering predictable:
 *   Green 70 on paper = #637f77, Tan 50 = #ebe7d9, Tan 40 = #f0ece0.
 * ink-soft is Green at 75, not the delivered 70: the 70% tint measures
 * 4.35:1 on paper, a hair under AA for the 16px excerpts that use this
 * token; +5 points lands 4.98:1 and is visually indistinguishable.
 * ink stays Pine Ink — Design has not delivered a text black (yet).
 * ---------------------------------------------------------------------- */

:root {
	--wakonda-ink: var(--wp--preset--color--contrast, #1f1f1f);
	--wakonda-ink-soft: #58766e; /* Wakonda Green 75 on paper */
	--wakonda-paper: var(--wp--preset--color--paper, #fff);
	--wakonda-surface: var(--wp--preset--color--tertiary, #ebe7d9); /* Tan 50 */
	--wakonda-accent: var(--wp--preset--color--primary, #20483d);
	--wakonda-accent-deep: var(--wp--preset--color--primary-deep, #20483d);
	--wakonda-line: #e2e0d8;
	--wakonda-line-strong: #b3b1a7;

	/* Type on the one dark band (the footer, Wakonda Green ground). */
	--wakonda-on-dark: #ebe7d9; /* Tan 50 — tan type on green */
	--wakonda-on-dark-soft: #b7c3b9;

	/*
	 * The header shares the content/footer container — one aligned edge
	 * from masthead to colophon. (It used to breathe 72rem, which left the
	 * logo and nav sitting 2rem outside the content edge on desktop.)
	 */
	--wakonda-header-width: var(--wp--style--global--wide-size, 68rem);
	--wakonda-header-gap: 2rem;

	/* Side gutter for every band of the page. */
	--wakonda-gutter: var(--wp--style--root--padding-left, var(--wp--preset--spacing--50, 1.5rem));

	/* Reading measure; templates widen it per layout, never per element. */
	--wakonda-measure: var(--wp--style--global--content-size, 42rem);
}

/*
 * Type sizes come from ONE place: the theme.json presets, referenced
 * everywhere as var(--wp--preset--font-size--*). The step names and
 * line-height ratios come from the designer's Figma sheet (2026-08-26) —
 * x-small (Body XS 12/16), small (Eyebrow and Label 14/20, Body Small
 * 14/22), medium (Body 16/28), large (H5 18/24, and the Link style
 * 18/28), x-large (H4 20/30), xx-large (H3 22/32), huge (H2 26/32),
 * gigantic (H1 32/48). The sizes themselves moved up a step 2026-09-09
 * (small 14→16 … huge 26→28; gigantic stays 32), so the sheet's px pairs
 * are where the ratios come from, not what renders. theme.json is where
 * a step's value changes; the rules below only say which element uses
 * which step, and carry the line-heights (per-role, so one size can serve
 * two roles — H5 vs Link). No fluid type anywhere — narrow screens get
 * the mobile set below, which re-declares the same WP variables.
 */
@media (max-width: 40rem) {
	:root {
		--wp--preset--font-size--gigantic: var(--wp--preset--font-size--huge); /* H1 drops to the H2 size */
	}
}

/* -------------------------------------------------------------------------
 * Base.
 *
 * Font families, the base size and line-height come from theme.json — core
 * emits them against body and h1–h6, so they reach template markup and block
 * content alike. This layer only adds what theme.json cannot express.
 * ---------------------------------------------------------------------- */

body {
	margin: 0;
	background: var(--wakonda-paper);
	color: var(--wakonda-ink);
	-webkit-font-smoothing: antialiased;

	/* Footer sits at the viewport bottom even under a short 404. */
	display: flex;
	flex-direction: column;
	min-height: 100vh;
}

.site-content {
	flex: 1 0 auto;
}

/*
 * Without this an unconstrained attachment (medium_large is 768px) forces the
 * document wider than a phone viewport, and every full-width band — the header
 * included — stops at the viewport edge while the content scrolls past it.
 */
img,
video {
	max-width: 100%;
	height: auto;
}

h1,
h2,
h3,
h4,
h5,
h6 {
	margin: 0;
	overflow-wrap: break-word;
}

/*
 * The ramp's heading steps. Line-heights are the sheet's pairs (H1 32/48,
 * H2 26/32, H3 22/32, H4 20/30, H5 18/24) as ratios, so they follow a
 * step wherever theme.json moves it. h6 sits at label size, still Lora.
 */
h1 {
	font-size: var(--wp--preset--font-size--gigantic);
	line-height: 1.5;
}

h2 {
	font-size: var(--wp--preset--font-size--huge);
	line-height: 1.23;
}

h3 {
	font-size: var(--wp--preset--font-size--xx-large);
	line-height: 1.45;
}

h4 {
	font-size: var(--wp--preset--font-size--x-large);
	line-height: 1.5;
}

h5 {
	font-size: var(--wp--preset--font-size--large);
	line-height: 1.33;
}

h6 {
	font-size: var(--wp--preset--font-size--small);
	line-height: 1.43;
}

/*
 * Monochrome links: colour cannot distinguish them, so underlines have to.
 * Chrome (nav, cards, titles) opts out locally and signals on hover instead.
 */
a {
	color: inherit;
	text-decoration-thickness: 1px;
	text-underline-offset: 0.15em;
}

:focus-visible {
	outline: 2px solid var(--wakonda-ink);
	outline-offset: 2px;
}

::selection {
	background: var(--wakonda-accent-deep);
	color: var(--wakonda-paper);
}

.screen-reader-text {
	position: absolute;
	width: 1px;
	height: 1px;
	padding: 0;
	margin: -1px;
	overflow: hidden;
	clip-path: inset(50%);
	white-space: nowrap;
	border: 0;
}

.skip-link:focus {
	position: absolute;
	top: 0.5rem;
	left: 0.5rem;
	z-index: 100;
	width: auto;
	height: auto;
	padding: 0.75rem 1rem;
	background: var(--wakonda-paper);
	clip-path: none;
}

/*
 * The Eyebrow style (caps, forest green) — dates, post types,
 * section headings. The green is what makes metadata read as wayfinding
 * rather than content.
 */
.entry-meta,
.event__date,
.event-list__date,
.news-list__date,
.search-list__type,
.news-lead__date,
.news-row__date {
	margin: 0;
	font-size: var(--wp--preset--font-size--small); /* Eyebrow */
	font-weight: 600;
	line-height: 1.43;
	letter-spacing: 0.07em;
	text-transform: uppercase;
	color: var(--wakonda-ink-soft);
}

/*
 * The start time under a date steps back out of the eyebrow voice —
 * "Starts 10:30 AM" in quiet Body Small, so the date stays the anchor.
 */
.event-list__time {
	font-weight: 400;
	letter-spacing: normal;
	text-transform: none;
	color: var(--wakonda-ink-soft);
}

/*
 * "Raffle" as a small bordered tag beside the date, so raffles read as the
 * ongoing statuses they are wherever they appear in a calendar list.
 */
.event-list__badge {
	display: inline-block;
	margin-inline-start: 0.5rem;
	padding: 0.05rem 0.5rem;
	border: 1px solid var(--wakonda-line-strong);
	border-radius: 2px;
	font-size: var(--wp--preset--font-size--x-small);
	letter-spacing: 0.08em;
	vertical-align: 0.1em;
}

/* -------------------------------------------------------------------------
 * Buttons and forms.
 *
 * .wp-element-button covers block buttons, the File block's download button
 * and the search submit; .button-outline is the header's Log In.
 * ---------------------------------------------------------------------- */

.wp-element-button,
.wp-block-button__link,
.search-submit {
	display: inline-block;
	padding: 0.6rem 1.4rem;
	background: var(--wakonda-ink);
	border: 1px solid var(--wakonda-ink);
	border-radius: 2px;
	color: var(--wakonda-paper);
	font: inherit;
	font-size: var(--wp--preset--font-size--small);
	font-weight: 500;
	line-height: 1.4;
	text-decoration: none;
	cursor: pointer;
	transition: background-color 150ms ease, color 150ms ease;
}

.wp-element-button:hover,
.wp-block-button__link:hover,
.search-submit:hover {
	background: var(--wakonda-paper);
	color: var(--wakonda-ink);
}

.is-style-outline .wp-block-button__link,
.button-outline {
	display: inline-block;
	padding: 0.6rem 1.4rem;
	background: transparent;
	border: 1px solid currentColor;
	border-radius: 2px;
	color: inherit;
	font-size: var(--wp--preset--font-size--small);
	font-weight: 500;
	line-height: 1.4;
	text-decoration: none;
	cursor: pointer;
	transition: background-color 150ms ease, color 150ms ease;
}

.is-style-outline .wp-block-button__link:hover,
.button-outline:hover {
	background: var(--wakonda-ink);
	border-color: var(--wakonda-ink);
	color: var(--wakonda-paper);
}

.search-form {
	display: flex;
	gap: 0.5rem;
	max-width: 28rem;
}

.search-form label {
	flex: 1;
}

.search-field {
	width: 100%;
	padding: 0.55rem 0.875rem;
	background: var(--wakonda-paper);
	border: 1px solid var(--wakonda-line-strong);
	border-radius: 2px;
	font: inherit;
	font-size: var(--wp--preset--font-size--medium);
	color: inherit;
}

.search-field:focus {
	border-color: var(--wakonda-ink);
	outline: none;
}

/* -------------------------------------------------------------------------
 * Site header — layout.
 * ---------------------------------------------------------------------- */

/* --- shared ------------------------------------------------------------ */

.site-header {
	background: var(--wakonda-paper);
}

.site-header__inner {
	display: flex;
	align-items: center;
	gap: var(--wakonda-header-gap);
	max-width: var(--wakonda-header-width);
	margin-inline: auto;
	/* The shared gutter, like .site-main and the footer — never a literal,
	 * or the header drifts the day the root padding changes. */
	padding: 1rem var(--wakonda-gutter);
}

/*
 * Both flex containers, so neither the wrapper nor the link creates a line box.
 * As `inline-flex` the link sat on a baseline, and the strut's descender space
 * below it made the div taller than the image — which left the mark 2.5px above
 * the centre it was supposed to be aligned on.
 */
.site-logo {
	display: flex;
	align-items: center;
}

.site-logo a {
	display: flex;
	align-items: center;
	text-decoration: none;
}

/*
 * Deliberately no `display` here. Setting it on the element selector would
 * score 0,1,1 and beat the class rules below that decide which mark shows.
 *
 * `max-width: none` opts the logo out of the global image rule. As a grid item
 * in a `1fr` column the mark would otherwise be allowed to shrink with the
 * track, so it visibly shrank to nothing in the last few pixels before the
 * mobile breakpoint. Both marks have explicit widths well inside any viewport,
 * so nothing here can overflow.
 */
.site-logo img {
	height: auto;
	max-width: none;
}

/*
 * Bird alone by default; the member header swaps in the lockup on wide screens
 * only. Written as a min-width override so the two rules never compete at
 * equal specificity — media queries add none of their own.
 */
.site-logo .site-logo__mark { display: block; width: 1.75rem; }
.site-logo .site-logo__lockup { display: none; width: 14rem; }

/*
 * <wakonda-nav> reads --wakonda-nav-mode to decide whether to run the
 * priority-plus overflow ("bar") or sit behind the menu button ("stack"), so
 * the breakpoint is defined here only and never duplicated in JavaScript.
 */
wakonda-nav {
	--wakonda-nav-mode: bar;
	display: block;
	min-width: 0;
}

.nav-list {
	display: flex;
	align-items: center;
	gap: var(--wakonda-header-gap);
	margin: 0;
	padding: 0;
	list-style: none;
}

.nav-list a {
	text-decoration: none;
}

.site-header__account {
	display: flex;
	align-items: center;
	gap: 1rem;
	margin-inline-start: auto;
	white-space: nowrap;
}

.site-header__link { text-decoration: none; }

/* --- header type -------------------------------------------------------- */

.nav-list a,
.nav-extra a,
.site-header__link {
	font-size: var(--wp--preset--font-size--medium);
	font-weight: 500;
}

.nav-list a:hover,
.nav-extra a:hover,
.site-header__link:hover {
	text-decoration: underline;
	text-underline-offset: 0.45em;
	text-decoration-thickness: 1px;
}

/*
 * The page being read keeps its underline. Underline rather than weight, so
 * the item is the same width on every page and <wakonda-nav>'s measuring
 * never shifts between them.
 */
.nav-list .current-menu-item > a,
.nav-list .current_page_item > a,
.nav-list .current-menu-ancestor > a,
.nav-list .current_page_ancestor > a {
	text-decoration: underline;
	text-underline-offset: 0.45em;
	text-decoration-thickness: 1px;
}

/* --- account menu ------------------------------------------------------ */

.account-menu {
	position: relative;
	display: inline-flex;
}

.account-menu__button {
	display: inline-flex;
	align-items: center;
	padding: 0.25rem;
	background: none;
	border: 0;
	color: inherit;
	cursor: pointer;
}

.account-menu__list {
	position: absolute;
	inset-inline-end: 0;
	top: calc(100% + 0.25rem);
	z-index: 30;
	min-width: 11rem;
	margin: 0;
	padding: 0.5rem 0;
	list-style: none;
	background: var(--wakonda-paper);
	border: 1px solid var(--wakonda-line);
	border-radius: 2px;
	box-shadow: 0 10px 30px rgba(0, 0, 0, 0.09);
}

/*
 * Visible until the element upgrades, so the links stay reachable with
 * JavaScript off rather than being hidden by CSS that nothing can undo.
 */
.account-menu.is-ready .account-menu__list {
	display: none;
}

.account-menu.is-ready.is-open .account-menu__list {
	display: block;
}

.account-menu__list a {
	display: block;
	padding: 0.4rem 1rem;
	white-space: nowrap;
	text-decoration: none;
	font-size: var(--wp--preset--font-size--small);
}

.account-menu__list a:hover {
	background: var(--wakonda-surface);
}

/*
 * The header bar drops "Public Home" / "Shareholder Home" on narrow screens.
 * It is not lost — it reappears at the end of the left-hand menu, alongside
 * the rest of the navigation. Hidden here, shown in the narrow block below.
 */
.nav-extra {
	display: none;
	margin: 0;
	padding: 0;
	list-style: none;
}

/* --- public: mark left, nav centred, button right ---------------------- */

/*
 * Grid, not flex, so the nav is centred on the *container* rather than on the
 * space left between the logo and the button. With auto margins the unequal
 * widths of those two drag it off centre — measured 31px on a 1280 viewport.
 * Three columns, 1fr either side, puts it exactly in the middle.
 *
 * The menu button is display:none at this width, so it creates no grid item
 * and the three remaining children land one per column.
 */
@media (min-width: 48.0625rem) {
	.site-header--public .site-header__inner {
		display: grid;
		grid-template-columns: 1fr minmax(0, auto) 1fr;
		align-items: center;
	}

	.site-header--public .site-header__account {
		justify-self: end;
	}
}

.site-header--public .nav-list {
	justify-content: center;
}

/* --- member: lockup + weather, then nav + account ---------------------- */

/*
 * Both headers sit on paper — the 2026-08-26 design keeps the member chrome
 * white; being "inside" is signalled by the member nav itself, not a tinted
 * band. (The pre-palette build tinted this with the surface tone.)
 */
.site-header--member {
	background: var(--wakonda-paper);
}

@media (min-width: 48.0625rem) {
	.site-header--member .site-logo .site-logo__mark { display: none; }
	.site-header--member .site-logo .site-logo__lockup { display: block; }

	/*
	 * A two-by-two grid: the lockup and the camp weather on the first row,
	 * the nav and the account controls on the second, the right-hand column
	 * sized to its content with everything in it pushed to the end. Grid
	 * rather than the flex-wrap this used to be because a wrapped flex row
	 * cannot be told to break after the weather — only a 100%-basis item
	 * forces a new line, and the lockup was that item.
	 *
	 * The nav's column is minmax(0, 1fr). The 0 is what makes the nav
	 * *shrink* rather than widen its column — and what gives <wakonda-nav> a
	 * real width to measure against. Sized to its content it reports that
	 * everything fits and moves nothing into More.
	 *
	 * align-items: center — the second row holds a 21px line of nav text and
	 * a 32px icon button. Top-aligning the boxes and centring inside each put
	 * their text on different baselines ("Public Home" 3px below the nav
	 * links, the glyph 5.5px below their centre); centring the boxes makes
	 * them agree.
	 */
	.site-header--member .site-header__inner {
		display: grid;
		grid-template-columns: minmax(0, 1fr) auto;
		align-items: center;
		column-gap: var(--wakonda-header-gap);
		row-gap: 1.25rem;
	}

	.site-header--member .site-logo {
		grid-column: 1;
		grid-row: 1;
	}

	.site-header--member .site-weather {
		grid-column: 2;
		grid-row: 1;
		justify-self: end;
	}

	.site-header--member wakonda-nav {
		grid-column: 1;
		grid-row: 2;
		min-width: 0;
	}

	.site-header--member .site-header__account {
		grid-column: 2;
		grid-row: 2;
		justify-self: end;
	}
}

/* --- the More dropdown ------------------------------------------------- */

/*
 * Overflow items are moved here by <wakonda-nav> rather than wrapped, so the
 * row keeps its height and the account controls are never pushed onto a second
 * line. nowrap is what forces the overflow to be measurable in the first place.
 */
.site-header--public .nav-list,
.site-header--member .nav-list {
	flex-wrap: nowrap;
}

.nav-list > li {
	white-space: nowrap;
}

.nav-more {
	position: relative;
}

.nav-more[hidden] {
	display: none;
}

.nav-more__button {
	padding: 0;
	background: none;
	border: 0;
	color: inherit;
	font: inherit;
	font-size: var(--wp--preset--font-size--small);
	font-weight: 500;
	cursor: pointer;
}

.nav-more__button::after {
	content: " \25BE";
}

.nav-more__list {
	position: absolute;
	inset-inline-end: 0;
	top: calc(100% + 0.5rem);
	z-index: 20;
	display: none;
	min-width: 12rem;
	margin: 0;
	padding: 0.5rem 0;
	list-style: none;
	background: var(--wakonda-paper);
	border: 1px solid var(--wakonda-line);
	border-radius: 2px;
	box-shadow: 0 10px 30px rgba(0, 0, 0, 0.09);
}

.nav-more.is-open .nav-more__list {
	display: block;
}

.nav-more__list > li {
	white-space: nowrap;
}

.nav-more__list a {
	display: block;
	padding: 0.4rem 1rem;
	text-decoration: none;
}

.nav-more__list a:hover {
	background: var(--wakonda-surface);
}

/* --- submenus ----------------------------------------------------------- */

/*
 * wp_nav_menu nests children as ul.sub-menu (ul.children from the
 * wp_page_menu fallback). Same progressive rule as the collapse: the
 * dropdown behaviour is scoped to wakonda-nav.is-ready, so before the
 * element upgrades — or with JavaScript off — children stay visible as a
 * plain indented list instead of vanishing behind a button that is not
 * there.
 */

.nav-list .sub-menu,
.nav-list .children {
	margin: 0;
	padding: 0 0 0 1rem;
	list-style: none;
}

.nav-sub__button {
	padding: 0 0.15rem;
	background: none;
	border: 0;
	color: inherit;
	font: inherit;
	cursor: pointer;
}

.nav-sub__button::after {
	content: "\25BE";
}

.nav-sub__button[aria-expanded="true"]::after {
	content: "\25B4";
}

/* Bar mode: a dropdown panel, same language as the More menu. Open on the
 * caret (is-open), on hover, or while anything inside has focus. */
wakonda-nav.is-ready .nav-list > li.menu-item-has-children,
wakonda-nav.is-ready .nav-list > li.page_item_has_children {
	position: relative;
}

wakonda-nav.is-ready .nav-list > li > .sub-menu,
wakonda-nav.is-ready .nav-list > li > .children {
	position: absolute;
	inset-inline-start: 0;
	top: calc(100% + 0.5rem);
	z-index: 20;
	visibility: hidden;
	opacity: 0;
	min-width: 12rem;
	padding: 0.5rem 0;
	background: var(--wakonda-paper);
	border: 1px solid var(--wakonda-line);
	border-radius: 2px;
	box-shadow: 0 10px 30px rgba(0, 0, 0, 0.09);

	/*
	 * Hidden via visibility with a 150ms delay, not display — so a pointer
	 * that briefly strays off the item mid-travel has a grace window in
	 * which the still-visible panel can catch it and keep the menu open.
	 */
	transition: opacity 120ms ease, visibility 0s 150ms;
}

/*
 * The hover bridge: the panel floats 0.5rem below the item, and that gap
 * used to break li:hover on the way down and snap the menu shut. An
 * invisible strip on the panel spans it, so the pointer never leaves the
 * hover tree; the grace above forgives diagonal wobbles besides.
 */
wakonda-nav.is-ready .nav-list > li > .sub-menu::before,
wakonda-nav.is-ready .nav-list > li > .children::before {
	content: "";
	position: absolute;
	inset-inline: 0;
	top: -0.6rem;
	height: 0.6rem;
}

wakonda-nav.is-ready .nav-list > li.is-open > .sub-menu,
wakonda-nav.is-ready .nav-list > li:hover > .sub-menu,
wakonda-nav.is-ready .nav-list > li:focus-within > .sub-menu,
wakonda-nav.is-ready .nav-list > li.is-open > .children,
wakonda-nav.is-ready .nav-list > li:hover > .children,
wakonda-nav.is-ready .nav-list > li:focus-within > .children {
	visibility: visible;
	opacity: 1;
	transition-delay: 0s, 0s;
}

wakonda-nav.is-ready .nav-list > li > .sub-menu a,
wakonda-nav.is-ready .nav-list > li > .children a {
	display: block;
	padding: 0.4rem 1rem;
	white-space: nowrap;
}

wakonda-nav.is-ready .nav-list > li > .sub-menu a:hover,
wakonda-nav.is-ready .nav-list > li > .children a:hover {
	background: var(--wakonda-surface);
}

/*
 * Inside the More panel a nested dropdown makes no sense — the direct-child
 * selectors above already stop applying once an item moves in there, so its
 * children render as the plain indented list; just drop the caret.
 */
.nav-more__list .nav-sub__button {
	display: none;
}

/* --- narrow screens ---------------------------------------------------- */

.nav-toggle {
	display: none;
	padding: 0.5rem;
	background: none;
	border: 0;
	color: inherit;
	cursor: pointer;
}

.nav-toggle__bars,
.nav-toggle__bars::before,
.nav-toggle__bars::after {
	display: block;
	width: 1.35rem;
	height: 2px;
	background: currentColor;
}

.nav-toggle__bars::before,
.nav-toggle__bars::after {
	content: "";
	position: relative;
}

.nav-toggle__bars::before { top: -0.45rem; }
.nav-toggle__bars::after { top: 0.25rem; }

@media (max-width: 48rem) {
	.nav-toggle { display: block; }

	/*
	 * Grid, not flex with auto margins — same reason the public nav is centred
	 * with grid on desktop. Auto margins centre the logo in the space *between*
	 * the menu button and the account controls, and those are not the same
	 * width (the Log In button is much wider than the account glyph), so the
	 * mark ends up visibly off centre. Three columns with 1fr either side
	 * centre it on the header itself.
	 */
	.site-header__inner,
	.site-header--public .site-header__inner,
	.site-header--member .site-header__inner {
		display: grid;
		grid-template-columns: 1fr auto 1fr;
		align-items: center;
		gap: 1rem;
	}

	/*
	 * Placed explicitly rather than left to auto-flow. The nav sits between the
	 * logo and the account controls in the DOM, so once it is open and spanning
	 * every column, auto-placement pushes the account onto a third row.
	 */
	.nav-toggle {
		grid-column: 1;
		grid-row: 1;
		justify-self: start;
	}

	.site-logo,
	.site-header--member .site-logo {
		grid-column: 2;
		grid-row: 1;
		margin-inline: 0;
		justify-self: center;
	}

	.site-header__account {
		grid-column: 3;
		grid-row: 1;
		justify-self: end;
		margin-inline-start: 0;
	}

	/*
	 * The bar keeps to menu button, logo, account glyph. The contextual link
	 * moves to the foot of the menu, set off by a rule so it reads as a
	 * different kind of destination from the pages above it.
	 */
	.site-header__link {
		display: none;
	}

	.nav-extra {
		display: block;
		margin-block-start: 0.75rem;
		padding-block-start: 0.75rem;
		border-block-start: 1px solid var(--wakonda-line);
	}

	.nav-extra a {
		text-decoration: none;
	}

	wakonda-nav {
		--wakonda-nav-mode: stack;
	}

	/* Collapsed only once the element has upgraded and taken responsibility. */
	wakonda-nav.is-ready {
		display: none;
	}

	/* Full width on its own row beneath the bar. */
	wakonda-nav.is-ready.is-open {
		display: block;
		grid-column: 1 / -1;
		grid-row: 2;
		border-block-start: 1px solid var(--wakonda-line);
	}

	.site-header--public .nav-list,
	.site-header--member .nav-list {
		flex-wrap: wrap;
	}

	.nav-list {
		flex-direction: column;
		align-items: flex-start;
		gap: 0.75rem;
		padding-block: 1rem;
	}

	/* Stacked: children are a static indented list under their parent — a
	 * floating panel has nowhere sensible to float — and the caret goes,
	 * along with the bar mode's hide/reveal and its hover bridge. */
	wakonda-nav.is-ready .nav-list > li > .sub-menu,
	wakonda-nav.is-ready .nav-list > li > .children {
		position: static;
		visibility: visible;
		opacity: 1;
		transition: none;
		min-width: 0;
		padding: 0.25rem 0 0 1rem;
		background: none;
		border: 0;
		box-shadow: none;
	}

	wakonda-nav.is-ready .nav-list > li > .sub-menu::before,
	wakonda-nav.is-ready .nav-list > li > .children::before {
		content: none;
	}

	.nav-list .nav-sub__button {
		display: none;
	}
}

/* -------------------------------------------------------------------------
 * Camp weather.
 *
 * <wakonda-weather>, in the member header, in a grid cell of its own —
 * never inside <wakonda-nav>, whose overflow measuring must not see it,
 * nor the account block. Wide screens: the top-right cell, beside the
 * lockup and above the account controls. Phones: a full-width row under
 * the bar, in the flow (nothing here is sticky). Rendered as a bare link;
 * once the element has fetched the forecast it becomes a trigger — the
 * whole today line: glyph, temperature, summary, high and low — with a
 * disclosure panel of the five days and the link beneath. The host gives
 * it two things: a colour, which the trigger inherits, and a muted tone
 * in --wakonda-weather-soft for the lows, labels and source line. The
 * panel is always ink on paper, whatever band hosts it.
 * Spec: docs/weather-widget-spec.md.
 * ---------------------------------------------------------------------- */

.site-header {
	--wakonda-weather-soft: var(--wakonda-ink-soft);
}

.site-weather {
	position: relative;
	display: inline-flex;
	align-items: center;
}

/* The shell before the element upgrades — and the whole widget when the
 * fetch fails: one link, in the header's link voice. */
.site-weather__link {
	font-size: var(--wp--preset--font-size--small);
	font-weight: 500;
	text-decoration: none;
}

.site-weather__link:hover {
	text-decoration: underline;
	text-underline-offset: 0.45em;
	text-decoration-thickness: 1px;
}

/* --- trigger ------------------------------------------------------------ */

/*
 * The trigger is the whole today line at every width: glyph and
 * temperature, the current summary, today's high and low, and a caret in
 * the nav's voice so a row of facts still reads as something to press. A
 * chip sized to its content on wide screens; the full row under the bar
 * on phones (below). One size across, the button's; the temperature is
 * set apart by the heading face, not by size.
 */
.site-weather__button {
	display: inline-flex;
	align-items: center;
	gap: 7px;
	padding: 5px 7px;
	background: none;
	border: 0;
	border-radius: 2px;
	color: inherit;
	font: inherit;
	font-size: var(--wp--preset--font-size--small);
	line-height: 1;
	cursor: pointer;
}

.site-weather__button:hover,
.site-weather.is-open .site-weather__button {
	background: var(--wakonda-surface);
}

.site-weather__button::after {
	content: "\25BE";
	color: var(--wakonda-weather-soft);
}

.site-weather.is-open .site-weather__button::after {
	content: "\25B4";
}

.site-weather__glyph {
	flex: none;
	width: 24px;
	height: 24px;
}

.site-weather__temp {
	font-family: var(--wp--preset--font-family--heading);
	line-height: 1;
}

/*
 * The summary is what gives way when the row is short: min-width: 0 (a
 * flex item's default minimum is its content) and overflow: hidden let it
 * ellipsise instead of widening the trigger. The 12rem cap keeps a wordy
 * NWS summary from stretching the wide-screen chip.
 */
.site-weather__summary {
	min-width: 0;
	max-width: 12rem;
	overflow: hidden;
	text-overflow: ellipsis;
	white-space: nowrap;
	text-align: start;
	color: var(--wakonda-weather-soft);
}

/*
 * A hairline between the conditions and the range on wide screens. A
 * border on the range's own box, so it is 1em tall — line-height 1 — and
 * centred on the glyph by the button's align-items; the padding matches
 * the gap, so the line sits midway. Phones drop it: the slack between the
 * summary and the range divides them there.
 */
.site-weather__range {
	flex: none;
	padding-inline-start: 7px;
	border-inline-start: 1px solid var(--wakonda-line);
	white-space: nowrap;
}

.site-weather__label,
.site-weather__low {
	color: var(--wakonda-weather-soft);
}

/*
 * Each range label carries both its word ("High") and its letter ("H").
 * The letter is for the phone row and hidden here; there the word moves
 * off screen for assistive tech instead, so the range is read as
 * "High 68° Low 40°" at every width whatever is shown.
 */
.site-weather__label-short {
	display: none;
}

/* --- panel -------------------------------------------------------------- */

.site-weather__panel {
	--wakonda-weather-soft: var(--wakonda-ink-soft);
	box-sizing: border-box; /* min/max-width below are outside measures */
	position: absolute;
	inset-inline-end: 0;
	top: calc(100% + 0.25rem);
	z-index: 30;
	display: none;
	min-width: 19rem;
	padding: 1rem 1.25rem;
	background: var(--wakonda-paper);
	border: 1px solid var(--wakonda-line);
	border-radius: 2px;
	box-shadow: 0 10px 30px rgba(0, 0, 0, 0.09);
	color: var(--wakonda-ink);
	font-size: var(--wp--preset--font-size--small);
	line-height: 1.4;
	white-space: normal;
	text-align: start;
}

.site-weather.is-open .site-weather__panel {
	display: block;
}

.site-weather__days {
	display: flex;
	justify-content: space-between;
	gap: 0.5rem;
	margin: 0;
	padding: 0;
	list-style: none;
}

.site-weather__day {
	flex: 1 1 0;
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: 0.2rem;
	text-align: center;
}

.site-weather__weekday {
	font-size: var(--wp--preset--font-size--x-small);
}

.site-weather__source {
	margin: 0.75rem 0 0;
	font-size: var(--wp--preset--font-size--x-small);
	color: var(--wakonda-weather-soft);
}

.site-weather__source .site-weather__link {
	font-size: inherit;
	font-weight: 400;
	color: inherit;
	text-decoration: underline;
	text-underline-offset: 0.2em;
}

/* --- phones ------------------------------------------------------------- */

@media (max-width: 48rem) {
	/*
	 * The row: the widget's own full-width row under the bar, hairline
	 * above, in the header's flow. Auto-placed rather than pinned to a row,
	 * so it takes the first free one — row 2 while the nav is collapsed,
	 * row 3 beneath the nav when that is open — without an empty track and
	 * its gap in between.
	 */
	.site-header--member .site-weather {
		grid-column: 1 / -1;
		display: flex;
		padding-block-start: 0.5rem;
		border-block-start: 1px solid var(--wakonda-line);
	}

	/* The trigger fills the row and the summary takes the slack; min-width: 0
	 * on the button is what lets the summary give way instead of the row. */
	.site-weather__button {
		flex: 1 1 auto;
		min-width: 0;
		gap: 6px;
		padding: 3px 6px;
	}

	.site-weather__button .site-weather__glyph {
		width: 20px;
		height: 20px;
	}

	.site-weather__summary {
		flex: 1 1 auto;
		max-width: none;
	}

	.site-weather__range {
		padding-inline-start: 0;
		border-inline-start: 0;
	}

	/* "H 68° L 40°": the letters show, the words go off screen for
	 * assistive tech — the same recipe as .screen-reader-text. */
	.site-weather__label-long {
		position: absolute;
		width: 1px;
		height: 1px;
		padding: 0;
		margin: -1px;
		overflow: hidden;
		clip-path: inset(50%);
		white-space: nowrap;
	}

	.site-weather__label-short {
		display: inline;
	}

	/* The panel is the row's width exactly, hung from both its edges. */
	.site-weather__panel {
		inset-inline: 0;
		min-width: 0;
	}
}

/* -------------------------------------------------------------------------
 * Main column.
 *
 * One centred column per template; --wakonda-measure is set per layout and
 * everything inside inherits it. The front page opts out entirely — its
 * layout belongs to the page content and the constrained-children rules in
 * the entry-content section below.
 * ---------------------------------------------------------------------- */

.site-main {
	box-sizing: content-box;
	max-width: var(--wakonda-measure);
	margin-inline: auto;
	padding: 2.75rem var(--wakonda-gutter) 5.5rem;
}

.site-main--archive,
.site-main--search {
	--wakonda-measure: 56rem;
}

.site-main--shareholder {
	--wakonda-measure: var(--wp--style--global--wide-size, 68rem);
}

.site-main--front {
	max-width: none;
	padding: 0;

	/*
	 * The two front-page width knobs, deliberately separate from the global
	 * wide tier so tuning here never moves the shareholder home or footer.
	 * front-wide caps the alignwide sections; front-cap is where the FULL
	 * sections stop bleeding and centre instead — 90rem ≈ 1440px screens
	 * (100rem for 1600).
	 */
	--wakonda-front-wide: 76rem;
	--wakonda-front-cap: 90rem;
}

/* -------------------------------------------------------------------------
 * Page and single headers.
 * ---------------------------------------------------------------------- */

.entry-title {
	margin-block-end: 0.75rem;
	letter-spacing: -0.01em;
	text-wrap: balance;
}

/*
 * The signature mark under a title block: a short ink rule. It hangs off the
 * last element of the header — the meta line when there is one, otherwise
 * the title itself — so the rule always sits between heading matter and
 * content.
 */
.entry-title::after,
.entry-meta::after,
.event__date::after {
	content: "";
	display: block;
	width: 2.5rem;
	margin-block-start: 1.5rem;
	border-block-start: 3px solid var(--wakonda-ink);
}

/* Singles have a meta line under the title; the rule moves down to it. */
.site-main--single .entry-title::after,
.site-main--event .entry-title::after {
	content: none;
}

.entry-image {
	margin: 2.25rem 0 0;
}

.entry-image img {
	width: 100%;
	border-radius: 2px;
}

article > .entry-content,
.entry-image + .entry-content {
	margin-block-start: 2.25rem;
}

/*
 * The way back to the archive from a single: a plain link with a direction
 * glyph, not a button. (Dashboard sections link forward through their
 * clickable headings instead — see the shareholder-home block.)
 */
.archive-link {
	margin: 3.5rem 0 0;
	padding-block-start: 1.5rem;
	border-block-start: 1px solid var(--wakonda-line);
}

.archive-link a {
	font-family: var(--wp--preset--font-family--body);
	font-size: var(--wp--preset--font-size--large); /* Link, DM Sans bold */
	line-height: 1.56;
	font-weight: 700;
	text-decoration: none;
}

.archive-link a::before {
	content: "\2190\00a0\00a0";
}

.archive-link a:hover {
	text-decoration: underline;
	text-underline-offset: 0.3em;
}

/* -------------------------------------------------------------------------
 * Archives.
 * ---------------------------------------------------------------------- */

.archive-title {
	margin-block-end: 1.5rem;
	letter-spacing: -0.01em;
}

/* Upcoming | Previous — a two-cell segmented control. */
.archive-toggle {
	display: inline-flex;
	margin-block-end: 2.75rem;
	border: 1px solid var(--wakonda-ink);
	border-radius: 2px;
	overflow: hidden;
}

.archive-toggle a {
	padding: 0.45rem 1.2rem;
	font-size: var(--wp--preset--font-size--small);
	font-weight: 500;
	text-decoration: none;
}

.archive-toggle a + a {
	border-inline-start: 1px solid var(--wakonda-ink);
}

.archive-toggle a[aria-current="page"] {
	background: var(--wakonda-ink);
	color: var(--wakonda-paper);
}

.archive-toggle a:not([aria-current="page"]):hover {
	background: var(--wakonda-surface);
}

/* Empty states. */
.site-main--archive > p,
.shareholder-section > p:not([class]) {
	color: var(--wakonda-ink-soft);
}

/* --- events: date column left, hairline rows ----------------------------- */

.event-list,
.news-list,
.search-list {
	margin: 0;
	padding: 0;
	list-style: none;
}

.event-list__item,
.news-list__item,
.search-list__item {
	position: relative;
	padding-block: 1.5rem;
	border-block-end: 1px solid var(--wakonda-line);
}

.event-list__item:first-child,
.news-list__item:first-child,
.search-list__item:first-child {
	padding-block-start: 0.5rem;
}

/*
 * Two flexed columns — the date block and a __body wrapper (title +
 * excerpt) — three with the archive's thumbnail. Each column flows on its
 * own and the first baselines align, so a two-line date ("AUG 29 /
 * Starts 10:30 AM") can never push the body's excerpt down.
 */
.event-list__item {
	display: flex;
	align-items: first baseline;
	gap: 2rem;
}

.event-list__date {
	flex: none;
	width: 11rem;
	/* Tabular dates line the column up even in a proportional face. */
	font-variant-numeric: tabular-nums;
}

.event-list__body {
	flex: 1;
	min-width: 0;
}

.event-list__title {
	font-size: var(--wp--preset--font-size--xx-large); /* H3 */
	line-height: 1.45;
}

/* The bare excerpt <p> the templates emit after the title. */
.event-list__body > p:not([class]) {
	margin: 0.35rem 0 0;
	font-size: var(--wp--preset--font-size--medium);
}

.event-list__image {
	flex: none;
	align-self: flex-start;
}

.event-list__image img {
	display: block;
	width: 7.5rem;
	aspect-ratio: 4 / 3;
	object-fit: cover;
	border-radius: 2px;
}

.event-list__title a,
.news-list__title a,
.search-list__title a,
.news-lead__title a,
.news-row__title a,
.doc-list__title a,
.raffle-list__title a {
	text-decoration: none;
}

.event-list__title a:hover,
.news-list__title a:hover,
.search-list__title a:hover,
.news-lead__title a:hover,
.news-row__title a:hover,
.doc-list__title a:hover,
.raffle-list__title a:hover {
	text-decoration: underline;
	text-decoration-thickness: 1px;
	text-underline-offset: 0.2em;
}

@media (max-width: 40rem) {
	.event-list__item {
		display: block;
	}

	.event-list__date {
		width: auto;
		margin-block-end: 0.35rem;
	}

	.event-list__image {
		margin-block-start: 0.75rem;
	}
}

/* --- news and search: stacked editorial rows ---------------------------- */

.news-list__item,
.search-list__item {
	padding-block: 1.75rem;
}

.news-list__title,
.search-list__title {
	margin-block-start: 0.4rem;
	font-size: var(--wp--preset--font-size--large);
}

.news-list__item > p:not([class]),
.search-list__item > p:not([class]) {
	margin: 0.6rem 0 0;
	font-size: var(--wp--preset--font-size--medium);
	max-width: 46rem;
}

.site-main--search .search-form {
	margin-block-end: 2.75rem;
}

/* --- pagination --------------------------------------------------------- */

.pagination {
	margin-block-start: 2.75rem;
}

.pagination .nav-links {
	display: flex;
	justify-content: center;
	gap: 0.35rem;
}

.pagination .page-numbers {
	display: inline-block;
	min-width: 2.25rem;
	padding: 0.35rem 0.6rem;
	border: 1px solid transparent;
	border-radius: 2px;
	font-size: var(--wp--preset--font-size--small);
	text-align: center;
	text-decoration: none;
}

.pagination a.page-numbers:hover {
	border-color: var(--wakonda-line-strong);
}

.pagination .page-numbers.current {
	background: var(--wakonda-ink);
	border-color: var(--wakonda-ink);
	color: var(--wakonda-paper);
}

/* -------------------------------------------------------------------------
 * Shareholder home.
 *
 * A dashboard, not an article: section headings step out of the serif voice
 * into small caps with a rule running to the margin, so the page reads as
 * labelled regions rather than one long document.
 * ---------------------------------------------------------------------- */

.shareholder-pinned {
	max-width: 100%;
	padding: 1.75rem 2rem;
	background: var(--wakonda-surface);
	border-inline-start: 3px solid var(--wakonda-ink);
	border-radius: 2px;
}

.shareholder-pinned > * {
	max-width: 62ch;
	margin-block: 0;
}

.shareholder-pinned > * + * {
	margin-block-start: 0.9rem;
}

.shareholder-pinned + .shareholder-columns {
	margin-block-start: 3rem;
}

/*
 * Reading matter left, meetings-and-documents rail right. The reading column
 * is first in the DOM (see the template), so under the breakpoint the stack
 * runs pinned → news → events → photos → rail: the matter that changes week
 * to week sits first, the reference matter follows. Explicit grid placement
 * rather than order:, so visual order and focus order agree in both layouts.
 */
.shareholder-section {
	margin-block-start: 3.25rem;
}

.shareholder-reading > :first-child,
.shareholder-aside > :first-child {
	margin-block-start: 0;
}

@media (min-width: 60rem) {
	.shareholder-columns {
		display: grid;
		/*
		 * The rail holds a third of the container (25% read too slight —
		 * Adam's call, 2026-08-26), with a floor so a percentage can never
		 * crush the doc rows just above this breakpoint; a fixed track did
		 * the opposite — it GREW proportionally as the viewport shrank,
		 * squeezing the reading column. (At the 78rem wide size the 33%
		 * renders ~25.7rem.)
		 */
		grid-template-columns: minmax(0, 1fr) minmax(16rem, 33%);
		column-gap: 3.5rem;
		align-items: start;
	}

	.shareholder-reading {
		grid-column: 1;
		grid-row: 1;
	}

	.shareholder-aside {
		grid-column: 2;
		grid-row: 1;
		padding-inline-start: 2.5rem;

		/* The rail is short; keep it in view while the reading column scrolls. */
		position: sticky;
		top: 2rem;
	}
}

@media (max-width: 59.9375rem) {
	.shareholder-columns > * + * {
		margin-block-start: 3.25rem;
	}
}

.shareholder-section > h2 {
	margin-block-end: 1.5rem;
	padding-block-end: 0.85rem;
	border-block-end: 1px solid var(--wakonda-line);
	font-family: var(--wp--preset--font-family--body);
	font-size: var(--wp--preset--font-size--small); /* Eyebrow */
	font-weight: 700;
	line-height: 1.43;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	color: var(--wakonda-accent);
}

/*
 * A linked heading IS the section's view-all: a small arrow follows the
 * label, and the whole row is one target (block anchor). The rule below
 * stays on the h2, so linked and plain headings draw identically — and
 * only anchors grow the arrow, so a plain heading never wears one.
 */
.shareholder-section > h2 > a {
	display: block;
	text-decoration: none;
}

.shareholder-section > h2 > a::after {
	content: "\2192" / "";
	display: inline-block;
	margin-inline-start: 0.5rem;
	transition: translate 120ms ease;
}

.shareholder-section > h2 > a:hover::after {
	translate: 0.2rem 0;
}

/* --- latest news: a lead story, then compact rows ------------------------ */

/*
 * The lead: text left, its picture large on the right — but only when the
 * post has art (featured image, else its first content image). The template
 * adds --has-media alongside the picture, and without it the lead stays a
 * clean full-measure text story rather than reserving an empty column.
 */
.news-lead--has-media {
	display: grid;
	grid-template-columns: minmax(0, 1fr) minmax(0, 20rem);
	column-gap: 2.5rem;
}

.news-lead__media {
	display: block;
	grid-column: 2;
	grid-row: 1 / span 3;
	align-self: start;
}

.news-lead__media img {
	display: block;
	width: 100%;
	aspect-ratio: 4 / 3;
	object-fit: cover;
	border-radius: 2px;
	transition: opacity 150ms ease;
}

.news-lead__media:hover img {
	opacity: 0.85;
}

.news-lead__date {
	grid-column: 1;
}

.news-lead__title {
	grid-column: 1;
	margin-block-start: 0.6rem;
	font-size: var(--wp--preset--font-size--huge); /* H2 */
	line-height: 1.23;
	letter-spacing: -0.01em;
	text-wrap: balance;
}

.news-lead > p:not([class]) {
	grid-column: 1;
	margin: 1rem 0 0;
	max-width: 46rem;
}

@media (max-width: 40rem) {
	.news-lead--has-media {
		display: block;
	}

	.news-lead__media {
		margin-block-end: 1.4rem;
	}
}

/*
 * The two items under the lead: text left, thumbnail right. The thumbnail
 * column collapses away when a post has no art, so a text-only announcement
 * reads as a clean editorial row.
 */
.news-rows {
	margin: 2.25rem 0 0;
	padding: 0;
	list-style: none;
}

.news-row {
	display: grid;
	grid-template-columns: minmax(0, 1fr) auto;
	column-gap: 2rem;
	row-gap: 0.35rem;
	padding-block: 1.5rem;
	border-block-start: 1px solid var(--wakonda-line);
}

.news-row__media {
	grid-column: 2;
	grid-row: 1 / span 3;
	align-self: start;
}

.news-row__media img {
	display: block;
	width: 12.5rem;
	aspect-ratio: 4 / 3;
	object-fit: cover;
	border-radius: 2px;
	transition: opacity 150ms ease;
}

.news-row__media:hover img {
	opacity: 0.85;
}

.news-row__date {
	grid-column: 1;
}

.news-row__title {
	grid-column: 1;
	margin: 0;
	font-size: var(--wp--preset--font-size--x-large); /* H4 */
	line-height: 1.5;
	display: -webkit-box;
	-webkit-box-orient: vertical;
	-webkit-line-clamp: 2;
	line-clamp: 2;
	overflow: hidden;
}

.news-row > p:not([class]) {
	grid-column: 1;
	display: -webkit-box;
	margin: 0;
	font-size: var(--wp--preset--font-size--medium);
	-webkit-box-orient: vertical;
	-webkit-line-clamp: 3;
	line-clamp: 3;
	overflow: hidden;
}

@media (max-width: 40rem) {
	.news-row {
		display: block;
	}

	.news-row__media {
		margin-block-start: 0.75rem;
	}

	.news-row__media img {
		width: 100%;
	}
}

/* --- upcoming events: the archive rows in dashboard voice --------------- */

/* Compact dates ("Jul 17 – Aug 29") need less column than the archive's. */
.event-list--compact .event-list__date {
	width: 8.5rem;
}

/* Timed events add a second line (start time). */
.event-list--compact .event-list__time {
	display: block;
}

/* The section's more-link follows — no rule after the last row. */
.event-list--compact .event-list__item:last-child {
	border-block-end: none;
}

.event-list--compact .event-list__body > p:not([class]) {
	display: -webkit-box;
	-webkit-box-orient: vertical;
	-webkit-line-clamp: 2;
	line-clamp: 2;
	overflow: hidden;
}

/* --- the rail ------------------------------------------------------------ */

/* Active raffles: title first, the drawing date quietly beneath it. */
.raffle-list {
	margin: 0;
	padding: 0;
	list-style: none;
}

.raffle-list__item + .raffle-list__item {
	margin-block-start: 1.5rem;
}

.raffle-list__title {
	margin: 0;
	font-size: var(--wp--preset--font-size--large); /* H5 */
	line-height: 1.33;
	letter-spacing: -0.01em;
	text-wrap: balance;
}

.raffle-list__ends {
	margin: 0.35rem 0 0;
	font-size: var(--wp--preset--font-size--small); /* Body Small */
	line-height: 1.57;
	color: var(--wakonda-ink-soft);
}

/* Minutes and resources: icon rows. */
.doc-list {
	margin: 0;
	padding: 0;
	list-style: none;
}

.doc-list__item {
	display: grid;
	grid-template-columns: 3.5rem minmax(0, 1fr);
	column-gap: 1.25rem;
	padding-block: 0.75rem;
}

/*
 * The badge: a sand circle holding a document glyph, with the file
 * extension ("PDF") stacked beneath it for rows that are real files; rows
 * that are pages (meeting minutes live in post content) get the glyph
 * alone.
 */
.doc-list__icon {
	display: grid;
	place-items: center;
	align-content: center;
	row-gap: 0.15rem;
	width: 3.5rem;
	height: 3.5rem;
	border-radius: 50%;
	background: var(--wakonda-surface);
	color: var(--wakonda-accent-deep);
	font-size: 0.5625rem;
	font-weight: 700;
	letter-spacing: 0.05em;
}

.doc-list__icon svg {
	width: 1.15rem;
	height: 1.15rem;
}

.doc-list__title {
	font-size: var(--wp--preset--font-size--large); /* H5 */
	line-height: 1.33;
}

.doc-list__meta {
	margin: 0.25rem 0 0;
	font-size: var(--wp--preset--font-size--small); /* Body Small */
	line-height: 1.57;
	color: var(--wakonda-ink-soft);
}

.doc-list__meta strong {
	font-weight: 600;
	color: var(--wakonda-ink);
}

/* -------------------------------------------------------------------------
 * Entry content — block content typography.
 *
 * Everything the block editor can emit for this site: prose, lists, quotes,
 * tables, galleries, File blocks. Scoped to .entry-content so the same rules
 * hold on pages, news and events, and inside the editor canvas.
 * ---------------------------------------------------------------------- */

.entry-content {
	overflow-wrap: break-word;
}

/* Owl spacing: rhythm lives in one place instead of per-element margins. */
.entry-content > * {
	margin-block: 0;
}

.entry-content > * + * {
	margin-block-start: var(--wp--style--block-gap, 1.2rem);
}

.entry-content > * + h2 {
	margin-block-start: 2.75rem;
}

.entry-content > * + h3,
.entry-content > * + h4 {
	margin-block-start: 2.25rem;
}

.entry-content h2 + *,
.entry-content h3 + *,
.entry-content h4 + * {
	margin-block-start: 0.9rem;
}

.entry-content a:not([class*="button"]) {
	text-decoration: underline;
	text-decoration-color: var(--wakonda-line-strong);
	text-decoration-thickness: 1px;
	text-underline-offset: 0.15em;
	transition: text-decoration-color 150ms ease;
}

.entry-content a:not([class*="button"]):hover {
	text-decoration-color: var(--wakonda-ink);
}

.entry-content ul,
.entry-content ol {
	padding-inline-start: 1.4rem;
}

.entry-content li {
	margin-block-start: 0.35rem;
}

.entry-content li:first-child {
	margin-block-start: 0;
}

.entry-content blockquote {
	margin-inline: 0;
	padding-inline-start: 1.5rem;
	border-inline-start: 2px solid var(--wakonda-ink);
	font-family: var(--wp--preset--font-family--heading);
	font-style: italic;
	font-size: var(--wp--preset--font-size--large);
}

.entry-content blockquote cite {
	display: block;
	margin-block-start: 0.75rem;
	font-family: var(--wp--preset--font-family--body);
	font-style: normal;
	font-size: var(--wp--preset--font-size--small);
	color: var(--wakonda-ink-soft);
}

.wp-block-pullquote {
	padding: 2rem 0;
	border-block: 1px solid var(--wakonda-ink);
	text-align: center;
	font-family: var(--wp--preset--font-family--heading);
	font-style: italic;
}

.entry-content hr,
.wp-block-separator {
	height: 0;
	border: 0;
	border-block-start: 1px solid var(--wakonda-line);
}

.entry-content table {
	width: 100%;
	border-collapse: collapse;
	font-size: var(--wp--preset--font-size--medium);
}

.entry-content th {
	text-align: start;
	font-size: var(--wp--preset--font-size--small);
	font-weight: 600;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var(--wakonda-ink-soft);
}

.entry-content th,
.entry-content td {
	padding: 0.6rem 0.75rem 0.6rem 0;
	border-block-end: 1px solid var(--wakonda-line);
}

.entry-content pre,
.entry-content code {
	background: var(--wakonda-surface);
	border-radius: 2px;
	font-size: 0.9em;
}

.entry-content pre {
	padding: 1rem 1.25rem;
	overflow-x: auto;
}

.entry-content code {
	padding: 0.1em 0.35em;
}

.entry-content pre code {
	padding: 0;
	background: none;
}

.entry-content figure {
	margin-inline: 0;
}

.entry-content figcaption,
.wp-element-caption {
	margin-block-start: 0.6rem;
	font-size: var(--wp--preset--font-size--small);
	color: var(--wakonda-ink-soft);
}

.entry-content img {
	border-radius: 2px;
}

/*
 * The File block — how minutes PDFs and forms are published. Rendered as a
 * flat slip: name left, download button right.
 */
.wp-block-file {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between;
	gap: 0.75rem 1.5rem;
	padding: 0.875rem 1.25rem;
	background: var(--wakonda-surface);
	border-radius: 2px;
}

.wp-block-file > a:first-child {
	font-weight: 500;
	text-decoration: none;
}

.wp-block-file > a:first-child:hover {
	text-decoration: underline;
	text-decoration-thickness: 1px;
	text-underline-offset: 0.2em;
}

.wp-block-file .wp-block-file__button {
	font-size: var(--wp--preset--font-size--small);
	padding: 0.45rem 1.1rem;
}

/*
 * Constrained children — only where the main column steps aside (the front
 * page). Prose holds the reading measure, alignwide steps out to the wide
 * size, alignfull bleeds to the viewport edge.
 */
.site-main--front .entry-content {
	padding: 3rem var(--wakonda-gutter) 7rem;

	/*
	 * Bleeding sections shove imagery past the viewport edge on purpose
	 * (the intro polaroids); clip it rather than grow a horizontal
	 * scrollbar. x only — tilted photos still poke out vertically.
	 */
	overflow-x: clip;
}

.site-main--front .entry-content > * {
	max-width: var(--wakonda-measure);
	margin-inline: auto;
}

.site-main--front .entry-content > .alignwide {
	max-width: var(--wakonda-front-wide, var(--wp--style--global--wide-size, 68rem));
}

/*
 * Full sections bleed to the viewport edge — negative margins eat the
 * gutter — until the viewport passes --wakonda-front-cap, where the margin
 * math flips positive and the section centres at the cap instead. One
 * expression, no media query, so the cap is a plain knob.
 */
.site-main--front .entry-content > .alignfull {
	max-width: none;
	margin-inline: max(
		calc(-1 * var(--wakonda-gutter)),
		calc((100% - var(--wakonda-front-cap)) / 2)
	);
}

/* Classic image floats inside prose. */
.entry-content .alignleft {
	float: left;
	margin: 0.35rem 1.75rem 1rem 0;
}

.entry-content .alignright {
	float: right;
	margin: 0.35rem 0 1rem 1.75rem;
}

.entry-content .aligncenter {
	margin-inline: auto;
}

/* -------------------------------------------------------------------------
 * Front page.
 *
 * The hero photo is the page's featured image (content); the lockup and the
 * shim are chrome. The shim is 454px of black fading down over the top of
 * the photo, so the inverted header always sits on near-black no matter how
 * pale the sky in whatever photo the board picks. The hero's bottom edge is
 * a clean cut to the page.
 * ---------------------------------------------------------------------- */

.front-hero {
	position: relative;
	display: block;

	/*
	 * One fixed band on every viewport (the mock's 768px), capped only so a
	 * short screen (phone landscape) still gets a whole heroful.
	 */
	height: 48rem;
	height: min(48rem, 100svh);
	background: var(--wakonda-ink);
	overflow: hidden;
}

.front-hero__backdrop {
	position: absolute;
	inset: 0;
}

.front-hero__image {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
	object-position: center bottom;
}

/*
 * The shim. On .front-hero--plain (no featured image) it just blends into
 * the ink band — obviously awaiting its photo, never broken.
 */
.front-hero__backdrop::after {
	content: "";
	position: absolute;
	inset-inline: 0;
	top: 0;
	height: 28.375rem; /* the mock's 454px */
	background: linear-gradient(
		to top,
		rgb(0 0 0 / 0) 0%,
		rgb(0 0 0 / 0.6) 30%,
		rgb(0 0 0) 75%
	);
	pointer-events: none;
}

/*
 * The lockup (hero-text.svg: bird over wordmark, 364×175, white), seated
 * 140px down from the hero's top — inside the shim's fade, per the mock.
 * The invert() is belt-and-braces — it renders the art white whatever fill
 * the SVG carries.
 */
.front-hero__title {
	position: absolute;
	left: 50%;
	top: 8.75rem; /* the mock's 140px */
	transform: translateX(-50%);
}

.front-hero__title img {
	width: clamp(16rem, 24vw, 22.75rem);
	height: auto;
	filter: brightness(0) invert(1) drop-shadow(0 1px 18px rgba(0, 0, 0, 0.35));
}

.front-hero__est {
	position: absolute;
	inset-inline-end: var(--wakonda-gutter);
	bottom: 1.25rem;
	margin: 0;
	font-size: var(--wp--preset--font-size--x-small);
	font-weight: 600;
	letter-spacing: 0.12em;
	text-transform: uppercase;
	color: rgba(255, 255, 255, 0.8);
}

/* --- the header over the hero ------------------------------------------ */

/*
 * Front page only (body.has-front-hero). Absolute by default so the
 * un-upgraded page degrades to an inverted header that scrolls away with the
 * hero; <wakonda-hero> pins it (is-fixed) and swaps it back to the standard
 * light bar once the hero is spent (is-past-hero).
 */
body.has-front-hero .site-header--public {
	position: absolute;
	inset-inline: 0;
	top: 0;
	z-index: 60;
	background: transparent;
	border-block-end: 1px solid transparent;
	color: #fff;
	transition: background-color 200ms ease, color 200ms ease,
		border-color 200ms ease;
}

/*
 * The legibility shim: a gradient taller than the bar itself, fading to
 * nothing, so white nav text survives a pale sky in the photo.
 */
body.has-front-hero .site-header--public::before {
	content: "";
	position: absolute;
	inset-inline: 0;
	top: 0;
	height: 180%;
	background: linear-gradient(to bottom, rgba(0, 0, 0, 0.55), rgba(0, 0, 0, 0));
	pointer-events: none;
	transition: opacity 200ms ease;
}

/* Keep the bar's contents above its own shim. */
body.has-front-hero .site-header--public .site-header__inner {
	position: relative;
}

body.has-front-hero .site-header--public .site-logo img {
	filter: brightness(0) invert(1);
	transition: filter 200ms ease;
}

/* The narrow-screen menu needs a solid ground the moment it opens. */
body.has-front-hero .site-header--public:has(wakonda-nav.is-open) {
	background: rgba(0, 0, 0, 0.92);
}

body.has-front-hero .site-header--public.is-fixed {
	position: fixed;
}

body.admin-bar.has-front-hero .site-header--public.is-fixed {
	top: var(--wp-admin--admin-bar--height, 32px);
}

/* Past the hero: the standard light bar again. */
body.has-front-hero .site-header--public.is-past-hero,
body.has-front-hero .site-header--public.is-past-hero:has(wakonda-nav.is-open) {
	background: var(--wakonda-paper);
	border-block-end-color: var(--wakonda-line);
	color: var(--wakonda-ink);
}

body.has-front-hero .site-header--public.is-past-hero::before {
	opacity: 0;
}

body.has-front-hero .site-header--public.is-past-hero .site-logo img {
	filter: none;
}

/*
 * Dropdown panels are paper in both header states, so they must carry their
 * own ink rather than inheriting the inverted header's white.
 */
.account-menu__list,
.nav-more__list,
wakonda-nav.is-ready .nav-list > li > .sub-menu,
wakonda-nav.is-ready .nav-list > li > .children {
	color: var(--wakonda-ink);
}

/* --- homepage sections (the wakonda/* patterns) ------------------------- */

/* Big air between sections; the generic content owl is for prose. */
.site-main--front .entry-content > * + * {
	margin-block-start: clamp(4rem, 9vh, 6.5rem);
}

/*
 * One rhythm for every section's text stack — heading, body, link. The
 * knob for all four sections lives here and nowhere else. (No specificity
 * armor needed: since the sections became dynamic blocks, core injects no
 * layout margins into their markup — the old flow-gap reset this file
 * carried is gone with the group blocks that required it.)
 */
.home-intro__text > * + *,
.home-experience__intro > * + *,
.home-history__panel > * + *,
.home-join__text > * + * {
	margin-block-start: var(--wp--style--block-gap, 1.2rem);
}

/*
 * Section display headings: regular-weight Lora, 40px in the mobile set and
 * 72px on desktop, per the design — a size class above the prose scale, so
 * it is set here rather than through the theme.json presets. Stepped, not
 * fluid, like everything else.
 */
.home-intro h2,
.home-experience h2,
.home-history h2,
.home-join h2 {
	font-size: 2.5rem;
	font-weight: 400;
	line-height: 1.05;
	letter-spacing: -0.01em;
	text-wrap: balance;
}

@media (min-width: 60rem) {
	.home-intro h2,
	.home-experience h2,
	.home-history h2,
	.home-join h2 {
		font-size: 4.5rem;
	}
}

/*
 * Section body copy is Lora too — 16px on a 28px line. The family var is
 * named "heading" but it is simply the theme's Lora preset. Card labels
 * keep their sans small-caps voice, hence the :not().
 */
.home-intro p:not(.home-card__label),
.home-experience p:not(.home-card__label),
.home-history p:not(.home-card__label),
.home-join p:not(.home-card__label) {
	font-family: var(--wp--preset--font-family--heading);
	font-size: var(--wp--preset--font-size--medium);
	line-height: 1.75;
}

/*
 * Snapshot treatment shared by every homepage photo — and resize-proofing.
 * The editor's drag handles write a fixed inline width into the page's copy
 * of a pattern (is-resized), silently defeating the collage geometry; the
 * contentOnly lock hides design panels but not those handles. !important
 * outranks inline styles everywhere this sheet loads — the front end AND
 * the editor canvas (it is the editor style) — so a stored resize simply
 * does nothing. Deliberately CSS, not a save-time content filter: a filter
 * that silently rewrites what an editor saved is the kind of spooky action
 * this project avoids.
 */
/*
 * block kills the inline-image baseline gap (the mystery space under the
 * photo inside its figure). width/height 100% + cover make the FIGURE the
 * unit of design: give .home-photo (or a wrapper) a width and a height or
 * aspect-ratio, and the photo fills the box, cropping from its centre. An
 * unsized figure still collapses to the image's natural ratio — height:100%
 * against an auto parent resolves to auto — so nothing changes until a box
 * is given real dimensions. The !importants remain the resize-proofing.
 */
.home-photo img {
	display: block;
	width: 100% !important;
	height: 100% !important;
	object-fit: cover;
	border-radius: 12px;
}

/* And in the canvas, remove the drag affordance itself. Editor-only by
 * construction: this selector matches nothing on the front end. */
.home-photo .components-resizable-box__handle {
	display: none !important;
}

/* Editor photo slots (the wakonda/* blocks): the swap button IS the image. */
.home-photo .wakonda-photo-slot {
	display: block;
	width: 100%;
	padding: 0;
	border: 0;
	background: none;
	cursor: pointer;
}

.home-photo .wakonda-photo-slot img {
	display: block;
}

.home-more a {
	font-family: var(--wp--preset--font-family--heading);
	font-size: var(--wp--preset--font-size--medium);
	font-weight: 700;
	line-height: 1.75;
	text-decoration: none;
}

.home-more a:hover {
	text-decoration: underline;
	text-underline-offset: 0.3em;
}

/* -------------------------------------------------------------------------
 * Our Happy Place.
 *
 * The collage architecture both this and Our History share: flexible side
 * rails flank a fixed centre column, prints anchor absolutely to the
 * rails' INNER edges (the content column's edges, maintained by flex for
 * free) so the composition hugs the content at every width, and translate
 * is the nudge/overlap knob. Section padding is the poke budget for how
 * far prints overhang. Below the breakpoint each section restates itself
 * as a declared grid — rows owned outright, prints sized in vw.
 * ---------------------------------------------------------------------- */

.home-intro {
	display: flex;
	align-items: stretch;

	/*
	 * The poke budget. Photos overhang the section by (their extent minus
	 * this padding): top stays 0 so the upper photo rides into the band
	 * above; grow the bottom value to pull the lower photo's overhang in.
	 */
	padding-block: 0 8rem;
}

.home-intro__photo-wrapper {
	flex-grow: 1;
	flex-shrink: 1;
	position: relative;
}

/*
 * Both photos anchor from the TOP in fixed rems, so longer copy grows the
 * section downward without dragging either photo with it. Individual
 * translate/rotate properties rather than the transform shorthand: they
 * apply in spec order (translate first), so the nudge off the text column
 * is purely horizontal and the order can never be written wrong.
 */
.home-intro__photo-wrapper--left .home-photo {
	width: 22rem;
	aspect-ratio: 11 / 14;
	position: absolute;
	right: 0;
	top: -6rem;
	translate: -15% 0;
	rotate: -8deg;
}

.home-intro__photo-wrapper--right .home-photo {
	width: 24rem;
	aspect-ratio: 4 / 5;
	position: absolute;
	left: 0;
	top: 10rem;
	translate: 15% 0;
	rotate: 8deg;
}

.home-intro__text {
	max-width: 380px;
	padding-inline: var(--wakonda-gutter);
	text-align: center;
}

/*
 * Small screens — meat over bread: the copy takes the whole first row
 * (order pulls it ahead of its DOM slot) and both photos share the second,
 * side by side IN FLOW. Row siblings cannot overlap by construction, so
 * the scrapbook spacing is just the column gap plus rotation headroom. The
 * left print hangs off the viewport edge (the negative margin), the right
 * one drops a beat lower (a real margin, so the section height stays
 * honest) and may crop at the far edge on the narrowest screens — which is
 * the point.
 *
 * The switch sits at 64rem, not the theme's usual 48: the desktop rails
 * need ~64rem before they can show most of each print, and in between the
 * composition reads as clipped accidents. The prints scale up through the
 * widened range (clamps below) so the pair never looks lost at tablet
 * sizes.
 */
@media (max-width: 64rem) {
	/*
	 * Grid, not flex-wrap: a wrapping flex container breaks lines on each
	 * item's CLAMPED size, so the text's max-width let a print hop up
	 * beside it at semi-wide widths — full-basis or not. Grid rows are
	 * declared, not derived: the copy owns row one outright (max-width
	 * then only shrinks it within the row), the prints own row two.
	 * justify-content centres the whole grid box, and since the copy's
	 * spanned row sits over the centred pair, centring within it lands on
	 * the section's centre too — no stretcher column needed.
	 */
	.home-intro {
		display: grid;
		grid-template-columns: auto auto;
		justify-content: center;
		align-items: start;
		gap: 2.5rem 1.5rem;
		padding-block: 0 3rem;
	}

	.home-intro__text {
		grid-row: 1;
		grid-column: 1 / -1;
		justify-self: center;
	}

	.home-intro__photo-wrapper--left {
		grid-row: 2;
		grid-column: 1;
	}

	/* The stagger. */
	.home-intro__photo-wrapper--right {
		grid-row: 2;
		grid-column: 2;
		margin-block-start: 2.5rem;
	}
	.home-intro__photo-wrapper--left .home-photo {
		position: static;
		translate: -10% 10%;
	}
	.home-intro__photo-wrapper--right .home-photo {
		position: static;
		translate: 20% -5%;
	}

	/*
	 * Pure vw: the pair is always the same fraction of the screen. Widths
	 * plus the gap total ~86vw, so the centred pair fits with air at every
	 * size in this range — no cropping. Heights come from each print's
	 * aspect-ratio in the base rules; width is the only size knob.
	 */
	.home-intro__photo-wrapper--left .home-photo {
		width: 44vw;
		rotate: -5deg;
	}

	.home-intro__photo-wrapper--right .home-photo {
		width: 40vw;
		rotate: 5deg;
	}
}


/* Figures carry UA margins; the collage slots must not. */
.home-intro .home-photo,
.home-history .home-photo {
	margin: 0;
}

/* Experience Camp Life: intro copy, then three labelled cards. */
/* The copy sits at column 2 of the design's 12-column grid: inset by one
 * column of the section's width, deeper than the card row's gutter. */
.home-experience__intro {
	max-width: 34rem;
	padding-inline: var(--wakonda-gutter);
	margin-inline-start: calc(100% / 12);
}

.home-experience__cards {
	display: grid;
	grid-template-columns: repeat(3, minmax(0, 1fr));
	gap: 2.25rem;
	margin-block-start: 2.5rem;

	/* The row never touches the viewport: same inset as the copy above it,
	 * so the first card's label left-aligns with the heading. */
	padding-inline: var(--wakonda-gutter);
}

.home-card__label {
	margin: 0 0 0.75rem;
	font-size: var(--wp--preset--font-size--small);
	font-weight: 600;
	letter-spacing: 0.07em;
	text-transform: uppercase;
}

.home-card__label a {
	text-decoration: none;
}

.home-card__label a:hover {
	text-decoration: underline;
	text-underline-offset: 0.3em;
}

.home-experience__cards .home-photo {
	margin: 0;
}

/* !important: a stored editor resize also writes an inline aspect-ratio. */
.home-experience__cards .home-photo img {
	width: 100%;
	aspect-ratio: 4 / 5 !important;
	object-fit: cover;
	box-shadow: none;
}

/*
 * Our History — same architecture as Our Happy Place: two flexible rails
 * flank the fixed panel, prints anchor absolutely to the rails' INNER
 * edges (which are the panel's edges, maintained by flex for free), and
 * translate is the overlap knob — how far each print rides onto the
 * panel. Rails carry z-index so prints lie over the panel even from the
 * left rail, which precedes it in the DOM.
 */
.home-history {
	display: flex;
	align-items: stretch;

	/*
	 * The poke budget: the panel band sits inside this padding, and the
	 * prints climb into the top space / hang into the bottom space. The
	 * bottom is deep because the bungalows print lives there.
	 */
	padding-block: 7.5rem 14rem;
}

.home-history__rail {
	position: relative;
	flex: 1 1 0;
	z-index: 1;
}

.home-history__panel {
	/* border-box so the width is the width the prints measure against. */
	box-sizing: border-box;
	width: 39rem;
	max-width: 100%;
	padding: 16rem 4.5rem;
	background: var(--wakonda-surface);
	border-radius: 2rem;
	text-align: center;
}

.home-history__panel p:not(.home-more) {
	max-width: 24rem;
	margin-inline: auto;
}

.home-history .home-photo {
	position: absolute;
	margin: 0;
}

/* Tent — big landscape over the panel's top-right corner, riding to the
 * section's top edge. translate pulls it 7rem onto the panel. */
.home-history__rail--right .home-photo:nth-of-type(1) {
	left: 0;
	top: -7.5rem;
	width: 34rem;
	aspect-ratio: 10 / 7;
	translate: -7rem 0;
}

/* Field — portrait on the right edge, lower. */
.home-history__rail--right .home-photo:nth-of-type(2) {
	left: 0;
	top: 22rem;
	width: 20rem;
	aspect-ratio: 4 / 5;
	translate: -3rem 0;
}

/* Dock — portrait on the left edge, upper. */
.home-history__rail--left .home-photo:nth-of-type(1) {
	right: 0;
	top: 3rem;
	width: 21rem;
	aspect-ratio: 6 / 7;
	translate: 5.5rem 0;
}

/* Bungalows — big landscape hanging below the panel, bleeding off the
 * viewport's left edge on all but the widest screens. */
.home-history__rail--left .home-photo:nth-of-type(2) {
	right: 0;
	bottom: -14rem;
	width: 36rem;
	aspect-ratio: 9 / 7;
	translate: 9rem 0;
}

/*
 * Small screens — the panel between the prints, with the prints STRADDLING
 * its edges like desktop: dock and tent ride its top edge, bungalows and
 * field its bottom. The rails dissolve (display: contents) so figures
 * place directly in this grid; slots keep their meaning.
 *
 * The no-overlap guarantee is the inner-edge pin: justify-self end/start
 * anchors each print's inner edge at the centre gap, so the pair can never
 * touch. Everything else moves prints OUTWARD, where the viewport crops
 * them. Per-print knobs:
 *   margin-inline (outward)  — the push toward/past the screen edge
 *   margin-block  (negative) — how deep it rides onto the panel
 *   width: max(vw, rem)      — the floor where shrinking stops and
 *                              cropping starts
 * Ratios match the desktop prints; heights derive.
 */
@media (max-width: 64rem) {
	.home-history {
		display: grid;
		/*
		 * minmax(0, …): without it a print wider than its track inflates
		 * the track, the section, and eventually the page's scroll width.
		 * With it the tracks hold their ground and oversized prints
		 * overflow visually, where the viewport crops them — the intended
		 * behaviour.
		 */
		grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
		gap: 0 1.5rem;
		padding-block: 0 3rem;
	}

	.home-history__rail {
		display: contents;
	}

	.home-history .home-photo {
		position: static;
		translate: 0 0;

		/* Prints lie ON the panel where they straddle it. */
		z-index: 1;
	}

	/* Above the panel: dock left, tent right riding deeper. */
	.home-history__rail--left .home-photo:nth-of-type(1) {
		grid-row: 1;
		grid-column: 1;
		justify-self: start;
		align-self: end;
		width: max(40vw, 16rem);
		margin-inline-end: 8vw;
		margin-block-end: -3rem;
		translate: -25% 5rem;
	}

	.home-history__rail--right .home-photo:nth-of-type(1) {
		grid-row: 1;
		grid-column: 2;
		justify-self: start;
		align-self: end;
		width: max(44vw, 18rem);
		margin-inline-start: 8vw;
		translate: 0 0;
		margin-block-end: -2.5rem;
	}

	.home-history__panel {
		grid-row: 2;
		grid-column: 1 / -1;
		justify-self: center;
		width: min(39rem, 100%);
		padding: 6.5rem 1.5rem;
	}

	/* Below it, mirroring the top pair's recipe: outer-edge pin, translate
	 * does the off-screen crop and the ride — y negated, their panel is
	 * ABOVE them. */
	.home-history__rail--left .home-photo:nth-of-type(2) {
		grid-row: 3;
		grid-column: 1;
		justify-self: start;
		align-self: start;
		width: max(44vw, 18rem);
		margin-inline-end: 6vw;
		margin-block-start: -3rem;
		translate: -25% -5rem;
	}

	.home-history__rail--right .home-photo:nth-of-type(2) {
		grid-row: 3;
		grid-column: 2;
		justify-self: end;
		align-self: start;
		width: max(44vw, 15rem);
		margin-inline-start: 10vw;
		margin-block-start: -3rem;
		margin-right: 5vw;
		translate: 0 0;
	}
}

/*
 * True phones: the panel goes FULL BLEED — an edge-to-edge band, no
 * radius, gutter-padded copy — and the straddle flattens to gentler
 * numbers: pure vw widths (the rem floors were most of the screen), a
 * 4rem total ride against 5rem of panel padding, modest crops. Same
 * knobs as the tier above; this block just re-tunes them, so it must
 * stay AFTER it in the file. Cut at 40rem: below that, the middle tier's
 * rem floors are most of the screen and its dance has no room to dance.
 */
@media (max-width: 40rem) {
	.home-history__panel {
		justify-self: stretch;
		width: 100%;
		border-radius: 0;
		padding: 5rem var(--wakonda-gutter);
	}

	.home-history__rail--left .home-photo:nth-of-type(1) {
		width: 42vw;
		margin-block-end: -2rem;
		translate: -15% 2rem;
	}

	.home-history__rail--right .home-photo:nth-of-type(1) {
		width: 50vw;
		margin-block-end: -2rem;
		translate: -10% 0;
	}

	.home-history__rail--left .home-photo:nth-of-type(2) {
		width: 65vw;
		margin-block-start: -2rem;
		translate: -15% -2rem;
	}

	.home-history__rail--right .home-photo:nth-of-type(2) {
		width: 40vw;
		margin-block-start: 1rem;
		translate: 10vw 0;
	}
}

/* Join our Cooperative: photo beside the pitch. */
.home-join {
	display: grid;
	grid-template-columns: minmax(0, 1.1fr) minmax(0, 1fr);
	gap: 3.5rem;
	align-items: center;
}

.home-join .home-photo {
	margin: 0;
}

.home-join .home-photo img {
	width: 100%;
	aspect-ratio: 4 / 3 !important;
	object-fit: cover;
}

@media (max-width: 48rem) {
	/* One phantom column of indent reads as a mistake at phone width. */
	.home-experience__intro {
		margin-inline-start: 0;
	}

	.home-experience__cards {
		grid-template-columns: 1fr;
	}

	.home-join {
		grid-template-columns: 1fr;
		gap: 2rem;
	}
}

/* -------------------------------------------------------------------------
 * Footer.
 *
 * The one dark band: Wakonda Green ground, Tan type. Three zones —
 * identity + mirrored contact stack, the mirrored hours table, then the
 * Log In / colophon column. The facts come from the Camp info page (see
 * footer.php); this block only draws them.
 * ---------------------------------------------------------------------- */

.site-footer {
	background: var(--wakonda-accent-deep);
	color: var(--wakonda-on-dark);
}

.site-footer__inner {
	display: grid;
	grid-template-columns: minmax(0, 1fr) auto minmax(0, 1fr);
	column-gap: 3rem;
	align-items: start;
	max-width: var(--wp--style--global--wide-size, 68rem);
	margin-inline: auto;
	padding: 3.5rem var(--wakonda-gutter) 3rem;
}

/* The same lockup as the header, inverted for the dark ground. */
.site-footer__logo {
	display: block;
	margin-block-end: 2rem;
}

.site-footer__logo img {
	display: block;
	height: 3.25rem;
	width: auto;
	filter: brightness(0) invert(1);
}

.site-footer__identity p {
	margin: 0;
	max-width: 24rem;
}

.site-footer__identity p + p {
	margin-block-start: 1.4rem;
}

/* The hours ledger, built row-per-day from Camp Settings. */
.site-footer__hours table {
	border-collapse: collapse;
}

.site-footer__hours td {
	padding: 0.2rem 0;
	border: 0;
}

.site-footer__hours td:first-child {
	padding-inline-end: 2.5rem;
}

/* Today's row — wakonda-elements.js sets the class on the client, so a
 * cached page can never freeze "today". */
.site-footer__hours .is-today {
	font-weight: 700;
	color: var(--wakonda-paper);
}

.site-footer__meta {
	display: flex;
	flex-direction: column;
	align-items: flex-end;
	justify-content: space-between;
	gap: 2.5rem;
	align-self: stretch;
	text-align: end;
}

.site-footer__login {
	display: inline-block;
	padding: 0.65rem 2.4rem;
	background: var(--wakonda-paper);
	border: 1px solid var(--wakonda-paper);
	color: var(--wakonda-ink);
	font-weight: 500;
	text-decoration: none;
}

.site-footer__login:hover {
	background: var(--wakonda-on-dark);
}

.site-footer__colophon {
	margin: 0;
	font-size: var(--wp--preset--font-size--small); /* Body Small */
	line-height: 1.57;
	color: var(--wakonda-on-dark-soft);
}

@media (max-width: 48rem) {
	.site-footer__inner {
		display: block;
	}

	.site-footer__hours {
		margin-block: 2.5rem;
	}

	.site-footer__meta {
		align-items: flex-start;
		text-align: start;
	}
}

/* -------------------------------------------------------------------------
 * Scroll-driven entry — the prints' opacity and lift are a pure function
 * of scroll position, scrubbed across each print's entry through the
 * viewport's bottom edge and reversible in both directions.
 *
 * No JavaScript: animation-timeline: view() drives it. The hidden state
 * lives only inside the keyframes, so browsers without support (Safari
 * pre-26, older Firefox) never hide anything — they simply get static
 * prints. Scoped to .has-front-hero, the front page's body class, which
 * the editor canvas never carries. The motion rides `transform`, which
 * composes on top of the collage's individual translate/rotate, so entry
 * movement and layout position never fight. Neighbouring prints stagger
 * naturally: their positions differ, so their timelines do.
 * ---------------------------------------------------------------------- */

@media (prefers-reduced-motion: no-preference) {
	@supports (animation-timeline: view()) {
		.has-front-hero .home-intro .home-photo,
		.has-front-hero .home-experience .home-photo,
		.has-front-hero .home-history .home-photo,
		.has-front-hero .home-join .home-photo {
			animation: wakonda-print-enter linear both;
			animation-timeline: view();

			/* Scrub from first pixel in to fully entered; tune the second
			 * value earlier (e.g. entry 75%) to finish the effect sooner. */
			animation-range: entry 0% contain 65%;

			/*
			 * Transform ONLY — no opacity. Blending big semi-transparent
			 * photo textures against the backdrop every scroll tick is the
			 * jank; sliding opaque layers is nearly free. will-change
			 * promotes the layers up front so creation never happens
			 * mid-scroll.
			 */
			will-change: transform;
		}

		/*
		 * The collage sections travel up AND inward: each side's prints
		 * start displaced toward their own edge and converge on the seat.
		 * Only the name changes — timeline, range and layer hints carry
		 * over from the shared rule above. Experience and join keep the
		 * pure rise.
		 */
		.has-front-hero .home-intro__photo-wrapper--left .home-photo,
		.has-front-hero .home-history__rail--left .home-photo {
			animation-name: wakonda-print-enter-left;
		}

		.has-front-hero .home-intro__photo-wrapper--right .home-photo,
		.has-front-hero .home-history__rail--right .home-photo {
			animation-name: wakonda-print-enter-right;
		}
	}
}

@keyframes wakonda-print-enter {
	from {
		transform: translateY(2rem);
	}
}

@keyframes wakonda-print-enter-left {
	from {
		transform: translate(-1.5rem, 2rem);
	}
}

@keyframes wakonda-print-enter-right {
	from {
		transform: translate(1.5rem, 2rem);
	}
}

/* -------------------------------------------------------------------------
 * Reduced motion.
 * ---------------------------------------------------------------------- */

@media (prefers-reduced-motion: reduce) {
	*,
	*::before,
	*::after {
		transition-duration: 0.01ms !important;
	}
}
