/*
Theme Name: LADUCA
Theme URI:
Author: LADUCA
Author URI:
Description: A native WordPress block theme for LADUCA. Every brand decision (colour, type, spacing) lives in theme.json, so the theme can be copied and re-skinned for a client build by editing that one file. Sections are registered patterns, so pages stay editable from the block editor without touching code.
Requires at least: 6.5
Tested up to: 7.0
Requires PHP: 7.4
Version: 1.0.6
License: GNU General Public License v2 or later
License URI: http://www.gnu.org/licenses/gpl-2.0.html
Text Domain: laduca
Tags: full-site-editing, block-patterns, blog, business, one-column, accessibility-ready, custom-colors, custom-logo, wide-blocks
*/

/* -------------------------------------------------------------------------
   This file holds only mechanism CSS - behaviour that block supports cannot
   express (sticky header, the hero grid-paper texture, the FAQ +/- marker,
   Gravity Forms integration). Every colour, size and space below resolves to
   a theme.json preset variable, so re-skinning a fork means editing
   theme.json and nothing else.
   ---------------------------------------------------------------------- */

/* --- Accessibility ------------------------------------------------------ */

.skip-link {
	position: absolute;
	left: -9999px;
	top: 0;
	z-index: 100000;
	padding: 12px 22px;
	background: var(--wp--preset--color--contrast);
	color: var(--wp--preset--color--base);
	font-weight: 600;
	text-decoration: none;
}

.skip-link:focus {
	left: 8px;
	top: 8px;
}

:where(a, button, input, textarea, select, summary, .wp-block-navigation-item__content):focus-visible {
	outline: 2px solid var(--wp--preset--color--primary);
	outline-offset: 3px;
}

/* Dark bands need the brighter logo orange for a visible focus ring. */
.has-contrast-background-color :where(a, button, input, textarea, summary):focus-visible {
	outline-color: var(--wp--preset--color--brand);
}

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

html {
	scroll-behavior: smooth;

	/* Lets the hero rings bleed past their column without producing a
	   horizontal scrollbar. `clip` rather than `hidden` on purpose: `hidden`
	   makes this a scroll container and silently kills position: sticky on
	   the header. */
	overflow-x: clip;
}

/* Sticky header must not cover the target of an in-page anchor link. */
:target {
	scroll-margin-top: 96px;
}

/* --- Section stacking ---------------------------------------------------
   WordPress applies --wp--style--block-gap as margin-block-start between
   siblings at two levels, and both show the page background as a stripe
   between coloured bands, breaking the design's colour blocking:

     1. .wp-site-blocks - between header, main and footer.
     2. post-content    - between the stacked page sections.

   The shell (1) is always flush: vertical rhythm comes from each section's
   own padding, never from a gap between them. Inside the content (2) the gap
   is collapsed only where two full-width sections meet, so ordinary blocks
   the client inserts between sections still get their normal spacing.
   ---------------------------------------------------------------------- */

.wp-site-blocks > * + * {
	margin-block-start: 0;
}

.wp-block-post-content > .alignfull + .alignfull,
.block-editor-block-list__layout > .alignfull + .alignfull {
	margin-block-start: 0;
}

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

.ld-header {
	position: sticky;
	top: 0;
	z-index: 40;
	background: color-mix(in srgb, var(--wp--preset--color--base) 94%, transparent);
	border-bottom: 1px solid var(--wp--preset--color--line);
}

/* Logged in, the fixed admin bar covers the top of the page, so the sticky
   header must pin below it or editors see it slide underneath. Core
   publishes the bar's height (32px, 46px on small screens) as a variable. */
.admin-bar .ld-header {
	top: var(--wp-admin--admin-bar--height, 0px);
}

@supports (backdrop-filter: blur(6px)) {
	.ld-header {
		backdrop-filter: blur(6px);
	}

	/* backdrop-filter makes the header a containing block for any
	   position: fixed descendant. Core's mobile menu overlay is
	   `position: fixed; inset: 0`, so with the blur applied it gets confined
	   to the header box instead of covering the viewport: the first link shows
	   and the rest paint underneath the page content, invisible and
	   unclickable. Drop the blur while the menu is open. There is nothing to
	   blur at that point, because the overlay is opaque. */
	.ld-header:has(.wp-block-navigation__responsive-container.is-menu-open) {
		backdrop-filter: none;
	}
}

.ld-logo img {
	height: auto;
	max-height: 44px;
	width: auto;
}

/* Nav links sit in ink, not link-rust, until hovered. */
.ld-nav .wp-block-navigation-item__content {
	color: var(--wp--preset--color--contrast);
	font-weight: 500;
	text-decoration: none;
}

.ld-nav .wp-block-navigation-item__content:hover {
	color: var(--wp--preset--color--primary);
	text-decoration: underline;
	text-underline-offset: 4px;
}

/* The phone number reads as a mono utility, not a nav item. */
.ld-phone a,
.ld-phone .wp-block-navigation-item__content {
	font-family: var(--wp--preset--font-family--mono);
	font-size: var(--wp--preset--font-size--x-small);
	color: var(--wp--preset--color--ink-muted);
	letter-spacing: 0.02em;
}

/* --- Navigation submenu -------------------------------------------------
   Core's default submenu is a rounded white box with its own borders. Square
   it off and put it in the theme's hairline language so the dropdown looks
   like part of the site rather than part of WordPress.
   ---------------------------------------------------------------------- */

.ld-header .wp-block-navigation__submenu-container {
	background-color: var(--wp--preset--color--base);
	border: 1px solid var(--wp--preset--color--line);
	border-radius: 0;
	box-shadow: 0 12px 28px rgba(18, 17, 16, 0.07);
	min-width: 260px;
	padding: var(--wp--preset--spacing--20) 0;
}

.ld-header .wp-block-navigation__submenu-container .wp-block-navigation-item__content {
	color: var(--wp--preset--color--contrast);
	font-weight: 500;
	padding: 0.5rem var(--wp--preset--spacing--50);
	text-decoration: none;
	width: 100%;
}

.ld-header .wp-block-navigation__submenu-container .wp-block-navigation-item__content:hover {
	background-color: var(--wp--preset--color--surface);
	color: var(--wp--preset--color--primary);
	text-decoration: none;
}

/* The parent item's chevron should not drift from its label. */
.ld-header .wp-block-navigation-submenu__toggle {
	padding-right: 0;
}

/* --- Hero grid-paper texture -------------------------------------------- */

.ld-gridpaper {
	background-image:
		linear-gradient(var(--wp--preset--color--line) 1px, transparent 1px),
		linear-gradient(90deg, var(--wp--preset--color--line) 1px, transparent 1px);
	background-size: 64px 64px;
	background-position: center top;
}

/* --- Hero mark animation ------------------------------------------------
   The lifebuoy rebuilt as geometry rather than an image: four sonar rings
   pulsing outward, a slowly rotating dashed orbit, and the ring itself drawn
   from four clipped quadrants. It is decorative, so it is aria-hidden and it
   stops entirely under prefers-reduced-motion (handled globally above).
   ---------------------------------------------------------------------- */

@keyframes ld-sonar {
	0%   { transform: scale(0.34); opacity: 0; }
	12%  { opacity: 0.85; }
	100% { transform: scale(1.6); opacity: 0; }
}

@keyframes ld-spin {
	to { transform: rotate(360deg); }
}

.ld-heromark {
	--ld-sonar: 400px;
	position: relative;
	display: flex;
	align-items: center;
	justify-content: center;
	min-height: clamp(320px, 46vh, 420px);

	/* Deliberately NOT clipped. The rings expand to 1.6x, which is wider than
	   the column they sit in, and the whole point is that they carry past its
	   edge. Page-level containment is handled once on <html> below. */
	overflow: visible;
}

.ld-heromark__sonar {
	position: absolute;
	width: var(--ld-sonar);
	height: var(--ld-sonar);
	border: 1px solid var(--wp--preset--color--primary);
	border-radius: 50%;
	opacity: 0;
	animation: ld-sonar 5.2s cubic-bezier(0.22, 0.61, 0.36, 1) infinite;
}

.ld-heromark__sonar:nth-child(2) { animation-delay: 1.3s; }
.ld-heromark__sonar:nth-child(3) { animation-delay: 2.6s; }
.ld-heromark__sonar:nth-child(4) { animation-delay: 3.9s; }

.ld-heromark__core {
	position: relative;
	width: 196px;
	height: 196px;
}

