/* Contact — Hero with form card. The section is built from core blocks, so this
 * file is the whole of its chrome.
 *
 * Figma node 2810:7558 (hero band), 2810:7565 (copy column), 2810:7611 (card).
 * Developer handoff r2 (Infinitus-Contact-Us-Dev-Handoff, 2026-08-25).
 *
 * THE PAGE HAS ONE GROUND, AND IT IS NEUTRAL 100. The comp stacks four layers on
 * a Neutral 25 fill — a blurred Neutral 100 ellipse (2810:7564), a Neutral 100
 * diagonal wash (2810:7562), a #F2F2F2 left scrim and a Neutral 25 top fade
 * (2810:7563) — over the FULL 2257px of Frame 154, i.e. across the hero AND the
 * testimonials below it. Sampled out of the comp's own render, that stack
 * resolves to a flat #F3F4F6 (Neutral 100) everywhere except a Neutral 25 bloom
 * in the top right corner, gone by roughly y=1300.
 *
 * So this ships as the RESULT rather than the recipe: Neutral 100 is the
 * block-owned ground on both sections, and the bloom is one gradient on the
 * hero's pseudo-element. Reproducing the comp's four layers per section instead
 * would put a diagonal gradient's own end-stop at the hero's bottom edge and
 * restart it at the testimonials' top edge — a visible seam mid-page, which is
 * exactly the bug this replaces. The handoff's "Frame 154 = Neutral 25" is the
 * BASE fill under all four layers, not the colour the page renders.
 *
 * Dropped with the recipe: assets/images/solutions/hero/hero-glow.svg. Its job
 * in the comp is to pull the left of the page DOWN toward Neutral 100, which the
 * ground now is; keeping it would darken a ground that is already its own
 * colour. The section therefore no longer uses the baked-glow idiom.
 *
 * blockGap is inert here on purpose: the pattern's groups and columns carry no
 * "layout" attribute (so core never emits its blockGap rule), and this file owns
 * every gap outright. */

