/**
 * global.css — base reset + accessibility utilities.
 *
 * Shared studio baseline. Loaded first; every other stylesheet in
 * assets/css/ depends on it. Per the methodology hard-constraints this file
 * sets NO font-size, NO margin for spacing, and NO gap — those belong to
 * theme.json tokens and block attributes. Keep it to resets + a11y only.
 */

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

/* Flush-left utility for the Max Width control (editor/max-width.js +
   inc/filters-max-width.php). WP constrained layout auto-centers any child
   narrower than contentSize via `margin-inline: auto !important`. The content
   column itself is centred inside the section's padding box, so simply zeroing
   margin-inline-start flushes to the PADDING edge — ~100px left of where the
   title/eyebrow (normal constrained children) sit, i.e. it breaks out of the
   content column. Align to the content-column left edge instead:
   (100% − contentSize)/2, clamped to 0 when the viewport is narrower than
   contentSize. Canonical rule from the wp-fse-theme starter (this project had
   drifted to the old padding-edge version). INLINE margins only — never touch
   margin-block or it breaks blockGap. */
.wulr-flush-left.wulr-flush-left {
	margin-inline-start: max(0px, calc((100% - var(--wp--style--global--content-size)) / 2)) !important;
	margin-inline-end: auto !important;
}
/* Same cure for elements in a rotated writing mode — physical properties,
   because that is what core's constrained rule sets on them. */
.wulr-flush-left--physical.wulr-flush-left--physical {
	margin-left: max(0px, calc((100% - var(--wp--style--global--content-size)) / 2)) !important;
	margin-right: auto !important;
}

/* Elevation tokens — reference these; never hardcode box-shadow in components. */
:root {
	--wulr-shadow-lift: 0 -6px 40px rgba(14, 14, 14, 0.16);
	/* Resting elevation for a floating card (masthead download card). */
	--wulr-shadow-card: 0 30px 60px -24px rgba(14, 14, 14, 0.28);

	/* -------------------------------------------------------------------
	   Brand double-rule mark — the thick + thin line pair that sits under
	   a green section edge (header mark, archive lists, page bodies, the
	   homepage featured hero, the About image hero, and the "Double Rule
	   (bottom)" group block style).

	   Reference these; never hardcode the weights or the offset in
	   components. The three primitives are the design; the rest are
	   derived so a single change moves every instance together.

	     offset ─┐
	             ├─ thick
	             ├─ gap  (background shows through)
	             └─ thin

	   Color is NOT tokenized here — it varies by context (primary green on
	   light, secondary paper on dark sections), so each component sets it.
	   ------------------------------------------------------------------- */
	--wulr-rule-thick: 4px;
	--wulr-rule-gap: 5px;
	--wulr-rule-thin: 1px;
	--wulr-rule-offset: 6px; /* gap between the section edge above and the thick line */

	/* Derived — where the thin line starts, measured inside the mark. */
	--wulr-rule-thin-start: calc(var(--wulr-rule-thick) + var(--wulr-rule-gap));
	/* Derived — total height of the mark, for single-element (gradient) builds. */
	--wulr-rule-span: calc(var(--wulr-rule-thin-start) + var(--wulr-rule-thin));
	/* Derived — the thin line's `top` when the mark is offset below a section edge. */
	--wulr-rule-thin-offset: calc(var(--wulr-rule-offset) + var(--wulr-rule-thin-start));
}

/* -----------------------------------------------
   Shared arrow control — circular prev/next button.

   Used by the homepage card rails (home.js) and the About timeline
   (timeline.js). Lived in home.css until it gained a second consumer; per the
   methodology a UI element appearing in 2+ components becomes a shared utility
   rather than being duplicated.

   `aria-disabled` (not the `disabled` attribute) marks an unavailable end-stop:
   a disabled button loses focus when it's the element you just clicked, which
   strands keyboard users mid-interaction. aria-disabled keeps it focusable and
   announced; the component's JS is responsible for no-op'ing the action.
   ----------------------------------------------- */
