/*
 * PRASPEKT (cement.bg): global styles. HANDOFF §3 and §5; Figma file aXBJMQumEEita5WCVzMSQH.
 * Token variables only (assets/css/tokens.css, generated from theme.json); no typed design values.
 * Where Figma uses a value off the spacing scale, the nearest step is used and noted.
 * Breakpoints (theme.json custom.breakpoint): 768 tablet, 1024 desktop (the header switches), 1440 wide.
 */

/* ---------- Base ---------- */

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

html {
	-webkit-text-size-adjust: 100%;
	text-size-adjust: 100%;
	background: var(--color-silo-white);
	scroll-padding-top: var(--header-height-scrolled);
}

@media (prefers-reduced-motion: no-preference) {
	html {
		scroll-behavior: smooth;
	}
}

body {
	margin: 0;
	background: var(--color-silo-white);
	color: var(--color-ink);
	font-family: var(--font-geologica);
	font-size: var(--font-size-body);
	font-weight: var(--font-weight-regular);
	line-height: var(--line-height-body);
	/* Text enlarged in the browser (a phone's font size, 200 %) must not run out of a narrow screen: a word breaks only if it can't fit. */
	overflow-wrap: break-word;
	-webkit-font-smoothing: antialiased;
	-moz-osx-font-smoothing: grayscale;
}

h1,
h2,
h3,
h4,
p,
ul,
ol,
figure,
blockquote {
	margin: 0;
}

:where(ul[role='list'], ol[role='list']) {
	padding: 0;
	list-style: none;
}

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

img,
video {
	height: auto;
}

button,
input,
select,
textarea {
	font: inherit;
	color: inherit;
}

a {
	color: inherit;
	text-decoration-thickness: var(--border-hairline);
	text-underline-offset: var(--space-4);
}

main:focus {
	outline: none;
}

/* Focus (HANDOFF §5.9): 2 px, 3 px off, on every interactive element. Ink on light; Signal Green on Ink and on photos. */
:focus-visible {
	outline: var(--focus-width) solid var(--focus-color, var(--color-ink));
	outline-offset: var(--focus-offset);
}

.on-dark,
.on-photo {
	--focus-color: var(--color-signal-green);
	color: var(--color-white);
}

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

.skip-link {
	position: fixed;
	top: var(--space-16);
	left: var(--space-16);
	z-index: 100;
	padding: var(--space-16) var(--space-24);
	background: var(--color-ink);
	color: var(--color-white);
	font-size: var(--font-size-button);
	font-weight: var(--font-weight-strong);
	line-height: var(--line-height-button);
	letter-spacing: var(--letter-spacing-button);
	text-transform: uppercase;
	text-decoration: none;
	transform: translateY(calc(-100% - var(--space-32)));
	--focus-color: var(--color-signal-green);
}

.skip-link:focus {
	transform: none;
}

/* Its ring is Signal Green over a photo (the header transparent) and Ink once the header behind it is solid and light
   (a page without a hero, or scrolled): HANDOFF §5.9. A browser without :has() keeps the green. */
body:has(.header:is([data-header='solid'], .is-scrolled)) .skip-link {
	--focus-color: var(--color-ink);
}

/* ---------- Layout: 12 columns at 1440 (margins 80, gutters 24), 8 at 768, 4 at 375; fluid between ---------- */

.container {
	width: 100%;
	max-width: calc(var(--layout-content) + var(--space-margin) * 2);
	margin-inline: auto;
	padding-inline: var(--space-margin);
}

.grid {
	display: grid;
	grid-template-columns: repeat(var(--grid-columns-mobile), minmax(0, 1fr));
	column-gap: var(--grid-gutter);
}

@media (min-width: 768px) {
	.grid {
		grid-template-columns: repeat(var(--grid-columns-tablet), minmax(0, 1fr));
	}
}

@media (min-width: 1024px) {
	.grid {
		grid-template-columns: repeat(var(--grid-columns), minmax(0, 1fr));
	}
}

/* ---------- Type (HANDOFF §3). Uppercase always from CSS, so <html lang> picks the right rules (Turkish İ/ı). ---------- */

