/*
 * Stillpoint — global stylesheet (front end + editor canvas).
 *
 * Binding references: docs/DESIGN.md §4–§8 (visual system) and docs/SPEC.md §1 (token names).
 * Golden rule: no hard-coded colours, font stacks, radii, shadows or spacing. Everything reads
 * theme.json tokens (--wp--preset--*, --wp--custom--*) through the contextual roles (--sp-*).
 *
 * Specificity policy
 *   - Properties that theme.json / Site Editor Global Styles also control (heading sizes, button
 *     colours, link colour…) are written with :where() so the merged global stylesheet still wins.
 *   - Rules that must beat a core block stylesheet or a structural default use the lightest
 *     selector that does so, and say why.
 *   - Block-style variations that only exist on one block live in assets/css/blocks/core-*.css,
 *     which load only when that block is on the page.
 *
 * Contents
 *   01 Tokens + contextual roles (DESIGN §5.1, §8.2 art tokens)
 *   02 Section styles + hand-coloured groups + palette text classes
 *   03 Cards (boxed, outline)
 *   04 Base + typography (DESIGN §4.4)
 *   05 Links, focus, skip link, selection (DESIGN §7.15)
 *   06 Eyebrow + Stillpoint marker (DESIGN §7.5)
 *   07 Buttons (DESIGN §7.4)
 *   08 Header, navigation, submenus, sticky, mobile, overlays (DESIGN §7.1–7.2)
 *   09 Footer (DESIGN §7.3)
 *   10 Tags, status tags, level meter, intensity, chips (DESIGN §7.7)
 *   11 Pricing, stats, dates (DESIGN §7.10, §9)
 *   12 Forms + joined form (DESIGN §7.12)
 *   13 Image treatments, echo, captions, art (DESIGN §8.1–8.2)
 *   14 Post meta, read more, post navigation (story cards, pagination and comments live in
 *      blocks/core-post-template.css, core-query-pagination.css, core-comments.css)
 *   15 Motion + reveal + reduced motion (DESIGN §6.4)
 *   16 Dark scheme (DESIGN §3.2, §8.1)
 *   17 Print
 */

/* =========================================================================================
   01 Tokens + contextual roles
   ========================================================================================= */

:root {
	/* Paper — the page ground (DESIGN §5.1). */
	--sp-bg: var(--wp--preset--color--base);
	--sp-fg: var(--wp--preset--color--contrast);
	--sp-muted: var(--wp--preset--color--muted);
	--sp-line: var(--wp--preset--color--border);
	--sp-soft: var(--wp--preset--color--tint);
	--sp-card: var(--wp--preset--color--surface);
	--sp-accent: var(--wp--preset--color--primary);
	--sp-on-accent: var(--wp--preset--color--on-primary);
	--sp-accent-hover: var(--wp--custom--color--primary-hover, var(--wp--preset--color--primary));
	--sp-focus: var(--wp--custom--focus--color, var(--wp--preset--color--primary));
	--sp-field: var(--wp--preset--color--muted);
	/* Private helper roles: the Stillpoint marker (secondary on light grounds, accent on Ink/Brand)
	   and the <mark> highlight (a secondary wash, or the soft fill where a wash would cost contrast). */
	--sp-mark: var(--wp--preset--color--secondary);
	--sp-highlight: color-mix(in srgb, var(--wp--preset--color--secondary) 45%, var(--wp--preset--color--base));
	/* The lighter and the darker of base/contrast, for covers. --wp--custom--scheme--dark is 1 in dark Looks
	   (the engine's token, present in the editor too), so the mix picks contrast there and base elsewhere. */
	--sp-light: color-mix(in srgb, var(--wp--preset--color--contrast) calc(var(--wp--custom--scheme--dark, 0) * 100%), var(--wp--preset--color--base));
	--sp-dark: color-mix(in srgb, var(--wp--preset--color--base) calc(var(--wp--custom--scheme--dark, 0) * 100%), var(--wp--preset--color--contrast));

	/* Art tokens: art follows the Look, never the section (DESIGN §8.2). */
	--sp-art-ground: var(--wp--preset--color--surface);
	--sp-art-paper: var(--wp--preset--color--base);
	--sp-art-sun: var(--wp--preset--color--secondary);
	--sp-art-clay: color-mix(in srgb, var(--wp--preset--color--primary) 35%, var(--wp--preset--color--base));
	--sp-art-deep: color-mix(in srgb, var(--wp--preset--color--primary) 70%, var(--wp--preset--color--contrast));
	--sp-art-tint: var(--wp--preset--color--tint);
	--sp-art-line: color-mix(in srgb, var(--wp--preset--color--contrast) 55%, var(--wp--preset--color--base));
	--sp-art-ink: var(--wp--preset--color--contrast);

	/* Motion shorthands (DESIGN §6.4). The engine sets the custom tokens to 0ms when motion is off. */
	--sp-ease: var(--wp--custom--motion--easing, cubic-bezier(.22, .61, .36, 1));
	--sp-fast: var(--wp--custom--motion--duration-fast, 160ms);
	--sp-dur: var(--wp--custom--motion--duration, 320ms);
	--sp-slow: var(--wp--custom--motion--duration-slow, 700ms);

	/* Type helpers. */
	--sp-scale: var(--wp--custom--heading--scale, 1);
	--sp-heading-lh: var(--wp--custom--heading--line-height, 1.1);

	/* Image echo offset (DESIGN §8.1): spacing-30, spacing-20 below 600px. */
	--sp-echo: var(--wp--preset--spacing--30);

	/* Card inner padding, shared by the nested-radius media bleed (DESIGN §6.1, §7.6). */
	--sp-card-pad: var(--wp--preset--spacing--40);
}

/* =========================================================================================
   02 Section styles (SPEC §1.6) + hand-coloured groups
   Every ground re-points every role, so components never need to know where they sit.
   ========================================================================================= */

/* Paper (also re-establishes Paper inside an inverted ancestor). */
:where(.has-base-background-color) {
	--sp-bg: var(--wp--preset--color--base);
	--sp-fg: var(--wp--preset--color--contrast);
	--sp-muted: var(--wp--preset--color--muted);
	--sp-line: var(--wp--preset--color--border);
	--sp-soft: var(--wp--preset--color--tint);
	--sp-card: var(--wp--preset--color--surface);
	--sp-accent: var(--wp--preset--color--primary);
	--sp-on-accent: var(--wp--preset--color--on-primary);
	--sp-accent-hover: var(--wp--custom--color--primary-hover, var(--wp--preset--color--primary));
	--sp-focus: var(--wp--custom--focus--color, var(--wp--preset--color--primary));
	--sp-field: var(--wp--preset--color--muted);
	--sp-mark: var(--wp--preset--color--secondary);
	--sp-highlight: color-mix(in srgb, var(--wp--preset--color--secondary) 45%, var(--wp--preset--color--base));
	color: var(--sp-fg);
}

/* Linen — section-surface. */
:where(.is-style-section-surface, .has-surface-background-color) {
	--sp-bg: var(--wp--preset--color--surface);
	--sp-fg: var(--wp--preset--color--contrast);
	--sp-muted: var(--wp--preset--color--muted);
	--sp-line: color-mix(in srgb, var(--wp--preset--color--contrast) 18%, var(--wp--preset--color--surface));
	--sp-soft: color-mix(in srgb, var(--wp--preset--color--contrast) 6%, var(--wp--preset--color--surface));
	--sp-card: var(--wp--preset--color--base);
	--sp-accent: var(--wp--preset--color--primary);
	--sp-on-accent: var(--wp--preset--color--on-primary);
	--sp-accent-hover: var(--wp--custom--color--primary-hover, var(--wp--preset--color--primary));
	--sp-focus: var(--wp--custom--focus--color, var(--wp--preset--color--primary));
	--sp-field: var(--wp--preset--color--muted);
	--sp-mark: var(--wp--preset--color--secondary);
	--sp-highlight: color-mix(in srgb, var(--wp--preset--color--secondary) 45%, var(--wp--preset--color--surface));
	color: var(--sp-fg);
}

/* Wash — section-tint. */
:where(.is-style-section-tint, .has-tint-background-color) {
	--sp-bg: var(--wp--preset--color--tint);
	--sp-fg: var(--wp--preset--color--contrast);
	--sp-muted: var(--wp--preset--color--muted);
	--sp-line: color-mix(in srgb, var(--wp--preset--color--contrast) 18%, var(--wp--preset--color--tint));
	--sp-soft: color-mix(in srgb, var(--wp--preset--color--contrast) 6%, var(--wp--preset--color--tint));
	--sp-card: var(--wp--preset--color--base);
	--sp-accent: var(--wp--preset--color--primary);
	--sp-on-accent: var(--wp--preset--color--on-primary);
	--sp-accent-hover: var(--wp--custom--color--primary-hover, var(--wp--preset--color--primary));
	--sp-focus: var(--wp--custom--focus--color, var(--wp--preset--color--primary));
	--sp-field: var(--wp--preset--color--muted);
	--sp-mark: var(--wp--preset--color--secondary);
	--sp-highlight: color-mix(in srgb, var(--wp--preset--color--secondary) 45%, var(--wp--preset--color--tint));
	color: var(--sp-fg);
}

/* Ink — section-inverse (a light "spotlight" band in dark Looks, by design). */
:where(.is-style-section-inverse, .has-contrast-background-color) {
	--sp-bg: var(--wp--preset--color--contrast);
	--sp-fg: var(--wp--preset--color--base);
	--sp-muted: color-mix(in srgb, var(--wp--preset--color--base) 72%, var(--wp--preset--color--contrast));
	--sp-line: color-mix(in srgb, var(--wp--preset--color--base) 18%, var(--wp--preset--color--contrast));
	--sp-soft: color-mix(in srgb, var(--wp--preset--color--base) 10%, var(--wp--preset--color--contrast));
	--sp-card: color-mix(in srgb, var(--wp--preset--color--base) 8%, var(--wp--preset--color--contrast));
	--sp-accent: var(--wp--preset--color--base);
	--sp-on-accent: var(--wp--preset--color--contrast);
	--sp-accent-hover: color-mix(in srgb, var(--wp--preset--color--base) 85%, var(--wp--preset--color--contrast));
	--sp-focus: var(--wp--preset--color--base);
	--sp-field: color-mix(in srgb, var(--wp--preset--color--base) 72%, var(--wp--preset--color--contrast));
	--sp-mark: var(--wp--preset--color--base);
	--sp-highlight: var(--sp-soft);
	color: var(--sp-fg);
}

/* Brand — section-brand. */
:where(.is-style-section-brand, .has-primary-background-color) {
	--sp-bg: var(--wp--preset--color--primary);
	--sp-fg: var(--wp--preset--color--on-primary);
	--sp-muted: color-mix(in srgb, var(--wp--preset--color--on-primary) 85%, var(--wp--preset--color--primary));
	--sp-line: color-mix(in srgb, var(--wp--preset--color--on-primary) 30%, var(--wp--preset--color--primary));
	--sp-soft: color-mix(in srgb, var(--wp--preset--color--on-primary) 12%, var(--wp--preset--color--primary));
	--sp-card: color-mix(in srgb, var(--wp--preset--color--on-primary) 10%, var(--wp--preset--color--primary));
	--sp-accent: var(--wp--preset--color--on-primary);
	--sp-on-accent: var(--wp--preset--color--primary);
	--sp-accent-hover: color-mix(in srgb, var(--wp--preset--color--on-primary) 85%, var(--wp--preset--color--primary));
	--sp-focus: var(--wp--preset--color--on-primary);
	--sp-field: color-mix(in srgb, var(--wp--preset--color--on-primary) 85%, var(--wp--preset--color--primary));
	--sp-mark: var(--wp--preset--color--on-primary);
	--sp-highlight: var(--sp-soft);
	color: var(--sp-fg);
}

/* Owner-picked decorative grounds (not section styles, but they must stay legible too). */
:where(.has-secondary-background-color) {
	--sp-bg: var(--wp--preset--color--secondary);
	--sp-fg: var(--wp--preset--color--on-secondary);
	--sp-muted: color-mix(in srgb, var(--wp--preset--color--on-secondary) 90%, var(--wp--preset--color--secondary));
	--sp-line: color-mix(in srgb, var(--wp--preset--color--on-secondary) 30%, var(--wp--preset--color--secondary));
	--sp-soft: color-mix(in srgb, var(--wp--preset--color--on-secondary) 6%, var(--wp--preset--color--secondary));
	--sp-card: color-mix(in srgb, var(--wp--preset--color--on-secondary) 10%, var(--wp--preset--color--secondary));
	--sp-accent: var(--wp--preset--color--on-secondary);
	--sp-on-accent: var(--wp--preset--color--secondary);
	--sp-accent-hover: color-mix(in srgb, var(--wp--preset--color--on-secondary) 92%, var(--wp--preset--color--secondary));
	--sp-focus: var(--wp--preset--color--on-secondary);
	--sp-field: color-mix(in srgb, var(--wp--preset--color--on-secondary) 90%, var(--wp--preset--color--secondary));
	--sp-mark: var(--wp--preset--color--on-secondary);
	--sp-highlight: var(--sp-soft);
	color: var(--sp-fg);
}

:where(.has-muted-background-color) {
	--sp-bg: var(--wp--preset--color--muted);
	--sp-fg: var(--wp--preset--color--base);
	--sp-muted: color-mix(in srgb, var(--wp--preset--color--base) 90%, var(--wp--preset--color--muted));
	--sp-line: color-mix(in srgb, var(--wp--preset--color--base) 30%, var(--wp--preset--color--muted));
	--sp-soft: color-mix(in srgb, var(--wp--preset--color--base) 6%, var(--wp--preset--color--muted));
	--sp-card: color-mix(in srgb, var(--wp--preset--color--base) 10%, var(--wp--preset--color--muted));
	--sp-accent: var(--wp--preset--color--base);
	--sp-on-accent: var(--wp--preset--color--muted);
	--sp-accent-hover: color-mix(in srgb, var(--wp--preset--color--base) 90%, var(--wp--preset--color--muted));
	--sp-focus: var(--wp--preset--color--base);
	--sp-field: color-mix(in srgb, var(--wp--preset--color--base) 90%, var(--wp--preset--color--muted));
	--sp-mark: var(--wp--preset--color--base);
	--sp-highlight: var(--sp-soft);
	color: var(--sp-fg);
}

/* Section styles paint themselves from the roles (theme.json variations set the same values). */
:where(.is-style-section-surface, .is-style-section-tint, .is-style-section-inverse, .is-style-section-brand) {
	background-color: var(--sp-bg);
	color: var(--sp-fg);
}

/* Palette text classes become contextual: "muted" text inside an Ink band is Ink-muted, a
   "primary" word inside a Brand band stays visible. Identical to core's values on light grounds.
   :root raises specificity above core's preset classes, which are !important as well. */
:root .has-muted-color {
	color: var(--sp-muted) !important;
}

:root .has-primary-color {
	color: var(--sp-accent) !important;
}

:root .has-contrast-color {
	color: var(--sp-fg) !important;
}

