/* -------------------------------------------------------------------------
   Campaign 2026
   Written mobile-first. --brand and --brand-contrast are injected inline by
   inc/customizer.php; the values below are only a fallback for the editor.
   ---------------------------------------------------------------------- */

:root {
	/* Sampled from the 2026 announcement lockup: the green of the "Mountain
	   House City Council" banner and the black of the plate it sits on. The
	   campaign's own colour is green — the crimson here previously came from an
	   older flyer and was superseded. Neutrals are tuned to the same hue so the
	   page reads as one brand. */
	--brand: #127830;
	--brand-contrast: #FFFFFF;

	--ink: #181818;
	--muted: #5A6560;
	--surface: #FFFFFF;
	--surface-alt: #F1F5F2;
	--border: #D8E2DB;
	--focus: #A15C00;

	--wrap: 68rem;
	--wrap-narrow: 46rem;
	--gap: 1.5rem;
	--radius: 0.625rem;

	--font-body: ui-sans-serif, system-ui, -apple-system, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
	--font-display: ui-serif, Georgia, "Times New Roman", serif;
}

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

html {
	-webkit-text-size-adjust: 100%;
}

body {
	margin: 0;
	background: var(--surface);
	color: var(--ink);
	font-family: var(--font-body);
	font-size: 1.0625rem;
	line-height: 1.65;
}

h1, h2, h3, h4 {
	font-family: var(--font-display);
	line-height: 1.2;
	margin: 0 0 0.5em;
	text-wrap: balance;
}

h1 { font-size: clamp(2.25rem, 1.5rem + 3.2vw, 3.5rem); }
h2 { font-size: clamp(1.5rem, 1.2rem + 1.3vw, 2rem); }
h3 { font-size: 1.25rem; }

p, ul, ol {
	margin: 0 0 1.15em;
}

a {
	color: var(--brand);
	text-underline-offset: 0.15em;
}

a:hover {
	text-decoration-thickness: 2px;
}

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

/* Focus is deliberately loud. Keyboard and screen-magnifier users are a real
   share of a municipal electorate, and a campaign site should not be the one
   place they lose their place on the page. */
:focus-visible {
	outline: 3px solid var(--focus);
	outline-offset: 2px;
	border-radius: 2px;
}

/* The amber ring reaches 5.19:1 on white and 4.81:1 on the cream panels, but
   only 1.80:1 against the brand green — below the 3:1 that WCAG 1.4.11 requires
   of a focus indicator. Because outline-offset puts the ring outside the button,
   on the green CTA band it lands on green and disappears for keyboard users.
   --brand-contrast is already computed as whichever of white or ink is readable
   on the brand colour, so this keeps working if the campaign changes it. */
.cta-band :focus-visible {
	outline-color: var(--brand-contrast);
}

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

.skip-link {
	position: absolute;
	left: -9999px;
	top: 0;
	z-index: 100;
	padding: 0.75rem 1.25rem;
	background: var(--ink);
	color: #fff;
	font-weight: 600;
}

.skip-link:focus {
	left: 0;
}

/* ---------- Layout ---------- */

.wrap {
	width: min(100% - 2.5rem, var(--wrap));
	margin-inline: auto;
}

.wrap--narrow {
	width: min(100% - 2.5rem, var(--wrap-narrow));
}

/* ---------- Buttons ---------- */

.button {
	display: inline-block;
	padding: 0.75rem 1.5rem;
	border: 2px solid transparent;
	border-radius: var(--radius);
	font-weight: 600;
	font-size: 1rem;
	line-height: 1.3;
	text-decoration: none;
	cursor: pointer;
	transition: background-color 0.15s ease, color 0.15s ease;
}

.button--primary {
	background: var(--brand);
	color: var(--brand-contrast);
	border-color: var(--brand);
}

.button--primary:hover {
	background: var(--ink);
	border-color: var(--ink);
	color: #fff;
}

.button--ghost {
	background: transparent;
	color: var(--brand);
	border-color: currentColor;
}

.button--ghost:hover {
	background: var(--brand);
	color: var(--brand-contrast);
}

.button--invert {
	background: var(--surface);
	color: var(--ink);
	border-color: var(--surface);
}

