/* Full Throttle Finishes — styled to the Staffordshire Truck Company house pattern.
   Carbon ground stepped up through panels, one typeface (Albert Sans), and two reds drawn
   from the logo: --accent #BE1622 is a FILL behind white text, so it stays the brand red.
   --accent-bright #F4707A is red TEXT on a dark panel, so it has to be lighter.
   A single accent cannot satisfy both directions at AA. */

/* ---------- Global ---------- */

html {
	scroll-behavior: smooth;
	scroll-padding-block-start: 140px;
	color-scheme: dark;
	/* `clip` rather than `hidden`: hidden would make this a scroll container and
	   break the sticky header. Needed because full-bleed bands use 100vw, which
	   counts the scrollbar. */
	overflow-x: clip;
}

body {
	-webkit-font-smoothing: antialiased;
}

/* ---------- Full-bleed bands ----------
   A band has to span the viewport even when it sits two constrained layouts deep
   — `page-wide` wraps post-content in its own container, which caps `alignfull`
   to the 820px content column. That was the boxed-in look on Services.

   Self-correcting: when the parent is already full width, 50% == 50vw and the
   margin resolves to 0, so this is safe to apply everywhere. */
.ftf-hero,
.ftf-stats,
.ftf-pagehead,
.ftf-section {
	inline-size: 100vw;
	max-inline-size: 100vw;
	margin-inline: calc(50% - 50vw);
}

img {
	max-inline-size: 100%;
	block-size: auto;
}

::selection {
	background: var(--wp--preset--color--accent);
	color: var(--wp--preset--color--accent-ink);
}

/* ---------- Section rhythm ---------- */

.ftf-section {
	padding-block: 80px;
}

/* A band straight after the hero or the stats strip doesn't need the full run-up,
   otherwise the page opens with a gap of dead space. */
.ftf-hero + .ftf-section,
.ftf-stats + .ftf-section {
	padding-block-start: 56px;
}

/* Two shaded bands back to back read as one; drop the seam between them. */
.ftf-section.has-surface-background-color + .ftf-section.has-surface-background-color {
	padding-block-start: 0;
}

.ftf-section-head {
	max-inline-size: 720px;
	margin-block-end: 2.5rem;
}

/* Mobile rhythm.

   Every rule here needs !important, and that is not laziness. The section groups
   carry their padding as an INLINE style — patterns/*.php and polish-pages.ps1 both
   emit `style="padding-top:var(--wp--preset--spacing--60);padding-bottom:…"`, and
   spacing|60 is a flat 5rem. An inline declaration outranks any selector in this
   file, so without !important the block below silently loses and mobile keeps the
   full 80px desktop padding. Measured at 390px: 4 of the 6 home bands were doing
   exactly that, and so were every band on About, Get a quote and Contact.

   `.alignfull` is here because those three pages build their bands as plain
   full-width groups that never got the .ftf-section class — they are the same
   thing by another name. The :not() guards keep the hero, the stats strip and the
   page header out of it; each sets its own padding deliberately. */
@media (max-width: 782px) {
	.ftf-section,
	:where(.entry-content, main) > .wp-block-group.alignfull:not(.ftf-hero, .ftf-stats, .ftf-pagehead) {
		padding-block: var(--ftf-pad-top, 56px) 56px !important;
	}

	/* Same intent as the desktop pair above: no dead run-up directly under the hero,
	   the stats strip or the page header.

	   This has to arrive as a custom property rather than as its own
	   `padding-block-start` rule. The rule above must be specific enough to beat an
	   inline style, which makes it (0,4,0); an adjacency selector like
	   `.ftf-stats + .ftf-section` is only (0,2,0), so when both carry !important the
	   base rule wins and the run-up is silently ignored. A custom property sidesteps
	   the contest — nothing else declares it. */
	.ftf-hero + *,
	.ftf-stats + *,
	.ftf-pagehead + * {
		--ftf-pad-top: 40px;
	}

	.ftf-section.has-surface-background-color + .ftf-section.has-surface-background-color {
		--ftf-pad-top: 0px;
	}

	/* 64px of title band costs a sixth of the viewport before any content shows. */
	.ftf-pagehead {
		padding-block: 44px !important;
	}

	.ftf-section-head {
		margin-block-end: 1.75rem;
	}
}

/* ---------- Header — two tiers: brand on top, navigation beneath ---------- */

.ftf-header {
	position: sticky;
	top: 0;
	z-index: 100;
	background: rgba(10, 10, 12, 0.94);
	/* No backdrop-filter here, deliberately.
	   backdrop-filter makes its element the containing block for position:fixed
	   descendants, which pinned the mobile navigation overlay to the header's own box
	   (227px) instead of the viewport (812px): the menu was cut off mid-item and had to
	   be scrolled. Safari had been ignoring the unprefixed property, so the overlay only
	   broke once the -webkit- prefix was added to "fix" the blur.
	   It is no loss. This background is 94% opaque (98% when scrolled), so a 10px blur
	   behind it was very close to invisible. */
	border-bottom: 1px solid var(--wp--preset--color--line);
}

.ftf-header__top {
	min-block-size: 88px;
}

.ftf-header__nav {
	border-top: 1px solid var(--wp--preset--color--line);
	background: rgba(0, 0, 0, 0.45);
}

.ftf-header .wp-block-site-title a {
	text-decoration: none;
}

.ftf-header .wp-block-site-title a:hover {
	color: var(--wp--preset--color--accent-bright);
}

/* Strapline under the wordmark, the way the reference sets its logo lockup. */
.ftf-header__strap {
	margin: 3px 0 0 !important;
	font-size: 0.7rem;
	font-weight: 700;
	letter-spacing: 0.2em;
	text-transform: uppercase;
	color: var(--wp--preset--color--accent-bright);
}

.ftf-header .wp-block-navigation {
	justify-content: center;
}

.ftf-header .wp-block-navigation-item__content {
	display: block;
	padding-block: 10px;
	color: var(--wp--preset--color--contrast);
	transition: color 0.15s ease;
}