.ld-heromark__orbit {
	position: absolute;
	inset: -34px;
	border: 1px dashed var(--wp--custom--hairline--orbit);
	border-radius: 50%;
	animation: ld-spin 24s linear infinite;
}

.ld-heromark__ring {
	position: absolute;
	inset: 0;
	border-radius: 50%;
	overflow: hidden;
}

/* Each quadrant is a full ring clipped to a wedge, which is what gives the
   buoy its four painted segments without four separate arc paths. */
.ld-heromark__seg {
	position: absolute;
	inset: 0;
	border: 13px solid var(--wp--preset--color--primary);
	border-radius: 50%;
	clip-path: polygon(50% 50%, 100% 13%, 100% 87%);
}

.ld-heromark__seg:nth-child(1) { transform: rotate(45deg); }
.ld-heromark__seg:nth-child(2) { transform: rotate(135deg); }
.ld-heromark__seg:nth-child(3) { transform: rotate(225deg); }
.ld-heromark__seg:nth-child(4) { transform: rotate(315deg); }

.ld-heromark__hub {
	position: absolute;
	inset: 44px;
	background-color: var(--wp--preset--color--base);
	border: 2px solid var(--wp--preset--color--contrast);
	border-radius: 50%;
}

@media (max-width: 600px) {
	.ld-heromark { --ld-sonar: 300px; }
	.ld-heromark__core { width: 150px; height: 150px; }
	.ld-heromark__hub { inset: 34px; }
	.ld-heromark__seg { border-width: 10px; }
}

/* --- Hairline card grids ------------------------------------------------
   The grid container carries the hairline colour and a 1px gap, so the gaps
   themselves draw the rules. Children just need their own background.
   ---------------------------------------------------------------------- */

.ld-hairline-grid {
	border: 1px solid var(--wp--preset--color--line);
	padding: 0;
}

.ld-hairline-grid.has-ink-line-background-color {
	border-color: var(--wp--preset--color--ink-line);
}

/* Cards lift slightly on hover where the design calls for it.
   !important is required throughout the hover states below: WordPress emits
   its preset utilities (.has-*-color, .has-*-background-color) with
   !important, so any hover override of a preset-coloured element loses
   without it. */
.ld-card {
	transition: background-color 120ms ease;
}

.ld-card:hover {
	background-color: var(--wp--custom--hover--card) !important;
}

/* --- Registered block styles -------------------------------------------- */

/* core/list - "Spec list" */
.wp-block-list.is-style-spec {
	list-style: none;
	margin: 0;
	padding: 0;
	display: grid;
	gap: 9px;
	font-family: var(--wp--preset--font-family--mono);
	font-size: var(--wp--preset--font-size--x-small);
	line-height: 1.45;
	color: var(--wp--preset--color--ink-muted);
}

.has-contrast-background-color .wp-block-list.is-style-spec {
	color: var(--wp--preset--color--on-dark);
}

/* core/group - "Numbered step" */
.wp-block-group.is-style-step {
	border-top: 2px solid var(--wp--preset--color--contrast);
	padding-top: 22px;
}

/* --- Comparison table ---------------------------------------------------
   core/table with the registered "Comparison table" block style. Using a real
   table keeps it semantic and lets the client edit it like a spreadsheet.
   ---------------------------------------------------------------------- */

.wp-block-table.is-style-compare {
	margin: 0;
}

.wp-block-table.is-style-compare table {
	border-collapse: collapse;
	width: 100%;
	border-top: 1px solid var(--wp--preset--color--contrast);
}

.wp-block-table.is-style-compare thead {
	/* Core draws a 3px rule under the head. The design puts the single dark
	   rule on TOP of the whole block instead, with hairlines between rows. */
	border-bottom: 0;
}

.wp-block-table.is-style-compare :where(th, td) {
	border: 0;
	border-bottom: 1px solid var(--wp--preset--color--line);
	text-align: left;
	vertical-align: baseline;
}

.wp-block-table.is-style-compare thead th {
	font-family: var(--wp--preset--font-family--mono);
	font-size: var(--wp--preset--font-size--eyebrow);
	font-weight: 400;
	letter-spacing: var(--wp--custom--letter-spacing--mono);
	text-transform: uppercase;
	color: var(--wp--preset--color--ink-muted);
	padding: 20px 0;
}

.wp-block-table.is-style-compare thead th:last-child {
	color: var(--wp--preset--color--primary);
}

.wp-block-table.is-style-compare tbody td {
	padding: 22px 0;
	font-size: var(--wp--preset--font-size--medium);
	color: var(--wp--preset--color--ink-muted);
}

.wp-block-table.is-style-compare tbody td:first-child {
	font-weight: 600;
	color: var(--wp--preset--color--contrast);
	width: 210px;
}

.wp-block-table.is-style-compare tbody td:last-child {
	color: var(--wp--preset--color--contrast);
}

.wp-block-table.is-style-compare :where(th, td) + :where(th, td) {
	padding-left: clamp(14px, 2vw, 32px);
}

@media (max-width: 600px) {
	.wp-block-table.is-style-compare tbody td:first-child {
		width: auto;
	}
	.wp-block-table.is-style-compare :where(th, td) {
		font-size: var(--wp--preset--font-size--small);
	}
}

/* --- FAQ (core/details) ------------------------------------------------- */

.ld-faq .wp-block-details {
	border-bottom: 1px solid var(--wp--preset--color--line);
	padding: 24px 0;
}

.ld-faq .wp-block-details summary {
	display: flex;
	justify-content: space-between;
	align-items: baseline;
	gap: 24px;
	list-style: none;
	cursor: pointer;
	font-size: var(--wp--preset--font-size--card-title);
	font-weight: 600;
	letter-spacing: -0.01em;
}

.ld-faq .wp-block-details summary::-webkit-details-marker,
.ld-faq .wp-block-details summary::marker {
	display: none;
	content: "";
}

.ld-faq .wp-block-details summary::after {
	content: "+";
	font-family: var(--wp--preset--font-family--mono);
	font-size: 20px;
	line-height: 1;
	color: var(--wp--preset--color--primary);
	flex: none;
}

.ld-faq .wp-block-details[open] summary::after {
	content: "\2212"; /* minus */
}

.ld-faq .wp-block-details > *:not(summary) {
	margin-top: 14px;
	max-width: 70ch;
	color: var(--wp--preset--color--ink-soft);
	line-height: var(--wp--custom--line-height--relaxed);
}

/* --- Card links ---------------------------------------------------------
   A linked card title alone is not an obvious affordance, so cards that lead
   somewhere also carry a mono link. The whole card lightens on hover.
   ---------------------------------------------------------------------- */

.ld-card h3 a {
	color: inherit;
	text-decoration: none;
}

.ld-card:hover h3 a {
	color: var(--wp--preset--color--primary);
}

.ld-cardlink a {
	color: var(--wp--preset--color--primary);
	text-decoration: none;
	letter-spacing: 0.06em;
	text-transform: uppercase;
}

.ld-card:hover .ld-cardlink a {
	text-decoration: underline;
	text-underline-offset: 4px;
}

/* --- Link index ---------------------------------------------------------
   The industries hub is a long list of links. A hairline-ruled grid reads as
   an index rather than as navigation, and stays scannable at 40+ entries.
   ---------------------------------------------------------------------- */

.ld-index__item {
	border-bottom: 1px solid var(--wp--preset--color--line);
	padding: 14px 0;
}

.ld-index__item a {
	color: var(--wp--preset--color--contrast);
	font-weight: 500;
	text-decoration: none;
}

.ld-index__item a:hover {
	color: var(--wp--preset--color--primary);
	text-decoration: underline;
	text-underline-offset: 4px;
}

/* --- Measure ------------------------------------------------------------
   The design constrains individual headings and paragraphs by character
   count rather than by column. Block supports have no max-width control, so
   these are exposed as utility classes - pick one in the block's Advanced >
   Additional CSS class field.
   ---------------------------------------------------------------------- */

:where(h1, h2, h3, h4) {
	text-wrap: balance;
}

:where(p) {
	text-wrap: pretty;
}

/* Slightly recede a label against a saturated band. */
.ld-dim {
	opacity: 0.72;
}

/* A text link that reads as a call to action without being a button. */
.ld-underline a {
	border-bottom: 2px solid var(--wp--preset--color--primary);
	padding-bottom: 4px;
	text-decoration: none;
}

.ld-underline a:hover {
	border-bottom-color: var(--wp--preset--color--primary-deep);
	text-decoration: underline;
	text-underline-offset: 3px;
}

