/* =============================================================================
   Contact form — Figma prototype frame 241:107
   Styles _partials/contact-modal.html. Load it on any page that includes that
   partial; it is not scoped to the home page.

   The same markup is two different things at two breakpoints, and the design
   adjustments swapped which is which:

     · above 768 — a collapsible panel, NOT an overlay. It sits directly beneath
       the page's final CTA band and expands downward, joining onto it. The band
       drops its bottom corners to meet it (see pages/home.css).
     · at 767 and below — a centred overlay dialog over a scrim. Expanding inline
       at phone widths pushed the footer most of a screen down.

   That is why the mobile rules undo so much: they are not adjustments to a
   panel, they are a different component built from the same DOM.

   The band this panel used to carry at its top is gone — it duplicated the CTA
   band that now always precedes it.

   The 767px cut is duplicated in assets/js/contact-form.js (MOBILE_BP).
   ========================================================================== */

/* Collapsed by default. Animating grid-template-rows from 0fr to 1fr is what
   lets an auto-height panel expand smoothly and push the footer down with it —
   a height transition cannot, because it has no number to animate to. */
.contact-modal {
	max-width: 931px; /* matches the CTA band it stacks under */
	margin: 0 auto 172px; /* flush to the band; Figma's gap before the footer */
	display: grid;
	grid-template-rows: 0fr;
	transition: grid-template-rows 0.55s cubic-bezier(0.22, 1, 0.36, 1);
}

.contact-modal.is-open {
	grid-template-rows: 1fr;
}

/* The chrome role, added by _templates/base.html on every page that does not
   place the panel itself. There is no CTA band above it to join onto and it only
   ever opens as the centred overlay, so closed it must take no room at all — the
   172px above would otherwise be a blank strip before the footer on 113 pages. */
.contact-modal--chrome {
	margin-bottom: 0;
}

/* No scrim in the inline role. */
.contact-modal__backdrop {
	display: none;
}

.contact-modal__panel {
	min-height: 0; /* lets the grid row collapse to zero */
	overflow: hidden;
	background: var(--color-cream);
	/* Joins onto the band above, so only the bottom corners are round. */
	border-radius: 0 0 var(--radius-panel) var(--radius-panel);
}

/* Only meaningful in the overlay role; contact-form.js also hides it from
   assistive tech above 768. */
.contact-modal__close {
	display: none;
}

@media (prefers-reduced-motion: reduce) {
	.contact-modal {
		transition: none;
	}
}

.contact-modal__body {
	padding: 70px 40px 64px;
	color: var(--color-carbon);
}

.contact-modal__intro {
	max-width: 594px;
	margin: 0 auto;
	text-align: center;
}

.contact-modal__eyebrow {
	margin: 0 0 var(--space-4);
	font-size: var(--text-xs);
	letter-spacing: 0.16em;
	color: var(--color-carbon);
}

.contact-modal__title {
	margin: 0 0 var(--space-4);
	font: 700 var(--text-3xl) / 1.15 var(--font-sans);
	letter-spacing: -0.02em;
	color: var(--color-carbon);
}

.contact-modal__desc {
	margin: 0;
	font-family: var(--font-sans);
	font-size: var(--text-sm);
	line-height: 1.5;
	color: var(--color-carbon);
}

.contact-modal__desc a {
	color: var(--color-carbon);
}

/* --- Form ----------------------------------------------------------------- */
/* Underlined fields: the label sits above the input and the rule belongs to the
   wrapper, so it spans both. */

.contact-form {
	max-width: 528px;
	margin: 24px auto 0;
}

.contact-form__field {
	margin-bottom: var(--space-4);
	border-bottom: 1px solid var(--color-carbon);
}

.contact-form__field label {
	display: block;
	font-family: var(--font-label);
	font-weight: 700;
	font-size: var(--text-2xs);
	letter-spacing: 0.1em;
	text-transform: uppercase;
	color: var(--color-carbon);
}


.contact-form__field input,
.contact-form__field textarea {
	display: block;
	width: 100%;
	border: none;
	background: transparent;
	outline: none;
	font-family: var(--font-sans);
	font-size: var(--text-md);
	color: var(--color-carbon);
	padding: var(--space-1) 0 var(--space-2);
}

.contact-form__field textarea {
	/* Starts one line high, exactly like the inputs, so its underline sits right
	   under the label instead of a couple of lines below it. rows="1" in the
	   markup sets that height; resize lets a longer message grow the box. */
	resize: vertical;
}

/* Honeypot: off-screen rather than display:none, because some bots skip inputs
   they can detect as hidden. Not focusable (tabindex=-1 in the markup) and
   aria-hidden, so it is inert for keyboard and screen-reader users alike. */
.contact-form__gotcha {
	position: absolute;
	left: -9999px;
	width: 1px;
	height: 1px;
	overflow: hidden;
}

/* Per-field validation message. Sits below its input, inside the wrapper that
   owns the underline, so the rule stays put when a message appears. */