.infinitus-section--contact-hero {
	/* Column geometry from node 2810:7566 / 2810:7610: the 1240px content the
	   .container publishes at 1440, split 611 + 130 + 499. The two column widths
	   are the BLOCKS' own inline flex-basis, editable in the editor's column
	   controls.

	   THE GAP IS THE REMAINDER, not a measurement — `justify-content:
	   space-between` below. Two fixed-width columns and a fixed gap only add up
	   to the content width at one viewport: at 1441 they do (611+130+499 = 1240),
	   and at 1553 the .container has stopped growing at 1280 of content while
	   the columns still total 1110, leaving 36px of slack that flex parks at the
	   RIGHT end. That put the form card 36px inside the content edge while the
	   testimonial arrows below it sat on the edge — two things the comp aligns.
	   Letting the gap absorb the slack keeps both column edges on the content
	   box at every width, which is the alignment that is actually designed.

	   This value is the FLOOR, for the widths where there is no slack to absorb
	   and the columns are shrinking instead. 30px is the DS grid gutter. */
	--contact-hero-columns-gap: 30px;

	/* Handoff r2: "Form minimum width ~380px". Applied from 768 up rather than
	   only in the tablet band — at 1025 the proportional shrink puts the form at
	   375px without it. */
	--contact-hero-form-min: 380px;

	/* Measures. The comp sets the headline, lede and proof heading to 605px
	   inside the 611px column; the 6px is a Figma artefact of the text frames,
	   not a designed inset, so only the headline keeps a measure. */
	--contact-hero-title-measure: 605px;

	--contact-hero-eyebrow-tracking: 0.012em;

	/* Photograph: node 2810:7575 draws 605x440 with the top-right corner cut at
	   45 degrees. Chamfer as a percentage of that box (121px x, 100px y) so it
	   stays proportional as the column narrows. */
	--contact-hero-photo-ratio: 605 / 440;
	--contact-hero-photo-chamfer-x: 20%;
	--contact-hero-photo-chamfer-y: 22.73%;

	/* Proof rows, node 2810:7581: 24px between rows, 20px icon gutter, and the
	   icon slot is 20x23 (the export is 22x24 — same as the Product Studio
	   feature icon, and sized down the same way). */
	--contact-hero-proof-gap: var(--wp--preset--spacing--sp-6);
	--contact-hero-proof-gutter: var(--wp--preset--spacing--sp-5);
	--contact-hero-proof-icon-width: 20px;
	--contact-hero-proof-icon-height: 23px;

	/* Card, node 2810:7611. Radius is the theme's md (12px) over the comp's 8px;
	   see the pattern's DESIGN QA note. */
	--contact-hero-card-padding: 50px;
	--contact-hero-card-border-width: 2px;

	/* Elevation/XL off the node: 0 16px 40px #1119272E. No token exists for the
	   DS elevation ramp, so it is spelled out. */
	--contact-hero-card-shadow: 0 16px 40px rgb(17 25 39 / 18%);

	/* The card's top edge sits 50px above the copy column's: node 2810:7610
	   starts the card at y=150 where the eyebrow starts at y=200. */
	--contact-hero-form-lift: 50px;

	/* Sticky offset. The comp's own offset is 0 from the top of the PAGE; the
	   header is fixed here, so the card clears it and keeps a little air.

	   sp-3 (12px), not sp-5: this value is subtracted from the height cap below
	   as well as added to `top`, so every pixel of air costs a pixel of the card's
	   budget. At 1085 wide the card wants 802px and a 20px gap left it 800 — a
	   two-pixel overflow is still a scrollbar. 12px reads the same and clears it. */
	--contact-hero-form-sticky-gap: var(--wp--preset--spacing--sp-3);

	/* The Neutral 25 bloom in the top right, fitted to the comp's own render
	   rather than to its layer list (see the file header). Alphas read off the
	   green channel at 50 sample points, Neutral 100 = 0 and Neutral 25 = 1:
	   1.0 at the top-right corner, 0.75 at y=500, 0.5 at y=800, 0.13 at y=1100,
	   0 by y=1400 — and at the very top it still reads 0.5 at mid-width and 0.25
	   at the left edge. Hence an ellipse wider than the section, centred on the
	   top-right corner. Percentages, not pixels: the bloom is a proportion of the
	   section, so it holds when the copy column makes the section taller. */
	--contact-hero-bloom-width: 115%;
	--contact-hero-bloom-height: 78%;

	/* NO `overflow: clip` here, unlike solutions-hero.css. That section needs it
	   because its media layer is a real <img> that overflows the box; every
	   layer here is a BACKGROUND on the pseudo-element below, and backgrounds are
	   already clipped to their own padding box, negative background-position
	   included. Clip would buy nothing and cost something: it is a clipping
	   ancestor for the sticky form card, so it would be a footgun the first time
	   the card's offsets change. */
	position: relative;
}

/* THE GROUND GOES ON THE BODY, not only on the two sections. Both sections carry
 * Neutral 100 as a block-owned palette preset — that is what the editor shows the
 * client and what they can change — but the page does not end at the last
 * section: partials/footer-cta.php is global chrome that sits OUTSIDE <main> and
 * deliberately leaves its top half transparent so it reads over whatever section
 * ended the page. On this page that showed the body's own Neutral 25 as a white
 * band between the testimonials and the footer, which is the "whole page should
 * be grey" report.
 *
 * `:has()` on the section class rather than `body.contact`: the slug class is a
 * property of one page, the ground is a property of this hero, and any page that
 * gets this hero wants the same continuous ground. It is the one selector in this
 * file not scoped under the section class, which is why it says so out loud. */
body:has(.infinitus-section--contact-hero) {
	background-color: var(--wp--preset--color--gray-100);
}

/* The bloom, in one decorative pseudo-element above the ground and below the
 * copy. It runs at EVERY width, unlike the layer stack it replaces: the bloom is
 * a proportion of the section rather than a 1440px artwork measurement, so it
 * reads the same on a phone, and it is the only thing keeping the top of the page
 * from being one flat grey. */
.infinitus-section--contact-hero::before {
	background-image: radial-gradient(
		var(--contact-hero-bloom-width) var(--contact-hero-bloom-height) at 100% 0%,
		var(--wp--preset--color--gray-25) 0%,
		color-mix(in srgb, var(--wp--preset--color--gray-25), transparent 100%) 100%
	);
	content: "";
	inset: 0;
	pointer-events: none;
	position: absolute;
	z-index: 1;
}

/* FIXED-HEADER CLEARANCE, not design padding. Keeping the two apart means the
 * section's padding control in the editor still reads as "space below the nav"
 * rather than silently bundling in a structural offset. */
