/*
 * Bachmann visual system.
 *
 * Three signatures, all derived from the wordmark's oblique:
 *   1. the angled rule beneath headings and pillar names
 *   2. pillar questions set in oblique, so the angle marks the moment the
 *      company asks something
 *   3. skewed photo crops matched to the same slant
 *
 * Width, not typeface, separates Construction from Design Group.
 */

/* --------------------------------------------------------------------------
   1. Angled rule
   -------------------------------------------------------------------------- */
.is-style-angled-rule {
	position: relative;
	padding-bottom: var(--wp--preset--spacing--30);
}

.is-style-angled-rule::after {
	content: "";
	position: absolute;
	left: 0;
	bottom: 0;
	width: var(--wp--custom--rule--width);
	height: var(--wp--custom--rule--height);
	background-color: var(--wp--preset--color--primary);
	transform: skewX(var(--wp--custom--angle));
}

/* Centred headings get a centred rule. */
.is-style-angled-rule[style*="text-align:center"]::after,
.is-style-angled-rule.has-text-align-center::after {
	left: 50%;
	margin-left: calc(var(--wp--custom--rule--width) / -2);
}

/* --------------------------------------------------------------------------
   2. Pillar question
   The four questions are the campaign device. Oblique, never uppercase —
   they are meant to read as something spoken.
   -------------------------------------------------------------------------- */
.is-style-pillar-question {
	font-style: italic;
	font-stretch: var(--wp--custom--width--condensed);
	font-weight: 600;
	font-size: var(--wp--preset--font-size--x-large);
	line-height: 1.15;
	text-transform: none;
	letter-spacing: -0.01em;
	max-width: 20ch;
}

/* --------------------------------------------------------------------------
   3. Skewed crop
   -------------------------------------------------------------------------- */
.is-style-skewed-crop {
	--bachmann-skew: 3.5rem;
}

/*
 * The diagonal belongs to the image, not to its figure.
 *
 * Clipping the whole element also clipped anything else inside it. The pillar
 * lead puts a caption in the same figure, so the diagonal cut straight through
 * the caption text and lost the end of longer project names - "Edgerton
 * Community Outreach" arrived as "Edgerton Community Outreac".
 */
.is-style-skewed-crop img {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
	clip-path: polygon(0 0, 100% 0, 100% calc(100% - var(--bachmann-skew)), 0 100%);
}

/* --------------------------------------------------------------------------
   4. The two brand lockups
   Construction holds the incumbent condensed width. Design Group opens up:
   lighter, upright, wide-tracked. The typography study warns that moving
   weight, slant and tracking at once reads as a different company, so the
   angled rule is carried through as the anchoring family signature.
   -------------------------------------------------------------------------- */
.brand-construction {
	font-stretch: var(--wp--custom--width--condensed);
	font-weight: 800;
	font-style: italic;
	text-transform: uppercase;
	letter-spacing: -0.005em;
}

.brand-design-group,
.is-style-design-group {
	font-stretch: var(--wp--custom--width--open);
	font-weight: 300;
	font-style: normal;
	text-transform: uppercase;
	letter-spacing: 0.33em;
}

/*
 * Weight 300 disappears in embroidery, vinyl, etched signage and anything
 * below roughly 14px. The study says to specify the small-size alternate up
 * front rather than improvise it later.
 */
@media (max-width: 600px) {
	.brand-design-group,
	.is-style-design-group {
		font-weight: 500;
		letter-spacing: 0.22em;
	}
}

/* The descriptor line is set identically in both marks, so CONSTRUCTION and
   DESIGN GROUP read as the same system. */
.brand-descriptor {
	font-stretch: var(--wp--custom--width--normal);
	font-weight: 600;
	font-size: var(--wp--preset--font-size--small);
	text-transform: uppercase;
	letter-spacing: 0.18em;
}

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

.skip-link:focus {
	position: fixed;
	top: 1rem;
	left: 1rem;
	z-index: 999;
	padding: 0.75rem 1.25rem;
	background: var(--wp--preset--color--dark);
	color: var(--wp--preset--color--base);
}

/* --------------------------------------------------------------------------
   6. Project facts
   A definition list rather than a table, because rows are skipped when empty
   and a sparse project must not show a column of blank labels. Half the
   portfolio has no recorded square footage.
   -------------------------------------------------------------------------- */
.project-facts {
	margin: 0;
	border-top: 2px solid var(--wp--preset--color--primary);
	padding-top: var(--wp--preset--spacing--30);
}

.project-fact {
	display: grid;
	grid-template-columns: minmax(7rem, 34%) 1fr;
	gap: var(--wp--preset--spacing--30);
	padding: var(--wp--preset--spacing--30) 0;
	border-bottom: 1px solid color-mix(in srgb, var(--wp--preset--color--contrast) 15%, transparent);
}

.project-fact dt {
	margin: 0;
	color: var(--wp--preset--color--contrast-2);
}

.project-fact dd {
	margin: 0;
	font-weight: 500;
}

/* --------------------------------------------------------------------------
   7. Project gallery
   -------------------------------------------------------------------------- */
.project-gallery {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(min(20rem, 100%), 1fr));
	gap: var(--wp--preset--spacing--40);
}

.project-gallery__item {
	margin: 0;
}

.project-gallery__img {
	display: block;
	width: 100%;
	height: 100%;
	aspect-ratio: 4 / 3;
	object-fit: cover;
}

.project-gallery figcaption {
	margin-top: var(--wp--preset--spacing--20);
	font-size: var(--wp--preset--font-size--small);
	color: var(--wp--preset--color--contrast-2);
}

/* --------------------------------------------------------------------------
   8. Project index
   -------------------------------------------------------------------------- */
.project-grid {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(min(19rem, 100%), 1fr));
	gap: var(--wp--preset--spacing--40);
}

/*
 * Each card is a full-height column so its meta line sits on the baseline of
 * the row regardless of how many lines the title takes. Without this, a
 * two-line title pushes its own meta down and the row loses its footing.
 */
.project-card {
	display: flex;
	flex-direction: column;
	background-color: var(--wp--preset--color--base);
}

.project-card__link {
	display: flex;
	flex-direction: column;
	flex: 1 1 auto;
	text-decoration: none;
	color: inherit;
}

/*
 * The aspect ratio lives on the WRAPPER, not the img.
 * On the img it was being defeated by the width/height attributes WordPress
 * emits plus core's `height: auto`, so cards inherited each source photo's
 * own proportions and rows lost their footing. It also means an image that
 * fails to load still holds its slot instead of collapsing to a thin line.
 */
.project-card__media {
	display: block;
	overflow: hidden;
	aspect-ratio: 4 / 3;
	background-color: color-mix(in srgb, var(--wp--preset--color--contrast) 8%, transparent);
}

.project-card__img {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
	/* Buildings read better with their tops kept, so bias the crop upward. */
	object-position: center 40%;
	transition: transform 240ms ease;
}

.project-card__link:hover .project-card__img,
.project-card__link:focus-visible .project-card__img {
	transform: scale(1.03);
}

.project-card__eyebrow {
	display: block;
	margin-top: var(--wp--preset--spacing--30);
	color: var(--wp--preset--color--primary);
}

.project-card__title {
	margin: var(--wp--preset--spacing--20) 0 0;
	font-size: var(--wp--preset--font-size--large);
	font-stretch: var(--wp--custom--width--condensed);
	font-weight: 800;
	line-height: 1.08;
	text-transform: uppercase;
	color: var(--wp--preset--color--contrast);
}

.project-card__link:hover .project-card__title,
.project-card__link:focus-visible .project-card__title {
	color: var(--wp--preset--color--primary);
}

/* Pinned to the bottom of the card, which is what aligns the row. */
.project-card__meta {
	display: flex;
	align-items: center;
	gap: var(--wp--preset--spacing--30);
	margin: auto 0 0;
	padding-top: var(--wp--preset--spacing--30);
	font-size: var(--wp--preset--font-size--small);
	color: var(--wp--preset--color--contrast-2);
}