.button--ghost-invert {
	background: transparent;
	color: inherit;
	border-color: currentColor;
}

.button--ghost-invert:hover {
	background: rgba(255, 255, 255, 0.14);
}

/* ---------- Header ---------- */

.site-header {
	border-bottom: 1px solid var(--border);
	background: var(--surface);
	position: relative;
}

.site-header__inner {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: var(--gap);
	padding: 1rem 0;
	flex-wrap: wrap;
}

.site-title {
	font-family: var(--font-display);
	font-size: 1.125rem;
	font-weight: 700;
	color: var(--ink);
	text-decoration: none;
	line-height: 1.2;
}

.site-description {
	margin: 0.15rem 0 0;
	font-size: 0.875rem;
	color: var(--muted);
}

.custom-logo {
	/* The lockup carries three lines of type, so it needs more height than a
	   one-line text title did or "RE-ELECT" becomes unreadable. */
	max-height: 4.25rem;
	width: auto;
}

/* The link around the logo is inline by default, which adds a few pixels of
   descender space beneath the image. */
.custom-logo-link {
	display: inline-block;
	line-height: 0;
}

.site-header__brand {
	/* Lets a long committee name wrap beside the buttons instead of pushing
	   them onto a row of their own and making the header three rows tall. */
	flex: 1 1 12rem;
	min-width: 0;
}

.site-header__actions {
	display: flex;
	align-items: center;
	gap: 0.5rem;
	flex: 0 0 auto;
}

/* The donate button sits outside the collapsible nav so it stays visible on a
   phone. Hiding the campaign's primary action behind a hamburger costs more
   than the horizontal space it saves. */
.site-header__donate {
	white-space: nowrap;
}

.nav-toggle {
	display: inline-flex;
	align-items: center;
	gap: 0.5rem;
	background: transparent;
	border: 2px solid var(--border);
	border-radius: var(--radius);
	padding: 0.5rem 0.85rem;
	font: inherit;
	font-size: 0.9375rem;
	font-weight: 600;
	color: var(--ink);
	cursor: pointer;
}

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

.nav-toggle__bars {
	position: relative;
}

.nav-toggle__bars::before { position: absolute; top: -6px; }
.nav-toggle__bars::after  { position: absolute; top: 6px; }

.site-nav {
	display: none;
	width: 100%;
}

.site-nav.is-open {
	display: block;
	padding-bottom: 1rem;
}

.site-nav__list {
	list-style: none;
	margin: 0 0 1rem;
	padding: 0;
}

.site-nav__list a {
	display: block;
	padding: 0.6rem 0;
	color: var(--ink);
	text-decoration: none;
	font-weight: 500;
	border-bottom: 1px solid var(--border);
}

.site-nav__list a:hover,
.site-nav__list .current-menu-item > a {
	color: var(--brand);
}

.site-nav__list .current-menu-item > a {
	font-weight: 700;
}

@media (min-width: 40rem) {
	.site-title {
		font-size: 1.375rem;
	}
}

@media (min-width: 56rem) {
	.nav-toggle {
		display: none;
	}

	.site-nav {
		display: flex !important;
		align-items: center;
		gap: 1.5rem;
		width: auto;
		padding-bottom: 0;
	}

	.site-nav__list {
		display: flex;
		gap: 1.5rem;
		margin: 0;
	}

	.site-nav__list a {
		padding: 0.25rem 0;
		border-bottom: 2px solid transparent;
	}

	.site-nav__list .current-menu-item > a,
	.site-nav__list .current-menu-item > a[aria-current] {
		border-bottom-color: var(--brand);
	}

	/* On a wide screen the donate button reads better after the menu than
	   before it, so the nav is re-ordered rather than duplicated in markup. */
	.site-header__brand {
		margin-right: auto;
	}

	.site-nav {
		order: 2;
	}

	.site-header__actions {
		order: 3;
	}
}

/* ---------- Hero ---------- */

.hero {
	position: relative;
	padding: 0;
	background: var(--surface-alt);
}

/* Mobile: the portrait runs full width and the card sits under it in normal
   flow. The place panel is desktop-only — at phone width a second photograph
   would push the campaign's actual ask below two screens of imagery. */
.hero__panel--place {
	display: none;
}