.infinitus-section--contact-hero .contact-hero__inner {
	gap: var(--contact-hero-columns-gap);
	/* Both column edges stay on the content box; the middle takes the slack.
	   See --contact-hero-columns-gap. */
	justify-content: space-between;
	margin-block-end: 0; /* core gives .wp-block-columns its own 1.75em bottom margin */
	padding-top: var(--navbar-height, 80px);
	position: relative;
	z-index: 2;
}

/* Column widths are the blocks' own inline flex-basis; core's
 * `.wp-block-columns...>.wp-block-column[style*=flex-basis]{flex-grow:0}` rule
 * exists to consume that, and the default flex-shrink:1 is what lets the row
 * scale down smoothly between 1025 and 1440 without a percentage ladder. */
.infinitus-section--contact-hero .contact-hero__copy,
.infinitus-section--contact-hero .contact-hero__form {
	min-width: 0;
}

/* Copy-column rhythm as an owl selector — node 2810:7566 draws 30px between
 * every block, with the eyebrow-to-headline pair tightened below.
 * margin-block-end (not margin) on every child so the rhythm survives. */
.infinitus-section--contact-hero .contact-hero__copy > * {
	margin-block-end: 0;
}

.infinitus-section--contact-hero .contact-hero__copy > *:first-child {
	margin-block-start: 0;
}

.infinitus-section--contact-hero .contact-hero__copy > * + * {
	margin-block-start: 30px;
}

/* Uppercased here rather than in the copy, so an editor typing sentence case
 * still gets the DS tag. Colour is a palette preset on the block and
 * deliberately absent here. */
.infinitus-section--contact-hero .contact-hero__eyebrow {
	font-size: var(--fs-h6);
	font-weight: 500;
	letter-spacing: var(--contact-hero-eyebrow-tracking);
	line-height: var(--lh-h6);
	text-transform: uppercase;
}

/* Overrides the owl rhythm: node 2810:7569 keeps the eyebrow tight to the
 * headline at 12px. */
.infinitus-section--contact-hero .contact-hero__title {
	font-size: var(--fs-h1);
	font-weight: 300;
	letter-spacing: 0;
	line-height: var(--lh-h1);
	margin-block-start: var(--wp--preset--spacing--sp-3);
	max-width: min(var(--contact-hero-title-measure), 100%);
}

/* Node 2810:7573 is Desktop/Body Large (24/36) in Neutral 900, not the Neutral
 * 600 the Solutions heroes' ledes use. The colour is a palette preset on the
 * block; only the type rung is here. */
.infinitus-section--contact-hero .contact-hero__lede {
	font-size: var(--fs-body-2xl);
	line-height: var(--lh-body-2xl);
}

/* chamfered-image: border-radius rounds all four corners, clip-path removes the
 * top-right one. The committed asset is a plain rectangle, so the clip-path is
 * the whole of the cut and a photograph the client swaps in keeps the shape. */
/* `height: auto` is LOAD-BEARING, not a reset. core/image with sizeSlug "full"
 * emits `class="wp-block-image size-full"`, and `size-full` is ALSO a Tailwind
 * utility in this theme's build — `height: 100%; width: 100%`. So every
 * full-size core/image figure resolves its height against its parent's, and in
 * a column this tall Chrome sizes the column from the image's natural height
 * first (438px), then feeds that column height back into the figure's 100% —
 * the figure became 1397px and pushed the proof points 959px below the section.
 * The width half of the utility is wanted; only the height has to go.
 * solutions-hero.css leans on the same utility deliberately (its media layer
 * does want 100%), and product-studio-workflows.css pins every figure height
 * explicitly, which is the same collision seen from the other side. */
.infinitus-section--contact-hero .contact-hero__photo {
	height: auto;
	line-height: 0; /* drops the inline image's descender space */
}

.infinitus-section--contact-hero .contact-hero__photo img {
	aspect-ratio: var(--contact-hero-photo-ratio);
	border-radius: var(--wp--custom--radius--md);
	clip-path: polygon(
		0 0,
		calc(100% - var(--contact-hero-photo-chamfer-x)) 0,
		100% var(--contact-hero-photo-chamfer-y),
		100% 100%,
		0 100%
	);
	display: block;
	height: auto;
	object-fit: cover;
	width: 100%;
}

/* An h2 typed at Desktop/Body Default bold, not at a heading rung: node
 * 2810:7577 is 20/30 at weight 700. It is a heading in the outline (the four
 * statistics under it are h3s) and a body-weight label on the page. */