.ld-measure-13 { max-width: 13ch; }
.ld-measure-16 { max-width: 16ch; }
.ld-measure-18 { max-width: 18ch; }
.ld-measure-20 { max-width: 20ch; }
.ld-measure-22 { max-width: 22ch; }
.ld-measure-46 { max-width: 46ch; }
.ld-measure-52 { max-width: 52ch; }
.ld-measure-58 { max-width: 58ch; }
.ld-measure-60 { max-width: 60ch; }
.ld-measure-70 { max-width: 70ch; }

/* --- Media -------------------------------------------------------------- */

/* Portraits fill their column but must not dictate the section's height. The
   design has them stretch to the copy, not the other way round. Both are shot
   with the head about a tenth of the way down, so the crop is biased upward
   to keep the face in frame at every viewport. */
.ld-hero-media {
	height: 100%;
}

/* Qualified with .wp-block-image: core's own `.wp-block-image img` rule ties
   a bare `.ld-hero-media img` on specificity and wins on source order, so the
   height silently falls back to the image's natural ratio. */
.wp-block-image.ld-hero-media img {
	height: clamp(340px, 58vh, 620px);
	object-position: 50% 28%;
}

.wp-block-image.ld-about-media img {
	height: clamp(380px, 62vh, 660px);
	object-position: 50% 16%;
}

.ld-media img {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
}

/* --- Buttons ------------------------------------------------------------
   Core's is-style-outline sets its own padding (0.667em) at a specificity
   that beats theme.json, so an outline button renders ~10px shorter than a
   filled one sitting next to it. Restore the theme.json rhythm on both, then
   add the design's hover states - the filled ones deepen, the outline ones
   fill in.
   ---------------------------------------------------------------------- */

.wp-block-buttons .wp-block-button.is-style-outline > .wp-block-button__link {
	padding-top: 1rem;
	padding-bottom: 1rem;
	padding-left: 1.75rem;
	padding-right: 1.75rem;
}

.wp-block-button__link {
	transition:
		background-color 120ms ease,
		border-color 120ms ease,
		color 120ms ease;
}

/* Outline buttons fill with ink on hover.
   The text colour needs !important: WordPress emits its preset colour
   utilities (.has-contrast-color) with !important, so a plain declaration
   here loses and the label stays ink-on-ink - invisible. */
.wp-block-buttons .wp-block-button.is-style-outline > .wp-block-button__link:hover,
.wp-block-buttons .wp-block-button.is-style-outline > .wp-block-button__link:focus-visible {
	background-color: var(--wp--preset--color--contrast);
	border-color: var(--wp--preset--color--contrast);
	color: var(--wp--preset--color--base) !important;
}

/* The header CTA is already ink, so it fills rust instead. */
.ld-header .wp-block-button__link:hover,
.ld-header .wp-block-button__link:focus-visible {
	background-color: var(--wp--preset--color--primary) !important;
	border-color: var(--wp--preset--color--primary);
	color: var(--wp--preset--color--base) !important;
}

/* On the rust band: the ink button deepens to true black, and the outline
   one veils rather than filling - an ink fill would fight the band. */
#audit .wp-block-button__link.has-contrast-background-color:hover,
#audit .wp-block-button__link.has-contrast-background-color:focus-visible {
	background-color: var(--wp--custom--hover--ink-deep) !important;
	border-color: var(--wp--custom--hover--ink-deep);
}

#audit .wp-block-button.is-style-outline > .wp-block-button__link:hover,
#audit .wp-block-button.is-style-outline > .wp-block-button__link:focus-visible {
	background-color: var(--wp--custom--hover--veil) !important;
	border-color: var(--wp--preset--color--shell);
	color: var(--wp--preset--color--shell) !important;
}

/* --- Gravity Forms -----------------------------------------------------
   GF 2.9 renders with the "Orbital" theme, which is driven by a documented
   CSS custom-property palette rather than by flat classes. Remapping those
   variables onto the theme.json presets is the upgrade-safe way to restyle
   it - GF can change its markup without breaking this. The explicit rules
   underneath only cover typography and the few things the palette does not
   reach.
   ---------------------------------------------------------------------- */

.ld-form .gform_wrapper.gform-theme,
.ld-form .gform_wrapper.gform-theme--orbital {
	/* Accent - buttons, active states. */
	--gf-color-primary: var(--wp--preset--color--primary);
	--gf-color-primary-rgb: 184, 65, 14;
	--gf-color-primary-contrast: var(--wp--preset--color--shell);
	--gf-color-primary-contrast-rgb: 255, 246, 241;
	--gf-color-primary-darker: var(--wp--preset--color--primary-deep);
	--gf-color-primary-lighter: var(--wp--preset--color--brand);

	/* Inside controls - input wells. */
	--gf-color-in-ctrl: var(--wp--preset--color--ink-raised);
	--gf-color-in-ctrl-rgb: 27, 25, 23;
	--gf-color-in-ctrl-contrast: var(--wp--preset--color--base);
	--gf-color-in-ctrl-contrast-rgb: 247, 245, 242;
	--gf-color-in-ctrl-darker: var(--wp--preset--color--contrast);
	--gf-color-in-ctrl-lighter: var(--wp--preset--color--ink-raised);
	--gf-color-in-ctrl-light: var(--wp--preset--color--ink-line);
	--gf-color-in-ctrl-light-darker: var(--wp--preset--color--ink-line);
	--gf-color-in-ctrl-light-lighter: var(--wp--preset--color--ink-line);
	--gf-color-in-ctrl-dark: var(--wp--preset--color--on-dark-mute);
	--gf-color-in-ctrl-dark-darker: var(--wp--preset--color--on-dark);
	--gf-color-in-ctrl-dark-lighter: var(--wp--preset--color--on-dark-mute);
	--gf-color-in-ctrl-primary: var(--wp--preset--color--brand);
	--gf-color-in-ctrl-primary-contrast: var(--wp--preset--color--shell);
	--gf-color-in-ctrl-primary-darker: var(--wp--preset--color--primary-deep);

	/* Outside controls - labels, descriptions, rules. */
	--gf-color-out-ctrl: var(--wp--preset--color--contrast);
	--gf-color-out-ctrl-contrast: var(--wp--preset--color--base);
	--gf-color-out-ctrl-dark: var(--wp--preset--color--on-dark-mute);
	--gf-color-out-ctrl-dark-darker: var(--wp--preset--color--base);
	--gf-color-out-ctrl-dark-lighter: var(--wp--preset--color--on-dark-mute);
	--gf-color-out-ctrl-light: var(--wp--preset--color--ink-line);
	--gf-color-out-ctrl-light-darker: var(--wp--preset--color--ink-line);
	--gf-color-out-ctrl-light-lighter: var(--wp--preset--color--ink-line);

	/* Validation reads in the logo orange, which clears AA on the dark band. */
	--gf-color-danger: var(--wp--preset--color--brand);
	--gf-color-danger-contrast: var(--wp--preset--color--contrast);
	--gf-color-danger-darker: var(--wp--preset--color--primary-deep);
	--gf-color-danger-lighter: var(--wp--preset--color--brand);

	/* Button controls read from their own --gf-ctrl-btn-* family. */
	--gf-ctrl-btn-bg-color-primary: var(--wp--preset--color--primary);
	--gf-ctrl-btn-bg-color-hover-primary: var(--wp--preset--color--brand);
	--gf-ctrl-btn-bg-color-focus-primary: var(--wp--preset--color--brand);
	--gf-ctrl-btn-color-primary: var(--wp--preset--color--shell);
	--gf-ctrl-btn-border-color-primary: var(--wp--preset--color--primary);
	--gf-ctrl-btn-border-color-hover-primary: var(--wp--preset--color--brand);

	/* Square corners, matching every other control in the design. */
	--gf-ctrl-radius: 0;
	--gf-ctrl-btn-radius: 0;
	--gf-ctrl-checkbox-radius: 0;
	--gf-field-gap-y: 1.125rem;
	--gf-field-gap-x: 1.125rem;
	--gf-form-gap-y: 1.125rem;
}

/* Labels take the mono eyebrow treatment used everywhere else. */
.ld-form .gform_wrapper .gfield_label,
.ld-form .gform_wrapper .gform-field-label {
	font-family: var(--wp--preset--font-family--mono);
	font-size: var(--wp--preset--font-size--eyebrow);
	font-weight: 400;
	letter-spacing: var(--wp--custom--letter-spacing--mono);
	text-transform: uppercase;
	color: var(--wp--preset--color--on-dark-mute);
	margin-bottom: 0.5rem;
}