/* Screen-reader only. The visible error signal is the orange field flag (the
   designer's spec has no per-field message); this text stays for assistive tech,
   reached through each field's aria-describedby, so the error is still described
   in words (WCAG 3.3.1) without showing on screen. When empty it carries `hidden`
   and drops out of the tree entirely. */
.contact-form__error {
	position: absolute;
	width: 1px;
	height: 1px;
	overflow: hidden;
	clip-path: inset(50%);
	white-space: nowrap;
}

/* Every field is required (the designer's rule). A missing one is flagged in
   brand orange (#FF5100) — its label and its underline — the moment submit is
   attempted; contact-form.js clears it as soon as the field has content.

   Colour is never the only signal — the field also carries aria-invalid, and the
   message below it says what is wrong in words (WCAG 1.4.1). */
.contact-form__field:has(input[aria-invalid="true"]),
.contact-form__field:has(textarea[aria-invalid="true"]) {
	border-bottom-color: var(--color-brand);
}

.contact-form__field:has(input[aria-invalid="true"]) label,
.contact-form__field:has(textarea[aria-invalid="true"]) label {
	color: var(--color-brand);
}

/* Form-level status. Announced via role="status" / aria-live="polite", so it is
   heard as well as seen. Neutral while sending; coloured on a result. */
.contact-form__status {
	margin: var(--space-4) 0 0;
	font-family: var(--font-sans);
	font-size: var(--text-sm);
	color: var(--color-carbon-soft);
}

.contact-form__status.is-error {
	color: var(--color-danger);
}

/* Success is carbon with an orange rule rather than a green: the palette has no
   success colour, and inventing a second one for a message that is already
   unambiguous in words was not worth it. */
.contact-form__status.is-success {
	padding-left: var(--space-3);
	border-left: 3px solid var(--color-brand);
	color: var(--color-carbon);
	font-weight: 700;
}

.contact-form__footer {
	margin-top: var(--space-6);
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 20px;
}

.contact-form__check {
	display: flex;
	align-items: center;
	gap: 10px;
	cursor: pointer;
}

.contact-form__check input {
	appearance: none;
	-webkit-appearance: none;
	width: 18px;
	height: 18px;
	margin: 0;
	border: 1.5px solid var(--color-carbon);
	border-radius: 5px;
	cursor: pointer;
}

.contact-form__check input:checked {
	background: var(--color-carbon);
	box-shadow: inset 0 0 0 3px var(--color-cream);
}

.contact-form__check span {
	font-family: var(--font-sans);
	font-size: var(--text-sm);
	color: var(--color-carbon);
}

.contact-form__send {
	padding: var(--space-2) var(--space-4);
	border: none;
	border-radius: var(--radius-pill);
	background: var(--color-carbon);
	color: var(--color-cream);
	font-family: var(--font-label);
	font-weight: 700;
	font-size: var(--text-xs);
	letter-spacing: 0.12em;
	text-transform: uppercase;
	cursor: pointer;
	transition: background var(--transition);
}

.contact-form__send:hover {
	background: var(--color-black);
}

.contact-form__send:disabled {
	opacity: 0.55;
	cursor: progress;
}

@media (max-width: 980px) {
	.contact-modal__body {
		padding: 56px 24px 64px;
	}
}

/* --- Success screen ------------------------------------------------------- */
/* Replaces the form once Formspree accepts the submission. Errors do not come
   here — they keep the filled-in form on screen with the status message above
   it, which is the whole point of not throwing the person's typing away. */

.contact-modal__success[hidden] {
	display: none; /* beats the display:flex below, which would outrank the UA rule */
}

.contact-modal__success {
	min-height: 654px; /* the success frame's height, 1095:43 */
	padding: 60px 40px;
	color: var(--color-carbon);
	text-align: center;
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
}

.contact-modal__mascot {
	width: 110px;
	height: auto;
	margin-bottom: 22px;
}

.contact-modal__success-eyebrow {
	margin: 0 0 var(--space-4);
	font-size: var(--text-xs);
	letter-spacing: var(--ls-label);
	color: var(--color-brand);
}

.contact-modal__success-title {
	margin: 0 0 18px;
	font: var(--display-m);
	letter-spacing: var(--ls-display);
	color: var(--color-carbon);
}

.contact-modal__success-desc {
	max-width: 480px;
	margin: 0 0 28px;
	font: var(--body-s);
	color: var(--color-carbon);
}

/* Two stages: the mascot fades and scales in, then after a beat the text
   follows with a short stagger. */
html.js:not(.reduced-motion) .contact-modal__success .contact-modal__mascot {
	opacity: 0;
	transform: scale(0.9);
}

html.js:not(.reduced-motion) .contact-modal__success .contact-modal__success-item {
	opacity: 0;
	transform: translateY(9px);
}

html.js:not(.reduced-motion)
	.contact-modal__success.is-shown
	.contact-modal__mascot {
	animation: contact-success-mascot 300ms ease forwards;
}

html.js:not(.reduced-motion)
	.contact-modal__success.is-shown
	.contact-modal__success-item {
	animation: contact-success-text 250ms ease forwards;
}

