/*
* Theme Name: All Phase Electric
* Theme URI: https://allphaseelectricnh.com
* Description: All Phase Electric LLC custom theme. Sections are composed in
* WPBakery, so layout lives in the template parts rather than per-element CSS.
* Author: Rob Parks
* Author URI: https://www.lachancedesign.com/
* Version: 1.0.0
* License: GNU General Public License v2 or later
* License URI: http://www.gnu.org/licenses/gpl-2.0.html
* Text Domain: allphase
*/
:root {
	/* Brand */
	--blue:         #22239E;
	--blue-dark:    #191A78;
	--blue-deep:    #12134F;

	/* fills / icons only — 2.09:1 on white, never text */
	--orange:       #F7A10D;
	--orange-hover: #E19008;

	/* orange TEXT on white — 4.88:1, WCAG AA */
	--orange-ink:   #A85F00;

	/* Neutrals */
	--ink:        #14161C;
	--ink-soft:   #454A55;
	--ink-faint:  #6B7280;
	--line:       #E2E5EC;
	--bg:         #FFFFFF;
	--bg-alt:     #F6F7FA;

	/* Type */
	--font-head: "Work Sans", system-ui, -apple-system, "Segoe UI", sans-serif;
	--font-body: "Catamaran", system-ui, -apple-system, "Segoe UI", sans-serif;

	/* Layout */
	--wrap: 1180px;
	--gut: clamp(1.25rem, 4vw, 2.5rem);

	/* Vertical rhythm — one scale drives every band. --space-section separates
	   content on the same background (~80px); --space-band is the internal
	   padding of colour-change bands (cta, footer). */
	--space-section: clamp(3.25rem, 6.5vw, 5rem);
	--space-band:    clamp(2.75rem, 5vw, 4rem);
	/* How far the trust card rides up over the hero's angled cut. Deliberately
	   a little under .hero-cut's own clamp(40px, 5vw, 78px) so the card
	   straddles the diagonal instead of clearing it. */
	--trust-overlap: clamp(28px, 3.5vw, 56px);
	--space-hug:     clamp(1.5rem, 3vw, 2.5rem);

	/* Component rhythm — 0.25rem steps. Section bands keep the fluid clamps
	   above; these cover gaps, card padding and heading margins. */
	--space-3xs: 0.25rem;  /*  4px */
	--space-2xs: 0.5rem;   /*  8px */
	--space-xs:  0.75rem;  /* 12px */
	--space-sm:  1rem;     /* 16px */
	--space-md:  1.25rem;  /* 20px */
	--space-lg:  1.5rem;   /* 24px */
	--space-xl:  1.75rem;  /* 28px */
	--space-2xl: 2rem;     /* 32px */
	--space-3xl: 2.5rem;   /* 40px */
	--space-4xl: 3rem;     /* 48px */

	/* Surface */
	--radius: 10px;
	--shadow: 0 1px 2px rgba(20,22,28,.06), 0 8px 24px rgba(20,22,28,.08);
	--shadow-lg: 0 2px 6px rgba(20,22,28,.08), 0 20px 50px rgba(20,22,28,.14);
}


/*---------------------------------------------------
>> Global Styles & Resets
---------------------------------------------------*/
*, *::before, *::after {
	box-sizing: border-box;
}
html {
	-webkit-text-size-adjust: 100%;
	scroll-behavior: smooth;
}
@media (prefers-reduced-motion: reduce) {
	html {
		scroll-behavior: auto;
	}
	*, *::before, *::after {
		animation-duration: .01ms !important;
		transition-duration: .01ms !important;
	}
}
body {
	margin: 0;
	background: var(--bg);
	color: var(--ink);
	font-family: var(--font-body);
	font-size: 1.0625rem;
	line-height: 1.65;
	-webkit-font-smoothing: antialiased;
}
img {
	max-width: 100%;
	height: auto;
	display: block;
}
a {
	color: var(--blue);
}
h1, h2, h3, h4 {
	font-family: var(--font-head);
	line-height: 1.15;
	margin: 0 0 .6em;
	letter-spacing: -.015em;
}
h1 {
	font-size: clamp(2.1rem, 5.2vw, 3.4rem);
	font-weight: 800;
}
h2 {
	font-size: clamp(1.65rem, 3.4vw, 2.4rem);
	font-weight: 700;
}
h3 {
	font-size: 1.2rem;
	font-weight: 700;
}
p {
	margin: 0 0 1.1em;
}
ul {
	margin: 0;
	padding: 0;
}
.wrap {
	width: min(100% - (var(--gut) * 2), var(--wrap));
	margin-inline: auto;
}
.section {
	padding: var(--space-section) 0;
}
.section-intro {
	max-width: 62ch;
	color: var(--ink-soft);
	font-size: 1.1rem;
}
.visually-hidden {
	position: absolute;
	width: 1px;
	height: 1px;
	padding: 0;
	margin: -1px;
	overflow: hidden;
	clip: rect(0 0 0 0);
	white-space: nowrap;
	border: 0;
}
.skip-link {
	position: absolute;
	left: 50%;
	top: 0;
	transform: translate(-50%, -120%);
	background: var(--blue);
	color: #fff;
	padding: var(--space-xs) var(--space-md);
	z-index: 999;
	border-radius: 0 0 var(--radius) var(--radius);
	font-family: var(--font-head);
	font-weight: 600;
}
.skip-link:focus {
	transform: translate(-50%, 0);
}
:where(a, button, input, select, textarea):focus-visible {
	outline: 3px solid var(--orange);
	outline-offset: 2px;
	border-radius: 3px;
}


/*---------------------------------------------------
>> Button Styles
---------------------------------------------------*/
.btn {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: var(--space-2xs);
	font-family: var(--font-head);
	font-weight: 700;
	font-size: .975rem;
	padding: var(--space-xs) var(--space-lg);
	border-radius: var(--radius);
	border: 2px solid transparent;
	text-decoration: none;
	cursor: pointer;
	transition: background-color .15s, color .15s, border-color .15s, transform .15s;
	line-height: 1.2;
}
.btn:hover {
	transform: translateY(-1px);
}
/* Amber fill + near-black ink = 8.34:1. White-on-amber (2.09:1) fails AA. */
.btn-primary {
	background: var(--orange);
	color: #1A1A1A;
}
.btn-primary:hover {
	background: var(--orange-hover);
	color: #1A1A1A;
}
.btn-ghost {
	background: transparent;
	color: #fff;
	border-color: rgba(255,255,255,.65);
}
.btn-ghost:hover {
	background: rgba(255,255,255,.12);
	border-color: #fff;
}
.btn-lg {
	font-size: 1.05rem;
	padding: var(--space-sm) var(--space-2xl);
}
.btn-block {
	width: 100%;
}


