/* ==========================================================================
   Northeast Discount Transmission — pitch site
   Rebuilt from the kafka-law-firm Framer reference (dossier 2026-08-04).
   Canvas: ~84% white; two near-black framing bands (hero + CTA/footer).
   Type: Newsreader (display) + Golos Text (body).
   Accent #8A2438 oxblood — only in the dossier's listed slots.
   Everything square except the single 99px nav pill.
   ========================================================================== */

:root {
	--ink: #101010;
	--ink-soft: rgba(16, 16, 16, 0.78);
	--ink-faint: rgba(16, 16, 16, 0.55);
	--paper: #ffffff;
	--dark: #101010;
	--hero: #0a0a0a;
	--accent: #8A2438;
	--accent-rgb: 138, 36, 56;
	--font-display: "Newsreader", Georgia, serif;
	--font-body: "Golos Text", system-ui, sans-serif;

	/* contact wizard tokens (palette-agnostic shared component) */
	--wz-backdrop: rgba(10, 10, 10, 0.66);
	--wz-surface: #ffffff;
	--wz-line: #e4e2df;
	--wz-ink: #101010;
	--wz-ink-soft: #5f5d5a;
	--wz-accent: #8A2438;
	--wz-accent-strong: #6d1c2d;
	--wz-accent-tint: rgba(138, 36, 56, 0.06);
	--wz-hover-line: #8A2438;
	--wz-font-ui: "Golos Text", system-ui, sans-serif;
	--wz-radius: 2px;
}

* {
	box-sizing: border-box;
}

html {
	scroll-behavior: auto;
}

body {
	margin: 0;
	background: var(--paper);
	color: var(--ink);
	font-family: var(--font-body);
	font-size: 16px;
	line-height: 1.6;
	-webkit-font-smoothing: antialiased;
	text-rendering: optimizeLegibility;
}

img {
	max-width: 100%;
	height: auto;
	display: block;
}

a {
	color: inherit;
	text-decoration: none;
}

h1, h2, h3, p, blockquote {
	margin: 0;
}

button {
	font-family: inherit;
}

ul {
	margin: 0;
	padding: 0;
	list-style: none;
}

/* Single grouped nowrap rule for every pill / button label */
.site-header__cta,
.wizard-nav .button,
.nav-overlay__links .site-header__cta {
	white-space: nowrap;
}

:focus-visible {
	outline: 2px solid var(--accent);
	outline-offset: 2px;
}

/* ---------- layout wrapper (gutter reproduced, never hardcoded) ---------- */
.wrap {
	width: 100%;
	max-width: 1368px;
	margin-inline: auto;
	padding-inline: max(24px, calc((100% - 1368px) / 2));
}

/* ---------- shared type ---------- */
.eyebrow {
	display: flex;
	align-items: center;
	gap: 12px;
	font-size: 12px;
	font-weight: 500;
	letter-spacing: 0.16em;
	text-transform: uppercase;
	color: #000000;
}

/* oxblood tick mark — eyebrow accent slot */
.eyebrow::before {
	content: "";
	flex: 0 0 auto;
	width: 14px;
	height: 2px;
	background: var(--accent);
}

.eyebrow--on-dark {
	color: rgba(255, 255, 255, 0.85);
}

.section-title {
	font-family: var(--font-display);
	font-size: 48px;
	font-weight: 400;
	/* 1.1 packs a 48px serif tight enough that descenders meet the next line's
	   ascenders on any two-line heading. */
	line-height: 1.22;
	letter-spacing: -0.02em;
	color: var(--ink);
	margin-top: 18px;
}

.text-link {
	display: inline-flex;
	align-items: center;
	gap: 10px;
	font-size: 15px;
	font-weight: 500;
	color: var(--ink);
}

.text-link .arrow {
	flex: 0 0 auto;
	transition: transform 0.2s ease;
}

.text-link:hover {
	color: var(--ink);
}

/* ---------- header ---------- */
.site-header {
	position: fixed;
	top: 0;
	left: 0;
	right: 0;
	z-index: 60;
	height: 91px;
	/* Translucent, never frosted. backdrop-filter would make this element the
	   containing block for position:fixed descendants, and .nav-overlay is one
	   of them - the mobile menu would size against the 91px header instead of
	   the viewport and collapse. If a frosted look is ever wanted, #nav-toggle
	   AND .nav-overlay must both move out to <body> first, because the menu is
	   driven by the sibling selector .nav-toggle-input:checked ~ .nav-overlay. */
	background: rgba(10, 10, 10, 0.76);
	transition: background 0.3s ease;
}

.site-header.is-scrolled {
	/* Opaque, not 0.94: at that alpha the hero's own CTA reads through the
	   bar and collides with the nav labels. */
	background: var(--hero);
}

.site-header__inner {
	height: 100%;
	max-width: 1368px;
	margin-inline: auto;
	padding-inline: max(24px, calc((100% - 1368px) / 2));
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 24px;
}

/* Both brands live in the bar on both pages; the active one is marked, never
   the inactive one dimmed. Greying the Northeast mark would push a 71%-white
   logo into its failing contrast range. */
.site-header__brands {
	display: flex;
	align-items: stretch;
	align-self: stretch;
	flex: 0 0 auto;
}

.brand-slot {
	display: flex;
	align-items: center;
	padding-inline: 20px;
	position: relative;
	text-decoration: none;
}

/* Sized by WIDTH, not height. The Northeast mark is a 2.43:1 arched wordmark
   whose strokes are already thin; matching the Hay script's height shrinks it
   to ~83px wide and it reads as a smudge. Its original slot was 126px. */
.brand-slot__mark {
	width: 126px;
	height: auto;
	display: block;
}

