/**
 * Two Column — Residential Roofing sections 5, 6, 8 and 9.
 *
 * Measured off the 1:1 export, the grid is identical in all four:
 *   media 705  |  gap 91  |  content 644   = 1440
 * Section 5 image box 240-944 x 120-629 (705x510), section 6 image
 * 975-1679 x 120-715 (705x596), section 8 form panel 975-1679.
 *
 * Reverse is a pure order flip, which is why one layout covers both the
 * image-left and image-right designs instead of two near-identical blocks.
 */

.two-column__inner {
	display: grid;
	grid-template-columns: 705fr 644fr;
	align-items: stretch;
	gap: 91px;
}

/* Five instances split 705 | 80 | 655 instead of 705 | 91 | 644 — surveyed
 * across the .fig, it is 91 in 27 places and 80 in these. The 11px matters:
 * at 644 the DaVinci lede takes a seventh line that the design does not have.
 * Opt in per row with the Extra CSS classes field. */
.two-column--gap-80 .two-column__inner {
	grid-template-columns: 705fr 655fr;
	gap: 80px;
}

/* Windows & Sliding Doors section 9 is the one row the design splits
 * 705 | 72 | 663 — the checklist beside the short 316px photo. Measured off
 * the .fig, not eyeballed: the content frame starts at x=777. */
.two-column--gap-72 .two-column__inner {
	grid-template-columns: 705fr 663fr;
	gap: 72px;
}

/* Warranties section 4 is the one row drawn 771 | 143 | 526 — a wider copy
 * column beside a narrower photo. Reversed, so the tracks are stated in
 * content-then-media order to beat the base --reverse rule below. */
.two-column--reverse.two-column--gap-143 .two-column__inner {
	grid-template-columns: 771fr 526fr;
	gap: 143px;
}

.two-column--gap-143 .two-column__inner {
	grid-template-columns: 526fr 771fr;
	gap: 143px;
}

/* The diamond lattice behind the band — Warranties section 2.
 *
 * NOT feature-columns' bg-vc.svg, which was the obvious candidate and is the
 * wrong artwork: that one is a 30 degree isometric cube mesh (its own path data
 * steps 45 across for 26 down) 638px tall and tiled across the top. This is a
 * 45 degree diamond lattice running the full height of the band.
 *
 * Every number measured off the 1:1 export, not estimated. Projecting the
 * pattern onto candidate axes and taking the variance peaks at 46 degrees (44
 * and 48 close behind), so 45; autocorrelating that profile gives a clean
 * 188px period (r = 0.57) for the spacing between parallel lines. Sampling a
 * content-free band at the top of the section, the pattern is EXACTLY flat left
 * of x 780 and starts at x 795, then the line contrast ramps steadily from a
 * peak deviation of 11 (of the 29 a solid white line would give) at x 800 to 27
 * at x 1900 — hence white lines under a mask that opens at 40% of the width.
 *
 * A CSS reproduction rather than the Figma vector: swap in the exported asset if
 * pixel parity ever matters. At ~3% contrast the two are indistinguishable.
 *
 * `isolation` makes the row a stacking context so the -1 pseudo-element lands
 * above the section's own background and below its content. Without it the
 * negative layer escapes to the root and paints behind the pale fill, which is
 * the same trap media-cta documents.
 *
 * Opt in per row with the Extra CSS classes field; only one row asks for it. */