.project-card__year {
	font-stretch: var(--wp--custom--width--normal);
	font-weight: 600;
	letter-spacing: 0.06em;
}

.project-card__badge {
	display: inline-flex;
	align-items: center;
	gap: 0.3em;
	font-size: 0.75rem;
	font-weight: 700;
	letter-spacing: 0.08em;
	text-transform: uppercase;
}

.project-card__badge--award { color: var(--wp--preset--color--primary); }
.project-card__badge--design { color: var(--wp--preset--color--accent); }

/* The CTA spans the full grid so it reads as a band, not a card. */
.project-cta {
	grid-column: 1 / -1;
}

.project-more {
	display: flex;
	justify-content: center;
	margin-top: var(--wp--preset--spacing--60);
}

.project-more__btn { cursor: pointer; border: 0; }
.project-more__btn[disabled] { opacity: 0.6; cursor: default; }
.project-pagination {
	display: flex;
	justify-content: center;
	gap: var(--wp--preset--spacing--30);
	margin-top: var(--wp--preset--spacing--60);
}

/*
 * Any author `display` beats the user-agent `[hidden] { display: none }`, so
 * the rule above kept the numbered nav on screen even after the script marked
 * it hidden. Two pagination schemes at once is confusing on its own, and they
 * disagreed: the nav marked the page you started on, so its Next link pointed
 * backwards into cards already appended above it.
 *
 * "Show more" is the only control once the script runs. The links stay in the
 * DOM with their hrefs intact - display:none does not stop a crawler
 * discovering them - and come back visible if a fetch ever fails.
 */
.project-pagination[hidden] { display: none; }

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

/* --------------------------------------------------------------------------
   9. Index ground
   The index was white cards on a white page, with blue link colour doing duty
   as label colour. Two changes, both cheap to reverse:
   1. a warm off-white ground so white cards have something to sit on. Depth
      without adding another colour to the palette.
   2. card furniture uses red and graphite; blue is reserved for actual
      navigation links, which is the only place it carries meaning.
   Revert by deleting this block.
   -------------------------------------------------------------------------- */
body.post-type-archive-portfolio,
body.tax-pillar,
body.tax-portfolio_category,
body.tax-service,
body.tax-project_location {
	background-color: var(--wp--preset--color--base-2);
}

body.post-type-archive-portfolio .project-card,
body.tax-pillar .project-card,
body.tax-portfolio_category .project-card,
body.tax-service .project-card,
body.tax-project_location .project-card {
	box-shadow: 0 1px 2px color-mix(in srgb, var(--wp--preset--color--dark) 8%, transparent);
}

.project-card__eyebrow,
.project-card__title,
.project-card__meta {
	padding-inline: var(--wp--preset--spacing--30);
}

.project-card__meta { padding-bottom: var(--wp--preset--spacing--30); }

/* Three across on desktop; two on tablet; one on phone. */
@media (min-width: 64rem) {
	.project-grid { grid-template-columns: repeat(3, 1fr); }
}
@media (min-width: 40rem) and (max-width: 63.999rem) {
	.project-grid { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 39.999rem) {
	.project-grid { grid-template-columns: 1fr; }
}

/* The index earns more width than body copy: it is a grid of photographs,
   not something anyone reads line by line. It fills the wide band it sits
   in (78rem) - not the viewport. The parent's constrained layout caps every
   child at the 46rem content width, which is why the grid sat at 736px
   inside a 1248px band until max-width was lifted. */
@media (min-width: 64rem) {
	body.post-type-archive-portfolio .project-index,
	body.tax-pillar .project-index,
	body.tax-portfolio_category .project-index,
	body.tax-service .project-index {
		max-width: none;
		width: 100%;
	}
}

/* The interstitial CTA stays at reading width whatever the grid does. */
.project-index .project-cta {
	max-width: var(--wp--style--global--content-size, 46rem);
	margin-inline: auto;
}

/* --------------------------------------------------------------------------
   10. Project detail
   The first version was a single column of very large images: hard to parse,
   no guidance, and the only route to contact was at the very bottom. This
   pairs the hero with the facts, sets the narrative beside a persistent CTA,
   and reduces the gallery to a scannable grid.
   -------------------------------------------------------------------------- */
.project-lede {
	display: grid;
	gap: var(--wp--preset--spacing--50);
}

@media (min-width: 56rem) {
	.project-lede { grid-template-columns: 1.6fr 1fr; align-items: start; }
}

.project-lede .wp-block-post-featured-image { margin: 0; }

.project-body {
	display: grid;
	gap: var(--wp--preset--spacing--60);
	align-items: start;
}

@media (min-width: 56rem) {
	.project-body { grid-template-columns: 1.6fr 1fr; }
}

.project-body .wp-block-post-content > * { max-width: 62ch; }

.project-body p { margin-block: 0 1em; }

/* The CTA rides alongside the narrative rather than waiting at the bottom,
   and stays in view while the copy scrolls past it. */
.project-context {
	border-top: 3px solid var(--wp--preset--color--primary);
	padding-top: var(--wp--preset--spacing--40);
}

@media (min-width: 56rem) {
	.project-context { position: sticky; top: var(--wp--preset--spacing--40); }
}

.project-context__label { color: var(--wp--preset--color--primary); margin: 0; }

.project-context__line {
	margin: var(--wp--preset--spacing--30) 0 0;
	font-size: var(--wp--preset--font-size--small);
	color: var(--wp--preset--color--contrast-2);
}

.project-context__question {
	margin: var(--wp--preset--spacing--40) 0 0;
	font-size: var(--wp--preset--font-size--large);
}

.project-context__actions {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	gap: var(--wp--preset--spacing--30);
	margin: var(--wp--preset--spacing--40) 0 0;
}

.project-context__cta { text-decoration: none; }

.project-context__more {
	font-size: var(--wp--preset--font-size--small);
	font-stretch: var(--wp--custom--width--condensed);
	text-transform: uppercase;
	letter-spacing: 0.06em;
}

/* Compact, scannable gallery instead of a long scroll of oversized images. */
.project-gallery {
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(min(13rem, 100%), 1fr));
	gap: var(--wp--preset--spacing--30);
}

.project-gallery__item {
	display: block;
	padding: 0;
	border: 0;
	background: none;
	cursor: zoom-in;
	overflow: hidden;
	aspect-ratio: 4 / 3;
}

.project-gallery__img {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
	transition: transform 240ms ease;
}

.project-gallery__item:hover .project-gallery__img,
.project-gallery__item:focus-visible .project-gallery__img { transform: scale(1.04); }

.related-projects__title { margin-bottom: var(--wp--preset--spacing--50); }

/* Lightbox */
.lightbox {
	max-width: 100vw;
	max-height: 100vh;
	width: 100%;
	height: 100%;
	border: 0;
	padding: 0;
	background: color-mix(in srgb, var(--wp--preset--color--dark) 94%, transparent);
}

.lightbox::backdrop { background: rgba(0,0,0,0.8); }

.lightbox__img {
	position: absolute;
	inset: 0;
	margin: auto;
	max-width: 92vw;
	max-height: 86vh;
	object-fit: contain;
}

.lightbox__close,
.lightbox__nav {
	position: absolute;
	z-index: 1;
	border: 0;
	background: none;
	color: #fff;
	font-size: 2.5rem;
	line-height: 1;
	padding: 0.4em 0.6em;
	cursor: pointer;
}

.lightbox__close { top: 0.5rem; right: 0.5rem; }
.lightbox__nav--prev { left: 0.5rem; top: 50%; transform: translateY(-50%); }
.lightbox__nav--next { right: 0.5rem; top: 50%; transform: translateY(-50%); }