.ld-form .gform_wrapper .gfield_required {
	color: var(--wp--preset--color--brand);
	font-family: var(--wp--preset--font-family--mono);
	letter-spacing: 0;
}

.ld-form .gform_wrapper.gform-theme--orbital :where(input, textarea, select) {
	background-color: var(--wp--preset--color--ink-raised);
	border: 1px solid var(--wp--preset--color--ink-line);
	border-radius: 0;
	color: var(--wp--preset--color--base);
	font-family: var(--wp--preset--font-family--heading);
	font-size: var(--wp--preset--font-size--medium);
	padding: 0.875rem;
}

.ld-form .gform_wrapper.gform-theme--orbital :where(input, textarea)::placeholder {
	color: var(--wp--preset--color--on-dark-mute);
	opacity: 1;
}

.ld-form .gform_wrapper.gform-theme--orbital :where(input, textarea, select):focus {
	border-color: var(--wp--preset--color--brand);
	outline: 2px solid var(--wp--preset--color--brand);
	outline-offset: 1px;
	box-shadow: none;
}

.ld-form .gform_wrapper.gform-theme--orbital textarea {
	min-height: 7.5rem;
	resize: vertical;
}

.ld-form .gform_wrapper.gform-theme--orbital .gform_footer :where(input, button).gform_button,
.ld-form .gform_wrapper.gform-theme--orbital input[type="submit"].gform_button,
.ld-form .gform_wrapper.gform-theme--orbital button.gform_button {
	--gf-local-bg-color: var(--wp--preset--color--primary);
	--gf-local-color: var(--wp--preset--color--shell);
	--gf-local-border-color: var(--wp--preset--color--primary);
	background-color: var(--wp--preset--color--primary);
	border: 1px solid var(--wp--preset--color--primary);
	border-radius: 0;
	color: var(--wp--preset--color--shell);
	cursor: pointer;
	font-family: var(--wp--preset--font-family--heading);
	font-size: var(--wp--preset--font-size--medium);
	font-weight: 600;
	padding: 1.0625rem 1.75rem;
	width: 100%;
	transition: background-color 120ms ease, border-color 120ms ease;
}

.ld-form .gform_wrapper.gform-theme--orbital .gform_footer :where(input, button).gform_button:hover,
.ld-form .gform_wrapper.gform-theme--orbital input[type="submit"].gform_button:hover,
.ld-form .gform_wrapper.gform-theme--orbital button.gform_button:hover,
.ld-form .gform_wrapper.gform-theme--orbital input[type="submit"].gform_button:focus,
.ld-form .gform_wrapper.gform-theme--orbital button.gform_button:focus {
	--gf-local-bg-color: var(--wp--preset--color--brand);
	--gf-local-border-color: var(--wp--preset--color--brand);
	background-color: var(--wp--preset--color--brand);
	border-color: var(--wp--preset--color--brand);
}

.ld-form .gform_wrapper.gform-theme--orbital .gform_footer {
	display: block;
	padding: 0;
	margin: 0.25rem 0 0;
}

/* Orbital nests the submit inside a shrink-to-fit wrapper, so the wrapper has
   to be stretched before width:100% on the button means anything. */
.ld-form .gform_wrapper.gform-theme--orbital .gform_footer > * {
	display: block;
	width: 100%;
	max-width: none;
}

.ld-form .gform_wrapper.gform-theme--orbital .gform_footer :where(input, button).gform_button {
	width: 100%;
	max-width: none;
	justify-content: center;
	text-align: center;
}

.ld-form .gform_wrapper .gform_validation_errors {
	background: var(--wp--preset--color--ink-raised);
	border: 1px solid var(--wp--preset--color--brand);
	border-radius: 0;
	box-shadow: none;
}

.ld-form .gform_wrapper .gform_validation_errors > h2,
.ld-form .gform_wrapper .validation_message {
	color: var(--wp--preset--color--brand);
	font-size: var(--wp--preset--font-size--small);
}

.ld-form .gform_confirmation_message {
	color: var(--wp--preset--color--base);
	font-size: var(--wp--preset--font-size--x-large);
	line-height: var(--wp--custom--line-height--body);
	border-left: 3px solid var(--wp--preset--color--brand);
	padding-left: var(--wp--preset--spacing--50);
}

/* Core's constrained layout gives EVERY child narrower than the content width
   `margin-left: auto !important; margin-right: auto !important`, which centres
   it. A measure class exists precisely to make an element narrower than its
   container, so the two combine to centre every constrained paragraph and
   heading that carries one, while the eyebrow and buttons beside it stay left.

   On the homepage this never showed, because those elements sit inside
   core/column, which is flow layout. The interior page sections put them
   directly inside a constrained group, so it appeared everywhere at once.

   The same auto margins bite a second way in any constrained group that has
   been turned into a flex column: in flexbox an auto cross-axis margin stops
   the item stretching and centres it at its content width instead, so the
   category card headings sat centred above left-aligned body copy.

   Core's rule is `.is-layout-constrained > :where(...)`, which is one class
   plus !important. These selectors tie it on specificity and win on source
   order, because the theme stylesheet is enqueued after the inline global
   styles.

   This must NOT be pointed at every constrained child. On a full-bleed
   section those same auto margins are what centre the 1280px content column,
   so zeroing them there drags the element out to the section edge instead.
   The section emitters solve that structurally, with an inner flow-layout
   group that takes the auto margins and becomes the column. What is left
   below are the containers that are already narrower than the content width,
   where the margins centre but position nothing. */
.ld-cat__body > *,
.ld-ctaband__copy > *,
.ld-emergency-band__copy > * {
	margin-left: 0 !important;
	margin-right: 0 !important;
}


/* --- Interior service pages ---------------------------------------------
   Everything below serves the pages built by build/make-pages.php. The
   emitters in inc/service-blocks.php name these classes; keep the two in
   step.
   ---------------------------------------------------------------------- */

/* The interior hero reuses the homepage hero's photo and scrim mechanism via
   .ld-hero, so it only needs its own stacking context for the copy. */
.ld-page-hero__body {
	position: relative;
	z-index: 1;
}

/* Breadcrumb. The separators are the literal " / " in the text, so there is
   nothing to style but the emphasis on the current page. */
.ld-crumbs strong {
	color: var(--wp--preset--color--base);
	font-weight: 700;
}

.ld-crumbs a {
	color: inherit;
}

.ld-crumbs a:hover {
	color: var(--wp--preset--color--base);
	text-decoration: underline;
	text-underline-offset: 3px;
}

/* A chip on its own line has to shrink to its label rather than fill the
   column, which a block-level paragraph would do. */
.ld-chip--solo {
	display: inline-block;
	width: fit-content;
}

/* --- Hero "at a glance" panel -------------------------------------------
   An outlined box beside the headline carrying the two or three numbers a
   visitor wants before reading anything. Only some service pages use it,
   which is deliberate: four pages built from one skeleton need something to
   tell them apart.
   ---------------------------------------------------------------------- */

.ld-glance {
	border: 1px solid rgba(255, 255, 255, 0.18);
	border-radius: var(--wp--custom--radius--panel);
	align-self: center;

	/* Same stacking context the hero copy gets. Without it the panel sits
	   under the scrim that ::after paints over the photo, and every value in
	   it renders washed out even though the colours are correct. */
	position: relative;
	z-index: 1;
}

/* The hero copy and the panel become a pair only when a panel is present.
   `:has()` keeps that decision in CSS rather than needing two hero emitters. */
.ld-page-hero .wp-block-group:has(> .ld-glance) {
	display: grid;
	grid-template-columns: minmax(0, 1.5fr) minmax(0, 1fr);
	gap: var(--wp--preset--spacing--90);
	align-items: center;
}

@media (max-width: 781px) {
	.ld-page-hero .wp-block-group:has(> .ld-glance) {
		grid-template-columns: minmax(0, 1fr);
		gap: var(--wp--preset--spacing--80);
	}
}

/* --- Rule grid ----------------------------------------------------------
   Cards under a coloured rule with no box, so a page can carry two list
   sections without them reading as the same component twice. The rule and
   padding are block attributes; nothing needed here but the measure reset,
   which the shared rule above already covers.
   ---------------------------------------------------------------------- */

/* --- Note panel and related cards --------------------------------------- */

.ld-note-panel {
	border-radius: var(--wp--custom--radius--panel);
}

/* --- Before and after --------------------------------------------------- */

.wp-block-image.ld-ba-media img {
	height: clamp(240px, 34vh, 340px);
	object-fit: cover;
	border-radius: var(--wp--custom--radius--card);
}