/* Headings sit in flex and grid boxes whose least width is their longest word, so with text enlarged (a phone's font size, 200 %)
   a word like "infrastructure" would push out of a narrow screen. They may break inside a word, but only when it can't fit. */
h1,
h2,
h3,
.display,
.h2,
.h3 {
	overflow-wrap: anywhere;
}

.display {
	font-size: var(--font-size-display);
	font-weight: var(--font-weight-strong);
	line-height: var(--line-height-display);
	letter-spacing: var(--letter-spacing-display-mobile);
}

.h2 {
	font-size: var(--font-size-h2);
	font-weight: var(--font-weight-strong);
	line-height: var(--line-height-h2);
	letter-spacing: var(--letter-spacing-h2-mobile);
}

@media (min-width: 768px) {
	.display {
		letter-spacing: var(--letter-spacing-display);
	}

	.h2 {
		letter-spacing: var(--letter-spacing-h2);
	}
}

.h3 {
	font-size: var(--font-size-h3);
	font-weight: var(--font-weight-strong);
	line-height: var(--line-height-h3);
}

.figure {
	font-size: var(--font-size-figure);
	font-weight: var(--font-weight-strong);
	line-height: var(--line-height-figure);
	letter-spacing: var(--letter-spacing-figure);
	font-variant-numeric: tabular-nums;
}

.lead {
	font-size: var(--font-size-lead);
	line-height: var(--line-height-lead);
}

.small {
	font-size: var(--font-size-small);
	line-height: var(--line-height-small);
}

.eyebrow {
	font-size: var(--font-size-eyebrow);
	font-weight: var(--font-weight-strong);
	line-height: var(--line-height-eyebrow);
	letter-spacing: var(--letter-spacing-eyebrow);
	text-transform: uppercase;
}

/* The Button style: buttons, nav links, text links, the footer's page and terminal links (and .button-type text). */
.button,
.button-type,
.text-link,
.header__link,
.footer__link {
	font-size: var(--font-size-button);
	font-weight: var(--font-weight-strong);
	line-height: var(--line-height-button);
	letter-spacing: var(--letter-spacing-button);
	text-transform: uppercase;
}

/* ---------- Icons: 24 px UI icons in currentColor; 12 px where small ---------- */

.ui-icon {
	flex: none;
	width: var(--icon-ui-size);
	height: var(--icon-ui-size);
}

.ui-icon--small {
	width: var(--icon-ui-small);
	height: var(--icon-ui-small);
}

/* The link Dart fills its 12 px box in Figma; its SVG sits on the 24 px grid, so it's drawn at 24 inside a 12 px slot. */
.ui-icon--dart {
	margin: calc((var(--icon-ui-small) - var(--icon-ui-size)) / 2);
}

/* The logo (interim trace): one <symbol> per page (the build's @use), drawn in currentColor, so only ever Ink or white. */
.logo {
	width: auto;
	height: var(--header-logo-height-mobile);
}

.sprite {
	position: absolute;
	width: 0;
	height: 0;
	overflow: hidden;
}

/* ---------- Buttons (HANDOFF §5.9, Figma 5:15): 48 tall, 0 × 28, square ---------- */

.button {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-height: var(--button-height);
	padding: 0 var(--button-padding-x);
	border: 0;
	border-radius: var(--border-radius);
	background: var(--color-ink);
	color: var(--color-white);
	text-align: center;
	text-decoration: none;
	cursor: pointer;
	transition:
		background-color var(--motion-button-duration) var(--motion-ease),
		color var(--motion-button-duration) var(--motion-ease),
		border-color var(--motion-button-duration) var(--motion-ease),
		transform var(--motion-press-duration) var(--motion-ease);
}

.button:hover {
	background: var(--color-slate);
}

/* Primary on Ink or over a photo. */
.button--accent {
	background: var(--color-signal-green);
	color: var(--color-ink);
}

.button--accent:hover {
	background: var(--color-white);
}

/* Secondary: an outline, filled on hover. */
.button--secondary,
.button--secondary-on-dark {
	border: var(--border-button-outline) solid currentColor;
	background: transparent;
}

.button--secondary {
	color: var(--color-ink);
}

.button--secondary:hover {
	border-color: var(--color-ink);
	background: var(--color-ink);
	color: var(--color-white);
}