/* ---------- Desktop header row ----------
   The brand row sits in the 1200px container, which left the wordmark 120px in while the
   hero copy starts at 48px. Full-bleed the row and give it the same 3rem gutter, so the
   brand lines up with the hero beneath it and the phone and quote button reach the far
   right. Same self-correcting idiom as the bands: 50% - 50vw is exactly the container's
   offset, whatever the viewport. */
@media (min-width: 782px) {
	.ftf-header__top > .wp-block-group.alignwide {
		inline-size: 100vw;
		max-inline-size: 100vw;
		/* !important because core's constrained layout sets the auto margins on
		   `> .alignwide` with !important of its own. Without it the row keeps a 0
		   margin, starts at the parent's 24px padding and runs 24px off the right. */
		margin-inline: calc(50% - 50vw) !important;
		padding-inline: 3rem;
	}
}

/* ---------- Desktop navigation ----------
   The bar was 15px links on a dark strip and read as an afterthought. Uppercase, larger
   and letter-spaced to match the display type elsewhere, each link a padded target with
   its own hover panel, plus a red rule that wipes in from the left and stays put on the
   current page — so there is always a visible answer to "where am I".
   Scoped to the desktop bar: the mobile overlay has its own treatment, and
   `position: relative` on a link inside that overlay would fight it. */
@media (min-width: 782px) {
	.ftf-header__nav {
		background: rgba(0, 0, 0, 0.55);
	}

	.ftf-header__nav .wp-block-navigation-item__content {
		position: relative;
		padding: 13px 15px;
		border-radius: 7px;
		font-weight: 800;
		font-size: 1rem;
		letter-spacing: 0.09em;
		text-transform: uppercase;
		transition: color 0.18s ease, background-color 0.18s ease;
	}

	.ftf-header__nav .wp-block-navigation-item__content:hover,
	.ftf-header__nav .wp-block-navigation-item__content:focus-visible {
		color: #fff;
		background: rgba(255, 255, 255, 0.07);
	}

	.ftf-header__nav .wp-block-navigation-item__content::after {
		content: "";
		position: absolute;
		/* Match the horizontal padding so the rule sits under the word, not the panel. */
		inset-inline: 15px;
		inset-block-end: 5px;
		block-size: 2px;
		border-radius: 2px;
		background: var(--wp--preset--color--accent);
		transform: scaleX(0);
		transform-origin: left center;
		transition: transform 0.28s cubic-bezier(0.2, 0.7, 0.3, 1);
	}

	.ftf-header__nav .wp-block-navigation-item__content:hover::after,
	.ftf-header__nav .wp-block-navigation-item__content:focus-visible::after,
	.ftf-header__nav .current-menu-item .wp-block-navigation-item__content::after {
		transform: scaleX(1);
	}

	/* The current page keeps the rule but in the light red, so it reads as "you are
	   here" rather than "hovered". Brand red as text fails AA on this panel. */
	.ftf-header__nav .current-menu-item .wp-block-navigation-item__content,
	.ftf-header__nav .current-menu-item .wp-block-navigation-item__content:hover {
		color: var(--wp--preset--color--accent-bright);
	}

	.ftf-header__nav .current-menu-item .wp-block-navigation-item__content::after {
		background: var(--wp--preset--color--accent-bright);
	}
}

.ftf-header .wp-block-navigation-item__content:hover,
.ftf-header .current-menu-item .wp-block-navigation-item__content {
	color: var(--wp--preset--color--accent-bright);
	text-decoration: none;
}

/* Phone button in the brand row. */
.ftf-call .wp-block-button__link {
	background: var(--wp--preset--color--accent-deep) !important;
	color: #fff !important;
	padding: 10px 18px;
	font-size: 0.95rem;
	white-space: nowrap;
	box-shadow: none;
}

.ftf-call .wp-block-button__link:hover {
	filter: brightness(1.1);
	box-shadow: none;
}

/* ---------- Mobile menu ----------
   Both toggles ship at 24x24, which is roughly half the 44px minimum both Apple and
   Google publish for a touch target, and the open menu set its links at 14px — smaller
   than the body copy, in a full-screen overlay with nothing else competing for room.
   The whole thing is sized for a mouse. */

/* Deliberately no `display` override with !important here. Core hides the open button
   above 600px with `.…-open:not(.always-shown){display:none}`, and forcing display won
   that fight — putting a hamburger next to the full desktop navigation. Sizing only;
   let core keep deciding whether the button exists. */
.wp-block-navigation__responsive-container-open,
.wp-block-navigation__responsive-container-close {
	place-items: center;
	align-items: center;
	justify-content: center;
	inline-size: 44px;
	block-size: 44px;
	padding: 0;
	border-radius: 8px;
	color: var(--wp--preset--color--contrast);
}

.wp-block-navigation__responsive-container-open svg,
.wp-block-navigation__responsive-container-close svg {
	inline-size: 28px;
	block-size: 28px;
	fill: currentColor;
}

.wp-block-navigation__responsive-container-close:hover,
.wp-block-navigation__responsive-container-open:hover {
	color: var(--wp--preset--color--accent-bright);
}

.wp-block-navigation__responsive-container.is-menu-open {
	background: var(--wp--preset--color--base) !important;
	color: var(--wp--preset--color--contrast) !important;
	/* Clear the notch and the home indicator on a modern handset. */
	padding-block: max(4rem, calc(env(safe-area-inset-top) + 3.25rem)) max(1.5rem, env(safe-area-inset-bottom));
	padding-inline: 1.5rem;
	/* Safety net only. With the sizing below, five items sit well inside the shortest
	   phone viewport, so this should never actually engage. */
	overflow-y: auto;
}

.wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__responsive-close {
	max-inline-size: none;
}

.wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation__container {
	gap: 0 !important;
	inline-size: 100%;
}

.wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-item {
	inline-size: 100%;
	border-block-end: 1px solid var(--wp--preset--color--line);
}

.wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-item:first-child {
	border-block-start: 1px solid var(--wp--preset--color--line);
}