/* =========================================================================================
   03 Cards (section styles `card`, `card-outline`; DESIGN §5.1, §7.6)
   ========================================================================================= */

/* Boxed card: the "other" ground (inverse-card rule). Two-class selectors so a theme.json
   variation that paints with a fixed palette colour can never break role inversion. */
:is(.wp-block-group, .wp-block-column).is-style-card {
	--sp-bg: var(--sp-card);
	--sp-line: color-mix(in srgb, var(--sp-fg) 18%, var(--sp-card));
	--sp-soft: color-mix(in srgb, var(--sp-fg) 6%, var(--sp-card));
	background-color: var(--sp-card);
	color: var(--sp-fg);
	border: var(--wp--custom--border--width, 1px) solid var(--sp-line);
	border-radius: var(--wp--custom--radius--card);
	box-shadow: var(--wp--custom--shadow--card, none);
}

/* With shadows on, the card drops its hairline (shadow-card is literally `none` when off). */
@container not style(--wp--custom--shadow--card: none) {
	:is(.wp-block-group, .wp-block-column).is-style-card {
		border-color: transparent;
	}
}

:is(.wp-block-group, .wp-block-column).is-style-card-outline {
	background-color: transparent;
	border: var(--wp--custom--border--width, 1px) solid var(--sp-line);
	border-radius: var(--wp--custom--radius--card);
}

:where(.is-style-card, .is-style-card-outline) {
	padding: var(--sp-card-pad);
}

/* Border ground: lighter than Linen, so secondary text is a darker mix of muted and text (4.5:1 in every Look). */
:where(.has-border-background-color) {
	--sp-bg: var(--wp--preset--color--border);
	--sp-fg: var(--wp--preset--color--contrast);
	--sp-muted: color-mix(in srgb, var(--wp--preset--color--contrast) 45%, var(--wp--preset--color--muted));
	--sp-line: color-mix(in srgb, var(--wp--preset--color--contrast) 30%, var(--wp--preset--color--border));
	--sp-soft: color-mix(in srgb, var(--wp--preset--color--contrast) 6%, var(--wp--preset--color--border));
	--sp-card: color-mix(in srgb, var(--wp--preset--color--contrast) 10%, var(--wp--preset--color--border));
	--sp-accent: color-mix(in srgb, var(--wp--preset--color--primary) 85%, var(--wp--preset--color--contrast));
	--sp-on-accent: var(--wp--preset--color--on-primary);
	--sp-accent-hover: var(--wp--custom--color--primary-hover, var(--wp--preset--color--primary));
	--sp-focus: var(--wp--preset--color--contrast);
	--sp-field: color-mix(in srgb, var(--wp--preset--color--contrast) 45%, var(--wp--preset--color--muted));
	--sp-mark: var(--wp--preset--color--contrast);
	--sp-highlight: var(--sp-soft);
	color: var(--sp-fg);
}

/* The two computed "text on" colours used as grounds: their partner colour is the text. */
:where(.has-on-primary-background-color) {
	--sp-bg: var(--wp--preset--color--on-primary);
	--sp-fg: var(--wp--preset--color--primary);
	--sp-muted: color-mix(in srgb, var(--wp--preset--color--primary) 90%, var(--wp--preset--color--on-primary));
	--sp-line: color-mix(in srgb, var(--wp--preset--color--primary) 30%, var(--wp--preset--color--on-primary));
	--sp-soft: color-mix(in srgb, var(--wp--preset--color--primary) 6%, var(--wp--preset--color--on-primary));
	--sp-card: color-mix(in srgb, var(--wp--preset--color--primary) 10%, var(--wp--preset--color--on-primary));
	--sp-accent: var(--wp--preset--color--primary);
	--sp-on-accent: var(--wp--preset--color--on-primary);
	--sp-accent-hover: color-mix(in srgb, var(--wp--preset--color--primary) 92%, var(--wp--preset--color--on-primary));
	--sp-focus: var(--wp--preset--color--primary);
	--sp-field: color-mix(in srgb, var(--wp--preset--color--primary) 90%, var(--wp--preset--color--on-primary));
	--sp-mark: var(--wp--preset--color--primary);
	--sp-highlight: var(--sp-soft);
	color: var(--sp-fg);
}

:where(.has-on-secondary-background-color) {
	--sp-bg: var(--wp--preset--color--on-secondary);
	--sp-fg: var(--wp--preset--color--secondary);
	--sp-muted: color-mix(in srgb, var(--wp--preset--color--secondary) 94%, var(--wp--preset--color--on-secondary));
	--sp-line: color-mix(in srgb, var(--wp--preset--color--secondary) 30%, var(--wp--preset--color--on-secondary));
	--sp-soft: color-mix(in srgb, var(--wp--preset--color--secondary) 6%, var(--wp--preset--color--on-secondary));
	--sp-card: color-mix(in srgb, var(--wp--preset--color--secondary) 10%, var(--wp--preset--color--on-secondary));
	--sp-accent: var(--wp--preset--color--secondary);
	--sp-on-accent: var(--wp--preset--color--on-secondary);
	--sp-accent-hover: color-mix(in srgb, var(--wp--preset--color--secondary) 92%, var(--wp--preset--color--on-secondary));
	--sp-focus: var(--wp--preset--color--secondary);
	--sp-field: color-mix(in srgb, var(--wp--preset--color--secondary) 94%, var(--wp--preset--color--on-secondary));
	--sp-mark: var(--wp--preset--color--secondary);
	--sp-highlight: var(--sp-soft);
	color: var(--sp-fg);
}

/* Covers pick their text from the overlay itself, not from core's saved is-light flag (that flag is decided once,
   in the Look the cover was built in, so it goes stale when the Look changes). The cover works out the colour
   behind its content (overlay at its opacity over the ground it sits on), and the content uses white or black,
   whichever contrasts more: the WCAG luminance of that colour is its xyz-d65 "y", and 0.1791 is where white and
   black tie, so text always reaches at least 4.58:1 against the overlay. A cover with a section style (the Hero
   cover pattern uses Ink) keeps that section's roles instead. Custom (non-palette) overlays fall back to the flag. */
:where(.wp-block-cover) {
	--sp-overlay: var(--sp-dark);
	--sp-dim: 0.5;
}

:where(.wp-block-cover.is-light) {
	--sp-overlay: var(--sp-light);
}

:where(.wp-block-cover:has(> .wp-block-cover__background.has-base-background-color)) { --sp-overlay: var(--wp--preset--color--base); }
:where(.wp-block-cover:has(> .wp-block-cover__background.has-surface-background-color)) { --sp-overlay: var(--wp--preset--color--surface); }
:where(.wp-block-cover:has(> .wp-block-cover__background.has-contrast-background-color)) { --sp-overlay: var(--wp--preset--color--contrast); }
:where(.wp-block-cover:has(> .wp-block-cover__background.has-muted-background-color)) { --sp-overlay: var(--wp--preset--color--muted); }
:where(.wp-block-cover:has(> .wp-block-cover__background.has-primary-background-color)) { --sp-overlay: var(--wp--preset--color--primary); }
:where(.wp-block-cover:has(> .wp-block-cover__background.has-on-primary-background-color)) { --sp-overlay: var(--wp--preset--color--on-primary); }
:where(.wp-block-cover:has(> .wp-block-cover__background.has-secondary-background-color)) { --sp-overlay: var(--wp--preset--color--secondary); }
:where(.wp-block-cover:has(> .wp-block-cover__background.has-on-secondary-background-color)) { --sp-overlay: var(--wp--preset--color--on-secondary); }
:where(.wp-block-cover:has(> .wp-block-cover__background.has-tint-background-color)) { --sp-overlay: var(--wp--preset--color--tint); }
:where(.wp-block-cover:has(> .wp-block-cover__background.has-border-background-color)) { --sp-overlay: var(--wp--preset--color--border); }

:where(.wp-block-cover:has(> .has-background-dim-0)) { --sp-dim: 0; }
:where(.wp-block-cover:has(> .has-background-dim-10)) { --sp-dim: 0.1; }
:where(.wp-block-cover:has(> .has-background-dim-20)) { --sp-dim: 0.2; }
:where(.wp-block-cover:has(> .has-background-dim-30)) { --sp-dim: 0.3; }
:where(.wp-block-cover:has(> .has-background-dim-40)) { --sp-dim: 0.4; }
:where(.wp-block-cover:has(> .has-background-dim-50)) { --sp-dim: 0.5; }
:where(.wp-block-cover:has(> .has-background-dim-60)) { --sp-dim: 0.6; }
:where(.wp-block-cover:has(> .has-background-dim-70)) { --sp-dim: 0.7; }
:where(.wp-block-cover:has(> .has-background-dim-80)) { --sp-dim: 0.8; }
:where(.wp-block-cover:has(> .has-background-dim-90)) { --sp-dim: 0.9; }
:where(.wp-block-cover:has(> .has-background-dim-100)) { --sp-dim: 1; }

:where(.wp-block-cover:not([class*="is-style-section-"])) {
	--sp-under: color-mix(in srgb, var(--sp-overlay) calc(var(--sp-dim) * 100%), var(--sp-bg));
	/* White or black by luminance, converted back to sRGB so the computed value is an ordinary colour. */
	--sp-cover-text: color-mix(in srgb, color(from var(--sp-under) xyz-d65 calc(clamp(0, (0.1791 - y) * 100000, 1) * 0.95047) clamp(0, (0.1791 - y) * 100000, 1) calc(clamp(0, (0.1791 - y) * 100000, 1) * 1.08883)) 100%, var(--sp-under));
}

/* On the cover itself: core colours it (#fff, or #000 when is-light) and its inner container inherits. */
.wp-block-cover:not([class*="is-style-section-"], .has-text-color) {
	color: var(--sp-cover-text);
}

:where(.wp-block-cover:not([class*="is-style-section-"]) > .wp-block-cover__inner-container) {
	--sp-bg: var(--sp-under);
	--sp-fg: var(--sp-cover-text);
	--sp-muted: var(--sp-fg);
	--sp-line: var(--sp-fg);
	--sp-soft: var(--sp-under);
	--sp-card: var(--sp-under);
	--sp-accent: var(--sp-fg);
	--sp-on-accent: var(--sp-under);
	--sp-accent-hover: var(--sp-fg);
	--sp-focus: var(--sp-fg);
	--sp-field: var(--sp-fg);
	--sp-mark: var(--sp-fg);
	--sp-highlight: var(--sp-under);
	color: var(--sp-fg);
}

/* A block with its own palette background and no text colour takes the text colour of that ground. Covers
   buttons (whose rule paints --sp-on-accent, which the ground re-points to the background itself) and headings
   (theme.json gives h1–h6 color:inherit, which beats the zero-specificity ground rules). */
:root .has-background:not(.has-text-color),
:root .has-background:not(.has-text-color):hover,
:root .has-background:not(.has-text-color):focus {
	color: var(--sp-fg);
}

:root .wp-block-button__link.has-background:not(.has-border-color) {
	border-color: transparent;
}

/* Soft fills (striped tables, solid pullquotes, the current submenu item) sit a step closer to the
   text colour, so muted text on them could drop under 4.5:1 (Wash, Brand). Secondary text on a soft
   fill uses the full text colour instead (tools/contrast-looks.mjs checks this for every Look). */
:where(.wp-block-table.is-style-stripes tbody tr:nth-child(odd), .wp-block-pullquote.is-style-solid-color:not(.has-background), pre) {
	--sp-muted: var(--sp-fg);
}

/* On Brand (and other saturated, owner-picked) grounds a lighter "other ground" would push
   secondary text under 4.5:1, so the boxed card keeps the section ground and is drawn by its
   hairline instead (same shape, same padding). */
:where(.is-style-section-brand, .has-primary-background-color, .has-secondary-background-color, .has-muted-background-color, .has-on-primary-background-color, .has-on-secondary-background-color) :is(.wp-block-group, .wp-block-column).is-style-card {
	--sp-bg: inherit;
	--sp-line: inherit;
	--sp-soft: inherit;
	background-color: transparent;
	border-color: var(--sp-line);
	box-shadow: none;
}

/* Media inset bleeds to the card edges; top radii follow the nested-radius rule (DESIGN §6.1). */
.is-style-card > .wp-block-image:first-child:not([class*="is-style-"]):not(.is-resized) {
	margin-block-start: calc(-1 * var(--sp-card-pad));
	margin-inline: calc(-1 * var(--sp-card-pad));
	margin-block-end: var(--wp--preset--spacing--30);
	max-width: none;
	width: auto;
}

.is-style-card > .wp-block-image:first-child:not([class*="is-style-"]):not(.is-resized) img {
	border-radius: var(--wp--custom--radius--card) var(--wp--custom--radius--card) 0 0;
	width: 100%;
}

/* Equal-height card columns (pricing tiers): buttons pin to the bottom. */
.wp-block-column:is(.is-style-card, .is-style-card-outline) {
	display: flex;
	flex-direction: column;
}

.wp-block-column:is(.is-style-card, .is-style-card-outline) > .wp-block-buttons:last-child {
	margin-block-start: auto;
	padding-block-start: var(--wp--preset--spacing--30);
}

/* Featured pricing card (a `card` among `card-outline` siblings) comes first on mobile. */
@media (max-width: 781px) {
	.wp-block-columns:has(> .wp-block-column.is-style-card-outline) > .wp-block-column.is-style-card {
		order: -1;
	}
}

/* =========================================================================================
   04 Base + typography (DESIGN §4.4)
   ========================================================================================= */

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

body {
	-webkit-font-smoothing: antialiased;
	-moz-osx-font-smoothing: grayscale;
	text-rendering: optimizeLegibility;
	font-optical-sizing: auto;
	/* No horizontal scroll at 360px, ever; clip (unlike hidden) keeps position: sticky working. */
	overflow-x: clip;
}

:where(img, svg, video, canvas) {
	max-width: 100%;
}

:where(img, video) {
	height: auto;
}

:where(p, li, dd, dt, figcaption, blockquote, td) {
	text-wrap: pretty;
	overflow-wrap: break-word;
}

:where(h1, h2, h3, h4, h5, h6) {
	text-wrap: balance;
	font-synthesis: none;
	overflow-wrap: break-word;
}

/* Heading voice. theme.json carries the same values; these zero-specificity rules fill gaps and
   cover editor contexts, and lose to any Global Styles choice. */
:where(h1, h2, h3, h4) {
	font-family: var(--wp--preset--font-family--heading);
	font-weight: var(--wp--custom--heading--font-weight, 400);
	letter-spacing: var(--wp--custom--heading--letter-spacing, 0);
	text-transform: var(--wp--custom--heading--text-transform, none);
	font-kerning: normal;
}

:where(h1) {
	font-size: calc(var(--wp--preset--font-size--xx-large) * var(--sp-scale));
	line-height: var(--sp-heading-lh);
}

:where(h2) {
	font-size: calc(var(--wp--preset--font-size--x-large) * var(--sp-scale));
	line-height: calc(var(--sp-heading-lh) + 0.04);
}

:where(h3) {
	font-size: calc(var(--wp--preset--font-size--large) * var(--sp-scale));
	line-height: calc(var(--sp-heading-lh) + 0.08);
	font-weight: max(var(--wp--custom--heading--font-weight, 400), 400);
}