.infinitus-section--contact-hero .contact-hero__proof-heading {
	font-size: var(--fs-body-xl);
	font-weight: 700;
	letter-spacing: 0;
	line-height: var(--lh-body-xl);
}

.infinitus-section--contact-hero .contact-hero__proofs {
	display: grid;
	gap: var(--contact-hero-proof-gap);
}

/* Core's flow layout gives every non-first child of a group a block-gap margin.
 * These groups become explicit grids, so that margin has to go to zero or it
 * adds to the token gaps. */
.infinitus-section--contact-hero .contact-hero__proofs > * + *,
.infinitus-section--contact-hero .contact-hero__proof > * + *,
.infinitus-section--contact-hero .contact-hero__proof-copy > * + * {
	margin-block-start: 0;
}

/* Start alignment keeps the check beside the statistic's first line when the
 * label below it wraps. */
.infinitus-section--contact-hero .contact-hero__proof {
	align-items: start;
	display: grid;
	gap: var(--contact-hero-proof-gutter);
	grid-template-columns: var(--contact-hero-proof-icon-width) minmax(0, 1fr);
}

/* The comp pads the icon 5px down so it centres on the statistic's cap height.
 * flex:none stops the theme's global image rules stretching it; line-height:0
 * removes the inline-image descender. */
.infinitus-section--contact-hero .contact-hero__proof-icon {
	flex: none;
	height: var(--contact-hero-proof-icon-height);
	line-height: 0;
	margin: 5px 0 0;
	width: var(--contact-hero-proof-icon-width);
}

.infinitus-section--contact-hero .contact-hero__proof-icon img {
	border-radius: 0;
	height: 100%;
	object-fit: contain;
	width: 100%;
}

/* Node 2810:7586 stacks the two lines with NO gap — the statistic's 34px line
 * box and the label's 30px one are the whole of the spacing. */
.infinitus-section--contact-hero .contact-hero__proof-copy {
	display: grid;
	gap: 0;
}

.infinitus-section--contact-hero .contact-hero__proof-stat {
	font-size: var(--fs-h4);
	font-weight: 300;
	letter-spacing: var(--contact-hero-eyebrow-tracking);
	line-height: var(--lh-h4);
	margin-block: 0;
}

.infinitus-section--contact-hero .contact-hero__proof-label {
	font-size: var(--fs-body-xl);
	line-height: var(--lh-body-xl);
	margin-block: 0;
}

/* Card fill remains the block-owned Gray 50 preset. */
.infinitus-section--contact-hero .contact-hero__card {
	border: var(--contact-hero-card-border-width) solid var(--wp--preset--color--gray-200);
	border-radius: var(--wp--custom--radius--md);
	box-shadow: var(--contact-hero-card-shadow);
	display: grid;
	gap: var(--wp--preset--spacing--sp-6);
	margin-block: 0;
	overflow: hidden;
	padding: var(--contact-hero-card-padding);
}

.infinitus-section--contact-hero .contact-hero__card-heading {
	font-size: var(--fs-h3);
	font-weight: 300;
	letter-spacing: var(--contact-hero-eyebrow-tracking);
	line-height: var(--lh-h3);
	margin-block: 0;
}

/* HubSpot owns everything inside. The field skin is in
 * assets/scss/elements/_forms.scss, keyed to .nylon-hs-form--contact-hero
 * alongside the Product Studio card's — one skin, two consumers, so the two
 * cards cannot drift apart. */
.infinitus-section--contact-hero .nylon-hs-form--contact-hero {
	margin: 0;
	width: 100%;
}

/* ⚑ DESIGN QA — auto-fit, not a breakpoint. The shared skin holds HubSpot's
 * two-column fieldsets side by side down to 767.98px, which is right for the
 * Product Studio card (a centred 820px box). This card is a shrinking COLUMN, so
 * the point at which a pair of fields stops being usable is a property of the
 * card's width, not of the viewport's; auto-fit finds it wherever it falls and
 * needs no breakpoint re-derived when the column geometry changes.
 *
 * THE FLOOR IS 130px, DOWN FROM 160. 160 was set while the fields still carried
 * HubSpot's placeholders and "Company name" had to fit inside its own input;
 * assets/js/modules/contact-form.js removes those, so the only constraint left is
 * that a text input stays usable, and the labels above them wrap freely. It
 * matters: dropping to one column doubles the card's height, and a card taller
 * than the space under the header is what puts a scrollbar inside it. At 130 the
 * pair survives down to a 380px card, which is the form column's own floor.
 *
 * `.contact-hero__card` is in the selector for SPECIFICITY, not scope: the
 * section stylesheets are enqueued BEFORE the compiled style.css that holds the
 * shared skin (verified in the sheet order on this page), so a section rule that
 * has to beat a skin rule cannot do it at equal specificity — the skin's
 * repeat(2, …) wins on order. One extra class is the whole fix. */