.button--secondary-on-dark {
	color: var(--color-white);
}

.button--secondary-on-dark:hover {
	border-color: var(--color-white);
	background: var(--color-white);
	color: var(--color-ink);
}

/* ---------- Text links (Figma 5:22): the Button style, then the Dart or the external icon, 8 apart ---------- */

.text-link {
	display: inline-flex;
	align-items: center;
	gap: var(--space-8);
	color: inherit;
	text-decoration: none;
}

.text-link__label {
	text-decoration: underline var(--border-hairline) transparent;
	text-underline-offset: var(--space-4);
	transition: text-decoration-color var(--motion-button-duration) var(--motion-ease);
}

.text-link:hover .text-link__label {
	text-decoration-color: currentColor;
}

.text-link .ui-icon--dart {
	transition: transform var(--motion-button-duration) var(--motion-ease);
}

.text-link:hover .ui-icon--dart {
	transform: translateX(var(--space-4));
}

/* ---------- Sections: section padding (120 → 72); Silo White by default ---------- */

/* Pages without a hero (the product page, the privacy policy, the 404): the header is solid from the start, so the
   content starts under it. */
.header[data-header='solid'] ~ main {
	padding-top: var(--header-height-mobile);
}

@media (min-width: 1024px) {
	.header[data-header='solid'] ~ main {
		padding-top: var(--header-height);
	}
}

.section {
	padding-block: var(--space-section);
}

.section--cement {
	background: var(--color-cement);
}

/* Section heading (Figma 5:48): the eyebrow rule above a centred H2, 16 apart. */
.section-heading {
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: var(--space-16);
	text-align: center;
}

/* The eyebrow rule (HANDOFF §5.1): 48 × 8, a 2 px line ending in the Dart. */
.eyebrow-rule {
	flex: none;
	width: var(--space-48);
	height: var(--space-8);
}

/* The Notch (HANDOFF §5.1): the V cut in the left edge, 0.25 × the height deep, its point at mid-height. A mask
   from the brand's notch bar (praspekt-notch-bar-40, its height set to the element's) plus a fill over the right
   half, so the cut grows with the bar when a label wraps (clip-path would need the height up front). Valid while
   the bar is at most 14 times as wide as it is tall. */
.notch {
	-webkit-mask:
		url('/assets/brand/notch/praspekt-notch-bar-40-ink.svg') left / auto 100% no-repeat,
		linear-gradient(var(--color-ink) 0 0) right / 50% 100% no-repeat;
	mask:
		url('/assets/brand/notch/praspekt-notch-bar-40-ink.svg') left / auto 100% no-repeat,
		linear-gradient(var(--color-ink) 0 0) right / 50% 100% no-repeat;
}

/* Split intro (R4; Home H.3, About A.2): the H2 in columns 1–5, the text from column 7. Below 1024 stacked, 24
   apart. Figma pads this frame 120 on every side; the grid's 80 margin is used, as everywhere else. */
.split {
	row-gap: var(--space-24);
}

.split > * {
	grid-column: 1 / -1;
}

.split__body {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: var(--space-24);
}

@media (min-width: 1024px) {
	.split__title {
		grid-column: 1 / span 5;
	}

	.split__body {
		grid-column: 7 / -1;
	}
}

/* Photo cards (Figma 13:37; Home H.4): a 4:3 photo, the H3, the text, 24 apart. One column below 1024 (32
   apart), three from 1024. The photo zooms on hover. */
.cards {
	display: grid;
	gap: var(--space-32);
	margin: 0;
}

@media (min-width: 1024px) {
	.cards {
		grid-template-columns: repeat(3, minmax(0, 1fr));
		gap: var(--grid-gutter);
	}
}

.photo-card {
	display: flex;
	flex-direction: column;
	gap: var(--space-24);
}

.photo-card__media {
	aspect-ratio: 4 / 3;
	overflow: hidden;
}

.photo-card__image {
	width: 100%;
	height: 100%;
	object-fit: cover;
}

@media (hover: hover) and (prefers-reduced-motion: no-preference) {
	.photo-card__image {
		transition: transform var(--motion-hover-duration) var(--motion-ease);
	}

	.photo-card:hover .photo-card__image {
		transform: scale(var(--motion-hover-zoom));
	}
}