/*---------------------------------------------------
>> Navigation and Header Styles
---------------------------------------------------*/
.site-header {
	position: sticky;
	top: 0;
	z-index: 100;
	background: rgba(255,255,255,.97);
	backdrop-filter: saturate(1.4) blur(8px);
	border-bottom: 1px solid var(--line);
}
.header-inner {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: var(--space-sm);
	padding: var(--space-xs) 0;
}
.brand {
	display: flex;
	align-items: center;
	gap: var(--space-xs);
	text-decoration: none;
	color: var(--ink);
}
.brand-mark {
	width: 60px;
	height: auto;
	border-radius: 4px;
}
.brand-text {
	display: flex;
	flex-direction: column;
}
.brand-name {
	font-family: var(--font-head);
	font-weight: 800;
	font-size: 1rem;
	letter-spacing: -.01em;
	line-height: 1.15;
}
.brand-tag {
	font-size: .72rem;
	letter-spacing: .12em;
	text-transform: uppercase;
	color: var(--ink-faint);
}
.primary-nav {
	display: flex;
	align-items: center;
	gap: var(--space-lg);
}
.primary-nav ul {
	display: flex;
	gap: var(--space-lg);
	list-style: none;
}
.primary-nav a {
	font-family: var(--font-head);
	font-weight: 500;
	font-size: .95rem;
	color: var(--ink-soft);
	text-decoration: none;
	padding: var(--space-3xs) 0;
	border-bottom: 2px solid transparent;
}
.primary-nav a:hover {
	color: var(--blue);
}
.primary-nav a[aria-current="page"] {
	color: var(--blue);
	border-bottom-color: var(--orange);
}
/* Matches .btn-primary — amber fill, near-black ink (8.34:1).
   Scoped to .primary-nav so it outranks the `.primary-nav a` link rule,
   which would otherwise win on specificity and flatten the padding/colour. */
.primary-nav .btn-phone {
	background: var(--orange);
	color: #1A1A1A;
	padding: var(--space-xs) var(--space-lg);
	font-size: .95rem;
	border-radius: var(--radius);
	border-bottom: none;
}
.primary-nav .btn-phone:hover {
	background: var(--orange-hover);
	color: #1A1A1A;
}
/* Services dropdown.
   Opens on hover and on :focus-within, so it works for keyboard tabbing as
   well as the mouse without any JS behind it. */
.primary-nav .menu-item-has-children {
	position: relative;
}
.primary-nav .menu-item-has-children > a::after {
	content: "";
	display: inline-block;
	width: .38em;
	height: .38em;
	margin-left: .45em;
	vertical-align: .14em;
	border-right: 2px solid currentColor;
	border-bottom: 2px solid currentColor;
	transform: rotate(45deg);
}
.primary-nav .sub-menu {
	display: none;
	position: absolute;
	top: 100%;
	left: 0;
	z-index: 10;
	flex-direction: column;
	gap: 0;
	min-width: 17.5rem;
	margin-top: var(--space-xs);
	padding: var(--space-2xs) 0;
	background: #fff;
	border: 1px solid var(--line);
	border-radius: var(--radius);
	box-shadow: var(--shadow-lg);
}
/* Bridges the margin-top gap so travelling from the parent down to the panel
   does not cross dead space and close the menu. */
.primary-nav .sub-menu::before {
	content: "";
	position: absolute;
	left: 0;
	right: 0;
	top: calc(var(--space-xs) * -1);
	height: var(--space-xs);
}
/* Wide layout only. Left unscoped this outranked the stacked collapse
   below: media queries add no specificity, and :hover made this (0,4,0)
   against (0,3,0) for .primary-nav.js-nav .sub-menu, so on touch a tap
   fired hover and opened the panel regardless of the disclosure button.
   Scoped here, the stacked layout is click-only. */
@media (min-width: 821px) {
	.primary-nav .menu-item-has-children:hover > .sub-menu,
	.primary-nav .menu-item-has-children:focus-within > .sub-menu {
		display: flex;
	}
}
.primary-nav .sub-menu a {
	display: block;
	padding: var(--space-2xs) var(--space-md);
	border-bottom: none;
	white-space: nowrap;
}
.primary-nav .sub-menu a:hover {
	background: var(--bg-alt);
	color: var(--blue);
}
.primary-nav .sub-menu a[aria-current="page"] {
	color: var(--blue);
	background: var(--bg-alt);
	border-bottom-color: transparent;
}
/* Injected by nav.js; the wide layout opens the dropdown on hover instead. */
.submenu-toggle {
	display: none;
}

.nav-toggle {
	display: none;
	background: none;
	border: 0;
	padding: var(--space-2xs);
	cursor: pointer;
}
.nav-toggle-bars, .nav-toggle-bars::before, .nav-toggle-bars::after {
	display: block;
	width: 24px;
	height: 2px;
	background: var(--ink);
	border-radius: 2px;
	content: "";
}
.nav-toggle-bars::before {
	transform: translateY(-7px);
}
.nav-toggle-bars::after {
	transform: translateY(5px);
}


/* Stacked navigation. Kept with the nav rather than in a shared media
   block: these override the rules directly above, and at equal
   specificity source order is what decides. */