:where(h4) {
	font-size: calc(var(--wp--custom--type--lead, 1.333rem) * var(--sp-scale));
	line-height: 1.25;
	letter-spacing: calc(var(--wp--custom--heading--letter-spacing, 0em) / 2);
	font-weight: max(var(--wp--custom--heading--font-weight, 400), 400);
}

/* h5/h6 are LABEL voice: body font, tracked capitals (DESIGN §4.4). */
:where(h5, h6) {
	font-family: var(--wp--preset--font-family--body);
	font-weight: 600;
	line-height: 1.3;
	letter-spacing: 0.14em;
	text-transform: uppercase;
}

:where(h5) {
	font-size: var(--wp--preset--font-size--small);
}

:where(h6) {
	font-size: var(--wp--preset--font-size--x-small);
}

/* The breath word: an <em> inside a heading-voice element (DESIGN §1, §4.4). */
:where(h1, h2, h3, h4, .is-style-display, .wp-block-post-title, .sp-price, .sp-stat, .wp-block-site-title) em {
	font-style: italic;
	font-weight: inherit;
	color: var(--sp-accent);
	font-synthesis: none;
}

/* Body links inside headings keep the breath word's colour logic too. */
:where(h1, h2, h3, h4) a em {
	color: var(--sp-accent);
}

/* Numerals: times, prices, dates, hours (DESIGN §4.4). */
:where(time, .sp-price, .sp-stat, .sp-date, .wp-block-post-date, .is-style-hours, .sp-nums) {
	font-variant-numeric: lining-nums tabular-nums;
}

/* Lead paragraph utility. */
:where(.sp-lead) {
	font-size: var(--wp--custom--type--lead, 1.333rem);
	line-height: 1.5;
	text-wrap: pretty;
}

/* Lead text is a statement; keep it to a readable measure when it stands alone. */
:where(.sp-lead.has-text-align-center) {
	margin-inline: auto;
	max-width: 40rem;
}

/* Lists. */
:where(ul, ol) {
	padding-inline-start: 1.25em;
}

:where(li)::marker {
	color: var(--sp-muted);
}

:where(ol > li)::marker {
	font-variant-numeric: lining-nums tabular-nums;
}

/* Prose rhythm inside post content (DESIGN §6.3): paragraphs spacing-30, headings spacing-60
   above and spacing-30 below. (0,1,1) beats core's flow-layout block gap of (0,1,0). */
:root :where(.wp-block-post-content, .entry-content) > :is(p, ul, ol) {
	margin-block-start: var(--wp--preset--spacing--30);
}

:root :where(.wp-block-post-content, .entry-content) > :is(h2, h3, h4) {
	margin-block-start: var(--wp--preset--spacing--60);
	margin-block-end: 0;
}

:root :where(.wp-block-post-content, .entry-content) > :is(h2, h3, h4) + * {
	margin-block-start: var(--wp--preset--spacing--30);
}

:root :where(.wp-block-post-content, .entry-content) > :first-child {
	margin-block-start: 0;
}

/* Core drop cap → heading voice, three lines, accent (DESIGN §9.2). `:root` + two classes beat
   core's rule in paragraph/style.css regardless of print order. Fallback: a float sized so the cap
   height spans three body lines; where `initial-letter` exists the browser fits it exactly. */
:root .has-drop-cap:not(:focus)::first-letter {
	float: left;
	float: inline-start;
	font-family: var(--wp--preset--font-family--heading);
	font-weight: var(--wp--custom--heading--font-weight, 400);
	font-style: normal;
	font-size: calc((var(--wp--custom--body--line-height, 1.65) * 2 + 0.7) * 1em / 0.72);
	line-height: 0.78;
	margin-block: 0.08em 0;
	margin-inline: 0 0.1em;
	color: var(--sp-accent);
	text-transform: var(--wp--custom--heading--text-transform, none);
}

@supports (initial-letter: 3) or (-webkit-initial-letter: 3) {
	:root .has-drop-cap:not(:focus)::first-letter {
		float: none;
		-webkit-initial-letter: 3;
		initial-letter: 3;
		font-size: inherit;
		line-height: inherit;
		margin: 0;
		margin-inline-end: 0.12em;
	}
}

/* Small print, code and preformatted text. */
:where(small) {
	font-size: var(--wp--preset--font-size--small);
}

:where(code, kbd, samp) {
	font-family: monospace, monospace;
	font-size: 0.9em;
	padding: 0.1em 0.35em;
	border-radius: var(--wp--custom--radius--xs);
	background-color: var(--sp-soft);
	color: var(--sp-fg);
}

:where(pre) {
	overflow-x: auto;
	padding: var(--wp--preset--spacing--30);
	border: var(--wp--custom--border--width, 1px) solid var(--sp-line);
	border-radius: var(--wp--custom--radius--sm);
	background-color: var(--sp-soft);
	color: var(--sp-fg);
	font-size: var(--wp--preset--font-size--small);
	line-height: 1.6;
	tab-size: 4;
}

:where(pre) code {
	padding: 0;
	background: none;
}

:where(abbr[title]) {
	text-decoration: underline dotted;
	text-decoration-color: var(--sp-muted);
	cursor: help;
}

:where(mark) {
	background-color: var(--sp-highlight);
	color: var(--sp-fg);
	padding-inline: 0.15em;
}

:where(hr:not(.wp-block-separator)) {
	border: 0;
	border-block-start: var(--wp--custom--border--width, 1px) solid var(--sp-line);
}

/* Verse and preformatted blocks keep the body measure. */
:where(.wp-block-verse) {
	font-family: var(--wp--preset--font-family--heading);
	font-size: var(--wp--custom--type--lead, 1.333rem);
	line-height: 1.6;
	background: none;
	border: 0;
	padding: 0;
	white-space: pre-wrap;
}

/* =========================================================================================
   05 Links, focus, skip link, selection (DESIGN §7.15)
   ========================================================================================= */

:where(a:not(.wp-element-button)) {
	color: var(--sp-fg);
	text-decoration-line: underline;
}

/* Decoration longhands at (0,1,1) so a theme.json `textDecoration: underline` shorthand at
   (0,1,0) cannot reset the accent underline colour. Whether a link is underlined at all stays
   with theme.json (elements.link, and `none` for menus, titles, meta…). */
:root a:where(:not(.wp-element-button)) {
	text-decoration-color: var(--sp-accent);
	text-decoration-thickness: 1px;
	text-underline-offset: 0.22em;
	text-decoration-skip-ink: auto;
	transition:
		text-decoration-thickness var(--sp-fast) var(--sp-ease),
		text-decoration-color var(--sp-fast) var(--sp-ease),
		color var(--sp-fast) var(--sp-ease);
}

:root a:where(:not(.wp-element-button)):hover {
	text-decoration-thickness: 2px;
	text-decoration-color: var(--sp-accent);
}

/* Menus, site titles and post-title links are not prose: no resting underline. */
.wp-block-navigation a:where(:not(.wp-element-button)),
.wp-block-site-title a,
.wp-block-post-title a,
.wp-block-site-logo a {
	text-decoration-line: none;
}

/* Focus ring for every interactive element. The outline follows border-radius natively. */
:where(a, button, input, select, textarea, summary, [tabindex], [contenteditable="true"]):focus-visible {
	outline: 2px solid var(--sp-focus);
	outline-offset: 3px;
}

:where(.wp-block-image a, .wp-block-post-featured-image a, .sp-media a):focus-visible {
	outline-offset: 4px;
}

/* A control with its own palette background re-points the roles to that background, so its ring is drawn
   inside it in its own text colour (an outside ring would take the button's colour onto the parent ground). */
:where(a, button, summary).has-background:focus-visible {
	outline-color: var(--sp-fg);
	outline-offset: -5px;
}

/* Skip link: restyled as an Ink chip by inc/setup.php (inline on core's skip-link handle). */

::selection {
	background-color: color-mix(in srgb, var(--wp--preset--color--secondary) 45%, var(--wp--preset--color--base));
	color: var(--wp--preset--color--contrast);
}

/* =========================================================================================
   06 Eyebrow + the Stillpoint marker (DESIGN §7.5)
   `is-style-eyebrow` is the paragraph style; `sp-eyebrow` is the same voice for any element
   (e.g. footer h2 list headings, post terms). (0,1,1) beats theme.json heading elements.
   ========================================================================================= */

:is(p, h1, h2, h3, h4, h5, h6, div, span).is-style-eyebrow,
:is(p, h1, h2, h3, h4, h5, h6, div, span, ul).sp-eyebrow {
	font-family: var(--wp--preset--font-family--body);
	font-size: var(--wp--custom--eyebrow--font-size, var(--wp--preset--font-size--x-small));
	font-weight: var(--wp--custom--eyebrow--font-weight, 500);
	font-style: normal;
	letter-spacing: var(--wp--custom--eyebrow--letter-spacing, 0.16em);
	text-transform: var(--wp--custom--eyebrow--text-transform, uppercase);
	line-height: 1.5;
	color: var(--sp-muted);
	margin-block-end: var(--wp--preset--spacing--20);
	text-wrap: balance;
}

:is(p, h1, h2, h3, h4, h5, h6, div, span).is-style-eyebrow::before,
:is(p, h1, h2, h3, h4, h5, h6, div, span, ul).sp-eyebrow:not(.wp-block-post-terms)::before {
	content: "";
	display: inline-block;
	inline-size: 0.5em;
	block-size: 0.5em;
	border-radius: var(--wp--custom--radius--marker, 50%);
	background-color: var(--sp-mark);
	vertical-align: 0.1em;
	margin-inline-end: 0.75em;
	flex: none;
}

/* Numbered variant: "01 — Practice" written as text (DESIGN §7.5). */
:is(p, h1, h2, h3, h4, h5, h6, div, span).is-style-eyebrow.sp-eyebrow-numbered,
.sp-eyebrow.sp-eyebrow-numbered {
	font-variant-numeric: lining-nums tabular-nums;
}

.is-style-eyebrow.sp-eyebrow-numbered::before,
.sp-eyebrow.sp-eyebrow-numbered::before {
	content: none;
}

/* The heading after an eyebrow sits right under it. */
:is(.is-style-eyebrow, .sp-eyebrow) + :is(h1, h2, h3, h4, h5, h6, .wp-block-heading, .wp-block-post-title) {
	margin-block-start: 0;
}

:is(.is-style-eyebrow, .sp-eyebrow) a {
	color: inherit;
	text-decoration-line: none;
}

:is(.is-style-eyebrow, .sp-eyebrow) a:hover,
:is(.is-style-eyebrow, .sp-eyebrow) a:focus-visible {
	text-decoration-line: underline;
	color: var(--sp-fg);
}

/* =========================================================================================
   07 Buttons (DESIGN §7.4)
   Colours, type and radius come from theme.json elements.button (role-based); the rules below
   are zero-specificity fallbacks for those and enforce the shared box. Variants are two-class
   selectors so they beat the global element-button rule at (0,1,0).
   ========================================================================================= */

/* Everything that should look like a button. */
:where(
	.wp-element-button,
	.wp-block-button__link,
	.wpcf7-submit,
	.wpforms-submit,
	.gform_button,
	.mc4wp-form input[type="submit"],
	#mc-embedded-subscribe,
	.sp-button
) {
	font-family: var(--wp--preset--font-family--body);
	font-size: var(--wp--preset--font-size--small);
	font-weight: var(--wp--custom--button--font-weight, 500);
	letter-spacing: var(--wp--custom--button--letter-spacing, 0.1em);
	text-transform: var(--wp--custom--button--text-transform, uppercase);
	padding-block: var(--wp--custom--button--padding-block, 0.95em);
	padding-inline: var(--wp--custom--button--padding-inline, 1.9em);
	border-radius: var(--wp--custom--radius--button);
	background-color: var(--sp-accent);
	color: var(--sp-on-accent);
	border-color: var(--sp-accent);
}

/* Core dims the File block's Download button to 85% on hover/focus and paints it white when visited; both cost
   contrast (3.2–4.4:1). Keep it opaque and in the ground's button colours. */
.wp-block-file .wp-block-file__button:is(:hover, :focus, :active, :visited) {
	opacity: 1;
}

.wp-block-file .wp-block-file__button:visited:not(.has-text-color) {
	color: var(--sp-on-accent);
}

:where(.wp-element-button, .wp-block-button__link, .wpcf7-submit, .wpforms-submit, .gform_button, .sp-button):hover {
	background-color: var(--sp-accent-hover);
	border-color: var(--sp-accent-hover);
	color: var(--sp-on-accent);
}

/* The shared box (structural; Global Styles does not expose these). */
:root :is(.wp-element-button, .wp-block-button__link, .sp-button) {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 0.6em;
	min-height: 3rem;
	border-style: solid;
	border-width: var(--wp--custom--border--width, 1px);
	line-height: 1.2;
	text-align: center;
	text-decoration: none;
	cursor: pointer;
	box-sizing: border-box;
	transition:
		background-color var(--sp-fast) var(--sp-ease),
		border-color var(--sp-fast) var(--sp-ease),
		color var(--sp-fast) var(--sp-ease),
		text-decoration-thickness var(--sp-fast) var(--sp-ease),
		transform var(--sp-fast) var(--sp-ease);
}

/* Plugin submit inputs/buttons (replaced elements cannot be flex). */
:root :is(.wpcf7-submit, .wpforms-submit, .gform_button, .mc4wp-form input[type="submit"], input[type="submit"].wp-element-button) {
	min-height: 3rem;
	border-style: solid;
	border-width: var(--wp--custom--border--width, 1px);
	line-height: 1.2;
	cursor: pointer;
	-webkit-appearance: none;
	appearance: none;
	transition:
		background-color var(--sp-fast) var(--sp-ease),
		border-color var(--sp-fast) var(--sp-ease),
		color var(--sp-fast) var(--sp-ease);
}

/* Buttons never break inside a word; full-width buttons drop the wide inline padding. */
:root :is(.wp-element-button, .wp-block-button__link, .sp-button) {
	word-break: normal;
	overflow-wrap: break-word;
}

:root .wp-block-buttons > .wp-block-button:is(.has-custom-width, .wp-block-button__width-100):not(.is-style-text-arrow) > .wp-block-button__link:not(.has-arrow) {
	padding-inline: 1em;
}

/* Core sets height:100% on the link; a flex row of buttons should keep their own height. */
.wp-block-buttons > .wp-block-button > .wp-block-button__link {
	height: auto;
}

:root :is(.wp-element-button, .wp-block-button__link, .sp-button):active {
	transform: translateY(1px);
}

/* Outline: fg box, inverts on hover. */
:root :is(.wp-block-button.is-style-outline > .wp-block-button__link, .wp-element-button.is-style-outline, .sp-button--outline) {
	background-color: transparent;
	color: var(--sp-fg);
	border-color: var(--sp-fg);
}

:root :is(.wp-block-button.is-style-outline > .wp-block-button__link, .wp-element-button.is-style-outline, .sp-button--outline):not(.has-background):hover {
	background-color: var(--sp-fg);
	color: var(--sp-bg);
	border-color: var(--sp-fg);
}