/* 300ms mascot + a 300ms pause = 600, then a short stagger. */
html.js:not(.reduced-motion)
	.contact-modal__success.is-shown
	.contact-modal__success-eyebrow {
	animation-delay: 600ms;
}
html.js:not(.reduced-motion)
	.contact-modal__success.is-shown
	.contact-modal__success-title {
	animation-delay: 650ms;
}
html.js:not(.reduced-motion)
	.contact-modal__success.is-shown
	.contact-modal__success-desc {
	animation-delay: 700ms;
}
html.js:not(.reduced-motion) .contact-modal__success.is-shown .btn--outline {
	animation-delay: 750ms;
}

@keyframes contact-success-mascot {
	to {
		opacity: 1;
		transform: scale(1);
	}
}

@keyframes contact-success-text {
	to {
		opacity: 1;
		transform: translateY(0);
	}
}

/* --- Desktop overlay: the header "Contact Us" ----------------------------- */
/* The CTA-band links expand the form inline; the header CTA instead opens it as
   a centred modal (Figma node 1102:332), because the header is reachable anywhere
   on the page and should not scroll to the bottom. Same markup — contact-form.js
   sets `.is-overlay`, which switches the collapsing grid into a fixed, backdropped
   dialog. Bounded to ≥768 so the mobile block below, which already overlays every
   open, is untouched. */

@media (min-width: 768px) {
	.contact-modal.is-overlay {
		position: fixed;
		inset: 0;
		z-index: var(--z-modal);
		max-width: none;
		margin: 0;
		padding: 24px;
		display: flex;
		align-items: center;
		justify-content: center;
		/* Beats the base .contact-modal.is-open { grid-template-rows: 1fr }; the
		   overlay is a flex box, not the collapsing grid. */
		grid-template-rows: none;
		transition: none;
	}

	.contact-modal.is-overlay:not(.is-open) {
		display: none;
	}

	.contact-modal.is-overlay .contact-modal__backdrop {
		display: block;
		position: absolute;
		inset: 0;
		background: var(--color-backdrop);
	}

	.contact-modal.is-overlay .contact-modal__panel {
		position: relative;
		width: 937px; /* Figma node 1102:332 */
		max-width: 100%;
		max-height: 92vh;
		overflow: auto;
		/* A free-floating panel, so every corner is round — not the bottom-only
		   radius the inline panel uses to join the band above it. */
		border-radius: var(--radius-panel);
	}

	.contact-modal.is-overlay .contact-modal__close {
		display: inline-flex;
		align-items: center;
		justify-content: center;
		position: absolute;
		top: 26px;
		right: 30px;
		z-index: 2;
		width: 44px;
		height: 44px;
		padding: 0;
		background: none;
		border: none;
		border-radius: var(--radius-pill);
		color: var(--color-carbon);
		cursor: pointer;
	}
}

/* --- Mobile: a centred overlay dialog ------------------------------------- */
/* The inline expansion is a desktop behaviour. At phone widths it pushed the
   footer most of a screen down, so here the same markup becomes an overlay. */

@media (max-width: 767px) {
	.contact-modal {
		position: fixed;
		inset: 0;
		z-index: var(--z-modal);
		max-width: none;
		margin: 0;
		padding: var(--page-gutter-sm);
		display: flex;
		align-items: center;
		justify-content: center;
		grid-template-rows: none;
		transition: none;
	}

	/* `hidden` here is the closed state — the grid collapse does not apply. */
	.contact-modal:not(.is-open) {
		display: none;
	}

	.contact-modal__backdrop {
		display: block;
		position: absolute;
		inset: 0;
		background: var(--color-backdrop);
	}

	.contact-modal__panel {
		position: relative;
		width: 100%;
		max-height: calc(100dvh - var(--page-gutter-sm) * 2);
		overflow: auto;
		border-radius: 30px;
	}

	.contact-modal__close {
		display: inline-flex;
		align-items: center;
		justify-content: center;
		position: absolute;
		top: 18px;
		right: 18px;
		z-index: 2;
		width: 40px;
		height: 40px;
		padding: 0;
		background: none;
		border: none;
		border-radius: var(--radius-pill);
		color: var(--color-carbon);
		cursor: pointer;
	}

	.contact-modal__body {
		padding: 40px 22px 44px;
	}

	.contact-modal__title {
		font-size: var(--text-xl); /* 24 */
	}

	.contact-modal__desc {
		font-size: var(--text-xs);
	}

	.contact-form {
		margin-top: 34px;
	}

	.contact-form__footer {
		flex-direction: column;
		align-items: stretch;
		gap: 18px;
	}

	.contact-form__send {
		align-self: flex-end;
	}

	/* Figma mobile node 2451:316. */
	.contact-modal__success {
		min-height: 0;
		padding: 48px 22px;
	}

	.contact-modal__success-eyebrow {
		font-size: var(--text-md);
	}

	.contact-modal__success-title {
		font-size: var(--text-xl);
	}

	.contact-modal__success .btn--outline {
		font-size: var(--text-xs);
		letter-spacing: var(--ls-label);
	}
}