/* The studio headshot exists only at 373x466 — the packet PDF carries the
   flyer flattened, where it is smaller still, so there is no larger copy. It is
   prepared for this panel by a two-step Lanczos enlargement to 1305px with a
   restrained unsharp mask, which adds no detail but stops the browser making a
   worse job of the same pixels. */
/* With `cover`, a face is drawn at whatever its panel is wide — so a tight
   head-and-shoulders headshot across half a 1920px screen becomes a 960px face.
   The fix is the panel, not the picture: the portrait column is narrower than
   the landscape beside it, which suits the crop and leaves the wide half to the
   photograph that has somewhere to go. */
.hero__panel--portrait {
	background: var(--surface-alt);
}

.hero__image {
	display: block;
	width: 100%;
	height: 80vw;
	max-height: 22rem;
	object-fit: cover;
	object-position: 50% 20%;
}

.hero__inner {
	position: relative;
	padding-top: 1.25rem;
	padding-bottom: 1.75rem;
}

.hero__card {
	background: var(--surface);
	border-radius: var(--radius);
	padding: 1.5rem;
	box-shadow: 0 2px 8px rgba(24, 24, 24, 0.10), 0 18px 44px rgba(24, 24, 24, 0.14);
}

/* Set like the campaign's own wordmark rather than the body serif: heavy,
   uppercase and tight. On an opaque white card --brand is 5.59:1. */
.hero__heading {
	margin: 0 0 0.75rem;
	font-family: var(--font-body);
	font-weight: 800;
	font-size: clamp(1.75rem, 1.1rem + 2.8vw, 3rem);
	line-height: 1.04;
	letter-spacing: -0.01em;
	text-transform: uppercase;
	color: var(--brand);
	text-wrap: balance;
}

.hero__subtext {
	margin: 0 0 1.25rem;
	font-size: 1.1875rem;
	font-weight: 700;
	line-height: 1.4;
	color: var(--ink);
	max-width: 26em;
}

.hero__actions {
	display: flex;
	flex-wrap: wrap;
	gap: 0.75rem;
	margin-bottom: 0;
}

.hero__image {
	border-radius: var(--radius);
	width: 100%;
	/* Slightly deeper than the gallery shadow: this sits on the tinted hero
	   band rather than on white, where a light shadow would not read. */
	box-shadow: 0 2px 6px rgba(24, 24, 24, 0.14), 0 14px 34px rgba(24, 24, 24, 0.14);
	/* No max-height and no object-fit here on purpose. The source file is
	   cropped to a 4:5 head-and-shoulders portrait; letting CSS crop it a
	   second time is what sliced the candidate off mid-torso. The image's own
	   proportions decide its height. */
	display: block;
}


@media (min-width: 56rem) {
	.hero {
		min-height: clamp(32rem, 46vw, 44rem);
	}

	/* The two photographs become the full width of the section, and the card
	   floats over the seam inside the normal wrap — so the card stays aligned
	   with the rest of the page while the imagery runs edge to edge. */
	.hero__frame {
		position: absolute;
		inset: 0;
		display: grid;
		grid-template-columns: 34% 66%;
	}

	.hero__panel {
		overflow: hidden;
	}

	.hero__panel--place {
		display: block;
		background: url("../img/hero-place.jpg") 50% 34% / cover no-repeat;
	}

	.hero__image {
		height: 100%;
		max-height: none;
		object-position: 50% 24%;
	}

	.hero__inner {
		display: flex;
		align-items: center;
		min-height: clamp(32rem, 46vw, 44rem);
		max-width: none;
		width: 100%;
		padding: 2rem 0;
	}

	.hero__card {
		margin-left: calc(34% - 2.5rem);
		width: min(30rem, 36%);
		padding: 2.25rem;
	}
}

/* ---------- Page header ---------- */

.page-header {
	padding: 1.75rem 0 0.875rem;
}

.page-header__eyebrow {
	margin: 0 0 0.5rem;
	font-size: 0.8125rem;
	font-weight: 700;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: var(--brand);
}

.page-header__title {
	margin-bottom: 0.35em;
}

.page-header__intro {
	font-size: 1.1875rem;
	color: var(--muted);
	max-width: 38em;
	margin-bottom: 0;
}

/* ---------- Entry content ---------- */