/* Owner-picked colours on an outline button win (core's has-* classes). */
:root .wp-block-button.is-style-outline > .wp-block-button__link.has-text-color:not(:hover) {
	border-color: currentColor;
}

/* Soft: a tint chip of a button. */
:root :is(.wp-block-button.is-style-soft > .wp-block-button__link, .sp-button--soft) {
	background-color: var(--sp-soft);
	color: var(--sp-fg);
	border-color: transparent;
}

:root :is(.wp-block-button.is-style-soft > .wp-block-button__link, .sp-button--soft):hover {
	background-color: color-mix(in srgb, var(--sp-bg) 50%, var(--sp-soft));
	color: var(--sp-fg);
	border-color: transparent;
}

/* Text-arrow: no box, label voice, accent underline, trailing arrow. */
:root :is(.wp-block-button.is-style-text-arrow > .wp-block-button__link, .sp-button--text-arrow) {
	background-color: transparent;
	color: var(--sp-fg);
	border-color: transparent;
	padding-inline: 0 1.5em;
	padding-block: 0.6em;
	min-height: 2.75rem;
	border-radius: 0;
	text-decoration-line: underline;
	text-decoration-color: var(--sp-accent);
	text-decoration-thickness: 1px;
	text-underline-offset: 0.4em;
	position: relative;
}

:root :is(.wp-block-button.is-style-text-arrow > .wp-block-button__link, .sp-button--text-arrow):hover {
	background-color: transparent;
	color: var(--sp-fg);
	border-color: transparent;
	text-decoration-thickness: 2px;
}

:root :is(.wp-block-button.is-style-text-arrow > .wp-block-button__link, .sp-button--text-arrow):active {
	transform: none;
}

/* Text-arrow buttons hug their label (core stretches links inside a buttons row). */
.wp-block-buttons > .wp-block-button.is-style-text-arrow:not(.has-custom-width) > .wp-block-button__link {
	width: auto;
}

/* The trailing arrow: absolutely placed so the underline never runs under it. */
:root :is(
	.wp-block-button.is-style-text-arrow > .wp-block-button__link,
	.wp-block-button.has-arrow > .wp-block-button__link,
	.wp-block-button__link.has-arrow,
	.sp-button--text-arrow,
	.sp-button.has-arrow
)::after {
	content: "→";
	content: "→" / "";
	position: absolute;
	inset-inline-end: 0;
	inset-block-start: 50%;
	inline-size: 1em;
	text-align: center;
	translate: 0 -50%;
	font-family: var(--wp--preset--font-family--body);
	letter-spacing: 0;
	text-transform: none;
	text-decoration: none;
	line-height: 1;
	transition: transform var(--sp-fast) var(--sp-ease);
}

:root :is(.wp-block-button.has-arrow > .wp-block-button__link, .wp-block-button__link.has-arrow, .sp-button.has-arrow) {
	position: relative;
	padding-inline-end: calc(var(--wp--custom--button--padding-inline, 1.9em) + 1.6em);
}

:root :is(.wp-block-button.has-arrow > .wp-block-button__link, .wp-block-button__link.has-arrow, .sp-button.has-arrow)::after {
	inset-inline-end: var(--wp--custom--button--padding-inline, 1.9em);
}

:root :is(.wp-block-button.is-style-text-arrow.has-arrow > .wp-block-button__link)::after {
	inset-inline-end: 0;
}

:root :is(.wp-block-button.is-style-text-arrow.has-arrow > .wp-block-button__link) {
	padding-inline-end: 1.5em;
}

:root :is(
	.wp-block-button.has-arrow > .wp-block-button__link,
	.wp-block-button__link.has-arrow,
	.sp-button.has-arrow
):hover::after {
	transform: translateX(3px);
}

:root :is(.wp-block-button.is-style-text-arrow > .wp-block-button__link, .sp-button--text-arrow):hover::after {
	transform: translateX(4px);
}

[dir="rtl"] :is(.wp-block-button.is-style-text-arrow, .wp-block-button.has-arrow) > .wp-block-button__link::after,
[dir="rtl"] :is(.sp-button--text-arrow, .sp-button.has-arrow)::after {
	content: "←";
	content: "←" / "";
}

[dir="rtl"] :is(.wp-block-button.is-style-text-arrow, .wp-block-button.has-arrow) > .wp-block-button__link:hover::after {
	transform: translateX(-3px);
}

/* Small size (header Book button, schedule rows). */
:root :is(
	.wp-block-button.sp-button-sm > .wp-block-button__link,
	.wp-block-button__link.sp-button-sm,
	.wp-block-buttons.is-small .wp-block-button__link,
	.sp-button.sp-button-sm
) {
	min-height: 2.75rem;
	padding-block: 0.7em;
	font-size: var(--wp--preset--font-size--x-small);
}

:root :is(
	.wp-block-button.sp-button-sm:not(.is-style-text-arrow) > .wp-block-button__link,
	.wp-block-button__link.sp-button-sm:not(.is-style-text-arrow),
	.wp-block-buttons.is-small .wp-block-button:not(.is-style-text-arrow) .wp-block-button__link,
	.sp-button.sp-button-sm:not(.sp-button--text-arrow)
) {
	padding-inline: 1.4em;
}

/* Disabled (a real `disabled` / `aria-disabled="true"` state only; WCAG exempts inactive controls
   from contrast, a merely styled link is not exempt). */
:root :is(.wp-element-button, .wp-block-button__link, .sp-button):is([disabled], [aria-disabled="true"]) {
	opacity: 0.45;
	pointer-events: none;
	cursor: not-allowed;
}

/* A row of buttons wraps gracefully and keeps a calm gap. */
:where(.wp-block-buttons) {
	row-gap: var(--wp--preset--spacing--20);
}

/* =========================================================================================
   08 Header + navigation (DESIGN §7.1–7.2)
   ========================================================================================= */

/* Announcement bar. */
.sp-announcement {
	display: flex;
	align-items: center;
	justify-content: center;
	min-height: 2.5rem;
	padding-block: var(--wp--preset--spacing--10);
	text-align: center;
	font-family: var(--wp--preset--font-family--body);
	font-size: var(--wp--preset--font-size--x-small);
	font-weight: 500;
	letter-spacing: 0.12em;
	text-transform: uppercase;
	line-height: 1.4;
}

.sp-announcement :where(p) {
	margin: 0;
}

.sp-announcement a {
	color: inherit;
	text-underline-offset: 0.3em;
}

/* Masthead. */
.sp-header {
	border-block-end: var(--wp--custom--border--width, 1px) solid var(--sp-line);
	transition:
		padding var(--sp-dur) var(--sp-ease),
		box-shadow var(--sp-dur) var(--sp-ease),
		background-color var(--sp-dur) var(--sp-ease);
}

.sp-header :where(.wp-block-site-logo) img {
	max-height: 2.5rem;
	width: auto;
}

/* Site title in the masthead: heading voice at large × scale × 0.8 (DESIGN §7.1). */
:where(.sp-header) :where(.wp-block-site-title) {
	font-family: var(--wp--preset--font-family--heading);
	font-size: calc(var(--wp--preset--font-size--large) * var(--sp-scale) * 0.8);
	font-weight: var(--wp--custom--heading--font-weight, 400);
	letter-spacing: 0.01em;
	text-transform: var(--wp--custom--heading--text-transform, none);
	line-height: 1.1;
	margin: 0;
}

/* Centred "flag" masthead (header-centered part). */
:where(.sp-header) :where(.wp-block-site-title.has-text-align-center) {
	font-size: calc(var(--wp--preset--font-size--x-large) * var(--sp-scale));
}

.sp-header .wp-block-site-title a {
	color: var(--sp-fg);
	text-decoration-line: none;
}

/* Sticky header (body.sp-header-sticky). The template-part wrapper is what sticks, because its
   containing block is the page; `.sp-header` inside it only carries the visuals. */
.sp-header-sticky :is(.wp-site-blocks > header.wp-block-template-part, header.wp-block-template-part:has(.sp-header)) {
	position: sticky;
	inset-block-start: var(--wp-admin--admin-bar--height, 0px);
	z-index: 50;
	transition: box-shadow var(--sp-dur) var(--sp-ease);
}

/* The frosted ground lives on a pseudo-element: a backdrop-filter on the header itself would make
   it the containing block of the fixed mobile overlay and trap the menu inside the header. */
.sp-header-sticky :is(.wp-site-blocks > header.wp-block-template-part, header.wp-block-template-part:has(.sp-header))::before {
	content: "";
	position: absolute;
	inset: 0;
	z-index: -1;
	background-color: color-mix(in srgb, var(--sp-bg) 92%, transparent);
	-webkit-backdrop-filter: blur(10px);
	backdrop-filter: blur(10px);
	pointer-events: none;
}

@media (max-width: 600px) {
	/* The admin bar scrolls away on small screens. */
	.sp-header-sticky :is(.wp-site-blocks > header.wp-block-template-part, header.wp-block-template-part:has(.sp-header)) {
		inset-block-start: 0;
	}
}

.sp-header-sticky header.wp-block-template-part.is-scrolled {
	box-shadow: var(--wp--custom--shadow--raised, none);
}

/* The masthead group(s) inside the sticky header lose the opaque page ground so blur shows. */
.sp-header-sticky header.wp-block-template-part > .sp-header:not([class*="background-color"]):not([class*="is-style-section"]) {
	background-color: transparent;
}

/* Scrolled: tighter masthead. Inline block padding is overridden on purpose here. */
.sp-header.is-scrolled:not(.sp-header--centered) {
	padding-block: var(--wp--preset--spacing--20) !important;
}

/* The centred masthead keeps its nav row intact and only tightens above the title. */
.sp-header.sp-header--centered.is-scrolled {
	padding-block-start: var(--wp--preset--spacing--20) !important;
}

/* Anchor jumps clear the sticky header (theme.js measures the real height as --sp-header-h). */
html:has(> body.sp-header-sticky) {
	scroll-padding-block-start: calc(var(--sp-header-h, var(--wp--custom--header--height, 4.75rem)) + var(--wp--preset--spacing--30));
}

/* Sticky aside utility (`sp-sticky` on a group/column): sticks below the header on desktop —
   teacher portrait, pricing FAQ heading, event details card, About signature column. */
@media (min-width: 960px) {
	.sp-sticky {
		position: sticky;
		inset-block-start: var(--wp--preset--spacing--40);
		align-self: flex-start;
	}

	.sp-header-sticky .sp-sticky {
		inset-block-start: calc(var(--wp-admin--admin-bar--height, 0px) + var(--sp-header-h, var(--wp--custom--header--height, 4.75rem)) + var(--wp--preset--spacing--40));
	}

	/* A sticky column must be shorter than its row to travel; a sticky child sticks inside its
	   (stretched) column. */
	.wp-block-columns > .wp-block-column.sp-sticky {
		align-self: flex-start;
	}
}

/* ---- Desktop navigation items (label voice) ---- */
:is(.sp-nav, .sp-header .wp-block-navigation) .wp-block-navigation__container:not(.is-menu-open *) > .wp-block-navigation-item > .wp-block-navigation-item__content {
	position: relative;
	font-family: var(--wp--preset--font-family--body);
	font-size: var(--wp--preset--font-size--small);
	font-weight: 500;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	line-height: 1.3;
	color: var(--sp-muted);
	padding-block: 0.6em;
	text-decoration: none;
	transition: color var(--sp-fast) var(--sp-ease);
}

:is(.sp-nav, .sp-header .wp-block-navigation) .wp-block-navigation__container:not(.is-menu-open *) > .wp-block-navigation-item > .wp-block-navigation-item__content:hover,
:is(.sp-nav, .sp-header .wp-block-navigation) .wp-block-navigation__container:not(.is-menu-open *) > .wp-block-navigation-item:focus-within > .wp-block-navigation-item__content {
	color: var(--sp-fg);
}

/* Hover: a 1px accent underline grows from the centre (no extra element needed). */
:is(.sp-nav, .sp-header .wp-block-navigation) .wp-block-navigation__container:not(.is-menu-open *) > .wp-block-navigation-item > .wp-block-navigation-item__content .wp-block-navigation-item__label {
	background-image: linear-gradient(var(--sp-accent), var(--sp-accent));
	background-position: 50% 100%;
	background-repeat: no-repeat;
	background-size: 0 1px;
	padding-block-end: 0.2em;
	transition: background-size var(--sp-fast) var(--sp-ease);
}

:is(.sp-nav, .sp-header .wp-block-navigation) .wp-block-navigation__container:not(.is-menu-open *) > .wp-block-navigation-item > .wp-block-navigation-item__content:hover .wp-block-navigation-item__label {
	background-size: 100% 1px;
}

/* Current item: fg colour + an accent marker centred under the label. */
:is(.sp-nav, .sp-header .wp-block-navigation) .wp-block-navigation__container:not(.is-menu-open *) > .wp-block-navigation-item:is(.current-menu-item, .current-menu-ancestor) > .wp-block-navigation-item__content,
:is(.sp-nav, .sp-header .wp-block-navigation) .wp-block-navigation__container:not(.is-menu-open *) > .wp-block-navigation-item > .wp-block-navigation-item__content[aria-current] {
	color: var(--sp-fg);
}

:is(.sp-nav, .sp-header .wp-block-navigation) .wp-block-navigation__container:not(.is-menu-open *) > .wp-block-navigation-item:is(.current-menu-item, .current-menu-ancestor) > .wp-block-navigation-item__content::after,
:is(.sp-nav, .sp-header .wp-block-navigation) .wp-block-navigation__container:not(.is-menu-open *) > .wp-block-navigation-item > .wp-block-navigation-item__content[aria-current]::after {
	content: "";
	position: absolute;
	inset-inline-start: 50%;
	inset-block-start: calc(100% - 0.1em);
	inline-size: 0.36em;
	block-size: 0.36em;
	translate: -50% 0;
	border-radius: var(--wp--custom--radius--marker, 50%);
	background-color: var(--sp-accent);
}

/* Submenu chevrons stay quiet. */
:is(.sp-nav, .sp-header .wp-block-navigation) .wp-block-navigation__submenu-icon {
	color: var(--sp-muted);
}

/* ---- Submenus (panels) ---- */
/* Floating panels only: always-open submenus (vertical menus, overlays) stay flat lists. */
:root .wp-block-navigation:not(.has-background) .has-child:not(.open-always) > .wp-block-navigation__submenu-container:not(.is-menu-open *, .sp-nav-overlay *),
:root .wp-block-navigation .has-child:not(.open-always) > .wp-block-navigation__submenu-container:not(.is-menu-open *, .sp-nav-overlay *) {
	background-color: var(--sp-bg);
	color: var(--sp-fg);
	border: var(--wp--custom--border--width, 1px) solid var(--sp-line);
	border-radius: min(var(--wp--custom--radius--md), 1rem);
	box-shadow: var(--wp--custom--shadow--raised, none);
	padding: var(--wp--preset--spacing--20);
	min-width: 14rem;
}

