/*
 * Blue Sky Plumbing: section archetypes
 *
 * Elementor supplies the structure and the content. This file supplies the
 * precision the design brief demands but which is fragile or impossible as
 * widget settings: the rotated vertical rail, numerals bleeding off their
 * column, and genuine edge-to-edge media.
 *
 * Every rule references tokens.css. No raw hex.
 */

/* ===========================================================================
 * A. SPLIT STAGE HERO
 * ======================================================================== */

.bs-hero {
	position: relative;
	overflow: hidden;
}

/* Elementor puts padding on containers by default; the band must reach the
   viewport edge on both sides or the "full-bleed" reads as a boxed layout. */
.bs-hero > .e-con-inner {
	max-width: 100%;
	padding: 0;
}

/* The ground is set here rather than through Elementor's global background.
   Elementor resolves container globals inconsistently once content_width is
   full, and the hero is unreadable if this silently fails: the H1 would render
   sky-on-white instead of white-on-midnight. Owning it in CSS makes it
   deterministic and keeps the value tied to the token. */
.bs-hero__copy {
	position: relative;
	justify-content: center;
	background-color: var(--midnight);
	padding-left: calc(56px + var(--space-gutter)) !important;
}

/* Elementor nests widgets inside .e-con-inner, which is not a positioning
   context. Without this the absolutely positioned rail escapes to the band. */
.bs-hero__copy > .e-con-inner {
	position: static;
}

.bs-hero__media {
	align-self: stretch;
}

/* Hero focal points.
 *
 * Every hero photo is a landscape 3:2 frame cropped into a tall panel, so about
 * a third of it is cut, and centre is often the wrong third: on the home page it
 * lands on the empty front of the van and clips both the wordmark and the
 * technician, on Mount Dora it cuts the shop sign in half.
 *
 * These belong on the Elementor container's own background_position setting,
 * but setting it to 'custom' with background_xpos/ypos emitted
 * `background-position: 0% 0%` rather than the requested percentage, so it lives
 * here instead. `!important` because Elementor's element rule ties on
 * specificity and enqueues later. Keyed on page id, which survives a database
 * migration to staging.
 */
.page-id-32 .bs-hero__media {  /* Home: hold the wordmark, number and technician */
	background-position: 62% center !important;
}

.page-id-77 .bs-hero__media {  /* Service Areas: bias toward the fleet */
	background-position: 55% center !important;
}

.page-id-78 .bs-hero__media {  /* Mount Dora: hold the whole shop sign */
	background-position: 38% center !important;
}

/* The rail widget is wrapped by Elementor; the wrapper must not occupy flow
   space or it pushes the eyebrow down and the rail lands mid-column. */
.bs-hero__copy .elementor-widget-html:has(.bs-hero__rail) {
	position: static;
	width: 0;
	height: 0;
	margin: 0;
}

/* The vertical rail. A signature device: it establishes the vertical axis that
   the horizontal bands cut across. Absolute so it cannot disturb the flow. */
.bs-hero__rail {
	position: absolute;
	top: 0;
	left: 0;
	bottom: 0;
	width: 56px;
	background-color: var(--sky);
	display: flex;
	align-items: center;
	justify-content: center;
	pointer-events: none;
}

.bs-hero__rail span {
	display: block;
	transform: rotate(-90deg);
	white-space: nowrap;
	font-family: var(--font-body);
	font-weight: 600;
	font-size: 11px;
	letter-spacing: 0.3em;
	text-transform: uppercase;
	color: var(--paper);
}

.bs-hero__h1 {
	margin: 0.25em 0 0.35em;
	max-width: 14ch;
}

.bs-hero__lead {
	max-width: 46ch;
}

.bs-hero__license {
	font-size: 0.8125rem;
	opacity: 0.62;
	margin-top: 0.5rem;
}

/* Trust strip: four items divided by thin rules, sitting at the foot of the
   copy column. */
.bs-hero__trust {
	display: flex;
	flex-wrap: wrap;
	list-style: none;
	margin: 2.5rem 0 0;
	padding: 0;
	border-top: 1px solid var(--line-on-dark);
}

.bs-hero__trust li {
	display: flex;
	flex-direction: column;
	gap: 2px;
	padding: 1rem 1.25rem 0 0;
	margin-right: 1.25rem;
	border-right: 1px solid var(--line-on-dark);
	font-size: 0.75rem;
	line-height: 1.3;
	text-transform: uppercase;
	letter-spacing: 0.08em;
	color: rgba(255, 255, 255, 0.72);
}

.bs-hero__trust li:last-child {
	border-right: 0;
	margin-right: 0;
}

.bs-hero__trust strong {
	color: var(--paper);
	font-family: var(--font-display);
	font-weight: 800;
	font-size: 0.9375rem;
	letter-spacing: 0.02em;
}

/* On mobile the photo goes above the copy, and the vertical rail becomes a thin
   horizontal bar so the device survives the reflow. */
@media (max-width: 1024px) {
	/* Photo above copy, per the brief. column-reverse because the media
	   container is second in source order. */
	.bs-hero {
		flex-direction: column-reverse !important;
		flex-wrap: nowrap !important;
	}

	.bs-hero__copy {
		/* The desktop rule reserves 56px for the vertical rail; on mobile the
		   rail is a horizontal bar, so that space would be dead margin. */
		padding-left: 24px !important;
	}

	/* Desktop zeroes this wrapper so the absolute rail cannot take flow space.
	   On mobile the rail IS in flow, so the wrapper has to be restored or it
	   collapses to a small square on top of the eyebrow. */
	.bs-hero__copy .elementor-widget-html:has(.bs-hero__rail) {
		position: static;
		width: 100%;
		height: auto;
		margin: 0 0 20px;
	}

	.bs-hero__rail {
		position: static;
		width: 100%;
		height: 34px;
		justify-content: flex-start;
		padding-left: 24px;
	}

	.bs-hero__rail span {
		transform: none;
		font-size: 10px;
	}

	/* The desktop hero is a full-viewport stage. Once it stacks, an 88vh photo
	   fills the entire first screen and the headline never appears above the
	   fold, which is the one thing the hero exists to do. */
	.bs-hero__media {
		min-height: 46vh !important;
		max-height: 52vh;
	}

	.bs-hero {
		min-height: 0 !important;
	}
}

@media (max-width: 480px) {
	.bs-hero__trust li {
		padding-right: 0.875rem;
		margin-right: 0.875rem;
	}
}

/* ===========================================================================
 * Shared band behaviour
 *
 * Elementor wraps container children in .e-con-inner with its own max-width.
 * Bands must reach the viewport edge, so full-bleed bands clear it and only
 * boxed inner wrappers reinstate the content column.
 * ======================================================================== */

.bs-band > .e-con-inner {
	max-width: 100%;
	padding: 0;
}

.bs-band [class*="__inner"] > .e-con-inner,
.bs-rail__head > .e-con-inner,
.bs-proof__inner > .e-con-inner,
.bs-areas__inner > .e-con-inner {
	max-width: var(--content-max);
	margin-inline: auto;
}

/* ===========================================================================
 * C. STATEMENT BAND
 * ======================================================================== */

.bs-statement__inner {
	text-align: left;
}

.bs-statement__h2 {
	font-family: var(--font-display);
	font-weight: 900;
	font-size: clamp(2.5rem, 6vw, 5.5rem);
	line-height: 1.02;
	letter-spacing: -0.03em;
	color: var(--paper);
	max-width: 18ch;
	margin: 0.5rem 0 1rem;
}

/* One word carries the color. The brief is explicit that only one does. */
.bs-statement__h2 em {
	font-style: normal;
	color: var(--sky);
}

.bs-statement__sub p {
	max-width: 52ch;
	color: rgba(255, 255, 255, 0.78);
}

/* ===========================================================================
 * D. HORIZONTAL SERVICE RAIL
 *
 * Cards overflow the right viewport edge so it reads as continuing. Native
 * scroll is preserved; only the scrollbar is hidden.
 * ======================================================================== */

/* Elementor renders a full-width container as .e-con-full with NO .e-con-inner
   wrapper, so these rules must sit on the track itself. Targeting the inner
   silently matched nothing, leaving Elementor's default flex-wrap: wrap in
   place, which stacked the cards vertically instead of scrolling them. */
.bs-rail__track,
.bs-rail__track > .e-con-inner {
	display: flex;
	flex-wrap: nowrap !important;
	gap: 24px;
	overflow-x: auto;
	scroll-snap-type: x mandatory;
	scroll-behavior: smooth;
	/* Mandatory snapping aligns the first card to the scrollport start, which
	   scrolls straight past padding-left. scroll-padding moves the snap line
	   itself so the first card lands on the content gutter. */
	scroll-padding-left: max(var(--space-gutter), calc((100vw - var(--content-max)) / 2));
	padding-left: max(var(--space-gutter), calc((100vw - var(--content-max)) / 2)) !important;
	padding-right: var(--space-gutter) !important;
	scrollbar-width: none;
}

.bs-rail__track::-webkit-scrollbar,
.bs-rail__track > .e-con-inner::-webkit-scrollbar {
	display: none;
}

/* Elementor sets container width through a --width custom property with high
   specificity, so the card collapses to nothing inside a nowrap track unless
   the size is forced here. */
.bs-rail__card {
	flex: 0 0 380px !important;
	width: 380px !important;
	max-width: 380px !important;
	height: 560px;
	scroll-snap-align: start;
	overflow: hidden;
}

.bs-rail__media {
	height: 60%;
	flex: 0 0 60%;
}

.bs-rail__copy {
	height: 40%;
	flex: 0 0 40%;
	justify-content: center;
	position: relative;
}

.bs-rail__num {
	font-family: var(--font-body);
	font-size: 11px;
	font-weight: 600;
	letter-spacing: 0.2em;
	color: var(--sky);
}

.bs-rail__title .elementor-heading-title {
	font-size: 1.25rem;
	color: var(--paper);
	margin: 0.35rem 0;
}

.bs-rail__line p {
	font-size: 0.875rem;
	color: rgba(255, 255, 255, 0.7);
	margin: 0;
}

.bs-rail__arrow {
	position: absolute;
	right: 24px;
	bottom: 20px;
	color: var(--sky);
	font-size: 1.25rem;
}

.bs-rail__h2 .elementor-heading-title {
	max-width: 18ch;
}

/* ===========================================================================
 * B. SPLIT BAND
 * ======================================================================== */

.bs-splitband {
	position: relative;
	overflow: hidden;
}

.bs-splitband__copy {
	position: relative;
	overflow: visible;
}

/* Same e-con-full caveat: constrain the copy itself, not a wrapper that does
   not exist on a full-width container. */
.bs-splitband__copy > .e-con-inner {
	position: relative;
	max-width: var(--copy-max);
	margin-inline: auto;
}

.bs-splitband__copy.e-con-full > * {
	max-width: var(--copy-max);
	width: 100%;
}

/* The numeral bleeds off the outer edge of the copy column and sits BEHIND the
   eyebrow and heading. This is what creates the vertical-against-horizontal
   tension; a tidy numeral in the flow defeats the whole device. */
.bs-splitband__num {
	position: absolute;
	top: -0.18em;
	left: -0.32em;
	z-index: 0;
	pointer-events: none;
}

.bs-splitband__copy .elementor-widget-html:has(.bs-splitband__num) {
	position: static;
	height: 0;
	margin: 0;
}

.bs-splitband__copy .bs-eyebrow,
.bs-splitband__copy .bs-splitband__h2,
.bs-splitband__copy .bs-splitband__body,
.bs-splitband__copy .bs-splitband__list,
.bs-splitband__copy .bs-splitband__cta {
	position: relative;
	z-index: 1;
}

.bs-splitband__h2 .elementor-heading-title {
	margin: 0.3em 0 0.5em;
	max-width: 16ch;
}

.bs-splitband__body p {
	max-width: 52ch;
}

/* Checklist uses thin sky rules, explicitly not circular icon badges. */
.bs-splitband__list {
	list-style: none;
	margin: 1.75rem 0;
	padding: 0;
}

.bs-splitband__list li {
	padding: 0.75rem 0 0.75rem 1.25rem;
	border-top: 1px solid var(--line);
	position: relative;
	font-size: 0.9375rem;
}

.bs-splitband__list li:last-child {
	border-bottom: 1px solid var(--line);
}

.bs-splitband__list li::before {
	content: "";
	position: absolute;
	left: 0;
	top: 1.35em;
	width: 12px;
	height: 2px;
	background-color: var(--sky);
}

.bs-invert .bs-splitband__list li {
	border-color: var(--line-on-dark);
}

.bs-splitband__cta {
	display: inline-flex;
	align-items: center;
	gap: 0.5rem;
	font-family: var(--font-display);
	font-weight: 700;
	font-size: 0.875rem;
	text-transform: uppercase;
	letter-spacing: 0.06em;
	color: var(--sky);
	text-decoration: none;
	transition: gap var(--dur-hover) ease-out;
}

.bs-splitband__cta:hover {
	gap: 0.875rem;
}

/* ===========================================================================
 * G. PROOF WALL
 * ======================================================================== */

.bs-proof__head {
	display: flex;
	flex-wrap: wrap;
	align-items: flex-end;
	justify-content: space-between;
	gap: 2rem;
	margin: 0.5rem 0 3rem;
}