.entry {
	padding-bottom: 2rem;
}

.entry__content > *:first-child {
	margin-top: 0;
}

.entry__content h2 {
	margin-top: 1.5rem;
}

.entry__content h3 {
	margin-top: 1.75rem;
}

.entry__featured {
	margin: 0 0 2rem;
}

.entry__featured img {
	border-radius: var(--radius);
	width: 100%;
	display: block;
}

.entry__meta {
	color: var(--muted);
	font-size: 0.9375rem;
}

.entry__content ul,
.entry__content ol {
	padding-left: 1.35rem;
}

.entry__content li + li {
	margin-top: 0.4rem;
}

.entry__content blockquote {
	margin: 2rem 0;
	padding: 0.25rem 0 0.25rem 1.25rem;
	border-left: 4px solid var(--brand);
	font-family: var(--font-display);
	font-size: 1.1875rem;
}

.entry__content blockquote cite {
	display: block;
	margin-top: 0.75rem;
	font-family: var(--font-body);
	font-size: 0.9375rem;
	font-style: normal;
	color: var(--muted);
}

.entry__content table {
	width: 100%;
	border-collapse: collapse;
}

.entry__content th,
.entry__content td {
	border: 1px solid var(--border);
	padding: 0.6rem 0.75rem;
	text-align: left;
}

/* ---------- Patterns ---------- */

.record-item {
	border-left: 3px solid var(--brand);
	padding: 0.25rem 0 0.25rem 1.25rem;
	margin-bottom: 2rem;
}

.record-item__year {
	margin: 0 0 0.25rem;
	font-size: 0.8125rem;
	font-weight: 700;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: var(--brand);
}

.record-item h3 {
	margin-bottom: 0.4rem;
}

/* A photograph documenting one accomplishment. Kept to a band rather than a
   full-height portrait so the list of entries stays scannable — the reader is
   here for the record, and the photo is evidence for one item in it. */
.record-item__photo {
	margin: 0.75rem 0 0;
}

.record-item__photo img {
	border-radius: var(--radius);
	width: 100%;
	/* The source files are cropped to a landscape band around the subject, so
	   the browser should not crop them a second time — that is what cut the
	   candidate off at the chin. Height follows the image's own proportions. */
	max-height: none;
	display: block;
}

.issue-cards .wp-block-column {
	background: var(--surface-alt);
	border-radius: var(--radius);
	padding: 1.5rem;
}

.issue-cards h3 {
	margin-top: 0;
}

.endorsement {
	background: var(--surface-alt);
	border-left: 4px solid var(--brand);
	border-radius: 0 var(--radius) var(--radius) 0;
	padding: 1.5rem;
	margin: 2rem 0;
}

.bio-split__photo img {
	border-radius: var(--radius);
}

/* ---------- CTA band ---------- */

.cta-band {
	background: var(--brand);
	color: var(--brand-contrast);
	padding: 2.25rem 0;
	text-align: center;
}

.cta-band__heading {
	margin-top: 0;
}

.cta-band__text {
	max-width: 36em;
	margin-inline: auto;
	opacity: 0.92;
}

.cta-band__actions {
	display: flex;
	flex-wrap: wrap;
	gap: 0.75rem;
	justify-content: center;
	margin-bottom: 0;
}

/* ---------- Donate ---------- */

.donate-form,
.donate-mail,
.volunteer-form,
.contact-form,
.contact-details {
	margin-top: 2.5rem;
}

.donate-form__note,
.donate-mail__note {
	color: var(--muted);
	font-size: 0.9375rem;
}

.donate-mail {
	background: var(--surface-alt);
	border-radius: var(--radius);
	padding: 1.5rem;
}

.donate-mail__address {
	font-weight: 600;
}

.donate-form__fallback {
	font-size: 0.9375rem;
}

.contact-details__list {
	margin: 0;
}

.contact-details__row {
	display: grid;
	gap: 0.15rem;
	padding: 0.85rem 0;
	border-bottom: 1px solid var(--border);
}

.contact-details__row dt {
	font-weight: 700;
	font-size: 0.875rem;
	letter-spacing: 0.04em;
	text-transform: uppercase;
	color: var(--muted);
}

.contact-details__row dd {
	margin: 0;
}