.lightbox__count {
	position: absolute;
	bottom: 1rem;
	left: 0;
	right: 0;
	text-align: center;
	color: #fff;
	font-size: var(--wp--preset--font-size--small);
	letter-spacing: 0.1em;
}

.project-awards { margin: 0; padding-left: 1.1em; }
.project-awards li { margin-bottom: 0.35em; }

/* --------------------------------------------------------------------------
   11. Project search
   -------------------------------------------------------------------------- */
.project-search { position: relative; margin-bottom: var(--wp--preset--spacing--50); }

.project-search__input {
	width: 100%;
	padding: 0.9em 2.5em 0.9em 1em;
	font-family: inherit;
	font-size: var(--wp--preset--font-size--medium);
	color: var(--wp--preset--color--contrast);
	background-color: var(--wp--preset--color--base);
	border: 1px solid color-mix(in srgb, var(--wp--preset--color--contrast) 22%, transparent);
	border-radius: 0;
}

.project-search__input:focus-visible {
	outline: 2px solid var(--wp--preset--color--primary);
	outline-offset: -2px;
}

.project-search__clear {
	position: absolute;
	right: 0.4em;
	top: 0.25em;
	border: 0;
	background: none;
	font-size: 1.8rem;
	line-height: 1;
	padding: 0.2em 0.5em;
	cursor: pointer;
	color: var(--wp--preset--color--contrast-2);
}

.project-search__results {
	margin-top: var(--wp--preset--spacing--30);
	background-color: var(--wp--preset--color--base);
	border: 1px solid color-mix(in srgb, var(--wp--preset--color--contrast) 12%, transparent);
}

.project-search__hit {
	display: flex;
	align-items: center;
	gap: var(--wp--preset--spacing--30);
	padding: var(--wp--preset--spacing--30);
	text-decoration: none;
	color: var(--wp--preset--color--contrast);
	border-bottom: 1px solid color-mix(in srgb, var(--wp--preset--color--contrast) 10%, transparent);
}

.project-search__hit:last-child { border-bottom: 0; }

.project-search__hit:hover,
.project-search__hit:focus-visible {
	background-color: var(--wp--preset--color--base-2);
	color: var(--wp--preset--color--primary);
}

.project-search__hit img,
.project-search__noimg {
	width: 56px;
	height: 56px;
	object-fit: cover;
	flex: 0 0 auto;
	background-color: var(--wp--preset--color--base-2);
}

.project-search__hit-text { display: flex; flex-direction: column; gap: 0.15em; }

.project-search__hit-title {
	font-stretch: var(--wp--custom--width--condensed);
	font-weight: 700;
	text-transform: uppercase;
	line-height: 1.1;
}

.project-search__hit-meta {
	font-size: var(--wp--preset--font-size--small);
	color: var(--wp--preset--color--contrast-2);
}

.project-search__empty { padding: var(--wp--preset--spacing--40); margin: 0; }

/* Badges are links now. */
a.project-card__badge { text-decoration: none; }
a.project-card__badge:hover,
a.project-card__badge:focus-visible { text-decoration: underline; text-underline-offset: 0.2em; }

.footer-list { list-style: none; padding: 0; margin: 0; }
.footer-list li { margin-bottom: 0.5em; font-size: var(--wp--preset--font-size--small); }
.footer-list a { color: inherit; text-decoration: none; }
.footer-list a:hover, .footer-list a:focus-visible { text-decoration: underline; text-underline-offset: 0.2em; }

/* --------------------------------------------------------------------------
   12. Site brand
   -------------------------------------------------------------------------- */
.site-brand { display: inline-block; line-height: 0; }
.site-brand svg { display: block; width: 100%; height: auto; }
.site-brand--color { width: clamp(9rem, 20vw, 13rem); }
.site-brand--white { width: clamp(10rem, 24vw, 14rem); }
.site-brand--text { line-height: 1.1; font-size: var(--wp--preset--font-size--large); text-decoration: none; }
.site-brand:focus-visible { outline: 2px solid var(--wp--preset--color--primary); outline-offset: 4px; }

/* --------------------------------------------------------------------------
   13. Pillar grid
   wp:columns forced four condensed uppercase headings into ~11rem each, which
   broke words mid-syllable ("COMMERCI AL"). A grid with a real minimum lets
   them reflow to two-up instead of breaking.
   -------------------------------------------------------------------------- */
.pillar-grid {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(min(15rem, 100%), 1fr));
	gap: var(--wp--preset--spacing--50);
}

.pillar-grid__item { min-width: 0; }

.pillar-grid__eyebrow { margin: 0 0 var(--wp--preset--spacing--20); color: var(--wp--preset--color--primary); }

.pillar-grid__title {
	margin: 0 0 var(--wp--preset--spacing--30);
	font-size: var(--wp--preset--font-size--large);
	font-stretch: var(--wp--custom--width--condensed);
	font-weight: 800;
	line-height: 1.05;
	text-transform: uppercase;
	/* Never break a word to fit; wrap to the next line instead. */
	overflow-wrap: normal;
	word-break: keep-all;
	hyphens: none;
}

/* Headings that happen to be links should read as headings. */
.pillar-grid__title a {
	color: var(--wp--preset--color--contrast);
	text-decoration: none;
}

.pillar-grid__title a:hover,
.pillar-grid__title a:focus-visible {
	color: var(--wp--preset--color--primary);
	text-decoration: underline;
	text-underline-offset: 0.12em;
}

.pillar-grid__question {
	margin: 0;
	font-style: italic;
	font-stretch: var(--wp--custom--width--condensed);
	font-weight: 600;
	font-size: var(--wp--preset--font-size--medium);
	line-height: 1.2;
	color: var(--wp--preset--color--contrast-2);
}

/* Landing heroes: the banner size is for the homepage only. */
.page-hero h1 { font-size: var(--wp--preset--font-size--display); }
.page-hero .is-style-pillar-question { margin-top: var(--wp--preset--spacing--40); }

/* --------------------------------------------------------------------------
   14. Imagery
   The site was almost entirely typographic outside the portfolio. These pull
   real project photography rather than adding a stock library to maintain.
   -------------------------------------------------------------------------- */
/*
 * Three across, always. auto-fit wrapped the third item onto its own row at
 * common widths, which broke the band into an L-shape and lost the impact.
 * Below 40rem it stacks deliberately rather than by accident.
 */
.image-band {
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	gap: var(--wp--preset--spacing--30);
}

@media (max-width: 40rem) {
	.image-band { grid-template-columns: 1fr; }
}

.image-band__item { text-decoration: none; color: inherit; display: block; }

.image-band__media {
	display: block;
	overflow: hidden;
	aspect-ratio: 3 / 2;
	background-color: color-mix(in srgb, var(--wp--preset--color--contrast) 8%, transparent);
}

.image-band__img {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
	object-position: center 40%;
	transition: transform 240ms ease;
}

.image-band__item:hover .image-band__img,
.image-band__item:focus-visible .image-band__img { transform: scale(1.03); }

.image-band__label {
	display: block;
	margin-top: var(--wp--preset--spacing--20);
	font-size: var(--wp--preset--font-size--small);
	font-stretch: var(--wp--custom--width--condensed);
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 0.05em;
}

.image-band__item:hover .image-band__label { color: var(--wp--preset--color--primary); }

.pillar-lead { margin: 0 0 var(--wp--preset--spacing--50); }

.pillar-lead__img {
	display: block;
	width: 100%;
	aspect-ratio: 21 / 9;
	object-fit: cover;
	object-position: center 42%;
}

.pillar-lead__caption {
	margin-top: var(--wp--preset--spacing--20);
	font-size: var(--wp--preset--font-size--small);
	color: var(--wp--preset--color--contrast-2);
}

.pillar-lead__caption a { color: inherit; text-decoration: none; }
.pillar-lead__caption a:hover { color: var(--wp--preset--color--primary); text-decoration: underline; }