.wulr-rail-controls { display: flex; align-items: center; gap: 18px; }
.wulr-rail-arrows { display: flex; gap: 10px; }
.wulr-rail-arrow {
	width: 46px;
	height: 46px;
	border-radius: 999px;
	/* stone (>=3:1) rail-arrow boundary on light sections; rule token was 1.8:1 (1.4.11). */
	border: 1px solid var(--wp--preset--color--stone);
	background: var(--wp--preset--color--white);
	color: var(--wp--preset--color--accent);
	cursor: pointer;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	transition: background 0.15s, color 0.15s, border-color 0.15s, opacity 0.15s;
}
.wulr-rail-arrow:hover,
.wulr-rail-arrow:focus-visible {
	background: var(--wp--preset--color--accent);
	border-color: var(--wp--preset--color--accent);
	color: var(--wp--preset--color--white);
}
.wulr-rail-arrow svg { width: 18px; height: 18px; }
.wulr-rail-arrow[aria-disabled="true"] {
	opacity: 0.32;
	cursor: default;
}
/* Don't invite a click that won't do anything. */
.wulr-rail-arrow[aria-disabled="true"]:hover {
	background: var(--wp--preset--color--white);
	/* keep the disabled arrow's border matching the enabled stone boundary. */
	border-color: var(--wp--preset--color--stone);
	color: var(--wp--preset--color--accent);
}

/* -----------------------------------------------
   Native core/button hover.

   theme.json defines the button BASE (styles.elements.button + the outline
   variation) but cannot express hover, so every core/button rendered anywhere
   on the site had no hover state. Both the filled default (accent fill) and the
   outline variant converge on ONE destination — dark-green fill, white text —
   matching the homepage subscribe/search pattern the client endorsed, so all
   buttons behave alike. Paired with :focus-visible so keyboard users get the
   same feedback (WCAG 2.4.7).

   Lives in global.css because core buttons are site-wide; scoping it to one
   component would leave the next button dead on hover again.
   ----------------------------------------------- */
.wp-element-button {
	transition: background-color 0.15s, color 0.15s, border-color 0.15s;
}
.wp-element-button:hover,
.wp-element-button:focus-visible {
	background-color: var(--wp--preset--color--primary);
	color: var(--wp--preset--color--white);
	/* theme.json gives every button a 1px accent border at rest; move it to
	   primary too or the filled button hovers to green ringed in red. This one
	   declaration also covers the outline variant, whose border is likewise
	   accent — so both converge on a clean green pill. */
	border-color: var(--wp--preset--color--primary);
}

/* Font rendering — grayscale antialiasing + legibility, matching the design
   comps (which set this on <body>). Only affects macOS WebKit/Blink; Windows
   and Firefox use their platform defaults. Does not change contrast — WCAG
   1.4.3 is computed from the specified color values, not rendered pixels. */
body {
	-webkit-font-smoothing: antialiased;
	-moz-osx-font-smoothing: grayscale;
	text-rendering: optimizeLegibility;
}

/* Horizontal-scroll guard. Full-bleed sections and the card rails bleed to the
   viewport edge with vw-based math; when a vertical scrollbar is present that
   math can land a few px past the content box and let the whole PAGE scroll /
   rubber-band sideways (sister sites prevent this with `body{overflow-x:hidden}`).
   `overflow-x: clip` on the root removes page-level horizontal scroll WITHOUT
   establishing a scroll container, so `position: sticky` (article share rail,
   sticky bar) and the rails' own internal horizontal scroll keep working —
   which `overflow-x: hidden` would break. Applied to <body> (not <html>): root
   overflow propagates oddly to the viewport and won't clip normal-flow content,
   whereas body-level clip does — matching the sister sites' `body` guard. */
body {
	overflow-x: clip;
}

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

/* -----------------------------------------------
   Spacing system — sections own their vertical spacing.

   WP implements the root blockGap as margin-block-start on each top-level
   block. Zeroing it here removes the blank space between full-width sections
   on the front end, in the editor canvas, and inside post-content — so each
   section controls its own breathing room via its `section` padding preset
   + per-section blockGap, and adjacent sections sit flush. Content NESTED
   inside a section still gets theme.json's blockGap rhythm.
   ----------------------------------------------- */