@media (max-width: 820px) {

	.nav-toggle {
		display: block;
	}
	.primary-nav {
		display: none;
		position: absolute;
		left: 0;
		right: 0;
		top: 100%;
		flex-direction: column;
		align-items: stretch;
		gap: 0;
		background: #fff;
		border-bottom: 1px solid var(--line);
		padding: .5rem var(--gut) 1.25rem;
		box-shadow: var(--shadow);
	}
	.primary-nav.is-open {
		display: flex;
	}
	.primary-nav ul {
		flex-direction: column;
		gap: 0;
	}
	.primary-nav ul a {
		display: block;
		padding: var(--space-xs) 0;
		border-bottom: 1px solid var(--line);
	}
	.primary-nav a[aria-current="page"] {
		border-bottom-color: var(--line);
	}
	/* Stacked nav: the dropdown becomes an indented inline list, always open.
	   Touch has no hover, and a disclosure toggle would need JS. */
	.primary-nav .sub-menu {
		display: flex;
		position: static;
		min-width: 0;
		margin: 0;
		padding: 0 0 0 var(--space-md);
		background: none;
		border: none;
		border-radius: 0;
		box-shadow: none;
	}
	.primary-nav .sub-menu::before {
		display: none;
	}
	.primary-nav .sub-menu a {
		padding: var(--space-xs) 0;
		border-bottom: 1px solid var(--line);
		white-space: normal;
		font-size: .9rem;
	}
	.primary-nav .menu-item-has-children > a::after {
		display: none;
	}
	/* Disclosure. Scoped to .js-nav, which nav.js adds - with JS off the
	   submenu above stays open rather than hiding behind a dead button. */
	.primary-nav .menu-item-has-children {
		display: flex;
		flex-wrap: wrap;
		align-items: stretch;
	}
	.primary-nav .menu-item-has-children > a {
		flex: 1;
	}
	.primary-nav .menu-item-has-children > .sub-menu {
		flex: 0 0 100%;
	}
	.submenu-toggle {
		display: flex;
		align-items: center;
		justify-content: center;
		width: 2.75rem;
		padding: 0;
		background: none;
		border: 0;
		/* Continues the link's rule across the button so the row reads as one. */
		border-bottom: 1px solid var(--line);
		color: var(--ink-soft);
		cursor: pointer;
	}
	.submenu-toggle::before {
		content: "";
		width: .45rem;
		height: .45rem;
		margin-top: -.22rem;
		border-right: 2px solid currentColor;
		border-bottom: 2px solid currentColor;
		transform: rotate(45deg);
		transition: transform .15s ease;
	}
	.menu-item-has-children.is-open > .submenu-toggle::before {
		margin-top: .22rem;
		transform: rotate(-135deg);
	}
	.primary-nav.js-nav .sub-menu {
		display: none;
	}
	.primary-nav.js-nav .menu-item-has-children.is-open > .sub-menu {
		display: flex;
	}
	.btn-phone {
		margin-top: var(--space-sm);
	}
	.header-inner {
		position: relative;
	}
}


/*---------------------------------------------------
>> Hero Styles
---------------------------------------------------*/
.hero, .page-hero {
	position: relative;
	isolation: isolate;
	background: var(--blue-deep);
	overflow: hidden;
}
.hero-bg {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	object-fit: cover;
	/* Framing is per-hero because the two use different photos - see the
	   .hero .hero-bg and .page-hero .hero-bg overrides below. */
	object-position: 68% 32%;
	z-index: -2;
	opacity: .85;
}
.hero::after, .page-hero::after {
	content: "";
	position: absolute;
	inset: 0;
	z-index: -1;
	/* Shared fallback; each hero overrides with a scrim fitted to its own
	   photo's measured luminance. */
	background:
		linear-gradient(100deg, rgba(18,19,79,.88) 0%, rgba(18,19,79,.70) 55%, rgba(18,19,79,.60) 100%),
		linear-gradient(to top, rgba(18,19,79,.55), transparent 58%);
}
.hero-inner {
	padding: clamp(4rem, 11vw, 8rem) 0 clamp(5.5rem, 12vw, 9rem);
	/* No max-width: .wrap already caps at --wrap, so the hero copy starts on
	   the same left edge as the trust bar and every band below. */
	color: #fff;
}
.eyebrow {
	font-family: var(--font-head);
	font-size: .78rem;
	font-weight: 600;
	letter-spacing: .16em;
	text-transform: uppercase;
	color: var(--orange);
	margin-bottom: var(--space-sm);
}
.hero h1, .page-hero h1 {
	color: #fff;
	margin-bottom: .5em;
	text-wrap: balance;
}
.hero h1 .hl, .page-hero h1 .hl {
	color: var(--orange);
}
.hero-sub {
	font-size: clamp(1.05rem, 2vw, 1.25rem);
	color: rgba(255,255,255,.9);
	max-width: 34rem;
	margin-bottom: var(--space-2xl);
}
.hero-actions {
	display: flex;
	flex-wrap: wrap;
	gap: var(--space-sm);
}
/* Interior-page hero — shorter than the homepage's, no CTA row. */
.page-hero-inner {
	padding: clamp(2.5rem, 6vw, 4.5rem) 0 clamp(4rem, 9vw, 6.5rem);
	/* No max-width, matching .hero-inner: .wrap already caps at --wrap so the
	   crumbs, h1 and sub start on the same left edge as the content below. */
	color: #fff;
}
.page-hero-inner .hero-sub {
	margin-bottom: 2rem;
}
.crumbs {
	margin-bottom: var(--space-md);
}
.crumbs ol {
	list-style: none;
	display: flex;
	flex-wrap: wrap;
	gap: var(--space-2xs);
	font-size: .85rem;
	padding-left: 0;
}
.crumbs li + li::before {
	content: "/";
	margin-right: var(--space-2xs);
	color: rgba(255,255,255,.45);
}
.crumbs a {
	color: rgba(255,255,255,.8);
	text-decoration: none;
}
.crumbs a:hover {
	color: #fff;
	text-decoration: underline;
	text-underline-offset: 3px;
}
.crumbs [aria-current="page"] {
	color: var(--orange);
}
.mt-lg {
	margin-top: var(--space-xl);
}
/* Home hero - source is the portrait meter-bank shot (attachment 157).
   Measured luminance is bright and fairly even across the frame (mean 99-160,
   windows peaking near 250), so the scrim stays heavy over the copy in the
   left ~43% and eases off right without letting the windows burn out. At
   desktop widths only ~384px of the photo's 1200 is visible, so 78% centres
   that band on the meter bank (source rows 636-1021) instead of the windows. */
.hero .hero-bg {
	object-position: 50% 78%;
}
.hero::after {
	background:
		linear-gradient(100deg,
			rgba(18,19,79,.88) 0%,
			rgba(18,19,79,.82) 35%,
			rgba(18,19,79,.66) 55%,
			rgba(18,19,79,.58) 80%,
			rgba(18,19,79,.62) 100%),
		linear-gradient(to top, rgba(18,19,79,.55), transparent 58%);
}

/* Interior heroes - source is hero1.jpg (landscape, technician right-of-centre),
   a different profile entirely: bright cream wall at 8-25% and again at 92%,
   dark panel through the middle. So this dips harder mid-frame to reveal the
   hoodie and logo, then closes again to stop the right-hand wall blowing out.
   68% 32% keeps the technician in frame. */
.page-hero .hero-bg {
	object-position: 68% 32%;
}
.page-hero::after {
	background:
		/* Copy scrim. Sits only behind the text and fades out by ~72%, so the
		   headline and crumbs keep their contrast without darkening the half
		   of the frame the photo actually shows. Interior heroes carry several
		   different photos, some bright (siding, sky), so this has to hold up
		   without being tuned to any one of them. */
		linear-gradient(90deg,
			rgba(18,19,79,.66) 0%,
			rgba(18,19,79,.58) 38%,
			rgba(18,19,79,.16) 62%,
			transparent 72%),
		/* Overall wash - much lighter than before, this is what lets the photo
		   read - plus a floor under the highlights so nothing glares. */
		linear-gradient(100deg,
			rgba(18,19,79,.34) 0%,
			rgba(18,19,79,.26) 60%,
			rgba(18,19,79,.40) 100%),
		linear-gradient(to top, rgba(18,19,79,.44), transparent 58%);
}