/* --------------------------------------------------------------------------
   15. Fold
   The hero at `banner` ran to five lines and pushed everything below the fold.
   The bold text-as-hero treatment is the point, so the size comes down rather
   than the treatment changing.
   -------------------------------------------------------------------------- */
.home-hero h1 {
	font-size: clamp(2.25rem, 6.5vw, 4.25rem);
	line-height: 0.98;
	max-width: 16ch;
}

.home-hero { padding-top: var(--wp--preset--spacing--50) !important; padding-bottom: var(--wp--preset--spacing--50) !important; }
.home-hero p { max-width: 54ch; }

/* --------------------------------------------------------------------------
   15b. Hero backdrop
   The text-as-hero treatment stays exactly as it was; a photograph now sits
   behind it. Three rules keep the words readable regardless of the image:

   - The scrim is a fixed gradient, not a property of the photo. Swap the
     image and the contrast still holds.
   - It is heaviest on the left, where the copy lives (the hero column is the
     wide width, so the copy sits left and the photograph's subject can stay
     visible on the right).
   - Motion is a transform on the image only. It runs on the compositor, so
     it costs nothing beyond the still, and it is off under reduced-motion.
   -------------------------------------------------------------------------- */
.home-hero.is-cover {
	position: relative;
	isolation: isolate;
	overflow: hidden;
	display: grid;
	align-content: center;
	min-height: clamp(28rem, 70vh, 44rem);
	/* 4rem, not 6: with 6 the CTAs ended 10px below the fold on a 1366x768
	   laptop and 58px below on 1280x720. Measured 2026-09-18. */
	padding-top: var(--wp--preset--spacing--60) !important;
	padding-bottom: var(--wp--preset--spacing--60) !important;
	color: var(--wp--preset--color--base);
}

.home-hero.is-cover :is(h1, p) { color: var(--wp--preset--color--base); }

@media (max-width: 47.99rem) {
	/* Edge to edge on phones. Inside the gutters it read as a black card in
	   a white frame, and the scrim written for a wide screen - heaviest on
	   the left, where the copy sits - covered the whole photograph once the
	   copy column was the full width. So: no frame, and a lighter, even
	   scrim that lets the image show while the text stays on the dark end. */
	.home-hero.is-cover {
		padding-top: var(--wp--preset--spacing--50) !important;
		padding-bottom: var(--wp--preset--spacing--50) !important;
		min-height: 0;
		/* The gutter is main's root padding (spacing 40), so cancel exactly
		   that - not 100vw, which counts a scrollbar and overshoots. */
		width: calc(100% + 2 * var(--wp--preset--spacing--40));
		max-width: none;
		margin-left: calc(-1 * var(--wp--preset--spacing--40)) !important;
		margin-right: calc(-1 * var(--wp--preset--spacing--40)) !important;
	}
	.home-hero__backdrop::after {
		background:
			linear-gradient(180deg, rgba(6, 6, 4, 0.55) 0%, rgba(6, 6, 4, 0.45) 55%, rgba(6, 6, 4, 0.70) 100%);
	}
	.home-hero.is-cover :is(h1, p) { text-shadow: 0 1px 2px rgba(0, 0, 0, 0.45); }
	/* 24px lead copy on a 375px screen pushed the buttons under the fold. */
	.home-hero.is-cover p { font-size: var(--wp--preset--font-size--medium); }
	.home-hero.is-cover h1 { font-size: clamp(2rem, 9vw, 2.75rem); }
	/* Full-width stacked buttons: at 393px the content column is ~265px and
	   "Tell Us What You Need" at the default size needs ~275, so it wrapped
	   onto two lines with a red field under it. One line, always. */
	.home-hero.is-cover .wp-block-buttons { flex-direction: column; align-items: stretch; }
	.home-hero.is-cover .wp-block-button { width: 100%; }
	.home-hero.is-cover .wp-block-button__link { display: block; width: 100%; text-align: center; font-size: var(--wp--preset--font-size--small); white-space: nowrap; padding-left: 0.75em; padding-right: 0.75em; }
}

/* Constrained layout centres every child with auto margins (!important). The
   copy belongs at the left of the column, where the scrim is heaviest. */
.home-hero.is-cover > :where(:not(.home-hero__backdrop)) { margin-left: 0 !important; }

.home-hero__backdrop {
	position: absolute;
	inset: 0;
	z-index: -1;
	max-width: none !important;
	margin: 0 !important;
}

.home-hero__img {
	position: absolute;
	inset: 0;
	display: block;
	width: 100%;
	height: 100%;
	object-fit: cover;
	object-position: 60% 45%;
	opacity: 0;
	transition: opacity 1.5s ease-in-out;
}

.home-hero__img.is-active { opacity: 1; }

/* The frames gallery is authoring UI: a normal Gallery block in the editor,
   read by the block and rendered as backdrop layers on the front end. */
.home-hero.is-cover > .home-hero-frames { display: none; }

.home-hero__backdrop::after {
	content: "";
	position: absolute;
	inset: 0;
	z-index: 1;
	background:
		linear-gradient(90deg, rgba(6, 6, 4, 0.86) 0%, rgba(6, 6, 4, 0.74) 42%, rgba(6, 6, 4, 0.34) 100%),
		linear-gradient(180deg, rgba(6, 6, 4, 0.30) 0%, rgba(6, 6, 4, 0) 40%, rgba(6, 6, 4, 0.40) 100%);
}

/* Outline button inherits currentColor for text but the border needs telling. */
.home-hero.is-cover .is-style-outline .wp-block-button__link {
	color: var(--wp--preset--color--base);
	border-color: var(--wp--preset--color--base);
}

.home-hero.is-cover .is-style-outline .wp-block-button__link:hover {
	background-color: var(--wp--preset--color--base);
	color: var(--wp--preset--color--dark);
}

/* Slow drift: 1.00 -> 1.08 over 36s, then back. Slow enough that nobody
   watches it happen; they only notice the frame is never quite still. */
@keyframes home-hero-drift {
	from { transform: scale(1) translate(0, 0); }
	to   { transform: scale(1.08) translate(-1.5%, -1%); }
}

.home-hero__backdrop.has-motion .home-hero__img {
	transform-origin: 60% 45%;
	animation: home-hero-drift 36s ease-in-out infinite alternate;
	will-change: transform;
}

@media (prefers-reduced-motion: reduce) {
	.home-hero__backdrop.has-motion .home-hero__img { animation: none; }
}

/* --------------------------------------------------------------------------
   16. Staff
   -------------------------------------------------------------------------- */
/*
 * The grid inherits the 46rem content measure, where three 14rem columns plus
 * gaps missed fitting by about 16px and silently collapsed to two - leaving
 * portraits far larger than they need to be. Widened, with explicit column
 * counts rather than relying on auto-fill to land well.
 */
.staff-grid {
	list-style: none;
	margin: 0 auto;
	padding: 0;
	display: grid;
	grid-template-columns: repeat(2, 1fr);
	gap: var(--wp--preset--spacing--40);
	width: min(100%, 62rem);
}

@media (min-width: 48rem) { .staff-grid { grid-template-columns: repeat(3, 1fr); } }
@media (min-width: 72rem) { .staff-grid { grid-template-columns: repeat(4, 1fr); } }

.staff-card { margin: 0; }

.staff-card__media {
	display: block;
	overflow: hidden;
	aspect-ratio: 3 / 4;
	background-color: color-mix(in srgb, var(--wp--preset--color--contrast) 8%, transparent);
}

.staff-card__img { display: block; width: 100%; height: 100%; object-fit: cover; object-position: center 20%; }

.staff-card__name {
	margin: var(--wp--preset--spacing--30) 0 0;
	font-stretch: var(--wp--custom--width--condensed);
	font-weight: 800;
	text-transform: uppercase;
	line-height: 1.1;
}