:root .wp-block-navigation:not(.has-text-color) .has-child:not(.open-always) > .wp-block-navigation__submenu-container:not(.is-menu-open *, .sp-nav-overlay *) {
	color: var(--sp-fg);
}

:root .wp-block-navigation .has-child .wp-block-navigation__submenu-container:not(.is-menu-open *, .sp-nav-overlay *) > .wp-block-navigation-item > .wp-block-navigation-item__content {
	font-family: var(--wp--preset--font-family--body);
	font-size: var(--wp--preset--font-size--small);
	font-weight: 400;
	letter-spacing: 0;
	text-transform: none;
	padding: 0.5em 0.75em;
	border-radius: min(var(--wp--custom--radius--sm), 0.75rem);
	color: var(--sp-fg);
	text-decoration: none;
	transition: background-color var(--sp-fast) var(--sp-ease);
}

:root .wp-block-navigation .has-child .wp-block-navigation__submenu-container:not(.is-menu-open *, .sp-nav-overlay *) > .wp-block-navigation-item > .wp-block-navigation-item__content:hover,
:root .wp-block-navigation .has-child .wp-block-navigation__submenu-container:not(.is-menu-open *, .sp-nav-overlay *) > .wp-block-navigation-item > .wp-block-navigation-item__content[aria-current] {
	background-color: var(--sp-soft);
}

/* ---- Mobile: collapse to the overlay below 960px, not core's 600px (DESIGN §7.2) ---- */
@media (min-width: 600px) and (max-width: 959px) {
	:is(.sp-header, .sp-nav) .wp-block-navigation__responsive-container-open:not(.always-shown) {
		display: flex;
	}

	:is(.sp-header, .sp-nav) .wp-block-navigation__responsive-container:not(.hidden-by-default):not(.is-menu-open) {
		display: none;
	}
}

/* Toggle: the word "Menu" (or the icon) in label voice, 44px target. */
:root :is(.sp-header, .sp-nav) .wp-block-navigation__responsive-container-open,
:root :is(.sp-header, .sp-nav, .sp-nav-overlay) .wp-block-navigation__responsive-container-close,
:root .wp-block-navigation-overlay-close {
	align-items: center;
	justify-content: center;
	gap: 0.5em;
	min-width: 2.75rem;
	min-height: 2.75rem;
	padding-inline: 0.25em;
	color: var(--sp-fg);
	font-family: var(--wp--preset--font-family--body);
	font-size: var(--wp--preset--font-size--small);
	font-weight: 500;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	line-height: 1;
	border-radius: var(--wp--custom--radius--xs);
}

:root :is(.sp-header, .sp-nav, .sp-nav-overlay) .wp-block-navigation__responsive-container-close {
	display: flex;
}

/* Header row on small screens: compact Book button (never wrapping), hidden below 360px.
   The overlay part renders inside the header, so its own CTA is excluded. */
@media (max-width: 959px) {
	.sp-header .wp-block-buttons:not(.sp-nav-overlay *) .wp-block-button__link {
		min-height: 2.75rem;
		padding-block: 0.7em;
		padding-inline: 1.1em;
		font-size: var(--wp--preset--font-size--x-small);
		letter-spacing: 0.08em;
		white-space: nowrap;
	}

	.sp-header :where(.sp-header__actions) {
		gap: var(--wp--preset--spacing--20);
	}
}

@media (max-width: 599px) {
	:where(.sp-header) :where(.wp-block-site-title:not(.has-text-align-center)) {
		font-size: calc(var(--wp--preset--font-size--large) * var(--sp-scale) * 0.7);
	}
}

@media (max-width: 359px) {
	.sp-header .wp-block-buttons:not(.sp-nav-overlay *) {
		display: none;
	}
}

/* ---- Overlay: core's default responsive container (no overlay part, or WP < 7.0) ---- */
:root .wp-block-navigation__responsive-container.is-menu-open:not(.disable-default-overlay),
:root .wp-block-navigation:not(.has-background) .wp-block-navigation__responsive-container.is-menu-open:not(.disable-default-overlay) {
	background-color: var(--sp-bg);
	color: var(--sp-fg);
	padding: var(--wp--preset--spacing--40);
}

:root .wp-block-navigation:not(.has-text-color) .wp-block-navigation__responsive-container.is-menu-open:not(.disable-default-overlay) {
	color: var(--sp-fg);
}

:root .wp-block-navigation__responsive-container.is-menu-open:not(.disable-default-overlay) .wp-block-navigation__responsive-container-close {
	inset-block-start: 0;
	inset-inline-end: 0;
}

:root .wp-block-navigation__responsive-container.is-menu-open:not(.disable-default-overlay) .wp-block-navigation__responsive-container-content {
	padding-block-start: calc(2.75rem + var(--wp--preset--spacing--30));
	align-items: stretch;
}

/* Overlay items (default overlay AND our navigation-overlay part share the same voice). */
:is(
	.wp-block-navigation__responsive-container.is-menu-open:not(.disable-default-overlay) .wp-block-navigation__responsive-container-content,
	.sp-nav-overlay
) .wp-block-navigation__container {
	counter-reset: sp-nav;
	width: 100%;
	gap: 0;
	align-items: stretch;
}

:root :is(
	.wp-block-navigation__responsive-container.is-menu-open:not(.disable-default-overlay) .wp-block-navigation__responsive-container-content,
	.sp-nav-overlay
) .wp-block-navigation__container > .wp-block-navigation-item {
	flex-direction: column;
	align-items: stretch;
	width: 100%;
	border-block-end: var(--wp--custom--border--width, 1px) solid var(--sp-line);
}

:root :is(
	.wp-block-navigation__responsive-container.is-menu-open:not(.disable-default-overlay) .wp-block-navigation__responsive-container-content,
	.sp-nav-overlay
) .wp-block-navigation__container > .wp-block-navigation-item > .wp-block-navigation-item__content {
	display: flex;
	align-items: baseline;
	gap: 0.9em;
	padding-block: var(--wp--preset--spacing--20);
	padding-inline: 0;
	font-family: var(--wp--preset--font-family--heading);
	font-size: calc(var(--wp--preset--font-size--large) * var(--sp-scale));
	font-weight: var(--wp--custom--heading--font-weight, 400);
	letter-spacing: var(--wp--custom--heading--letter-spacing, 0);
	text-transform: var(--wp--custom--heading--text-transform, none);
	line-height: 1.15;
	color: var(--sp-fg);
	text-decoration: none;
}

:root :is(
	.wp-block-navigation__responsive-container.is-menu-open:not(.disable-default-overlay) .wp-block-navigation__responsive-container-content,
	.sp-nav-overlay
) .wp-block-navigation__container > .wp-block-navigation-item > .wp-block-navigation-item__content::before {
	counter-increment: sp-nav;
	content: counter(sp-nav, decimal-leading-zero);
	content: counter(sp-nav, decimal-leading-zero) / "";
	flex: none;
	min-width: 2em;
	font-family: var(--wp--preset--font-family--body);
	font-size: var(--wp--preset--font-size--x-small);
	font-weight: 500;
	font-style: normal;
	letter-spacing: 0.12em;
	text-transform: uppercase;
	font-variant-numeric: lining-nums tabular-nums;
	color: var(--sp-muted);
	translate: 0 -0.35em;
}

:root :is(
	.wp-block-navigation__responsive-container.is-menu-open:not(.disable-default-overlay) .wp-block-navigation__responsive-container-content,
	.sp-nav-overlay
) .wp-block-navigation__container > .wp-block-navigation-item > .wp-block-navigation-item__content:is(:hover, [aria-current]) .wp-block-navigation-item__label {
	text-decoration-line: underline;
	text-decoration-color: var(--sp-accent);
	text-decoration-thickness: 1px;
	text-underline-offset: 0.18em;
}

/* Overlay submenus: body font, indented, always expanded. */
:root :is(
	.wp-block-navigation__responsive-container.is-menu-open:not(.disable-default-overlay) .wp-block-navigation__responsive-container-content,
	.sp-nav-overlay
) .wp-block-navigation__submenu-container {
	position: static;
	visibility: visible;
	opacity: 1;
	width: auto;
	height: auto;
	overflow: visible;
	min-width: 0;
	border: 0;
	box-shadow: none;
	background: transparent;
	padding-block: 0 var(--wp--preset--spacing--20);
	/* Align with the item labels: counter column (2em of x-small) + gap (0.9em of the item size). */
	padding-inline: calc(2 * var(--wp--preset--font-size--x-small) + 0.9 * var(--wp--preset--font-size--large) * var(--sp-scale)) 0;
	gap: 0;
}

:root :is(
	.wp-block-navigation__responsive-container.is-menu-open:not(.disable-default-overlay) .wp-block-navigation__responsive-container-content,
	.sp-nav-overlay
) .wp-block-navigation__submenu-container .wp-block-navigation-item__content {
	font-family: var(--wp--preset--font-family--body);
	font-size: var(--wp--preset--font-size--medium);
	font-weight: 400;
	letter-spacing: 0;
	text-transform: none;
	padding-block: 0.4em;
	padding-inline: 0;
	color: var(--sp-fg);
	text-decoration: none;
}

:is(.wp-block-navigation__responsive-container.is-menu-open, .sp-nav-overlay) .wp-block-navigation__submenu-icon {
	display: none;
}

/* ---- Our 7.0 overlay part (parts/navigation-overlay.html, `.sp-nav-overlay`) ---- */
:root .wp-block-navigation__responsive-container.disable-default-overlay.is-menu-open {
	background-color: var(--sp-bg);
	color: var(--sp-fg);
}

.sp-nav-overlay {
	min-height: 100dvh;
	padding: var(--wp--preset--spacing--40);
	box-sizing: border-box;
	display: flex;
	flex-direction: column;
	gap: var(--wp--preset--spacing--50);
}

.sp-nav-overlay > * {
	margin-block: 0;
}

.sp-nav-overlay .wp-block-site-title {
	font-family: var(--wp--preset--font-family--heading);
	font-size: calc(var(--wp--preset--font-size--large) * var(--sp-scale) * 0.8);
	font-weight: var(--wp--custom--heading--font-weight, 400);
	text-transform: var(--wp--custom--heading--text-transform, none);
	margin: 0;
}

.sp-nav-overlay .wp-block-site-title a {
	color: var(--sp-fg);
	text-decoration-line: none;
}

.sp-nav-overlay .wp-block-navigation {
	width: 100%;
}

.sp-nav-overlay .wp-block-buttons {
	margin-block-start: auto;
	width: 100%;
}

.sp-nav-overlay .wp-block-buttons > .wp-block-button {
	flex: 1 1 auto;
}

.sp-nav-overlay .wp-block-buttons > .wp-block-button > .wp-block-button__link {
	width: 100%;
}

/* Overlay entrance: fade + a small rise over `duration` (none with reduced motion). */
@media (prefers-reduced-motion: no-preference) {
	:root .wp-block-navigation__responsive-container.is-menu-open {
		animation: sp-overlay-in var(--sp-dur) var(--sp-ease) both;
	}
}

@keyframes sp-overlay-in {
	from {
		opacity: 0;
		transform: translateY(0.5rem);
	}

	to {
		opacity: 1;
		transform: none;
	}
}

/* =========================================================================================
   09 Footer (DESIGN §7.3)
   ========================================================================================= */

.sp-footer {
	overflow: clip;
}

/* Footer links: fg, underline only on hover/focus. */
.sp-footer a:where(:not(.wp-element-button)) {
	color: var(--sp-fg);
	text-decoration-line: none;
}

.sp-footer a:where(:not(.wp-element-button)):is(:hover, :focus-visible) {
	text-decoration-line: underline;
	text-decoration-thickness: 1px;
}

/* Footer menus: plain vertical lists of links in body voice. */
.sp-footer .wp-block-navigation .wp-block-navigation-item__content {
	color: var(--sp-fg);
	padding-block: 0.25em;
}

.sp-footer :is(ul.wp-block-list, .wp-block-navigation__container) {
	list-style: none;
	padding-inline-start: 0;
}

.sp-footer :is(ul.wp-block-list) > li + li {
	margin-block-start: var(--wp--preset--spacing--10);
}

/* Hours lists use tabular figures. */
.sp-footer :is(ul, table, p) {
	font-variant-numeric: lining-nums tabular-nums;
}

/* Ghost wordmark (`p.sp-wordmark`, core/site-title with isLink:false). */
.sp-wordmark,
:root .wp-block-site-title.sp-wordmark {
	display: block;
	font-family: var(--wp--preset--font-family--heading);
	font-size: clamp(4rem, 15vw, 15rem);
	font-weight: var(--wp--custom--heading--font-weight, 400);
	letter-spacing: var(--wp--custom--heading--letter-spacing, 0);
	text-transform: var(--wp--custom--heading--text-transform, none);
	line-height: 0.8;
	color: color-mix(in srgb, var(--sp-fg) 9%, var(--sp-bg));
	white-space: nowrap;
	/* Clip sideways only: tall ascenders (line-height 0.8) must not be cut at the top. */
	overflow-x: clip;
	overflow-y: visible;
	text-overflow: clip;
	margin-block-end: -0.18em;
	max-width: 100%;
	user-select: none;
	pointer-events: none;
}

/* The wordmark is decoration (aria-hidden, WCAG "incidental" text). Painting the glyphs with
   background-clip keeps the ghost colour while telling automated contrast checkers this is not
   running text (they defer it to manual review instead of failing every page). The padding gives
   the clipped background room for ascenders and descenders; translate + margin keep the glyphs
   and the following bottom bar exactly where they were. */
@supports (background-clip: text) or (-webkit-background-clip: text) {
	.sp-wordmark,
	:root .wp-block-site-title.sp-wordmark {
		color: transparent;
		background-color: color-mix(in srgb, var(--sp-fg) 9%, var(--sp-bg));
		-webkit-background-clip: text;
		background-clip: text;
		padding-block: 0.2em 0.25em;
		translate: 0 -0.2em;
		margin-block-end: calc(-0.18em - 0.45em);
	}
}

.sp-wordmark a {
	color: inherit;
	text-decoration: none;
}

/* Bottom bar (`.sp-footer__bar`): label voice, x-small, muted. */
:where(.sp-footer__bar, .sp-footer-bar) {
	font-family: var(--wp--preset--font-family--body);
	font-size: var(--wp--preset--font-size--x-small);
	font-weight: 500;
	letter-spacing: 0.12em;
	text-transform: uppercase;
	color: var(--sp-muted);
}

:where(.sp-footer__bar, .sp-footer-bar) a:where(:not(.wp-element-button)) {
	color: var(--sp-muted);
}

:where(.sp-footer__bar, .sp-footer-bar) a:where(:not(.wp-element-button)):is(:hover, :focus-visible) {
	color: var(--sp-fg);
}

:where(.sp-footer__bar, .sp-footer-bar) :where(p) {
	margin: 0;
}

/* "Back to top" — works without JS (#top), smooth with theme.js. */
:where(.sp-back-to-top, a[href="#top"]) {
	white-space: nowrap;
}

/* =========================================================================================
   10 Tags, status tags, level meter, intensity, chips (DESIGN §7.7)
   Shared with the Stillpoint Studio plugin (it ships the same class names with fallbacks).
   ========================================================================================= */