@media (min-width: 40rem) {
	.contact-details__row {
		grid-template-columns: 9rem 1fr;
		gap: 1rem;
		align-items: baseline;
	}
}

/* Form plugins ship their own styles; these only set the rhythm around them. */
.campaign-form {
	margin-top: 1.5rem;
}

.campaign-form input[type="text"],
.campaign-form input[type="email"],
.campaign-form input[type="tel"],
.campaign-form textarea,
.campaign-form select {
	font: inherit;
	font-size: 1rem;
}

/* ---------- Post list ---------- */

.post-list {
	display: grid;
	gap: 2.5rem;
	padding-bottom: 2rem;
}

.post-card {
	display: grid;
	gap: 1rem;
}

.post-card__media img {
	border-radius: var(--radius);
	width: 100%;
}

.post-card__title {
	margin: 0.25rem 0 0.5rem;
	font-size: 1.375rem;
}

.post-card__title a {
	color: var(--ink);
	text-decoration: none;
}

.post-card__title a:hover {
	color: var(--brand);
	text-decoration: underline;
}

.post-card__excerpt {
	color: var(--muted);
	margin-bottom: 0.5rem;
}

.post-card__more {
	margin-bottom: 0;
	font-weight: 600;
}

@media (min-width: 44rem) {
	.post-card {
		grid-template-columns: 15rem 1fr;
		align-items: start;
	}
}

.pagination {
	padding: 1rem 0 3rem;
}

.pagination .page-numbers {
	display: inline-block;
	padding: 0.4rem 0.7rem;
	margin-right: 0.25rem;
	border: 1px solid var(--border);
	border-radius: 0.375rem;
	text-decoration: none;
}

.pagination .current {
	background: var(--brand);
	color: var(--brand-contrast);
	border-color: var(--brand);
}

.post-navigation {
	display: grid;
	gap: 1rem;
	margin-top: 2.5rem;
	padding-top: 1.5rem;
	border-top: 1px solid var(--border);
}

.post-navigation .nav-label {
	display: block;
	font-size: 0.8125rem;
	text-transform: uppercase;
	letter-spacing: 0.06em;
	color: var(--muted);
}

/* ---------- Search ---------- */

.search-form {
	margin: 1.5rem 0 2rem;
}

.search-form__label {
	display: block;
	font-weight: 600;
	margin-bottom: 0.4rem;
}

.search-form__row {
	display: flex;
	gap: 0.5rem;
	flex-wrap: wrap;
}

.search-form__input {
	flex: 1 1 14rem;
	font: inherit;
	padding: 0.7rem 0.85rem;
	border: 2px solid var(--border);
	border-radius: var(--radius);
}

.search-form__input:focus {
	border-color: var(--brand);
}

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

.site-footer {
	background: var(--surface-alt);
	border-top: 1px solid var(--border);
	margin-top: 0;
	padding: 2.5rem 0 2rem;
	font-size: 0.9375rem;
}

.site-footer__list {
	list-style: none;
	display: flex;
	flex-wrap: wrap;
	gap: 0.5rem 1.5rem;
	justify-content: center;
	margin: 0 0 1rem;
	padding: 0;
}

.site-footer__list a {
	color: var(--ink);
}

.site-footer__contact {
	text-align: center;
	margin-bottom: 1rem;
}

.site-footer__disclaimer {
	border-top: 1px solid var(--border);
	padding-top: 1rem;
	color: var(--ink);
}

/* The disclaimer must stay legible. Do not reduce this below 0.875rem, and do
   not lighten the colour — it is the one piece of text on the page that is
   there because the law requires it. */
.campaign-disclaimer {
	font-size: 0.9375rem;
	color: var(--ink);
	margin: 0;
}

.campaign-disclaimer__address {
	color: var(--muted);
	font-size: 0.875rem;
}

.campaign-disclaimer--missing {
	background: #FEF3C7;
	border: 2px solid #B45309;
	color: #7C2D12;
	padding: 1rem;
	border-radius: var(--radius);
}

/* Contribution notice, styled from the plugin's neutral base. */
.campaign-notice {
	background: var(--surface-alt);
	border-color: var(--border);
	color: var(--ink);
}

.campaign-notice h3 {
	font-family: var(--font-body);
	font-weight: 700;
}