.staff-card__role {
	margin: 0.25em 0 0;
	font-size: var(--wp--preset--font-size--small);
	color: var(--wp--preset--color--contrast-2);
}

.staff-empty {
	padding: var(--wp--preset--spacing--40);
	border: 1px dashed color-mix(in srgb, var(--wp--preset--color--contrast) 25%, transparent);
	color: var(--wp--preset--color--contrast-2);
}

/* --------------------------------------------------------------------------
   17. Heritage timeline
   The original was a horizontal carousel. A vertical grid reads better on the
   phone, keeps every year visible at once, and needs no JavaScript.
   -------------------------------------------------------------------------- */
.timeline {
	list-style: none;
	margin: 0;
	padding: 0;
	display: grid;
	grid-template-columns: repeat(auto-fill, minmax(min(17rem, 100%), 1fr));
	gap: var(--wp--preset--spacing--50);
	counter-reset: timeline;
}

.timeline__item {
	margin: 0;
	padding-top: var(--wp--preset--spacing--30);
	border-top: 3px solid var(--wp--preset--color--primary);
}

.timeline__year {
	margin: 0 0 var(--wp--preset--spacing--30);
	font-stretch: var(--wp--custom--width--condensed);
	font-weight: 800;
	font-size: var(--wp--preset--font-size--large);
	letter-spacing: 0.02em;
	color: var(--wp--preset--color--primary);
}

.timeline__media {
	display: block;
	overflow: hidden;
	aspect-ratio: 4 / 3;
	background-color: color-mix(in srgb, var(--wp--preset--color--contrast) 8%, transparent);
}

.timeline__img { display: block; width: 100%; height: 100%; object-fit: cover; }

.timeline__desc {
	margin: var(--wp--preset--spacing--30) 0 0;
	font-size: var(--wp--preset--font-size--small);
	line-height: 1.5;
}

.heritage-quote { border: 0; padding: 0; margin: 0; }
.heritage-quote cite {
	display: block;
	margin-top: var(--wp--preset--spacing--30);
	font-style: normal;
	font-stretch: var(--wp--custom--width--condensed);
	text-transform: uppercase;
	letter-spacing: 0.1em;
	font-size: var(--wp--preset--font-size--small);
	color: var(--wp--preset--color--primary);
}

/* --------------------------------------------------------------------------
   18. News
   -------------------------------------------------------------------------- */
.news-grid { gap: var(--wp--preset--spacing--50) !important; }

.news-card { display: flex; flex-direction: column; height: 100%; }
.news-card .wp-block-post-featured-image { margin: 0 0 var(--wp--preset--spacing--30); overflow: hidden; }
.news-card .wp-block-post-featured-image img { transition: transform 240ms ease; }
.news-card:hover .wp-block-post-featured-image img { transform: scale(1.03); }

.news-card__date { margin: 0; color: var(--wp--preset--color--primary); }

.news-card__title { margin: var(--wp--preset--spacing--20) 0 0; }
.news-card__title a { color: var(--wp--preset--color--contrast); text-decoration: none; }
.news-card__title a:hover, .news-card__title a:focus-visible { color: var(--wp--preset--color--primary); }

.news-card .wp-block-post-excerpt { margin-top: var(--wp--preset--spacing--20); color: var(--wp--preset--color--contrast-2); }

/* --------------------------------------------------------------------------
   19. Events
   -------------------------------------------------------------------------- */
.event-list { list-style: none; margin: 0 0 var(--wp--preset--spacing--60); padding: 0; }
.event-list__heading { margin-bottom: var(--wp--preset--spacing--40); font-size: var(--wp--preset--font-size--large); }
.event-list__heading--past { color: var(--wp--preset--color--contrast-2); }

.event-card {
	padding: var(--wp--preset--spacing--40) 0;
	border-top: 1px solid color-mix(in srgb, var(--wp--preset--color--contrast) 15%, transparent);
}
.event-card:last-child { border-bottom: 1px solid color-mix(in srgb, var(--wp--preset--color--contrast) 15%, transparent); }

.event-card__date { margin: 0 0 var(--wp--preset--spacing--20); color: var(--wp--preset--color--primary); }

.event-card__title {
	margin: 0;
	font-size: var(--wp--preset--font-size--large);
	font-stretch: var(--wp--custom--width--condensed);
	font-weight: 800;
	text-transform: uppercase;
	line-height: 1.1;
}
.event-card__title a { color: var(--wp--preset--color--contrast); text-decoration: none; }
.event-card__title a:hover { color: var(--wp--preset--color--primary); }

.event-card__where { margin: var(--wp--preset--spacing--20) 0 0; font-size: var(--wp--preset--font-size--small); color: var(--wp--preset--color--contrast-2); }
.event-card__excerpt { margin: var(--wp--preset--spacing--20) 0 0; max-width: 60ch; }

.event-facts { max-width: 34rem; }
.event-past {
	margin-top: var(--wp--preset--spacing--40);
	padding: var(--wp--preset--spacing--30);
	background-color: var(--wp--preset--color--base-2);
	border-left: 3px solid var(--wp--preset--color--primary);
}

/* --------------------------------------------------------------------------
   20. Header
   The brand and the navigation were wrapping onto separate lines because the
   flex row inherited the 46rem content width. It needs the wide measure.
   -------------------------------------------------------------------------- */
.wp-block-group.alignwide > .wp-block-navigation { flex: 0 1 auto; }

/* One row, always. Below 60rem the header cannot hold the wordmark, the
   menu, the stacked phone and the long button on one line, so the same
   header gets narrower: the wordmark becomes the mark, the button label
   becomes "Contact Us", the phone loses its "Call us" label. Nothing is
   page-specific; the homepage hero's own CTA is not the reason for this,
   the fold on a phone is (the old header was 224px tall on a 375px screen). */
.site-brand__mark { display: none; }
.header-cta__short { display: none; }

@media (max-width: 59.99rem) {
	/* The wordmark stays: the company name belongs on the page. With the
	   short button and the phone icon it fits a 375px row at 8.5rem. */
	.site-brand--color { width: 8.5rem; }
	.header-cta__long { display: none; }
	.header-cta__short { display: inline; }
	/* "header" prefix: the stacked-phone rules in section 26 come later in
	   this file and would otherwise win the tie. */
	header .header-phone.is-stacked { flex-direction: row; align-items: center; gap: 0.4rem; padding-right: 0; }
	header .header-phone.is-stacked::before { content: none; }
	header .header-phone.is-stacked .header-phone__icon { display: block; }
	header .header-phone.is-stacked .header-phone__number { font-size: 1rem; }
	header.wp-block-group { padding-top: var(--wp--preset--spacing--30) !important; padding-bottom: var(--wp--preset--spacing--30) !important; }
	header .wp-block-group.alignwide,
	header .wp-block-group.alignwide > .wp-block-group { flex-wrap: nowrap; gap: 0.75rem; }
	header .wp-block-button__link { padding: 0.6em 0.9em; white-space: nowrap; }
	/* Core collapses the navigation to the hamburger at 600px. The single
	   row needs it at 60rem, or the menu items wrap onto a second line on a
	   tablet. Same overlay, same button; only the threshold moves. */
	header .wp-block-navigation__responsive-container-open:not(.always-shown) { display: flex; }
	header .wp-block-navigation__responsive-container:not(.hidden-by-default):not(.is-menu-open) { display: none; }
}

/* Only where the wordmark genuinely cannot share the row (~350px and
   under): the Ooglie+B mark stands in. Same link, same target. */
@media (max-width: 21.99rem) {
	.site-brand__logo { display: none; }
	.site-brand__mark { display: block; width: 2.75rem; }
	.site-brand__mark svg { display: block; width: 100%; height: auto; }
}

/* On phones the header's own padding is the only space below it. The root
   block gap otherwise adds 1.5rem between header and main on every page,
   which read as a header thicker at the bottom than the top. Desktop keeps
   the gap. */