/* Missing assets (HANDOFF §7): a 1 px dashed Slate outline and the slot's name in Small Slate, as the Figma slots,
   with data-pending="asset" and data-slot until the client's file arrives. The context sets the size. */
.slot {
	display: flex;
	align-items: center;
	justify-content: center;
	min-height: var(--space-48);
	padding: var(--space-8) var(--space-16);
	border: var(--border-hairline) dashed var(--color-slate);
	color: var(--color-slate);
	font-size: var(--font-size-small);
	line-height: var(--line-height-small);
	text-align: center;
}

/* ---------- Header (HANDOFF §5.2, Figma 8:108) ---------- */

/* Fixed. The bar and the backdrop are layers, so the header changes state with opacity and transform only:
   on desktop it shrinks from 80 to 64 by moving the bar up 16 and the row up 8. */
.header {
	position: fixed;
	inset: 0 0 auto;
	z-index: 10;
	height: var(--header-height-mobile);
	color: var(--color-ink);
	pointer-events: none;
	--focus-color: var(--color-ink);
}

.header a,
.header button {
	pointer-events: auto;
}

.header__bar,
.header__backdrop {
	position: absolute;
	inset: 0 0 auto;
}

.header__bar {
	height: 100%;
	border-bottom: var(--border-hairline) solid var(--color-cement);
	background: var(--color-silo-white);
}

/* Over a photo: Ink at 55% for the first 48 px, clear at 128 (Figma: ink 50% → 0 over 140 px). Held, so the
   white links keep 4.5:1 over the brightest frame of the hero loop (measured: 3.2:1 with a plain fade). */
.header__backdrop {
	height: var(--space-128);
	background: linear-gradient(var(--color-header-backdrop) var(--space-48), transparent);
	opacity: 0;
}

.header__inner {
	position: relative;
	display: flex;
	align-items: center;
	gap: var(--space-32);
	height: 100%;
}

.header__logo {
	display: block;
	flex: none;
	color: inherit;
}

.header__nav {
	display: none;
	margin-inline-start: auto;
}

.header__links {
	display: flex;
	gap: var(--space-32);
	margin: 0;
}

.header__link {
	display: block;
	color: inherit;
	text-decoration: underline var(--border-hairline) transparent;
	text-underline-offset: var(--space-4);
	transition: text-decoration-color var(--motion-button-duration) var(--motion-ease);
}

.header__link:hover {
	text-decoration-color: currentColor;
}

.header__cta {
	display: none;
	flex: none;
}

/* The menu button: a 48 px target around the 24 px icon, the icon on the margin line. */
.menu-button,
.menu__close {
	display: inline-flex;
	flex: none;
	align-items: center;
	justify-content: center;
	width: var(--button-height);
	height: var(--button-height);
	margin-inline-end: calc((var(--icon-ui-size) - var(--button-height)) / 2);
	padding: 0;
	border: 0;
	background: none;
	color: inherit;
	cursor: pointer;
}

.menu-button {
	margin-inline-start: auto;
}

/* Without JavaScript it would do nothing; the footer's links are the way round. */
html:not(.js) .menu-button {
	display: none;
}

/* Over a photo or video hero, until 80 px of scroll: transparent, white, the green button. */
.header[data-header='over-photo']:not(.is-scrolled) {
	color: var(--color-white);
	--focus-color: var(--color-signal-green);
}

.header[data-header='over-photo']:not(.is-scrolled) .header__bar {
	opacity: 0;
}

.header[data-header='over-photo']:not(.is-scrolled) .header__backdrop {
	opacity: 1;
}

.header[data-header='over-photo']:not(.is-scrolled) .header__cta {
	background: var(--color-signal-green);
	color: var(--color-ink);
}

.header[data-header='over-photo']:not(.is-scrolled) .header__cta:hover {
	background: var(--color-white);
}

/* Transitions only once header.js has set the starting state, so a reload mid-page doesn't animate. */
.header.is-ready,
.header.is-ready .header__cta {
	transition:
		color var(--motion-header-duration) var(--motion-ease),
		background-color var(--motion-header-duration) var(--motion-ease);
}