/* The Hay & Sons script is navy ink and measures 1.21:1 on the dark bar, so it
   sits on a paper plate spanning the bar's full height. The plate is the reason
   no reversed white version of their mark had to be invented. */
.brand-slot--hay {
	background: var(--paper);
}

/* The script is 1.62:1 and much heavier per unit height, so it holds its own
   against the wordmark at a smaller width. */
.brand-slot__mark--hay {
	width: 84px;
}

.brand-slot.is-active::after {
	content: "";
	position: absolute;
	left: 20px;
	right: 20px;
	bottom: 0;
	height: 3px;
	background: var(--accent-on-dark);
}

/* Inside the paper plate the on-dark accent measures 3.72:1 and reads washed
   out; the base accent measures 8.79:1 there. One marker, one token per canvas. */
.brand-slot--hay.is-active::after {
	left: 0;
	right: 0;
	background: var(--accent);
}

.site-header__nav {
	display: flex;
	align-items: center;
	gap: 36px;
}

.site-header__nav > a {
	font-size: 12px;
	font-weight: 500;
	letter-spacing: 0.14em;
	text-transform: uppercase;
	color: #ffffff;
	transition: color 0.2s ease;
}

/* The header used to turn PAPER on scroll, so every control inverted to ink.
   It is now dark in both states — it only deepens from 0.76 to 0.94 — so those
   inversions would paint ink on near-black. Measured at 1.07:1 before removal.
   The top-state colours are correct in both states; there is nothing to swap. */

/* the single 99px pill — structural, not an accent slot */
.site-header__cta {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	height: 43px;
	padding: 0 28px;
	border-radius: 99px;
	background: #ffffff;
	color: var(--ink);
	font-size: 15px;
	font-weight: 500;
	transition: background 0.4s ease;
}

.site-header__cta:hover {
	background: rgba(255, 255, 255, 0.8);
}

/* The pill kept its white fill in both states for the same reason as the nav
   links above: inverted to var(--ink) it becomes a dark pill on a dark bar and
   stops reading as a button at all. */

/* mobile toggle + overlay */
.nav-toggle-input {
	position: absolute;
	opacity: 0;
	pointer-events: none;
}

.nav-toggle {
	display: none;
	align-items: center;
	justify-content: center;
	width: 44px;
	height: 44px;
	/* The 44px above is a hint, not a floor. This is a flex item in the header
	   row, and flex-shrink defaults to 1 — with the two brand plates and the
	   nav competing for a 390px line, the box was being squeezed to 28px wide
	   while keeping its full height, so it measured "44px tall" and passed a
	   glance. The menu button is the only way into navigation on a phone. */
	flex: 0 0 auto;
	color: #ffffff;
	cursor: pointer;
}

.nav-overlay {
	display: none;
}

/* ---------- hero ---------- */
.hero {
	position: relative;
	background: var(--hero);
	color: #ffffff;
	overflow: clip;
}

/* The reference hero is a FULL-BLEED 1440x900 <video> with the scrim below over
   it. The dossier recorded "zero photo" — its §15 notes view_image was broken,
   so it read the band via OCR + pixel analysis, measured ~84% dark and concluded
   there was nothing there. The build reproduced 1013px of geometry with nothing
   in it, which is what the owner saw as a black void. Media layer restored as a
   photo (no video of theirs exists); the scrim already matched. */
.hero__media {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	object-fit: cover;
	z-index: 0;
}

.hero__scrim {
	position: absolute;
	left: 0;
	right: 0;
	bottom: 0;
	height: 240px;
	background: linear-gradient(rgba(16, 16, 16, 0) 0%, rgba(16, 16, 16, 0.8) 100%);
	pointer-events: none;
}

.hero__grid {
	position: relative;
	z-index: 1;
	display: grid;
	grid-template-columns: 674px minmax(0, 1fr);
	column-gap: 64px;
	align-items: end;
	/* The reference band is a flat 1013px. Faithful — and on any laptop whose
	   content area is shorter than that (measured 814px on the owner's window,
	   which is ordinary once browser chrome is counted) the headline falls below
	   the fold and the hero reads as an empty photo. Cap to the viewport so the
	   H1 is always visible; the 1013px intent still applies on tall displays.
	   Padding scales with it so the vertical rhythm holds at both sizes. */
	min-height: min(1013px, 100svh);
	padding-top: clamp(160px, 27svh, 280px);
	padding-bottom: clamp(90px, 15svh, 150px);
}

.hero__title {
	font-family: var(--font-display);
	font-size: 84px;
	font-weight: 400;
	line-height: 1.1;
	letter-spacing: -0.02em;
	color: #ffffff;
	max-width: 674px;
}

.hero__side {
	align-self: start;
	max-width: 520px;
	animation: hero-fade 0.7s ease-out both;
}

.hero__copy {
	margin-bottom: 36px;
	font-size: 15px;
	line-height: 1.7;
	color: rgba(255, 255, 255, 0.82);
}

.hero__cta {
	display: inline-flex;
	align-items: center;
	gap: 10px;
	font-size: 16px;
	font-weight: 500;
	color: #ffffff;
	text-decoration: underline;
	text-decoration-color: var(--accent);
	text-decoration-thickness: 2px;
	text-underline-offset: 6px;
	transition: color 0.2s ease;
}

.hero__cta .arrow {
	flex: 0 0 auto;
}

.hero__cta:hover {
	color: #ffffff;
	text-decoration-color: var(--accent);
}

@keyframes hero-fade {
	from { opacity: 0; transform: translateY(8px); }
	to { opacity: 1; transform: none; }
}