/* --- Trust bar ---------------------------------------------------------- */

.ld-trustbar {
	border-bottom: 1px solid var(--wp--preset--color--line);
}

/* --- What we offer ------------------------------------------------------ */

/* The intro column tracks the reader down the card stack. Sticky needs a top
   offset clear of the sticky header, and it must not apply once the columns
   have stacked or it pins the intro over the cards. */
@media (min-width: 782px) {
	.ld-sticky-col {
		position: sticky;
		top: 120px;
		align-self: start;
	}
}

.ld-offer {
	border: 1px solid var(--wp--preset--color--line);
	border-radius: var(--wp--custom--radius--panel);
}

/* The card that leads to its own page is outlined in navy and lifts, so it
   reads as a destination rather than another description. */
.ld-offer--link {
	border-color: var(--wp--preset--color--primary);
	transition: transform 200ms ease;
}

.ld-offer--link:hover {
	transform: translateY(-3px);
}

.ld-offer__note {
	letter-spacing: 0.08em;
	text-transform: uppercase;
}

/* --- Who turns up ------------------------------------------------------- */

.wp-block-image.ld-team-media img {
	height: clamp(340px, 56vh, 520px);
	object-fit: cover;
	border-radius: var(--wp--custom--radius--panel);
}

.ld-pullquote {
	border-radius: var(--wp--custom--radius--card);
}

/* --- Recent work gallery ------------------------------------------------
   A feature tile beside two stacked, then a row of three. Grid rather than
   columns because the feature tile spans two rows, which a column layout
   cannot express.
   ---------------------------------------------------------------------- */

.ld-gallery {
	display: grid;
	grid-template-columns: minmax(0, 2fr) minmax(0, 1fr);
	grid-template-rows: 230px 230px;
	gap: var(--wp--preset--spacing--50);
}

.ld-gallery > .ld-gallery__item:first-child {
	grid-row: span 2;
}

.ld-gallery--row {
	grid-template-columns: repeat(3, minmax(0, 1fr));
	grid-template-rows: 200px;
}

.ld-gallery--row > .ld-gallery__item:first-child {
	grid-row: auto;
}

.ld-gallery__item {
	margin: 0;
	height: 100%;
	overflow: hidden;
	border-radius: var(--wp--custom--radius--card);
}

.wp-block-image.ld-gallery__item img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	border-radius: var(--wp--custom--radius--card);
}

@media (max-width: 781px) {
	.ld-gallery,
	.ld-gallery--row {
		grid-template-columns: minmax(0, 1fr);
		grid-template-rows: none;
	}

	.ld-gallery > .ld-gallery__item:first-child {
		grid-row: auto;
	}

	.ld-gallery__item {
		height: 220px;
	}
}

/* --- Service category cards --------------------------------------------- */

.ld-cat {
	border-radius: var(--wp--custom--radius--panel);
	overflow: hidden;
}

.ld-cat__media {
	margin: 0;
}

.ld-cat__media img {
	display: block;
	width: 100%;
	height: 230px;
	object-fit: cover;
	border-radius: 0;
}

/* The body grows so every card's read-more line sits on the same baseline
   however long the description runs. */
.ld-cat__body {
	display: flex;
	flex-direction: column;
	flex: 1;
}

.ld-cat .ld-cardlink {
	margin-top: auto;
}

/* The chips naming what a category covers. */
.ld-tag {
	background-color: var(--wp--preset--color--surface);
	border: 1px solid var(--wp--preset--color--line);
	border-radius: var(--wp--custom--radius--pill);
	padding: 8px 15px;
}

/* --- Urgent work band --------------------------------------------------- */

.ld-emergency-band {
	border-radius: var(--wp--custom--radius--panel);
}

/* The copy has to be allowed to share the row, or it takes the full width of
   the flex line and pushes the phone button onto its own row underneath. The
   design has them side by side, with the button vertically centred against the
   heading. The basis is the point below which they should stack. */
.ld-emergency-band__copy {
	flex: 1 1 30rem;
}

/* --- How we work steps -------------------------------------------------- */

.ld-step {
	border-top-style: solid;
}

/* --- Closing call to action --------------------------------------------- */

.ld-ctaband__copy {
	flex: 1 1 420px;
}

/* The two buttons stack rather than sitting side by side, which is what the
   design does and what keeps them the same width. */
.ld-btn-stack {
	flex-direction: column;
	align-items: stretch;
}

.ld-btn-stack .wp-block-button__link {
	display: block;
	text-align: center;
}

@media (max-width: 781px) {
	.ld-ctaband {
		padding: var(--wp--preset--spacing--80) !important;
	}
}

/* =========================================================================
   LADUCA homepage sections
   Everything below resolves to theme.json presets. Corner radii come from
   --wp--custom--radius--*, so a fork changes the shape language in one place.
   ========================================================================= */

/* --- Shared ------------------------------------------------------------- */

/* Paragraph style "Section label": small capitals with a short red rule. */
p.is-style-eyebrow {
	display: flex;
	align-items: center;
	gap: 12px;
	font-size: var(--wp--preset--font-size--eyebrow);
	font-weight: 700;
	letter-spacing: var(--wp--custom--letter-spacing--eyebrow);
	line-height: 1.3;
	text-transform: uppercase;
	color: var(--wp--preset--color--primary-text);
}

p.is-style-eyebrow::before {
	content: "";
	flex: none;
	width: 28px;
	height: 2px;
	background: var(--wp--preset--color--primary);
}

p.is-style-eyebrow.has-text-align-center {
	justify-content: center;
}

.ld-dark p.is-style-eyebrow {
	color: var(--wp--preset--color--brand);
}

.ld-dark p.is-style-eyebrow::before {
	background: var(--wp--preset--color--brand);
}

/* Group style "Leaf corners": top left and bottom right rounded. */
.wp-block-group.is-style-leaf {
	border-radius: var(--wp--custom--radius--leaf) 0 var(--wp--custom--radius--leaf) 0;
	overflow: hidden;
}

/* Text links that act as a call to action read heavier than body links. */
.ld-textlink a,
.ld-textlinks a,
.ld-event__link a {
	font-weight: 600;
}

/* Two-column sections: a wider gutter than core's 2em, and no trailing
   margin under the columns block. */
.wp-block-columns.ld-split,
.wp-block-columns.ld-about__intro {
	gap: clamp(2.5rem, 6vw, 6rem);
	margin-bottom: 0;
}

/* The heading row above a card grid caps its copy so the link can sit at
   the right on the same baseline. */
.ld-headrow__copy {
	max-width: 680px;
}

/* On navy, headings go white and plain links go pale. Buttons keep their
   own colours, and the white portal card keeps ink. */
.ld-dark :where(h1, h2, h3, h4) {
	color: var(--wp--preset--color--on-dark-strong);
}

.ld-dark a:where(:not(.wp-element-button)) {
	color: var(--wp--preset--color--on-dark);
}

.ld-dark a:where(:not(.wp-element-button)):hover {
	color: var(--wp--preset--color--shell);
}

.ld-dark :where(a, button, input, textarea, summary):focus-visible {
	outline-color: var(--wp--preset--color--brand);
}

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

/* Outline buttons: a fine ink border at the same height as a filled one. */
.wp-block-buttons .wp-block-button.is-style-outline > .wp-block-button__link {
	border: 1.5px solid var(--wp--preset--color--contrast);
	color: var(--wp--preset--color--contrast);
	padding-top: calc(0.95rem - 1.5px);
	padding-bottom: calc(0.95rem - 1.5px);
	border-radius: var(--wp--custom--radius--button);
}

.ld-dark .wp-block-buttons .wp-block-button.is-style-outline > .wp-block-button__link {
	border-color: var(--wp--preset--color--shell);
	color: var(--wp--preset--color--shell);
}

.ld-dark .wp-block-buttons .wp-block-button.is-style-outline > .wp-block-button__link:hover,
.ld-dark .wp-block-buttons .wp-block-button.is-style-outline > .wp-block-button__link:focus-visible {
	background-color: var(--wp--custom--hover--veil);
	border-color: var(--wp--preset--color--shell);
	color: var(--wp--preset--color--shell) !important;
}

/* A navy button deepens rather than turning red on hover. */
.wp-block-button__link.has-band-background-color:hover,
.wp-block-button__link.has-band-background-color:focus-visible {
	background-color: var(--wp--custom--hover--ink-deep) !important;
}

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

.ld-header {
	background: var(--wp--preset--color--base);
	border-bottom-color: var(--wp--preset--color--line);
}