/* Restrained version of the concept's angled cut */
.hero-cut, .page-hero .hero-cut {
	position: absolute;
	left: 0;
	right: 0;
	bottom: -1px;
	height: clamp(40px, 5vw, 78px);
	background: var(--bg);
	clip-path: polygon(0 100%, 100% 0, 100% 100%);
	/* box-shadow would be clipped away with the rest of the box; drop-shadow
	   is applied after the clip, so it traces the diagonal edge. */
	filter:
		drop-shadow(0 -1px 1px rgba(4,5,24,.55))
		drop-shadow(0 -10px 20px rgba(4,5,24,.45));
}


@media (max-width: 820px) {
	/* The desktop scrim is shaped around copy sitting in the left 43% of the
	   frame. Once the hero goes full-width the text crosses the light part of
	   that ramp, so swap to an even scrim: still shows the photo, but no part
	   of the headline lands on a bright patch. */
	.hero::after, .page-hero::after {
		background: linear-gradient(180deg, rgba(18,19,79,.55) 0%, rgba(18,19,79,.66) 100%);
	}
}


@media (max-width: 560px) {
	.hero-actions .btn {
		width: 100%;
	}
}


/*---------------------------------------------------
>> Trust Bar Styles
---------------------------------------------------*/
/* Hugs the hero cut above; the next band supplies the gap below. */
.trustbar {
	background: var(--bg);
	padding: var(--space-hug) 0 0;
}
/*
 * Overlap the hero.
 *
 * Scoped to a trust bar that DIRECTLY follows a hero, so the negative margin
 * can never yank the bar into whatever happens to sit above it somewhere else.
 *
 * z-index is not optional here: .hero-cut carries a drop-shadow filter, which
 * creates a stacking context, so without one the card renders underneath the
 * diagonal instead of on top of it.
 *
 * The background has to go transparent too — it is --bg, which would paint a
 * solid block over the hero in the overlap area.
 */
.hero + .trustbar,
.page-hero + .trustbar {
	position: relative;
	z-index: 2;
	background: transparent;
	padding-top: 0;
	margin-top: calc(var(--trust-overlap) * -1);
}
.trust-grid {
	display: grid;
	grid-template-columns: repeat(4, 1fr);
	gap: 1px;
	/* Dividers are a darker gold rather than --line, which read as grey
	   scratches once the cells went gold. */
	background: var(--orange-hover);
	border: 1px solid var(--orange-hover);
	border-radius: var(--radius);
	overflow: hidden;
	box-shadow: var(--shadow);
}
.trust-item {
	background: var(--orange);
	padding: var(--space-lg) var(--space-md);
	text-align: center;
}
.trust-k {
	display: block;
	font-family: var(--font-head);
	font-weight: 800;
	font-size: 1.55rem;
	color: var(--ink-soft);
	margin-bottom:0;
}
.trust-v {
	display: block;
	font-size: .9rem;
	/* CONTRAST: white on --orange is 2.09:1 - the exact figure :root warns
	   about ("fills / icons only ... never text"). At .9rem this is not large
	   text, so bolder does not exempt it; AA wants 4.5:1. --ink is 8.7:1 and
	   --ink-soft 4.21:1. Left as chosen - flagged, not overridden. */
	color: white;
	font-weight: bolder;
	margin-bottom: 10px;
}


@media (max-width: 980px) {
	.trust-grid {
		grid-template-columns: repeat(2, 1fr);
	}
}


/* Two columns all the way down rather than collapsing to one: a single stack
   ran 496px tall on a 375px screen, which is half a phone screen of trust
   badges before any real content. 2x2 is 240px. */
@media (max-width: 560px) {
	/* minmax(0, ...) not plain 1fr: 1fr is minmax(auto, 1fr), so a long
	   unbreakable word ("Estimates", "Authorized") widens its own column and
	   throws the divider off centre — measured 158.9px vs 173.1px. */
	.trust-grid {
		grid-template-columns: repeat(2, minmax(0, 1fr));
	}
	/* Vertical padding only. Horizontal stays --space-md: dropping it to
	   --space-sm saved nothing (measured identical height) and only tightens
	   the wrap on "EcoFlow & Anker Dealer". */
	.trust-item {
		padding-block: var(--space-sm);
	}
}


/*---------------------------------------------------
>> Shared Content Styles
---------------------------------------------------*/
.bolt {
	display: inline-flex;
	color: var(--orange);
	margin-bottom: var(--space-xs);
}
.grid-2 {
	display: grid;
	gap: clamp(2rem, 5vw, 4rem);
	align-items: start;
}
.grid-2-estimate, .grid-2-even {
	grid-template-columns: 1fr 1fr;
}
.lead-call {
	font-weight: 600;
}
.lead-call a {
	color: var(--orange-ink);
	text-underline-offset: 3px;
}
.checklist {
	list-style: none;
	display: grid;
	gap: var(--space-2xs);
	margin-top: var(--space-lg);
}
.checklist li {
	position: relative;
	padding-left: var(--space-2xl);
	color: var(--ink-soft);
}
.checklist li::before {
	content: "";
	position: absolute;
	left: 0;
	top: .45em;
	width: 1.15rem;
	height: 1.15rem;
	border-radius: 50%;
	background: var(--orange);
	-webkit-mask: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M9 16.2 4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4z'/%3E%3C/svg%3E") center/1.15rem no-repeat;
	mask: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M9 16.2 4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4z'/%3E%3C/svg%3E") center/1.15rem no-repeat;
}
.link-arrow {
	font-family: var(--font-head);
	font-weight: 700;
	color: var(--blue);
	text-decoration: none;
}
.link-arrow::after {
	content: " →";
}
.link-arrow:hover {
	text-decoration: underline;
	text-underline-offset: 3px;
}


@media (max-width: 980px) {
	.grid-2-estimate, .grid-2-even {
		grid-template-columns: 1fr;
	}
}