/* ---------- split hero (dual brand) ----------
   Equal halves. Active/inactive is expressed through CONTENT and a rule, never
   by dimming a mark: each logo is only legible on its own canvas, so greying
   either one pushes it toward its failing contrast range. */
.hero--split {
	display: flex;
	align-items: stretch;
	min-height: min(680px, 94svh);
	padding-top: 91px;              /* clears the fixed header */
	overflow: clip;
}

.hero--split .hero__half {
	flex: 1 1 50%;
	min-width: 0;                   /* flex children default to min-content */
	position: relative;
	display: flex;
	align-items: center;
	overflow: clip;
}

.hero--split .hero__half--ndt {
	background: var(--hero);
	color: #ffffff;
}

.hero--split .hero__half--hay {
	background: var(--paper);
	color: var(--ink);
}

/* The base hero scrim is a 240px bottom gradient, sized for a headline sitting
   at the foot of a full-bleed photo. Here the mark, headline, copy and button
   all sit over the image, so the whole half needs covering. Measured in
   _review — the white mark holds above its flat-colour figure. */
.hero--split .hero__scrim {
	inset: 0;
	height: auto;
	background: linear-gradient(180deg, rgba(10, 10, 10, 0.42) 0%, rgba(10, 10, 10, 0.78) 100%);
}

/* The Hay half carries dark ink on paper, so its scrim runs the other way:
   it lightens the photograph instead of darkening it. Using the dark scrim
   here would leave navy script and near-black headline on a mid-grey field. */
.hero--split .hero__scrim--hay {
	background: linear-gradient(180deg, rgba(255, 255, 255, 0.80) 0%, rgba(255, 255, 255, 0.93) 100%);
}

/* Both halves lay their content on the SAME horizontal planes: the marks share
   a top edge and the two buttons share a baseline. Centring each half
   independently floats them to different heights, which reads as one brand
   being an afterthought bolted onto the other. */
.hero--split .hero__inner {
	position: relative;
	z-index: 1;
	width: 100%;
	max-width: 560px;
	margin-inline: auto;
	padding: clamp(40px, 6vh, 72px) clamp(24px, 4vw, 56px);
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	align-self: stretch;
	animation: hero-fade 0.7s ease-out both;
}

/* Fixed HEIGHT, auto width. The two marks have very different aspects (2.43:1
   against 1.62:1), so matching their widths would leave their baselines
   nowhere near each other. */
.hero__mark {
	height: 88px;
	width: auto;
	display: block;
	/* Centred in its half. The two marks are very different widths at a shared
	   height, so left-aligning them made the halves look misregistered. */
	margin-inline: auto;
	margin-bottom: 26px;
	flex: 0 0 auto;
}

.hero__mark--hay {
	height: 88px;
}

/* Pushes both buttons to the foot of their half, which is what puts them on a
   shared plane regardless of how much copy sits above each one. */
.hero--split .hero__cta,
.hero--split .hero__switch {
	margin-top: auto;
	flex: 0 0 auto;
}

/* The 84px display size is set for a full-bleed headline; at half width it
   breaks into ragged two-word lines. */
.hero--split .hero__title {
	font-size: clamp(32px, 3.3vw, 50px);
	line-height: 1.18;
	max-width: none;
	margin-bottom: 26px;
}

.hero--split .hero__copy {
	margin-bottom: 30px;
}

.hero__copy--hay {
	color: var(--ink-soft);
}

.hero__kicker {
	font-family: var(--font-body);
	font-size: 12px;
	font-weight: 600;
	letter-spacing: 0.14em;
	text-transform: uppercase;
	color: var(--ink-faint);
	margin-bottom: 16px;
}


.hero__switch {
	display: inline-flex;
	align-items: center;
	gap: 10px;
	font-size: 13px;
	font-weight: 600;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var(--accent);
	border-bottom: 1px solid currentColor;
	padding-bottom: 4px;
}

.hero--split .hero__half.is-active::after {
	content: "";
	position: absolute;
	left: 0;
	right: 0;
	bottom: 0;
	height: 4px;
	background: var(--accent-on-dark);
	z-index: 2;
}

.hero--split .hero__half--hay.is-active::after {
	background: var(--accent);
}

/* ---- canvas modifiers ----
   These MUST come after the base rules they modify. Every one of them has the
   same specificity as its base (0,1,0), so source order decides the winner —
   placed earlier, .hero__switch--dark silently loses to .hero__switch and the
   link renders at 2.25:1 on near-black while the CSS still reads correct.
   Each element that crosses between the two canvases restates its colour. */
.hero__title--hay {
	color: var(--ink);
}

.hero__kicker--dark {
	color: rgba(255, 255, 255, 0.68);
}

.hero__switch--dark {
	color: var(--accent-on-dark);
}

.hero__cta--hay {
	color: var(--accent);
}

@media screen and (max-width: 900px) {
	.hero--split {
		flex-direction: column;
		min-height: 0;
	}

	.hero--split .hero__half {
		flex: 0 0 auto;
		min-height: 62svh;
	}

	/* The brand whose page this is leads the stack.
	   Source order is Northeast-first on BOTH pages — that is what makes the
	   hero identical, and side by side it is right: order is spatial and both
	   halves are on screen at once. Stacking converts that spatial order into a
	   sequence, and the hero is 1138px in an 844px viewport, so first became
	   ONLY. The Hay page opened on a greyscale Northeast hero with its own h1
	   614px below the fold — the greying reads as "the other brand" beside a
	   colour half, and as "closed" when it is the whole screen.

	   CSS order rather than reordering the markup: a DOM swap would put
	   Northeast on the RIGHT on the Hay page and the desktop heroes would no
	   longer match. Keyed off .is-active so one rule serves both pages.

	   This does leave visual order ahead of DOM order for the stacked case.
	   Accepted here: the two halves are independent sibling panels, not a
	   sequence, and every control in the passed-over half (cover link and CTA)
	   goes to the same destination, so nothing is skipped by reading in source
	   order. Do not extend this pattern to content where order carries meaning. */
	.hero--split .hero__half.is-active {
		order: -1;
	}

	.hero--split .hero__inner {
		padding-block: 44px;
	}

	.hero__mark {
		width: 196px;
	}
}