.ld-brand .wp-block-site-title {
	margin: 0;
}

.ld-brand .wp-block-site-title a {
	color: var(--wp--preset--color--contrast);
	text-decoration: none;
}

.ld-tagline {
	max-width: 140px;
	margin: 0;
	padding-left: 14px;
	border-left: 1px solid var(--wp--preset--color--field-line);
	color: var(--wp--preset--color--ink-muted);
	font-size: var(--wp--preset--font-size--x-small);
	line-height: 1.25;
}

.ld-nav {
	font-size: var(--wp--preset--font-size--medium);
}

.ld-nav .wp-block-navigation-item__content:hover {
	text-decoration: none;
}

.ld-header__login a {
	display: inline-flex;
	align-items: center;
	min-height: 44px;
	color: var(--wp--preset--color--contrast);
	font-weight: 600;
	text-decoration: none;
}

.ld-header__login a:hover {
	color: var(--wp--preset--color--primary-text);
}

.ld-btn-compact > .wp-block-button__link {
	padding: 0.8rem 1.4rem;
	font-size: var(--wp--preset--font-size--medium);
}

/* The starter fills the header button with the primary colour on hover,
   but here it is already primary, so it deepens instead. */
.ld-header .wp-block-button__link:hover,
.ld-header .wp-block-button__link:focus-visible {
	background-color: var(--wp--preset--color--primary-deep) !important;
	border-color: var(--wp--preset--color--primary-deep);
	color: var(--wp--preset--color--shell) !important;
}

/* The tagline would otherwise crowd the menu button on a phone. */
@media (max-width: 599px) {
	.ld-tagline {
		display: none;
	}

	.ld-header__login {
		display: none;
	}
}

/* --- Hero: photo with overlapping panels -------------------------------- */

.ld-hero {
	padding-inline: clamp(0px, 2vw, 24px);
}

.ld-hero .ld-hero__photo {
	margin: 0;
}

.wp-block-image.ld-hero__photo img {
	display: block;
	width: 100%;
	height: clamp(260px, 34vw, 500px);
	object-fit: cover;
	object-position: center 55%;
	border-radius: 0 0 var(--wp--custom--radius--leaf) var(--wp--custom--radius--leaf);
}

.wp-block-columns.ld-hero__panels {
	position: relative;
	box-sizing: border-box;
	max-width: calc(var(--wp--style--global--content-size) + var(--wp--style--root--padding-left) + var(--wp--style--root--padding-right));
	margin: clamp(-200px, -12vw, -60px) auto 0;
	padding-inline: var(--wp--style--root--padding-left) var(--wp--style--root--padding-right);
	gap: var(--wp--preset--spacing--50);
	align-items: flex-start !important;
}

/* Two equal halves, as in the design: the intro takes one, and the login card
   sits at the far end of the other. Core's flex rules zero the card's margin,
   hence the extra specificity on margin-top. */
@media (min-width: 782px) {
	.wp-block-columns.ld-hero__panels > .ld-hero__intro {
		box-sizing: border-box;
		flex: 0 1 calc(50% - var(--wp--preset--spacing--50) / 2);
	}

	.wp-block-columns.ld-hero__panels > .ld-hero__login {
		margin-top: clamp(0px, 4vw, 56px);
		margin-left: auto;
	}
}

.ld-hero__intro {
	background: var(--wp--preset--color--base);
	border-radius: var(--wp--custom--radius--leaf) 0 0 0;
	padding: clamp(32px, 5vw, 64px) clamp(24px, 4vw, 56px) var(--wp--preset--spacing--50);
}

.ld-hero__login {
	box-sizing: border-box;
	max-width: 460px;
	padding: clamp(28px, 4vw, 44px);
	background: var(--wp--preset--color--base);
	border: 1px solid var(--wp--preset--color--line);
	border-radius: 0 var(--wp--custom--radius--leaf) 0 0;
}

@media (max-width: 781px) {
	.ld-hero__login {
		max-width: none;
		margin-top: 0;
		border-radius: 0;
	}
}

/* Core's Login/out block, shown as a form. */
.ld-login form > p {
	display: flex;
	flex-direction: column;
	gap: 6px;
	margin: 0 0 var(--wp--preset--spacing--40);
}

.ld-login label {
	font-size: var(--wp--preset--font-size--small);
	font-weight: 600;
}

.ld-login input.input {
	box-sizing: border-box;
	width: 100%;
	height: 48px;
	padding: 0 14px;
	background: var(--wp--preset--color--base);
	border: 1px solid var(--wp--preset--color--field-line);
	border-radius: var(--wp--custom--radius--field);
	color: var(--wp--preset--color--contrast);
	font: inherit;
	font-size: var(--wp--preset--font-size--small);
	line-height: 1.2;
}

.ld-login input.input:focus {
	outline: 2px solid var(--wp--preset--color--primary);
	outline-offset: 1px;
}

.ld-login .login-remember {
	display: none;
}

.ld-login form > p.login-submit {
	margin-bottom: 0;
}

.ld-login input[type="submit"] {
	width: 100%;
	min-height: 50px;
	border: 0;
	border-radius: var(--wp--custom--radius--button);
	background: var(--wp--preset--color--band);
	color: var(--wp--preset--color--shell);
	font: inherit;
	font-weight: 600;
	cursor: pointer;
}

.ld-login input[type="submit"]:hover,
.ld-login input[type="submit"]:focus-visible {
	background: var(--wp--custom--hover--ink-deep);
}

/* --- About: icon pillars ------------------------------------------------ */

.ld-icon {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 52px;
	height: 52px;
	border-radius: 50%;
	background: var(--wp--preset--color--tint);
	color: var(--wp--preset--color--primary-text);
}

/* --- Ticked list -------------------------------------------------------- */

.ld-checklist {
	display: flex;
	flex-direction: column;
	gap: 18px;
	margin: 0;
	padding: 0;
	list-style: none;
}

.ld-checklist li {
	position: relative;
	padding-left: 38px;
}

.ld-checklist li::before {
	content: "";
	position: absolute;
	left: 0;
	top: 2px;
	width: 24px;
	height: 24px;
	background: var(--wp--preset--color--primary);
	-webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2'%3E%3Cpath d='M5 12l5 5L19 7'/%3E%3C/svg%3E") center / 24px no-repeat;
	mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='2'%3E%3Cpath d='M5 12l5 5L19 7'/%3E%3C/svg%3E") center / 24px no-repeat;
}

.ld-checklist strong {
	font-weight: 600;
}

.ld-dark .ld-checklist li::before {
	background: var(--wp--preset--color--brand);
}

.ld-dark .ld-checklist strong {
	color: var(--wp--preset--color--on-dark-strong);
}

/* --- Portal preview card ------------------------------------------------ */

.ld-portal {
	overflow: hidden;
	background: var(--wp--preset--color--base);
	border-radius: 0 var(--wp--custom--radius--leaf) 0 var(--wp--custom--radius--leaf);
	color: var(--wp--preset--color--contrast);
	font-size: var(--wp--preset--font-size--small);
}

.ld-portal p {
	margin: 0;
}

.ld-portal__top {
	gap: 12px;
	padding: 20px 28px;
	border-bottom: 1px solid var(--wp--preset--color--line);
}

.ld-portal__hello {
	font-family: var(--wp--preset--font-family--heading);
	font-size: 1.25rem;
	font-weight: 500;
}

.ld-portal__tabs {
	row-gap: 4px;
	padding: 0 28px;
	border-bottom: 1px solid var(--wp--preset--color--line);
	color: var(--wp--preset--color--ink-muted);
	font-size: var(--wp--preset--font-size--small);
	font-weight: 600;
}

.ld-portal__tabs p {
	padding: 14px 0;
	border-bottom: 2px solid transparent;
}

.ld-portal__tabs p.is-active {
	border-bottom-color: var(--wp--preset--color--primary);
	color: var(--wp--preset--color--contrast);
}

.ld-portal__body {
	padding: var(--wp--preset--spacing--50) 28px 28px;
}

.ld-portal__next {
	padding: 18px;
	border-radius: var(--wp--custom--radius--badge);
	background: var(--wp--preset--color--surface);
}

.ld-portal__event {
	min-width: 0;
}

.ld-portal__status {
	margin-left: auto !important;
	color: var(--wp--preset--color--success);
	font-size: var(--wp--preset--font-size--x-small);
	font-weight: 600;
}

.ld-label {
	color: var(--wp--preset--color--ink-muted);
	font-size: 0.75rem;
	font-weight: 700;
	letter-spacing: 0.1em;
	text-transform: uppercase;
}