.infinitus-section--contact-hero
	.contact-hero__card
	.nylon-hs-form--contact-hero
	form
	fieldset.form-columns-2 {
	grid-template-columns: repeat(auto-fit, minmax(130px, 1fr));
}

/* ⚑ CONTENT QA — THE MESSAGE TEXTAREA IS HIDDEN, and this is a content decision,
 * not a layout one. Node 2810:7655 ("Leave us a message") is present in the comp
 * and switched OFF, so the card the comp draws is 729px; the same form renders
 * ~898px here because HubSpot still emits the field. That extra ~150px is what
 * made the sticky card taller than the space below the header, which is what
 * forced the height cap to bite and put a scrollbar inside the card.
 *
 * Handoff r2 disagrees with the node here — it describes the textarea as a real
 * field — so this is the one place a hidden node is being followed over the
 * handoff's prose. `display: none` (not `visibility` or an offscreen shift) also
 * takes it out of the tab order and the accessibility tree, so nothing is left
 * for a keyboard or a screen reader to land on. The field stays optional in
 * HubSpot and submits empty; putting it back is deleting this one rule.
 *
 * Same specificity trick as the rules above — the section stylesheets load
 * before the compiled skin. */
.infinitus-section--contact-hero
	.contact-hero__card
	.nylon-hs-form--contact-hero
	form
	.hs_message {
	display: none;
}

/* ⚑ DESIGN QA — the consent line is Neutral 900, the privacy line below it is
 * Neutral 600. Node 2810:7663 draws the two a step apart deliberately; the shared
 * skin colours both Neutral 600 because the Product Studio comp does. Handoff r2
 * lists a third value for this line (Neutral 700, #374151) — the node wins, per
 * docs/agents/section-patterns.md. Same specificity trick as the rule above; the
 * privacy paragraph is deliberately left alone. */
.infinitus-section--contact-hero
	.contact-hero__card
	.nylon-hs-form--contact-hero
	form
	.hs-form-booleancheckbox-display {
	color: var(--wp--preset--color--gray-900);
}

/* THE STICKY CARD, node 2810:7610 — and handoff r2, which asks for it at tablet
 * as well ("Maintain side-by-side layout with form sticky … Form minimum width
 * ~380px … without introducing a scroll-to-form UX"). So it runs from 768 up,
 * not from 1025, and only mobile stacks.
 *
 * The lift is a negative margin rather than a `top` offset because the card has
 * to start above the copy column's first line AND stick from there — a translate
 * would leave the sticky box measuring from the un-lifted edge.
 *
 * THE HEIGHT CAP IS WHAT MAKES THE PIN WORK AT ALL. A sticky box taller than the
 * space below a fixed header cannot pin: it scrolls until its own bottom is
 * reached, and its top disappears behind the header on the way — which is exactly
 * what this card did, because HubSpot's rendered form is ~926px against the
 * comp's 729px (an extra message field, and one label that wraps to two lines).
 * Capping the card to the viewport below the header makes the pin unconditional at
 * every viewport height and every form length; the card scrolls internally in the
 * rare case it still does not fit, which is strictly better than a form header
 * nobody can see.
 *
 * ⚑ DECIDED 2026-08-27, DO NOT RE-OPEN PER REVIEW — the card DOES ride up behind
 * the header over the last stretch of the section, and that is accepted. Sticky
 * releases when its containing block runs out: the copy column is 1403px and the
 * card 760px, so from roughly 727px of scroll the row's remaining height is less
 * than the card needs and the card must move with it. Measured, not assumed.
 * Holding the pin until the last proof point has scrolled past would take ~871px
 * of empty ground at the bottom of the hero; that trade was put to the client with
 * the numbers and declined in favour of the standard sticky release. The
 * alternative — dropping sticky altogether — loses what node 2810:7610 and handoff
 * r2 both specify. Nothing above 727px of scroll is affected: the card pins 12px
 * clear of the header from the first scroll to that point. */