.sp-tag,
.wp-block-post-terms.is-style-pills a {
	display: inline-flex;
	align-items: center;
	gap: 0.4em;
	min-height: 1.75rem;
	box-sizing: border-box;
	padding: 0.35em 0.85em;
	border: var(--wp--custom--border--width, 1px) solid transparent;
	border-radius: var(--wp--custom--radius--tag, var(--wp--custom--radius--xs));
	background-color: var(--sp-soft);
	color: var(--sp-fg);
	font-family: var(--wp--preset--font-family--body);
	font-size: var(--wp--preset--font-size--x-small);
	font-weight: 500;
	font-style: normal;
	letter-spacing: 0.04em;
	text-transform: none;
	line-height: 1.2;
	text-decoration: none;
	white-space: nowrap;
	vertical-align: middle;
	transition: background-color var(--sp-fast) var(--sp-ease), border-color var(--sp-fast) var(--sp-ease);
}

a.sp-tag,
a.sp-chip,
:root .wp-block-post-terms.is-style-pills a {
	text-decoration-line: none;
}

/* A tag written as its own paragraph/group shrink-wraps instead of spanning the column. */
:is(p, div, span.wp-block-group).sp-tag {
	display: flex;
	width: fit-content;
	margin-block-end: 0;
}

:is(p, div).sp-tag.has-text-align-center {
	margin-inline: auto;
}

a.sp-tag:hover,
.wp-block-post-terms.is-style-pills a:hover {
	background-color: color-mix(in srgb, var(--sp-bg) 50%, var(--sp-soft)) /* hover moves toward the ground: never less contrast than the soft fill */;
	color: var(--sp-fg);
}

/* Status tags: text always states the status; colour is never the only signal. */
.sp-tag--status:is(.sp-tag--few, [data-status="few"]) {
	background-color: var(--sp-soft);
}

.sp-tag--status:is(.sp-tag--waitlist, .sp-tag--full, [data-status="waitlist"], [data-status="full"]) {
	background-color: transparent;
	border-color: var(--sp-fg);
	color: var(--sp-fg);
}

.sp-tag--status:is(.sp-tag--new, .sp-tag--loved, .sp-tag--accent, [data-status="new"], [data-status="loved"]) {
	background-color: var(--sp-accent);
	border-color: var(--sp-accent);
	color: var(--sp-on-accent);
}

.sp-tag--status:is(.sp-tag--cancelled, .sp-tag--ended, [data-status="cancelled"], [data-status="ended"]) {
	background-color: transparent;
	border-color: var(--sp-line);
	color: var(--sp-muted);
}

.is-cancelled :is(.sp-title, [class*="__title"]) {
	text-decoration-line: line-through;
	text-decoration-color: var(--sp-muted);
}

/* Level meter: three markers (filled accent / empty hairline ring) + a muted text label.
   Markup: .sp-level[data-level="0–3"] > .sp-level__dots[aria-hidden] > .sp-level__dot ×3 (+ .is-filled),
   then .sp-level__label. `data-level` alone is enough to fill the dots. */
.sp-level,
.sp-intensity {
	display: inline-flex;
	align-items: center;
	gap: 0.6em;
	font-family: var(--wp--preset--font-family--body);
	font-size: var(--wp--preset--font-size--x-small);
	line-height: 1.3;
	color: var(--sp-muted);
	vertical-align: middle;
}

:is(.sp-level, .sp-intensity) :is(.sp-level__dots, .sp-intensity__dots) {
	display: inline-flex;
	align-items: center;
	gap: 3px;
	flex: none;
}

:is(.sp-level__dot, .sp-intensity__dot) {
	display: inline-block;
	inline-size: 0.375rem;
	block-size: 0.375rem;
	box-sizing: border-box;
	border-radius: var(--wp--custom--radius--marker, 50%);
	border: var(--wp--custom--border--width, 1px) solid var(--sp-line);
	background-color: transparent;
}

:is(.sp-level__dot, .sp-intensity__dot):is(.is-filled, .is-on),
.sp-level:is([data-level="1"], .sp-level--1) .sp-level__dot:nth-child(-n + 1),
.sp-level:is([data-level="2"], .sp-level--2) .sp-level__dot:nth-child(-n + 2),
.sp-level:is([data-level="3"], .sp-level--3) .sp-level__dot:nth-child(-n + 3),
.sp-intensity[data-level="1"] .sp-intensity__dot:nth-child(-n + 1),
.sp-intensity[data-level="2"] .sp-intensity__dot:nth-child(-n + 2),
.sp-intensity[data-level="3"] .sp-intensity__dot:nth-child(-n + 3),
.sp-intensity[data-level="4"] .sp-intensity__dot:nth-child(-n + 4),
.sp-intensity[data-level="5"] .sp-intensity__dot:nth-child(-n + 5) {
	background-color: var(--sp-accent);
	border-color: var(--sp-accent);
}

/* "All levels" / unknown: text only. */
.sp-level:is([data-level="0"], .sp-level--0) .sp-level__dots {
	display: none;
}

/* Filter chips (`button.sp-chip[aria-pressed]`). */
.sp-chip {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: 0.5em;
	min-height: 2.75rem;
	box-sizing: border-box;
	padding: 0.6em 1.1em;
	border: var(--wp--custom--border--width, 1px) solid var(--sp-line);
	border-radius: var(--wp--custom--radius--tag, var(--wp--custom--radius--xs));
	background-color: transparent;
	color: var(--sp-fg);
	font-family: var(--wp--preset--font-family--body);
	font-size: var(--wp--preset--font-size--x-small);
	font-weight: 500;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	line-height: 1.2;
	text-decoration: none;
	cursor: pointer;
	transition:
		background-color var(--sp-fast) var(--sp-ease),
		border-color var(--sp-fast) var(--sp-ease),
		color var(--sp-fast) var(--sp-ease);
}

.sp-chip:hover {
	border-color: var(--sp-fg);
}

.sp-chip:is([aria-pressed="true"], .is-pressed, [aria-current]) {
	background-color: var(--sp-fg);
	border-color: var(--sp-fg);
	color: var(--sp-bg);
}

.sp-chip:is([aria-pressed="true"], .is-pressed)::before {
	content: "✓";
	content: "✓" / "";
	font-size: 1.1em;
	line-height: 1;
	letter-spacing: 0;
}

/* =========================================================================================
   11 Pricing, stats, dates (DESIGN §7.10, §9)
   ========================================================================================= */

/* The price: heading voice at xx-large × scale, lining tabular figures. A flex row so the cadence
   ("/ month") sits on the baseline and, in a narrow card, wraps tight under the figure. */
:root :is(p, div).sp-price {
	display: flex;
	flex-wrap: wrap;
	align-items: baseline;
	column-gap: 0;
}

:root :is(p, div).sp-price.has-text-align-center {
	justify-content: center;
}

:root :is(p, div).sp-price.has-text-align-right {
	justify-content: flex-end;
}

:root :is(p, div, span).sp-price {
	font-family: var(--wp--preset--font-family--heading);
	font-size: calc(var(--wp--preset--font-size--xx-large) * var(--sp-scale));
	font-weight: var(--wp--custom--heading--font-weight, 400);
	letter-spacing: var(--wp--custom--heading--letter-spacing, 0);
	line-height: 1;
	font-variant-numeric: lining-nums tabular-nums;
	color: var(--sp-fg);
	font-synthesis: none;
}

/* Patterns may pick a preset size (e.g. x-large for the intro offer) — keep the heading scale. */
:root :is(p, div, span).sp-price.has-x-large-font-size {
	font-size: calc(var(--wp--preset--font-size--x-large) * var(--sp-scale)) !important;
}

:root :is(p, div, span).sp-price.has-xxx-large-font-size {
	font-size: calc(var(--wp--preset--font-size--xxx-large) * var(--sp-scale)) !important;
}

:root :is(p, div, span).sp-price.has-large-font-size {
	font-size: calc(var(--wp--preset--font-size--large) * var(--sp-scale)) !important;
}

.sp-price sup {
	font-size: 0.45em;
	vertical-align: 0.9em;
	line-height: 1;
	margin-inline-end: -0.15em;
}

/* In the flex row the currency hangs from the top of the figures. */
:is(p, div).sp-price > sup {
	align-self: flex-start;
	margin-block-start: 0.12em;
	/* A hair of air so ball terminals (Bodoni, Fraunces) never touch the symbol. */
	margin-inline-end: 0.06em;
}

.sp-price .sp-price__per,
.sp-price__per {
	font-family: var(--wp--preset--font-family--body);
	font-size: var(--wp--preset--font-size--small);
	font-weight: 400;
	font-style: normal;
	letter-spacing: 0;
	text-transform: none;
	color: var(--sp-muted);
	white-space: nowrap;
}

.sp-price .sp-price__per {
	margin-inline-start: 0.4em;
}

/* Spa-menu leader (flex 1 dotted hairline between item and price). */
.sp-leader {
	flex: 1 1 2rem;
	align-self: auto;
	min-width: 1.5rem;
	height: auto;
	min-height: 0;
	margin: 0 0.5em 0.35em !important;
	border-block-end: var(--wp--custom--border--width, 1px) dotted var(--sp-line);
	padding: 0;
}

/* Stat: a heading-voice numeral over a label-voice caption. Markup: .sp-stat > p + p. */
.sp-stat > :first-child {
	font-family: var(--wp--preset--font-family--heading);
	font-size: calc(var(--wp--preset--font-size--x-large) * var(--sp-scale));
	font-weight: var(--wp--custom--heading--font-weight, 400);
	letter-spacing: var(--wp--custom--heading--letter-spacing, 0);
	line-height: 1;
	font-variant-numeric: lining-nums tabular-nums;
	color: var(--sp-fg);
	margin-block: 0;
}

.sp-stat > :first-child.has-large-font-size {
	font-size: calc(var(--wp--preset--font-size--large) * var(--sp-scale)) !important;
}

.sp-stat > :first-child.has-xx-large-font-size {
	font-size: calc(var(--wp--preset--font-size--xx-large) * var(--sp-scale)) !important;
}

.sp-stat > :not(:first-child) {
	font-family: var(--wp--preset--font-family--body);
	font-size: var(--wp--preset--font-size--x-small);
	font-weight: 500;
	letter-spacing: 0.12em;
	text-transform: uppercase;
	line-height: 1.4;
	color: var(--sp-muted);
	margin-block-start: var(--wp--preset--spacing--10);
}

/* Date block: day numeral over month (and weekday) in label voice.
   Markup: .sp-date > (.sp-date__day | first child) + (.sp-date__month | rest). `.sp-date--lg` → xx-large. */
.sp-date {
	display: inline-flex;
	flex-direction: column;
	align-items: center;
	gap: 0.35em;
	min-width: 4.5rem;
	text-align: center;
	line-height: 1;
}

.sp-date > * {
	margin: 0;
}

.sp-date > :is(.sp-date__day, :first-child) {
	font-family: var(--wp--preset--font-family--heading);
	font-size: calc(var(--wp--preset--font-size--x-large) * var(--sp-scale));
	font-weight: var(--wp--custom--heading--font-weight, 400);
	font-variant-numeric: lining-nums tabular-nums;
	line-height: 0.9;
	color: var(--sp-fg);
}

.sp-date.sp-date--lg > :is(.sp-date__day, :first-child) {
	font-size: calc(var(--wp--preset--font-size--xx-large) * var(--sp-scale));
}

.sp-date > :is(.sp-date__month, .sp-date__weekday, :not(:first-child)) {
	font-family: var(--wp--preset--font-family--body);
	font-size: var(--wp--preset--font-size--x-small);
	font-weight: 500;
	letter-spacing: 0.14em;
	text-transform: uppercase;
	color: var(--sp-muted);
}

/* =========================================================================================
   12 Forms (DESIGN §7.12) — generic fields + common form-plugin markup
   ========================================================================================= */

/* Field look, shared by bare forms and the popular form plugins. */
:where(
	input:not([type="checkbox"], [type="radio"], [type="submit"], [type="button"], [type="reset"], [type="file"], [type="image"], [type="range"], [type="color"], [type="hidden"]),
	select,
	textarea
),
:is(.wpcf7-form, .wpforms-form, .gform_wrapper, .jetpack-contact-form, .wp-block-jetpack-contact-form, .contact-form, .mc4wp-form, .comment-form, .sp-joined, .sp-form) :is(
	input[type="text"], input[type="email"], input[type="tel"], input[type="url"], input[type="number"],
	input[type="password"], input[type="search"], input[type="date"], input[type="time"], input[type="datetime-local"],
	select, textarea
) {
	box-sizing: border-box;
	width: 100%;
	min-height: 3rem;
	padding: 0.85em 1em;
	margin: 0;
	background-color: var(--sp-bg);
	color: var(--sp-fg);
	border: var(--wp--custom--border--width, 1px) solid var(--sp-field);
	border-radius: var(--wp--custom--radius--input);
	box-shadow: none;
	font-family: var(--wp--preset--font-family--body);
	/* ≥ 16px so iOS does not zoom on focus. */
	font-size: max(var(--wp--preset--font-size--medium), 1rem);
	font-weight: 400;
	letter-spacing: 0;
	text-transform: none;
	line-height: 1.4;
	transition: border-color var(--sp-fast) var(--sp-ease), box-shadow var(--sp-fast) var(--sp-ease);
}

:where(textarea),
:is(.wpcf7-form, .wpforms-form, .gform_wrapper, .jetpack-contact-form, .wp-block-jetpack-contact-form, .contact-form, .mc4wp-form, .comment-form, .sp-form) textarea {
	min-height: 8rem;
	resize: vertical;
	/* Never pill-shaped. */
	border-radius: min(var(--wp--custom--radius--input), 0.75rem);
}

:where(input, select, textarea)::placeholder {
	color: var(--sp-muted);
	opacity: 1;
}

:where(input, select, textarea):focus,
:is(.wpcf7-form, .wpforms-form, .gform_wrapper, .jetpack-contact-form, .contact-form, .mc4wp-form, .comment-form, .sp-joined, .sp-form) :is(input, select, textarea):focus {
	border-color: var(--sp-accent);
}

:where(input, select, textarea):focus-visible {
	outline: 2px solid var(--sp-focus);
	outline-offset: 3px;
}

/* Errors: a heavier fg border + a message; never colour alone. */
:where(input, select, textarea)[aria-invalid="true"],
:is(.wpcf7-not-valid, .wpforms-error:is(input, select, textarea), .gfield_error :is(input, select, textarea)) {
	border-color: var(--sp-fg);
	border-width: 2px;
}

:where(.sp-field-error, .wpcf7-not-valid-tip, .wpforms-error:not(input, select, textarea), .gfield_validation_message, .validation_message, .comment-form .error) {
	display: block;
	margin-block-start: var(--wp--preset--spacing--10);
	color: var(--sp-fg);
	font-family: var(--wp--preset--font-family--body);
	font-size: var(--wp--preset--font-size--small);
	font-weight: 500;
}