.ld-files > .ld-label {
	margin-bottom: 10px !important;
}

.ld-file {
	gap: 12px;
	padding: 12px 0;
	border-bottom: 1px solid var(--wp--preset--color--line);
}

.ld-file:last-child {
	border-bottom: 0;
}

.ld-file > p:first-child {
	display: flex;
	align-items: center;
	gap: 12px;
}

.ld-file > p:first-child::before {
	content: "";
	flex: none;
	width: 20px;
	height: 20px;
	background: var(--wp--preset--color--ink-muted);
	-webkit-mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.7'%3E%3Cpath d='M6 3h9l4 4v14H6z'/%3E%3Cpath d='M14 3v5h5'/%3E%3C/svg%3E") center / 20px no-repeat;
	mask: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='black' stroke-width='1.7'%3E%3Cpath d='M6 3h9l4 4v14H6z'/%3E%3Cpath d='M14 3v5h5'/%3E%3C/svg%3E") center / 20px no-repeat;
}

.ld-file__type {
	flex: none;
	color: var(--wp--preset--color--ink-muted);
	font-size: var(--wp--preset--font-size--x-small);
}

/* --- Chips and date badges ---------------------------------------------- */

p.ld-chip {
	flex: none;
	margin: 0;
	padding: 4px 12px;
	border-radius: var(--wp--custom--radius--pill);
	background: var(--wp--preset--color--surface);
	color: var(--wp--preset--color--ink-soft);
	font-size: var(--wp--preset--font-size--x-small);
	font-weight: 600;
	line-height: 1.4;
}

p.ld-chip--ok {
	background: var(--wp--preset--color--success-tint);
	color: var(--wp--preset--color--success);
}

.ld-datebadge {
	flex: none;
	overflow: hidden;
	width: 64px;
	background: var(--wp--preset--color--base);
	border: 1px solid var(--wp--preset--color--line);
	border-radius: var(--wp--custom--radius--button);
	text-align: center;
}

.ld-datebadge p {
	margin: 0;
}

.ld-datebadge__mon {
	padding: 3px 0;
	background: var(--wp--preset--color--primary);
	color: var(--wp--preset--color--shell);
	font-size: 0.75rem;
	font-weight: 700;
	letter-spacing: 0.1em;
	line-height: 1.4;
}

.ld-datebadge__day {
	padding: 4px 0;
	font-family: var(--wp--preset--font-family--heading);
	font-size: 1.625rem;
	line-height: 1.3;
}

/* --- Numbered steps ----------------------------------------------------- */

.ld-vstep {
	position: relative;
}

.ld-vstep:not(:last-child)::before {
	content: "";
	position: absolute;
	left: 23px;
	top: 48px;
	bottom: 0;
	width: 2px;
	background: var(--wp--preset--color--line);
}

p.ld-vstep__num {
	position: relative;
	z-index: 1;
	display: flex;
	flex: none;
	align-items: center;
	justify-content: center;
	box-sizing: border-box;
	width: 48px;
	height: 48px;
	margin: 0;
	background: var(--wp--preset--color--base);
	border: 2px solid var(--wp--preset--color--primary);
	border-radius: 50%;
	color: var(--wp--preset--color--primary-text);
	font-family: var(--wp--preset--font-family--heading);
	font-size: 1.25rem;
}

.ld-vstep__body {
	padding: 8px 0 40px;
}

.ld-vstep:last-child .ld-vstep__body {
	padding-bottom: 0;
}

/* --- Card grids --------------------------------------------------------- */

.ld-event {
	display: flex;
	flex-direction: column;
	padding: 28px;
	background: var(--wp--preset--color--base);
	border-radius: 0 var(--wp--custom--radius--card) 0 var(--wp--custom--radius--card);
}

.ld-event__top {
	gap: 12px;
}

.ld-event .ld-datebadge {
	width: 68px;
}

.ld-event .ld-datebadge__mon {
	padding: 4px 0;
}

.ld-event .ld-datebadge__day {
	padding: 6px 0;
	font-size: 1.75rem;
}

.ld-meta {
	display: grid;
	gap: 4px;
	font-size: var(--wp--preset--font-size--small);
}

.ld-meta p {
	margin: 0;
}

.ld-meta__key {
	display: inline-block;
	min-width: 4.5rem;
	color: var(--wp--preset--color--ink-muted);
}

/* The link sits on the card's bottom edge whatever the title length. */
.ld-event__link {
	margin-top: auto !important;
	padding-top: var(--wp--preset--spacing--40);
}

.ld-person {
	padding: 22px;
	background: var(--wp--preset--color--base);
	border-radius: 0 var(--wp--custom--radius--panel) 0 var(--wp--custom--radius--panel);
}

p.ld-person__initials {
	display: flex;
	flex: none;
	align-items: center;
	justify-content: center;
	width: 64px;
	height: 64px;
	margin: 0;
	background: var(--wp--preset--color--band);
	border-radius: 0 var(--wp--custom--radius--panel) 0 var(--wp--custom--radius--panel);
	color: var(--wp--preset--color--shell);
	font-family: var(--wp--preset--font-family--heading);
	font-size: 1.375rem;
}

.ld-person__text {
	min-width: 0;
}

.ld-person__text h3 {
	font-size: 1.25rem;
}

.ld-person__org {
	color: var(--wp--preset--color--primary-text);
	font-size: var(--wp--preset--font-size--small);
	font-weight: 600;
}

/* --- Upcoming events block (laduca/upcoming-events) -------------------- */

/* The block prints a plain list, so the grid, the card's inner spacing and the
   date badge's spans are set here rather than by block layout. */
.ld-upcoming__list {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(min(100%, 320px), 1fr));
	gap: var(--wp--preset--spacing--50);
	margin: 0;
	padding: 0;
	list-style: none;
}

.ld-upcoming .ld-event {
	gap: var(--wp--preset--spacing--40);
}

.ld-upcoming .ld-event > * {
	margin: 0;
}

.ld-upcoming .ld-event__top {
	display: flex;
	align-items: flex-start;
	justify-content: space-between;
}

.ld-upcoming .ld-datebadge time,
.ld-upcoming .ld-datebadge span {
	display: block;
}

.ld-upcoming .ld-datebadge__mon {
	text-transform: uppercase;
}

.ld-event__title {
	font-size: var(--wp--preset--font-size--card-title);
	line-height: 1.3;
}

.ld-event__title a {
	color: inherit;
	text-decoration: none;
}

.ld-event__title a:hover,
.ld-event__title a:focus-visible {
	color: var(--wp--preset--color--primary-text);
	text-decoration: underline;
}

.ld-upcoming .ld-meta div {
	display: flex;
	gap: 0;
}

.ld-upcoming .ld-meta dd {
	margin: 0;
}

.ld-upcoming__empty {
	max-width: 680px;
	margin: 0;
	padding: var(--wp--preset--spacing--60);
	background: var(--wp--preset--color--base);
	border-radius: 0 var(--wp--custom--radius--card) 0 var(--wp--custom--radius--card);
	color: var(--wp--preset--color--ink-soft);
}

.ld-upcoming__empty a {
	font-weight: 600;
}

/* --- Eventward: calendar, event pages and RSVP -------------------------- */

/* Eventward is deliberately bare and mixes its lines and tints from
   currentColor. These rules feed it the theme's tokens and shapes instead, so
   the calendar, event pages and booking form read as part of the site. */
.ew-calendar,
.ew-details {
	--ew-line: var(--wp--preset--color--line);
	--ew-control: var(--wp--preset--color--field-line);
	--ew-soft: var(--wp--preset--color--surface);
	--ew-tint: var(--wp--preset--color--line);
	--ew-muted: var(--wp--preset--color--ink-muted);
	--ew-radius: var(--wp--custom--radius--button);
	--ew-accent: var(--wp--preset--color--primary);
	--ew-on-accent: var(--wp--preset--color--shell);
}

.ew-calendar .ew-title,
.ew-calendar .ew-item-title,
.ew-calendar .ew-photo-title,
.ew-details .ew-section-title,
.ew-tickets > h2,
.ew-tickets > h3 {
	font-family: var(--wp--preset--font-family--heading);
	font-weight: 500;
	letter-spacing: 0;
}

.ew-calendar .ew-title {
	font-size: var(--wp--preset--font-size--subhead);
}

.ew-calendar .ew-group-label {
	color: var(--wp--preset--color--primary-text);
	font-size: var(--wp--preset--font-size--eyebrow);
	font-weight: 700;
	letter-spacing: var(--wp--custom--letter-spacing--eyebrow);
}