/* ---------- capability strip ---------- */
.cap-strip {
	border-bottom: 1px solid #eceae6;
	padding: 34px 0;
}

.cap-strip__line {
	font-size: 12px;
	font-weight: 500;
	letter-spacing: 0.16em;
	text-transform: uppercase;
	color: var(--ink);
}

/* ---------- about ---------- */
.about {
	padding: 130px 0 140px;
}

/* 337px is the reference's IMAGE column (337x280 stacked photos in services,
   337x333 timeline images). This column holds a 48px display HEADING, not a
   photo — pinned at 337px it broke to ~1.7 words per line. Sized for the type
   instead; the services/process grids keep 337px because those really do hold
   the images. See verification.md "Borrowed dimensions". */
.about__grid {
	display: grid;
	grid-template-columns: minmax(420px, 480px) minmax(0, 1fr);
	column-gap: 96px;
}

.about__lead {
	align-self: start;
}

/* 337px is the reference's IMAGE column width (337x280 photos, 337x333 timeline
   images) — applying it to a 48px display heading broke it to ~1.7 words per
   line. A borrowed dimension used on a box whose content does not fit it; see
   verification.md "Borrowed dimensions". Measure set for the TYPE instead. */
.about__lead .section-title {
	max-width: 15ch;
}

.about__copy {
	align-self: start;
	padding-top: 8px;
	max-width: 620px;
}

.about__copy p {
	margin-bottom: 24px;
	font-size: 16px;
	line-height: 1.75;
	color: var(--ink-soft);
}

.about__copy p:last-child {
	margin-bottom: 0;
}

/* ---------- services ---------- */
.services {
	padding: 0 0 150px;
}

.services__grid {
	display: grid;
	grid-template-columns: minmax(337px, 430px) 684px;
	column-gap: 48px;
	justify-content: start;
}

.services__left .section-title {
	margin: 18px 0 56px;
}

.services__photos {
	display: flex;
	flex-direction: column;
	gap: 73px;
}

.services__photo {
	width: 337px;
	height: 280px;
	object-fit: cover;
}

.services__rows {
	padding-top: 250px;
}

.service-row {
	padding: 30px 0 26px;
	border-top: 1px solid #e4e2df;
	margin-bottom: 213px;
}

.service-row:last-of-type {
	margin-bottom: 140px;
}

.service-row__title {
	font-size: 12px;
	font-weight: 500;
	letter-spacing: 0.16em;
	text-transform: uppercase;
	color: var(--ink);
	margin-bottom: 14px;
}

.service-row__caption {
	font-size: 15px;
	line-height: 1.65;
	color: var(--ink-soft);
	max-width: 560px;
}

/* ---------- trust / why us ---------- */
.trust {
	padding: 140px 0;
}

.trust__grid {
	display: grid;
	grid-template-columns: minmax(0, 1fr) 428px;
	column-gap: 96px;
	align-items: start;
}

.trust__left .section-title {
	margin: 18px 0 64px;
	max-width: 560px;
}

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

.trust-point {
	display: grid;
	grid-template-columns: 40px minmax(0, 1fr);
	column-gap: 18px;
	padding: 30px 0 34px;
	border-top: 1px solid #e4e2df;
}

.trust-point__icon {
	grid-row: span 2;
	display: flex;
	align-items: flex-start;
	justify-content: flex-start;
	color: var(--ink);
	padding-top: 2px;
}

.trust-point__label {
	font-size: 13px;
	font-weight: 600;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	color: var(--ink);
	margin-bottom: 10px;
}

.trust-point__caption {
	font-size: 14px;
	line-height: 1.65;
	color: var(--ink-soft);
	max-width: 520px;
}

.trust__portrait {
	width: 428px;
	height: 500px;
	object-fit: cover;
}

/* ---------- process ---------- */
.process {
	padding: 150px 0;
}

.process__grid {
	display: grid;
	grid-template-columns: 330px minmax(0, 1fr);
	column-gap: 96px;
	align-items: start;
}

.process__portrait {
	width: 330px;
	height: 385px;
	object-fit: cover;
}

.process__right .section-title {
	margin: 18px 0 64px;
	max-width: 600px;
}

.process__steps {
	display: flex;
	flex-direction: column;
	margin-bottom: 48px;
}

.process-step {
	padding: 26px 0;
	border-top: 1px solid #e4e2df;
}

.process-step__title {
	font-family: var(--font-display);
	font-size: 22px;
	font-weight: 500;
	color: var(--ink);
	margin-bottom: 8px;
}

.process-step__caption {
	font-size: 14px;
	line-height: 1.65;
	color: var(--ink-soft);
	max-width: 580px;
}

/* ---------- stories ---------- */
.stories {
	padding: 140px 0 150px;
}

.stories__grid {
	display: grid;
	grid-template-columns: 337px minmax(0, 1fr);
	column-gap: 96px;
	align-items: start;
}

.stories__left .section-title {
	margin: 18px 0 56px;
}

.stories__intro {
	width: 337px;
	height: 333px;
	object-fit: cover;
}

.stories__cards {
	display: flex;
	flex-direction: column;
	gap: 120px;
	padding-top: 12px;
}

.story-card {
	display: flex;
	align-items: stretch;
	max-width: 684px;
	border: 1px solid #e4e2df;
	background: var(--paper);
}