.header.is-ready .header__bar,
.header.is-ready .header__backdrop,
.header.is-ready .header__inner {
	transition:
		opacity var(--motion-header-duration) var(--motion-ease),
		transform var(--motion-header-duration) var(--motion-ease);
}

@media (min-width: 1024px) {
	.header {
		height: var(--header-height);
	}

	.header .logo {
		height: var(--header-logo-height);
	}

	.header__nav {
		display: block;
	}

	.header__cta {
		display: inline-flex;
	}

	.menu-button {
		display: none;
	}

	.header.is-scrolled .header__bar {
		transform: translateY(calc(var(--header-height-scrolled) - var(--header-height)));
	}

	.header.is-scrolled .header__inner {
		transform: translateY(calc((var(--header-height-scrolled) - var(--header-height)) / 2));
	}
}

/* ---------- Mobile menu (HANDOFF §5.3, Figma 35:1070): a modal <dialog>, Ink, full screen ---------- */

html.menu-is-open {
	overflow: hidden;
}

.menu {
	position: fixed;
	inset: 0;
	flex-direction: column;
	width: 100%;
	max-width: none;
	height: 100%;
	max-height: none;
	margin: 0;
	padding: 0 var(--space-margin) var(--space-margin);
	overflow-y: auto;
	overscroll-behavior: contain;
	scroll-padding-top: calc(var(--header-height-mobile) + var(--space-8));
	border: 0;
	background: var(--color-ink);
	color: var(--color-white);
}

.menu[open] {
	display: flex;
}

.menu::backdrop {
	background: transparent;
}

/* The top row matches the header's, so the logo and the button don't move when the menu opens. Where the links are taller
   than the screen (a phone on its side, a page zoomed to 200 %) the panel scrolls under it, so the close button stays in reach. */
.menu__top {
	position: sticky;
	top: 0;
	z-index: 1;
	display: flex;
	flex: none;
	align-items: center;
	justify-content: space-between;
	height: var(--header-height-mobile);
	background: var(--color-ink);
}

/* Figma: the links start 140 from the top (64 + 80 here). */
.menu__nav {
	margin-top: calc(var(--space-64) + var(--space-16));
}

.menu__links {
	display: flex;
	flex-direction: column;
	gap: var(--space-16);
	margin: 0;
}

.menu__link {
	color: inherit;
	font-size: var(--font-size-menu);
	font-weight: var(--font-weight-strong);
	line-height: var(--line-height-menu);
	text-decoration: none;
}

.menu__cta {
	flex: none;
	width: 100%;
	margin-top: var(--space-48);
}

.menu__contact {
	display: flex;
	flex-direction: column;
	gap: var(--space-8);
	margin: auto 0 0;
	padding-top: var(--space-48);
	color: var(--color-cement);
}

.menu__contact a {
	text-decoration: none;
}

.menu__link:hover,
.menu__contact a:hover {
	text-decoration: underline;
}

@media (prefers-reduced-motion: no-preference) {
	.menu[open] {
		animation: menu-in var(--motion-menu-open) var(--motion-ease) both;
	}

	.menu[open] .menu__item {
		animation: rise var(--motion-menu-open) var(--motion-ease) both;
		animation-delay: calc(var(--i, 0) * var(--motion-menu-stagger));
	}

	.menu.is-closing {
		animation: menu-out var(--motion-menu-close) var(--motion-ease) both;
	}
}

@media (prefers-reduced-motion: reduce) {
	.menu[open] {
		animation: fade-in var(--motion-menu-reduced) linear both;
	}

	.menu.is-closing {
		animation: fade-out var(--motion-menu-reduced) linear both;
	}
}

@keyframes menu-in {
	from {
		opacity: 0;
		transform: translateX(var(--motion-reveal-distance));
	}
}

@keyframes menu-out {
	to {
		opacity: 0;
		transform: translateX(var(--motion-reveal-distance));
	}
}

@keyframes rise {
	from {
		opacity: 0;
		transform: translateY(var(--motion-reveal-distance));
	}
}

@keyframes fade-in {
	from {
		opacity: 0;
	}
}

@keyframes fade-out {
	to {
		opacity: 0;
	}
}