@media (min-width: 768px) {
	.infinitus-section--contact-hero .contact-hero__form {
		align-self: start;
		margin-block-start: calc(var(--contact-hero-form-lift) * -1);
		min-width: var(--contact-hero-form-min);
		position: sticky;
		top: calc(var(--navbar-height, 80px) + var(--contact-hero-form-sticky-gap));
	}

	.infinitus-section--contact-hero .contact-hero__card {
		/* svh, not vh: the small-viewport unit is the one that does not assume
		   retractable browser chrome is retracted. vh first as the fallback.
		   The sticky gap is subtracted ONCE, not twice: the guarantee is about
		   the card's top edge clearing the header, so only the space above it has
		   to be reserved. Counting it at both ends cost 20px of budget and, with
		   the card at 772px, was the difference between a clean fit and an
		   11px scroll on a 900px-tall window. */
		max-height: calc(100vh - var(--navbar-height, 80px) - var(--contact-hero-form-sticky-gap));
		max-height: calc(
			100svh - var(--navbar-height, 80px) - var(--contact-hero-form-sticky-gap)
		);
		/* The card's radius still needs the horizontal clip; only the block axis
		   becomes scrollable, and only when the cap actually bites. */
		overflow: hidden auto;
		/* Thin, because this scrollbar is a fallback for a short window rather
		   than a designed part of the card. NOT scrollbar-gutter: stable — that
		   reserves the track at every height and would pull the fields in by
		   ~15px on the windows where the cap never bites. */
		scrollbar-width: thin;
	}
}

/* Tablet, 768–1024: the two-up survives, on handoff r2's instruction. The form
 * stops shrinking at its stated 380px floor and the copy column takes the whole
 * squeeze; the gap drops to the DS's own 30px tablet gutter so the copy column
 * keeps every pixel the form does not need.
 *
 * ⚑ DESIGN QA — at 768 that leaves the copy column 298px, which is 6 words a
 * line under a 48px headline. The handoff asked for this explicitly and it is not
 * mocked; the alternative is stacking below ~900 instead of below 768. Raise it
 * at design review rather than deciding it here. */
@media (min-width: 768px) and (max-width: 1024.98px) {
	/* The 605px headline measure is a desktop constraint; at tablet the column
	   is the measure. The form's 380px floor and the 30px gap are already the
	   defaults above, so nothing else is needed for this band. */
	.infinitus-section--contact-hero .contact-hero__title {
		max-width: none;
	}
}

/* The card's 50px padding is a measurement off a 499px card. Below 1280 the card
   is a shrinking column and 100px of padding is up to a third of it, which
   squeezes the field pair to the point where it wraps to one column and doubles
   the card's height. sp-8 keeps the pair alive down to the column's own 380px
   floor. The comp only draws 1440, where the padding stays 50. */
@media (max-width: 1279.98px) {
	.infinitus-section--contact-hero {
		--contact-hero-card-padding: var(--wp--preset--spacing--sp-8);
	}
}

/* Mobile, under 768: one column, form after the copy, no sticky — handoff r2's
 * stack order is Nav → copy → stats → form → testimonials → footer, which is
 * document order.
 *
 * THIS FILE OWNS THE STACK, because the block turns core's own stacking off. The
 * pattern sets isStackedOnMobile: false so the tablet band survives (core would
 * otherwise force one column under 782px, 14px inside the band handoff r2 asks
 * to keep side by side). The `!important`s here are not specificity theatre:
 * core's `is-not-stacked-on-mobile` rule is itself `flex-wrap: nowrap !important`,
 * so nothing else can beat it. */
@media (max-width: 767.98px) {
	.infinitus-section--contact-hero {
		--contact-hero-card-padding: var(--wp--preset--spacing--sp-6);
		--contact-hero-columns-gap: var(--wp--preset--spacing--sp-16);
	}

	.infinitus-section--contact-hero .contact-hero__inner {
		flex-wrap: wrap !important;
	}

	/* Both columns fill the row once it is one column wide; the inline
	   flex-basis stays in the markup so desktop keeps the designed split. */
	.infinitus-section--contact-hero .contact-hero__copy,
	.infinitus-section--contact-hero .contact-hero__form {
		flex-basis: 100% !important;
	}

	.infinitus-section--contact-hero .contact-hero__title {
		max-width: none;
	}

	.infinitus-section--contact-hero .contact-hero__copy > * + * {
		margin-block-start: var(--wp--preset--spacing--sp-6);
	}
}