.bs-proof__head h2 {
	max-width: 16ch;
	margin: 0;
}

.bs-proof__stat {
	display: flex;
	align-items: baseline;
	gap: 1rem;
}

.bs-proof__big {
	font-family: var(--font-display);
	font-weight: 900;
	font-size: clamp(5rem, 12vw, 12rem);
	line-height: 0.8;
	color: var(--ink);
	letter-spacing: -0.04em;
}

.bs-proof__note {
	max-width: 16ch;
	font-size: 0.8125rem;
	color: var(--slate);
}

/* Masonry via columns: varying heights without a grid, per the brief. */
.bs-proof__wall {
	column-count: 3;
	column-gap: 24px;
	position: relative;
}

.bs-proof__card {
	break-inside: avoid;
	margin: 0 0 24px;
	padding: 24px;
	background-color: var(--paper);
	border: 1px solid var(--line);
}

.bs-proof__stars {
	color: var(--sunbeam);
	letter-spacing: 0.1em;
	margin-bottom: 0.75rem;
}

.bs-proof__card blockquote {
	margin: 0 0 0.75rem;
	padding: 0;
	border: 0;
	font-size: 0.9375rem;
	line-height: 1.6;
	color: var(--ink);
}

.bs-proof__card figcaption {
	font-size: 0.8125rem;
	color: var(--slate);
}

/* ===========================================================================
 * H. SERVICE AREA BAND
 * ======================================================================== */

.bs-areas__grid {
	display: grid;
	grid-template-columns: repeat(4, 1fr);
	gap: 24px;
}

.bs-areas__col h3 {
	font-size: 0.75rem;
	letter-spacing: 0.14em;
	text-transform: uppercase;
	color: var(--paper);
	padding-top: 12px;
	border-top: 2px solid var(--sky);
	margin: 0 0 0.875rem;
}

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

.bs-areas__col li {
	margin-bottom: 0.4rem;
}

/* Towns with their own page render white; the rest sit at 60%. */
.bs-areas__col a {
	color: var(--paper);
	text-decoration: none;
	font-size: 0.9375rem;
	font-weight: 500;
}

.bs-areas__col a:hover {
	color: var(--sky);
}

.bs-areas__col span {
	color: rgba(255, 255, 255, 0.6);
	font-size: 0.9375rem;
	font-weight: 500;
}

/* ===========================================================================
 * I. EMERGENCY BAND
 * ======================================================================== */

.bs-emergency__inner > .e-con-inner {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between;
	gap: 24px;
	max-width: var(--content-max);
	margin-inline: auto;
}

.bs-emergency__lead {
	font-family: var(--font-display);
	font-weight: 800;
	font-size: clamp(1.375rem, 2.4vw, 2rem);
	color: var(--paper);
	margin: 0 0 0.35rem;
	line-height: 1.1;
}

.bs-emergency__sub {
	color: rgba(255, 255, 255, 0.9);
	margin: 0;
}

/* White button with siren text, the inverse of every other CTA on the site. */
.bs-btn--onsiren .elementor-button {
	background-color: var(--paper) !important;
	color: var(--siren) !important;
	border-radius: var(--radius-button);
	font-family: var(--font-display);
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 0.06em;
	font-size: 1.0625rem;
}

/* ===========================================================================
 * RESPONSIVE
 * ======================================================================== */

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

	.bs-proof__wall {
		column-count: 2;
	}
}

@media (max-width: 768px) {
	.bs-rail__card {
		flex: 0 0 300px !important;
		width: 300px !important;
		max-width: 300px !important;
		height: 480px;
	}

	.bs-proof__wall {
		column-count: 1;
	}

	/* Bands stack image-then-copy. Using order on the media rather than
	   column-reverse means it works for image-left and image-right bands
	   alike, without regenerating any page. */
	.bs-splitband {
		flex-direction: column;
	}

	.bs-splitband__media {
		order: -1;
	}

	/* On desktop the numeral bleeds off the outer edge of the copy column. At
	   this width that would push it off the viewport and read as broken, so it
	   moves inside and shrinks while keeping its position behind the text. */
	.bs-splitband__num {
		font-size: clamp(3.5rem, 16vw, 6rem);
		top: -0.05em;
		left: 0;
	}

	.bs-splitband__copy > .e-con-inner {
		max-width: 100%;
	}
}

@media (max-width: 480px) {
	.bs-areas__grid {
		grid-template-columns: 1fr;
	}
}

/* ===========================================================================
 * SITE HEADER: utility bar + sticky nav + services mega-dropdown
 * ======================================================================== */

.bs-utility__inner {
	max-width: var(--content-max);
	margin-inline: auto;
	display: flex;
	justify-content: space-between;
	align-items: center;
	gap: 16px;
	min-height: 40px;
	padding-inline: var(--space-gutter);
	font-size: 0.6875rem;
	font-weight: 600;
	letter-spacing: 0.12em;
	text-transform: uppercase;
	color: rgba(255, 255, 255, 0.82);
}

.bs-utility__inner a {
	color: var(--paper);
	text-decoration: none;
}

.bs-header {
	position: sticky;
	top: 0;
	z-index: 100;
	border-bottom: 1px solid var(--line);
	transition: box-shadow 240ms ease, background-color 240ms ease;
}

.bs-header__inner {
	max-width: var(--content-max);
	margin-inline: auto;
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 32px;
	padding: 14px var(--space-gutter);
}

.bs-header__logo img {
	display: block;
	width: 168px;
	height: auto;
}

.bs-nav > ul {
	display: flex;
	align-items: center;
	gap: 28px;
	list-style: none;
	margin: 0;
	padding: 0;
}

.bs-nav a {
	font-family: var(--font-body);
	font-weight: 500;
	font-size: 0.9375rem;
	color: var(--ink);
	text-decoration: none;
}

.bs-nav a:hover {
	color: var(--sky);
}

.bs-nav__item {
	position: static;
}

.bs-header__actions {
	display: flex;
	align-items: center;
	gap: 16px;
}

.bs-header__phone {
	font-family: var(--font-display);
	font-weight: 800;
	font-size: 1.25rem;
	color: var(--ink);
	text-decoration: none;
	white-space: nowrap;
}

.bs-header__book {
	background-color: var(--sky);
	color: var(--paper);
	font-family: var(--font-display);
	font-weight: 700;
	font-size: 0.875rem;
	text-transform: uppercase;
	letter-spacing: 0.06em;
	padding: 12px 20px;
	border-radius: var(--radius-button);
	text-decoration: none;
	white-space: nowrap;
	transition: background-color var(--dur-hover) ease-out, transform var(--dur-hover) ease-out;
}

.bs-header__book:hover {
	background-color: var(--sky-deep);
	transform: translateY(-2px);
}

/* Full-width mega-dropdown. CSS only, no script. */
.bs-mega {
	position: absolute;
	left: 0;
	right: 0;
	top: 100%;
	background-color: var(--paper);
	border-top: 1px solid var(--line);
	border-bottom: 1px solid var(--line);
	opacity: 0;
	visibility: hidden;
	transform: translateY(-6px);
	transition: opacity 180ms ease-out, transform 180ms ease-out, visibility 180ms;
}

.bs-nav__item--has-mega:hover .bs-mega,
.bs-nav__item--has-mega:focus-within .bs-mega {
	opacity: 1;
	visibility: visible;
	transform: none;
}

.bs-mega__inner {
	max-width: var(--content-max);
	margin-inline: auto;
	display: grid;
	grid-template-columns: repeat(4, 1fr) 1.1fr;
	gap: 32px;
	padding: 36px var(--space-gutter);
}

.bs-mega__col h4 {
	font-family: var(--font-body);
	font-size: 0.6875rem;
	letter-spacing: 0.16em;
	text-transform: uppercase;
	color: var(--sky);
	margin: 0 0 12px;
	padding-bottom: 10px;
	border-bottom: 1px solid var(--line);
}

.bs-mega__col ul,
.bs-foot__col ul {
	list-style: none;
	margin: 0;
	padding: 0;
}

.bs-mega__col li {
	margin-bottom: 8px;
}

.bs-mega__promo {
	background-color: var(--midnight);
	padding: 24px;
}

.bs-mega__promo h4 {
	color: var(--paper);
	font-family: var(--font-display);
	font-weight: 800;
	margin: 0 0 8px;
}

.bs-mega__promo p {
	color: rgba(255, 255, 255, 0.78);
	font-size: 0.875rem;
	margin: 0 0 16px;
}

.bs-mega__cta {
	display: inline-block;
	background-color: var(--siren);
	color: var(--paper);
	font-family: var(--font-display);
	font-weight: 700;
	padding: 10px 16px;
	border-radius: var(--radius-button);
	text-decoration: none;
}

/* ===========================================================================
 * J. MEGA FOOTER
 * ======================================================================== */

.bs-foot__inner {
	position: relative;
	max-width: var(--content-max);
	margin-inline: auto;
	padding: 96px var(--space-gutter) 48px;
	/* No overflow: hidden. This container is 1360px wide, so hiding overflow
	   clipped the full-bleed tail to 40px inside each viewport edge, which is
	   what cropped the wordmark. It was only needed when the wordmark was
	   absolutely positioned; it now sits in flow inside .bs-foot__wide. */
}

.bs-foot__top {
	display: flex;
	flex-wrap: wrap;
	align-items: flex-start;
	gap: 48px;
	padding-bottom: 48px;
	border-bottom: 1px solid var(--line-on-dark);
}

.bs-foot__logo img {
	display: block;
	width: 260px;
	height: auto;
}

.bs-foot__nap {
	font-style: normal;
	line-height: 1.8;
	color: rgba(255, 255, 255, 0.82);
}

.bs-foot__nap strong {
	color: var(--paper);
}

.bs-foot__nap a {
	color: var(--sky);
	text-decoration: none;
}

.bs-foot__cols {
	position: relative;
	z-index: 1;
	display: grid;
	grid-template-columns: repeat(4, 1fr);
	gap: 32px;
	padding: 48px 0;
}

.bs-foot__col h4 {
	font-family: var(--font-body);
	font-size: 0.6875rem;
	letter-spacing: 0.16em;
	text-transform: uppercase;
	color: var(--sky);
	margin: 0 0 14px;
}

.bs-foot__col li {
	margin-bottom: 9px;
}

.bs-foot__col a {
	color: rgba(255, 255, 255, 0.82);
	text-decoration: none;
	font-size: 0.9375rem;
}

.bs-foot__col a:hover {
	color: var(--paper);
}

.bs-foot__badges {
	position: relative;
	z-index: 1;
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: center;
	gap: 28px;
	padding: 24px 0 32px;
	border-top: 1px solid var(--line-on-dark);
}

.bs-foot__badges img {
	height: 56px;
	width: auto;
	opacity: 0.9;
}

.bs-foot__bar {
	position: relative;
	z-index: 1;
	display: flex;
	flex-wrap: wrap;
	justify-content: space-between;
	gap: 16px;
	padding-top: 24px;
	border-top: 1px solid var(--line-on-dark);
	font-size: 0.75rem;
	color: rgba(255, 255, 255, 0.6);
}

/* The oversized wordmark bleeds off both edges behind everything. */
.bs-foot__wordmark {
	position: absolute;
	left: 50%;
	bottom: -0.22em;
	transform: translateX(-50%);
	font-family: var(--font-display);
	font-weight: 900;
	font-size: clamp(5rem, 15vw, 14rem);
	line-height: 0.8;
	white-space: nowrap;
	color: rgba(255, 255, 255, 0.06);
	pointer-events: none;
	user-select: none;
	z-index: 0;
}

@media (max-width: 1024px) {
	.bs-nav,
	.bs-header__phone {
		display: none;
	}

	.bs-mega__inner {
		grid-template-columns: repeat(2, 1fr);
	}

	.bs-foot__cols {
		grid-template-columns: repeat(2, 1fr);
	}
}

@media (max-width: 600px) {
	.bs-foot__cols {
		grid-template-columns: 1fr;
	}

	.bs-utility__inner {
		font-size: 0.625rem;
		letter-spacing: 0.06em;
	}
}

/* ===========================================================================
 * SERVICE PAGE PARTS
 * ======================================================================== */

/* Page heroes are shorter than the homepage's full-viewport stage. */
.bs-hero--page {
	min-height: 520px;
}

.bs-hero--page .bs-hero__h1 .elementor-heading-title {
	font-size: clamp(2.25rem, 4.6vw, 4rem);
}

/* Quick answer: one bordered box near the top, answer-first, no fluff. */
.bs-quick__box {
	border: 1px solid var(--line);
	border-left: 4px solid var(--sky);
	padding: 28px 32px;
	background-color: var(--mist);
	max-width: 78ch;
}

.bs-quick__box h2 {
	font-size: clamp(1.125rem, 1.6vw, 1.375rem);
	margin: 0 0 0.5rem;
}

.bs-quick__box p {
	margin: 0;
	color: var(--ink);
}

/* Symptoms: two columns of thin-ruled items, not icon cards. */
.bs-symptoms__list {
	list-style: none;
	margin: 1.5rem 0 0;
	padding: 0;
	columns: 2;
	column-gap: 48px;
}

.bs-symptoms__list li {
	break-inside: avoid;
	padding: 0.75rem 0 0.75rem 1.5rem;
	border-top: 1px solid var(--line);
	position: relative;
}