/* ---------- Contact block (HANDOFF §5.11, Figma 35:1001): the photo under Ink at 55%; the details in columns 1–5,
   the form card in 7–12. Below 1024 the card comes first, then the details, as in Figma (the heading stays first in
   the document). ---------- */

.contact {
	position: relative;
	isolation: isolate;
	padding-block: var(--space-section);
}

.contact__media {
	position: absolute;
	inset: 0;
	z-index: -1;
}

.contact__photo {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	object-fit: cover;
}

/* Ink at 58% (Figma: 55%). At 55% the address line was 4.30:1 where the white silo shows through the photo; at 58%
   nothing in the block is under 4.5:1 at 1024 to 1920 px (approved after the testing round, 3 October 2026). */
.contact__media::after {
	content: '';
	position: absolute;
	inset: 0;
	background: var(--color-photo-overlay);
}

/* Phones (the tall crop): Ink at 75%, as Figma's mobile frame. At 55% the Cement "Headquarters" was 3.6:1 over the
   bright shed behind it; at 75% it is 7.0:1 (approved at the second review). */
@media (max-width: 767px) {
	.contact__media::after {
		background: var(--color-photo-overlay-phone);
	}
}

.contact__body {
	row-gap: var(--space-32);
}

.contact__body > * {
	grid-column: 1 / -1;
}

.contact__card {
	order: -1;
	padding: var(--space-24);
	background: var(--color-white);
	color: var(--color-ink);
	--focus-color: var(--color-ink);
}

.contact__details {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: var(--space-24);
}

.contact__label {
	color: var(--color-cement);
}

.contact__details a {
	text-decoration: none;
}

.contact__details a:hover {
	text-decoration: underline;
}

@media (min-width: 768px) {
	.contact__card {
		padding: var(--form-card-padding);
	}
}

@media (min-width: 1024px) {
	.contact__body {
		align-items: start;
	}

	.contact__details {
		grid-column: 1 / span 5;
	}

	.contact__card {
		order: 0;
		grid-column: 7 / -1;
	}
}

/* The form (Figma 5:67, 5:68): labels above the fields (Eyebrow, Slate), a 1 px Slate line under each, 2 px Ink
   on focus and when invalid; no placeholders. Errors under the field (Small, Ink, 600); one accent only, no red. */
.contact__card > .h3 {
	margin-bottom: var(--space-24);
}

.form {
	display: flex;
	flex-direction: column;
	gap: var(--space-24);
}

.form__field {
	display: flex;
	flex-direction: column;
}

/* The focus ring (2 px, 3 px off) would cut through the label sitting right above the field; 4 px keeps it clear. */
.form__label {
	margin-bottom: var(--space-4);
	color: var(--color-slate);
}

.form__input {
	display: block;
	width: 100%;
	height: var(--space-48);
	margin: 0;
	padding: 0;
	border: 0;
	border-bottom: var(--border-form-line) solid var(--color-slate);
	border-radius: var(--border-radius);
	background: transparent;
	color: var(--color-ink);
	font-size: var(--font-size-body);
	line-height: var(--line-height-body);
	-webkit-appearance: none;
	appearance: none;
}

.form__input:focus,
.form__input[aria-invalid='true'] {
	border-bottom: var(--border-form-line-focus) solid var(--color-ink);
}

/* Figma: 144 tall. */
.form__input--message {
	height: calc(var(--space-48) * 3);
	padding-block: var(--space-8);
	resize: vertical;
}

/* The Subject: a native <select> drawn as Figma 5:68, the chevron (16) at the right. */
.form__select {
	position: relative;
}

.form__select .form__input {
	padding-inline-end: var(--space-24);
	cursor: pointer;
}

.form__chevron {
	position: absolute;
	top: 50%;
	right: 0;
	width: var(--space-16);
	height: var(--space-16);
	transform: translateY(-50%);
	pointer-events: none;
}

.form__error,
.form__failure {
	color: var(--color-ink);
	font-weight: var(--font-weight-strong);
}

.form__error {
	margin-top: var(--space-8);
}

.form__failure:empty {
	display: none;
}

.form__consent {
	color: var(--color-slate);
}

.form__submit {
	width: 100%;
}

.form__submit[aria-disabled='true'] {
	cursor: progress;
}

.form__success:focus {
	outline: none;
}