:where(.sp-field-error)::before {
	content: "!";
	content: "!" / "";
	display: inline-flex;
	align-items: center;
	justify-content: center;
	inline-size: 1.25em;
	block-size: 1.25em;
	margin-inline-end: 0.5em;
	border-radius: 50%;
	background-color: var(--sp-fg);
	color: var(--sp-bg);
	font-size: 0.85em;
	font-weight: 700;
	vertical-align: 0.05em;
}

/* Labels above fields, label voice. */
:where(label, legend, .wp-block-search__label, .gfield_label, .wpforms-field-label, .wpcf7-form label) {
	font-family: var(--wp--preset--font-family--body);
	font-size: var(--wp--preset--font-size--x-small);
	font-weight: 500;
	letter-spacing: 0.12em;
	text-transform: uppercase;
	line-height: 1.4;
	color: var(--sp-fg);
}

:where(label:has(+ input, + select, + textarea), legend, .gfield_label, .wpforms-field-label) {
	display: block;
	margin-block-end: var(--wp--preset--spacing--10);
}

/* Labels that wrap a checkbox/radio stay in sentence case at body size. */
:where(label:has(> input[type="checkbox"], > input[type="radio"]), .wpcf7-list-item-label, .comment-form-cookies-consent label) {
	font-size: var(--wp--preset--font-size--small);
	font-weight: 400;
	letter-spacing: 0;
	text-transform: none;
}

/* "(required)" text and plugin required markers. */
:where(.sp-required, .required, .gfield_required, .wpforms-required-label, .required-field-message) {
	color: var(--sp-muted);
	font-weight: 400;
	letter-spacing: 0;
	text-transform: none;
}

:where(input[type="checkbox"], input[type="radio"]) {
	inline-size: 1.25rem;
	block-size: 1.25rem;
	margin: 0;
	margin-inline-end: 0.5em;
	vertical-align: -0.2em;
	accent-color: var(--sp-accent);
	cursor: pointer;
}

/* Select: native control with a custom chevron. On a bare <select> the chevron is two CSS
   gradients in the fg role (no image, no colour literal); inside a wrapper (`.sp-select` or a
   plugin's field wrapper) it is the chevron ornament as a mask in currentColor (DESIGN §7.12). */
:root select,
:is(.wpcf7-form, .wpforms-form, .gform_wrapper, .jetpack-contact-form, .contact-form, .mc4wp-form, .sp-form) select {
	-webkit-appearance: none;
	appearance: none;
	padding-inline-end: 2.75em;
	cursor: pointer;
}

:root select:not([multiple]):not([size]),
:is(.wpcf7-form, .wpforms-form, .gform_wrapper, .jetpack-contact-form, .contact-form, .mc4wp-form, .sp-form) select:not([multiple]):not([size]) {
	/* A hairline chevron: two thin diagonals, matching the chevron ornament. */
	background-image:
		linear-gradient(45deg, transparent calc(50% - 0.6px), var(--sp-fg) calc(50% - 0.6px), var(--sp-fg) calc(50% + 0.6px), transparent calc(50% + 0.6px)),
		linear-gradient(-45deg, transparent calc(50% - 0.6px), var(--sp-fg) calc(50% - 0.6px), var(--sp-fg) calc(50% + 0.6px), transparent calc(50% + 0.6px));
	background-position:
		calc(100% - 1em - 0.4em) 50%,
		calc(100% - 1em) 50%;
	background-size: 0.4em 0.4em, 0.4em 0.4em;
	background-repeat: no-repeat;
}

[dir="rtl"] select:not([multiple]):not([size]) {
	background-position:
		1em 50%,
		1.4em 50%;
}

:where(.sp-select, .wpcf7-form-control-wrap:has(> select:not([multiple])), .ginput_container_select:has(> select:not([multiple]))) {
	position: relative;
	display: block;
	color: var(--sp-fg);
}

@supports (mask-image: none) or (-webkit-mask-image: none) {
	:root :is(.sp-select, .wpcf7-form-control-wrap:has(> select:not([multiple])), .ginput_container_select:has(> select:not([multiple]))) select {
		background-image: none;
	}

	:where(.sp-select, .wpcf7-form-control-wrap:has(> select:not([multiple])), .ginput_container_select:has(> select:not([multiple])))::after {
		content: "";
		position: absolute;
		inset-inline-end: 1em;
		inset-block-start: 50%;
		inline-size: 1em;
		block-size: 1em;
		translate: 0 -50%;
		background-color: currentColor;
		-webkit-mask: url("../images/ornaments/chevron.svg") center / contain no-repeat;
		mask: url("../images/ornaments/chevron.svg") center / contain no-repeat;
		pointer-events: none;
	}
}

:where(fieldset) {
	border: var(--wp--custom--border--width, 1px) solid var(--sp-line);
	border-radius: var(--wp--custom--radius--sm);
	padding: var(--wp--preset--spacing--30);
	margin: 0 0 var(--wp--preset--spacing--30);
}

:where(fieldset) > :where(label) {
	display: inline-flex;
	align-items: center;
	margin-inline-end: var(--wp--preset--spacing--30);
	min-height: 2.75rem;
}

:where(fieldset) > :where(legend) {
	padding-inline: 0.5em;
	margin-inline-start: -0.5em;
}

/* Plugin form rhythm. */
:is(.wpcf7-form, .mc4wp-form, .comment-form, .sp-form) > p,
.wpcf7-form p {
	margin-block: 0 var(--wp--preset--spacing--30);
}

.wpcf7-form .wpcf7-form-control-wrap {
	display: block;
}

.wpcf7-form .wpcf7-response-output {
	margin: var(--wp--preset--spacing--30) 0 0;
	padding: var(--wp--preset--spacing--20) var(--wp--preset--spacing--30);
	border: var(--wp--custom--border--width, 1px) solid var(--sp-fg) !important;
	border-radius: var(--wp--custom--radius--sm);
	font-size: var(--wp--preset--font-size--small);
}

.wpcf7-form .wpcf7-response-output:empty {
	display: none;
}

.wpcf7-spinner {
	background-color: var(--sp-muted);
}

/* WPForms (modern markup) and Gravity Forms (Orbital) expose CSS variables; map them to roles. */
:root :is(.wpforms-container, div.wpforms-container-full) {
	--wpforms-field-border-radius: var(--wp--custom--radius--input);
	--wpforms-field-background-color: var(--sp-bg);
	--wpforms-field-border-color: var(--sp-field);
	--wpforms-field-text-color: var(--sp-fg);
	--wpforms-label-color: var(--sp-fg);
	--wpforms-label-sublabel-color: var(--sp-muted);
	--wpforms-label-error-color: var(--sp-fg);
	--wpforms-button-border-radius: var(--wp--custom--radius--button);
	--wpforms-button-background-color: var(--sp-accent);
	--wpforms-button-text-color: var(--sp-on-accent);
	--wpforms-page-break-color: var(--sp-accent);
}

:root .gform-theme--framework,
:root .gform_wrapper.gform-theme {
	--gf-color-primary: var(--sp-accent);
	--gf-color-primary-contrast: var(--sp-on-accent);
	--gf-color-in-ctrl: var(--sp-bg);
	--gf-color-in-ctrl-contrast: var(--sp-fg);
	--gf-color-in-ctrl-dark: var(--sp-field);
	--gf-ctrl-border-color: var(--sp-field);
	--gf-ctrl-radius: var(--wp--custom--radius--input);
	--gf-ctrl-btn-radius: var(--wp--custom--radius--button);
	--gf-ctrl-label-color-primary: var(--sp-fg);
	--gf-ctrl-label-color-secondary: var(--sp-muted);
	--gf-font-family-base: var(--wp--preset--font-family--body);
}

/* Mailchimp classic embed: beat its ID-scoped CSS. */
#mc_embed_signup {
	background: transparent;
	font-family: inherit;
	color: var(--sp-fg);
}

#mc_embed_signup :is(input.email, input[type="email"], input[type="text"]) {
	min-height: 3rem;
	padding: 0.85em 1em;
	background-color: var(--sp-bg);
	color: var(--sp-fg);
	border: var(--wp--custom--border--width, 1px) solid var(--sp-field);
	border-radius: var(--wp--custom--radius--input);
	font-family: var(--wp--preset--font-family--body);
	font-size: max(var(--wp--preset--font-size--medium), 1rem);
}

#mc_embed_signup :is(.button, #mc-embedded-subscribe) {
	height: auto;
	min-height: 3rem;
	padding: var(--wp--custom--button--padding-block, 0.95em) var(--wp--custom--button--padding-inline, 1.9em);
	background-color: var(--sp-accent);
	color: var(--sp-on-accent);
	border: var(--wp--custom--border--width, 1px) solid var(--sp-accent);
	border-radius: var(--wp--custom--radius--button);
	font-family: var(--wp--preset--font-family--body);
	font-size: var(--wp--preset--font-size--small);
	font-weight: var(--wp--custom--button--font-weight, 500);
	letter-spacing: var(--wp--custom--button--letter-spacing, 0.1em);
	text-transform: var(--wp--custom--button--text-transform, uppercase);
}

#mc_embed_signup :is(.button, #mc-embedded-subscribe):hover {
	background-color: var(--sp-accent-hover);
	border-color: var(--sp-accent-hover);
}

/* Success notice (form plugins + `.sp-form-success`): a Wash panel with the sun glyph. */
:where(.sp-form-success, .wpcf7 form.sent .wpcf7-response-output, .wpforms-confirmation-container-full, .gform_confirmation_message, .mc4wp-success) {
	--sp-bg: var(--wp--preset--color--tint);
	--sp-line: color-mix(in srgb, var(--wp--preset--color--contrast) 18%, var(--wp--preset--color--tint));
	background-color: var(--wp--preset--color--tint) !important;
	color: var(--wp--preset--color--contrast) !important;
	border: 0 !important;
	border-radius: var(--wp--custom--radius--card);
	padding: var(--wp--preset--spacing--40) !important;
}

:where(.sp-form-success)::before {
	content: "";
	display: block;
	inline-size: 1.5rem;
	block-size: 1.5rem;
	margin-block-end: var(--wp--preset--spacing--20);
	background-color: var(--wp--preset--color--primary);
	-webkit-mask: url("../images/ornaments/sun-horizon.svg") center / contain no-repeat;
	mask: url("../images/ornaments/sun-horizon.svg") center / contain no-repeat;
}

/* ---- Joined newsletter form (`.sp-joined`): field + button in one row (DESIGN §7.12) ---- */
.sp-joined,
.sp-joined :is(form, .mc4wp-form-fields, .wpcf7-form, .wpforms-field-container) {
	display: flex;
	flex-wrap: nowrap;
	align-items: stretch;
	gap: 0;
}

.sp-joined :is(p:has(input, button), .wpcf7-form-control-wrap, .wp-block-search__inside-wrapper) {
	display: contents;
}

.sp-joined :is(label, .screen-reader-text) {
	position: absolute !important;
	width: 1px;
	height: 1px;
	overflow: hidden;
	clip-path: inset(50%);
	white-space: nowrap;
}

.sp-joined :is(input[type="email"], input[type="text"], input[type="search"]) {
	flex: 1 1 12rem;
	min-width: 0;
	border-start-start-radius: var(--wp--custom--radius--button);
	border-end-start-radius: var(--wp--custom--radius--button);
	border-start-end-radius: 0;
	border-end-end-radius: 0;
	border-inline-end-width: 0;
}

.sp-joined :is(button, input[type="submit"], .wp-element-button, .wp-block-button__link) {
	flex: none;
	margin: 0;
	border-start-start-radius: 0;
	border-end-start-radius: 0;
	border-start-end-radius: var(--wp--custom--radius--button);
	border-end-end-radius: var(--wp--custom--radius--button);
}

@media (max-width: 599px) {
	.sp-joined,
	.sp-joined :is(form, .mc4wp-form-fields, .wpcf7-form, .wpforms-field-container) {
		flex-direction: column;
		gap: var(--wp--preset--spacing--20);
	}

	.sp-joined :is(input[type="email"], input[type="text"], input[type="search"]) {
		flex-basis: auto;
		border-radius: var(--wp--custom--radius--button);
		border-inline-end-width: var(--wp--custom--border--width, 1px);
	}

	.sp-joined :is(button, input[type="submit"], .wp-element-button, .wp-block-button__link) {
		width: 100%;
		border-radius: var(--wp--custom--radius--button);
	}
}

/* =========================================================================================
   13 Image treatments, echo, captions, art (DESIGN §8.1–8.2)
   Shapes apply to core/image, core/post-featured-image and the plugin's `.sp-media--{style}`
   wrappers. The arch keeps a true semicircle top AND the corner setting at the bottom by giving
   the top corners elliptical radii computed from the frame ratio (--sp-wh = width / height).
   ========================================================================================= */

:is(.wp-block-image, .wp-block-post-featured-image) :is(img, svg.sp-art),
:where(.sp-media, [class*="sp-media--"]) :where(img, svg.sp-art) {
	box-sizing: border-box;
	border-radius: var(--sp-shape, var(--wp--custom--radius--image));
}

/* Shaped images and art fill their frame; plain images keep core's intrinsic sizing. */
:is(.wp-block-image, .wp-block-post-featured-image):is(.is-style-arch, .is-style-circle, .is-style-organic, .is-style-framed) :is(img, svg.sp-art),
:is(.wp-block-image, .wp-block-post-featured-image) svg.sp-art,
.wp-block-post-featured-image img {
	display: block;
	width: 100%;
	height: auto;
	object-fit: cover;
}

/* A width chosen in the editor (inline style) always wins; aligned figures shrink-wrap. */
.wp-block-image:is(.alignleft, .alignright, .aligncenter):not(.is-resized) :is(img, svg.sp-art) {
	max-width: 100%;
}

/* Full-bleed images are never rounded. */
.wp-block-image.alignfull :is(img, svg.sp-art),
.wp-block-post-featured-image.alignfull :is(img, svg.sp-art) {
	--sp-shape: 0;
	border-radius: 0;
}

/* Shape definitions. */
:is(.wp-block-image, .wp-block-post-featured-image).is-style-arch,
.sp-media--arch {
	--sp-wh: 0.75;
	--sp-shape:
		50% 50% var(--wp--custom--radius--md) var(--wp--custom--radius--md) /
		calc(50% * var(--sp-wh)) calc(50% * var(--sp-wh)) var(--wp--custom--radius--md) var(--wp--custom--radius--md);
}

:is(.wp-block-image, .wp-block-post-featured-image).is-style-circle,
.sp-media--circle {
	--sp-shape: 50%;
}

:is(.wp-block-image, .wp-block-post-featured-image).is-style-organic,
.sp-media--organic {
	--sp-shape: 62% 38% 54% 46% / 49% 60% 40% 51%;
}

/* Organic shapes rotate through three variants so grids never repeat. */
:is(.wp-block-image, .wp-block-post-featured-image).is-style-organic:nth-of-type(3n + 2),
.sp-media--organic:nth-of-type(3n + 2),
.wp-block-post:nth-child(3n + 2) .is-style-organic,
.wp-block-column:nth-child(3n + 2) > .is-style-organic {
	--sp-shape: 41% 59% 45% 55% / 58% 42% 58% 42%;
}