.story-card__media {
	flex: 0 0 337px;
	width: 337px;
	height: 333px;
	object-fit: cover;
}

.story-card--media-right {
	flex-direction: row-reverse;
}

.story-card--media-left {
	flex-direction: row;
}

.story-card__body {
	flex: 1 1 auto;
	min-width: 0;
	display: flex;
	flex-direction: column;
	justify-content: center;
	padding: 34px 40px;
}

/* oxblood tag chip — timeline accent slot */
.tag-chip {
	align-self: flex-start;
	display: inline-block;
	padding: 5px 12px;
	border: 1px solid var(--accent);
	color: var(--accent);
	font-size: 11px;
	font-weight: 500;
	letter-spacing: 0.12em;
	text-transform: uppercase;
	margin-bottom: 20px;
}

.story-card__title {
	font-family: var(--font-display);
	font-size: 24px;
	font-weight: 500;
	color: var(--ink);
	margin-bottom: 14px;
}

.story-card__quote {
	font-size: 13px;
	line-height: 1.7;
	color: var(--ink-soft);
}

/* ---------- testimonial ---------- */
.testimonial {
	padding: 150px 0;
}

.testimonial__grid {
	display: grid;
	grid-template-columns: minmax(0, 1fr) 330px;
	column-gap: 96px;
	align-items: start;
}

.testimonial__lead .section-title {
	margin: 18px 0 56px;
	max-width: 560px;
}

.testimonial__quote {
	font-family: var(--font-display);
	font-size: 26px;
	line-height: 1.45;
	letter-spacing: -0.01em;
	color: var(--ink);
	max-width: 720px;
	margin-bottom: 28px;
}

.testimonial__attr {
	font-size: 12px;
	font-weight: 500;
	letter-spacing: 0.14em;
	text-transform: uppercase;
	color: var(--ink-soft);
	margin-bottom: 40px;
}

.testimonial__photo {
	width: 330px;
	height: 275px;
	object-fit: cover;
}

/* ---------- FAQ ---------- */
.faq {
	padding: 40px 0 150px;
}

.faq__grid {
	display: grid;
	grid-template-columns: 337px minmax(0, 1fr);
	column-gap: 96px;
	align-items: start;
}

.faq__lead .section-title {
	margin: 18px 0 56px;
}

.faq__lead {
	align-self: start;
}

.faq__list {
	border-bottom: 1px solid #e4e2df;
}

.faq-row {
	border-top: 1px solid #e4e2df;
}

.faq-row__heading {
	margin: 0;
}

.faq-row__q {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 24px;
	width: 100%;
	padding: 30px 4px 30px 0;
	background: none;
	border: 0;
	cursor: pointer;
	text-align: left;
	font-size: 17px;
	font-weight: 500;
	color: var(--ink);
}

/* the + is a real inline SVG, oxblood on hover (accent slot) */
.faq-row__q .faq-plus {
	flex: 0 0 auto;
	color: var(--ink);
	transition: color 0.2s ease;
}

.faq-row__q:hover .faq-plus {
	color: var(--accent);
}

.faq-row__a {
	display: grid;
	grid-template-rows: 1fr;
	transition: grid-template-rows 0.3s ease;
}

.faq-row__a-inner {
	overflow: hidden;
	font-size: 14px;
	line-height: 1.7;
	color: var(--ink-soft);
	max-width: 720px;
	padding-bottom: 28px;
}

/* JS-enhanced accordion: one row open at a time. Without JS every answer
   stays visible — content never depends on the script. */
.has-js .faq-row:not(.is-open) .faq-row__a {
	grid-template-rows: 0fr;
}

.has-js .faq-row:not(.is-open) .faq-row__a-inner {
	padding-bottom: 0;
}

/* ---------- CTA band + footer (the dark framing band) ---------- */
.cta-band {
	background: var(--dark);
	color: #ffffff;
	padding: 140px 0 120px;
}

.cta-band__grid {
	display: grid;
	grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
	column-gap: 120px;
}

.cta-band__title {
	font-family: var(--font-display);
	font-size: 64px;
	font-weight: 400;
	line-height: 1.05;
	letter-spacing: -0.02em;
	text-transform: uppercase;
	color: #ffffff;
	margin: 18px 0 32px;
}

.cta-band__body {
	font-size: 15px;
	line-height: 1.75;
	color: rgba(255, 255, 255, 0.78);
	max-width: 520px;
	margin-bottom: 20px;
}

.cta-band__note {
	font-size: 13px;
	line-height: 1.7;
	color: rgba(255, 255, 255, 0.6);
	max-width: 520px;
	margin-bottom: 40px;
}

.cta-band__link {
	display: inline-flex;
	align-items: center;
	gap: 10px;
	font-size: 16px;
	font-weight: 500;
	color: #ffffff;
}

.cta-band__link .arrow {
	flex: 0 0 auto;
	transition: transform 0.2s ease;
}

.cta-band__link:hover {
	color: #ffffff;
}

.contact-block {
	padding: 26px 0;
	border-bottom: 1px solid rgba(255, 255, 255, 0.18);
}

.contact-block__label {
	font-size: 12px;
	font-weight: 500;
	letter-spacing: 0.16em;
	text-transform: uppercase;
	color: rgba(255, 255, 255, 0.55);
	margin-bottom: 12px;
}

.contact-block__value {
	font-size: 17px;
	line-height: 1.5;
	color: #ffffff;
}

/* footer phone — oxblood accent slot on the dark band */
.contact-block__phone {
	color: var(--accent);
	font-weight: 600;
}

.contact-block__phone:hover {
	color: #ffffff;
}