/* A full-width row, so the whole line is the tap target rather than the word. */
.wp-block-navigation__responsive-container.is-menu-open .wp-block-navigation-item__content {
	display: block;
	inline-size: 100%;
	/* Core resets this to 0 from a more specific selector; without !important the rows
	   collapse to the height of the text and the tap target is the word, not the line.
	   0.8rem gives a ~47px row: comfortably over the 44px touch minimum, without the
	   oversized 61px rows that pushed five items past the bottom of the screen. */
	padding-block: 0.8rem !important;
	font-family: var(--wp--preset--font-family--display);
	font-size: 1.1rem;
	font-weight: 800;
	text-transform: uppercase;
	letter-spacing: 0.06em;
	line-height: 1.2;
}

.wp-block-navigation__responsive-container.is-menu-open .current-menu-item .wp-block-navigation-item__content {
	color: var(--wp--preset--color--accent-bright);
}

@media (max-width: 620px) {
	.ftf-header__top {
		min-block-size: 0;
	}
}

/* ---------- Kicker (eyebrow) ---------- */

.is-style-ftf-eyebrow {
	display: flex;
	align-items: center;
	gap: 12px;
	margin-block-end: 0.75rem;
	color: var(--wp--preset--color--accent-bright) !important;
	font-size: 0.8rem !important;
	font-weight: 700;
	letter-spacing: 0.25em;
	text-transform: uppercase;
}

.is-style-ftf-eyebrow::before {
	content: "";
	flex: none;
	inline-size: 28px;
	block-size: 2px;
	border-radius: 2px;
	background: var(--wp--preset--color--accent-bright);
}

.has-text-align-center.is-style-ftf-eyebrow {
	justify-content: center;
}

/* ---------- Buttons ---------- */

.wp-block-button__link {
	transition: transform 0.16s ease, box-shadow 0.16s ease, filter 0.16s ease;
}

.wp-block-button__link:hover {
	filter: brightness(1.08);
	transform: translateY(-1px);
	box-shadow: 0 1px 0 rgba(255, 255, 255, 0.28) inset, 0 14px 28px -12px rgba(190, 22, 34, 1);
}

.wp-block-button__link:active {
	transform: translateY(0);
}

.wp-block-button.is-style-outline .wp-block-button__link {
	background: transparent !important;
	border: 2px solid rgba(245, 246, 247, 0.85);
	color: var(--wp--preset--color--contrast) !important;
	box-shadow: none;
}

.wp-block-button.is-style-outline .wp-block-button__link:hover {
	border-color: var(--wp--preset--color--accent-bright);
	color: var(--wp--preset--color--accent-bright) !important;
	box-shadow: none;
	filter: none;
}

/* ---------- Hero ---------- */

.ftf-hero {
	position: relative;
	min-block-size: 78vh;
	display: flex;
	align-items: center;
	overflow: hidden;
	background: var(--wp--preset--color--deep);
}

/* Scrim so headline copy still holds up once a photograph is dropped in behind. */
.ftf-hero::after {
	content: "";
	position: absolute;
	inset: 0;
	background: var(--wp--preset--gradient--hero-scrim);
	pointer-events: none;
	z-index: 1;
}

.ftf-hero > .wp-block-group,
.ftf-hero .wp-block-cover__inner-container {
	position: relative;
	z-index: 2;
	inline-size: 100%;
}

/* Sit the copy against the left edge of the container: the scrim is heaviest there,
   which is what keeps the headline readable over the photograph. */
.ftf-hero__inner {
	max-inline-size: 640px;
	margin-inline: 0 auto;
	padding-block: clamp(4rem, 9vw, 7rem);
}

/* The hero photograph is a white spray booth, and the copy sits over the left of it —
   white text on a white room. The default scrim was built for a photo that was already
   dark on that side, so desktop needs a heavier left-hand ramp than the preset gives.
   Held to the left 55% so the finished black truck on the right stays untouched.
   The figure that matters is the contrast ratio behind the headline, not how it looks
   in a thumbnail: measured, not eyeballed. */
@media (min-width: 782px) {
	.ftf-hero::after {
		background:
			linear-gradient(90deg,
				rgba(10, 10, 12, 0.97) 0%,
				rgba(10, 10, 12, 0.95) 30%,
				rgba(10, 10, 12, 0.78) 48%,
				rgba(10, 10, 12, 0.34) 68%,
				rgba(10, 10, 12, 0.12) 100%),
			linear-gradient(0deg, rgba(10, 10, 12, 0.55) 0%, rgba(10, 10, 12, 0) 46%);
	}

	/* Keep the call to action above the fold.
	   Measured at 1440x900: the buttons ended at 984px on a 900px viewport, so the one
	   thing the hero exists to do was off screen. The logo was 225px tall and the block
	   padding 112px top and bottom; trimming both brings the buttons to roughly 850px
	   with room to spare, without touching the type sizes. */
	.ftf-hero__inner {
		padding-block: clamp(2.5rem, 4.5vw, 4rem);

		/* Pull the copy out of the 1200px container and onto the viewport's left edge,
		   keeping a 3rem gutter. Same self-correcting trick as the full-bleed bands:
		   50% is half the parent, 50vw half the viewport, so the difference is exactly
		   the container's left offset — 120px at 1440, and 0 once the container is as
		   wide as the viewport. One expression, correct at every desktop width.
		   Safe because .ftf-hero is overflow: hidden, so the negative margin cannot
		   produce a horizontal scrollbar. */
		margin-inline-start: calc(50% - 50vw + 3rem);
	}
}

/* Below the two-column breakpoint the scrim goes vertical, so the copy can use the
   full width and still sit on a dark base. */
@media (max-width: 781px) {
	.ftf-hero::after {
		background: linear-gradient(180deg, rgba(10, 10, 12, 0.74) 0%, rgba(10, 10, 12, 0.90) 60%, rgba(10, 10, 12, 0.97) 100%);
	}

	.ftf-hero__inner {
		max-inline-size: none;
	}
}