/*---------------------------------------------------
>> Estimate Form Styles
---------------------------------------------------*/
.form-card {
	background: var(--bg-alt);
	border: 1px solid var(--line);
	border-radius: var(--radius);
	padding: clamp(1.5rem, 3vw, 2.25rem);
	box-shadow: var(--shadow);
}
.form-title {
	font-size: .8rem;
	font-weight: 700;
	letter-spacing: .14em;
	text-transform: uppercase;
	color: var(--blue);
	margin-bottom: var(--space-lg);
	padding-bottom: var(--space-sm);
	border-bottom: 2px solid var(--orange);
}
/* Name / phone / email / service sit two-up; message stays full width. */
.field-grid {
	display: grid;
	grid-template-columns: 1fr 1fr;
	column-gap: var(--space-sm);
}
.field {
	margin-bottom: var(--space-sm);
	min-width: 0;
}
.field label {
	display: block;
	font-family: var(--font-head);
	font-weight: 600;
	font-size: .85rem;
	color: var(--ink);
	margin-bottom: var(--space-3xs);
}
.field input, .field select, .field textarea {
	width: 100%;
	font: inherit;
	font-size: 1rem;
	color: var(--ink);
	background: #fff;
	border: 1.5px solid #CDD2DC;
	border-radius: 8px;
	padding: var(--space-xs) var(--space-xs);
	transition: border-color .15s, box-shadow .15s;
}
.field textarea {
	resize: vertical;
	/* CF7 emits rows="10" (290px), which min-height cannot pull back. An
	   explicit height overrides the attribute; resize still lets it grow. */
	min-height: 6.5rem;
	height: 7rem;
}
.field input:hover, .field select:hover, .field textarea:hover {
	border-color: #A9B1C0;
}
.field input:focus, .field select:focus, .field textarea:focus {
	border-color: var(--blue);
	box-shadow: 0 0 0 3px rgba(34,35,158,.14);
	outline: none;
}
.captcha-slot {
	display: flex;
	align-items: center;
	justify-content: center;
	min-height: 65px;
	border: 1px dashed #C3C9D4;
	border-radius: 8px;
	background: #fff;
	color: var(--ink-faint);
	font-size: .85rem;
	margin-bottom: var(--space-sm);
}
.form-note {
	font-size: .85rem;
	color: var(--ink-faint);
	margin: var(--space-sm) 0 0;
	text-align: center;
}


@media (max-width: 560px) {
	.field-grid {
		grid-template-columns: 1fr;
	}
}


/*---------------------------------------------------
>> Split Panel Styles
---------------------------------------------------*/
.split {
	display: grid;
	grid-template-columns: 1fr 1fr;
	background: var(--blue);
}
.split-media {
	position: relative;
	min-height: 420px;
}
/* image1.jpg is portrait (900x1200) — bias the crop upward so the service
   board and conduit runs stay in frame rather than the foreground dirt. */
.split-media img {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	object-fit: cover;
	object-position: center 38%;
}
.split-panel {
	display: flex;
	align-items: center;
	padding: clamp(2.5rem, 5vw, 4.5rem) 0;
}
.split-panel-inner {
	color: #fff;
	max-width: 34rem;
	/* Margin, not padding. The right inset exists to line the panel copy up
	   with the site's content grid - the panel is full-bleed to the right, so
	   it has to pull in by half the leftover viewport. As padding under
	   border-box that inset came out of max-width instead of outside it, so
	   the text column shrank as the viewport grew: 454px at 1280, 294px at
	   1600, 134px at 1920, and collapsed entirely past ~2200. As margin the
	   inset sits outside the box, so max-width governs the text alone and the
	   column stays a constant 34rem at every width. */
	margin-inline: var(--gut) max(var(--gut), calc((100vw - var(--wrap)) / 2));
}
.split-panel h2 {
	color: #fff;
}
.split-panel p {
	color: rgba(255,255,255,.88);
}
/* -- Scoped to .split-panel so it outranks `.split-panel p` (0,1,1) on
   specificity rather than needing !important. -- */
.split-panel .dealer-flag {
	font-weight: 600;
	color: #fff;
	border-left: 3px solid var(--orange);
	padding-left: var(--space-sm);
	margin-bottom: var(--space-md);
}


@media (max-width: 980px) {
	.split {
		grid-template-columns: 1fr;
	}
	/* Portrait source — needs more height once stacked or the crop gets severe. */
	.split-media {
		min-height: 340px;
	}
	.split-panel-inner {
		margin-inline: var(--gut);
		max-width: none;
	}
}


@media (max-width: 820px) {
	/* Opt-in per section (checkbox on the Split element). The split has already
	   stacked by this width, and the portrait sources need 340px of height once
	   stacked, which pushes the panel a long way down a phone screen. */
	.split.split-hide-media-mobile .split-media {
		display: none;
	}
}


/*---------------------------------------------------
>> Card Grid and Service Area Styles
---------------------------------------------------*/
.services {
	background: white;
}
.service-grid {
	list-style: none;
	display: grid;
	gap: var(--space-md);
	margin-top: var(--space-3xl);
	grid-template-columns: repeat(auto-fit, minmax(255px, 1fr));
}
.service {
	background: #fff;
	border: 1px solid var(--line);
	border-top: 3px solid var(--orange);
	border-radius: var(--radius);
	padding: var(--space-lg) var(--space-lg);
	transition: box-shadow .18s, transform .18s;
}
.service:hover {
	box-shadow: var(--shadow-lg);
	transform: translateY(-3px);
}
.service-thumb {
	display: block;
	width: calc(100% + var(--space-lg) * 2);
	max-width: none;   /* the global img{max-width:100%} would clamp the bleed */
	margin: calc(var(--space-lg) * -1) calc(var(--space-lg) * -1) var(--space-md);
	aspect-ratio: 4 / 3;
	object-fit: cover;
	border-radius: calc(var(--radius) - 1px) calc(var(--radius) - 1px) 0 0;
	background: var(--line);
}
.service h3 {
	margin-bottom: var(--space-2xs);
}
.service h3 a {
	color: var(--orange-ink);
	text-decoration: none;
}
.service h3 a:hover {
	text-decoration: underline;
	text-underline-offset: 3px;
}
.service p {
	color: var(--ink-soft);
	font-size: .97rem;
	margin: 0;
}
.services-more {
	margin-top: var(--space-2xl);
}
/* ---------- Areas ----------
   Photo band (img2.jpg). The source is a bright interior, so it carries a
   heavy navy scrim and the type flips to white to stay legible. */