.ew-calendar .ew-item article {
	gap: var(--wp--preset--spacing--50);
	padding-block: var(--wp--preset--spacing--50);
}

.ew-calendar .ew-item-title {
	font-size: var(--wp--preset--font-size--card-title);
}

.ew-calendar .ew-item-title a:hover,
.ew-calendar .ew-photo-title a:hover {
	color: var(--wp--preset--color--primary-text);
}

/* The list's date badge matches the homepage cards: month in red. */
.ew-calendar .ew-badge {
	padding: 6px 0;
	background: var(--wp--preset--color--base);
	border-color: var(--wp--preset--color--line);
}

.ew-calendar .ew-badge-day {
	font-family: var(--wp--preset--font-family--heading);
	font-size: 1.625rem;
	font-weight: 400;
}

.ew-calendar .ew-badge-mon {
	color: var(--wp--preset--color--primary-text);
	font-weight: 700;
}

/* Today in the month grid. Eventward paints the circle with currentColor and
   the number with the page colour on the same element, so currentColor
   resolves to that page colour and the date disappears. */
.ew-calendar .ew-month .is-today .ew-day-num,
.ew-calendar .ew-month .is-today .ew-day-link:hover .ew-day-num,
.ew-calendar .ew-week-day.is-today .ew-week-num {
	background: var(--wp--preset--color--primary);
	color: var(--wp--preset--color--shell);
}

.ew-calendar .ew-day-events a {
	background: var(--wp--preset--color--surface);
	color: var(--wp--preset--color--contrast);
}

.ew-calendar .ew-day-events a:hover {
	background: var(--wp--preset--color--line);
}

.ew-calendar .ew-views a[aria-current] {
	background: var(--wp--preset--color--band);
	color: var(--wp--preset--color--shell);
}

.ew-calendar .ew-past-link a,
.ew-calendar .ew-pager a {
	color: var(--wp--preset--color--primary-text);
	font-weight: 600;
}

.ew-calendar .ew-empty {
	padding: var(--wp--preset--spacing--60);
	background: var(--wp--preset--color--surface);
	border: 0;
	border-radius: 0 var(--wp--custom--radius--card) 0 var(--wp--custom--radius--card);
	color: var(--wp--preset--color--ink-soft);
}

/* Event page: the stone band carries the back link, title and access tag. */
.ld-backlink a {
	color: inherit;
	text-decoration: none;
}

.ld-backlink a:hover,
.ld-backlink a:focus-visible {
	text-decoration: underline;
}

.ld-event-terms {
	display: flex;
	flex-wrap: wrap;
	gap: 8px;
	font-size: 0;
}

.ld-event-terms a {
	padding: 4px 12px;
	border-radius: var(--wp--custom--radius--pill);
	background: var(--wp--preset--color--base);
	color: var(--wp--preset--color--ink-soft);
	font-size: var(--wp--preset--font-size--x-small);
	font-weight: 600;
	text-decoration: none;
}

.ld-event-terms .wp-block-post-terms__separator {
	display: none;
}

.wp-block-columns.ld-event-layout {
	gap: clamp(2.5rem, 6vw, 5rem);
	margin-bottom: 0;
}

/* The details and booking form sit in a card beside the description. */
.ld-event-aside .ew-details {
	margin-block: 0;
	padding: clamp(24px, 3vw, 36px);
	background: var(--wp--preset--color--base);
	border: 1px solid var(--wp--preset--color--line);
	border-radius: 0 var(--wp--custom--radius--card) 0 var(--wp--custom--radius--card);
}

.ld-event-aside .ew-details .ew-facts {
	grid-template-columns: 1fr;
	gap: var(--wp--preset--spacing--50);
	padding-top: 0;
	border-top: 0;
}

.ld-event-aside .ew-details .ew-fact dt {
	color: var(--wp--preset--color--primary-text);
	font-size: var(--wp--preset--font-size--eyebrow);
	font-weight: 700;
	letter-spacing: var(--wp--custom--letter-spacing--eyebrow);
}

/* On a phone the date, place and booking form come before the description. */
@media (max-width: 781px) {
	.ld-event-aside {
		order: -1;
	}
}

@media (min-width: 782px) {
	.ld-event-aside {
		position: sticky;
		top: calc(var(--wp-admin--admin-bar--height, 0px) + 7rem);
	}
}

.ew-details .ew-button {
	min-height: 48px;
	padding: 0 1.25rem;
	border-color: var(--wp--preset--color--contrast);
	border-radius: var(--wp--custom--radius--button);
	font-size: var(--wp--preset--font-size--medium);
}

.ew-details .ew-button-primary {
	border-color: var(--wp--preset--color--primary);
	background: var(--wp--preset--color--primary);
	color: var(--wp--preset--color--shell);
}

.ew-details .ew-button-primary:hover,
.ew-details .ew-button-primary:focus-visible {
	border-color: var(--wp--preset--color--primary-deep);
	background: var(--wp--preset--color--primary-deep);
}

.ew-details .ew-ticket-types {
	background: var(--wp--preset--color--surface);
	border: 0;
}

.ew-details .ew-ticket-type select,
.ew-details .ew-ticket-buyer input,
.ew-details .ew-ticket-buyer select,
.ew-details .ew-ticket-buyer textarea {
	min-height: 48px;
	background: var(--wp--preset--color--base);
	border-color: var(--wp--preset--color--field-line);
	border-radius: var(--wp--custom--radius--field);
}

.ew-details .ew-ticket-buyer input:focus-visible,
.ew-details .ew-ticket-type select:focus-visible {
	outline-color: var(--wp--preset--color--primary);
}

.ew-details .ew-booking.is-ok {
	background: var(--wp--preset--color--success-tint);
	border-color: var(--wp--preset--color--success-tint);
	color: var(--wp--preset--color--contrast);
}

/* --- Photo with leaf corners and the price row -------------------------- */

.wp-block-image.ld-media-leaf {
	margin: 0;
}

.wp-block-image.ld-media-leaf img {
	display: block;
	width: 100%;
	aspect-ratio: 4 / 3;
	object-fit: cover;
	border-radius: var(--wp--custom--radius--leaf) 0 var(--wp--custom--radius--leaf) 0;
}

.ld-prices {
	column-gap: 48px !important;
	padding: var(--wp--preset--spacing--50) 0;
	border-top: 1px solid var(--wp--preset--color--line);
	border-bottom: 1px solid var(--wp--preset--color--line);
}

.ld-price p {
	margin: 0;
}

.ld-price__figure {
	font-family: var(--wp--preset--font-family--heading);
	font-size: var(--wp--preset--font-size--price);
	line-height: 1.1;
}

p.ld-prices__note {
	flex-basis: 100%;
	margin: 0;
}

/* --- Sponsor logos ------------------------------------------------------ */

.ld-logos {
	row-gap: var(--wp--preset--spacing--40) !important;
}

.wp-block-image.ld-logo-item {
	display: flex;
	align-items: center;
	justify-content: center;
	width: 180px;
	height: 96px;
	margin: 0;
}

.wp-block-image.ld-logo-item img {
	width: auto;
	max-width: 100%;
	height: auto;
	max-height: 60px;
}

/* --- Closing call to action --------------------------------------------- */

.ld-cta__panel {
	align-items: center;
	padding: clamp(40px, 6vw, 80px);
}

.ld-cta__copy {
	max-width: 680px;
}

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

.ld-footer a,
.ld-footer .wp-block-navigation-item__content {
	color: var(--wp--preset--color--on-dark);
	text-decoration: none;
}

.ld-footer a:hover,
.ld-footer .wp-block-navigation-item__content:hover {
	color: var(--wp--preset--color--shell);
}

.ld-footer__brand {
	color: var(--wp--preset--color--shell);
	font-family: var(--wp--preset--font-family--heading);
	font-size: 1.625rem;
	font-weight: 600;
	line-height: 1.2;
}

.ld-footer__heading {
	color: var(--wp--preset--color--shell);
	font-size: var(--wp--preset--font-size--eyebrow);
	font-weight: 700;
	letter-spacing: var(--wp--custom--letter-spacing--eyebrow);
	text-transform: uppercase;
}

.ld-footer__base {
	padding-top: var(--wp--preset--spacing--50);
	border-top: 1px solid var(--wp--preset--color--ink-line);
}

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

@media print {
	.ld-header,
	.ld-form,
	.wp-block-navigation {
		display: none !important;
	}
}