.site-footer {
	background: var(--dark);
	color: #ffffff;
	padding: 40px 0 90px;
}

.site-footer__inner {
	display: flex;
	flex-direction: column;
	align-items: center;
	text-align: center;
}

.site-footer__logo {
	width: 409px;
	height: 168px;
	margin-bottom: 56px;
}

.site-footer__menu {
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	gap: 20px 44px;
	margin-bottom: 48px;
}

.site-footer__menu a {
	font-size: 12px;
	font-weight: 500;
	letter-spacing: 0.16em;
	text-transform: uppercase;
	color: rgba(255, 255, 255, 0.75);
}

.site-footer__menu a:hover {
	color: #ffffff;
}

.site-footer__tagline {
	font-family: var(--font-display);
	font-size: 22px;
	font-style: italic;
	color: rgba(255, 255, 255, 0.9);
	margin-bottom: 18px;
}

.site-footer__meta {
	font-size: 13px;
	color: rgba(255, 255, 255, 0.55);
	margin-bottom: 12px;
}

.site-footer__note {
	font-size: 11px;
	line-height: 1.7;
	color: rgba(255, 255, 255, 0.4);
	max-width: 720px;
}

/* ---------- reduced motion: this template is almost entirely still ---------- */
@media (prefers-reduced-motion: reduce) {
	.hero__side {
		animation: none;
	}

	.hero__cta .arrow,
	.text-link .arrow,
	.cta-band__link .arrow {
		transition: none;
	}

	.site-header__cta {
		transition: none;
	}

	.site-header {
		transition: none;
	}

	.faq-row__a {
		transition: none;
	}
}

/* ---------- reflow: two-column sections stack around 1200px ---------- */
@media screen and (max-width: 1200px) {
	.hero__grid {
		grid-template-columns: minmax(0, 1fr);
		align-items: start;
		min-height: 0;
		padding-top: 200px;
		padding-bottom: 110px;
		gap: 56px;
	}

	.hero__title {
		max-width: 640px;
	}

	.hero__side {
		align-self: start;
	}

	.about__grid,
	.services__grid,
	.trust__grid,
	.process__grid,
	.stories__grid,
	.testimonial__grid,
	.faq__grid,
	.cta-band__grid {
		grid-template-columns: minmax(0, 1fr);
		column-gap: 0;
		row-gap: 56px;
	}

	.services__grid {
		justify-content: stretch;
	}

	.services__left .section-title {
		margin-bottom: 40px;
	}

	.services__photos {
		flex-direction: row;
		flex-wrap: wrap;
		gap: 16px;
	}

	.services__photo {
		width: calc(50% - 8px);
		height: auto;
		aspect-ratio: 337 / 280;
	}

	.services__rows {
		padding-top: 0;
	}

	.service-row {
		margin-bottom: 40px;
	}

	.service-row:last-of-type {
		margin-bottom: 40px;
	}

	.trust__portrait {
		width: 100%;
		max-width: 480px;
		height: auto;
		aspect-ratio: 428 / 500;
	}

	.process__portrait {
		width: 100%;
		max-width: 400px;
		height: auto;
		aspect-ratio: 330 / 385;
	}

	.stories__intro {
		width: 100%;
		max-width: 400px;
		height: auto;
		aspect-ratio: 337 / 333;
	}

	.stories__cards {
		gap: 40px;
	}

	.testimonial__photo {
		width: 100%;
		max-width: 480px;
		height: auto;
		aspect-ratio: 330 / 275;
	}

	.cta-band__grid {
		row-gap: 64px;
	}
}

/* ---------- mobile ---------- */
@media screen and (max-width: 760px) {
	.site-header__nav {
		display: none;
	}

	.nav-toggle {
		display: flex;
	}

	.nav-overlay {
		position: fixed;
		top: 0;
		left: 0;
		right: 0;
		height: 454px;
		/* Dark to match the bar. A paper panel over a near-black header flashes
		   white every time the menu opens. Fully opaque, unlike the bar: the
		   bar's translucency earns its keep by showing the hero through it,
		   whereas a ghost of the h1 behind the menu items is only noise.
		   Measured at 0.97 the headline still read at 18/255 against a 10/255
		   field. */
		background: var(--hero);
		color: var(--paper);
		z-index: 70;
		flex-direction: column;
		align-items: stretch;
		padding: 96px 28px 32px;
	}

	.nav-toggle-input:checked ~ .nav-overlay {
		display: flex;
	}

	.nav-overlay__close {
		position: absolute;
		top: 24px;
		right: 24px;
		display: flex;
		align-items: center;
		justify-content: center;
		width: 44px;
		height: 44px;
		/* The overlay is a near-black panel, so var(--ink) (#101010) put the X at
		   about 1.1:1 against it — present, correctly sized, and invisible. Same
		   failure as the header pill twice above: a colour token chosen for the
		   white canvas, reused on a dark one. The mark is an SVG drawn with
		   `stroke="currentColor"`, so this single property is what paints it. */
		color: #ffffff;
		cursor: pointer;
	}

	.nav-overlay__links {
		display: flex;
		flex-direction: column;
		align-items: flex-start;
		gap: 26px;
	}

	.nav-overlay__links > a:not(.site-header__cta) {
		font-size: 15px;
		font-weight: 500;
		letter-spacing: 0.14em;
		text-transform: uppercase;
		color: var(--paper);
	}

	/* On the dark panel the base accent drops to 2.25:1; the on-dark token
	   carries the button at 5.33:1 against near-black label text. */
	.nav-overlay__links .site-header__cta {
		margin-top: 18px;
		background: var(--accent-on-dark);
		color: var(--hero);
	}

	.hero__grid {
		padding-top: 170px;
		padding-bottom: 90px;
	}

	.hero__title {
		font-size: 48px;
		line-height: 1.08;
	}

	.hero__copy {
		font-size: 15px;
	}

	.cap-strip {
		padding: 26px 0;
	}

	.about {
		padding: 90px 0 100px;
	}

	.section-title {
		font-size: 36px;
		line-height: 1.12;
	}

	.services {
		padding-bottom: 100px;
	}

	.services__photos {
		/* 12px read as a filmstrip — four full-width photos nearly touching.
		   28px separates each as its own image, matching the vertical rhythm
		   the service rows below already use (30px top padding per row). */
		gap: 28px;
	}

	.services__photo {
		width: 100%;
		aspect-ratio: 337 / 280;
	}

	.trust,
	.stories {
		padding: 100px 0;
	}

	.process {
		padding: 100px 0;
	}

	.testimonial {
		padding: 100px 0;
	}

	.story-card,
	.story-card--media-right,
	.story-card--media-left {
		flex-direction: column;
	}

	.story-card__media {
		flex: 0 0 auto;
		width: 100%;
		height: auto;
		aspect-ratio: 337 / 333;
	}

	.story-card__body {
		padding: 28px 24px;
	}

	.faq {
		padding-bottom: 100px;
	}

	.faq-row__q {
		font-size: 16px;
		padding: 24px 0;
	}

	.cta-band {
		padding: 100px 0 80px;
	}

	.cta-band__title {
		font-size: 44px;
	}

	.site-footer {
		padding-bottom: 70px;
	}

	.site-footer__logo {
		width: 300px;
		height: 123px;
	}

	.site-footer__menu {
		gap: 16px 32px;
	}
}