.areas {
	position: relative;
	isolation: isolate;
	background: var(--blue-deep) url("../img/img2.jpg") center 42% / cover no-repeat;
	color: #fff;
}
.areas::before {
	content: "";
	position: absolute;
	inset: 0;
	z-index: -1;
	background: linear-gradient(100deg, rgba(18,19,79,.93) 0%, rgba(18,19,79,.86) 55%, rgba(18,19,79,.72) 100%);
}
.areas h2 {
	color: #fff;
}
.areas .section-intro {
	color: rgba(255,255,255,.88);
}
.areas .link-arrow {
	color: var(--orange);
}
.area-list {
	list-style: none;
	display: flex;
	flex-wrap: wrap;
	gap: var(--space-xs);
	margin: var(--space-xl) 0 0;
}
.area-list a {
	display: inline-block;
	padding: var(--space-2xs) var(--space-md);
	border: 1.5px solid rgba(255,255,255,.5);
	border-radius: 999px;
	background: rgba(255,255,255,.08);
	color: #fff;
	font-family: var(--font-head);
	font-weight: 600;
	font-size: .95rem;
	text-decoration: none;
	transition: background-color .15s, border-color .15s, color .15s;
}
.area-list a:hover {
	border-color: var(--orange);
	background: var(--orange);
	color: #1A1A1A;
}


/*---------------------------------------------------
>> CTA Band Styles
---------------------------------------------------*/
.cta-band {
	background: var(--blue-deep);
	color: #fff;
	padding: var(--space-band) 0;
}
.cta-inner {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: var(--space-2xl);
	flex-wrap: wrap;
}
.cta-band h2 {
	color: #fff;
	margin-bottom: .3em;
}
.cta-band p {
	color: rgba(255,255,255,.85);
	margin: 0;
}


@media (max-width: 560px) {
	.cta-inner .btn {
		width: 100%;
	}
}


/*---------------------------------------------------
>> Footer Styles
---------------------------------------------------*/
.site-footer {
	background: #0E0F3A;
	color: rgba(255,255,255,.78);
	padding: var(--space-band) 0 2rem;
	font-size: .95rem;
}
.footer-grid {
	display: grid;
	gap: var(--space-3xl);
	grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
}
.site-footer h2 {
	font-size: .82rem;
	letter-spacing: .14em;
	text-transform: uppercase;
	color: var(--orange);
	margin-bottom: var(--space-sm);
}
.site-footer h2.mt {
	margin-top: var(--space-2xl);
}
.footer-list {
	list-style: none;
	display: grid;
	gap: var(--space-2xs);
}
.footer-list.inline {
	display: flex;
	gap: var(--space-md);
}
.site-footer a {
	color: #fff;
	text-decoration: none;
}
.site-footer a:hover {
	text-decoration: underline;
	text-underline-offset: 3px;
}
.footer-p {
	color: rgba(255,255,255,.78);
}
.footer-bottom {
	display: flex;
	justify-content: space-between;
	flex-wrap: wrap;
	gap: var(--space-xs);
	margin-top: var(--space-4xl);
	padding-top: var(--space-lg);
	border-top: 1px solid rgba(255,255,255,.15);
	font-size: .85rem;
	color: rgba(255,255,255,.6);
}
.footer-bottom p {
	margin: 0;
}


/* Footer widget areas.
   The three columns are widgetised, so core widget markup has to land on the
   same styling the hand-built columns had. Widget titles come through as <h2>
   via before_title, so .site-footer h2 already covers them; these rules cover
   the Navigation Menu widget's <ul class="menu"> and the stacking of multiple
   widgets in one column, which h2.mt used to handle. */
.footer-col .footer-widget + .footer-widget {
	margin-top: var(--space-2xl);
}
.site-footer .menu {
	list-style: none;
	display: grid;
	gap: var(--space-2xs);
	padding-left: 0;
	margin: 0;
}
.site-footer .footer-widget p:last-child {
	margin-bottom: 0;
}


/*---------------------------------------------------
>> Composed Section Styles
>> Grid columns and split image side for the
>> WPBakery elements.
---------------------------------------------------*/
.service-grid.cols-2 {
	grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
}
.service-grid.cols-3 {
	grid-template-columns: repeat(auto-fit, minmax(230px, 1fr));
}
.service-grid.cols-4 {
	grid-template-columns: repeat(auto-fit, minmax(210px, 1fr));
}
.split.split-media-right .split-media {
	order: 2;
}
.split.split-media-right .split-panel {
	order: 1;
}
/* Inline area chips inside a light section */
.area-list-inline li, .section .area-list li {
	border-color: var(--line);
}
/* Amber fill to match .btn-primary. These were previously color:white on a
   light section background — the labels rendered invisible, which read as
   empty outlined pills. #1A1A1A on --orange is 8.34:1, same as the buttons.
   Excludes .areas: that band is dark (--blue-deep + photo) and keeps the
   white ghost pills the design intends. .areas carries BOTH classes, so an
   unscoped `.section .area-list a` reaches it. */
.section:not(.areas) .area-list a {
	background: var(--orange);
	border-color: var(--orange);
	color: #1A1A1A;
}
.section:not(.areas) .area-list a:hover {
	background: var(--orange-hover);
	border-color: var(--orange-hover);
	color: #1A1A1A;
}


/*---------------------------------------------------
>> FAQ Accordion Styles
---------------------------------------------------*/
.accordion {
	display: grid;
	gap: var(--space-2xs);
	margin-top: var(--space-xl);
}
.accordion-item {
	border: 1px solid var(--line);
	border-radius: var(--radius);
	background: var(--bg);
	overflow: hidden;
}
.accordion-item.is-open {
	border-color: var(--orange);
	box-shadow: var(--shadow);
}
.accordion-heading {
	margin: 0;
	font-size: 1rem;
}
.accordion-trigger {
	width: 100%;
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: var(--space-sm);
	background: none;
	border: 0;
	cursor: pointer;
	text-align: left;
	font-family: var(--font-head);
	font-weight: 700;
	font-size: 1.05rem;
	color: var(--ink);
	padding: var(--space-sm) var(--space-md);
	line-height: 1.35;
}
.accordion-trigger:hover {
	color: var(--blue);
}
.accordion-trigger:focus-visible {
	outline: 3px solid var(--orange);
	outline-offset: -3px;
}
.accordion-icon {
	position: relative;
	flex: 0 0 18px;
	height: 18px;
}
.accordion-icon::before, .accordion-icon::after {
	content: "";
	position: absolute;
	left: 0;
	top: 8px;
	width: 18px;
	height: 2px;
	background: var(--orange);
	transition: transform .2s ease;
}
.accordion-icon::after {
	transform: rotate(90deg);
}
.accordion-item.is-open .accordion-icon::after {
	transform: rotate(0deg);
}
.accordion-panel-inner {
	padding: 0 var(--space-md) var(--space-sm);
	color: var(--ink-soft);
}
.accordion-panel-inner p {
	margin: 0;
}
@media (prefers-reduced-motion: reduce) {
	.accordion-icon::before, .accordion-icon::after {
		transition: none;
	}
}