/* ---------- Footer (HANDOFF §5.12, Figma 35:1069) ---------- */

/* Figma: 96 top on desktop, 72 on mobile; 32 at the bottom (40 on desktop); 64 between the rows (40 → 48 on mobile). */
.footer {
	padding-block: min(var(--space-section), var(--space-96)) var(--space-32);
	background: var(--color-ink);
}

.footer__top {
	display: grid;
	gap: var(--space-48);
}

.footer__about {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: var(--space-24);
}

.footer .logo {
	height: var(--header-logo-height);
}

.footer__text {
	color: var(--color-cement);
}

/* The KRIB logo (14 October 2026): "Member of" (Eyebrow, Cement) over the logo in its own colours on a White tile, 16 apart, 32 under the text. */
.footer__member {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: var(--space-16);
	margin-top: var(--space-32);
}

/* A row across the whole footer, centred, above the terminals (15 October 2026). */
.footer__members {
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	align-items: flex-end;
	gap: var(--space-32) var(--space-48);
	grid-column: 1 / -1;
}

.footer__members .footer__member {
	margin-top: 0;
}

/* The three membership logos (white), in a row, 24 apart; they wrap on narrow screens. */
.footer__member-list {
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	align-items: center;
	gap: var(--space-16) var(--space-24);
	margin: 0;
	padding: 0;
	list-style: none;
}

.footer__member-link {
	display: inline-flex;
}

/* Membership logos: the white copy and the colour copy stacked; the colour fades in on hover and keyboard focus. */
.footer__member-list .footer__member-link {
	display: inline-grid;
}

.footer__member-list .footer__member-link > picture {
	grid-area: 1 / 1;
}

.footer__member-logo--colour {
	opacity: 0;
}

.footer__member-link:hover .footer__member-logo--colour,
.footer__member-link:focus-visible .footer__member-logo--colour {
	opacity: 1;
}

.footer__member-link:hover .footer__member-logo--white,
.footer__member-link:focus-visible .footer__member-logo--white {
	opacity: 0;
}

@media (prefers-reduced-motion: no-preference) {
	.footer__member-logo--white,
	.footer__member-logo--colour {
		transition: opacity var(--motion-hover-duration) var(--motion-ease);
	}
}

.footer__bibg-logo {
	display: block;
	height: 3.5rem;
	width: auto;
}

.footer__member-logo {
	display: block;
	width: auto;
	height: 3rem;
}

.footer__column {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: var(--space-16);
}

.footer__label {
	color: var(--color-cement);
}

/* Links 24 tall (4 above and below the 16 px line), 28 apart as in Figma (16 + 12). */
.footer__list {
	display: flex;
	flex-direction: column;
	gap: var(--space-4);
	margin: calc(var(--space-4) * -1) 0;
}

/* Flex items, so the body text's line box doesn't add to each link's 24 px. */
.footer__list > li {
	display: flex;
}

.footer__link {
	display: inline-flex;
	align-items: center;
	gap: var(--space-8);
	padding-block: var(--space-4);
	color: var(--color-white);
	text-decoration: underline var(--border-hairline) transparent;
	text-underline-offset: var(--space-4);
	transition: text-decoration-color var(--motion-button-duration) var(--motion-ease);
}

.footer__link:hover {
	text-decoration-color: currentColor;
}

/* The six bases: a row under the columns, spread across the full width (from 1024 one line, space-between; below that
   wrapped, three or two a row), each link 24 tall as in the lists above. */
.footer__terminals {
	display: grid;
	grid-column: 1 / -1;
	grid-template-columns: repeat(2, minmax(0, max-content));
	gap: var(--space-4) var(--space-24);
	margin: 0;
	padding-top: var(--space-24);
	border-top: var(--border-hairline) solid var(--color-hairline-on-dark);
}

.footer__terminals > li {
	display: flex;
}

@media (min-width: 768px) {
	.footer__terminals {
		grid-template-columns: repeat(3, minmax(0, max-content));
		justify-content: space-between;
		row-gap: var(--space-8);
	}
}

@media (min-width: 1024px) {
	.footer__terminals {
		grid-template-columns: repeat(6, max-content);
	}
}