.bs-symptoms__list li::before {
	content: "";
	position: absolute;
	left: 0;
	top: 1.4em;
	width: 14px;
	height: 2px;
	background-color: var(--sky);
}

/* F. PROCESS LADDER: each step reaches horizontally and indents further right,
   so the sequence forms a descending diagonal. */
.bs-ladder__list {
	list-style: none;
	margin: 2.5rem 0 0;
	padding: 0;
	counter-reset: ladder;
}

.bs-ladder__step {
	display: flex;
	align-items: flex-start;
	gap: 32px;
	padding: 32px 0;
	border-top: 1px solid var(--line);
}

.bs-ladder__step:nth-child(2) { padding-left: 4%; }
.bs-ladder__step:nth-child(3) { padding-left: 8%; }
.bs-ladder__step:nth-child(4) { padding-left: 12%; }

.bs-ladder__num {
	font-family: var(--font-display);
	font-weight: 900;
	font-size: clamp(2.5rem, 5vw, 4.5rem);
	line-height: 0.85;
	color: var(--sky);
	opacity: 0.22;
	flex: 0 0 auto;
	min-width: 2.5ch;
}

.bs-ladder__body h3 {
	margin: 0 0 0.35rem;
}

.bs-ladder__body p {
	margin: 0;
	max-width: 60ch;
}

/* FAQ cards.
 *
 * Open rather than an accordion: every answer is visible without interaction,
 * which reads better and is safer for AI answer engines, where content behind a
 * collapsed control may be discounted. Two columns, sharp corners, hairline
 * borders, per the brief's card treatment.
 */
.bs-faq__grid {
	display: grid;
	grid-template-columns: repeat(2, 1fr);
	gap: 24px;
	margin-top: 2.5rem;
	align-items: start;
}

.bs-faq__card {
	background-color: var(--paper);
	border: 1px solid var(--line);
	border-top: 3px solid var(--sky);
	padding: 28px;
}

.bs-faq__q {
	font-family: var(--font-display);
	font-weight: 700;
	font-size: 1.0625rem;
	line-height: 1.3;
	color: var(--ink);
	margin: 0 0 0.65rem;
}

/* The first sentence of every answer must answer the question outright, so the
   copy is set at full readable measure rather than truncated. */
.bs-faq__a {
	margin: 0;
	font-size: 0.9375rem;
	line-height: 1.7;
	color: var(--slate);
	max-width: 60ch;
}

/* Cards on a dark ground keep the same structure with inverted values. */
.bs-invert .bs-faq__card {
	background-color: var(--card-on-dark);
	border-color: var(--line-on-dark);
}

.bs-invert .bs-faq__q {
	color: var(--paper);
}

.bs-invert .bs-faq__a {
	color: rgba(255, 255, 255, 0.78);
}

@media (max-width: 768px) {
	.bs-faq__grid {
		grid-template-columns: 1fr;
	}

	.bs-symptoms__list {
		columns: 1;
	}

	.bs-ladder__step {
		gap: 18px;
	}

	.bs-ladder__step:nth-child(2),
	.bs-ladder__step:nth-child(3),
	.bs-ladder__step:nth-child(4) {
		padding-left: 0;
	}
}

/* Proof chips: short scannable facts under the quick answer. Pills are one of
   the two places radius is allowed. */
.bs-chips__row {
	display: flex;
	flex-wrap: wrap;
	gap: 10px;
	list-style: none;
	margin: 0;
	padding: 0;
}

.bs-chips__row li {
	border: 1px solid var(--line);
	border-radius: var(--radius-pill);
	padding: 7px 16px;
	font-size: 0.8125rem;
	font-weight: 500;
	color: var(--ink);
	background-color: var(--paper);
}

/* The kit's global link color (sky) outranks these classes, which renders sky
   text on a sky button: invisible. Anything that is a link styled as a solid
   button must reassert its color. */
.bs-header__book,
.bs-header__book:hover,
.bs-mega__cta,
.bs-mega__cta:hover,
.bs-foot__badges a {
	color: var(--paper) !important;
}

.bs-header__phone,
.bs-utility__inner a {
	color: var(--ink) !important;
}

.bs-utility__inner a {
	color: var(--paper) !important;
}

.bs-splitband__cta,
.bs-splitband__cta:hover {
	color: var(--sky) !important;
}

/* ===========================================================================
 * LOCATION PAGE PARTS
 * ======================================================================== */

.bs-localdetail__body p {
	max-width: 72ch;
	margin-bottom: 1rem;
}

/* Service tiles: sharp-cornered rows, not a grid of rounded icon cards. */
.bs-tiles__grid {
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	gap: 1px;
	background-color: var(--line);
	border: 1px solid var(--line);
	margin-top: 2rem;
}

.bs-tiles__tile {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: 16px;
	padding: 28px 24px;
	background-color: var(--paper);
	text-decoration: none;
	font-family: var(--font-display);
	font-weight: 700;
	font-size: 1.0625rem;
	color: var(--ink) !important;
	transition: background-color var(--dur-hover) ease-out, color var(--dur-hover) ease-out;
}

.bs-tiles__tile:hover {
	background-color: var(--midnight);
	color: var(--paper) !important;
}

.bs-tiles__arrow {
	color: var(--sky);
}

.bs-tiles__tile:hover .bs-tiles__arrow {
	color: var(--sunbeam);
}

.bs-nearby__list {
	display: flex;
	flex-wrap: wrap;
	gap: 10px;
	list-style: none;
	margin: 1.5rem 0 0;
	padding: 0;
}

.bs-nearby__list a {
	display: inline-block;
	border: 1px solid var(--line-on-dark);
	border-radius: var(--radius-pill);
	padding: 8px 18px;
	color: var(--paper) !important;
	text-decoration: none;
	font-size: 0.875rem;
	font-weight: 500;
	transition: background-color var(--dur-hover) ease-out, border-color var(--dur-hover) ease-out;
}

.bs-nearby__list a:hover {
	background-color: var(--sky);
	border-color: var(--sky);
}

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

@media (max-width: 600px) {
	.bs-tiles__grid {
		grid-template-columns: 1fr;
	}
}

/* ===========================================================================
 * INDEX LIST (services landing)
 *
 * Oversized numerals and full-width rules, deliberately not a card grid.
 * ======================================================================== */

.bs-index__list {
	border-top: 1px solid var(--line);
}

.bs-index__row {
	display: flex;
	align-items: center;
	gap: 32px;
	padding: 28px 0;
	border-bottom: 1px solid var(--line);
	text-decoration: none;
	color: var(--ink) !important;
	transition: padding-left var(--dur-hover) ease-out, background-color var(--dur-hover) ease-out;
}

.bs-index__row:hover {
	padding-left: 16px;
	background-color: var(--mist);
}

.bs-index__num {
	font-family: var(--font-display);
	font-weight: 900;
	font-size: clamp(2rem, 4vw, 3.5rem);
	line-height: 0.85;
	color: var(--sky);
	opacity: 0.28;
	flex: 0 0 auto;
	min-width: 2.5ch;
}

.bs-index__body {
	display: flex;
	flex-direction: column;
	gap: 4px;
	flex: 1 1 auto;
}

.bs-index__name {
	font-family: var(--font-display);
	font-weight: 800;
	font-size: clamp(1.125rem, 1.8vw, 1.5rem);
	letter-spacing: -0.015em;
}

.bs-index__line {
	font-size: 0.9375rem;
	color: var(--slate);
}

.bs-index__arrow {
	color: var(--sky);
	font-size: 1.5rem;
	flex: 0 0 auto;
}

@media (max-width: 600px) {
	.bs-index__row {
		gap: 16px;
	}

	.bs-index__line {
		display: none;
	}
}

.bs-localdetail__item {
	padding: 20px 0;
	border-top: 1px solid var(--line);
	max-width: 78ch;
}

.bs-localdetail__item h3 {
	font-size: 1.0625rem;
	margin: 0 0 0.35rem;
}

.bs-localdetail__item p {
	margin: 0;
}

.bs-localdetail__drive {
	margin-top: 1.25rem;
	font-size: 0.875rem;
	color: var(--slate);
	font-style: italic;
}

/* Contact detail grid */
.bs-contact__grid {
	display: grid;
	grid-template-columns: repeat(4, 1fr);
	gap: 32px;
	margin-top: 2rem;
}

.bs-contact__block h3 {
	font-size: 0.75rem;
	letter-spacing: 0.14em;
	text-transform: uppercase;
	color: var(--sky);
	padding-top: 12px;
	border-top: 2px solid var(--sky);
	margin: 0 0 0.75rem;
}

.bs-contact__block p,
.bs-contact__block address {
	font-style: normal;
	margin: 0 0 0.5rem;
	line-height: 1.7;
}

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

@media (max-width: 600px) {
	.bs-contact__grid {
		grid-template-columns: 1fr;
	}
}

/* ===========================================================================
 * MOBILE NAVIGATION
 *
 * <details> disclosure: keyboard accessible with an open state for free, so no
 * JavaScript. Hidden above 1024 where the real nav takes over.
 * ======================================================================== */

.bs-mobnav {
	display: none;
	position: relative;
}

.bs-mobnav > summary {
	list-style: none;
	cursor: pointer;
	width: 44px;
	height: 44px;
	display: flex;
	align-items: center;
	justify-content: center;
	border: 1px solid var(--line);
	border-radius: var(--radius-button);
}

.bs-mobnav > summary::-webkit-details-marker {
	display: none;
}

/* Three bars drawn from one element via borders. */
.bs-mobnav__bars,
.bs-mobnav__bars::before,
.bs-mobnav__bars::after {
	display: block;
	width: 20px;
	height: 2px;
	background-color: var(--ink);
	content: "";
	position: relative;
}

.bs-mobnav__bars::before {
	top: -6px;
}

.bs-mobnav__bars::after {
	top: 4px;
}

.bs-mobnav[open] > summary {
	background-color: var(--midnight);
	border-color: var(--midnight);
}

.bs-mobnav[open] .bs-mobnav__bars,
.bs-mobnav[open] .bs-mobnav__bars::before,
.bs-mobnav[open] .bs-mobnav__bars::after {
	background-color: var(--paper);
}

.bs-mobnav__panel {
	position: absolute;
	right: 0;
	top: calc(100% + 10px);
	width: min(78vw, 320px);
	background-color: var(--paper);
	border: 1px solid var(--line);
	padding: 8px;
	z-index: 200;
	box-shadow: 0 18px 40px -24px rgba(6, 42, 74, 0.5);
}

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

.bs-mobnav__panel li + li {
	border-top: 1px solid var(--line);
}

.bs-mobnav__panel a {
	display: block;
	padding: 14px 12px;
	min-height: 44px;
	color: var(--ink) !important;
	text-decoration: none;
	font-weight: 500;
}

.bs-mobnav__call {
	display: block;
	margin-top: 8px;
	padding: 14px 12px;
	text-align: center;
	background-color: var(--sky);
	color: var(--paper) !important;
	font-family: var(--font-display);
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 0.06em;
	border-radius: var(--radius-button);
	text-decoration: none;
}

/* ===========================================================================
 * FIXED MOBILE CALL BAR
 *
 * Two halves per the brief: siren for the call, sunbeam for booking. Mobile
 * only; the body gets bottom padding so the footer is never covered.
 * ======================================================================== */

.bs-callbar {
	display: none;
	position: fixed;
	left: 0;
	right: 0;
	bottom: 0;
	z-index: 300;
}

.bs-callbar a {
	flex: 1 1 50%;
	text-align: center;
	padding: 16px 8px;
	min-height: 56px;
	display: flex;
	align-items: center;
	justify-content: center;
	font-family: var(--font-display);
	font-weight: 700;
	font-size: 0.9375rem;
	text-transform: uppercase;
	letter-spacing: 0.06em;
	text-decoration: none;
}

.bs-callbar__call {
	background-color: var(--siren);
	color: var(--paper) !important;
}

.bs-callbar__book {
	background-color: var(--sunbeam);
	color: var(--midnight) !important;
}

@media (max-width: 1024px) {
	.bs-mobnav {
		display: block;
	}

	/* The header row must fit a 390px viewport: the logo shrinks, the desktop
	   phone link gives way to the call bar, and nothing may overflow. */
	.bs-header__inner {
		gap: 12px;
		padding: 10px 16px;
		flex-wrap: nowrap;
	}

	.bs-header__logo img {
		width: 132px;
	}

	.bs-header__actions {
		gap: 10px;
		flex-shrink: 0;
	}

	.bs-header__book {
		padding: 10px 14px;
		font-size: 0.75rem;
	}

	/* The utility bar was wrapping mid phone number. Let it stack cleanly and
	   drop the letter-spacing that forced the break. */
	.bs-utility__inner {
		flex-direction: column;
		align-items: flex-start;
		gap: 2px;
		padding: 7px 16px;
		min-height: 0;
		letter-spacing: 0.06em;
		line-height: 1.4;
	}
}

@media (max-width: 767px) {
	.bs-callbar {
		display: flex;
	}

	/* Reserve room so the fixed bar never covers the footer's last row. */
	body {
		padding-bottom: 56px;
	}

	/* Below 768 the Book Online button duplicates the call bar, so drop it and
	   give the logo the room back. */
	.bs-header__book {
		display: none;
	}

	.bs-header__logo img {
		width: 150px;
	}
}