@media (max-width: 47.99rem) {
	.wp-site-blocks > main { margin-block-start: 0 !important; }
}

/* Tighter still on a phone: the number goes, the icon stays as the tap target. */
@media (max-width: 30rem) {
	header .header-phone.is-stacked .header-phone__number { display: none; }
	header .header-phone__icon { width: 1.4rem; height: 1.4rem; }
	header .wp-block-group.alignwide > .wp-block-group { gap: 0.5rem; }
}

/* --------------------------------------------------------------------------
   21. Forms
   Gravity Forms ships unstyled defaults that look nothing like the rest of the
   site. This is the conversion path, so it gets the same treatment as
   everything else rather than browser chrome.
   -------------------------------------------------------------------------- */
.gform_wrapper form { max-width: 40rem; }

.gform_wrapper .gfield { margin-bottom: var(--wp--preset--spacing--40); }

.gform_wrapper .gfield_label,
.gform_wrapper legend.gfield_label {
	display: block;
	margin-bottom: var(--wp--preset--spacing--20);
	font-stretch: var(--wp--custom--width--condensed);
	font-weight: 700;
	font-size: var(--wp--preset--font-size--small);
	text-transform: uppercase;
	letter-spacing: 0.06em;
	color: var(--wp--preset--color--contrast);
}

.gform_wrapper .gfield_required { color: var(--wp--preset--color--primary); font-style: normal; }

.gform_wrapper input[type="text"],
.gform_wrapper input[type="email"],
.gform_wrapper input[type="tel"],
.gform_wrapper input[type="url"],
.gform_wrapper input[type="number"],
.gform_wrapper select,
.gform_wrapper textarea {
	width: 100%;
	padding: 0.75em 0.9em;
	font-family: inherit;
	font-size: var(--wp--preset--font-size--medium);
	color: var(--wp--preset--color--contrast);
	background-color: var(--wp--preset--color--base);
	border: 1px solid color-mix(in srgb, var(--wp--preset--color--contrast) 28%, transparent);
	border-radius: 0;
	box-shadow: none;
}

.gform_wrapper input:focus-visible,
.gform_wrapper select:focus-visible,
.gform_wrapper textarea:focus-visible {
	outline: 2px solid var(--wp--preset--color--primary);
	outline-offset: -2px;
	border-color: var(--wp--preset--color--primary);
}

.gform_wrapper textarea { min-height: 10rem; resize: vertical; }

.gform_wrapper .ginput_complex label,
.gform_wrapper .gfield_description {
	display: block;
	margin-top: 0.35em;
	font-size: var(--wp--preset--font-size--small);
	color: var(--wp--preset--color--contrast-2);
	text-transform: none;
	letter-spacing: 0;
	font-weight: 400;
}

.gform_wrapper .gform_footer input[type="submit"],
.gform_wrapper .gform_button {
	appearance: none;
	border: 0;
	border-radius: 0;
	cursor: pointer;
	padding: 0.9em 1.6em;
	background-color: var(--wp--preset--color--primary);
	color: var(--wp--preset--color--base);
	font-family: inherit;
	font-stretch: var(--wp--custom--width--condensed);
	font-weight: 700;
	font-size: var(--wp--preset--font-size--medium);
	text-transform: uppercase;
	letter-spacing: 0.04em;
}

.gform_wrapper .gform_footer input[type="submit"]:hover,
.gform_wrapper .gform_button:hover { background-color: var(--wp--preset--color--dark); }

.gform_wrapper .validation_message,
.gform_wrapper .gfield_validation_message {
	margin-top: 0.4em;
	color: var(--wp--preset--color--primary);
	font-size: var(--wp--preset--font-size--small);
}

/* Two-column name fields should not collapse awkwardly on a phone. */
@media (max-width: 34rem) {
	.gform_wrapper .ginput_complex span { display: block; width: 100% !important; margin-bottom: var(--wp--preset--spacing--30); }
}

/* --------------------------------------------------------------------------
   22. News card titles
   Core sets overflow-wrap:break-word, which snapped "CONSTRUCTION" mid-word
   and left the N stranded on its own line. That word is in most of the post
   titles, so it has to wrap as a word or not at all.
   -------------------------------------------------------------------------- */
.news-card__title {
	font-size: var(--wp--preset--font-size--medium);
	font-stretch: var(--wp--custom--width--condensed);
	font-weight: 800;
	line-height: 1.15;
	text-transform: uppercase;
	overflow-wrap: normal;
	word-break: keep-all;
	hyphens: none;
	text-wrap: balance;
}

.news-card__title a { overflow-wrap: normal; word-break: keep-all; }

/* Same protection anywhere a long word meets a narrow condensed column. */
.project-card__title,
.pillar-grid__title,
.event-card__title,
.il-card__title {
	overflow-wrap: normal;
	word-break: keep-all;
	hyphens: none;
}

/* Logos used as featured images get cropped to nonsense by object-fit:cover
   ("BACHMA / CONSTRUCTIO"). Contain them instead and give them a ground. */
.news-card .wp-block-post-featured-image img[src*="logo"],
.news-card .wp-block-post-featured-image img[src*="Logo"] {
	object-fit: contain;
	background-color: var(--wp--preset--color--base-2);
	padding: var(--wp--preset--spacing--30);
}

/* --------------------------------------------------------------------------
   23. Headline wrapping
   Condensed uppercase at display size breaks badly in a narrow measure:
   "CONSTRUCTION" snapped mid-word, and "OLD BUILDINGS THAT STILL HAVE WORK TO
   DO" fell into four ragged lines. Two rules fix both everywhere rather than
   case by case.
   -------------------------------------------------------------------------- */
h1, h2, h3, h4,
.wp-block-heading,
.wp-block-post-title {
	/* Never split a word to fit; wrap to the next line instead. */
	overflow-wrap: normal;
	word-break: keep-all;
	hyphens: none;
	/* Distribute lines evenly rather than filling greedily, which is what
	   made long headlines choppy. */
	text-wrap: balance;
}

/* A display headline needs room before it starts wrapping at all. */
.page-hero h1,
.wp-block-post-title.has-display-font-size,
h1.has-display-font-size {
	max-width: 18ch;
}

.home-hero h1 { max-width: 16ch; }

@media (min-width: 64rem) {
	.page-hero h1,
	h1.has-display-font-size { max-width: 22ch; }
}

/* Let the staff grid use the wide measure rather than the reading measure. */
.wp-block-group.alignwide > .staff-grid,
.wp-block-group.alignwide .staff-grid { max-width: none; }

/* A person with no photograph yet gets a calm placeholder, not a gap. */
.staff-card__media--empty,
.staff-card__media:empty {
	background-color: color-mix(in srgb, var(--wp--preset--color--contrast) 6%, transparent);
	border: 1px dashed color-mix(in srgb, var(--wp--preset--color--contrast) 18%, transparent);
}

/* interiorLOGIC: Robin's portrait beside her intro. */
.is-interiorlogic .il-person__photo img { width: 100%; height: auto; display: block; }
.is-interiorlogic .il-person__intro { align-self: end; }

/* --------------------------------------------------------------------------
   24. Facts list under a heading
   .project-facts carries its own red top border so the list reads as a unit
   on project pages, where nothing sits above it. When it follows one of the
   angled-rule headings the two rules stack and read as a mistake.
   -------------------------------------------------------------------------- */
.project-facts.is-under-heading { border-top: 0; padding-top: 0; }

/* --------------------------------------------------------------------------
   25. Dark bands inset their content
   Text sitting flush against the edge of a black band reads as a mistake. The
   homepage CTA solved this with explicit padding on the block, which meant
   every other dark band had to remember to do the same - and the scholarship
   page's did not. Light bands are deliberately left alone: their content lines
   up with the body copy above and below, which only works because there is no
   visible edge to sit against.

   Declared as a floor, so a block carrying its own inline padding still wins.
   -------------------------------------------------------------------------- */