.footer__contact {
	display: flex;
	flex-direction: column;
	gap: var(--space-8);
}

.footer__contact a {
	text-decoration: none;
}

.footer__contact a:hover {
	text-decoration: underline;
}

.footer__bottom {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: var(--space-16);
	margin-top: var(--space-48);
	padding-top: var(--space-16);
	border-top: var(--border-hairline) solid var(--color-hairline-on-dark);
}

.footer__legal {
	color: var(--color-cement);
}

@media (min-width: 768px) {
	.footer__top {
		grid-template-columns: repeat(var(--grid-columns-tablet), minmax(0, 1fr));
		column-gap: var(--grid-gutter);
	}

	.footer__about {
		grid-column: 1 / -1;
	}

	.footer__pages {
		grid-column: 1 / span 3;
	}

	.footer__info {
		grid-column: 4 / -1;
	}

	.footer__bottom {
		flex-direction: row;
		align-items: center;
		justify-content: space-between;
		padding-top: var(--space-24);
	}
}

@media (min-width: 1024px) {
	.footer__top {
		grid-template-columns: repeat(var(--grid-columns), minmax(0, 1fr));
	}

	.footer__about {
		grid-column: 1 / span 5;
	}

	.footer__pages {
		grid-column: 7 / span 2;
	}

	.footer__info {
		grid-column: 9 / -1;
	}

	.footer__bottom {
		margin-top: var(--space-64);
	}
}

/* ---------- Motion (HANDOFF §5.13): hidden-until-revealed only once motion.js has added .motion-ready ---------- */

@media (prefers-reduced-motion: no-preference) {
	.motion-ready .reveal,
	.motion-ready .stagger > * {
		transition:
			opacity var(--motion-reveal-duration) var(--motion-ease),
			transform var(--motion-reveal-duration) var(--motion-ease);
		transition-delay: calc(var(--i, 0) * var(--motion-stagger));
	}

	.motion-ready .reveal:not(.is-in),
	.motion-ready .stagger:not(.is-in) > * {
		opacity: 0;
		transform: translateY(var(--motion-reveal-distance));
	}

	/* The eyebrow rule draws like a map's route (site-map §1.4): its line grows from the left, then its Dart appears. */
	.motion-ready .eyebrow-rule rect {
		transform-box: fill-box;
		transform-origin: left;
		transition: transform var(--motion-route-draw) var(--motion-ease);
	}

	.motion-ready .eyebrow-rule polygon {
		transition: opacity var(--motion-stagger) linear var(--motion-route-draw);
	}

	.motion-ready .eyebrow-rule:not(.is-in) rect {
		transform: scaleX(0);
	}

	.motion-ready .eyebrow-rule:not(.is-in) polygon {
		opacity: 0;
	}
}

/* ---------- Motion that answers the visitor (14 October 2026, from the find-animation-opportunities review) ---------- */

/* Press feedback: a pressed button gives a little (not while it is busy sending). */
@media (prefers-reduced-motion: no-preference) {
	.button:active:not([aria-disabled='true']) {
		transform: scale(var(--motion-press-scale));
	}
}

/* The form's moments: a field's error comes in with a short fade and a 4 px rise instead of popping in and shoving the fields below
   down (reduced motion: the fade only); the success message rises in like the page's reveals, in place of the form. */
@keyframes error-in {
	from {
		opacity: 0;
		transform: translateY(-4px);
	}
}

.form__error:not([hidden]) {
	animation: fade-in var(--motion-error-duration) linear both;
}

@media (prefers-reduced-motion: no-preference) {
	.form__error:not([hidden]) {
		animation: error-in var(--motion-error-duration) var(--motion-ease) both;
	}

	.form__success:not([hidden]) {
		animation: rise var(--motion-reveal-duration) var(--motion-ease) both;
	}
}

/* The click-to-load embeds (the film, the map): the frame is created by script, starts transparent and fades in once it has loaded
   (script adds .is-loaded; a 3 s fallback in case a load event never comes), instead of a white flash. */
.film__frame,
.hq-map__frame {
	opacity: 0;
	transition: opacity var(--motion-button-duration) var(--motion-ease);
}

.film__frame.is-loaded,
.hq-map__frame.is-loaded {
	opacity: 1;
}