.two-column--lattice {
	isolation: isolate;
	/* The wash the lattice sits on. Sampling a cell CENTRE at the right-hand end
	 * of the export reads ~(250,253,252) against the band's own (241,250,245) —
	 * the ground itself lightens toward the right, it is not only the lines. That
	 * is what the measured MEAN deviation of 19 against a line PEAK of 27 says:
	 * most of the area is lit, not just 1.5px of it. Lines alone gave a mean of
	 * 0.95 and read as a wireframe.
	 *
	 * The stops are the measured ramp, which is not linear: reading mean deviation
	 * per 40px slab, the wash is 0 to x 790, ~32% by x 1000, ~53% by x 1280 and
	 * plateaus at ~66% from x 1520 to the right edge. A single stop to 68% landed
	 * the far end exactly but ran ~5 units light through the middle. */
	background-image: linear-gradient(
		90deg,
		transparent 41%,
		rgb(255 255 255 / 32%) 52%,
		rgb(255 255 255 / 53%) 67%,
		rgb(255 255 255 / 66%) 79%,
		rgb(255 255 255 / 66%) 100%
	);
}

.two-column--lattice::before {
	position: absolute;
	z-index: -1;
	inset: 0;
	background-image:
		repeating-linear-gradient(45deg, rgb(255 255 255 / 95%) 0 1.5px, transparent 1.5px 188px),
		repeating-linear-gradient(-45deg, rgb(255 255 255 / 95%) 0 1.5px, transparent 1.5px 188px);
	mask-image: linear-gradient(90deg, transparent 40%, rgb(0 0 0 / 45%) 42%, #000 100%);
	content: "";
	pointer-events: none;
}

/* Content-only rows collapse to a single column rather than leaving a hole. */
.two-column--single .two-column__inner {
	grid-template-columns: 1fr;
}

.two-column--align-center .two-column__inner {
	align-items: center;
}

.two-column--align-start .two-column__inner {
	align-items: start;
}

/* --- stretch (equal height) ---------------------------------------------
 * "Stretch (equal height)" emitted `two-column--align-stretch` and then had no
 * rule to land on, so it fell through to the grid's default `stretch` — which
 * the media column's own `aspect-ratio` immediately defeated: a ratio resolves
 * the height from the width, so the column never grew to meet the copy.
 *
 * Releasing the ratio alone would collapse the column, because the photo is its
 * only child and would size the box rather than fill it. Taking the photo out of
 * flow instead leaves the media column with no in-flow content at all, so the
 * row height comes from the content column and the photo covers whatever that
 * turns out to be.
 *
 * Excludes the three media treatments that own their height for other reasons: a
 * form panel is as tall as its fields, a stacked pair sets a ratio per photo,
 * and a sticky column needs `align-self: start` — which is the opposite of
 * stretch, and would collapse an out-of-flow photo to nothing. */
.two-column--align-stretch .two-column__media:not(.two-column__media--stacked):not(.two-column__media--sticky):not(.two-column--form .two-column__media) {
	aspect-ratio: auto;
}

.two-column--align-stretch .two-column__media:not(.two-column__media--stacked):not(.two-column__media--sticky) > .two-column__image {
	position: absolute;
	inset: 0;
	height: 100%;
}

/* Stacked below 992, the media column has no sibling to inherit a height from,
 * so an out-of-flow photo would collapse the box to zero. The ratio comes back
 * and the photo returns to flow. */
@media (max-width: 991px) {

	.two-column--align-stretch .two-column__media:not(.two-column__media--stacked):not(.two-column__media--sticky) {
		aspect-ratio: var(--media-ratio, auto);
	}

	.two-column--align-stretch .two-column__media:not(.two-column__media--stacked):not(.two-column__media--sticky) > .two-column__image {
		position: static;
	}
}

/* Media left / content right is the source order. Reversing swaps the tracks
 * so the content column keeps its 644px width on either side. */
.two-column--reverse .two-column__inner {
	grid-template-columns: 644fr 705fr;
}

/* About Us section 4 is the reversed twin of the gap-80 split — content 655 |
 * 80 | media 705. Without this the --reverse rule above wins on the track list
 * and the text column renders 644, 11px narrow. */
.two-column--reverse.two-column--gap-80 .two-column__inner {
	grid-template-columns: 655fr 705fr;
}

.two-column--reverse.two-column--gap-72 .two-column__inner {
	grid-template-columns: 663fr 705fr;
}

.two-column--reverse .two-column__media {
	order: 2;
}

.two-column--reverse .two-column__content {
	order: 1;
}

/* --- media --------------------------------------------------------- */
/* --media-ratio carries the Figma placed box (705/510, 705/596, 705/466).
 * Without it the source file's own proportions drive the row height: the
 * section 6 photo is 1120x1401, which rendered 882px tall against a design
 * that asks for 596 and pushed the whole section 285px over. */
.two-column__media {
	position: relative;
	min-width: 0;
	aspect-ratio: var(--media-ratio, auto);
	overflow: hidden;
}

/* The form panel is not a cropped image, and `overflow: hidden` was silently
 * clipping its drop shadow — the shadow was declared and computed correctly,
 * it simply had nowhere to paint. Only the image variant needs the clip.
 *
 * Nor does it have a ratio. A photo can be cropped to the box Figma drew; a
 * form is as tall as its fields are, and holding the column to 705/590 cut the
 * panel off mid-form and left the submit button below the green rule that is
 * supposed to close it. The template no longer emits --media-ratio for a form,
 * and this makes sure a value stored on the row cannot reintroduce the crop. */
.two-column--form .two-column__media {
	aspect-ratio: auto;
	overflow: visible;
	/* Fill the row, so the panel's own height is the grid row's and its closing
	 * green rule lands at the foot of the column rather than partway up it when
	 * the copy beside it runs longer. */
	height: 100%;
}

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

/* Two photos stacked in the media column — Vinyl-siding section 5, measured
 * 649 + 70 + 649 = 1368 against a 1367 frame. The column drops its own
 * aspect-ratio here and hands --media-ratio to each photo instead, or a single
 * 705/649 ratio on the wrapper would squash both into half the height. */
.two-column__media--stacked {
	display: flex;
	flex-direction: column;
	gap: 70px;
	aspect-ratio: auto;
}

.two-column__media--stacked .two-column__image {
	height: auto;
	aspect-ratio: var(--media-ratio, auto);
}

/* Sticky media — About Us section 2, where a 705x700 photo sits beside eleven
 * lines of copy plus an eight-item list and the text column runs ~470px longer.
 * Opt in per row with the "Sticky image" field.
 *
 * `align-self: start` is what makes it work at all: the grid is `stretch` by
 * default, and a media column stretched to the full row height has no room left
 * to travel, so sticky would resolve to nothing. Stated here rather than relying
 * on the row's Vertical alignment, which is a separate per-row choice.
 *
 * The offset is a variable so a row that needs to clear something can override
 * it inline without a new class.
 *
 * The default now clears the site header, which is itself sticky at top: 0 — a
 * flat 40 pinned the photo underneath it. Header height plus 10, and it tracks
 * the token, so the 137 -> 90 step below 768 is carried automatically. */
.two-column__media--sticky {
	position: sticky;
	top: var(--media-sticky-top, calc(var(--header-height) + 10px));
	align-self: start;
}

/* Below 992 the columns stack, so the photo is above the copy rather than
 * beside it — pinned, it would ride down over the text it is supposed to
 * illustrate. `height: 100%` from the stacked rule below also fights a
 * self-sized sticky box. */
@media (max-width: 991px) {

	.two-column__media--sticky {
		position: static;
	}
}

/* --- content ------------------------------------------------------- */
.two-column__content {
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	justify-content: center;
	min-width: 0;
}

/* Set from rendered ink, not Figma node tops. Design ink in the Form section:
 * mark 120..154, heading lines 182 / 255 / 327 (ending 380), body first line
 * 418. The browser sets a 64px Anek cap 1px below its line-box top where Figma
 * centres it in the 72px line, so the box has ~25px of dead space underneath —
 * which is why the gap under the heading is 14, not the 20 it looks like. */
.two-column__content .section-eyebrow {
	margin-bottom: 26px;
}

.two-column__heading {
	margin-bottom: 14px;
}

/* Ten instances open 40 between the shamrock mark and the heading instead of
 * the 30 the other twenty-five use (the closing FAQ heads use 20, but they have
 * no mark). It only shows where the text column is the taller of the two —
 * Wood Shake section 7 and James Hardie section 7 — but the class is applied
 * everywhere the design says 40 so the rule stays honest. */
.two-column--head-40 .two-column__content .section-eyebrow {
	margin-bottom: 36px;
}

/* A centred head above a two-column row closes 46 above the row in the design
 * (DaVinci section 10: lede ink ends 386, image starts 432). The shared
 * .section-head gives 40 measured to the lede's box, which lands 56 — the FAQ
 * variant needs that 40, so this is scoped to the block. */
.two-column .section-head {
	margin-bottom: var(--space-30);
}

/* When the heading is the whole column — Residential Roofing section 9, whose
 * text column is a 644x466 frame holding nothing else — the 26px of dead space
 * under the last line's ink plus that 14px margin made the column 507 instead
 * of 466 and pushed the link-card row 41 down. */
.two-column__content > .two-column__heading:last-child {
	margin-bottom: -26px;
}

/* Some instances set the column heading at 36 rather than the 64 that
 * `.section-title` gives — DaVinci section 10, where a 64px centred head sits
 * above and the column heading is the subordinate one. Opt in per row with the
 * Extra CSS classes field. */
.two-column--heading-sm .two-column__heading {
	font-size: var(--fs-36);
	line-height: var(--lh-36);
}

.two-column__text {
	margin: 0;
}

.two-column__text > :first-child {
	margin-top: 0;
}

.two-column__text > :last-child {
	margin-bottom: 0;
}

/* Figma runs body lines on a 32px pitch and opens paragraphs to 47 — a 15px
 * gap, not the 20 this was built with. Worth correcting: Storm Damage section
 * 5 stacks five paragraphs, where the 5px error compounds to 20.
 *
 * The paragraphs also carry a 20px bottom margin from the base stylesheet, and
 * margin collapsing means the LARGER of the two wins — so the 15 above did
 * nothing until this zeroed the bottom. */
.two-column__text p {
	margin-bottom: 0;
}

.two-column__text p + p {
	margin-top: 15px;
}

/* The design underlines inline links inside the body copy. */
.two-column__text a {
	color: var(--primary-green);
	text-decoration: underline;
	transition: var(--transition);
}

.two-column__text a:hover,
.two-column__text a:focus-visible {
	color: var(--primary-black);
}

/* --- checklist (section 6) ------------------------------------------ */
.check-list {
	margin: 0;
	padding: 0;
	list-style: none;
}

/* The design's List frame is not always a bare stack: on Windows & Sliding
 * Doors 6 and 9 and About Us 4 it carries 8px above the first item and 16px
 * below the last (6 items at 32 with a 20 gap is 292; those frames are 316).
 *
 * This is opt-in rather than the default on purpose. Applied globally it moved
 * all twelve pages built before 2026-08-20 — six closer to the design and five
 * further away (commercial-roofing -1 -> +31, storm-damage +6 -> +27) — because
 * their list rows were already tuned to the ink under the 2026-08-19 pass. A
 * net-zero change that churns signed-off pages is not worth taking. */
.two-column--list-pad .check-list {
	padding: 8px 0 16px;
}

.check-list__item {
	display: flex;
	align-items: flex-start;
	gap: var(--space-12);
	color: var(--body-grey);
	font-family: var(--font-body);
	font-size: var(--fs-20);
	font-weight: 400;
	line-height: var(--lh-body);
}

.check-list__item + .check-list__item {
	margin-top: var(--space-20);
}

.check-list__mark {
	display: inline-flex;
	flex: 0 0 auto;
	/* Optically centred on the first line of a 32px-leading item. */
	margin-top: 5px;
	color: var(--primary-green);
}

.check-list__mark svg {
	width: 20px;
	height: 20px;
}

/* Metal Roofs section 6 lists what goes wrong rather than what you get, and
 * marks it with a red cross instead of the green tick. */
.check-list--warn .check-list__mark {
	color: var(--alert-red);
}

.check-list__text a {
	color: var(--primary-green);
	text-decoration: underline;
}

/* --- buttons -------------------------------------------------------- */
/* Section 5: body ends 540, button top 580 — a 40px gap. */
.two-column__buttons {
	margin-top: var(--space-40);
}

.two-column__text--after {
	margin-top: var(--space-30);
}

/* A green subhead inside the body copy — Vinyl-siding section 5, "Benefits of
 * Vinyl Siding" at Anek 700 29/42 #01963A, 20px above its paragraph. */
.two-column__text h3 {
	margin-bottom: var(--space-20);
	font-family: var(--font-heading);
	font-size: var(--fs-29);
	font-weight: 700;
	line-height: 1.45;
	color: var(--primary-green);
}

/* Figma stacks the content column's blocks 40px apart, so a subhead opening the
 * after-block gets that rather than the 30 a continuation paragraph gets. */
.two-column__text--after > h3:first-child {
	margin-top: 10px;
}

.two-column__text + .two-column__list,
.two-column__list + .two-column__buttons {
	margin-top: var(--space-40);
}

/* --- form panel (section 8) -----------------------------------------
 * Every number here is read off the Figma node, not estimated:
 *   panel   705x721, padding 0 0 30, stack gap 40, #FFFFFF,
 *           DROP_SHADOW 0 1px 50px rgba(0,0,0,0.05)   (no green rule)
 *   header  705x82, padding 25/15, background #333333
 *   body    594 wide  -> (705-594)/2 = 55.5 side inset
 *   field   594x60, padding 12/20, 1px #DBDBDB, 10px apart
 *   submit  156x50, padding 15/30, gap 15, #01963A
 * ------------------------------------------------------------------- */
.form-panel {
	display: flex;
	flex-direction: column;
	gap: var(--space-40);
	height: 100%;
	/* 66 at the developer's instruction. Note this moves the panel off the
	 * design: 36 + the 4px rule below made the 40 the design leaves under the
	 * submit button (button ends 772, panel ends 812 on node 1112:4062 section
	 * 8), which put the panel at exactly its drawn 692. The extra 30 opens that
	 * to 70 and grows the panel to ~722. Stepped back down below desktop, where
	 * a 66px foot is a lot of empty white on a narrow column. */
	padding-bottom: 66px;
	/* Measured on the export: a 4px #01963A rule closes the panel at y 837-840.
	 * It was removed earlier on the strength of the node dump, which reports no
	 * stroke — but the rule is a filled rectangle, not a border, so it never
	 * showed up there. The export is the authority. */
	border-bottom: 4px solid var(--primary-green);
	background-color: var(--white);
	box-shadow: 0 1px 50px 0 rgb(0 0 0 / 5%);
}

/* 400 on the lead words at the developer's instruction — the .fig instance for
 * this panel carries an `isOverrideOverTextStyle` run with fontName Regular and
 * semanticWeight NORMAL over an otherwise Bold node, which the node-level style
 * hides. The accent run keeps the weight. */
.form-panel__heading {
	margin: 0;
	padding: 25px var(--space-30) var(--space-15);
	background-color: var(--strip-grey);
	color: var(--white);
	font-family: var(--font-heading);
	font-size: var(--fs-36);
	font-weight: 400;
	line-height: var(--lh-36);
	text-align: center;
}

.form-panel__heading span,
.form-panel__heading .is-accent {
	color: var(--primary-green);
	font-weight: 700;
}

.form-panel__body {
	flex: 1 1 auto;
	padding-inline: 55px;
}

/* --- Gravity Forms inside the panel ---------------------------------
 * GF 2.9's Orbital theme ships four stylesheets that override everything,
 * so the shortcode is rendered with theme="legacy" (see kerrigan_form())
 * and the design is reproduced here instead.
 * ------------------------------------------------------------------- */
.form-panel__body .gform_wrapper,
.form-panel__body .gform_wrapper form {
	margin: 0;
}

/* A 12-column grid rather than a stack, because the Contact panel puts its
 * first eight fields two-up: 594 = 292 | 10 | 292, and 6 of 12 columns on a
 * 10px gap is exactly 292. Forms whose fields are all full width render
 * identically to the previous flex column. */
.form-panel__body .gform_fields {
	display: grid;
	grid-template-columns: repeat(12, 1fr);
	gap: var(--space-10);
	margin: 0;
	padding: 0;
	list-style: none;
}

.form-panel__body .gfield {
	grid-column: span 12;
}

.form-panel__body .gfield--width-half {
	grid-column: span 6;
}

/* Half-width fields carry a 180px min-width from the shared form styles, which
 * two-up cannot honour on a phone — they overflowed the panel by 35px at 375. */
@media (max-width: 767px) {

	.form-panel__body .gfield--width-half {
		grid-column: span 12;
	}
}

/* Gravity Forms gives each field its own margin/padding even in the legacy
 * theme; zero it so the 10px flex gap above is the only spacing. Left in, the
 * panel ran 125px past the designed 721. */
.form-panel__body .gfield {
	margin: 0;
	padding: 0;
}

.form-panel__body .gfield_label {
	/* The design shows placeholders only. */
	position: absolute !important;
	overflow: hidden;
	clip-path: inset(50%);
	width: 1px;
	height: 1px;
}

/* Gravity Forms prints its own "Accepted file types… Max. file size…" line under
 * a file input. The Careers panel is the only form on the site with an upload
 * and the design does not draw that line. It is the input's aria-describedby
 * target, so it is hidden the same way the labels are — off-canvas rather than
 * display:none — and still announced. */
.form-panel__body .gform_fileupload_rules {
	position: absolute !important;
	overflow: hidden;
	clip-path: inset(50%);
	width: 1px;
	height: 1px;
}

/* --- file upload (Careers only) --------------------------------------
 * Read off the Careers panel node, which differs from the estimate panel:
 *   panel        705x648, padding-bottom 40 (the estimate panel's is 30)
 *   fields group 594x406 = inputs 340 + gap 20 + upload row 46
 *   upload row   279x46 — a dark CHOOSE FILE button beside "No file chosen"
 * The native control is 32 tall with a 10px gap above it, which left the panel
 * 34px short once the file-type hint was hidden.
 * ------------------------------------------------------------------- */
.form-panel__body .gfield--type-fileupload {
	/* 10 here plus the 10 the field stack already carries makes the design's 20. */
	margin-top: 10px;
}

.form-panel__body .ginput_container_fileupload {
	display: flex;
	align-items: center;
	height: 46px;
}

.form-panel__body input[type="file"] {
	font-family: var(--font-body);
	font-size: var(--fs-14);
	color: var(--body-grey);
}

.form-panel__body input[type="file"]::file-selector-button {
	height: 46px;
	margin-right: var(--space-15);
	padding: 0 var(--space-25);
	border: 0;
	background: var(--strip-grey);
	color: var(--white);
	font-family: var(--font-body);
	font-size: var(--fs-18);
	font-weight: 600;
	text-transform: uppercase;
	cursor: pointer;
	transition: all 0.3s ease;
}

.form-panel__body input[type="file"]::file-selector-button:hover {
	background: var(--primary-black);
}

.two-column--form-pad-40 .form-panel {
	padding-bottom: var(--space-40);
}

.form-panel__body input[type="text"],
.form-panel__body input[type="email"],
.form-panel__body input[type="tel"],
.form-panel__body select,
.form-panel__body textarea {
	width: 100%;
	height: 60px;
	padding: 12px var(--space-20);
	border: 1px solid var(--border-grey);
	border-radius: var(--radius-0);
	background-color: var(--white);
	color: var(--primary-black);
	font-family: var(--font-body);
	font-size: var(--fs-18);
	font-weight: 400;
	line-height: var(--lh-18-30);
	transition: var(--transition);
}

.form-panel__body select {
	appearance: none;
	background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 18 10'%3E%3Cpath d='M1 1l8 8 8-8' fill='none' stroke='%23010101' stroke-width='2'/%3E%3C/svg%3E");
	background-repeat: no-repeat;
	background-position: right var(--space-20) center;
	background-size: 18px 10px;
	padding-right: 50px;
}

.form-panel__body input:focus,
.form-panel__body select:focus {
	border-color: var(--primary-green);
	outline: none;
}

.form-panel__body ::placeholder {
	color: var(--primary-black);
	opacity: 1;
}

/* The design opens 20px between the last input and the consent row, where the
 * inputs themselves are 10 apart (field tops 242/312/382/452/522, consent 602). */
.form-panel__body .gfield--type-consent {
	margin-top: var(--space-10);
}

/* Consent row: 20x20 box, 4px optical nudge onto the first text line. */
.form-panel__body .gfield--type-consent .ginput_container_consent {
	display: flex;
	align-items: flex-start;
	gap: var(--space-15);
}

/* Drawn rather than left native. Safari rounds its own checkbox and Chrome does
 * not, so the same 20px box rendered as a squircle on one and a square on the
 * other. `appearance: none` drops the platform control — which also drops
 * `accent-color`, so the checked state is painted here: a green fill and a tick
 * built from two borders on ::after. */
.form-panel__body .gfield--type-consent input[type="checkbox"] {
	appearance: none;
	-webkit-appearance: none;
	position: relative;
	flex: 0 0 auto;
	width: 20px;
	height: 20px;
	margin-top: 4px;
	border: 1px solid var(--border-grey);
	border-radius: 0;
	background-color: var(--white);
	cursor: pointer;
}

.form-panel__body .gfield--type-consent input[type="checkbox"]:checked {
	border-color: var(--primary-green);
	background-color: var(--primary-green);
}

.form-panel__body .gfield--type-consent input[type="checkbox"]:checked::after {
	position: absolute;
	top: 50%;
	left: 50%;
	width: 5px;
	height: 10px;
	/* The tick is the right and bottom borders of the box, so once it is rotated
	 * its INK sits toward the bottom-right of the box it is drawn in — centring
	 * the box left the mark 0.4/0.5px low and right, measured at 4x. The nudge
	 * centres the ink itself. */
	transform: translate(calc(-50% - 0.4px), calc(-50% - 0.5px)) rotate(45deg);
	border-right: 2px solid var(--white);
	border-bottom: 2px solid var(--white);
	content: "";
}

.form-panel__body .gfield--type-consent input[type="checkbox"]:focus-visible {
	outline: 2px solid var(--primary-green);
	outline-offset: 2px;
}

.form-panel__body .gfield_consent_label,
.form-panel__body .gfield--type-consent label {
	color: var(--primary-black);
	font-family: var(--font-body);
	font-size: var(--fs-18);
	font-weight: 400;
	line-height: var(--lh-18-30);
}

/* Gravity Forms wraps the consent field in a <fieldset>, which carries the
 * browser's default 2px groove border. The design has no box there. */
.form-panel__body fieldset {
	margin: 0;
	padding: 0;
	border: 0;
	min-width: 0;
}

.form-panel__body legend {
	padding: 0;
}

.form-panel__body .gform_required_legend,
.form-panel__body .gfield_required {
	/* The design shows no "(Required)" legend or per-field suffix; every
	 * required placeholder already ends with an asterisk. */
	display: none;
}

.form-panel__body .gform_footer {
	display: flex;
	/* Figma centres the submit under the consent copy rather than hanging it
	 * off the left edge. */
	justify-content: center;
	margin: var(--space-30) 0 0;
	padding: 0;
}

/* Figma "Button" node: 156x50, padding 15/30. Same trap as the hero submit —
 * .btn's 20px block padding renders 60 unless the height is stated. */
.form-panel__body .gform_button {
	width: auto;
	height: 50px;
	padding: 0 var(--space-30);
}

/* Tracked out at the developer's instruction. Scoped to the block's own
 * selector, not the shared .form-panel__body, so the panel on every other
 * layout keeps the label it was set with. */
.two-column__form-body .gform_button {
	letter-spacing: 0.05em;
}

/* --- responsive ------------------------------------------------------ */
@media (max-width: 1199px) {

	.two-column__inner,
	.two-column--reverse .two-column__inner,
	.two-column--gap-80 .two-column__inner,
	.two-column--gap-72 .two-column__inner,
	.two-column--gap-143 .two-column__inner {
		gap: var(--space-40);
	}
}

@media (max-width: 991px) {

	/* The gap variants carry a two-class selector, so they outrank a bare
	 * .two-column__inner here and stay side by side unless they are named. */
	.two-column__inner,
	.two-column--reverse .two-column__inner,
	.two-column--gap-80 .two-column__inner,
	.two-column--gap-72 .two-column__inner,
	.two-column--reverse.two-column--gap-80 .two-column__inner,
	.two-column--reverse.two-column--gap-72 .two-column__inner,
	.two-column--gap-143 .two-column__inner,
	.two-column--reverse.two-column--gap-143 .two-column__inner {
		grid-template-columns: 1fr;
		gap: var(--space-40);
	}

	/* Stacked, the image always leads — a reversed desktop row that keeps its
	 * order on mobile puts a wall of text above the fold. */
	.two-column--reverse .two-column__media {
		order: 1;
	}

	.two-column--reverse .two-column__content {
		order: 2;
	}

	/* Except when the media IS the form. Leading with it puts a ten-field
	 * panel above the copy that explains what the form is for, and pushes the
	 * heading off the first screen. The form goes last on mobile, at the
	 * developer's instruction. Two classes, so it outranks the rule above. */
	.two-column--reverse.two-column--form .two-column__media {
		order: 2;
	}

	.two-column--reverse.two-column--form .two-column__content {
		order: 1;
	}

	/* 100%, at the developer's instruction. `auto` let the image fall back to
	 * its own proportions inside a box still holding the Figma --media-ratio,
	 * and every source that is wider than its placed box left dead space under
	 * the photo — a 705x281 file in a 705/512 box painted 705x281 and left 231
	 * empty. Filling the box hands the crop back to `object-fit: cover`, which
	 * is what it does above 992. */
	.two-column__image {
		height: 100%;
	}
}

/* Tablet — 1199 rather than 991, so iPad landscape steps down with the rest. */
@media (max-width: 1199px) {

	.form-panel {
		padding-bottom: 50px;
	}
}

@media (max-width: 767px) {

	.form-panel {
		gap: 10px;
		padding-bottom: var(--space-36, 36px);
	}

	.form-panel__body {
		padding: var(--space-20);
	}

	/* 15 at the developer's instruction. The fields inherit the desktop body
	 * size otherwise, which is wider than a 375 column wants. Note 15 is below
	 * the 16px iOS Safari uses as its zoom-on-focus threshold, so tapping a
	 * field will zoom the page on an iPhone. */
	.form-panel__body input[type="text"],
	.form-panel__body input[type="email"],
	.form-panel__body input[type="tel"],
	.form-panel__body select,
	.form-panel__body textarea {
		font-size: 15px;
	}

	/* The consent tickbox is the one label the panel shows — every other
	 * gfield_label is screen-reader only, because the design uses placeholders.
	 * 15 at the developer's instruction, matching the fields above. */
	.form-panel__body .gfield_consent_label,
	.form-panel__body .gfield--type-consent label {
		font-size: 15px;
	}
}