.ftf-hero .ftf-lead {
	font-size: 1.15rem;
	color: var(--wp--preset--color--contrast);
}

/* ---------- Stats strip ---------- */

/* Each stat is ONE line, and the emphasis is carried by weight rather than size.
   Previously the value was 2.1rem against a 0.72rem label — a 2.9x jump that read as two
   unrelated pieces of text stacked on top of each other rather than one statement. At a
   single size "Free written estimates" is a sentence somebody can actually read, and the
   band comes down from 92px to about 60px, which matters more on mobile where these
   stack into four rows. */
.ftf-stats {
	background: var(--wp--preset--color--accent-deep);
	padding-block: 22px;
}

.ftf-stat {
	display: flex;
	flex-wrap: wrap;
	gap: 0.45rem;
	align-items: baseline;
	justify-content: center;
	text-align: center;
}

.ftf-stat__value,
.ftf-stat__label {
	margin: 0 !important;
	font-size: 1.05rem;
	line-height: 1.35;
	color: #fff;
}

.ftf-stat__value {
	font-weight: 800;
	letter-spacing: 0.01em;
}

/* The label is deliberately NOT uppercase small print any more. Tracking-out at 0.72rem
   is what made it read as a caption for the word above rather than the rest of the line. */
.ftf-stat__label {
	font-weight: 400;
	text-transform: none;
	letter-spacing: normal;
	opacity: 0.8;
}

/* The stats strip renders through WordPress's grid layout, which emits
   `container-type: inline-size` on the wrapper. On iOS Safari that containment let the
   four stat blocks resolve to collapsed heights, so they were painted on top of one
   another — "Free" over "Same day", "5" over "Insurance" — while reading perfectly in
   every Chrome capture, including full device emulation at 390px. Two screenshots from
   a real iPhone are the only reason this was visible at all.

   Nothing here needs a container query, so the containment is pure liability: drop it.
   Below the breakpoint the grid resolves to a single column anyway, so a plain flex
   column is the same layout built out of something that cannot fail this way. */
.ftf-stats .is-layout-grid {
	container-type: normal !important;
}

@media (max-width: 782px) {
	.ftf-stats .is-layout-grid {
		display: flex !important;
		flex-direction: column !important;
		gap: 1.4rem !important;
	}

	/* Belt and braces: if anything else ever tries to collapse these, they still
	   occupy their own line box.

	   This used to force `display: block`, which was fine when the value and label were
	   stacked but now flattens the one-line layout back into two rows. The actual fix for
	   the iOS collapse is `container-type: normal` above; this only ever needed to
	   guarantee a line box, and a flex row does that just as well as a block. */
	.ftf-stat {
		display: flex !important;
		position: static !important;
	}

	.ftf-stat__value,
	.ftf-stat__label {
		position: static !important;
	}

	.ftf-stat__value {
		min-block-size: 1em;
	}
}

/* ---------- Surfaces ----------
   One treatment shared by every panel. The hairline along the top edge reads as
   light catching it, which is most of what separates a "dark card" from
   something that looks made. */

.is-style-ftf-card,
.ftf-projects .wp-block-post,
.ftf-map__frame,
.ftf-form__notice {
	position: relative;
	background: var(--wp--preset--color--surface-raised);
	border: 1px solid var(--wp--preset--color--line);
	border-radius: 12px;
	box-shadow: var(--wp--preset--shadow--panel);
}

.is-style-ftf-card {
	block-size: 100%;
}

/* Cards that lead somewhere get a lift and a deeper shadow on hover. */
.is-style-ftf-card,
.ftf-projects .wp-block-post {
	transition: transform 0.22s cubic-bezier(0.2, 0.7, 0.3, 1), border-color 0.22s ease, box-shadow 0.22s ease;
}

.is-style-ftf-card:hover,
.ftf-projects .wp-block-post:hover {
	transform: translateY(-3px);
	border-color: var(--wp--preset--color--accent);
	box-shadow: var(--wp--preset--shadow--lift);
}

.is-style-ftf-card h3 a,
.ftf-projects .wp-block-post-title a {
	color: var(--wp--preset--color--contrast);
	text-decoration: none;
}

.is-style-ftf-card:hover h3 a,
.ftf-projects .wp-block-post-title a:hover {
	color: var(--wp--preset--color--accent-bright);
}

/* Only the column that actually holds a card becomes a flex container, and it stacks.
   Applying this to every column in the row turned the neighbouring text column into a
   flex ROW — which is what squashed the Services headings and stood the buttons on end. */
.wp-block-column:has(> .is-style-ftf-card) {
	display: flex;
	flex-direction: column;
}

/* ---------- Project grid ---------- */

.ftf-projects .wp-block-post {
	overflow: hidden;
}

.ftf-projects .wp-block-post-featured-image {
	margin: 0;
	overflow: hidden;
}

.ftf-projects .wp-block-post-featured-image img {
	aspect-ratio: 4 / 3;
	object-fit: cover;
	inline-size: 100%;
	display: block;
	transition: transform 0.5s ease;
}

.ftf-projects .wp-block-post:hover .wp-block-post-featured-image img {
	transform: scale(1.04);
}

.ftf-projects .wp-block-post-terms {
	font-size: 0.72rem;
	font-weight: 700;
	text-transform: uppercase;
	letter-spacing: 0.16em;
}

.ftf-projects .wp-block-post-terms a {
	color: var(--wp--preset--color--accent-bright);
	text-decoration: none;
}

/* ---------- Filter pills ---------- */

.ftf-filter {
	display: flex;
	flex-wrap: wrap;
	gap: 0.55rem;
	list-style: none;
	padding: 0;
	margin: 0;
}

.ftf-filter a {
	display: inline-block;
	padding: 9px 18px;
	font-size: 0.85rem;
	font-weight: 600;
	color: var(--wp--preset--color--contrast);
	background: var(--wp--preset--color--surface-raised);
	border: 1px solid var(--wp--preset--color--line);
	border-radius: 999px;
	text-decoration: none;
	transition: all 0.18s ease;
}