.campaign-consent {
	color: var(--muted);
}

/* ---------- Motion ---------- */

@media (prefers-reduced-motion: reduce) {
	*,
	*::before,
	*::after {
		animation-duration: 0.01ms !important;
		animation-iteration-count: 1 !important;
		transition-duration: 0.01ms !important;
		scroll-behavior: auto !important;
	}
}

/* ---------- Print ---------- */

@media print {
	.site-header,
	.site-nav,
	.cta-band,
	.nav-toggle,
	.skip-link {
		display: none;
	}

	body {
		font-size: 11pt;
	}

	/* Keep the disclaimer on anything printed from the site. */
	.campaign-disclaimer {
		font-size: 9pt;
	}
}


/* ---------- Editorial typography ---------- */

/* The opening paragraph carries the page. Sizing it up gives the reader an
   entry point instead of an undifferentiated wall of body copy. */
.entry__content > p:first-of-type {
	font-size: 1.125rem;
	line-height: 1.65;
	color: var(--ink);
}

.entry--front .entry__content {
	font-size: 1.125rem;
}

.entry--front .entry__content > p:first-of-type {
	font-size: 1.25rem;
}

/* A line from the candidate's own material, set as a pull quote. */
.pullquote {
	margin: 1.75rem 0;
	padding: 0 0 0 1.5rem;
	border-left: 4px solid var(--brand);
	font-family: var(--font-display);
	font-size: 1.3125rem;
	line-height: 1.45;
	font-style: italic;
	color: var(--ink);
}

.pullquote p {
	margin: 0;
}

.pullquote cite {
	display: block;
	margin-top: 0.6rem;
	font-family: var(--font-body, inherit);
	font-size: 0.875rem;
	font-style: normal;
	letter-spacing: 0.04em;
	text-transform: uppercase;
	color: var(--muted);
}

/* The campaign's three-word close, used as a rule between sections. */
.values-strip {
	margin: 1.75rem 0 0;
	padding-top: 1.125rem;
	border-top: 1px solid var(--border);
	text-align: center;
	font-family: var(--font-display);
	font-size: 0.9375rem;
	font-weight: 700;
	letter-spacing: 0.14em;
	text-transform: uppercase;
	color: var(--brand);
}

/* "My commitment" — a short list of undertakings, set apart from prose. */
.commitment-list {
	margin: 1.5rem 0;
	padding: 1.25rem 1.5rem;
	background: var(--surface-alt);
	border-radius: var(--radius);
}

.commitment-list h2 {
	margin-top: 0;
	font-size: 1.0625rem;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: var(--brand);
}

.commitment-list ul {
	display: grid;
	gap: 0.35rem 1.75rem;
	margin: 0;
	padding: 0;
	list-style: none;
}

@media (min-width: 40rem) {
	.commitment-list ul {
		grid-template-columns: 1fr 1fr;
	}
}


/* ---------- About page ---------- */

/* The biography is long and was previously eight undifferentiated paragraphs.
   These rules give it entry points a reader can scan: ruled sections, two
   lists, and the two community moments set side by side. */

.about-section {
	margin: 1.75rem 0 0;
	padding-top: 1.25rem;
	border-top: 1px solid var(--border);
}

.about-section > h2:first-child {
	margin-top: 0;
}

/* One marker language for both lists on the page: a short brand rule rather
   than a bullet, echoing the banner device in the header. */
.lead-list ul,
.commitment-list ul {
	list-style: none;
}

.lead-list ul {
	display: grid;
	gap: 0.4rem;
	margin: 0;
	padding: 0;
}

.lead-list li,
.commitment-list li {
	position: relative;
	margin: 0;
	padding-left: 1.625rem;
}

.lead-list li::before,
.commitment-list li::before {
	content: "";
	position: absolute;
	left: 0;
	top: 0.72em;
	width: 0.75rem;
	height: 2px;
	background: var(--brand);
}

.lead-list li {
	font-family: var(--font-display);
	font-size: 1.125rem;
	line-height: 1.45;
}