/* The heading shares this column with the 4 stacked photos. The PHOTOS are
   genuinely 337px (reference: 337x280); the 48px heading is not, and pinned to
   337 it broke to ~1.7 words per line. Widen the TRACK for the type and pin the
   photos to their real width, rather than forcing the heading to the image
   measure. See verification.md "Borrowed dimensions". */
.services__photo { width: 337px; max-width: 100%; }

/* pill ink must outrank the nav-link colour — IN BOTH HEADER STATES */
/* `.site-header__nav > a` sets white for the nav links (0,1,1). The CTA pill
   lives inside that nav, so that rule outranked `.site-header__cta` (0,1,0) and
   the pill rendered WHITE TEXT ON A WHITE BACKGROUND — the label was present and
   invisible, contrast 1.0. Neither layout-scan nor site-kit catches this: the box
   is correctly sized and the text fits. Match the nav rule's specificity. */
.site-header__nav > a.site-header__cta {
	color: var(--ink);
}

/* accent needs a lighter tint on the dark bands */
/* #8A2438 is tuned for the WHITE canvas, where it reads strongly. On the
   near-black CTA/footer band (#101010) it falls to 2.17:1 — too low for a phone
   number, the page's key conversion element. Same hue (348deg), lifted lightness
   only, so the accent identity is unchanged: 5.12:1, clears AA for body text. */