.wp-block-group.has-background.has-base-2-background-color,
.wp-block-group.has-background.has-dark-background-color {
	padding-left: var(--wp--preset--spacing--50);
	padding-right: var(--wp--preset--spacing--50);
}

/* --------------------------------------------------------------------------
   26. Telephone number in the header
   Most inbound enquiry still arrives by telephone, so burying the number in
   the footer works against the way people actually get in touch. It sits
   beside the CTA rather than replacing it: the button is for people who want
   to describe a project, the number is for people who want to talk now.

   Set in the condensed width so it reads as brand furniture rather than body
   copy, and tabular figures so the digits do not wobble.
   -------------------------------------------------------------------------- */
.header-phone {
	display: inline-flex;
	align-items: center;
	gap: 0.45rem;
	text-decoration: none;
	color: var(--wp--preset--color--contrast);
	font-size: var(--wp--preset--font-size--small);
	font-weight: 600;
	font-stretch: var(--wp--custom--width--condensed);
	font-variant-numeric: tabular-nums;
	letter-spacing: 0.01em;
	white-space: nowrap;
}

.header-phone:hover .header-phone__number,
.header-phone:focus-visible .header-phone__number {
	color: var(--wp--preset--color--primary);
	text-decoration: underline;
	text-underline-offset: 0.2em;
}

/* Drawn rather than an image file so it takes the brand red and needs no
   request of its own. */
.header-phone__icon {
	width: 0.95rem;
	height: 0.95rem;
	flex: none;
	background-color: var(--wp--preset--color--primary);
	-webkit-mask: var(--phone-glyph) center / contain no-repeat;
	mask: var(--phone-glyph) center / contain no-repeat;
}

:root {
	--phone-glyph: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M6.6 10.8c1.4 2.8 3.8 5.2 6.6 6.6l2.2-2.2c.3-.3.7-.4 1-.2 1.1.4 2.3.6 3.6.6.6 0 1 .4 1 1V20c0 .6-.4 1-1 1C10.6 21 3 13.4 3 4c0-.6.4-1 1-1h3.4c.6 0 1 .4 1 1 0 1.2.2 2.4.6 3.6.1.4 0 .7-.2 1z'/%3E%3C/svg%3E");
}

/* On a phone the number matters most and the label is the thing to lose, not
   the tap target. */
@media (max-width: 47.99rem) {
	.header-phone__number { font-size: 0.9375rem; }
}

/* The stacked treatment: a label over the number, in brand blue, so it reads
   as a second call to action rather than another nav item. Drop is-stacked
   from the markup to get the compact inline version instead. */
.header-phone.is-stacked {
	flex-direction: column;
	align-items: flex-start;
	gap: 0.1rem;
	padding-right: 0.35rem;
}
.header-phone.is-stacked::before {
	content: "Call us";
	font-size: 0.6875rem;
	font-weight: 700;
	letter-spacing: 0.12em;
	text-transform: uppercase;
	color: var(--wp--preset--color--contrast-2);
}
.header-phone.is-stacked .header-phone__icon { display: none; }
.header-phone.is-stacked .header-phone__number {
	font-size: 1.1875rem;
	font-weight: 700;
	line-height: 1.05;
	color: var(--wp--preset--color--accent);
}

/* --------------------------------------------------------------------------
   27. Application link
   The application is a hosted Microsoft Form we send people to rather than
   embed, so this is the handover: what it asks for, the button, and what
   happens to their answers.
   -------------------------------------------------------------------------- */
.application-link__note {
	margin-top: var(--wp--preset--spacing--30);
	font-size: var(--wp--preset--font-size--small);
	color: var(--wp--preset--color--contrast-2);
	max-width: 46ch;
}

.application-fallback p:first-child { margin-top: 0; }

/* --------------------------------------------------------------------------
   28. Enquiry form
   The site's own form rather than a plugin's, so it inherits the type and the
   spacing instead of fighting them. Single column on purpose: a two-column
   form reads as a database record to fill in, and this is meant to read as
   the start of a conversation.
   -------------------------------------------------------------------------- */
/* Sits in a 58% column on the contact page. A fixed 34rem overflowed into the
   details column beside it, so the cap was dropped to 100% - which then let the
   inputs run the full width of that column, a very long box to type a name
   into. min() gives the readable measure back without it ever being able to
   exceed the column. */
.enquiry { max-width: min(34rem, 100%); }

/* A short answer does not need a long box. Telephone numbers in particular
   look wrong in a field sized for a sentence. */
.enquiry input[type="tel"] { max-width: 15rem; }

.enquiry__field { margin: 0 0 var(--wp--preset--spacing--40); }

.enquiry__field label {
	display: block;
	margin-bottom: 0.4rem;
	font-weight: 600;
	font-stretch: var(--wp--custom--width--condensed);
	letter-spacing: 0.01em;
}

.enquiry__req,
.enquiry__opt {
	font-weight: 400;
	font-stretch: var(--wp--custom--width--normal);
	color: var(--wp--preset--color--contrast-2);
	font-size: var(--wp--preset--font-size--small);
}

.enquiry input,
.enquiry select,
.enquiry textarea {
	width: 100%;
	padding: 0.7rem 0.85rem;
	font: inherit;
	color: var(--wp--preset--color--contrast);
	background-color: var(--wp--preset--color--base);
	border: 1px solid color-mix(in srgb, var(--wp--preset--color--contrast) 30%, transparent);
	border-radius: 0;
}

.enquiry input:focus-visible,
.enquiry select:focus-visible,
.enquiry textarea:focus-visible {
	outline: 2px solid var(--wp--preset--color--primary);
	outline-offset: 1px;
	border-color: transparent;
}

.enquiry textarea { resize: vertical; }

/* Errors are announced, so they need to be findable as well as audible. */
.enquiry__error {
	margin: 0 0 var(--wp--preset--spacing--40);
	padding: var(--wp--preset--spacing--30);
	background-color: color-mix(in srgb, var(--wp--preset--color--primary) 10%, transparent);
	border-left: 3px solid var(--wp--preset--color--primary);
	font-weight: 500;
}

.enquiry__note {
	margin-top: var(--wp--preset--spacing--40);
	font-size: var(--wp--preset--font-size--small);
	color: var(--wp--preset--color--contrast-2);
}

.form-link__note,
.form-pending {
	font-size: var(--wp--preset--font-size--small);
	color: var(--wp--preset--color--contrast-2);
	max-width: 46ch;
}

/* --------------------------------------------------------------------------
   29. Design team
   A photograph beside a paragraph, repeated. Not the staff grid: this page has
   to show judgement rather than headcount, and that needs room to read.
   -------------------------------------------------------------------------- */
.design-team { display: grid; gap: var(--wp--preset--spacing--50); }

.design-person { display: grid; gap: var(--wp--preset--spacing--40); align-items: start; }

@media (min-width: 40rem) {
	.design-person { grid-template-columns: 12rem 1fr; }
}

.design-person__img { width: 100%; height: auto; display: block; }

.design-person__name {
	margin: 0;
	font-size: var(--wp--preset--font-size--large);
	font-stretch: var(--wp--custom--width--condensed);
	line-height: 1.1;
}

.design-person__creds {
	font-size: var(--wp--preset--font-size--small);
	font-weight: 500;
	font-stretch: var(--wp--custom--width--normal);
	color: var(--wp--preset--color--contrast-2);
	letter-spacing: 0.04em;
}

.design-person__role {
	margin: 0.3rem 0 0;
	font-size: var(--wp--preset--font-size--small);
	font-weight: 700;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: var(--wp--preset--color--primary);
}

.design-person__bio { margin-top: var(--wp--preset--spacing--30); max-width: 62ch; }
.design-person__bio p:first-child { margin-top: 0; }