/* The ask. White on --brand is 5.59:1, above AA for body text. */
.closing-ask {
	margin: 1.75rem 0 0;
	padding: 1.25rem 1.5rem;
	background: var(--brand);
	color: var(--brand-contrast);
	border-radius: var(--radius);
	font-family: var(--font-display);
	font-size: 1.1875rem;
	line-height: 1.5;
}

.closing-ask p {
	margin: 0;
}

.closing-ask p + p {
	margin-top: 0.75rem;
}


/* ---------- Campaign photography ---------- */

/* Event photographs are phone-sized originals (600px on the long edge for most
   of them), so they are shown in a grid rather than stretched across the
   column, where the softness would be obvious. */
.campaign-gallery,
.about-gallery {
	margin: 1.5rem 0 1.75rem;
}

.campaign-gallery img,
.about-gallery img {
	border-radius: var(--radius);
}

/* Lifting the photographs off the page: they are phone snapshots of varying
   exposure, and a soft edge keeps the lighter ones from dissolving into white. */
.campaign-gallery img,
.about-gallery img,
.entry__content > .wp-block-image img {
	box-shadow: 0 1px 3px rgba(24, 24, 24, 0.12), 0 8px 20px rgba(24, 24, 24, 0.10);
}

.gallery-heading {
	text-align: center;
	text-transform: uppercase;
	letter-spacing: 0.06em;
	font-size: clamp(1.25rem, 1.05rem + 0.9vw, 1.625rem);
}

.entry__content > .wp-block-image img {
	border-radius: var(--radius);
}

/* The single wide photograph between the opening prose and the priorities. */
.entry--front .entry__content > .wp-block-image {
	margin: 1.5rem 0 1.75rem;
}

.entry--front .entry__content > .wp-block-image img {
	width: 100%;
	height: auto;
}

/* Gallery layout is defined here rather than inherited from WordPress's block
   stylesheet: that stylesheet is not being enqueued on this install, so a
   gallery would otherwise stack into one tall column of phone snapshots. */
/* Layout only. The outer margin belongs to .campaign-gallery/.about-gallery;
   setting it here too meant this two-class selector quietly won on specificity
   and the spacing rule above had no effect. */
.wp-block-gallery.has-nested-images {
	display: grid;
	grid-template-columns: repeat(2, 1fr);
	gap: 0.75rem;
	padding: 0;
	list-style: none;
}

/* WordPress's gallery stylesheet is being enqueued again and sizes these
   figures as flex items: `width: calc(33.33% - ...)`. Against a grid parent
   that percentage resolves against the cell, so every photograph came out at a
   third of its cell — 112px inside 354px.
   
   That rule is written as `.wp-block-gallery.has-nested-images.columns-3
   figure.wp-block-image:not(#individual-image)`. The `:not(#individual-image)`
   matches nothing; it is there to buy ID-level specificity (1-4-1). Beating it
   needs the same shape plus one more class, hence the gallery class up front —
   this then wins regardless of stylesheet order, which `!important` would also
   do but less legibly. */