/* ===========================================================================
 * SECTION GUTTERS
 *
 * Boxed inner containers were generated with a flat 24px horizontal padding,
 * which puts text almost against the viewport edge on wide screens. This
 * standardises every boxed section on the token gutter, clamp(24px, 5vw, 88px),
 * so it stays 24px on a phone and opens up to 88px on a desktop.
 *
 * Vertical padding is left alone; each section sets its own rhythm.
 * ======================================================================== */

.bs-band [class*="__inner"],
.bs-rail__head {
	padding-left: var(--space-gutter) !important;
	padding-right: var(--space-gutter) !important;
}

/* Split band copy already carries generous internal padding and a max-width;
   the shared gutter would push it off-centre. */
.bs-splitband__copy,
.bs-hero__copy {
	padding-right: var(--space-gutter) !important;
}

/* ===========================================================================
 * GROUND COLORS SET IN CSS, NOT VIA ELEMENTOR GLOBALS
 *
 * Elementor resolves container global backgrounds unreliably, particularly on
 * inner containers and once content_width is full. When it fails the section
 * falls back to transparent, which on a light page means white text on white,
 * or in the rail's case a card whose copy block vanishes.
 *
 * Owning these here makes them deterministic while keeping the value tied to
 * the token, so a palette change still propagates from one place.
 * ======================================================================== */

.bs-rail__copy {
	background-color: var(--midnight);
}

.bs-statement,
.bs-areas,
.bs-nearby,
.bs-foot,
.bs-utility,
.bs-bloghead,
.bs-postheader {
	background-color: var(--midnight);
}

.bs-emergency {
	background-color: var(--siren);
}

.bs-symptoms,
.bs-proof,
.bs-faq {
	background-color: var(--mist);
}

.bs-bloggrid,
.bs-postbody,
.bs-postfeature,
.bs-related,
.bs-quick,
.bs-chips,
.bs-ladder,
.bs-tiles,
.bs-index,
.bs-rail,
.bs-localdetail,
.bs-header {
	background-color: var(--paper);
}

/* ===========================================================================
 * RAIL CONTROLS
 *
 * Without these the rail scrolls but gives no sign that it can, so the cards
 * past the right edge go unseen. Square, sharp-cornered, midnight, sitting at
 * top-right in line with the H2.
 * ======================================================================== */

.bs-rail__headrow {
	display: flex;
	align-items: flex-end;
	justify-content: space-between;
	gap: 24px;
}

.bs-rail__headrow .bs-rail__h2 {
	margin: 0.3em 0 0;
	max-width: 18ch;
}

.bs-rail__controls {
	display: flex;
	gap: 8px;
	flex-shrink: 0;
}

/* The kit sets a background and radius on every button element, so the brief's
   square midnight control needs these forced. */
.bs-rail__btn {
	width: 48px;
	height: 48px;
	border: 0;
	border-radius: 0 !important;
	background-color: var(--midnight) !important;
	color: var(--paper) !important;
	font-size: 1.125rem;
	line-height: 1;
	cursor: pointer;
	display: flex;
	align-items: center;
	justify-content: center;
	transition: background-color var(--dur-hover) ease-out, opacity var(--dur-hover) ease-out;
}

.bs-rail__btn:hover:not(:disabled) {
	background-color: var(--sky) !important;
}

.bs-rail__btn:disabled {
	opacity: 0.25;
	cursor: default;
}

.bs-rail__btn:focus-visible {
	outline: 2px solid var(--sky);
	outline-offset: 2px;
}

/* Thin progress line under the rail: a second, passive signal that there is
   more to the right. */
.bs-rail__progress {
	position: relative;
	height: 2px;
	background-color: var(--line);
	margin-top: 28px;
}

.bs-rail__progressbar {
	position: absolute;
	inset: 0;
	background-color: var(--sky);
	transform: scaleX(0);
	transform-origin: left;
	transition: transform 120ms linear;
}

/* When everything fits there is nothing to scroll, so the controls would be
   misleading. JS adds this class. */
.bs-rail--static .bs-rail__controls,
.bs-rail--static .bs-rail__progress {
	display: none;
}

/* The last card is deliberately cut by the viewport edge so the row reads as
   continuing. This fade reinforces it without hiding content. */