.wp-site-blocks > *,
.editor-styles-wrapper > .is-root-container > *,
.entry-content > * {
	margin-block-start: 0;
	margin-block-end: 0;
}

/* Adjacent same-color section hairline fix — overlap same-background
   sections by 1px to defeat sub-pixel seams at DPR >= 2. */
.has-primary-background-color + .has-primary-background-color,
.has-secondary-background-color + .has-secondary-background-color,
.has-secondary-background-color + .has-white-background-color,
.has-white-background-color + .has-secondary-background-color,
.has-white-background-color + .has-white-background-color,
.has-accent-background-color + .has-accent-background-color,
.has-muted-background-color + .has-muted-background-color {
	margin-top: -1px;
}

/* Prose opt-in — restore native block-gap rhythm for long-form content.
   Section-based pages manage their own spacing; single posts contain
   paragraphs/headings that need vertical rhythm. */
.single-post .entry-content > * + * {
	margin-block-start: var(--wp--style--block-gap);
	margin-block-end: 0;
}

/* Page prose rhythm — pages aren't the article reading column (no 20px), but a
   content page's paragraphs/headings/lists still need vertical rhythm. Section-
   based pages (About, Masthead, …) put full-width Group sections at the top
   level; those own their spacing and must stay flush, so restore blockGap only
   BETWEEN adjacent constrained blocks — a full/wide neighbor on either side
   keeps the seam flush. */
.page .entry-content > :not(.alignfull):not(.alignwide) + :not(.alignfull):not(.alignwide) {
	margin-block-start: var(--wp--style--block-gap);
	margin-block-end: 0;
}

/* Accessibility — visually hidden until focused (WP-standard). Self-contained
   color + background so contrast tools score it against its own white ground
   (~16:1) instead of whatever section it's clipped inside — e.g. the "Posts"
   list label sits in the dark-green archive hero and inherits dark heading ink,
   which reads as dark-on-dark to WAVE even though the 1x1 clip makes it
   invisible. No visual effect (clipped); the skip-link :focus rule below still
   overrides both when it becomes visible. */
.screen-reader-text {
	border: 0;
	clip: rect(1px, 1px, 1px, 1px);
	clip-path: inset(50%);
	height: 1px;
	width: 1px;
	overflow: hidden;
	padding: 0;
	position: absolute !important;
	word-wrap: normal !important;
	color: var(--wp--preset--color--body);
	background-color: var(--wp--preset--color--white);
}

/* Skip link — abspos overlay, becomes visible on focus. */
.skip-link.screen-reader-text:focus {
	background-color: var(--wp--preset--color--secondary);
	color: var(--wp--preset--color--primary);
	clip: auto;
	clip-path: none;
	display: block;
	height: auto;
	left: 8px;
	top: 8px;
	padding: 12px 20px;
	width: auto;
	z-index: 100000;
	outline: 2px solid var(--wp--preset--color--accent);
}

/* Honor reduced-motion globally. */
@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;
	}
}

/* The native WebKit clear (×) button on search inputs renders blue (off-brand).
   Tint it across every search field — results-page field, header search
   overlay, etc.: stone at rest, accent red on hover. Context-specific overrides
   (e.g. the white-on-green 404 field) win by higher specificity. */
input[type="search"]::-webkit-search-cancel-button {
	-webkit-appearance: none;
	appearance: none;
	width: 15px;
	height: 15px;
	margin-left: 8px;
	cursor: pointer;
	background-color: var(--wp--preset--color--stone);
	-webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.5' stroke-linecap='round'%3E%3Cpath d='M6 6l12 12M18 6L6 18'/%3E%3C/svg%3E") center / contain no-repeat;
	        mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23000' stroke-width='2.5' stroke-linecap='round'%3E%3Cpath d='M6 6l12 12M18 6L6 18'/%3E%3C/svg%3E") center / contain no-repeat;
	transition: background-color 0.15s;
}
input[type="search"]::-webkit-search-cancel-button:hover {
	background-color: var(--wp--preset--color--accent);
}