:root { --accent-on-dark: #D55D75; }

.contact-block__phone,
.site-footer a[href^="tel:"] {
	color: var(--accent-on-dark);
}

/* The scrolled header repeats the bug in mirror image. `.site-header.is-scrolled
   .site-header__nav > a` (0,3,1) sets ink for the nav links on the now-white bar,
   and it outranks `.site-header.is-scrolled .site-header__cta` (0,3,0) — so the
   pill got ink text on its ink background: BLACK ON BLACK, 1.00:1.

   Two lessons, both cost a round trip tonight:
   1. Fixing one state of a component is not fixing the component. The top-state
      fix below left this one broken, identically.
   2. layout-scan.py's contrast pass samples at scroll 0 only, so a state that
      only exists after scrolling is invisible to it. Scroll-dependent states
      must be checked by hand until that pass learns to scroll. */
/* The mirror-image fix this rule used to carry is no longer needed: the bar
   never turns white, so the pill never needs its label re-inverted. */

/* ---------- Hay & Sons footer mark ----------
   The footer band is var(--dark) #101010, where the navy script measures
   1.21:1. The reversed mark carries it at 18.1:1, with the ampersand on the
   on-dark accent at 5.12:1 rather than the base accent's 2.25:1. */
.site-footer__logo--hay {
	width: 200px;
	height: auto;
}

/* ---------- Hay & Sons services rhythm ----------
   .service-row carries a fixed 213px margin, tuned so the transmission page's
   longer list balances against its photo column. The Hay page runs five rows
   against four photos, and the same margin leaves the photo column 403px short
   at 1440 — a visible gap before the About section. Rebalanced for this list
   length rather than changing the shared rhythm. */
.services--hay .service-row {
	margin-bottom: 132px;
}

.services--hay .service-row:last-of-type {
	margin-bottom: 40px;
}

/* ---------- inactive half: desaturated, not dimmed ----------
   The hero is identical on both pages; the brand you are NOT on is greyed.

   grayscale() rather than opacity. Desaturation converts using the luminance
   coefficients, so relative luminance — and therefore every contrast ratio in
   the half — survives almost exactly. Dimming with opacity would drag the
   white Northeast mark toward its failing range on the dark canvas, which is
   the reason this design originally avoided greying anything at all.

   filter also creates a containing block for position:fixed descendants. That
   is safe HERE because nothing inside a hero half is fixed — but do not move
   this rule up onto .hero--split or the header, which do carry fixed children. */
.hero--split .hero__half:not(.is-active) {
	filter: grayscale(1);
	transition: filter 0.35s ease;
	cursor: pointer;
}

/* Colour returns on hover or keyboard focus: a preview of the brand you are
   about to switch to, and the only affordance telling you the half is live. */
.hero--split .hero__half:not(.is-active):hover,
.hero--split .hero__half:not(.is-active):focus-within {
	filter: grayscale(0);
}

/* The whole half is the switch, not just its button.
   An explicit cover link rather than a stretched pseudo-element: ::after on the
   button resolves `inset: 0` against the nearest POSITIONED ancestor, which is
   .hero__inner, not the half - so it covered only the text column and clicks
   near the top of the half fell through. This element is a child of the half
   itself, so it covers the half.
   Present only in the INACTIVE half; the active half's button opens the
   contact modal and must not be covered. */
.hero__half-link {
	position: absolute;
	inset: 0;
	z-index: 4;
}

.hero--split .hero__half:not(.is-active) .hero__cta {
	color: var(--ink-faint);
}

.hero--split .hero__half--ndt:not(.is-active) .hero__cta {
	color: rgba(255, 255, 255, 0.72);
}

/* ---------- breathing room ----------
   Body copy sat directly against its heading and against the next paragraph.
   These are the shared blocks that carry most of the reading on both pages. */
.about__copy p + p,
.service-row__caption {
	margin-top: 22px;
}

.service-row__title {
	margin-bottom: 4px;
}

.cta-band__body {
	margin-top: 22px;
}

.cta-band__note {
	margin-top: 18px;
}

.hero--split .hero__copy {
	line-height: 1.7;
}

/* ==========================================================================
   MOBILE PASS
   Everything below was found by measuring both pages at 390x844 with touch
   emulation. The recurring cause is the same one: desktop values reaching a
   phone unchanged, because nothing in the build asked what they cost there.
   ========================================================================== */

/* ---------- wizard buttons ----------
   `.button` carries no styling anywhere in this build. The wizard component
   ships behaviour and layout and leaves the look to the site, and the site
   never claimed it — so Next and Back rendered as raw user-agent chrome:
   grey system buttons, 22px tall, at the UA default 13.3px, inside an
   otherwise finished modal. This is the conversion path for every lead the
   site collects, and it was the least finished thing on either page.
   Matched to .site-header__cta so the modal reads as part of the site. */
.wizard-nav .button {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-height: 44px;
	padding: 0 26px;
	border: 1px solid var(--ink);
	border-radius: 999px;
	background: var(--ink);
	color: var(--paper);
	font-family: var(--font-body);
	font-size: 15px;
	font-weight: 500;
	cursor: pointer;
	transition: background 0.2s ease, border-color 0.2s ease, color 0.2s ease;
}

.wizard-nav .button:hover {
	background: var(--accent);
	border-color: var(--accent);
	color: var(--paper);
}

/* Back is secondary: same size so the row stays even, no fill so it never
   competes with the action that moves the visitor forward. */
.wizard-nav .wizard-back {
	background: transparent;
	color: var(--ink);
}

.wizard-nav .wizard-back:hover {
	background: transparent;
	border-color: var(--accent);
	color: var(--accent);
}

/* At 480 the component wraps the nav and sends Next full-width, leaving Back
   stranded on its own row against the right edge — an orphan that reads as a
   third thing rather than the pair's quieter half. Full width under it instead;
   the fill/outline contrast carries the hierarchy, so matching widths costs
   nothing and both stay a full thumb wide. */
@media screen and (max-width: 480px) {
	.wizard-nav .wizard-back {
		width: 100%;
	}
}

/* ---------- fingertip targets ----------
   Measured at 390: the phone number stood 21px tall, the hero calls to action
   26px, the footer menu 19px. For a repair shop the tel: link is the single
   most valuable control on the page and it was the smallest.

   These links underline with text-decoration and text-underline-offset, both
   of which track the TEXT box rather than the padding box — so growing the hit
   area vertically does not drag the rule away from the words. That is why this
   is min-height rather than padding on a block. */
@media (pointer: coarse) {
	.hero__cta,
	.cta-band__link,
	.text-link,
	.contact-block__phone,
	.site-footer__menu a,
	.site-header__nav > a {
		min-height: 44px;
	}

	.contact-block__phone,
	.site-footer__menu a {
		display: inline-flex;
		align-items: center;
	}
}

@media screen and (max-width: 760px) {
	/* ---------- Hay services rhythm ----------
	   `.services--hay .service-row` (0,2,0) is tuned to balance a five-row list
	   against a four-photo column at desktop width. It outranks the (0,1,0)
	   mobile reduction to 40px, because a media query adds no specificity — so
	   the desktop value survived into the phone layout, where the halves stack
	   and there is no photo column left to balance against. It was buying 568px
	   of empty scroll across the list, against 160px for the same list on
	   index. Restated here at the same specificity, inside the query. */
	.services--hay .service-row,
	.services--hay .service-row:last-of-type {
		margin-bottom: 40px;
	}

	/* ---------- section rhythm ----------
	   Every band ran 100px top and bottom — 200px of empty space at each seam,
	   on a 390px-wide screen. Desktop is 150px, so the phone value was already
	   a deliberate reduction; it just was not a large enough one. index stood
	   16.6 screens tall. 72px still reads as generous at this width. */
	.trust,
	.stories,
	.process,
	.testimonial {
		padding: 72px 0;
	}

	.about {
		padding: 72px 0;
	}

	.services,
	.faq {
		padding-bottom: 72px;
	}

	.cta-band {
		padding: 72px 0 64px;
	}

	/* ---------- small type floors ----------
	   11px is below comfortable reading on a phone. These are labels and notes
	   rather than body copy, so they stay smaller than the surrounding text —
	   they just stop being the smallest thing the design is willing to ship. */
	.site-footer__note,
	.tag-chip {
		font-size: 12.5px;
	}
}