.ftf-filter a:hover {
	border-color: var(--wp--preset--color--accent-bright);
	color: var(--wp--preset--color--accent-bright);
}

.ftf-filter a[aria-current="page"] {
	background: var(--wp--preset--color--accent-deep);
	border-color: var(--wp--preset--color--accent-deep);
	color: #fff;
}

/* ---------- Page header band ---------- */

.ftf-pagehead {
	background: var(--wp--preset--color--deep);
	border-bottom: 1px solid var(--wp--preset--color--line);
	padding-block: 64px;
}

.ftf-pagehead h1 {
	margin-block-end: 0.4em;
}

.ftf-pagehead p {
	max-inline-size: 62ch;
	color: var(--wp--preset--color--muted);
	font-size: 1.15rem;
}

/* ---------- Red bands ---------- */

.has-accent-background-color,
.has-accent-deep-background-color {
	color: #fff;
}

.has-accent-background-color :is(h1, h2, h3, h4, h5),
.has-accent-deep-background-color :is(h1, h2, h3, h4, h5) {
	color: #fff;
}

.has-accent-background-color p,
.has-accent-deep-background-color p {
	color: rgba(255, 255, 255, 0.92);
}

.has-accent-background-color .is-style-ftf-eyebrow,
.has-accent-deep-background-color .is-style-ftf-eyebrow {
	color: #fff !important;
	opacity: 0.9;
}

.has-accent-background-color .is-style-ftf-eyebrow::before,
.has-accent-deep-background-color .is-style-ftf-eyebrow::before {
	background: #fff;
}

.has-accent-background-color .wp-block-button__link,
.has-accent-deep-background-color .wp-block-button__link {
	background: #fff !important;
	color: var(--wp--preset--color--accent-deep) !important;
}

/* ---------- Process steps ---------- */

.ftf-steps {
	counter-reset: ftf-step;
}

.ftf-step {
	counter-increment: ftf-step;
	position: relative;
	padding-block-start: 3rem;
	border-top: 2px solid var(--wp--preset--color--line);
}

.ftf-step::before {
	content: counter(ftf-step, decimal-leading-zero);
	position: absolute;
	inset-block-start: 0.9rem;
	font-size: 0.85rem;
	font-weight: 800;
	letter-spacing: 0.14em;
	color: var(--wp--preset--color--accent-bright);
}

/* ---------- Services sections ---------- */

.ftf-service-section {
	scroll-margin-block-start: 150px;
}

/* Text column and media column should end up the same visual height, with the
   image filling its side rather than floating in a small box. */
.ftf-service-section .wp-block-columns {
	align-items: center;
}

/* ---------- Media fills its column ----------
   A gallery inside a column was rendering at a fraction of the available width
   because the slider reserves a track per slide. Anything media-shaped now
   stretches to the column it lives in. */

.ftf-gallery,
.ftf-gallery__viewport,
.ftf-gallery__track {
	inline-size: 100%;
}

.ftf-media,
.ftf-media img {
	inline-size: 100%;
	display: block;
}

.ftf-media img {
	border-radius: 12px;
	object-fit: cover;
	box-shadow: var(--wp--preset--shadow--panel);
}

/* Portrait workshop shots would otherwise run enormously tall in a wide column. */
.ftf-media--landscape img {
	aspect-ratio: 4 / 3;
}

.ftf-media--portrait img {
	aspect-ratio: 3 / 4;
	max-block-size: 34rem;
	inline-size: auto;
	margin-inline: auto;
}

/* ---------- Prose ---------- */

.ftf-prose :is(h2, h3) {
	margin-block-start: 2em;
}

.ftf-spec h6 {
	margin-block-end: 0.15rem;
	color: var(--wp--preset--color--muted);
}

.ftf-spec p {
	margin-block-start: 0;
	margin-block-end: 1.35rem;
	font-weight: 600;
}

/* ---------- Search & pagination ---------- */

.wp-block-search__input {
	inline-size: 100%;
	padding: 12px 14px;
	background: var(--wp--preset--color--surface-raised);
	border: 1px solid var(--wp--preset--color--line);
	border-radius: 8px;
	color: var(--wp--preset--color--contrast);
	font-family: inherit;
}

.wp-block-query-pagination a,
.wp-block-query-pagination span {
	font-weight: 600;
	font-size: 0.9rem;
	text-decoration: none;
}

.wp-block-query-pagination .current {
	color: var(--wp--preset--color--accent-bright);
}

/* ---------- Footer ---------- */

.ftf-footer {
	background: var(--wp--preset--color--deep);
	border-top: 1px solid var(--wp--preset--color--line);
	padding-block: 56px 32px;
}

.ftf-footer h6 {
	font-size: 0.85rem;
	letter-spacing: 0.18em;
	text-transform: uppercase;
	color: var(--wp--preset--color--muted);
}

.ftf-footer p,
.ftf-footer li {
	color: var(--wp--preset--color--muted);
}

.ftf-footer a {
	color: var(--wp--preset--color--contrast);
	text-decoration: none;
}

.ftf-footer a:hover {
	color: var(--wp--preset--color--accent-bright);
}

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

.ftf-footer .wp-block-separator {
	border-color: var(--wp--preset--color--line);
	color: var(--wp--preset--color--line);
}

/* ---------- Accessibility ---------- */

:where(a, button, input, select, textarea):focus-visible {
	outline: 2px solid var(--wp--preset--color--accent-bright);
	outline-offset: 3px;
	border-radius: 4px;
}

.skip-link:focus {
	position: fixed;
	inset-block-start: 0;
	inset-inline-start: 12px;
	z-index: 200;
	padding: 12px 20px;
	background: var(--wp--preset--color--accent-deep);
	color: #fff;
	font-weight: 700;
	border-radius: 0 0 8px 8px;
}

@media (prefers-reduced-motion: reduce) {
	html {
		scroll-behavior: auto;
	}

	*,
	*::before,
	*::after {
		animation-duration: 0.01ms !important;
		transition-duration: 0.01ms !important;
	}
}