:is(.wp-block-image, .wp-block-post-featured-image).is-style-organic:nth-of-type(3n),
.sp-media--organic:nth-of-type(3n),
.wp-block-post:nth-child(3n) .is-style-organic,
.wp-block-column:nth-child(3n) > .is-style-organic {
	--sp-shape: 55% 45% 62% 38% / 44% 56% 44% 56%;
}

/* Forced aspect ratios (an aspectRatio picked in the editor is an inline style and wins). */
:is(.wp-block-image, .wp-block-post-featured-image).is-style-arch :is(img, svg.sp-art),
:where(.sp-media--arch) > :where(img, svg),
:where(.sp-media--arch) > a > :where(img, svg) {
	aspect-ratio: 3 / 4;
}

:is(.wp-block-image, .wp-block-post-featured-image).is-style-circle :is(img, svg.sp-art),
:where(.sp-media--circle) > :where(img, svg),
:where(.sp-media--circle) > a > :where(img, svg) {
	aspect-ratio: 1;
}

:is(.wp-block-image, .wp-block-post-featured-image).is-style-organic :is(img, svg.sp-art),
:where(.sp-media--organic) > :where(img, svg),
:where(.sp-media--organic) > a > :where(img, svg) {
	aspect-ratio: 4 / 5;
}

:where(.sp-media--arch, .sp-media--circle, .sp-media--organic) :where(img, svg) {
	display: block;
	width: 100%;
	height: auto;
	object-fit: cover;
	border-radius: var(--sp-shape);
}

/* Teacher monogram fallback (plugin SVG `.sp-monogram--arch`): a faint olive-branch layer at 12%
   of the fg role (DESIGN §7.9, §8.3). The art file is used as a mask, so it takes any Look. */
.sp-media:has(> svg.sp-monogram--arch)::after {
	content: "";
	position: absolute;
	inset: 12% 14% 6%;
	background-color: var(--sp-fg, currentColor);
	opacity: 0.12;
	-webkit-mask: url("../images/art/olive-branch.svg") center / contain no-repeat;
	mask: url("../images/art/olive-branch.svg") center / contain no-repeat;
	pointer-events: none;
}

/* Arch: when the editor sets a frame ratio, recompute the semicircle (--sp-wh = w / h). */
.is-style-arch :is(img, svg)[style*="aspect-ratio:1"],
.is-style-arch[style*="aspect-ratio:1"] {
	--sp-wh: 1;
}

.is-style-arch :is(img, svg)[style*="aspect-ratio:4/5"],
.is-style-arch[style*="aspect-ratio:4/5"] {
	--sp-wh: 0.8;
}

.is-style-arch :is(img, svg)[style*="aspect-ratio:2/3"],
.is-style-arch[style*="aspect-ratio:2/3"] {
	--sp-wh: 0.6667;
}

.is-style-arch :is(img, svg)[style*="aspect-ratio:9/16"],
.is-style-arch[style*="aspect-ratio:9/16"] {
	--sp-wh: 0.5625;
}

.is-style-arch :is(img, svg)[style*="aspect-ratio:3/4"],
.is-style-arch[style*="aspect-ratio:3/4"] {
	--sp-wh: 0.75;
}

.is-style-arch :is(img, svg)[style*="aspect-ratio:4/3"],
.is-style-arch[style*="aspect-ratio:4/3"] {
	--sp-wh: 1.3333;
}

.is-style-arch :is(img, svg)[style*="aspect-ratio:3/2"],
.is-style-arch[style*="aspect-ratio:3/2"] {
	--sp-wh: 1.5;
}

/* Re-evaluate the shape on the element that carries the inline ratio. */
.is-style-arch :is(img, svg)[style*="aspect-ratio"] {
	border-radius:
		50% 50% var(--wp--custom--radius--md) var(--wp--custom--radius--md) /
		calc(50% * var(--sp-wh)) calc(50% * var(--sp-wh)) var(--wp--custom--radius--md) var(--wp--custom--radius--md);
}

/* Framed: a hairline frame spacing-20 away from the picture. Drawn as border + padding on the
   image itself (not outline-offset), so the frame keeps the image radius and the picture inside
   follows the nested-radius rule (replaced content is clipped to the content-box curve); the
   frame also stays inside the column, so it never clips or overflows. */
:is(.wp-block-image, .wp-block-post-featured-image).is-style-framed :is(img, svg.sp-art),
.sp-media--framed :is(img, svg) {
	padding: var(--wp--preset--spacing--20);
	border: var(--wp--custom--border--width, 1px) solid var(--sp-line);
	border-radius: var(--wp--custom--radius--image);
	background-color: transparent;
}

/* ---- Echo (`has-echo`, `has-echo-line`; DESIGN §8.1) ----
   Drawn as an offset box-shadow of the image itself: it follows every shape exactly (arch,
   circle, organic, any radius), ignores captions and links, and never adds scrollable overflow. */
:is(.wp-block-image, .wp-block-post-featured-image, .sp-media, [class*="sp-media--"]).has-echo,
:is(.wp-block-image, .wp-block-post-featured-image, .sp-media, [class*="sp-media--"]).has-echo-line {
	position: relative;
	isolation: isolate;
	overflow: visible;
	margin-block-end: max(var(--sp-echo), var(--wp--style--block-gap, 0px));
	padding-inline-end: var(--sp-echo);
	box-sizing: border-box;
}

:is(.wp-block-image, .wp-block-post-featured-image):is(.has-echo, .has-echo-line) > figcaption {
	/* The echo hangs below the picture; the caption starts under it. */
	margin-block-start: calc(var(--sp-echo) + var(--wp--preset--spacing--20));
}

:is(.wp-block-image, .wp-block-post-featured-image, .sp-media, [class*="sp-media--"]).has-echo :is(img, svg) {
	box-shadow: var(--sp-echo) var(--sp-echo) 0 0 var(--wp--preset--color--secondary);
}

:is(.wp-block-image, .wp-block-post-featured-image, .sp-media, [class*="sp-media--"]).has-echo-line :is(img, svg) {
	box-shadow:
		var(--sp-echo) var(--sp-echo) 0 -1px var(--sp-bg),
		var(--sp-echo) var(--sp-echo) 0 0 color-mix(in srgb, var(--sp-fg) 40%, transparent);
}

@media (max-width: 599px) {
	:root {
		--sp-echo: var(--wp--preset--spacing--20);
	}
}

/* ---- Captions (label voice, "— " lead-in; DESIGN §8.1) ---- */
figcaption.wp-element-caption,
:is(.wp-block-image, .wp-block-gallery, .wp-block-table, .wp-block-embed, .wp-block-video, .wp-block-audio, .wp-block-post-featured-image) figcaption {
	margin-block: var(--wp--preset--spacing--20) 0;
	font-family: var(--wp--preset--font-family--body);
	font-size: var(--wp--preset--font-size--x-small);
	font-weight: 500;
	font-style: normal;
	letter-spacing: 0.12em;
	text-transform: uppercase;
	line-height: 1.5;
	color: var(--sp-muted);
	text-align: start;
}

figcaption.wp-element-caption.has-text-align-center {
	text-align: center;
}

figcaption.wp-element-caption::before {
	content: "— ";
	content: "— " / "";
}

/* Gallery captions overlay images in core; keep them readable and quiet. */
.wp-block-gallery .wp-block-image figcaption::before {
	content: none;
}

/* ---- Inline art (`svg.sp-art`, inlined by inc/art.php) ---- */
svg.sp-art {
	display: block;
	width: 100%;
	height: auto;
	overflow: hidden;
}

.wp-block-image > svg.sp-art,
.wp-block-image > a > svg.sp-art {
	border-radius: var(--sp-shape, var(--wp--custom--radius--image));
}

/* Art banding blocks (full-bleed art, e.g. layered hills at 21/9) keep a sensible floor. */
.wp-block-image.alignfull > svg.sp-art {
	min-height: 15rem;
}

/* Other media blocks share the image radius. */
:where(.wp-block-media-text__media img, .wp-block-gallery .wp-block-image img, .wp-block-video video, .wp-block-embed iframe, .wp-block-cover:not(.alignfull)) {
	border-radius: var(--wp--custom--radius--image);
}

/* =========================================================================================
   14 Post meta, read more, post navigation (DESIGN §9.9)
   ========================================================================================= */

/* Post meta in label voice (date, author, reading time, term list). */
:where(.wp-block-post-date, .wp-block-post-author-name, .wp-block-post-time-to-read, .wp-block-post-terms:not(.is-style-pills), .wp-block-post-author__byline, .wp-block-comment-date) {
	font-family: var(--wp--preset--font-family--body);
	font-size: var(--wp--preset--font-size--x-small);
	font-weight: 500;
	letter-spacing: 0.12em;
	text-transform: uppercase;
	line-height: 1.5;
	color: var(--sp-muted);
}

:where(.wp-block-post-date, .wp-block-post-author-name, .wp-block-post-terms:not(.is-style-pills), .wp-block-comment-date) a {
	color: inherit;
	text-decoration-line: none;
}

:where(.wp-block-post-date, .wp-block-post-author-name, .wp-block-post-terms:not(.is-style-pills), .wp-block-comment-date) a:hover {
	color: var(--sp-fg);
	text-decoration-line: underline;
}

/* Read more link. */
:where(.wp-block-read-more, .wp-block-post-excerpt__more-link) {
	font-family: var(--wp--preset--font-family--body);
	font-size: var(--wp--preset--font-size--x-small);
	font-weight: 500;
	letter-spacing: 0.12em;
	text-transform: uppercase;
	color: var(--sp-fg);
}

/* Previous / next post navigation. */
:where(.wp-block-post-navigation-link) {
	font-family: var(--wp--preset--font-family--body);
	font-size: var(--wp--preset--font-size--small);
	letter-spacing: 0.04em;
}

:where(.wp-block-post-navigation-link) a {
	text-decoration-line: none;
}

:where(.wp-block-post-navigation-link) a:hover {
	text-decoration-line: underline;
}

/* No-results message. */
:where(.wp-block-query-no-results) {
	color: var(--sp-muted);
}

/* =========================================================================================
   15 Motion (DESIGN §6.4)
   ========================================================================================= */

/* One reveal: theme.js adds .sp-reveal (only with body.sp-motion and no reduced motion), then
   .is-revealed once in view. Content is fully visible without JS. */
.sp-motion .sp-reveal {
	opacity: 0;
	transform: translateY(0.875rem);
	transition:
		opacity var(--sp-slow) var(--sp-ease),
		transform var(--sp-slow) var(--sp-ease);
	transition-delay: calc(var(--sp-i, 0) * 70ms);
}

.sp-motion .sp-reveal.is-revealed {
	opacity: 1;
	transform: none;
}

/* Smooth in-page scrolling only when the owner wants motion. */
@media (prefers-reduced-motion: no-preference) {
	html:has(> body.sp-motion) {
		scroll-behavior: smooth;
	}
}

/* Reduced motion wins over the setting: zero durations, no transforms, no reveals. */
@media (prefers-reduced-motion: reduce) {
	:root:root {
		--sp-fast: 0ms;
		--sp-dur: 0ms;
		--sp-slow: 0ms;
		--wp--custom--motion--duration-fast: 0ms;
		--wp--custom--motion--duration: 0ms;
		--wp--custom--motion--duration-slow: 0ms;
	}

	html {
		scroll-behavior: auto !important;
	}

	*,
	*::before,
	*::after {
		animation-duration: 0.01ms !important;
		animation-iteration-count: 1 !important;
		transition-duration: 0.01ms !important;
		transition-delay: 0ms !important;
	}

	.sp-reveal,
	.sp-motion .sp-reveal {
		opacity: 1 !important;
		transform: none !important;
	}

	:root :is(.wp-element-button, .wp-block-button__link, .sp-button):active,
	.wp-block-post-template .wp-block-post:is(:hover, :focus-within) .wp-block-post-featured-image :is(img, svg),
	:root :is(.wp-block-button.has-arrow > .wp-block-button__link, .wp-block-button__link.has-arrow, .sp-button.has-arrow):hover::after,
	:root :is(.wp-block-button.is-style-text-arrow > .wp-block-button__link, .sp-button--text-arrow):hover::after,
	.wp-block-social-link:hover {
		transform: none !important;
	}
}

/* =========================================================================================
   16 Dark scheme (body.sp-scheme-dark; DESIGN §3.2, §8.1)
   ========================================================================================= */

html:has(> body.sp-scheme-dark) {
	color-scheme: dark;
}

/* Native controls follow the ground they sit on. */
body:not(.sp-scheme-dark) :is(.is-style-section-inverse, .has-contrast-background-color) {
	color-scheme: dark;
}

.sp-scheme-dark :is(.is-style-section-inverse, .has-contrast-background-color) {
	color-scheme: light;
}

/* Photos sit slightly lower on dark paper; art (inline SVG or theme art files) is excluded. */
.sp-scheme-dark :is(.wp-block-image, .wp-block-post-featured-image, .wp-block-media-text, .wp-block-cover, .wp-block-gallery, .sp-media) img:not([src*="/assets/images/art/"]):not([src$=".svg"]) {
	filter: brightness(0.94);
}

/* =========================================================================================
   17 Print
   ========================================================================================= */

@media print {
	:root {
		--sp-echo: 0;
	}

	body {
		overflow: visible;
	}

	/* System colours follow color-scheme, which Ink bands flip on screen; paper is always light. */
	html,
	body,
	body * {
		color-scheme: light !important;
	}

	/* Every ground prints as ink on paper. */
	body * {
		--sp-bg: Canvas !important;
		--sp-fg: CanvasText !important;
		--sp-muted: CanvasText !important;
		--sp-line: CanvasText !important;
		--sp-soft: transparent !important;
		--sp-card: Canvas !important;
		--sp-accent: CanvasText !important;
		--sp-on-accent: Canvas !important;
		--sp-mark: CanvasText !important;
		--sp-highlight: transparent !important;
	}

	body * {
		color: CanvasText !important;
		background-color: transparent !important;
		box-shadow: none !important;
		text-shadow: none !important;
	}

	.sp-header-sticky header.wp-block-template-part {
		position: static;
		backdrop-filter: none;
	}

	.sp-reveal {
		opacity: 1 !important;
		transform: none !important;
	}

	.wp-block-navigation,
	.sp-announcement,
	.sp-wordmark,
	.sp-back-to-top,
	.skip-link,
	.wp-block-search,
	.wp-block-post-comments-form,
	.sp-joined,
	.wp-block-buttons {
		display: none !important;
	}

	:is(.is-style-section-surface, .is-style-section-tint, .is-style-section-inverse, .is-style-section-brand, .is-style-card) {
		border: var(--wp--custom--border--width, 1px) solid CanvasText;
	}

	a {
		text-decoration-color: CanvasText !important;
	}

	:where(.wp-block-post-content, .entry-content) a[href^="http"]::after {
		content: " (" attr(href) ")";
		font-size: 0.85em;
		word-break: break-all;
	}

	:is(h1, h2, h3, h4, figure, blockquote, table, .wp-block-image) {
		break-inside: avoid;
	}

	:is(h1, h2, h3, h4) {
		break-after: avoid;
	}
}