.bs-rail__track {
	-webkit-mask-image: linear-gradient(to right, #000 0, #000 92%, transparent 100%);
	mask-image: linear-gradient(to right, #000 0, #000 92%, transparent 100%);
}

@media (max-width: 768px) {
	.bs-rail__headrow {
		flex-direction: column;
		align-items: flex-start;
		gap: 16px;
	}

	/* Touch users swipe, so the buttons matter less and the row is tight. */
	.bs-rail__btn {
		width: 44px;
		height: 44px;
	}
}

/* ===========================================================================
 * COLUMN LABELS
 *
 * Footer and mega-dropdown column labels are navigation group labels, not
 * document sections. They were <h4>, which produced h1-to-h4 jumps in the
 * outline on every page since the footer follows the page h1. They are now
 * paragraphs styled to look identical.
 * ======================================================================== */

.bs-collabel {
	font-family: var(--font-body);
	font-size: 0.6875rem;
	font-weight: 600;
	letter-spacing: 0.16em;
	text-transform: uppercase;
	color: var(--sky);
	margin: 0 0 14px;
}

.bs-mega__col .bs-collabel {
	padding-bottom: 10px;
	border-bottom: 1px solid var(--line);
	margin-bottom: 12px;
}

.bs-collabel--promo {
	font-family: var(--font-display);
	font-size: 1.0625rem;
	font-weight: 800;
	letter-spacing: 0;
	text-transform: none;
	color: var(--paper);
	margin-bottom: 8px;
}

/* ===========================================================================
 * TOUCH TARGETS
 *
 * Link rows in the footer, area lists and index sat at 12 to 20px tall, well
 * under the 44px that thumbs need. These give real hit area on touch widths
 * without changing the visual rhythm much.
 * ======================================================================== */

@media (max-width: 820px) {
	.bs-foot__col li,
	.bs-areas__col li,
	.bs-mega__col li {
		margin-bottom: 0;
	}

	.bs-foot__col a,
	.bs-areas__col a,
	.bs-areas__col span,
	.bs-mega__col a {
		display: flex;
		align-items: center;
		min-height: 44px;
		padding-block: 4px;
	}

	.bs-nearby__list a {
		min-height: 44px;
		padding: 10px 18px;
	}

	.bs-splitband__cta,
	.bs-index__arrow {
		min-height: 44px;
	}

	.bs-splitband__cta {
		align-items: center;
	}

	.bs-index__row {
		padding: 20px 0;
		min-height: 64px;
	}

	.bs-tiles__tile {
		min-height: 56px;
	}

	/* Inline phone links in the utility bar and footer NAP. */
	.bs-utility__inner a,
	.bs-foot__nap a {
		display: inline-flex;
		align-items: center;
		min-height: 32px;
	}
}

/* The footer NAP block sits inside <address> with a tight line-height, leaving
   its phone and email links around 20px tall. Thumbs need more. */
@media (max-width: 820px) {
	.bs-foot__nap a {
		display: inline-flex;
		align-items: center;
		min-height: 44px;
		padding-block: 6px;
	}
}

/* The contact page's phone and email are the two most-tapped links on the site
   from a phone, and they sat at 20px inside their detail blocks. */
@media (max-width: 820px) {
	.bs-contact__block a {
		display: inline-flex;
		align-items: center;
		min-height: 44px;
		padding-block: 6px;
	}
}

/* ===========================================================================
 * SERVICES GRID (replaces the horizontal rail)
 *
 * The rail hid four of eight services behind a horizontal scroll. Even with
 * arrows and a progress line it did not read as scrollable, and services inside
 * a scroll container carry less weight than ones plainly on the page. The cards
 * keep their design; only the container changes.
 *
 * rail.js sees no overflow here and adds .bs-rail--static, which hides the
 * arrows and progress line on its own.
 * ======================================================================== */

.bs-rail__track,
.bs-rail__track > .e-con-inner {
	display: grid !important;
	grid-template-columns: repeat(4, 1fr);
	gap: 24px !important;
	overflow: visible !important;
	scroll-snap-type: none;
	padding-left: var(--space-gutter) !important;
	padding-right: var(--space-gutter) !important;
	max-width: var(--content-max);
	margin-inline: auto;
}

/* The mask existed to hint at content past the right edge. Nothing is off-screen
   now, so it would only dim the last column. */
.bs-rail__track {
	-webkit-mask-image: none;
	mask-image: none;
}

.bs-rail__card {
	flex: initial !important;
	width: auto !important;
	max-width: none !important;
	height: auto;
	min-height: 420px;
}

/* Fixed card height gave way to a ratio so cards align on a row regardless of
   how long a service name runs. */
.bs-rail__media {
	height: auto;
	flex: 0 0 auto;
	aspect-ratio: 4 / 3;
}

.bs-rail__copy {
	height: auto;
	flex: 1 1 auto;
	min-height: 150px;
}

@media (max-width: 1024px) {
	.bs-rail__track,
	.bs-rail__track > .e-con-inner {
		grid-template-columns: repeat(2, 1fr);
	}
}

@media (max-width: 600px) {
	.bs-rail__track,
	.bs-rail__track > .e-con-inner {
		grid-template-columns: 1fr;
	}

	.bs-rail__card {
		min-height: 0;
	}

	.bs-rail__media {
		aspect-ratio: 16 / 10;
	}
}

/* The arrow is pinned bottom-right, so the one-line description needs room or
   it runs underneath it. */
.bs-rail__line p {
	padding-right: 32px;
}

/* ===========================================================================
 * COVERAGE MAP (city pages only)
 *
 * The brief bans maps in the Service Area Band, and that holds. A city page is
 * a different question: someone is checking whether we come to them, and a map
 * answers it faster than a town list. Sharp corners and a hairline, like every
 * other framed element.
 * ======================================================================== */

.bs-map__frame {
	position: relative;
	margin-top: 2rem;
	border: 1px solid var(--line);
	/* Reserves height before the iframe loads so the map cannot shift the page
	   as it arrives. */
	aspect-ratio: 16 / 7;
	background-color: var(--mist);
}

.bs-map__frame iframe {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	border: 0;
	display: block;
}

.bs-map__note {
	margin-top: 1rem;
	font-size: 0.875rem;
	color: var(--slate);
	max-width: 70ch;
}

@media (max-width: 600px) {
	.bs-map__frame {
		aspect-ratio: 4 / 3;
	}
}

/* ===========================================================================
 * GRAVITY FORMS
 *
 * Gravity ships an opinionated theme with rounded inputs and its own palette.
 * These rules pull it onto the Blue Sky design system: sharp corners, hairline
 * borders, token colors, and inputs tall enough to tap.
 * ======================================================================== */

.bs-formband__lead p {
	max-width: 56ch;
}

.bs-formband .gform_wrapper {
	margin-top: 2rem;
	max-width: 760px;
}

.bs-formband .gform_wrapper .gfield_label {
	font-family: var(--font-body);
	font-weight: 600;
	font-size: 0.8125rem;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var(--ink);
	margin-bottom: 6px;
}

.bs-formband .gform_wrapper input[type="text"],
.bs-formband .gform_wrapper input[type="email"],
.bs-formband .gform_wrapper input[type="tel"],
.bs-formband .gform_wrapper select,
.bs-formband .gform_wrapper textarea {
	width: 100%;
	border: 1px solid var(--line) !important;
	border-radius: 0 !important;
	background-color: var(--paper);
	padding: 14px 16px !important;
	min-height: 48px;
	font-family: var(--font-body);
	font-size: 1rem;
	color: var(--ink);
	transition: border-color var(--dur-hover) ease-out;
}

.bs-formband .gform_wrapper textarea {
	min-height: 132px;
	resize: vertical;
}

.bs-formband .gform_wrapper input:focus,
.bs-formband .gform_wrapper select:focus,
.bs-formband .gform_wrapper textarea:focus {
	border-color: var(--sky) !important;
	outline: 2px solid var(--sky);
	outline-offset: -2px;
}

.bs-formband .gform_wrapper .gfield_required {
	color: var(--siren);
}

.bs-formband .gform_wrapper .gfield_description {
	font-size: 0.8125rem;
	color: var(--slate);
}

/* Submit button matches every other primary CTA on the site. */
.bs-formband .gform_wrapper .gform_button {
	background-color: var(--sky) !important;
	color: var(--paper) !important;
	border: 0 !important;
	border-radius: var(--radius-button) !important;
	font-family: var(--font-display);
	font-weight: 700;
	font-size: 0.9375rem;
	text-transform: uppercase;
	letter-spacing: 0.06em;
	padding: 16px 28px !important;
	min-height: 52px;
	cursor: pointer;
	transition: background-color var(--dur-hover) ease-out, transform var(--dur-hover) ease-out;
}

.bs-formband .gform_wrapper .gform_button:hover {
	background-color: var(--sky-deep) !important;
	transform: translateY(-2px);
}

/* Validation states use siren, which is otherwise reserved for emergencies;
   a failed submission is the one non-emergency case where that red is right. */
.bs-formband .gform_wrapper .gfield_error input,
.bs-formband .gform_wrapper .gfield_error select,
.bs-formband .gform_wrapper .gfield_error textarea {
	border-color: var(--siren) !important;
}

.bs-formband .gform_wrapper .validation_message {
	color: var(--siren);
	font-size: 0.8125rem;
}

@media (prefers-reduced-motion: reduce) {
	.bs-formband .gform_wrapper .gform_button:hover {
		transform: none;
	}
}

/* ===========================================================================
 * SERVICE CARD EQUAL HEIGHT
 *
 * Two separate problems. Grid rows size independently, so a two-line service
 * name in row one made that whole row taller than row two. And the card height
 * came from its content, so the midnight copy block stopped short of the card
 * bottom whenever a name ran to one line instead of two.
 * ======================================================================== */

.bs-rail__track,
.bs-rail__track > .e-con-inner {
	/* Every row matches the tallest row, not just the tallest card in it. */
	grid-auto-rows: 1fr;
	align-items: stretch;
}

.bs-rail__card {
	height: 100% !important;
	min-height: 0;
}

/* The copy block takes whatever height the photo leaves, so the dark ground
   always reaches the bottom edge regardless of how long the name runs.
   Elementor sets flex-grow on its containers with higher specificity than a
   shorthand, so this computed to 0 and cards with a one-line service name left
   a gap between the copy block and the card edge. */
.bs-rail__copy {
	flex-grow: 1 !important;
	flex-shrink: 1 !important;
	flex-basis: auto !important;
	min-height: 0;
	display: flex;
	flex-direction: column;
	justify-content: flex-start;
}

/* The photo keeps its ratio and never absorbs the leftover space. */
.bs-rail__media {
	flex-grow: 0 !important;
	flex-shrink: 0 !important;
}

/* Push the arrow to the bottom rather than pinning it absolutely, so it sits
   correctly whatever the card height. */
.bs-rail__copy > .elementor-widget-html:last-child {
	margin-top: auto;
}

.bs-rail__arrow {
	position: static;
	display: block;
	text-align: right;
}

.bs-rail__line p {
	padding-right: 0;
}

/* ===========================================================================
 * GLOBAL CTA BAND
 *
 * Renders on every page from the footer template. Copy on the left, short form
 * on the right, so the ask is visible without scrolling past a wall of fields.
 * ======================================================================== */

.bs-ctaband__grid {
	display: grid;
	grid-template-columns: 1fr 1fr;
	gap: 64px;
	align-items: start;
}

.bs-ctaband__copy h2 {
	color: var(--paper);
	margin: 0.3em 0 0.6em;
	max-width: 16ch;
}

.bs-ctaband__lead {
	color: rgba(255, 255, 255, 0.82);
	max-width: 46ch;
	margin: 0 0 1.5rem;
}

.bs-ctaband__points {
	list-style: none;
	margin: 0 0 1.75rem;
	padding: 0;
}

.bs-ctaband__points li {
	position: relative;
	padding: 0.6rem 0 0.6rem 1.5rem;
	border-top: 1px solid var(--line-on-dark);
	color: rgba(255, 255, 255, 0.82);
	font-size: 0.9375rem;
}

.bs-ctaband__points li::before {
	content: "";
	position: absolute;
	left: 0;
	top: 1.15em;
	width: 12px;
	height: 2px;
	background-color: var(--sky);
}

.bs-ctaband__phone {
	display: inline-flex;
	align-items: center;
	min-height: 44px;
	font-family: var(--font-display);
	font-weight: 700;
	font-size: 0.9375rem;
	text-transform: uppercase;
	letter-spacing: 0.06em;
	color: var(--sky) !important;
	text-decoration: none;
}

/* The form sits on paper so the fields read clearly against the dark band. */
.bs-ctaband__form {
	background-color: var(--paper);
	padding: 32px;
}

.bs-ctaband__form .gform_wrapper {
	margin: 0;
}

.bs-ctaband__form .gfield_label {
	font-family: var(--font-body);
	font-weight: 600;
	font-size: 0.75rem;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var(--ink);
	margin-bottom: 5px;
}

.bs-ctaband__form input[type="text"],
.bs-ctaband__form input[type="tel"],
.bs-ctaband__form input[type="email"] {
	width: 100%;
	border: 1px solid var(--line) !important;
	border-radius: 0 !important;
	padding: 13px 15px !important;
	min-height: 48px;
	font-family: var(--font-body);
	font-size: 1rem;
	color: var(--ink);
	background-color: var(--paper);
}

.bs-ctaband__form input:focus {
	border-color: var(--sky) !important;
	outline: 2px solid var(--sky);
	outline-offset: -2px;
}

.bs-ctaband__form .gform_button {
	width: 100%;
	background-color: var(--sky) !important;
	color: var(--paper) !important;
	border: 0 !important;
	border-radius: var(--radius-button) !important;
	font-family: var(--font-display);
	font-weight: 700;
	font-size: 0.9375rem;
	text-transform: uppercase;
	letter-spacing: 0.06em;
	padding: 16px 24px !important;
	min-height: 52px;
	cursor: pointer;
	transition: background-color var(--dur-hover) ease-out;
}

.bs-ctaband__form .gform_button:hover {
	background-color: var(--sky-deep) !important;
}

.bs-ctaband__form .gfield_required {
	color: var(--siren);
}

.bs-ctaband__form .validation_message {
	color: var(--siren);
	font-size: 0.8125rem;
}

/* The Contact page already carries the full form; a second one directly above
   the footer would be asking twice on the same screen. */
.page-id-93 .bs-ctaband {
	display: none;
}

@media (max-width: 1024px) {
	.bs-ctaband__grid {
		grid-template-columns: 1fr;
		gap: 40px;
	}
}

@media (max-width: 600px) {
	.bs-ctaband__form {
		padding: 24px 20px;
	}
}

/* Gravity sets its own button width, so the full-width rule needs forcing. A
   full-width submit reads as the obvious next step in a narrow form column. */
.bs-ctaband__form .gform_button,
.bs-ctaband__form .gform_footer input[type="submit"] {
	width: 100% !important;
	display: block;
}

.bs-ctaband__form .gform_footer {
	margin-top: 8px;
	padding: 0;
}

/* ===========================================================================
 * COUPON OFFERS
 *
 * Sharp cards with the amount doing the shouting, since that is what someone
 * scanning the page is looking for.
 * ======================================================================== */

.bs-offers__grid {
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	gap: 24px;
	margin-top: 2rem;
}

.bs-offer {
	border: 1px solid var(--line);
	border-top: 4px solid var(--sky);
	padding: 32px 28px;
	background-color: var(--paper);
	display: flex;
	flex-direction: column;
}

.bs-offer__amount {
	font-family: var(--font-display);
	font-weight: 900;
	font-size: clamp(2.75rem, 5vw, 4rem);
	line-height: 0.9;
	letter-spacing: -0.03em;
	color: var(--sky);
	margin: 0 0 0.4rem;
}

.bs-offer__title {
	font-size: 1.0625rem;
	margin: 0 0 0.6rem;
	color: var(--ink);
}

.bs-offer__body {
	margin: 0;
	font-size: 0.9375rem;
	color: var(--slate);
}

.bs-terms {
	border-top: 1px solid var(--line);
	padding-top: 24px;
	max-width: 72ch;
}

.bs-terms h3 {
	font-size: 1rem;
	margin: 0 0 0.5rem;
}

.bs-terms p {
	font-size: 0.9375rem;
	margin: 0 0 0.75rem;
}

.bs-supplies__note {
	margin-top: 1.5rem;
	font-size: 0.9375rem;
	color: var(--slate);
	max-width: 68ch;
}

@media (max-width: 900px) {
	.bs-offers__grid {
		grid-template-columns: 1fr;
	}
}

/* ===========================================================================
 * BLOG ARCHIVE AND SINGLE POST
 *
 * Hello Elementor outputs a bare loop: .site-main > .page-header + .post
 * articles. These pull it onto the design system as a card list, since building
 * full Theme Builder archive and single templates is a larger job than the
 * content warrants right now.
 * ======================================================================== */

.blog .site-main,
.single-post .site-main,
.archive .site-main {
	max-width: var(--content-max);
	margin-inline: auto;
	padding: clamp(56px, 7vw, 96px) var(--space-gutter);
}

/* Archive header, styled like a section eyebrow plus H1 rather than a bare
   "Archives" string. */
.blog .page-header,
.archive .page-header {
	padding-bottom: 32px;
	margin-bottom: 8px;
	border-bottom: 1px solid var(--line);
}

.blog .page-header .entry-title,
.archive .page-header .entry-title {
	font-family: var(--font-display);
	font-weight: 900;
	font-size: clamp(2.25rem, 4.5vw, 3.5rem);
	letter-spacing: -0.03em;
	color: var(--ink);
	margin: 0;
}

/* Each post becomes a row with a hairline rule, not a giant blue link. */
.blog .site-main .post,
.archive .site-main .post {
	padding: 32px 0;
	border-bottom: 1px solid var(--line);
}

.blog .site-main .post .entry-title,
.archive .site-main .post .entry-title {
	font-family: var(--font-display);
	font-weight: 800;
	font-size: clamp(1.25rem, 2vw, 1.625rem);
	line-height: 1.2;
	letter-spacing: -0.015em;
	margin: 0 0 0.5rem;
	max-width: 30ch;
}

.blog .site-main .post .entry-title a,
.archive .site-main .post .entry-title a {
	color: var(--ink) !important;
	text-decoration: none;
	transition: color var(--dur-hover) ease-out;
}

.blog .site-main .post .entry-title a:hover,
.archive .site-main .post .entry-title a:hover {
	color: var(--sky) !important;
}

.blog .site-main .post .page-content,
.archive .site-main .post .page-content {
	font-size: 0.9375rem;
	color: var(--slate);
	max-width: 72ch;
}

.blog .site-main .post .page-content p {
	margin: 0;
}

/* Pagination as square, sharp controls consistent with the rail buttons. */
.pagination {
	display: flex;
	gap: 8px;
	margin-top: 40px;
}

.pagination a,
.pagination .page-numbers {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-width: 48px;
	min-height: 48px;
	padding: 0 14px;
	border: 1px solid var(--line);
	color: var(--ink) !important;
	text-decoration: none;
	font-family: var(--font-display);
	font-weight: 700;
	font-size: 0.875rem;
}

.pagination a:hover {
	background-color: var(--midnight);
	color: var(--paper) !important;
	border-color: var(--midnight);
}

/* ---- Single post ------------------------------------------------------ */

.single-post .site-main .entry-title {
	font-family: var(--font-display);
	font-weight: 900;
	font-size: clamp(2rem, 4vw, 3.25rem);
	line-height: 1.05;
	letter-spacing: -0.03em;
	color: var(--ink);
	max-width: 24ch;
	margin: 0 0 24px;
}

/* Migrated posts are 2015 to 2017 prose written for a different template, so
   the reading measure matters more than usual. */
.single-post .site-main .page-content {
	max-width: 72ch;
}

.single-post .site-main .page-content p,
.single-post .site-main .page-content li {
	font-size: 1.0625rem;
	line-height: 1.75;
	color: var(--slate);
}

.single-post .site-main .page-content h2,
.single-post .site-main .page-content h3 {
	margin-top: 2em;
	margin-bottom: 0.5em;
	color: var(--ink);
}

.single-post .site-main .page-content a {
	color: var(--sky);
	text-decoration: underline;
	text-underline-offset: 2px;
}

.single-post .site-main .page-content img {
	max-width: 100%;
	height: auto;
	margin: 2rem 0;
	border: 1px solid var(--line);
}

.single-post .site-main .page-content ul,
.single-post .site-main .page-content ol {
	padding-left: 1.25rem;
	margin: 1.25rem 0;
}

.single-post .site-main .page-content li {
	margin-bottom: 0.5rem;
}

/* ===========================================================================
 * SINGLE POST TEMPLATE
 *
 * The Elementor template is a shell holding one shortcode; all of this markup
 * comes from template-parts/single.php. The shell has to keep existing because
 * Elementor Pro groups error-404 templates into the "single" location, so with
 * no competing single template the 404 renders on every blog post.
 * ======================================================================== */

/* The shortcode widget sits inside Elementor's own wrappers, which add width
   and padding this layout supplies itself. */
.bs-postshell,
.bs-postshell .elementor-widget-shortcode,
.bs-postshell .elementor-shortcode {
	width: 100%;
	max-width: none;
	padding: 0;
	margin: 0;
}

/* --- header ------------------------------------------------------------- */

.bs-postheader__inner {
	max-width: var(--content-max);
	margin-inline: auto;
	padding: 88px var(--space-gutter) 72px;
}

.bs-postheader__back {
	color: var(--sky);
	text-decoration: none;
	transition: color 0.18s ease;
}

.bs-postheader__back:hover {
	color: var(--paper);
}

.bs-postheader__title {
	font-family: var(--font-display);
	font-weight: 900;
	font-size: clamp(2rem, 4.4vw, 3.5rem);
	line-height: 1.04;
	letter-spacing: -0.03em;
	color: var(--paper);
	max-width: 20ch;
	margin: 0.35em 0 0;
}

.bs-postheader__meta {
	display: flex;
	flex-wrap: wrap;
	gap: 0.6rem;
	align-items: center;
	margin: 1.5rem 0 0;
	font-size: 0.75rem;
	font-weight: 600;
	letter-spacing: 0.14em;
	text-transform: uppercase;
	color: rgba(255, 255, 255, 0.62);
}

.bs-postheader__meta time {
	color: var(--sky);
}

/* --- featured image ----------------------------------------------------- */

/* Pulled up into the midnight band so the photo bridges the header and the
   body rather than sitting as a third stripe. */
.bs-postfeature__inner {
	max-width: var(--content-max);
	margin-inline: auto;
	padding: 0 var(--space-gutter);
	margin-top: -48px;
	position: relative;
	z-index: 1;
}

.bs-postfeature {
	background: linear-gradient(to bottom, var(--midnight) 0, var(--midnight) 48px, var(--paper) 48px);
}

.bs-postfeature__inner img {
	display: block;
	width: 100%;
	height: auto;
	aspect-ratio: 16 / 9;
	object-fit: cover;
	border: 1px solid var(--line);
}

/* --- body --------------------------------------------------------------- */

.bs-postbody__inner {
	max-width: var(--content-max);
	margin-inline: auto;
	padding: 72px var(--space-gutter) 96px;
	display: grid;
	grid-template-columns: minmax(0, 1fr) 340px;
	gap: 64px;
	align-items: start;
}

/* Migrated posts are 2015 to 2017 prose written for a different template, so
   the reading measure does the heavy lifting. */
.bs-postbody__content {
	max-width: 68ch;
}

/* The opening paragraph carries the article, so it gets set larger than the
   rest. Only when it genuinely leads: many migrated posts open on a subheading
   instead, and enlarging the paragraph beneath one reads as a mistake. */
.bs-postbody__content > p:first-child {
	font-size: 1.25rem;
	line-height: 1.6;
	color: var(--ink);
}

.bs-postbody__content p,
.bs-postbody__content li {
	font-size: 1.0625rem;
	line-height: 1.75;
	color: var(--slate);
}

.bs-postbody__content h2,
.bs-postbody__content h3,
.bs-postbody__content h4 {
	font-family: var(--font-display);
	font-weight: 800;
	letter-spacing: -0.02em;
	color: var(--ink);
	margin-top: 2.2em;
	margin-bottom: 0.5em;
}

/* The migrated posts start their sections at h3, not h2, so the top-level
   section treatment has to cover both or the rules land on nothing. Checked
   against the rendered DOM rather than assumed. */
.bs-postbody__content h2,
.bs-postbody__content h3 {
	font-size: clamp(1.375rem, 2.4vw, 1.75rem);
	line-height: 1.15;
	padding-top: 1.75rem;
	border-top: 1px solid var(--line);
}

.bs-postbody__content > :is(h2, h3):first-child {
	padding-top: 0;
	border-top: 0;
	margin-top: 0;
}

.bs-postbody__content h4 {
	font-size: 1.125rem;
	line-height: 1.3;
	margin-top: 1.8em;
}

.bs-postbody__content a {
	color: var(--sky-deep);
	text-decoration: underline;
	text-underline-offset: 3px;
	text-decoration-thickness: 1px;
}

.bs-postbody__content a:hover {
	color: var(--sky);
}

.bs-postbody__content img {
	max-width: 100%;
	height: auto;
	margin: 2.5rem 0;
	border: 1px solid var(--line);
}

.bs-postbody__content ul,
.bs-postbody__content ol {
	padding-left: 1.25rem;
	margin: 1.5rem 0;
}

.bs-postbody__content li {
	margin-bottom: 0.6rem;
	padding-left: 0.25rem;
}

.bs-postbody__content li::marker {
	color: var(--sky);
}

.bs-postbody__content strong {
	color: var(--ink);
	font-weight: 600;
}

.bs-postbody__content blockquote {
	margin: 2.5rem 0;
	padding: 0 0 0 1.75rem;
	border-left: 3px solid var(--sky);
}

.bs-postbody__content blockquote p {
	font-family: var(--font-display);
	font-size: 1.375rem;
	font-weight: 700;
	line-height: 1.35;
	letter-spacing: -0.02em;
	color: var(--ink);
}

/* --- in-article CTA ----------------------------------------------------- */

/* Sticky rather than parked at the foot of the article: these posts run long,
   and the moment someone decides to call is usually mid-read. */
.bs-postcta {
	position: sticky;
	top: 96px;
	background-color: var(--midnight);
	color: var(--paper);
	padding: 36px 32px 40px;
}

.bs-postcta__eyebrow {
	margin: 0;
	font-size: 0.6875rem;
	font-weight: 600;
	letter-spacing: 0.16em;
	text-transform: uppercase;
	color: var(--sky);
}

/* The kit's global h2 typography enqueues after the theme and wins outright:
   without these it renders ink-on-midnight at 48px, which is invisible. */
.bs-postcta__h2 {
	font-family: var(--font-display) !important;
	font-weight: 800 !important;
	font-size: 1.5rem !important;
	line-height: 1.15 !important;
	letter-spacing: -0.02em;
	color: var(--paper) !important;
	margin: 0.5em 0 0.4em;
}

.bs-postcta__lead {
	font-size: 0.9375rem;
	line-height: 1.6;
	color: rgba(255, 255, 255, 0.72);
	margin: 0 0 1.75rem;
}

.bs-postcta__actions {
	display: flex;
	flex-direction: column;
	gap: 12px;
}

/* The Elementor kit sets a global link colour of sky and enqueues after the
   theme, which paints the primary button's label sky-on-sky. Same fight as
   every other CTA on the site, same remedy. */
.bs-postcta__actions .bs-btn {
	width: 100%;
	text-align: center;
	text-decoration: none;
}

.bs-postcta__actions .bs-btn--primary {
	color: var(--paper) !important;
}

.bs-postcta__actions .bs-btn--ghost {
	color: var(--paper) !important;
}

/* --- related ------------------------------------------------------------ */

.bs-related {
	border-top: 1px solid var(--line);
}

.bs-related__inner {
	max-width: var(--content-max);
	margin-inline: auto;
	padding: 88px var(--space-gutter) 96px;
}

.bs-related__h2 {
	font-family: var(--font-display) !important;
	font-weight: 800 !important;
	font-size: clamp(1.75rem, 3vw, 2.5rem) !important;
	line-height: 1.1 !important;
	letter-spacing: -0.03em;
	color: var(--ink) !important;
	margin: 0.3em 0 2rem;
}

/* --- responsive --------------------------------------------------------- */

@media (max-width: 1024px) {
	/* The sidebar has nowhere useful to sit once the measure narrows, so the
	   CTA becomes a full-width block after the article. */
	.bs-postbody__inner {
		grid-template-columns: minmax(0, 1fr);
		gap: 56px;
	}

	.bs-postcta {
		position: static;
		max-width: 68ch;
	}

	.bs-postcta__actions {
		flex-direction: row;
		flex-wrap: wrap;
	}

	.bs-postcta__actions .bs-btn {
		width: auto;
		flex: 1 1 220px;
	}
}

@media (max-width: 768px) {
	.bs-postheader__inner {
		padding: 56px var(--space-gutter) 56px;
	}

	.bs-postfeature__inner img {
		aspect-ratio: 3 / 2;
	}

	.bs-postbody__inner {
		padding: 48px var(--space-gutter) 64px;
	}

	.bs-related__inner {
		padding: 56px var(--space-gutter) 64px;
	}
}

/* ===========================================================================
 * 404
 *
 * The last page still carrying Ferguson's classes, which is why its button
 * rendered sunbeam while every other CTA is sky. Worth designing rather than
 * inheriting: someone who mistyped a URL still has a leaking pipe.
 * ======================================================================== */

.bs-404__h1 .elementor-heading-title {
	color: var(--paper);
	max-width: 18ch;
	margin: 0.2em 0 0.4em;
}

.bs-404__lead p {
	color: rgba(255, 255, 255, 0.82);
	max-width: 52ch;
}

.bs-404__links {
	border-top: 1px solid var(--line-on-dark);
	padding-top: 24px;
	margin-top: 8px;
}

.bs-404__linkhead {
	font-size: 0.6875rem;
	font-weight: 600;
	letter-spacing: 0.16em;
	text-transform: uppercase;
	color: var(--sky);
	margin: 0 0 14px;
}

.bs-404__link {
	display: inline-flex;
	align-items: center;
	min-height: 44px;
	margin: 0 24px 4px 0;
	color: var(--paper) !important;
	text-decoration: none;
	font-size: 0.9375rem;
	border-bottom: 1px solid transparent;
	transition: border-color var(--dur-hover) ease-out, color var(--dur-hover) ease-out;
}

.bs-404__link:hover {
	color: var(--sky) !important;
	border-bottom-color: var(--sky);
}

/* Any tel: link is a primary action on a phone, so give them all real hit area
   rather than patching each context individually as it turns up. */
@media (max-width: 820px) {
	a[href^="tel:"],
	a[href^="mailto:"] {
		display: inline-flex;
		align-items: center;
		min-height: 44px;
	}

	/* The utility bar is a thin strip; 32px keeps it tappable without doubling
	   the bar's height. */
	.bs-utility__inner a[href^="tel:"] {
		min-height: 32px;
	}
}

/* ===========================================================================
 * PPC LANDING PAGES
 *
 * A deliberate deviation from the brief, which has no landing-page archetype.
 * Paid traffic arrived from a specific ad with specific intent and no interest
 * in browsing, so the form sits above the fold and the page states one offer.
 * ======================================================================== */

.bs-lp__grid {
	display: grid;
	grid-template-columns: 1.05fr 0.95fr;
	gap: 56px;
	align-items: start;
}

.bs-lp__h1 {
	font-family: var(--font-display);
	font-weight: 900;
	font-size: clamp(2rem, 3.8vw, 3.25rem);
	line-height: 1.03;
	letter-spacing: -0.03em;
	color: var(--paper);
	margin: 0.25em 0 0.5em;
	max-width: 18ch;
}

.bs-lp__lead {
	color: rgba(255, 255, 255, 0.84);
	max-width: 48ch;
	margin: 0 0 1.5rem;
}

.bs-lp__points {
	list-style: none;
	margin: 0 0 1.75rem;
	padding: 0;
}

.bs-lp__points li {
	position: relative;
	padding: 0.55rem 0 0.55rem 1.5rem;
	border-top: 1px solid var(--line-on-dark);
	color: rgba(255, 255, 255, 0.84);
	font-size: 0.9375rem;
}

.bs-lp__points li::before {
	content: "";
	position: absolute;
	left: 0;
	top: 1.1em;
	width: 12px;
	height: 2px;
	background-color: var(--sky);
}

/* Trust markers sit directly under the ask, where they answer the hesitation
   that stops someone filling in a form for a trade they have not used. */
.bs-lp__trust {
	display: flex;
	flex-wrap: wrap;
	gap: 8px 28px;
	padding: 16px 0;
	border-top: 1px solid var(--line-on-dark);
	border-bottom: 1px solid var(--line-on-dark);
	font-size: 0.8125rem;
	color: rgba(255, 255, 255, 0.7);
}

.bs-lp__trust strong {
	color: var(--paper);
	font-family: var(--font-display);
}

.bs-lp__phone {
	display: inline-flex;
	align-items: center;
	min-height: 44px;
	margin-top: 14px;
	font-family: var(--font-display);
	font-weight: 700;
	font-size: 0.9375rem;
	text-transform: uppercase;
	letter-spacing: 0.06em;
	color: var(--sky) !important;
	text-decoration: none;
}

.bs-lp__form {
	background-color: var(--paper);
	padding: 32px;
}

.bs-lp__formhead {
	font-family: var(--font-display);
	font-weight: 800;
	font-size: 1.125rem;
	color: var(--ink);
	margin: 0 0 18px;
}

/* Gravity styling, matched to the global CTA form. */
.bs-lp__form .gform_wrapper { margin: 0; }

.bs-lp__form .gfield_label {
	font-family: var(--font-body);
	font-weight: 600;
	font-size: 0.75rem;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var(--ink);
	margin-bottom: 5px;
}

.bs-lp__form input[type="text"],
.bs-lp__form input[type="tel"],
.bs-lp__form input[type="email"] {
	width: 100%;
	border: 1px solid var(--line) !important;
	border-radius: 0 !important;
	padding: 13px 15px !important;
	min-height: 48px;
	font-family: var(--font-body);
	font-size: 1rem;
	color: var(--ink);
}

.bs-lp__form input:focus {
	border-color: var(--sky) !important;
	outline: 2px solid var(--sky);
	outline-offset: -2px;
}

.bs-lp__form .gform_button,
.bs-lp__form .gform_footer input[type="submit"] {
	width: 100% !important;
	display: block;
	background-color: var(--sky) !important;
	color: var(--paper) !important;
	border: 0 !important;
	border-radius: var(--radius-button) !important;
	font-family: var(--font-display);
	font-weight: 700;
	font-size: 0.9375rem;
	text-transform: uppercase;
	letter-spacing: 0.06em;
	padding: 16px 24px !important;
	min-height: 52px;
	cursor: pointer;
}

.bs-lp__form .gform_button:hover { background-color: var(--sky-deep) !important; }
.bs-lp__form .gfield_required { color: var(--siren); }
.bs-lp__form .validation_message { color: var(--siren); font-size: 0.8125rem; }

.bs-lpproof__grid {
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	gap: 32px;
}

.bs-lpproof__grid strong {
	display: block;
	font-family: var(--font-display);
	font-size: 1.0625rem;
	color: var(--ink);
	margin-bottom: 6px;
}

.bs-lpproof__grid p {
	margin: 0;
	font-size: 0.9375rem;
}

/* ===========================================================================
 * THANK YOU
 * ======================================================================== */

.bs-thanks__h1 .elementor-heading-title {
	color: var(--paper);
	max-width: 18ch;
	margin: 0.2em 0 0.4em;
}

.bs-thanks__lead p {
	color: rgba(255, 255, 255, 0.84);
	max-width: 56ch;
}

.bs-thanks__next {
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	gap: 32px;
	margin: 2.5rem 0;
	padding-top: 32px;
	border-top: 1px solid var(--line-on-dark);
}

.bs-thanks__num {
	display: block;
	font-family: var(--font-display);
	font-weight: 900;
	font-size: 2rem;
	line-height: 1;
	color: var(--sky);
	opacity: 0.4;
	margin-bottom: 10px;
}

.bs-thanks__next strong {
	display: block;
	font-family: var(--font-display);
	font-size: 1.0625rem;
	color: var(--paper);
	margin-bottom: 6px;
}

.bs-thanks__next p {
	margin: 0;
	font-size: 0.9375rem;
	color: rgba(255, 255, 255, 0.78);
}

.bs-thanks__urgent {
	border-left: 4px solid var(--siren);
	padding: 16px 20px;
	background-color: var(--card-on-dark);
}

.bs-thanks__urgent p { margin: 0; color: rgba(255, 255, 255, 0.9); }
.bs-thanks__urgent a { color: var(--sky) !important; }

@media (max-width: 1024px) {
	.bs-lp__grid { grid-template-columns: 1fr; gap: 36px; }
	.bs-lpproof__grid,
	.bs-thanks__next { grid-template-columns: 1fr; gap: 24px; }
}

/* ===========================================================================
 * L. NUMERAL STRIP
 *
 * Oversized figures on a flat band, divided by hairlines. Sits under the
 * statement band, which on its own was a headline and one line and read thin
 * between the hero and the services grid.
 * ======================================================================== */

.bs-stats__row {
	display: flex;
	flex-wrap: wrap;
	list-style: none;
	margin: 0;
	padding: 0;
}

.bs-stat {
	display: flex;
	flex-direction: column;
	flex: 1 1 25%;
	padding: 0 32px;
	border-left: 1px solid var(--line);
}

.bs-stat:first-child {
	padding-left: 0;
	border-left: 0;
}

.bs-stat__n {
	font-family: var(--font-display);
	font-weight: 900;
	font-size: clamp(2.5rem, 5vw, 4.5rem);
	line-height: 0.9;
	letter-spacing: -0.04em;
	color: var(--midnight);
}

.bs-stat__k {
	margin-top: 14px;
	font-size: 0.75rem;
	font-weight: 600;
	letter-spacing: 0.18em;
	text-transform: uppercase;
	color: var(--sky);
}

.bs-stat__d {
	margin-top: 10px;
	font-size: 0.875rem;
	line-height: 1.6;
	color: var(--slate);
}

/* ===========================================================================
 * COVERAGE MAP
 *
 * Sits above the emergency band. The brief's ban on maps inside the Service
 * Area Band still holds; this is a separate section that answers "do you come
 * to me?" visually, after the town list has answered it in text.
 * ======================================================================== */

.bs-covermap__h2 .elementor-heading-title {
	max-width: 20ch;
	margin: 0.3em 0 0;
}

.bs-covermap__frame {
	position: relative;
	margin-top: 2rem;
	border: 1px solid var(--line);
	aspect-ratio: 16 / 8;
	background-color: var(--mist);
}

.bs-covermap__frame iframe {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	border: 0;
	display: block;
}

.bs-covermap__legend {
	display: grid;
	grid-template-columns: repeat(4, 1fr);
	gap: 24px;
	margin-top: 28px;
}

.bs-covermap__legend div {
	padding-top: 14px;
	border-top: 2px solid var(--sky);
}

.bs-covermap__legend strong {
	display: block;
	font-family: var(--font-body);
	font-size: 0.6875rem;
	font-weight: 600;
	letter-spacing: 0.16em;
	text-transform: uppercase;
	color: var(--ink);
	margin-bottom: 8px;
}

.bs-covermap__legend span {
	font-size: 0.875rem;
	color: var(--slate);
	line-height: 1.6;
}

.bs-covermap__note {
	margin-top: 24px;
	font-size: 0.9375rem;
	color: var(--slate);
	max-width: 68ch;
}

/* ===========================================================================
 * FOOTER LAYOUT
 *
 * Brand, address and Get Help stack on the left; the three navigation columns
 * sit right. Get Help was a fourth column pushed hard right, which left the
 * brand block stranded on its own.
 * ======================================================================== */

.bs-foot__top {
	display: grid;
	grid-template-columns: minmax(280px, 1fr) 2.2fr;
	gap: 56px;
	align-items: start;
}

.bs-foot__brand {
	display: flex;
	flex-direction: column;
	gap: 24px;
}

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

.bs-foot__help li {
	margin-bottom: 9px;
}

.bs-foot__help a {
	color: rgba(255, 255, 255, 0.82);
	text-decoration: none;
	font-size: 0.9375rem;
}

.bs-foot__help a:hover {
	color: var(--paper);
}

/* Three columns now, not four. */
.bs-foot__cols {
	grid-template-columns: repeat(3, 1fr);
	padding-top: 0;
}

@media (max-width: 1024px) {
	.bs-stat {
		flex: 1 1 50%;
		padding: 24px 24px 24px 0;
		border-left: 0;
		border-top: 1px solid var(--line);
	}

	.bs-stat:first-child {
		border-top: 1px solid var(--line);
	}

	.bs-covermap__legend {
		grid-template-columns: repeat(2, 1fr);
	}

	.bs-foot__top {
		grid-template-columns: 1fr;
		gap: 40px;
	}

	.bs-foot__cols {
		grid-template-columns: repeat(2, 1fr);
	}
}

@media (max-width: 600px) {
	.bs-stat {
		flex: 1 1 100%;
	}

	.bs-covermap__legend {
		grid-template-columns: 1fr;
	}

	.bs-covermap__frame {
		aspect-ratio: 4 / 3;
	}

	.bs-foot__cols {
		grid-template-columns: 1fr;
	}
}

/* Drive times per city, borrowed from a competitor who shows response time
   beside each area. It works because it answers the real question, "how long
   until someone is here", with a number rather than a claim. Ours are the
   genuine drive times from the content record, not invented. */
.bs-covermap__col h3 {
	font-family: var(--font-body);
	font-size: 0.6875rem;
	font-weight: 600;
	letter-spacing: 0.16em;
	text-transform: uppercase;
	color: var(--ink);
	margin: 0 0 10px;
	padding-top: 14px;
	border-top: 2px solid var(--sky);
}

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

.bs-covermap__col li {
	border-bottom: 1px solid var(--line);
}

.bs-covermap__col a {
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	gap: 12px;
	padding: 9px 0;
	min-height: 40px;
	text-decoration: none;
	transition: color var(--dur-hover) ease-out;
}

.bs-covermap__city {
	font-size: 0.9375rem;
	font-weight: 500;
	color: var(--ink);
}

.bs-covermap__drive {
	font-family: var(--font-display);
	font-weight: 700;
	font-size: 0.8125rem;
	color: var(--sky);
	white-space: nowrap;
}

.bs-covermap__col a:hover .bs-covermap__city {
	color: var(--sky);
}

@media (max-width: 820px) {
	.bs-covermap__col a {
		min-height: 44px;
	}
}

/* Get Help moved out of the column grid, so it missed the touch-target rule
   that covers .bs-foot__col links. */
@media (max-width: 820px) {
	.bs-foot__help li {
		margin-bottom: 0;
	}

	.bs-foot__help a {
		display: flex;
		align-items: center;
		min-height: 44px;
		padding-block: 4px;
	}
}

/* ===========================================================================
 * SERVICE AREA BAND WITH MAP
 *
 * The map now lives inside "Where We Work" rather than as its own section, so
 * the coverage question is answered in one place: map on the left, towns and
 * drive times on the right.
 * ======================================================================== */

.bs-areas__lead p {
	max-width: 60ch;
	color: rgba(255, 255, 255, 0.82);
	margin: 0 0 2rem;
}

.bs-areas__split {
	display: grid;
	grid-template-columns: 1fr 1.15fr;
	gap: 48px;
	align-items: start;
	margin-bottom: 2.5rem;
}

.bs-areas__map {
	position: relative;
}

.bs-areas__map iframe {
	width: 100%;
	aspect-ratio: 4 / 3;
	border: 1px solid var(--line-on-dark);
	display: block;
	background-color: var(--mist);
}

.bs-areas__maplabel {
	margin: 12px 0 0;
	font-size: 0.75rem;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: rgba(255, 255, 255, 0.6);
}

/* Two columns of counties beside the map, four across on wide screens would
   squeeze the town names. */
.bs-areas__grid {
	display: grid;
	grid-template-columns: repeat(2, 1fr);
	gap: 20px 32px;
}

.bs-areas__col h3 {
	font-size: 0.6875rem;
	letter-spacing: 0.16em;
	text-transform: uppercase;
	color: var(--paper);
	margin: 0 0 8px;
	padding-top: 12px;
	border-top: 2px solid var(--sky);
}

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

.bs-areas__col li {
	border-bottom: 1px solid var(--line-on-dark);
}

.bs-areas__col a {
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	gap: 12px;
	padding: 8px 0;
	min-height: 38px;
	text-decoration: none;
}

.bs-areas__city {
	font-size: 0.9375rem;
	font-weight: 500;
	color: var(--paper);
}

.bs-areas__drive {
	font-family: var(--font-display);
	font-weight: 700;
	font-size: 0.8125rem;
	color: var(--sky);
	white-space: nowrap;
}

.bs-areas__col a:hover .bs-areas__city {
	color: var(--sky);
}

/* ===========================================================================
 * FOOTER: HORIZONTAL GET HELP, FULL-BLEED TAIL
 * ======================================================================== */

/* Get Help reads as a row of links under the address rather than a stacked
   list, which balances the brand block. */
.bs-foot__help ul {
	display: flex;
	flex-wrap: wrap;
	gap: 8px 28px;
}

.bs-foot__help li {
	margin-bottom: 0;
}

/* The tail escapes the 1360px content column so its rules and the wordmark
   reach the viewport edges at any width. */
.bs-foot__wide {
	position: relative;
	width: 100vw;
	/* margin-inline, not margin-left. With only the left side offset the 100vw
	   block is not centred against its padded parent, which pushed content off
	   the left edge of the viewport. */
	margin-inline: calc(50% - 50vw);
	overflow: hidden;
}

/* The wrapper carries no horizontal padding, so each child's top border runs
   the full viewport width while its content stays inset by the gutter. Padding
   the wrapper instead would inset the rules too, which is what stopped them
   short of the edges. */
.bs-foot__wide .bs-foot__badges,
.bs-foot__wide .bs-foot__bar {
	max-width: none;
	padding-inline: var(--space-gutter);
}

.bs-foot__wide .bs-foot__wordmark {
	position: static;
	transform: none;
	display: block;
	margin-top: 24px;
	text-align: center;
	/* Escapes the wrapper's gutter so the wordmark reaches the true viewport
	   edges rather than stopping at the padding. */
	width: 100vw;
	margin-inline: calc(50% - 50vw);
	/* Calibrated by measurement, not guessed: at 10.2vw the rendered text was
	   1.14x the viewport and got cropped mid-word. 8.9vw makes "BLUE SKY
	   PLUMBING" span almost exactly edge to edge at every width. */
	font-size: clamp(1.75rem, 8.9vw, 20rem);
	line-height: 0.85;
	letter-spacing: -0.02em;
	white-space: nowrap;
	overflow: hidden;
}

@media (max-width: 1024px) {
	.bs-areas__split {
		grid-template-columns: 1fr;
		gap: 32px;
	}
}

@media (max-width: 600px) {
	.bs-areas__grid {
		grid-template-columns: 1fr;
	}

	.bs-foot__help ul {
		flex-direction: column;
		gap: 0;
	}
}

/* Elementor stretches a button to its container when it is the only child;
   the areas CTA should sit at its natural width. */
.bs-areas__inner .elementor-widget-button {
	max-width: max-content;
}

.bs-areas__inner .elementor-widget-button .elementor-button {
	width: auto;
}

/* The bottom bar's privacy link is the last small target left; it sits in a
   flex row of spans so it never inherited a link rule. */
@media (max-width: 820px) {
	.bs-foot__bar a {
		display: inline-flex;
		align-items: center;
		min-height: 44px;
	}
}

/* ===========================================================================
 * STATEMENT BAND SUPPORTING COLUMNS
 *
 * The band was a large headline and one line, which left most of its height
 * empty. Three columns of supporting copy give it weight and spell out what
 * "clear sky" actually means in practice.
 * ======================================================================== */

.bs-statement__cols {
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	gap: 40px;
	margin-top: 3rem;
	padding-top: 40px;
	border-top: 1px solid var(--line-on-dark);
}

.bs-statement__cols h3 {
	font-family: var(--font-display);
	font-weight: 800;
	font-size: 1.0625rem;
	color: var(--paper);
	margin: 0 0 0.6rem;
}

.bs-statement__cols p {
	margin: 0;
	font-size: 0.9375rem;
	line-height: 1.7;
	color: rgba(255, 255, 255, 0.72);
}

/* The headline no longer needs to carry the section alone, so it can run
   wider now that copy sits beneath it. */
.bs-statement__h2 {
	max-width: 22ch;
}

/* ===========================================================================
 * CLICKABLE SERVICE CARDS
 *
 * Elementor renders a linked container as an <a>. These rules stop it picking
 * up link styling and give the whole card a hover state, since the entire card
 * is now the target rather than the arrow alone.
 * ======================================================================== */

a.bs-rail__card,
a.bs-rail__card:hover {
	text-decoration: none;
	color: inherit;
}

.bs-rail__card {
	transition: transform var(--dur-hover) ease-out;
}

.bs-rail__card:hover {
	transform: translateY(-4px);
}

.bs-rail__card:hover .bs-rail__title .elementor-heading-title {
	color: var(--sky);
}

.bs-rail__card:hover .bs-rail__arrow {
	color: var(--sunbeam);
}

.bs-rail__card:focus-visible {
	outline: 3px solid var(--sky);
	outline-offset: 3px;
}

@media (prefers-reduced-motion: reduce) {
	.bs-rail__card:hover {
		transform: none;
	}
}

@media (max-width: 900px) {
	.bs-statement__cols {
		grid-template-columns: 1fr;
		gap: 28px;
	}
}

/* Stretched link: the anchor covers the card so the whole thing is the click
   target, while the visible content stays where it is. */
.bs-rail__card {
	position: relative;
}

.bs-rail__link {
	position: absolute;
	inset: 0;
	z-index: 3;
	display: block;
	text-indent: -9999px;
	overflow: hidden;
}

/* The wrapper Elementor puts around the link must not take flow space. */
.bs-rail__card .elementor-widget-html:has(.bs-rail__link) {
	position: static;
	height: 0;
	margin: 0;
}

/* ===========================================================================
 * FOOTER TAIL: TRUE EDGE TO EDGE
 *
 * The wrapper already spans 100vw, but its children carried the full content
 * gutter (up to 88px), so the badges and bottom bar still read as contained.
 * A small fixed inset instead puts them at the viewport edge while keeping the
 * text off the glass.
 * ======================================================================== */

.bs-foot__wide .bs-foot__badges,
.bs-foot__wide .bs-foot__bar {
	padding-inline: 24px;
}

/* Divider between accreditations and review platforms. */
.bs-foot__badgerule {
	display: inline-block;
	width: 1px;
	height: 36px;
	background-color: var(--line-on-dark);
	margin-inline: 6px;
}

.bs-foot__badges a {
	display: inline-flex;
	align-items: center;
	min-height: 44px;
	opacity: 0.85;
	transition: opacity var(--dur-hover) ease-out;
}

.bs-foot__badges a:hover {
	opacity: 1;
}

.bs-foot__badges img {
	height: 56px;
	width: auto;
}

.bs-foot__badges a img {
	height: 40px;
}

@media (max-width: 600px) {
	.bs-foot__badges {
		gap: 18px;
	}

	.bs-foot__badgerule {
		display: none;
	}
}

/* ===========================================================================
 * DARK-TO-DARK SEAM
 *
 * The hero's midnight column runs straight into the statement band's midnight
 * ground, so the two sections met at a hard invisible edge and read as one
 * undifferentiated slab. A soft sky glow along the top of the band separates
 * them without introducing a colour outside the palette or a drop shadow, both
 * of which the brief rules out.
 * ======================================================================== */

.bs-statement {
	position: relative;
	isolation: isolate;
}

.bs-statement::before {
	content: "";
	position: absolute;
	inset: 0 0 auto 0;
	height: 320px;
	pointer-events: none;
	z-index: -1;
	/* Wide, low-opacity sky wash fading out downward. Elliptical rather than
	   circular so it reads as a horizon rather than a spotlight. */
	background:
		radial-gradient(120% 100% at 50% 0%,
			rgba(0, 159, 227, 0.16) 0%,
			rgba(0, 159, 227, 0.06) 42%,
			rgba(0, 159, 227, 0) 78%);
}

/* A hairline catch at the very top, which is how the brief separates things
   everywhere else. */
.bs-statement::after {
	content: "";
	position: absolute;
	inset: 0 0 auto 0;
	height: 1px;
	pointer-events: none;
	background: linear-gradient(90deg,
		rgba(0, 159, 227, 0) 0%,
		rgba(0, 159, 227, 0.55) 25%,
		rgba(0, 159, 227, 0.55) 75%,
		rgba(0, 159, 227, 0) 100%);
}

/* The same seam occurs where the service area band follows a dark section. */
.bs-areas {
	position: relative;
	isolation: isolate;
}

.bs-areas::before {
	content: "";
	position: absolute;
	inset: 0 0 auto 0;
	height: 260px;
	pointer-events: none;
	z-index: -1;
	background:
		radial-gradient(120% 100% at 50% 0%,
			rgba(0, 159, 227, 0.10) 0%,
			rgba(0, 159, 227, 0) 72%);
}

/* ===========================================================================
 * FOOTER GROUND
 *
 * The CTA band and the footer are both midnight, so they ran together as one
 * dark mass. A fine blueprint grid gives the footer its own surface without
 * introducing a colour outside the palette.
 *
 * Deliberately restrained: 1px lines at ~2.5% white on a 64px module. It should
 * register as texture, not as a visible grid, and it is the kind of drafting
 * reference a trade earns rather than decoration for its own sake.
 * ======================================================================== */

.bs-foot {
	position: relative;
	isolation: isolate;
	background-image:
		linear-gradient(rgba(255, 255, 255, 0.025) 1px, transparent 1px),
		linear-gradient(90deg, rgba(255, 255, 255, 0.025) 1px, transparent 1px);
	background-size: 64px 64px;
	background-position: center top;
}

/* A sky hairline at the join, matching how every other section separates. */
.bs-foot::before {
	content: "";
	position: absolute;
	inset: 0 0 auto 0;
	height: 1px;
	pointer-events: none;
	background: linear-gradient(90deg,
		rgba(0, 159, 227, 0) 0%,
		rgba(0, 159, 227, 0.45) 30%,
		rgba(0, 159, 227, 0.45) 70%,
		rgba(0, 159, 227, 0) 100%);
	z-index: 2;
}

/* The grid would fight the wordmark and the badge row, so it fades out toward
   the bottom of the footer. */
.bs-foot::after {
	content: "";
	position: absolute;
	inset: 40% 0 0 0;
	pointer-events: none;
	z-index: -1;
	background: linear-gradient(to bottom,
		rgba(6, 42, 74, 0) 0%,
		rgba(6, 42, 74, 0.9) 70%,
		var(--midnight) 100%);
}

/* Keep the grid off small screens, where a 64px module on a 390px viewport
   reads as stripes rather than texture. */
@media (max-width: 600px) {
	.bs-foot {
		background-image: none;
	}
}

/* ===========================================================================
 * COUNTY DETAIL
 *
 * Each county gets a short piece on what the plumbing is actually like there,
 * which is what makes a service area page worth reading rather than a list of
 * town names with the nouns swapped.
 * ======================================================================== */

.bs-counties__grid {
	display: grid;
	grid-template-columns: repeat(2, 1fr);
	gap: 40px;
	margin-top: 2.5rem;
}

.bs-countynote {
	padding-top: 20px;
	border-top: 2px solid var(--sky);
}

.bs-countynote h3 {
	font-family: var(--font-display);
	font-weight: 800;
	font-size: 1.125rem;
	color: var(--ink);
	margin: 0 0 0.6rem;
}

.bs-countynote p {
	margin: 0 0 0.9rem;
	font-size: 0.9375rem;
	line-height: 1.7;
	color: var(--slate);
	max-width: 56ch;
}

.bs-countynote__towns a {
	color: var(--sky);
	text-decoration: none;
	font-weight: 500;
}

.bs-countynote__towns a:hover {
	text-decoration: underline;
	text-underline-offset: 2px;
}

@media (max-width: 900px) {
	.bs-counties__grid {
		grid-template-columns: 1fr;
		gap: 28px;
	}
}

/* The county town links are inline in a sentence, so they need padding rather
   than a min-height, which would break the line flow. */
@media (max-width: 820px) {
	.bs-countynote__towns {
		display: flex;
		flex-wrap: wrap;
		gap: 4px 14px;
	}

	.bs-countynote__towns a {
		display: inline-flex;
		align-items: center;
		min-height: 44px;
	}
}

/* ===========================================================================
 * BLOG ARCHIVE
 *
 * Replaces Hello Elementor's bare loop. Cards with topic-matched featured
 * images, sharp corners and hairline borders, consistent with every other card
 * on the site.
 * ======================================================================== */

.bs-bloghead__inner,
.bs-bloggrid__inner {
	max-width: var(--content-max);
	margin-inline: auto;
	padding-inline: var(--space-gutter);
}

.bs-bloghead__inner {
	padding-block: clamp(72px, 8vw, 112px);
}

.bs-bloghead__h1 {
	font-family: var(--font-display);
	font-weight: 900;
	font-size: clamp(2.25rem, 5vw, 4rem);
	line-height: 1.02;
	letter-spacing: -0.035em;
	color: var(--paper);
	margin: 0.25em 0 0.5em;
	max-width: 20ch;
}

.bs-bloghead__lead {
	color: rgba(255, 255, 255, 0.82);
	max-width: 58ch;
	margin: 0;
}

.bs-bloggrid__inner {
	padding-block: clamp(64px, 7vw, 96px);
}

.bs-postcards {
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	gap: 32px;
}

.bs-postcard {
	position: relative;
	display: flex;
	flex-direction: column;
	background-color: var(--paper);
	border: 1px solid var(--line);
	transition: transform var(--dur-hover) ease-out, border-color var(--dur-hover) ease-out;
}

.bs-postcard:hover {
	transform: translateY(-4px);
	border-color: var(--sky);
}

/* Stretched link: the whole card is the target, one crawlable anchor per post. */
.bs-postcard__link {
	position: absolute;
	inset: 0;
	z-index: 2;
}

.bs-postcard__media {
	aspect-ratio: 3 / 2;
	overflow: hidden;
	background-color: var(--mist);
}

.bs-postcard__media img {
	width: 100%;
	height: 100%;
	object-fit: cover;
	display: block;
	transition: transform 400ms var(--ease-reveal);
}

.bs-postcard:hover .bs-postcard__media img {
	transform: scale(1.04);
}

.bs-postcard__body {
	display: flex;
	flex-direction: column;
	flex: 1 1 auto;
	padding: 24px;
}

.bs-postcard__date {
	font-family: var(--font-body);
	font-size: 0.6875rem;
	font-weight: 600;
	letter-spacing: 0.16em;
	text-transform: uppercase;
	color: var(--sky);
	margin: 0 0 10px;
}

/* The card title is an h2 on the archive and an h3 in the related row, so the
   kit's global heading sizes reach it and blow it up to 40px, which wraps a
   normal headline to four lines and leaves the cards ragged. Forced. */
.bs-postcard__title {
	font-family: var(--font-display) !important;
	font-weight: 800 !important;
	font-size: 1.1875rem !important;
	line-height: 1.25 !important;
	letter-spacing: -0.015em;
	color: var(--ink) !important;
	margin: 0 0 10px !important;
}

.bs-postcard:hover .bs-postcard__title {
	color: var(--sky);
}

.bs-postcard__excerpt {
	font-size: 0.9375rem;
	line-height: 1.6;
	color: var(--slate);
	margin: 0 0 18px;
}

/* Pushed to the foot so cards align regardless of excerpt length. */
.bs-postcard__more {
	margin-top: auto;
	font-family: var(--font-display);
	font-weight: 700;
	font-size: 0.8125rem;
	text-transform: uppercase;
	letter-spacing: 0.06em;
	color: var(--sky);
}

/* Pagination, matching the square controls used elsewhere. */
.bs-bloggrid .navigation.pagination {
	margin-top: 56px;
}

.bs-bloggrid .nav-links {
	display: flex;
	flex-wrap: wrap;
	gap: 8px;
	justify-content: center;
}

.bs-bloggrid .page-numbers {
	display: inline-flex;
	align-items: center;
	justify-content: center;
	min-width: 48px;
	min-height: 48px;
	padding: 0 14px;
	border: 1px solid var(--line);
	color: var(--ink) !important;
	text-decoration: none;
	font-family: var(--font-display);
	font-weight: 700;
	font-size: 0.875rem;
}

.bs-bloggrid .page-numbers.current {
	background-color: var(--midnight);
	color: var(--paper) !important;
	border-color: var(--midnight);
}

.bs-bloggrid .page-numbers:hover:not(.current) {
	border-color: var(--sky);
	color: var(--sky) !important;
}

.bs-bloggrid .screen-reader-text {
	position: absolute;
	width: 1px;
	height: 1px;
	overflow: hidden;
	clip: rect(0 0 0 0);
}

@media (max-width: 1024px) {
	.bs-postcards {
		grid-template-columns: repeat(2, 1fr);
		gap: 24px;
	}
}

@media (max-width: 600px) {
	.bs-postcards {
		grid-template-columns: 1fr;
	}
}

@media (prefers-reduced-motion: reduce) {
	.bs-postcard:hover,
	.bs-postcard:hover .bs-postcard__media img {
		transform: none;
	}
}