/* ================================================================
   Enhancements
   ================================================================ */

/* ---------- Screen-reader utility + skip link ---------- */

.screen-reader-text:not(:focus) {
	position: absolute !important;
	inline-size: 1px;
	block-size: 1px;
	overflow: hidden;
	clip-path: inset(50%);
	white-space: nowrap;
}

/* ---------- Scroll reveal ----------
   Only active once JS has added .ftf-reveal-on, so content is never hidden
   from a browser that cannot reveal it again. */

.ftf-reveal-on .ftf-reveal {
	opacity: 0;
	transform: translateY(14px);
}

.ftf-reveal-on .ftf-reveal.is-revealed {
	opacity: 1;
	transform: none;
	transition: opacity 0.6s cubic-bezier(0.2, 0.7, 0.3, 1) var(--ftf-reveal-delay, 0ms),
		transform 0.6s cubic-bezier(0.2, 0.7, 0.3, 1) var(--ftf-reveal-delay, 0ms);
}

/* ---------- Header scrolled state ---------- */

.ftf-header {
	transition: box-shadow 0.25s ease, background-color 0.25s ease;
}

.ftf-header.is-scrolled {
	box-shadow: 0 12px 30px -22px rgba(0, 0, 0, 0.9);
	background: rgba(10, 10, 12, 0.98);
}

/* ---------- Mobile call bar ---------- */

.ftf-callbar {
	position: fixed;
	inset-inline: 0;
	inset-block-end: 0;
	z-index: 90;
	display: none;
	background: rgba(0, 13, 12, 0.97);
	backdrop-filter: blur(12px);
	border-top: 1px solid var(--wp--preset--color--line);
	padding-block-end: env(safe-area-inset-bottom, 0);
	/* Visible by default: if the script never runs, the bar is still there and usable.
	   JS hides it only while the hero's own call to action is on screen. */
	transform: none;
	transition: transform 0.28s cubic-bezier(0.2, 0.7, 0.3, 1);
}

.ftf-callbar.is-hidden {
	transform: translateY(100%);
}

.ftf-callbar__item {
	flex: 1;
	display: flex;
	flex-direction: column;
	align-items: center;
	justify-content: center;
	gap: 4px;
	padding-block: 0.7rem;
	font-size: 0.72rem;
	font-weight: 700;
	letter-spacing: 0.1em;
	text-transform: uppercase;
	color: var(--wp--preset--color--contrast);
	text-decoration: none;
	border-inline-end: 1px solid var(--wp--preset--color--line);
}

.ftf-callbar__item:last-child {
	border-inline-end: 0;
}

.ftf-callbar__item.is-primary {
	background: var(--wp--preset--color--accent);
	color: #fff;
}

.ftf-callbar__icon {
	inline-size: 20px;
	block-size: 20px;
	background: currentColor;
	/* Icons as masked shapes: one colour source, no image requests. */
	-webkit-mask-repeat: no-repeat;
	mask-repeat: no-repeat;
	-webkit-mask-position: center;
	mask-position: center;
	-webkit-mask-size: contain;
	mask-size: contain;
}

.ftf-callbar__icon--phone {
	-webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M6.6 10.8a15.1 15.1 0 0 0 6.6 6.6l2.2-2.2c.3-.3.7-.4 1-.2 1.2.4 2.4.6 3.6.6.6 0 1 .4 1 1V20c0 .6-.4 1-1 1A17 17 0 0 1 3 4c0-.6.4-1 1-1h3.5c.6 0 1 .4 1 1 0 1.3.2 2.5.6 3.6.1.4 0 .8-.2 1l-2.3 2.2Z'/%3E%3C/svg%3E");
	mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M6.6 10.8a15.1 15.1 0 0 0 6.6 6.6l2.2-2.2c.3-.3.7-.4 1-.2 1.2.4 2.4.6 3.6.6.6 0 1 .4 1 1V20c0 .6-.4 1-1 1A17 17 0 0 1 3 4c0-.6.4-1 1-1h3.5c.6 0 1 .4 1 1 0 1.3.2 2.5.6 3.6.1.4 0 .8-.2 1l-2.3 2.2Z'/%3E%3C/svg%3E");
}

.ftf-callbar__icon--quote {
	-webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8l-6-6Zm0 2.5L17.5 8H14V4.5ZM8 12h8v2H8v-2Zm0 4h8v2H8v-2Z'/%3E%3C/svg%3E");
	mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M14 2H6a2 2 0 0 0-2 2v16a2 2 0 0 0 2 2h12a2 2 0 0 0 2-2V8l-6-6Zm0 2.5L17.5 8H14V4.5ZM8 12h8v2H8v-2Zm0 4h8v2H8v-2Z'/%3E%3C/svg%3E");
}

.ftf-callbar__icon--pin {
	-webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 2a7 7 0 0 0-7 7c0 5.2 7 13 7 13s7-7.8 7-13a7 7 0 0 0-7-7Zm0 9.5A2.5 2.5 0 1 1 12 6.5a2.5 2.5 0 0 1 0 5Z'/%3E%3C/svg%3E");
	mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M12 2a7 7 0 0 0-7 7c0 5.2 7 13 7 13s7-7.8 7-13a7 7 0 0 0-7-7Zm0 9.5A2.5 2.5 0 1 1 12 6.5a2.5 2.5 0 0 1 0 5Z'/%3E%3C/svg%3E");
}

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

	/* Keep the bar clear of the last section and the footer. */
	body {
		padding-block-end: 4.25rem;
	}
}

/* ---------- Trust band ---------- */

.ftf-trust {
	display: grid;
	grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
	gap: 1.25rem;
	list-style: none;
	margin: 0;
	padding: 0;
}

.ftf-trust li {
	display: flex;
	gap: 0.9rem;
	align-items: flex-start;
	padding: 1.25rem 1.35rem;
	background: var(--wp--preset--color--surface-raised);
	border: 1px solid var(--wp--preset--color--line);
	border-radius: 12px;
	box-shadow: var(--wp--preset--shadow--panel);
}