/*---------------------------------------------------
>> Service Copy
>> Typography for the 16 service pages.
---------------------------------------------------*/
/* These pages are ~500 words of genuinely distinct copy each. The note at the
   top of single-service.php warns against growing shared furniture around
   them, so this is rhythm and measure only - nothing here adds repeated
   content across the set. The real problem was that the copy ran the full
   1180px wrap: roughly 140 characters a line, about twice a comfortable
   measure. */
/* Copy left, jump list right. The copy keeps the page's left edge so it still
   lines up with the hero and crumbs above it. */
.service-layout.has-toc {
	display: grid;
	grid-template-columns: minmax(0, 68ch) minmax(0, 1fr);
	gap: var(--space-4xl);
	align-items: start;
}
.service-copy {
	max-width: 68ch;
}
.service-toc {
	position: sticky;
	top: calc(var(--space-4xl) + 3.5rem);
	padding: var(--space-lg);
	background: var(--bg-alt);
	border-radius: var(--radius);
	border: 1px solid var(--line);
}
.service-toc-title {
	font-family: var(--font-head);
	/* Sentence case, so it can carry the service name without shouting.
	   The eyebrow treatment it used to share (.78rem, uppercase, wide
	   tracking) is for two- or three-word labels, not a full title.
	
	   Fluid rather than fixed. At 1.55rem flat, 13 of the 16 titles sat on
	   one line on desktop but only 1 of 16 did once the column narrowed to
	   285px on a phone. Easing to 1.15rem there puts most back on one line
	   and keeps the label just under the copy's h3, so a sidebar nav label
	   stops outranking the content headings it links past. 1.9vw so the
	   1.55rem ceiling is actually reached by ~1305px; at 1.6vw it would not
	   have hit it until 1550px and desktop would have quietly sat smaller. */
	font-size: clamp(1.15rem, 1.9vw, 1.55rem);
	font-weight: 600;
	letter-spacing: 0;
	line-height: 1.35;
	color: var(--orange-ink);
	margin-bottom: var(--space-sm);
}
.service-toc ul {
	list-style: none;
	display: grid;
	gap: var(--space-2xs);
	padding-left: 0;
	margin: 0;
}
.service-toc a {
	color: var(--ink-soft);
	text-decoration: none;
	font-size: .92rem;
	line-height: 1.4;
	display: block;
}
.service-toc a:hover {
	color: var(--blue);
	text-decoration: underline;
	text-underline-offset: 3px;
}
/* Anchor targets clear the sticky header when jumped to. */
.service-copy h2[id],
section[id] {
	scroll-margin-top: 5.5rem;
}
/* Placed after the layout rules above, not in the 980px block earlier in
   the file: equal specificity, so source order decides and from up there
   it lost, leaving a two-column grid and horizontal overflow on phones. */
@media (max-width: 980px) {
	.service-layout.has-toc {
		grid-template-columns: 1fr;
		gap: var(--space-2xl);
	}
	.service-toc {
		position: static;
	}
}
/* Opening paragraph reads as a standfirst. */
.service-copy > p:first-of-type {
	font-size: 1.2rem;
	line-height: 1.6;
	color: var(--ink-soft);
}
.service-copy h2 {
	margin-top: var(--space-4xl);
	margin-bottom: var(--space-sm);
	padding-top: var(--space-lg);
	border-top: 2px solid var(--line);
}
.service-copy > h2:first-child {
	margin-top: 0;
	padding-top: 0;
	border-top: 0;
}
.service-copy h3 {
	margin-top: var(--space-2xl);
	margin-bottom: var(--space-2xs);
	font-family: var(--font-head);
	color: var(--blue);
}
/* Lists pick up the same amber tick used by .checklist, so the service pages
   read as part of the same system rather than as raw editor output. The
   margin-bottom also fixes the last bullet colliding with the next paragraph. */
.service-copy ul {
	list-style: none;
	display: grid;
	gap: var(--space-2xs);
	padding-left: 0;
	margin: var(--space-lg) 0 var(--space-2xl);
}
.service-copy ul li {
	position: relative;
	padding-left: var(--space-2xl);
	color: var(--ink-soft);
}
.service-copy ul li::before {
	content: "";
	position: absolute;
	left: 0;
	top: .42em;
	width: 1.1rem;
	height: 1.1rem;
	background: var(--orange);
	-webkit-mask: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M9 16.2 4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4z'/%3E%3C/svg%3E") center/1.1rem no-repeat;
	mask: url("data:image/svg+xml;charset=utf-8,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M9 16.2 4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4z'/%3E%3C/svg%3E") center/1.1rem no-repeat;
}
.service-copy > *:last-child {
	margin-bottom: 0;
}


/*---------------------------------------------------
>> WPBakery Overrides
---------------------------------------------------*/
/* WPBakery pulls every .vc_row out by 15px a side, expecting an
   ancestor with matching padding to absorb it. This theme drops the
   row straight into .wpb-content-wrapper, which has none, so the
   right-hand 15px escaped as a horizontal scrollbar and a blank strip
   beside the body - on every page built inside a row, not just home.
   The ape_* sections set their own width via .wrap, so the gutter has
   nothing to compensate for. Zeroing it fixes all pages at once, with
   no per-row stretch setting to remember and no reliance on
   WPBakery's JS having run. */
.wpb-content-wrapper > .vc_row {
	margin-left: 0;
	margin-right: 0;
}


/*---------------------------------------------------
>> Gallery Styles
>> NextGEN output pulled onto the site grid.
---------------------------------------------------*/
.gallery-section .ngg-wrap {
	margin-top: var(--space-xl);
}
.gallery-section .ngg-galleryoverview {
	margin: 0;
}
.gallery-section .ngg-gallery-thumbnail-box {
	margin: 0;
}
.gallery-section .ngg-gallery-thumbnail {
	margin: 0;
	border: 0;
}
.gallery-section .ngg-gallery-thumbnail img {
	border: 0;
	margin: 0;
	width: 100%;
	height: 100%;
	object-fit: cover;
	border-radius: var(--radius);
	display: block;
	aspect-ratio: 4 / 3;
}
/* NextGEN ships `.ngg-galleryoverview { display: block !important }` in
   nextgen_basic_thumbnails.css, so this grid never applied however
   specific the selector was, and the plugin's centred inline-block
   thumbnails took over: 4 x 244px centred in the 1180px wrap, leaving
   the grid inset 102px from the copy above it. Matching !important is
   the only way to beat a plugin !important. NextGEN's text-align:center
   is left alone: grid places the items, and these thumbnails carry no
   captions for it to affect. */