.campaign-gallery.wp-block-gallery.has-nested-images figure.wp-block-image:not(#individual-image),
.about-gallery.wp-block-gallery.has-nested-images figure.wp-block-image:not(#individual-image) {
	flex: none;
	width: 100%;
	max-width: none;
	margin: 0;
	min-width: 0;
}

.wp-block-gallery.has-nested-images > figure > img {
	display: block;
	width: 100%;
	height: 100%;
	aspect-ratio: 4 / 3;
	object-fit: cover;
	border-radius: var(--radius);
}

@media (min-width: 40rem) {
	.wp-block-gallery.has-nested-images.columns-3 {
		grid-template-columns: repeat(3, 1fr);
	}

	.wp-block-gallery.has-nested-images.columns-2 {
		grid-template-columns: repeat(2, 1fr);
	}
}

/* ---------- Click to enlarge ---------- */

/* The photographs are links whether or not the script runs, so they get the
   affordance of one. */
.campaign-gallery a,
.about-gallery a,
.entry__content > .wp-block-image a {
	display: block;
	border-radius: var(--radius);
}

.campaign-gallery a:hover img,
.about-gallery a:hover img,
.entry__content > .wp-block-image a:hover img {
	opacity: 0.92;
}

/* An author `display` beats the browser's own `[hidden] { display: none }`, so
   without this rule setting overlay.hidden does nothing and the overlay stays
   on screen — showing a broken image, because closing also clears the src. */
.lightbox[hidden] {
	display: none;
}

.lightbox {
	position: fixed;
	inset: 0;
	z-index: 999;
	display: flex;
	align-items: center;
	justify-content: center;
	padding: 1.5rem;
	background: rgba(10, 12, 11, 0.92);
}

.lightbox__frame {
	margin: 0;
	max-width: min(100%, 64rem);
	text-align: center;
}

.lightbox__image {
	display: block;
	max-width: 100%;
	/* Leave room for the close button. */
	max-height: calc(100vh - 6rem);
	width: auto;
	height: auto;
	margin: 0 auto;
	border-radius: var(--radius);
}


.lightbox__close {
	position: absolute;
	top: 1rem;
	right: 1rem;
	padding: 0.55rem 1rem;
	font: inherit;
	font-weight: 600;
	color: #FFFFFF;
	background: rgba(255, 255, 255, 0.14);
	border: 2px solid rgba(255, 255, 255, 0.5);
	border-radius: var(--radius);
	cursor: pointer;
}

.lightbox__close:hover {
	background: rgba(255, 255, 255, 0.24);
}

.lightbox__close:focus-visible {
	outline: 3px solid #FFFFFF;
	outline-offset: 2px;
}

/* Stop the page behind the overlay from scrolling under it. */
body.has-lightbox {
	overflow: hidden;
}

@media print {
	.lightbox {
		display: none;
	}
}

/* Mobile header: a nameplate over a banner.
   
   Two buttons floating under a logo is what the header did before, and it read
   as leftovers — equal visual weight for two actions of very unequal value, and
   whichever way they were aligned there was dead space beside them.
   
   The campaign's own lockup already contains the answer: a green banner with
   angled ends running under the name. Repeating that shape as the action strip
   makes the header one object instead of three, gives Donate the width it
   deserves against a menu toggle, and is a device taken from the candidate's
   printed material rather than imported from a component library. */
@media (max-width: 39.999rem) {
	.site-header__inner {
		flex-direction: column;
		align-items: stretch;
		gap: 0.625rem;
		padding: 1rem 0 0.875rem;
	}

	/* Her material is centred — "RE-ELECT", the banner, the script all sit on a
	   centre axis — so the nameplate does too. */
	.site-header__brand {
		display: flex;
		justify-content: center;
		flex: 0 0 auto;
	}

	.site-header__actions {
		width: 100%;
		gap: 0;
		align-items: stretch;
		min-height: 3rem;
		padding: 0 0.875rem;
		background: var(--brand);
		/* The banner's parallelogram, at the same lean. */
		clip-path: polygon(0.75rem 0, 100% 0, calc(100% - 0.75rem) 100%, 0 100%);
	}

	/* Donate takes the width; the toggle takes only what it needs. The two stop
	   competing as a matched pair of pills. */
	.site-header__actions .site-header__donate {
		flex: 1;
		display: flex;
		align-items: center;
		justify-content: center;
		padding: 0.75rem 0.5rem;
		background: transparent;
		border: 0;
		border-radius: 0;
		color: var(--brand-contrast);
		font-size: 0.875rem;
		font-weight: 700;
		letter-spacing: 0.12em;
		text-transform: uppercase;
	}

	.site-header__actions .nav-toggle {
		display: inline-flex;
		padding: 0.75rem 0.25rem 0.75rem 1rem;
		background: transparent;
		border: 0;
		/* A hairline, the way the banner separates its stars from its type. */
		border-left: 1px solid rgba(255, 255, 255, 0.45);
		border-radius: 0;
		color: var(--brand-contrast);
		font-size: 0.8125rem;
		font-weight: 700;
		letter-spacing: 0.12em;
		text-transform: uppercase;
	}

	/* The clip-path would crop an outline drawn outside the element, so focus
	   rings are drawn inside it instead. */
	.site-header__actions a:focus-visible,
	.site-header__actions button:focus-visible {
		outline: 3px solid var(--brand-contrast);
		outline-offset: -5px;
	}

	.site-header__actions .site-header__donate:hover,
	.site-header__actions .nav-toggle:hover {
		background: rgba(255, 255, 255, 0.12);
	}
}