/* The photograph we have of the office cat is small, and stretching it to a
   12rem column would show every pixel. */
/* One ratio for all of them. The headshots arrived square, portrait, and
   whatever the cat photo is; left alone the column looked like four different
   documents. Cropped to a consistent portrait so the page reads as one team. */
.design-person__photo { max-width: 12rem; }
.design-person__photo .design-person__img {
	aspect-ratio: 4 / 5;
	object-fit: cover;
	object-position: center 20%;
}

/* --------------------------------------------------------------------------
   30. Testimonials
   Salvaged from a page nobody linked to. Set larger than body copy because a
   named client saying it is worth more than anything we write about ourselves.
   -------------------------------------------------------------------------- */
.testimonials { display: grid; gap: var(--wp--preset--spacing--50); }

@media (min-width: 52rem) {
	.testimonials { grid-template-columns: repeat(2, 1fr); }
}

.testimonial { margin: 0; }

.testimonial__quote {
	margin: 0;
	padding: 0 0 0 var(--wp--preset--spacing--30);
	border-left: 3px solid var(--wp--preset--color--primary);
	font-size: 1.0625rem;
	line-height: 1.6;
}

.testimonial__quote p:first-child { margin-top: 0; }
.testimonial__quote p:last-child { margin-bottom: 0; }

.testimonial__who {
	margin-top: var(--wp--preset--spacing--30);
	padding-left: calc(var(--wp--preset--spacing--30) + 3px);
	font-size: var(--wp--preset--font-size--small);
}

.testimonial__name { display: block; font-weight: 700; }
.testimonial__role,
.testimonial__org { display: block; color: var(--wp--preset--color--contrast-2); }

/* --------------------------------------------------------------------------
   31. Pillar grid, illustrated
   The four pillars are the argument the site is built on, and they were the
   only part of it with nothing to look at. The photograph sits above the
   number so the eye lands on the work first and reads the label second.
   -------------------------------------------------------------------------- */
/*
 * A slice, not a picture.
 *
 * At 4:3 the four tiles committed most of the first screen to photographs
 * before the page had said anything. Cropping to a wide band keeps the warmth
 * they were added for and gives the height back. Kept as a custom property
 * because the right ratio is a judgment call - 4/1 or 3/1 if 5/1 reads as too
 * thin at your window width.
 */
.pillar-grid--illustrated { --pillar-slice: 5 / 1; }

.pillar-grid__media {
	display: block;
	margin-bottom: var(--wp--preset--spacing--30);
	aspect-ratio: var(--pillar-slice, 4 / 3);
	overflow: hidden;
	background-color: var(--wp--preset--color--base-2);
}

.pillar-grid__img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
	transition: transform 240ms ease;
}

.pillar-grid__item:hover .pillar-grid__img { transform: scale(1.03); }

@media (prefers-reduced-motion: reduce) {
	.pillar-grid__img { transition: none; }
	.pillar-grid__item:hover .pillar-grid__img { transform: none; }
}

/* --------------------------------------------------------------------------
   32. Case study
   Only three projects carry one. It has to read as a longer piece of writing
   than the page around it without becoming a different website: same type,
   more room, and a measure that suits paragraphs rather than captions.
   -------------------------------------------------------------------------- */
.case-study { max-width: 42rem; }

.case-study__heading {
	margin: 0.25rem 0 var(--wp--preset--spacing--40);
	font-size: var(--wp--preset--font-size--x-large);
	font-stretch: var(--wp--custom--width--condensed);
	line-height: 1.05;
}

.case-study__body h3 {
	margin-top: var(--wp--preset--spacing--50);
	font-stretch: var(--wp--custom--width--condensed);
}

.case-study__body h3:first-child { margin-top: 0; }

.case-study__body p { max-width: 68ch; }

/* The one sentence in each section worth stopping on. */
.case-study__pull {
	margin: var(--wp--preset--spacing--40) 0;
	padding-left: var(--wp--preset--spacing--30);
	border-left: 3px solid var(--wp--preset--color--primary);
	font-size: 1.1875rem;
	line-height: 1.45;
	font-style: italic;
	color: var(--wp--preset--color--contrast);
}

/* --------------------------------------------------------------------------
   Craft galleries on the trades pages
   Core lays nested gallery images out with flex-grow:1, so a last row holding
   one image stretches it to full width - four photographs came out as three
   thumbnails and one billboard. Pinning the growth keeps every tile the size
   the column count promised, and a fixed ratio stops portrait and landscape
   originals from setting different row heights.
   -------------------------------------------------------------------------- */
.wp-block-gallery.has-nested-images figure.wp-block-image {
	flex-grow: 0;
}

.wp-block-gallery.has-nested-images figure.wp-block-image img {
	width: 100%;
	aspect-ratio: 4 / 3;
	object-fit: cover;
}

/* --------------------------------------------------------------------------
   Trades story sections
   Alternating image-and-text describing a capability. The originals are a
   mixture of portrait and landscape shot over twenty years, so a fixed ratio
   stops each section setting its own height and the column rhythm breaking.
   -------------------------------------------------------------------------- */
.trade-section {
	margin-block: var(--wp--preset--spacing--70);
	gap: var(--wp--preset--spacing--50);
}

.trade-section .wp-block-media-text__media img {
	width: 100%;
	aspect-ratio: 4 / 3;
	object-fit: cover;
	display: block;
}

/* Stacked on a phone, the image should lead rather than follow the words. */
@media (max-width: 600px) {
	.trade-section {
		margin-block: var(--wp--preset--spacing--60);
	}
	.trade-section .wp-block-media-text__media img {
		aspect-ratio: 3 / 2;
	}
}

/* --------------------------------------------------------------------------
   Footer social
   --------------------------------------------------------------------------
   Three accounts, two of them LinkedIn. Two identical LinkedIn glyphs side by
   side tells a visitor nothing about which company they are about to open, so
   each link carries its name rather than relying on the icon alone. The icons
   are inline SVG: the footer is on every page and a webfont or a sprite would
   be a network request for three shapes that never change.
   -------------------------------------------------------------------------- */
.footer-social {
	display: flex;
	flex-direction: column;
	gap: 0.55rem;
	margin-top: var(--wp--preset--spacing--40);
}

.footer-social__link {
	display: inline-flex;
	align-items: center;
	gap: 0.55rem;
	font-size: var(--wp--preset--font-size--small);
	text-decoration: none;
	/* The footer link colour is inherited; underline only on interaction so a
	   column of three does not read as a wall of rules. */
	color: inherit;
}

.footer-social__link:hover,
.footer-social__link:focus-visible {
	text-decoration: underline;
	text-underline-offset: 0.2em;
}

.footer-social__link:focus-visible {
	outline: 2px solid var(--wp--preset--color--primary);
	outline-offset: 3px;
}

.footer-social__icon {
	flex: 0 0 auto;
	width: 1.15rem;
	height: 1.15rem;
}

/* The eyebrow above the four cards. Small, condensed, quiet — it frames the
   grid without competing with the titles, which carry the angled rule. */
.pillar-grid__lede {
	margin: 0 0 var(--wp--preset--spacing--40);
	font-size: var(--wp--preset--font-size--small);
	font-stretch: var(--wp--custom--width--condensed);
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: var(--wp--preset--color--contrast-2);
}

/* Somebody without a photograph gets their initials. The markup for this
   existed and the styling did not, so the initials rendered as default-size
   inline text in the top-left corner of the 3:4 frame - which read as a bug
   rather than as a placeholder. Centred and sized, it reads as intended. */
.staff-card__media--empty {
	display: grid;
	place-items: center;
}

.staff-card__initials {
	font-size: var(--wp--preset--font-size--x-large);
	font-stretch: var(--wp--custom--width--condensed);
	font-weight: 800;
	letter-spacing: 0.02em;
	color: color-mix(in srgb, var(--wp--preset--color--contrast) 32%, transparent);
}