.gallery-section .ngg-galleryoverview, .gallery-section .ngg-imagebrowser {
	display: grid !important;
	grid-template-columns: repeat(auto-fill, minmax(220px, 1fr));
	gap: var(--space-sm);
}
.gallery-section .ngg-gallery-thumbnail img:hover {
	opacity: .92;
}
/* Placed after the grid rule above, not in the 560px block further up the
   file: same specificity, so source order decides and the earlier block
   would lose. auto-fill/minmax(220px) drops to a single column below
   ~472px; pin it at two so phones still read as a gallery. */
@media (max-width: 560px) {
	.gallery-section .ngg-galleryoverview, .gallery-section .ngg-imagebrowser {
		grid-template-columns: repeat(2, 1fr);
	}
}

/*---------------------------------------------------
>> Logo Marquee Styles
>> Brand logos on a seamless loop (ape_logos).
---------------------------------------------------*/
.logos-section {
	background: var(--bg-alt);
	text-align: center;
}
.logos-section .section-intro {
	margin-inline: auto;
}
.logo-marquee {
	--logo-gap: var(--space-4xl);
	--logo-h: 56px;
	margin-top: var(--space-2xl);
}
/* Soft fade at both edges so logos slide in and out rather than being cut. */
.logo-viewport {
	overflow: hidden;
	-webkit-mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
	mask-image: linear-gradient(90deg, transparent, #000 8%, #000 92%, transparent);
}
.logo-track {
	display: flex;
	width: max-content;
	animation: logo-scroll var(--marquee-duration, 35s) linear infinite;
}
/* Pause while someone is looking at or tabbing through it. */
.logo-marquee:hover .logo-track,
.logo-marquee:focus-within .logo-track {
	animation-play-state: paused;
}
/* The trailing padding equals the gap, so every copy is exactly the same
   width and shifting by one copy lands the second where the first began. */
.logo-set {
	display: flex;
	align-items: center;
	gap: var(--logo-gap);
	padding-inline-end: var(--logo-gap);
	list-style: none;
}
.logo-item {
	flex: none;
	display: flex;
	align-items: center;
	justify-content: center;
	height: var(--logo-h);
}
.logo-item a {
	display: flex;
	align-items: center;
	height: 100%;
	border-radius: 4px;
}
/* Full colour on purpose: dealer badges (Lutron's especially) carry usage
   rules, and brand guides forbid greyscale or recoloured marks. */
/* --logo-w is set per image by the template (equal-area sizing); the scale
   shrinks the whole row on phones without re-deriving each width. */
.logo-item img {
	width: calc(var(--logo-w, 140px) * var(--logo-scale, 1));
	max-width: none;
	height: auto;
	max-height: var(--logo-h);
}
/* Stand-in until the dealer-portal artwork arrives. */
.logo-wordmark {
	font-family: var(--font-head);
	font-size: 1.35rem;
	font-weight: 700;
	letter-spacing: .02em;
	white-space: nowrap;
	color: var(--ink-soft);
}
.logos-cta {
	margin-top: var(--space-2xl);
}
@keyframes logo-scroll {
	to {
		transform: translateX(calc(-100% / var(--marquee-copies, 3)));
	}
}
@media (max-width: 560px) {
	.logo-marquee {
		--logo-gap: var(--space-2xl);
		--logo-h: 44px;
		--logo-scale: .8;
	}
}
/*
 * Motion off: a still, centred, wrapping row with the duplicate copy removed.
 * animation: none is required, not just tidy: the global reduced-motion rule
 * shrinks durations to .01ms, and an INFINITE animation at .01ms flickers.
 */
@media (prefers-reduced-motion: reduce) {
	.logo-viewport {
		-webkit-mask-image: none;
		mask-image: none;
	}
	.logo-track {
		width: auto;
		animation: none;
	}
	.logo-set {
		flex-wrap: wrap;
		justify-content: center;
		row-gap: var(--space-lg);
		padding-inline-end: 0;
		width: 100%;
	}
	.logo-set[aria-hidden="true"] {
		display: none;
	}
}


/*---------------------------------------------------
>> Estimate Button + Modal Styles
---------------------------------------------------*/
/* Sits under the sticky header (z 100) so the open mobile nav covers it. */
.estimate-fab {
	position: fixed;
	right: max(var(--space-sm), env(safe-area-inset-right));
	bottom: max(var(--space-sm), env(safe-area-inset-bottom));
	z-index: 90;
	display: inline-flex;
	align-items: center;
	gap: var(--space-2xs);
	padding: var(--space-xs) var(--space-md);
	border-radius: 999px;
	background: var(--orange);
	color: #1A1A1A;
	font-family: var(--font-head);
	font-weight: 700;
	font-size: .975rem;
	line-height: 1.2;
	text-decoration: none;
	box-shadow: var(--shadow-lg);
	transition: background-color .15s, transform .15s, opacity .2s, visibility .2s;
}
.estimate-fab:hover {
	background: var(--orange-hover);
	color: #1A1A1A;
	transform: translateY(-1px);
}
.estimate-fab:focus-visible {
	outline: 3px solid var(--blue);
	outline-offset: 3px;
}
.estimate-fab.is-hidden {
	opacity: 0;
	visibility: hidden;
	transform: translateY(8px);
}
.has-modal {
	overflow: hidden;
}
.estimate-modal {
	width: min(640px, calc(100% - 2 * var(--space-sm)));
	max-height: calc(100dvh - 2 * var(--space-sm));
	padding: 0;
	border: 0;
	border-radius: var(--radius);
	background: var(--bg-alt);
	color: var(--ink);
	box-shadow: var(--shadow-lg);
	overflow: auto;
	overscroll-behavior: contain;
}
.estimate-modal::backdrop {
	background: rgba(18,19,79,.6);
}
.estimate-modal-head {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: var(--space-sm);
	padding: var(--space-md) clamp(1.5rem, 3vw, 2.25rem) 0;
}
.estimate-modal-head h2 {
	margin: 0;
	font-size: 1.5rem;
}
.estimate-modal-close {
	display: inline-flex;
	padding: var(--space-2xs);
	border: 0;
	border-radius: 6px;
	background: transparent;
	color: var(--ink-soft);
	cursor: pointer;
}
.estimate-modal-close:hover {
	color: var(--ink);
	background: var(--line);
}
.estimate-modal .form-card {
	border: 0;
	box-shadow: none;
}
@media (max-width: 560px) {
	.estimate-modal .field-grid {
		grid-template-columns: 1fr;
	}
}