/* Teal tick, drawn rather than typed. */
.ftf-trust li::before {
	content: "";
	flex: none;
	inline-size: 1.4rem;
	block-size: 1.4rem;
	margin-block-start: 0.15rem;
	border-radius: 50%;
	background: var(--wp--preset--color--accent);
	-webkit-mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M9 16.2 4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4L9 16.2Z'/%3E%3C/svg%3E");
	mask-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M9 16.2 4.8 12l-1.4 1.4L9 19 21 7l-1.4-1.4L9 16.2Z'/%3E%3C/svg%3E");
	-webkit-mask-repeat: no-repeat;
	mask-repeat: no-repeat;
	-webkit-mask-size: contain;
	mask-size: contain;
}

.ftf-trust strong {
	display: block;
	margin-block-end: 0.2rem;
	color: var(--wp--preset--color--contrast);
}

.ftf-trust span {
	color: var(--wp--preset--color--muted);
	font-size: 0.95rem;
	line-height: 1.5;
}

/* ---------- Hero refinements ---------- */

.ftf-hero h1 {
	text-wrap: balance;
}

.ftf-pagehead h1,
.ftf-section h2 {
	text-wrap: balance;
}

/* ---------- Print ---------- */

@media print {
	.ftf-header,
	.ftf-callbar,
	.ftf-footer,
	.ftf-gallery__arrows,
	.ftf-gallery__dots {
		display: none !important;
	}

	body {
		background: #fff;
		color: #000;
		padding-block-end: 0;
	}
}

/* ---------- Overflow guards ----------
   Two classic causes of horizontal overflow, both invisible on a desktop screen and
   both hidden by `overflow-x: clip` until you look at a phone.

   1. A flex item defaults to `min-width: auto`, so it refuses to shrink below its
      content's max-content width. The hero is a flex container, so its inner group
      was staying as wide as the widest line of copy instead of the viewport.
   2. `minmax(180px, 1fr)` grid tracks cannot go below 180px, so a four-up stats row
      overflowed rather than dropping to one column. `min()` lets the track collapse. */

.ftf-hero > *,
.ftf-hero .wp-block-group,
.ftf-hero__inner {
	min-inline-size: 0;
}

.ftf-stats .wp-block-group.alignwide,
.ftf-stats .is-layout-grid {
	grid-template-columns: repeat(auto-fit, minmax(min(170px, 100%), 1fr));
	min-inline-size: 0;
}

/* Long words and URLs in body copy shouldn't push a column open either. */
.ftf-section p,
.ftf-pagehead p,
.ftf-hero p,
.ftf-faq__a p {
	overflow-wrap: break-word;
}

/* Columns must be allowed to shrink before they stack. */
.wp-block-column {
	min-inline-size: 0;
}

/* Form controls must be border-box, or `inline-size: 100%` plus padding and border
   renders them wider than their column. That was a 10px horizontal overflow on the
   Contact and Get a quote pages at 390px. */
.ftf-form input,
.ftf-form select,
.ftf-form textarea,
.ftf-booking input,
.wp-block-search__input {
	box-sizing: border-box;
}

/* ================================================================
   Brand elements, drawn from the logo
   ================================================================ */

/* ---------- Chrome lettering ----------
   The logo's wordmark is brushed chrome. Reproduced as a clipped gradient rather
   than an image so it stays selectable, scalable and translatable.

   The solid colour is declared first and unconditionally: if background-clip:text
   is unsupported the heading is simply chrome-white, never invisible. */
.ftf-chrome,
.is-style-ftf-chrome {
	color: var(--wp--preset--color--contrast);
}

@supports ((-webkit-background-clip: text) or (background-clip: text)) {
	.ftf-chrome,
	.is-style-ftf-chrome {
		background-image: var(--wp--preset--gradient--chrome);
		/* One full chrome sweep per LINE. Left to span the whole block, a three-line
		   heading takes one slice each and the middle line just reads flat grey. */
		background-size: 100% 1.05em;
		background-repeat: repeat-y;
		-webkit-background-clip: text;
		background-clip: text;
		color: transparent;
		/* A hairline dark edge, the way the logo's lettering is outlined. */
		filter: drop-shadow(0 1px 0 rgba(0, 0, 0, 0.55));
	}
}

/* Windows High Contrast would otherwise render clipped text as nothing. */
@media (forced-colors: active) {
	.ftf-chrome,
	.is-style-ftf-chrome {
		color: CanvasText;
		background-image: none;
		-webkit-text-fill-color: CanvasText;
	}
}

/* ---------- Tachometer ticks ----------
   The sweep of gauge marks from the top of the logo, used as a section rule. */
.ftf-tach {
	--ftf-tach-h: 14px;
	block-size: var(--ftf-tach-h);
	inline-size: min(320px, 60%);
	margin-block: 1.25rem 0;
	background-image: repeating-linear-gradient(
		90deg,
		var(--wp--preset--color--line) 0 2px,
		transparent 2px 9px
	);
	/* Ticks fade out to the right and rise to full red at the redline. */
	-webkit-mask-image: linear-gradient(90deg, #000 0%, #000 62%, transparent 100%);
	mask-image: linear-gradient(90deg, #000 0%, #000 62%, transparent 100%);
	position: relative;
}

.ftf-tach::after {
	content: "";
	position: absolute;
	inset-block: 0;
	inset-inline-start: 0;
	inline-size: 34%;
	background-image: repeating-linear-gradient(
		90deg,
		var(--wp--preset--color--accent) 0 2px,
		transparent 2px 9px
	);
}

/* ---------- Red slash ----------
   The angled streaks that cut across the badge. Purely decorative. */
.ftf-slash {
	position: relative;
}

.ftf-slash::before {
	content: "";
	position: absolute;
	inset-block-start: -0.35em;
	inset-inline-start: -1.15rem;
	inline-size: 5px;
	block-size: calc(100% + 0.7em);
	background: var(--wp--preset--color--accent);
	transform: skewX(-14deg);
	border-radius: 2px;
}

/* The skew throws the two ends sideways in proportion to the mark's height — half the
   height times tan(14deg). Over the two lines the lead wraps to on desktop that is about
   7px and reads as intended. On mobile the same paragraph wraps to five lines, so the
   mark grew to 165px and the throw to +/-21px: the top corner crossed x=33 while the
   text starts at x=24, cutting through the first line, and the bottom corner reached
   x=-9, off the edge of the screen.

   The gutter here is only 24px wide, so the fix is to keep the mark short and the angle
   shallow enough that both ends stay inside it whatever the paragraph does. Capping the
   height also means this cannot come back on a narrower phone where the text wraps
   further. */
@media (max-width: 781px) {
	.ftf-slash::before {
		inset-inline-start: -0.9rem;
		inline-size: 4px;
		block-size: min(calc(100% + 0.7em), 6.5em);
		transform: skewX(-6deg);
	}
}

/* ---------- Hero lockup ---------- */

.ftf-hero__logo {
	margin-block-end: 1.75rem;
}

.ftf-hero__logo img {
	inline-size: clamp(230px, 26vw, 340px);
	block-size: auto;
	filter: drop-shadow(0 18px 34px rgba(0, 0, 0, 0.7));
}

/* Sized by height rather than width on desktop, because height is what pushes the call
   to action off the fold. At 1440x900 the logo was 225px tall and the buttons ended at
   984px — below a 900px viewport. This must sit after the rule above: an override with
   the same specificity placed earlier in the file loses, which is exactly what happened
   on the first attempt. */
@media (min-width: 782px) {
	.ftf-hero__logo {
		margin-block-end: 1.25rem;
	}

	.ftf-hero__logo img {
		inline-size: auto;
		block-size: clamp(110px, 11vw, 150px);
	}
}

/* Spray mist creeping in from the right, echoing the logo's overspray. */
.ftf-hero::before {
	content: "";
	position: absolute;
	inset-block: 0;
	inset-inline-end: 0;
	inline-size: 42%;
	z-index: 1;
	pointer-events: none;
	background-image: radial-gradient(circle at 1px 1px, rgba(255, 255, 255, 0.16) 1px, transparent 0);
	background-size: 7px 7px;
	-webkit-mask-image: linear-gradient(90deg, transparent 0%, rgba(0, 0, 0, 0.55) 55%, rgba(0, 0, 0, 0.85) 100%);
	mask-image: linear-gradient(90deg, transparent 0%, rgba(0, 0, 0, 0.55) 55%, rgba(0, 0, 0, 0.85) 100%);
	opacity: 0.5;
}

@media (max-width: 781px) {
	.ftf-hero::before {
		display: none;
	}

	.ftf-hero__logo img {
		inline-size: min(240px, 62vw);
	}
}

/* ---------- Header brand wordmark ----------
   The badge is a detailed illustration; at header size it turns to mush. The name set
   in chrome reads at a glance, and the badge still leads the hero. */

.ftf-brand__name {
	font-size: clamp(1.2rem, 2.1vw, 1.7rem) !important;
	letter-spacing: 0.01em;
	line-height: 1.05;
}

.ftf-brand__name a {
	text-decoration: none;
}

.ftf-brand__strap {
	margin: 6px 0 0 !important;
	font-size: 0.72rem;
	font-weight: 700;
	letter-spacing: 0.22em;
	text-transform: uppercase;
	color: var(--wp--preset--color--accent-bright);
}

/* Opening hours sit between the brand and the buttons so the row is not two
   clusters with a void between them. */
.ftf-header__hours {
	margin: 0 !important;
	font-size: 0.82rem;
	font-weight: 600;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: var(--wp--preset--color--muted);
	white-space: nowrap;
}

@media (max-width: 900px) {
	.ftf-header__hours {
		display: none;
	}
}

@media (max-width: 620px) {
	.ftf-brand__strap {
		letter-spacing: 0.14em;
		font-size: 0.62rem;
	}
}

/* ---------- Stats strip on brand red ---------- */

.ftf-stats {
	position: relative;
}

/* Chrome hairline top and bottom, the way the logo's banner is edged. */
.ftf-stats::before,
.ftf-stats::after {
	content: "";
	position: absolute;
	inset-inline: 0;
	block-size: 1px;
	background: linear-gradient(90deg, transparent, rgba(255, 255, 255, 0.45), transparent);
}

.ftf-stats::before { inset-block-start: 0; }
.ftf-stats::after  { inset-block-end: 0; }

/* ---------- WhatsApp button ----------
   Sits alongside the hero's primary and secondary buttons. Deliberately not filled
   with WhatsApp green: three saturated fills side by side would fight, and the red
   "Get a free quote" has to stay the obvious primary. The glyph carries the brand
   green so it is still scannable at a glance. */

.ftf-wa {
	display: inline-flex;
	align-items: center;
	gap: 0.6rem;
	padding: 14px 26px;
	border: 2px solid rgba(245, 246, 247, 0.85);
	border-radius: 999px;
	font-family: var(--wp--preset--font-family--body);
	font-size: 1rem;
	font-weight: 700;
	line-height: 1;
	color: var(--wp--preset--color--contrast);
	text-decoration: none;
	background: transparent;
	transition: border-color 0.16s ease, background-color 0.16s ease, transform 0.16s ease;
}

.ftf-wa:hover {
	border-color: #25d366;
	background: rgba(37, 211, 102, 0.12);
	color: var(--wp--preset--color--contrast);
	transform: translateY(-1px);
	text-decoration: none;
}

.ftf-wa:active {
	transform: translateY(0);
}

.ftf-wa:focus-visible {
	outline: 2px solid #25d366;
	outline-offset: 3px;
}

.ftf-wa svg {
	inline-size: 20px;
	block-size: 20px;
	flex: none;
	fill: #25d366;
}

@media (max-width: 781px) {
	.ftf-wa {
		padding: 13px 22px;
	}
}
