/* ==========================================================================
   SAN DIEGO BBQ CLEANERS - ORGANISMS
   Cascade position 5. Depends on foundations.css tokens.

   Page-level composites: header, footer, and the eight front-page sections.
   One rule set per section, no breakpoint duplicates. The Elementor build
   shipped a desktop copy and a mobile copy of six of these.
   ========================================================================== */

/* ==========================================================================
   HEADER
   Three columns: brand, menu, actions. Flex would centre the menu in whatever
   space is left over, which shifts every time the logo or the phone number
   changes width.
   ========================================================================== */

.sdb-header {
	position: sticky;
	top: 0;
	z-index: 100;
	background: rgba(24, 26, 29, .72);
	backdrop-filter: saturate(150%) blur(14px);
}

.sdb-header::after {
	content: "";
	position: absolute;
	left: 0; right: 0; bottom: 0;
	height: 1px;
	background: var(--sdb-chrome-edge);
}

/* Logo and menu together on the left, actions on the right. The menu reads as
   part of the brand block rather than floating in the middle of the bar. */
.sdb-header__inner {
	display: flex;
	align-items: center;
	gap: var(--sdb-s5);
	min-height: 76px;
}

.sdb-header__logo {
	display: flex;
	align-items: center;
	gap: 12px;
	flex: none;
	text-decoration: none;
}

/* Sheen. A wide highlight crossing the plate on overlay blend, so it lifts the
   brushed texture already in the artwork rather than painting over it.

   Fires once on load and again on hover. Not on a timer: periodic motion in
   the corner of the eye while somebody is reading is the thing ad blockers
   exist for, and a repeating animation would need a site-wide pause control
   under WCAG 2.2.2. Hover is user-triggered, so it is exempt. */
.sdb-header__logo--custom {
	position: relative;
	overflow: hidden;
	flex: none;
}

.sdb-header__logo--custom::after {
	content: "";
	position: absolute;
	inset: 0;
	pointer-events: none;
	mix-blend-mode: overlay;
	background: linear-gradient(105deg,
		transparent 38%,
		rgba(255, 255, 255, .55) 47%,
		rgba(255, 255, 255, .9) 50%,
		rgba(255, 255, 255, .55) 53%,
		transparent 62%);
	background-size: 220% 100%;
	background-position: 150% 0;

	/* Clipped to the logo's alpha. Without this the band is a rectangle over
	   the bounding box, and the lockup is a banner shape with transparency
	   around it, so the sheen showed above, below and past both ends. */
	-webkit-mask-image: var(--sdb-logo-mask);
	        mask-image: var(--sdb-logo-mask);
	-webkit-mask-size: 100% 100%;
	        mask-size: 100% 100%;
	-webkit-mask-repeat: no-repeat;
	        mask-repeat: no-repeat;
}

/* No logo set, no mask: do not run a rectangle across the header. */
.sdb-header__logo--custom:not([style*="--sdb-logo-mask"])::after { display: none; }

.sdb-header__logo--custom.is-sheening::after {
	animation: sdb-sheen 3400ms cubic-bezier(.25, .35, .2, 1) 1 forwards;
}

@keyframes sdb-sheen {
	from { background-position: 150% 0; }
	to   { background-position: -50% 0; }
}

@media (prefers-reduced-motion: reduce) {
	.sdb-header__logo--custom::after { display: none; }
}

/* WordPress writes width and height attributes onto the custom logo, so both
   axes have to be released or the intrinsic size wins. */
.sdb-header__logo :where(a, img) { display: block; }

.sdb-header__logo img {
	width: auto;
	height: auto;
	max-height: 46px;
	max-width: 260px;
	object-fit: contain;
}

@media (max-width: 1180px) {
	.sdb-header__logo img { max-height: 40px; max-width: 200px; }
}

@media (max-width: 480px) {
	.sdb-header__logo img { max-height: 36px; max-width: 168px; }
}

.sdb-header__mark { width: 18px; height: auto; flex: none; }
.sdb-header__mark use { fill: url(#sdb-chrome-grad); }

/* Wordmark fallback carries the chrome sweep, fired once on load. A solid
   colour is declared first so the text survives if the clip fails. */
.sdb-header__wordmark {
	font-family: var(--sdb-font-display);
	font-variation-settings: "wdth" var(--sdb-display-wide);
	font-weight: 700;
	font-size: 17px;
	letter-spacing: .04em;
	text-transform: uppercase;
	color: #E6EAED;
	background: linear-gradient(105deg,
		var(--sdb-cr-2) 0%, var(--sdb-cr-2) 38%,
		var(--sdb-cr-1) 46%, #fff 50%, var(--sdb-cr-1) 54%,
		var(--sdb-cr-2) 62%, var(--sdb-cr-2) 100%);
	background-size: 280% 100%;
	background-position: 120% 0;
	animation: sdb-sweep 1700ms cubic-bezier(.2, .7, .2, 1) 500ms 1 forwards;
}

@supports ((-webkit-background-clip: text) or (background-clip: text)) {
	.sdb-header__wordmark { -webkit-background-clip: text; background-clip: text; color: transparent; }
}

@keyframes sdb-sweep {
	from { background-position: 120% 0; }
	to   { background-position: -20% 0; }
}

@media (prefers-reduced-motion: reduce) {
	.sdb-header__wordmark { animation: none; background-position: 50% 0; }
}

.sdb-header__actions {
	display: flex;
	align-items: center;
	justify-content: flex-end;
	gap: var(--sdb-s3);
}

/* Secondary to the button, not a rival to it. The icon makes it findable; the
   size keeps it in second place. */
.sdb-header__tel {
	display: inline-flex;
	align-items: center;
	gap: 7px;
	white-space: nowrap;
	font-size: 15px;
	font-weight: var(--sdb-w-semi);
	color: rgba(255, 255, 255, .82);
	text-decoration: none;
	transition: color .2s ease;
}

.sdb-header__tel .sdb-icon { width: 14px; height: 14px; stroke: var(--sdb-red-hot); stroke-width: 2.2; transition: stroke .2s ease; }
.sdb-header__tel:hover { color: var(--sdb-red-hot); }
.sdb-header__tel:hover .sdb-icon { stroke: var(--sdb-white); }

.sdb-header__cta { padding: 14px 24px; font-size: 15px; }

.sdb-header__toggle {
	display: none;
	width: 44px;
	height: 44px;
	padding: 0;
	border: 0;
	background: none;
	cursor: pointer;
}

.sdb-header__bars,
.sdb-header__bars::before,
.sdb-header__bars::after {
	display: block;
	width: 22px;
	height: 2px;
	background: var(--sdb-white);
	transition: transform .2s ease, opacity .2s ease;
}

.sdb-header__bars { margin-inline: auto; position: relative; }
.sdb-header__bars::before,
.sdb-header__bars::after { content: ""; position: absolute; left: 0; }
.sdb-header__bars::before { top: -7px; }
.sdb-header__bars::after  { top: 7px; }

[aria-expanded="true"] .sdb-header__bars { background: transparent; }
[aria-expanded="true"] .sdb-header__bars::before { transform: translateY(7px) rotate(45deg); }
[aria-expanded="true"] .sdb-header__bars::after  { transform: translateY(-7px) rotate(-45deg); }

/* ==========================================================================
   PRIMARY NAV
   Three services. Service areas, about and contact live in the footer, which
   still gives them a link on every page without crowding the bar.
   No underline: state is weight, colour and a single ember dot.
   ========================================================================== */

.sdb-nav { margin-right: auto; }

.sdb-nav__list {
	display: flex;
	align-items: center;
	gap: var(--sdb-s5);
	margin: 0;
	padding: 0;
	list-style: none;
}

.sdb-nav__item,
.sdb-nav__list > li { position: relative; }

.sdb-nav__link,
.sdb-nav a {
	position: relative;
	/* Scopes the flame's negative z-index to this link. Without it the flame
	   resolves against the header, which is sticky with z-index 100 and
	   therefore a stacking context, and would paint behind the header's own
	   background instead of behind the text. */
	isolation: isolate;
	display: block;
	padding: 26px 0;
	font-family: var(--sdb-font-body);
	font-size: 14px;
	font-weight: 700;
	letter-spacing: .06em;
	text-transform: uppercase;
	color: rgba(255, 255, 255, .84);
	text-decoration: none;
	white-space: nowrap;
	transition: color .2s ease;
}

.sdb-nav a:hover { color: var(--sdb-white); }

.sdb-nav a[aria-current] { color: var(--sdb-white); }

/* The mark rises behind the label on hover. The drift is doing more work than
   the fade: without it this reads as a graphic appearing rather than a flame
   catching. Sits behind the text, takes no pointer events, and is removed
   entirely under reduced motion. Focus gets the same treatment so it is not
   mouse-only. */
.sdb-nav__flame {
	position: absolute;
	left: 50%;
	bottom: 8px;
	height: 58px;
	width: auto;
	z-index: -1;
	opacity: 0;
	transform: translate(-50%, 10px);
	pointer-events: none;
	transition: opacity 900ms ease, transform 900ms cubic-bezier(.2, .7, .2, 1);
}

.sdb-nav__flame path { fill: url(#sdb-flame-grad); }

.sdb-nav a:hover .sdb-nav__flame,
.sdb-nav a:focus-visible .sdb-nav__flame {
	opacity: .30;
	transform: translate(-50%, 0);
}

@media (prefers-reduced-motion: reduce) {
	.sdb-nav__flame { display: none; }
}

/* In the mobile drawer the labels are stacked and left-aligned, so a centred
   flame behind each one would be a column of marks down the middle. */
@media (max-width: 1024px) {
	.sdb-nav__flame { display: none; }
}

.sdb-nav a[aria-current]::before {
	content: "";
	position: absolute;
	left: 50%;
	bottom: 20px;
	width: 5px;
	height: 5px;
	margin-left: -2.5px;
	border-radius: 50%;
	background: var(--sdb-red-hot);
	box-shadow: 0 0 10px rgba(204, 89, 68, .9);
}

/* Narrow desktop: tighten before the bar wraps. */
@media (max-width: 1180px) {
	.sdb-header__inner { gap: var(--sdb-s4); }
	.sdb-nav__list { gap: var(--sdb-s4); }
	.sdb-nav a { font-size: 13px; letter-spacing: .05em; }
}

@media (max-width: 1024px) {
	/* The nav becomes a fixed drawer, so it is out of the flex flow. The
	   actions have to claim the remaining space themselves. */
	.sdb-nav { margin-right: 0; }
	.sdb-header__actions { margin-left: auto; }
	.sdb-header__toggle { display: block; }
	.sdb-header__tel span { display: none; }
	.sdb-header__tel { padding: 10px; }
	.sdb-header__actions { gap: var(--sdb-s2); }

	/* ---- Drawer (redesigned 2026-10-14) ------------------------------
	   Services as photo rows first, then the other pages as tiles, then
	   booking and the phone pinned to the bottom. Opens with a fade and a
	   short rise, items stagger in by --i. No shadows: rows sit on the well
	   with a chrome hairline, like every other card on the site. */
	.sdb-nav {
		position: fixed;
		inset: 76px 0 0 0;
		display: flex;
		flex-direction: column;
		padding: var(--sdb-s3) var(--sdb-gutter) 0;
		background: var(--sdb-ink);
		overflow-y: auto;
		overscroll-behavior: contain;
		visibility: hidden;
		opacity: 0;
		transform: translateY(-8px);
		transition: opacity .28s ease, transform .36s cubic-bezier(.2, .7, .2, 1), visibility 0s linear .36s;
	}

	.sdb-nav::before {
		content: "";
		position: absolute;
		left: 0; right: 0; top: 0;
		height: 1px;
		background: var(--sdb-chrome-edge);
		opacity: .5;
	}

	.sdb-nav.is-open { visibility: visible; opacity: 1; transform: none; transition: opacity .28s ease, transform .36s cubic-bezier(.2, .7, .2, 1), visibility 0s; }

	/* Stagger. */
	.sdb-nav__list > li,
	.sdb-nav__more > li,
	.sdb-nav__act {
		opacity: 0;
		transform: translateX(18px);
		transition: opacity .4s ease, transform .5s cubic-bezier(.2, .7, .2, 1);
		transition-delay: 0s;
	}
	.sdb-nav.is-open .sdb-nav__list > li,
	.sdb-nav.is-open .sdb-nav__more > li,
	.sdb-nav.is-open .sdb-nav__act {
		opacity: 1;
		transform: none;
		transition-delay: calc(60ms + var(--i, 0) * 45ms);
	}

	/* Services: photo rows. */
	.sdb-nav__list { flex-direction: column; align-items: stretch; gap: var(--sdb-s1); }

	.sdb-nav .sdb-nav__link {
		display: grid;
		grid-template-columns: 56px 1fr 20px;
		align-items: center;
		gap: var(--sdb-s2);
		padding: 10px 14px 10px 10px;
		border-radius: var(--sdb-radius-card);
		background: var(--sdb-well);
		text-transform: none;
		letter-spacing: 0;
		white-space: normal;
		transition: background .25s ease;
	}
	.sdb-nav .sdb-nav__link::after {
		content: "";
		position: absolute;
		inset: 0;
		border-radius: inherit;
		padding: 1px;
		background: var(--sdb-chrome-edge);
		-webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
		-webkit-mask-composite: xor;
		mask-composite: exclude;
		opacity: .35;
		pointer-events: none;
		transition: opacity .25s ease;
	}
	.sdb-nav .sdb-nav__link:hover,
	.sdb-nav .sdb-nav__link:active { background: var(--sdb-raised); }
	.sdb-nav .sdb-nav__link:hover::after,
	.sdb-nav .sdb-nav__link[aria-current]::after { opacity: .9; }

	.sdb-nav__thumb { display: block; width: 56px; height: 56px; border-radius: 10px; overflow: hidden; background: var(--sdb-raised); }
	.sdb-nav__thumb img { display: block; width: 100%; height: 100%; object-fit: cover; transition: transform .6s cubic-bezier(.2, .7, .2, 1); }
	.sdb-nav__link:hover .sdb-nav__thumb img { transform: scale(1.08); }

	.sdb-nav__txt { display: grid; gap: 2px; min-width: 0; }
	.sdb-nav__label {
		font-family: var(--sdb-font-display);
		font-variation-settings: "wdth" var(--sdb-display-wide);
		font-size: 1.25rem;
		font-weight: 700;
		line-height: 1.1;
		color: var(--sdb-white);
	}
	.sdb-nav__sub { font-size: 13px; font-weight: 500; color: var(--sdb-cr-3); }

	.sdb-nav__chev { width: 20px; height: 20px; stroke: var(--sdb-red-hot); transition: transform .3s cubic-bezier(.2, .7, .2, 1); }
	.sdb-nav__link:hover .sdb-nav__chev,
	.sdb-nav__link:focus-visible .sdb-nav__chev { transform: translateX(4px); }

	/* Current page: raised row, ember sub line, and the dot on the thumb. */
	.sdb-nav .sdb-nav__link[aria-current] { padding-left: 10px; background: var(--sdb-raised); }
	.sdb-nav .sdb-nav__link[aria-current] .sdb-nav__sub { color: var(--sdb-red-hot); }
	.sdb-nav .sdb-nav__link[aria-current]::before { left: 58px; top: 12px; bottom: auto; width: 8px; height: 8px; margin: 0; z-index: 1; }

	/* Logged in, the admin bar pushes the header down (46px under 783px,
	   32px above). Start the drawer under the header either way. */
	.admin-bar .sdb-nav { top: calc(76px + 32px); }

	/* Other pages: two-column tiles. */
	.sdb-nav__more {
		display: grid;
		grid-template-columns: 1fr 1fr;
		gap: var(--sdb-s1);
		margin: var(--sdb-s3) 0 0;
		padding: 0;
		list-style: none;
	}
	.sdb-nav .sdb-nav__more a {
		display: flex;
		align-items: center;
		gap: 10px;
		padding: 14px 12px;
		border-radius: var(--sdb-radius-card);
		background: var(--sdb-well);
		font-size: 15px;
		font-weight: 600;
		color: rgba(244, 247, 249, .86);
		text-transform: none;
		letter-spacing: 0;
		white-space: nowrap;
		transition: background .25s ease, color .25s ease;
	}
	.sdb-nav .sdb-nav__more a:hover { background: var(--sdb-raised); color: var(--sdb-white); }
	.sdb-nav .sdb-nav__more .sdb-icon { width: 18px; height: 18px; flex: none; stroke: var(--sdb-red-hot); }
	.sdb-nav .sdb-nav__more a[aria-current] { color: var(--sdb-white); padding-left: 12px; }
	.sdb-nav .sdb-nav__more a[aria-current]::before { display: none; }

	/* Actions pinned to the bottom of the drawer. */
	.sdb-nav__act {
		position: sticky;
		bottom: 0;
		display: grid;
		grid-template-columns: 1fr 1fr;
		gap: var(--sdb-s1);
		margin: auto calc(var(--sdb-gutter) * -1) 0;
		padding: var(--sdb-s3) var(--sdb-gutter) calc(var(--sdb-s3) + env(safe-area-inset-bottom));
		background: linear-gradient(180deg, rgba(24, 26, 29, 0) 0, var(--sdb-ink) 22px);
	}
	.sdb-nav .sdb-nav__book { grid-column: 1 / -1; display: block; padding: 16px; text-align: center; font-size: 16px; text-transform: none; letter-spacing: 0; color: var(--sdb-white); }
	.sdb-nav .sdb-nav__call,
	.sdb-nav .sdb-nav__contact {
		display: flex;
		align-items: center;
		justify-content: center;
		gap: 8px;
		padding: 13px 10px;
		border-radius: var(--sdb-radius-btn);
		background: var(--sdb-well);
		box-shadow: inset 0 0 0 1px rgba(244, 247, 249, .14);
		font-size: 14px;
		font-weight: 600;
		text-transform: none;
		letter-spacing: 0;
		color: var(--sdb-white);
	}
	.sdb-nav .sdb-nav__call .sdb-icon { width: 16px; height: 16px; stroke: var(--sdb-red-hot); }
	.sdb-nav__act a[aria-current]::before { display: none; }

	html.sdb-nav-locked { overflow: hidden; }

	/* backdrop-filter makes the header the containing block for any fixed
	   child, which clipped the drawer to the header's own 76px and showed one
	   link (2026-10-14). Drop the blur while the drawer is open. */
	html.sdb-nav-locked .sdb-header { backdrop-filter: none; -webkit-backdrop-filter: none; background: var(--sdb-ink); }
}

@media (max-width: 782px) { .admin-bar .sdb-nav { top: calc(76px + 46px); } }

@media (max-width: 1024px) and (prefers-reduced-motion: reduce) {
	.sdb-nav,
	.sdb-nav.is-open,
	.sdb-nav__list > li,
	.sdb-nav__more > li,
	.sdb-nav__act { transition: none !important; transform: none !important; }
	.sdb-nav__thumb img, .sdb-nav__chev { transition: none; }
}

/* Desktop bar: labels only. */
@media (min-width: 1025px) {
	.sdb-nav__more,
	.sdb-nav__act,
	.sdb-nav__thumb,
	.sdb-nav__sub,
	.sdb-nav__chev { display: none; }
	.sdb-nav__txt, .sdb-nav__label { display: inline; }
}

/* Phone widths. The booking button wrapped to two lines and pushed the menu
   toggle 18px past the viewport at 390px, on every page. The logo steps
   down, the button stays on one line, and the phone icon goes only under
   340px, where the drawer and the close still carry the number. */
@media (max-width: 480px) {
	.sdb-header__inner { gap: var(--sdb-s2); }
	.sdb-header__logo, .sdb-header__logo img { max-width: 132px; height: auto; }
	.sdb-header__cta { padding: 9px 14px; font-size: 13px; white-space: nowrap; }
	.sdb-header__tel { padding: 8px 6px; }
	.sdb-header__actions { gap: var(--sdb-s1); }
}

@media (max-width: 380px) {
	.sdb-header__logo, .sdb-header__logo img { max-width: 108px; }
	.sdb-header__cta { padding: 8px 12px; }
	.sdb-header__tel { padding: 8px 4px; }
}

@media (max-width: 340px) { .sdb-header__tel { display: none; } }

/* ==========================================================================
   READING PROGRESS (single posts)
   ========================================================================== */

.sdb-progress {
	position: fixed;
	top: 0; left: 0; right: 0;
	height: 3px;
	z-index: 200;
	pointer-events: none;
}

.sdb-progress__bar {
	display: block;
	height: 100%;
	width: 0;
	background: var(--sdb-red-hot);
}

/* ==========================================================================
   1 - HERO
   Video layer, flame watermark, centred type, proof bar, motion control.
   ========================================================================== */

.sdb-hero {
	position: relative;
	display: grid;
	align-items: center;
	min-height: calc(100svh - 76px);
	overflow: hidden;
	isolation: isolate;
	color: var(--sdb-white);
}

.sdb-hero__media { position: absolute; inset: 0; z-index: -2; }

.sdb-hero__media-el {
	width: 100%;
	height: 100%;
	object-fit: cover;
	object-position: 56% 50%;
	display: block;
	/* Starts dull and desaturated, lifts to full colour once after paint.
	   The service, stated in the first three seconds. */
	filter: saturate(.5) brightness(.5) contrast(1.06);
	transform: scale(1.06);
	transition: filter 2200ms cubic-bezier(.2, .7, .2, 1), transform 2600ms cubic-bezier(.2, .7, .2, 1);
}

.sdb-hero.is-lit .sdb-hero__media-el {
	filter: saturate(1) brightness(.88) contrast(1);
	transform: scale(1);
}

/* A vignette, not an angled wash. Clear through the middle where the grill
   is, dark at the edges and top where the type needs a bed. */
.sdb-hero__media::after {
	content: "";
	position: absolute;
	inset: 0;
	background:
		radial-gradient(118% 92% at 50% 44%, rgba(15, 17, 19, .18) 0%, rgba(15, 17, 19, .52) 46%, rgba(15, 17, 19, .88) 100%),
		linear-gradient(180deg, rgba(15, 17, 19, .62) 0%, transparent 26%, transparent 58%, rgba(15, 17, 19, .78) 100%);
}

/* The mark, oversized, rising behind the headline. Three paths drifting at
   different speeds so it reads as flame rather than a decal. */
.sdb-hero__flame {
	position: absolute;
	left: 50%;
	bottom: -18%;
	height: 128%;
	width: auto;
	z-index: -1;
	opacity: 0;
	pointer-events: none;
	animation: sdb-flame-in 1400ms cubic-bezier(.2, .7, .2, 1) 700ms forwards;
}

.sdb-hero__flame path { fill: url(#sdb-flame-grad); }
.sdb-hero__flame path:nth-child(1) { transform-origin: 50% 100%; animation: sdb-lick 5.5s ease-in-out 2.4s infinite; }
.sdb-hero__flame path:nth-child(2) { transform-origin: 50% 100%; animation: sdb-lick 6.8s ease-in-out 2.9s infinite; }
.sdb-hero__flame path:nth-child(3) { transform-origin: 50% 100%; animation: sdb-lick 6.1s ease-in-out 2.1s infinite; }
.sdb-hero.is-paused .sdb-hero__flame path,
body.sdb-motion-paused .sdb-hero__flame path { animation-play-state: paused; }

@keyframes sdb-flame-in {
	from { opacity: 0; transform: translate(-50%, 40px); }
	to   { opacity: .14; transform: translate(-50%, 0); }
}

@keyframes sdb-lick {
	0%, 100% { transform: scaleY(1) translateY(0); }
	50%      { transform: scaleY(1.035) translateY(-8px); }
}

.sdb-hero__inner { position: relative; padding-block: var(--sdb-s7); text-align: center; }

/* Solid white. The heat gradient was tried and dropped: across a two-line
   headline the second line sits entirely in the hot end of the ramp and reads
   as a different colour rather than as a warm baseline. */
.sdb-hero__title {
	max-width: 14ch;
	margin: 0 auto;
	color: var(--sdb-white);
	opacity: 0;
	animation: sdb-rise 1000ms cubic-bezier(.2, .7, .2, 1) 300ms forwards;
}

.sdb-hero__lede {
	max-width: 50ch;
	margin: var(--sdb-s2) auto 0;
	font-size: clamp(1.0625rem, 1.5vw, 1.3125rem);
	line-height: 1.5;
	color: rgba(255, 255, 255, .78);
	opacity: 0;
	animation: sdb-rise 1000ms cubic-bezier(.2, .7, .2, 1) 440ms forwards;
}

/* The three services live in the sentence. As a row of their own they read as
   an interrupted sub-heading and duplicated the nav. */
.sdb-hero__verb {
	position: relative;
	color: var(--sdb-white);
	font-weight: var(--sdb-w-med);
	text-decoration: none;
	white-space: nowrap;
}

.sdb-hero__verb::after {
	content: "";
	position: absolute;
	left: 0; right: 0; bottom: -2px;
	height: 1px;
	background: var(--sdb-red-hot);
	opacity: .5;
	transition: opacity .25s ease, height .25s ease;
}

.sdb-hero__verb:hover { color: var(--sdb-red-hot); }
.sdb-hero__verb:hover::after { opacity: 1; height: 2px; }

.sdb-hero__cta {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: center;
	gap: var(--sdb-s3);
	margin: var(--sdb-s5) 0 0;
	opacity: 0;
	animation: sdb-rise 1000ms cubic-bezier(.2, .7, .2, 1) 700ms forwards;
}

.sdb-btn--lg { padding: 21px 38px; font-size: 17px; }

/* One primary action. A matching second button is a decision, and a hero
   should ask for one thing. */
.sdb-hero__alt {
	font-size: .9375rem;
	font-weight: var(--sdb-w-med);
	color: var(--sdb-cr-2);
	text-decoration: underline;
	text-underline-offset: 5px;
	text-decoration-thickness: 1px;
}

.sdb-hero__alt:hover { color: var(--sdb-white); }

@keyframes sdb-rise {
	from { opacity: 0; transform: translateY(18px); }
	to   { opacity: 1; transform: none; }
}

/* ==========================================================================
   MOTION CONTROL
   WCAG 2.2.2. Anything moving on its own for more than five seconds beside
   other content needs an in-page mechanism. prefers-reduced-motion is not a
   substitute: the criterion asks for a control. One button stops the video
   and the flame together.
   ========================================================================== */

.sdb-motion {
	position: absolute;
	right: var(--sdb-gutter);
	bottom: var(--sdb-s4);
	z-index: 5;
	display: inline-flex;
	align-items: center;
	gap: 8px;
	padding: 9px 16px;
	border: 0;
	border-radius: var(--sdb-radius-btn);
	background: rgba(15, 17, 19, .62);
	backdrop-filter: blur(8px);
	box-shadow: inset 0 0 0 1px rgba(244, 247, 249, .22);
	color: var(--sdb-white);
	font-family: var(--sdb-font-body);
	font-size: 12px;
	font-weight: var(--sdb-w-med);
	line-height: 1;
	cursor: pointer;
}

.sdb-motion:hover { background: rgba(15, 17, 19, .82); }
.sdb-motion .sdb-icon { width: 12px; height: 12px; fill: currentColor; stroke: none; display: block; }
.sdb-motion__play { display: none; }
.sdb-hero.is-paused .sdb-motion__pause { display: none; }
.sdb-hero.is-paused .sdb-motion__play { display: block; }

/* ==========================================================================
   PROOF BAR
   ========================================================================== */

.sdb-proof {
	position: relative;
	display: flex;
	flex-wrap: wrap;
	justify-content: center;
	gap: var(--sdb-s5);
	margin-top: var(--sdb-s7);
	padding-top: var(--sdb-s3);
	opacity: 0;
	animation: sdb-rise 1000ms cubic-bezier(.2, .7, .2, 1) 860ms forwards;
}

/* Inset, not edge to edge. A full-width rule under centred content reads as
   a mistake. */
.sdb-proof div b {
	display: block;
	font-family: var(--sdb-font-display);
	font-variation-settings: "wdth" var(--sdb-display-wide);
	font-weight: 700;
	font-size: 1.625rem;
	letter-spacing: -.01em;
	line-height: 1.1;
	color: var(--sdb-white);
}

.sdb-proof div span { font-size: var(--sdb-tiny); color: var(--sdb-cr-3); }
.sdb-proof__stars { display: inline-flex; gap: 2px; color: var(--sdb-red-hot); vertical-align: -2px; }
.sdb-proof__stars .sdb-icon { width: 14px; height: 14px; fill: currentColor; stroke: none; }

@media (max-width: 900px) {
	.sdb-hero { min-height: auto; }
	.sdb-hero__inner { padding-block: var(--sdb-s6); }
	.sdb-hero__flame { height: 92%; bottom: -10%; }
	.sdb-proof { gap: var(--sdb-s4); margin-top: var(--sdb-s6); }
}

@media (max-width: 640px) {
	.sdb-motion { bottom: var(--sdb-s2); right: var(--sdb-s2); }
}

@media (prefers-reduced-motion: reduce) {
	.sdb-hero__title,
	.sdb-hero__lede,
	.sdb-hero__cta,
	.sdb-proof { opacity: 1; animation: none; }
	.sdb-hero__flame { opacity: .14; animation: none; }
	.sdb-hero__media-el { filter: saturate(1) brightness(.88); transform: none; transition: none; }
}

/* ==========================================================================
   2 - SERVICES
   One lead card and two beside it. Three equal thirds is the default grid and
   it tells the visitor the three things matter equally, which is not true:
   cleaning is the volume service and the one most people arrive for.

   Nothing is hidden on hover. The side cards carry no paragraph at all,
   because "Repair" under "Something has stopped working" is already the whole
   message. That gets the same quiet as a reveal without a hover state, a
   focus state, a pointer media query and a reduced-motion rule, and without
   anything to break on touch.
   ========================================================================== */

.sdb-services__head {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: var(--sdb-s5);
	flex-wrap: wrap;
	margin-bottom: var(--sdb-s5);
}

/* Ember across the whole line, not one word. A gradient over part of a
   heading is decoration; end to end on a single line it reads as heat. It
   only works on one line, which is why the hero headline is plain white. */
.sdb-services__title {
	max-width: 18ch;
	margin: 0;
	color: var(--sdb-white);
	background: linear-gradient(100deg, #FFFFFF 0%, #FFF4EF 34%, #F0BFAE 66%, #CC5944 100%);
}

@supports ((-webkit-background-clip: text) or (background-clip: text)) {
	.sdb-services__title { -webkit-background-clip: text; background-clip: text; color: transparent; }
}

/* The heading asks a question, so this answers it for anyone the three cards
   do not reach. */
.sdb-ask {
	display: inline-flex;
	align-items: center;
	gap: 14px;
	padding: 14px 20px 14px 16px;
	border-radius: 14px;
	background: rgba(244, 247, 249, .04);
	box-shadow: inset 0 0 0 1px rgba(244, 247, 249, .14);
	text-decoration: none;
	transition: background-color .35s ease, box-shadow .35s ease, transform .35s ease;
}

.sdb-ask:hover {
	background: rgba(244, 247, 249, .07);
	box-shadow: inset 0 0 0 1px rgba(204, 89, 68, .55);
	transform: translateY(-1px);
}

.sdb-ask__icon {
	display: grid;
	place-items: center;
	width: 38px;
	height: 38px;
	flex: none;
	border-radius: 50%;
	background: rgba(204, 89, 68, .14);
}

.sdb-ask__icon .sdb-icon { width: 19px; height: 19px; stroke: var(--sdb-red-hot); stroke-width: 1.7; }
.sdb-ask__txt { display: flex; flex-direction: column; gap: 2px; }
.sdb-ask__txt b { font-size: .9375rem; font-weight: var(--sdb-w-semi); color: var(--sdb-white); }
.sdb-ask__txt em { font-style: normal; font-size: var(--sdb-tiny); color: var(--sdb-cr-3); }

.sdb-services__grid {
	display: grid;
	grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
	gap: var(--sdb-s3);
}

.sdb-services__col { display: grid; gap: var(--sdb-s3); }

.sdb-svc {
	position: relative;
	display: flex;
	align-items: flex-end;
	border-radius: var(--sdb-radius-img);
	overflow: hidden;
	isolation: isolate;
	text-decoration: none;
}

/* Graded dark at rest, lifting once on scroll, the same treatment the hero
   footage gets. The hover brighten is faster than the arrival: if they
   matched, hovering would feel broken. Both eased slowly on purpose. */
.sdb-svc__img {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	object-fit: cover;
	z-index: -2;
	filter: saturate(.45) brightness(.46) contrast(1.05);
	transform: scale(1.04);
	transition: filter 1800ms cubic-bezier(.2, .7, .2, 1), transform 1800ms cubic-bezier(.2, .7, .2, 1);
}

.sdb-svc.is-lit .sdb-svc__img { filter: saturate(.95) brightness(.72) contrast(1); transform: scale(1); }

.sdb-svc:hover .sdb-svc__img,
.sdb-svc:focus-visible .sdb-svc__img {
	filter: saturate(1) brightness(.86);
	transform: scale(1.045);
	transition-duration: 1100ms;
}

.sdb-svc::after {
	content: "";
	position: absolute;
	inset: 0;
	z-index: -1;
	background: linear-gradient(0deg,
		rgba(15, 17, 19, .96) 0%,
		rgba(15, 17, 19, .78) 38%,
		rgba(15, 17, 19, .34) 70%,
		rgba(15, 17, 19, .08) 100%);
}

.sdb-svc__flame {
	position: absolute;
	right: -4%;
	bottom: -20%;
	height: 120%;
	width: auto;
	z-index: -1;
	opacity: .10;
	pointer-events: none;
}

.sdb-svc__flame path { fill: url(#sdb-flame-grad); }

/* Glass, not a solid panel: it takes its colour from the photograph behind it
   and stays legible wherever the image is bright. The dot is the only looping
   animation in the section, so the hero motion control stops it too. */
.sdb-svc__badge {
	position: absolute;
	top: var(--sdb-s3);
	left: var(--sdb-s3);
	z-index: 2;
	display: inline-flex;
	align-items: center;
	gap: 8px;
	padding: 7px 14px 7px 12px;
	border-radius: var(--sdb-radius-btn);
	background: rgba(15, 17, 19, .42);
	backdrop-filter: blur(14px) saturate(140%);
	-webkit-backdrop-filter: blur(14px) saturate(140%);
	box-shadow: inset 0 0 0 1px rgba(244, 247, 249, .18);
	font-size: 11px;
	font-weight: var(--sdb-w-semi);
	color: var(--sdb-white);
}

.sdb-svc__badge::before {
	content: "";
	width: 6px;
	height: 6px;
	border-radius: 50%;
	background: var(--sdb-red-hot);
	box-shadow: 0 0 9px rgba(204, 89, 68, .95);
	animation: sdb-ember 3600ms ease-in-out infinite;
}

body.sdb-motion-paused .sdb-svc__badge::before { animation-play-state: paused; }

@keyframes sdb-ember {
	0%, 100% { opacity: 1; transform: scale(1); }
	50%      { opacity: .55; transform: scale(.82); }
}

.sdb-svc__txt { position: relative; padding: var(--sdb-s4); }
/* Was 12px ember red straight on the photograph, which disappeared on the
   busier shots (2026-10-14). White on a stronger grade, with the ember kept
   as a dot so the label still reads as the accent. */
.sdb-svc__when { display: flex; align-items: center; gap: 8px; margin: 0 0 var(--sdb-s1); font-size: 13px; font-weight: var(--sdb-w-semi); color: rgba(255, 255, 255, .92); }
.sdb-svc__when::before { content: ""; flex: none; width: 6px; height: 6px; border-radius: 50%; background: var(--sdb-red-hot); }

/* The lead card's badge sits top left; on a phone the text block grew up into
   it. Reserve the badge's height above the text. */
.sdb-svc:has(.sdb-svc__badge) .sdb-svc__txt { padding-top: calc(var(--sdb-s3) + 56px); }
.sdb-svc__title { margin: 0 0 12px; color: var(--sdb-white); }
.sdb-svc__copy { margin: 0; color: rgba(255, 255, 255, .82); }

.sdb-svc--lead { min-height: 520px; }
.sdb-svc--lead .sdb-svc__title { font-size: clamp(1.9rem, 3.2vw, 2.75rem); }
.sdb-svc--lead .sdb-svc__copy { max-width: 42ch; font-size: var(--sdb-lead); }

.sdb-svc--side { min-height: 248px; }
.sdb-svc--side .sdb-svc__txt { padding: var(--sdb-s3); }
.sdb-svc--side .sdb-svc__title { font-size: var(--sdb-h5); margin-bottom: 6px; }

.sdb-svc__meta { display: flex; flex-wrap: wrap; gap: 10px; margin-top: var(--sdb-s4); }

.sdb-chip {
	display: flex;
	flex-direction: column;
	gap: 2px;
	padding: 10px 16px;
	border-radius: 12px;
	background: rgba(15, 17, 19, .38);
	backdrop-filter: blur(16px) saturate(140%);
	-webkit-backdrop-filter: blur(16px) saturate(140%);
	box-shadow: inset 0 0 0 1px rgba(244, 247, 249, .16);
	transition: box-shadow .8s ease, background-color .8s ease;
}

.sdb-svc:hover .sdb-chip {
	background: rgba(15, 17, 19, .46);
	box-shadow: inset 0 0 0 1px rgba(244, 247, 249, .30);
}

.sdb-chip b {
	font-family: var(--sdb-font-display);
	font-variation-settings: "wdth" var(--sdb-display-wide);
	font-weight: 700;
	font-size: 1.0625rem;
	line-height: 1.1;
	letter-spacing: -.01em;
	color: var(--sdb-white);
}

.sdb-chip span { font-size: .75rem; line-height: 1.2; color: var(--sdb-cr-2); }

/* The affordance. A text label rather than an arrow, because an arrow on a
   link is decoration pretending to be information. Appears on focus as well
   as hover so it is not mouse-only. */
.sdb-svc__go {
	display: inline-flex;
	align-items: center;
	gap: 8px;
	margin-top: var(--sdb-s3);
	font-size: var(--sdb-small);
	font-weight: var(--sdb-w-semi);
	color: var(--sdb-white);
	opacity: 0;
	transform: translateY(8px);
	transition: opacity .8s ease, transform .85s cubic-bezier(.2, .7, .2, 1);
}

.sdb-svc--side .sdb-svc__go { margin-top: var(--sdb-s2); }

.sdb-svc:hover .sdb-svc__go,
.sdb-svc:focus-visible .sdb-svc__go { opacity: 1; transform: none; }

.sdb-svc__go i {
	display: block;
	width: 26px;
	height: 1px;
	background: var(--sdb-red-hot);
	transition: width .8s cubic-bezier(.2, .7, .2, 1);
}

.sdb-svc:hover .sdb-svc__go i { width: 40px; }

@media (max-width: 900px) {
	.sdb-services__head { display: block; }
	.sdb-ask { width: 100%; margin-top: var(--sdb-s3); }
	.sdb-services__grid { grid-template-columns: 1fr; }
	.sdb-svc--lead { min-height: 400px; }
}

@media (prefers-reduced-motion: reduce) {
	.sdb-svc__img { filter: saturate(.95) brightness(.72); transform: none; transition: none; }
	.sdb-svc__go { opacity: 1; transform: none; }
	.sdb-svc__badge::before { animation: none; }
}

/* ==========================================================================
   3 - PROOF
   The before and after, directly under the services. Evidence for the claim
   the cards just made.
   ========================================================================== */

.sdb-proofshot { padding-top: 0; }

/* Ember end to end, as on the services heading. */
.sdb-proofshot__title {
	max-width: 20ch;
	margin: 0 0 var(--sdb-s4);
	font-size: clamp(1.6rem, 3vw, 2.25rem);
	color: var(--sdb-white);
	background: linear-gradient(100deg, #FFFFFF 0%, #FFF4EF 34%, #F0BFAE 66%, #CC5944 100%);
}

@supports ((-webkit-background-clip: text) or (background-clip: text)) {
	.sdb-proofshot__title { -webkit-background-clip: text; background-clip: text; color: transparent; }
}

/* ==========================================================================
   4 - REVIEWS WALL
   Three columns of cards drifting vertically at offset speeds, masked top
   and bottom, paused on hover. Pattern ported from the Muskoka theme.
   Reduced motion, or fewer than six cards, gets a still grid.
   ========================================================================== */

/* Dark, like every other section. It had been white, which with the brands
   band gave the page a dark / white / dark / white flip. */
.sdb-rwall { background: transparent; }

.sdb-rwall__head {
	max-width: 640px;
	margin: 0 auto var(--sdb-s5);
	text-align: center;
}

.sdb-rwall__badge {
	display: inline-flex;
	align-items: center;
	gap: var(--sdb-s1);
	margin-bottom: var(--sdb-s3);
	padding: 8px 16px;
	border-radius: 999px;
	background: rgba(244, 247, 249, .05);
	box-shadow: inset 0 0 0 1px rgba(244, 247, 249, .14);
	font-size: var(--sdb-tiny);
	font-weight: var(--sdb-w-semi);
	color: var(--sdb-white);
}

.sdb-rwall__badge-stars { display: inline-flex; gap: 1px; color: var(--sdb-red-hot); }
.sdb-rwall__badge-stars .sdb-icon { width: 14px; height: 14px; fill: currentColor; stroke: none; }

.sdb-rwall__title {
	margin: 0;
	font-size: clamp(1.8rem, 3.4vw, 2.6rem);
	color: var(--sdb-white);
	background: linear-gradient(100deg, #FFFFFF 0%, #FFF4EF 34%, #F0BFAE 66%, #CC5944 100%);
}

@supports ((-webkit-background-clip: text) or (background-clip: text)) {
	.sdb-rwall__title { -webkit-background-clip: text; background-clip: text; color: transparent; }
}
.sdb-rwall__lede { margin: var(--sdb-s2) 0 0; color: var(--sdb-cr-3); }

.sdb-rwall__wall {
	display: grid;
	grid-template-columns: 1fr;
	gap: var(--sdb-s3);
}

@media (min-width: 700px)  { .sdb-rwall__wall { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1024px) { .sdb-rwall__wall { grid-template-columns: repeat(3, 1fr); } }

.sdb-rwall__col {
	position: relative;
	max-height: 560px;
	overflow: hidden;
	/* Mask alpha, not a brand colour. */
	-webkit-mask-image: linear-gradient(to bottom, transparent, #000 9%, #000 91%, transparent);
	        mask-image: linear-gradient(to bottom, transparent, #000 9%, #000 91%, transparent);
}

.sdb-rwall__track {
	display: flex;
	flex-direction: column;
	gap: var(--sdb-s3);
	animation: sdb-drift 46s linear infinite;
}

.sdb-rwall__col:nth-child(2) .sdb-rwall__track { animation-duration: 58s; }
.sdb-rwall__col:nth-child(3) .sdb-rwall__track { animation-duration: 52s; }
/* Hover pauses, for devices that really hover (see the touch block below).
   But hover is not a mechanism: a touch or keyboard user gets
   nothing from it, and WCAG 2.2.2 asks for one. The hero motion control
   toggles .sdb-motion-paused on the body and stops this too. */
@media (hover: hover) and (pointer: fine) {
	.sdb-rwall__wall:hover .sdb-rwall__track { animation-play-state: paused; }
}
body.sdb-motion-paused .sdb-rwall__track { animation-play-state: paused; }

@keyframes sdb-drift {
	from { transform: translateY(0); }
	to   { transform: translateY(-50%); }
}

.sdb-rcard {
	padding: var(--sdb-s4);
	background: var(--sdb-raised);
	border-radius: 10px;
}

.sdb-rcard__stars { display: flex; gap: 2px; margin: 0 0 var(--sdb-s2); color: var(--sdb-red-hot); }
.sdb-rcard__stars .sdb-icon { width: 14px; height: 14px; fill: currentColor; stroke: none; }

.sdb-rcard__text { font-size: var(--sdb-small); line-height: 1.65; color: rgba(255, 255, 255, .8); }
.sdb-rcard__text p:last-child { margin-bottom: 0; }

.sdb-rcard__author {
	margin: var(--sdb-s3) 0 0;
	padding-top: var(--sdb-s2);
	border-top: 1px solid var(--sdb-hairline);
	font-family: var(--sdb-font-display);
	font-size: var(--sdb-h6);
	/* Was --sdb-ink, from when the wall sat on a light section. That token
	   became the page surface, so the name was charcoal on charcoal. */
	color: var(--sdb-white);
}

.sdb-rcard__source {
	display: block;
	margin-top: 2px;
	font-family: var(--sdb-font-body);
	font-size: var(--sdb-tiny);
	color: var(--sdb-text-quiet);
}

/* Still grid: reduced motion, or fewer than six cards. */
@media (prefers-reduced-motion: reduce) {
	.sdb-rwall__track { animation: none; }
	.sdb-rwall__col { max-height: none; -webkit-mask-image: none; mask-image: none; }
	.sdb-rwall__track > .is-clone { display: none; }
}

.sdb-rwall--static .sdb-rwall__track { animation: none; }
.sdb-rwall--static .sdb-rwall__col { max-height: none; -webkit-mask-image: none; mask-image: none; }
.sdb-rwall--static .is-clone { display: none; }

/* ---- Reviews wall on touch ---------------------------------------------------
   Two faults, one cause: a vertical auto-scrolling region inside a page that
   is scrolled vertically by finger.

   1. The wall paused on :hover. A touch device has no hover, so it fakes one:
      the first finger that lands sets :hover and it sticks until something
      else is tapped. Scrolling the page past the wall froze it.
   2. Under 700px the three columns stack, so there are three masked windows
      each drifting at its own speed, one above the other. Once one has been
      frozen and released they are out of step, and the masked, transformed
      tracks repaint badly on iOS. That is the "kept going but broken".

   So hover-pause is now for devices that really hover, and anything touch-led
   or narrow gets a different object: one row of cards to swipe, native
   scrolling, scroll-snap, no animation at all. The next card shows at the
   edge, which is the only hint a swipe needs. */
@media (hover: none), (max-width: 699px) {
	.sdb-rwall__wall { display: flex; gap: var(--sdb-s2); overflow-x: auto; overscroll-behavior-x: contain; scroll-snap-type: x mandatory;
		margin-inline: calc(var(--sdb-gutter) * -1); padding-inline: var(--sdb-gutter); scroll-padding-inline: var(--sdb-gutter);
		-webkit-overflow-scrolling: touch; scrollbar-width: none; }
	.sdb-rwall__wall::-webkit-scrollbar { display: none; }
	.sdb-rwall__col, .sdb-rwall__track { display: contents; }
	.sdb-rwall__col { max-height: none; -webkit-mask-image: none; mask-image: none; }
	.sdb-rwall__track { animation: none; }
	.sdb-rwall__track > .is-clone { display: none; }
	.sdb-rcard { flex: 0 0 min(84%, 360px); scroll-snap-align: start; display: flex; flex-direction: column; }
	.sdb-rcard__text { display: -webkit-box; -webkit-box-orient: vertical; -webkit-line-clamp: 11; overflow: hidden; }
	.sdb-rcard__author { margin-top: auto; }
}


/* Legacy review cards still used by page-testimonials.php and the location
   template's inline quotes. */
.sdb-reviews__grid--plain {
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	gap: var(--sdb-s3);
}

@media (max-width: 1024px) { .sdb-reviews__grid--plain { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 767px)  { .sdb-reviews__grid--plain { grid-template-columns: 1fr; } }

.sdb-review {
	display: flex;
	flex-direction: column;
	gap: var(--sdb-s2);
	padding: var(--sdb-s4);
	background: var(--sdb-cream);
	border-radius: var(--sdb-radius-card);
}

.sdb-review__stars { display: flex; gap: 3px; margin: 0; color: var(--sdb-red-hot); }
.sdb-review__stars .sdb-icon { width: 16px; height: 16px; fill: currentColor; stroke: none; }
.sdb-review__text { margin: 0; }
.sdb-review__text p:last-child { margin-bottom: 0; }
.sdb-review__cite { display: flex; flex-direction: column; margin-top: auto; }
.sdb-review__name { font-family: var(--sdb-font-display); font-size: var(--sdb-h6); font-style: normal; color: var(--sdb-ink); }
.sdb-review__label { font-size: var(--sdb-tiny); color: var(--sdb-text-quiet); }
.sdb-review__label a { color: inherit; }

/* ==========================================================================
   5 - WHY CHOOSE US
   Replaces the founder quote and the Comprehensive BBQ Care cards, which were
   two sections making one point.

   The column is four objects, not seven: quote, proof line, marked points,
   footer. One gap value separates all of them, so it reads as a column with a
   beat rather than a stack of things with four different margins.
   ========================================================================== */

.sdb-why__panel {
	display: grid;
	grid-template-columns: minmax(0, 6fr) minmax(0, 6fr);
	align-items: stretch;
	border-radius: 10px;
	overflow: hidden;
	background: var(--sdb-raised);
}

.sdb-why__body {
	display: flex;
	flex-direction: column;
	justify-content: center;
	gap: var(--sdb-s5);
	padding: var(--sdb-s6);
}

/* No eyebrow above the quote: a label reading "why choose us" over a quote
   that answers the question is the question asked twice. */
.sdb-why__quote {
	margin: 0;
	max-width: 17ch;
	font-family: var(--sdb-font-display);
	font-variation-settings: "wdth" 118;
	font-weight: 800;
	letter-spacing: -.02em;
	line-height: 1.08;
	font-size: clamp(1.55rem, 2.7vw, 2.375rem);
}

/* The marks are their own elements so the sweep never touches them. Inside the
   clipped span they would sweep too, which reads as text changing colour
   rather than as the sentence arriving. */
.sdb-why__mark { color: var(--sdb-white); }

/* A fixed gradient moved with background-position. Animating the gradient
   stops with calc() goes negative at rest, which some browsers treat as an
   invalid gradient, and a multiplied position slides the background off the
   element entirely. Either way the text is transparent with nothing behind
   it and the quote disappears. Range is 0 to 100 with no arithmetic. */
.sdb-why__txt {
	--sdb-sweep: 0%;
	color: transparent;
	-webkit-background-clip: text;
	background-clip: text;
	background-repeat: no-repeat;

	/* Vertical, because heat rises. A horizontal wipe on a quote about fire is
	   a direction picked at random; this one matches the thing it describes.

	   The front climbs from beneath the last line to above the first and keeps
	   going, so the sentence is ember while it passes and white once it has.
	   It ends at full contrast, which is where it should be once somebody is
	   reading, and the colour reads as something that happened rather than a
	   state the text is in. */
	background-size: 100% 340%;
	background-position: 0 var(--sdb-sweep);

	/* Fires once when the quote reaches the middle of the viewport, over a
	   fixed 5.5 seconds. Driving it from scroll position instead made the
	   duration a function of scroll velocity: flick past and it finished in
	   two frames, and anyone arriving mid-page from a refresh or an anchor
	   found it already over. A timed transition is the same event every time.

	   Non-repeating, so WCAG 2.2.2 does not apply even past five seconds. The
	   easing decelerates, so the front moves quickest through the middle of
	   the text and settles at either end. */
	transition: background-position 5500ms cubic-bezier(.28, .08, .2, 1);
	background-image: linear-gradient(180deg,
		var(--sdb-white) 0%, var(--sdb-white) 24%,
		#F0C9BC 30%,
		var(--sdb-red-hot) 36%, var(--sdb-red-hot) 46%,
		#F0C9BC 52%,
		var(--sdb-white) 58%, var(--sdb-white) 100%);
}

/* Without background-clip the text must not be invisible. */
.sdb-why__txt.is-swept { --sdb-sweep: 100%; }

@supports not ((-webkit-background-clip: text) or (background-clip: text)) {
	.sdb-why__txt { color: var(--sdb-white); background-image: none; }
}

.sdb-why__sub {
	margin: 0;
	max-width: 38ch;
	font-size: var(--sdb-lead);
	color: var(--sdb-cr-2);
}

/* A marked list is structure. Two paragraphs in two boxes is a layout. The
   mark matches the ten-point tune-up on the cleaning page, so it means the
   same thing in both places. */
.sdb-why__pts {
	display: grid;
	gap: var(--sdb-s3);
	margin: 0;
	padding: 0;
	list-style: none;
}

.sdb-why__pts li { position: relative; padding-left: 30px; }
.sdb-why__ptmark { position: absolute; left: 0; top: 5px; width: 12px; height: auto; }
.sdb-why__ptmark path { fill: var(--sdb-red-hot); }
.sdb-why__pts b { display: block; margin-bottom: 2px; font-size: var(--sdb-small); font-weight: var(--sdb-w-semi); color: var(--sdb-white); }
.sdb-why__pts span { font-size: var(--sdb-small); color: var(--sdb-cr-3); }

/* A footer, so the attribution and the link land on one line under a rule
   rather than floating as two more separate objects. */
.sdb-why__foot {
	position: relative;
	display: flex;
	align-items: center;
	justify-content: space-between;
	flex-wrap: wrap;
	gap: var(--sdb-s3);
	padding-top: var(--sdb-s4);
}

.sdb-why__cite { display: flex; align-items: center; gap: 12px; margin: 0; }
.sdb-why__shield { width: 32px; height: auto; flex: none; }

.sdb-why__cite b {
	display: block;
	font-family: var(--sdb-font-display);
	font-variation-settings: "wdth" var(--sdb-display-wide);
	font-weight: 700;
	font-size: 1.0625rem;
	letter-spacing: -.01em;
	line-height: 1.2;
	color: var(--sdb-white);
}

.sdb-why__cite span span { font-size: var(--sdb-tiny); color: var(--sdb-cr-3); }

.sdb-why__go {
	display: inline-flex;
	align-items: center;
	gap: 10px;
	font-size: var(--sdb-small);
	font-weight: var(--sdb-w-semi);
	color: var(--sdb-white);
	text-decoration: none;
	white-space: nowrap;
}

.sdb-why__go i {
	display: block;
	width: 26px;
	height: 1px;
	background: var(--sdb-red-hot);
	transition: width .6s cubic-bezier(.2, .7, .2, 1);
}

.sdb-why__go:hover { color: var(--sdb-red-hot); }
.sdb-why__go:hover i { width: 42px; }

/* Full height, feathered into the panel over about a fifth of the width so it
   reads as one surface rather than an image beside a text box. */
.sdb-why__media { position: relative; overflow: hidden; }

.sdb-why__img {
	position: absolute;
	inset: 0;
	width: 100%;
	height: 100%;
	object-fit: cover;
	object-position: 50% 24%;
	filter: saturate(.5) brightness(.6);
	transform: scale(1.04);
	transition: filter 1800ms cubic-bezier(.2, .7, .2, 1), transform 1800ms cubic-bezier(.2, .7, .2, 1);
}

.sdb-why__panel.is-lit .sdb-why__img { filter: none; transform: none; }

.sdb-why__media::after {
	content: "";
	position: absolute;
	inset: 0;
	background: linear-gradient(90deg,
		rgba(32, 35, 39, 1) 0%,
		rgba(32, 35, 39, .55) 14%,
		rgba(32, 35, 39, .06) 34%,
		transparent 58%);
}

@media (max-width: 900px) {
	.sdb-why__panel { grid-template-columns: 1fr; }
	.sdb-why__media { min-height: 320px; order: -1; }
	.sdb-why__media::after {
		background: linear-gradient(0deg, rgba(32, 35, 39, 1) 0%, rgba(32, 35, 39, .4) 26%, transparent 62%);
	}
	.sdb-why__body { padding: var(--sdb-s5) var(--sdb-s4); gap: var(--sdb-s4); }
}

@media (prefers-reduced-motion: reduce) {
	.sdb-why__txt { --sdb-sweep: 100%; transition: none; }
	.sdb-why__img { filter: none; transform: none; transition: none; }
}

/* ==========================================================================
   6 - BRANDS
   Dark section, each logo on its own white tile.

   The band was full-width white, because these logos are white-canvas files
   and a third of the set is black ink with no plate, so they vanish on dark
   however the files are made. A tile keeps each mark on the surface it needs
   without a white stripe across the page. Same files, no re-processing.
   ========================================================================== */

.sdb-brands {
	position: relative;
	overflow: hidden;
	padding-block: var(--sdb-s8);
}

.sdb-brands__head {
	/* Above the edge fades, which run the full height of the section: on a
	   phone they washed out the start of the heading (2026-10-14). */
	position: relative;
	z-index: 3;
	display: flex;
	align-items: flex-end;
	justify-content: space-between;
	gap: var(--sdb-s5);
	flex-wrap: wrap;
	margin-bottom: var(--sdb-s5);
}

.sdb-brands__title {
	max-width: 20ch;
	margin: 0;
	font-size: clamp(1.7rem, 3vw, 2.375rem);
	color: var(--sdb-white);
	background: linear-gradient(100deg, #FFFFFF 0%, #FFF4EF 34%, #F0BFAE 66%, #CC5944 100%);
}

@supports ((-webkit-background-clip: text) or (background-clip: text)) {
	.sdb-brands__title { -webkit-background-clip: text; background-clip: text; color: transparent; }
}

.sdb-brands__sub {
	max-width: 32ch;
	margin: 0;
	font-size: var(--sdb-small);
	color: var(--sdb-cr-3);
	text-align: right;
}

.sdb-brands__sub a {
	color: var(--sdb-cr-2);
	font-weight: var(--sdb-w-semi);
	text-decoration: underline;
	text-underline-offset: 4px;
}

.sdb-brands__sub a:hover { color: var(--sdb-red-hot); }

/* Edge fades take the page colour, not white, now that the band is dark. */
.sdb-brands::before,
.sdb-brands::after {
	content: "";
	position: absolute;
	top: 0;
	bottom: 0;
	width: 140px;
	z-index: 2;
	pointer-events: none;
}

.sdb-brands::before { left: 0;  background: linear-gradient(to right, var(--sdb-ink), transparent); }
.sdb-brands::after  { right: 0; background: linear-gradient(to left,  var(--sdb-ink), transparent); }

.sdb-brands__track {
	display: flex;
	width: max-content;
	animation: sdb-marquee 60s linear infinite;
}

/* Hover pauses, for devices that really hover (see the touch block below).
   But hover is not a mechanism: touch and keyboard users get
   nothing from it. The real control is the hero's motion button, which
   toggles .sdb-motion-paused on the body. */
.sdb-brands:hover .sdb-brands__track { animation-play-state: paused; }
body.sdb-motion-paused .sdb-brands__track { animation-play-state: paused; }

@keyframes sdb-marquee {
	from { transform: translateX(0); }
	to   { transform: translateX(-50%); }
}

.sdb-brands__set {
	display: flex;
	align-items: center;
	gap: var(--sdb-s2);
	padding-inline: var(--sdb-s1);
}

.sdb-brands__logo {
	display: grid;
	place-items: center;
	flex: none;
	width: 184px;
	height: 76px;
	padding: 10px 16px;
	border-radius: 10px;
	background: var(--sdb-white);
	box-shadow: inset 0 0 0 1px rgba(15, 17, 19, .08);
	transition: transform .4s cubic-bezier(.2, .7, .2, 1);
}

.sdb-brands__logo:hover { transform: translateY(-3px); }

.sdb-brands__logo img {
	display: block;
	width: 100%;
	height: 100%;
	object-fit: contain;
}

/* When one set already fits, brands.js adds this: the row centres, the clone
   is hidden and the fades come off, so a wide monitor does not scroll a strip
   that has nothing to scroll. */
.sdb-brands.is-static::before,
.sdb-brands.is-static::after { display: none; }

.sdb-brands.is-static .sdb-brands__track {
	width: 100%;
	animation: none;
	justify-content: center;
	flex-wrap: wrap;
}

.sdb-brands.is-static .sdb-brands__set[aria-hidden="true"] { display: none; }
.sdb-brands.is-static .sdb-brands__set { flex-wrap: wrap; justify-content: center; }

@media (max-width: 900px) {
	.sdb-brands__head { display: block; }
	.sdb-brands__sub { text-align: left; margin-top: var(--sdb-s2); }
}

@media (max-width: 640px) {
	.sdb-brands__logo { width: 150px; height: 62px; }
	.sdb-brands::before,
	.sdb-brands::after { width: 60px; }
}

@media (prefers-reduced-motion: reduce) {
	.sdb-brands__track { animation: none; flex-wrap: wrap; justify-content: center; width: 100%; }
	.sdb-brands__set[aria-hidden="true"] { display: none; }
	.sdb-brands__set { flex-wrap: wrap; justify-content: center; }
	.sdb-brands::before,
	.sdb-brands::after { display: none; }
}

/* ==========================================================================
   PHOTO REVEAL
   Images sit graded dark and lift once when scrolled into view. Used on
   cleaning and repair photography, where dull becoming gleaming is the
   service. reveal.js adds .is-lit. Reduced motion skips the grade entirely.
   ========================================================================== */

.sdb-reveal {
	filter: saturate(.55) brightness(.62) contrast(1.05);
	transition: filter 900ms cubic-bezier(.2, .7, .2, 1);
}

.sdb-reveal.is-lit { filter: none; }

@media (prefers-reduced-motion: reduce) {
	.sdb-reveal { filter: none; transition: none; }
}

/* ==========================================================================
   7 - FROM THE BLOG
   One lead with a photograph, five as text rows. Six links in less vertical
   space than three cards: the blog carries the traffic and the service pages
   pull almost none, so every extra route in from here counts.

   It also avoids a real flaw in the card layout. The featured images were made
   with the post headlines burned into them, so a card shows the same words
   twice, once in the image and once beneath it. Only the lead shows an image.
   ========================================================================== */

.sdb-blog__head {
	display: flex;
	align-items: center;
	justify-content: space-between;
	gap: var(--sdb-s4);
	flex-wrap: wrap;
	margin-bottom: var(--sdb-s5);
}

.sdb-blog__title {
	margin: 0;
	font-size: clamp(1.7rem, 3vw, 2.375rem);
	color: var(--sdb-white);
	background: linear-gradient(100deg, #FFFFFF 0%, #FFF4EF 34%, #F0BFAE 66%, #CC5944 100%);
}

@supports ((-webkit-background-clip: text) or (background-clip: text)) {
	.sdb-blog__title { -webkit-background-clip: text; background-clip: text; color: transparent; }
}

.sdb-blog__more {
	display: inline-flex;
	align-items: center;
	gap: 10px;
	font-size: var(--sdb-small);
	font-weight: var(--sdb-w-semi);
	color: var(--sdb-white);
	text-decoration: none;
}

.sdb-blog__more i { display: block; width: 26px; height: 1px; background: var(--sdb-red-hot); transition: width .6s cubic-bezier(.2, .7, .2, 1); }
.sdb-blog__more:hover { color: var(--sdb-red-hot); }
.sdb-blog__more:hover i { width: 42px; }

.sdb-blog__grid {
	display: grid;
	grid-template-columns: minmax(0, 5fr) minmax(0, 7fr);
	gap: var(--sdb-s6);
}

.sdb-blog__lead { display: block; text-decoration: none; }

.sdb-blog__shot {
	display: block;
	aspect-ratio: 16 / 10;
	overflow: hidden;
	margin-bottom: var(--sdb-s3);
	border-radius: var(--sdb-radius-img);
}

.sdb-blog__shot img { width: 100%; height: 100%; object-fit: cover; display: block; transition: transform 1200ms cubic-bezier(.2, .7, .2, 1); }
.sdb-blog__lead:hover .sdb-blog__shot img { transform: scale(1.04); }

.sdb-blog__cat { display: block; margin-bottom: 8px; font-size: 11px; font-weight: var(--sdb-w-semi); color: var(--sdb-red-hot); }
.sdb-blog__lead h3 { margin: 0; font-size: var(--sdb-h5); line-height: 1.14; max-width: 22ch; }
.sdb-blog__lead p { margin: 10px 0 0; max-width: 40ch; font-size: var(--sdb-small); color: var(--sdb-cr-3); }

.sdb-blog__rows { margin: 0; padding: 0; list-style: none; }
.sdb-blog__rows li { position: relative; }

/* Rows are separated by space, not rules. The chrome hairline had become a
   tic: seven of them on one page, most marking nothing real. */
.sdb-blog__rows li + li { margin-top: 2px; }

.sdb-blog__rows a {
	display: grid;
	grid-template-columns: 1fr auto;
	gap: var(--sdb-s4);
	align-items: baseline;
	padding: var(--sdb-s3) 0;
	text-decoration: none;
	transition: padding-left .4s cubic-bezier(.2, .7, .2, 1);
}

.sdb-blog__rows a:hover { padding-left: 12px; }

.sdb-blog__rows h3 {
	margin: 0;
	font-family: var(--sdb-font-body);
	font-variation-settings: normal;
	font-weight: var(--sdb-w-semi);
	font-size: 1.0625rem;
	line-height: 1.25;
	letter-spacing: 0;
}

.sdb-blog__rows a:hover h3 { color: var(--sdb-red-hot); }
.sdb-blog__rows .sdb-blog__cat { margin: 6px 0 0; color: var(--sdb-cr-3); font-weight: var(--sdb-w-body); font-size: var(--sdb-tiny); }
.sdb-blog__rows time { font-size: var(--sdb-tiny); color: var(--sdb-cr-4); white-space: nowrap; }

@media (max-width: 900px) {
	.sdb-blog__grid { grid-template-columns: 1fr; gap: var(--sdb-s5); }
}

/* ==========================================================================
   8 - CLOSE
   The page had no closing ask; it ended on blog cards.

   The surface is a gradient, not a fill. A flat fill against a flat fill
   always reads as a seam, which is what made the flame crossing the boundary
   look wrong. This fades in from the page and lands on the footer colour, so
   there is no top edge for the flame to cross and no bottom edge before the
   footer.
   ========================================================================== */

/* overflow is visible on purpose. With it hidden the flame was clipped at the
   section's top edge while the mask still had it at most of its opacity, which
   is the hard horizontal cut. It has to leave the box to rise into the block
   above. */
.sdb-close {
	position: relative;
	padding-block: var(--sdb-s8);
	text-align: center;
	background: linear-gradient(180deg,
		rgba(15, 17, 19, 0) 0%,
		rgba(15, 17, 19, .55) 38%,
		var(--sdb-well) 78%,
		var(--sdb-well) 100%);
}

/* The section above has to sit over the flame, or a mark that has left the
   close would paint on top of the blog text: .sdb-close comes later in the
   document, so without this it wins. */
.sdb-blog { position: relative; z-index: 1; }

/* Taller than the section and anchored below it, so the tip rises into the
   block above rather than meeting an edge. The mask fades it out before it
   gets there. */
.sdb-close__flame {
	position: absolute;
	left: 50%;

	/* Base sits on the join with the footer, not below it. The footer is a
	   solid block and paints over anything that crosses into it, so a flame
	   extending past this edge was cut off square. It crosses upward only,
	   where there is no edge to fight, and meets a surface at the bottom: a
	   mark that fades at both ends floats, one that is rooted looks like it
	   comes from somewhere. */
	bottom: 0;

	/* 140%, down from 205%. At the old size roughly a full section height
	   rose above the join, so it travelled up behind the blog text and read as
	   bleeding rather than rising. This clears the boundary by about 40% of a
	   section and dies out in the space above it. It is also proportionally
	   narrower, which leaves the heading more room. */
	height: 140%;
	width: auto;

	/* 0, not -1. At -1 it paints behind its own parent's background, and the
	   close has a gradient, so the flame would vanish inside the section and
	   only be visible above it. At 0 it sits above that background and below
	   the content, and outside the section the blog's z-index 1 keeps it
	   behind the text there. */
	z-index: 0;
	opacity: .13;
	transform: translateX(-50%);
	pointer-events: none;

	/* Fade finishes sooner than before, because there is less distance to
	   cover now that the mark is shorter. */
	-webkit-mask-image: linear-gradient(180deg,
		transparent 0%, rgba(0, 0, 0, .14) 20%, rgba(0, 0, 0, .5) 36%, #000 55%);
	        mask-image: linear-gradient(180deg,
		transparent 0%, rgba(0, 0, 0, .14) 20%, rgba(0, 0, 0, .5) 36%, #000 55%);
}

.sdb-close__flame path { fill: url(#sdb-flame-grad); }

/* A wide band of light crossing the section once on entry. Same gesture as
   the logo sheen, at section scale. Non-repeating, so WCAG 2.2.2 does not
   apply. */
.sdb-close__glint {
	position: absolute;
	inset: 0;
	z-index: 1;
	overflow: hidden;
	pointer-events: none;
	mix-blend-mode: screen;
	background: linear-gradient(104deg,
		transparent 34%,
		rgba(244, 247, 249, .09) 46%,
		rgba(244, 247, 249, .16) 50%,
		rgba(244, 247, 249, .09) 54%,
		transparent 66%);
	background-size: 250% 100%;
	background-position: 150% 0;
}

.sdb-close.is-lit .sdb-close__glint {
	transition: background-position 4200ms cubic-bezier(.3, .08, .2, 1);
	background-position: -50% 0;
}

.sdb-close__inner { position: relative; z-index: 2; }

.sdb-close__title {
	max-width: 18ch;
	margin: 0 auto var(--sdb-s3);
	font-size: clamp(1.9rem, 4vw, 3rem);
	color: var(--sdb-white);
}

.sdb-close__lede {
	max-width: 44ch;
	margin: 0 auto var(--sdb-s5);
	font-size: var(--sdb-lead);
	color: var(--sdb-cr-2);
}

.sdb-close__actions {
	display: flex;
	align-items: center;
	justify-content: center;
	flex-wrap: wrap;
	gap: var(--sdb-s4);
	margin: 0;
}

/* The sheen crosses the button 0.9s after the section glint starts, so the
   two read as one piece of light travelling across the block rather than as
   two animations. A chrome-filled button was tried and dropped: it sits at
   roughly the lightness of the section, so it stopped being the brightest
   thing in view, and it gave up the colour that means "click this"
   everywhere else on the site. */
.sdb-btn--sheen { position: relative; overflow: hidden; }

.sdb-btn--sheen::after {
	content: "";
	position: absolute;
	inset: 0;
	pointer-events: none;
	background: linear-gradient(104deg,
		transparent 36%,
		rgba(255, 255, 255, .28) 47%,
		rgba(255, 255, 255, .55) 50.5%,
		rgba(255, 255, 255, .28) 54%,
		transparent 64%);
	background-size: 250% 100%;
	background-position: 160% 0;
}

.sdb-close.is-lit .sdb-btn--sheen::after {
	transition: background-position 2600ms cubic-bezier(.3, .08, .2, 1) 900ms;
	background-position: -60% 0;
}

.sdb-btn--sheen:hover::after {
	transition: background-position 1200ms cubic-bezier(.3, .08, .2, 1);
	background-position: -60% 0;
}

.sdb-close__tel { font-size: 1rem; font-weight: var(--sdb-w-semi); color: var(--sdb-cr-2); text-decoration: none; }
.sdb-close__tel:hover { color: var(--sdb-white); }

.sdb-close__areas {
	margin: var(--sdb-s5) 0 0;
	font-size: var(--sdb-tiny);
	color: var(--sdb-cr-3);
}

.sdb-close__areas a {
	display: inline-block;
	margin-left: 10px;
	color: var(--sdb-cr-2);
	font-weight: var(--sdb-w-semi);
	text-decoration: underline;
	text-underline-offset: 4px;
	text-decoration-thickness: 1px;
}

.sdb-close__areas a:hover { color: var(--sdb-red-hot); }

@media (max-width: 700px) {
	/* Narrower and shorter, so the mark does not dominate a small screen and
	   the overflow stays modest. */
	.sdb-close__flame { height: 115%; opacity: .11; }
}

@media (prefers-reduced-motion: reduce) {
	.sdb-close.is-lit .sdb-close__glint,
	.sdb-close.is-lit .sdb-btn--sheen::after { transition: none; }
}

/* ==========================================================================
   POST CARDS
   Used by single.php (Related Posts) and the service pages. The front page no
   longer uses this; it has its own index layout below.
   ========================================================================== */

.sdb-popular__head {
	display: flex;
	align-items: baseline;
	justify-content: space-between;
	gap: var(--sdb-s3);
	margin-bottom: var(--sdb-s4);
}

.sdb-popular__title { margin: 0; font-size: var(--sdb-h4); }

.sdb-popular__more {
	font-family: var(--sdb-font-display);
	font-size: var(--sdb-btn);
	color: var(--sdb-red-hot);
	white-space: nowrap;
}

.sdb-cards {
	display: grid;
	grid-template-columns: repeat(3, 1fr);
	gap: var(--sdb-s3);
	margin: 0;
	padding: 0;
	list-style: none;
}

.sdb-card__link {
	display: flex;
	flex-direction: column;
	height: 100%;
	position: relative;
	background: var(--sdb-well);
	color: var(--sdb-text);
	border-radius: var(--sdb-radius-card);
	overflow: hidden;
	text-decoration: none;
	transition: background .2s ease, transform .2s ease;
}

/* Post cards sat on white from the light build, with titles inheriting the
   dark theme's white text: white on white (found 2026-10-14). Now on the
   well with a chrome hairline, like every other card. */
.sdb-card__link::after {
	content: "";
	position: absolute;
	inset: 0;
	border-radius: inherit;
	padding: 1px;
	background: var(--sdb-chrome-edge);
	-webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0);
	-webkit-mask-composite: xor;
	mask-composite: exclude;
	opacity: .35;
	pointer-events: none;
}

.sdb-card__link:hover {
	background: var(--sdb-raised);
	transform: translateY(-2px);
}
.sdb-card__link:hover .sdb-card__title { color: var(--sdb-red-hot); }

/* No forced aspect ratio. The featured images carry designed text; cropping
   them cut the headlines in half. They render at their own ratio. */
.sdb-card__media { line-height: 0; }
.sdb-card__img { width: 100%; height: auto; }

.sdb-card__body { padding: var(--sdb-s3); }
.sdb-card__title { margin: 0 0 var(--sdb-s1); font-size: var(--sdb-h6); color: var(--sdb-white); transition: color .2s ease; }
.sdb-card__meta { margin: 0 0 var(--sdb-s1); font-size: var(--sdb-tiny); color: var(--sdb-text-quiet); }
.sdb-card__excerpt { margin: 0; }

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

/* ==========================================================================
   FOOTER
   Sits in the well. No rule above it: the close section already fades into
   this colour, so a hairline there would be drawing a seam across a join that
   does not exist.
   ========================================================================== */

.sdb-footer {
	position: relative;
	background: var(--sdb-well);
	color: var(--sdb-text);
}

.sdb-footer a { color: var(--sdb-text); text-decoration: none; }
.sdb-footer a:hover { color: var(--sdb-red-hot); }

.sdb-footer__grid {
	display: grid;
	grid-template-columns: minmax(0, 2fr) repeat(3, minmax(0, 1fr));
	gap: var(--sdb-s5);
	padding-block: var(--sdb-s7);
}

.sdb-footer__logo img { max-height: 52px; width: auto; }
.sdb-footer__tagline { margin-top: var(--sdb-s2); max-width: 34ch; color: var(--sdb-cr-3); }

.sdb-footer__heading {
	margin: 0 0 var(--sdb-s2);
	padding-bottom: var(--sdb-s1);
	font-family: var(--sdb-font-body);
	font-size: var(--sdb-tiny);
	font-weight: var(--sdb-w-semi);
	color: var(--sdb-cr-3);
	position: relative;
}

.sdb-footer__heading::after {
	content: "";
	position: absolute;
	left: 0; right: 0; bottom: 0;
	height: 1px;
	background: var(--sdb-chrome-edge);
	opacity: .6;
}

.sdb-footer__list {
	display: grid;
	gap: var(--sdb-s1);
	margin: 0;
	padding: 0;
	list-style: none;
}

.sdb-footer__address { font-style: normal; display: grid; gap: var(--sdb-s2); }

/* Footer links, 2026-10-14. Quick links run in two columns with an ember
   tick that stretches on hover, the same gesture as the "go" links in the
   page bodies. Social links are icon chips; contact rows lead with an icon. */
.sdb-footer__quick {
	grid-template-columns: 1fr 1fr;
	column-gap: var(--sdb-s3);
	row-gap: 10px;
}
.sdb-footer__quick a {
	display: inline-flex;
	align-items: center;
	gap: 10px;
	padding: 2px 0;
	transition: color .2s ease;
}
.sdb-footer__quick a::before {
	content: "";
	display: block;
	flex: none;
	width: 10px;
	height: 1px;
	background: var(--sdb-red-hot);
	transition: width .5s cubic-bezier(.2, .7, .2, 1);
}
.sdb-footer__quick a:hover::before,
.sdb-footer__quick a:focus-visible::before { width: 20px; }
.sdb-footer__quick .current-menu-item > a { color: var(--sdb-white); }

.sdb-footer__social { gap: var(--sdb-s1); }
.sdb-footer__social a,
.sdb-footer__row {
	display: inline-flex;
	align-items: center;
	gap: 12px;
	line-height: 1.4;
}
.sdb-footer__social .sdb-icon,
.sdb-footer__row .sdb-icon {
	flex: none;
	box-sizing: content-box;
	width: 16px;
	height: 16px;
	padding: 10px;
	border-radius: 50%;
	stroke: var(--sdb-text);
	background: var(--sdb-raised);
	box-shadow: inset 0 0 0 1px rgba(244, 247, 249, .12);
	transition: stroke .2s ease, background .2s ease;
}
.sdb-footer__social a:hover .sdb-icon,
.sdb-footer__row:hover .sdb-icon { stroke: var(--sdb-white); background: var(--sdb-red); }
.sdb-footer__row { align-items: flex-start; }
.sdb-footer__row span { padding-top: 7px; }

.sdb-footer__legal { position: relative; }

.sdb-footer__legal::before {
	content: "";
	position: absolute;
	left: 0; right: 0; top: 0;
	height: 1px;
	background: var(--sdb-chrome-edge);
	opacity: .6;
}

.sdb-footer__legal-inner {
	display: flex;
	flex-wrap: wrap;
	align-items: center;
	justify-content: space-between;
	gap: var(--sdb-s2);
	padding-block: var(--sdb-s3);
}

.sdb-footer__legal-list {
	display: flex;
	gap: var(--sdb-s3);
	margin: 0;
	padding: 0;
	list-style: none;
	font-size: var(--sdb-tiny);
}

.sdb-footer__copyright { margin: 0; font-size: var(--sdb-tiny); color: var(--sdb-cr-3); }
.sdb-footer__copyright a { text-decoration: underline; text-underline-offset: 2px; }

/* Desktop: quick links get the room for two columns. */
@media (min-width: 901px) {
	.sdb-footer__grid { grid-template-columns: minmax(0, 1.4fr) minmax(0, 1.6fr) minmax(0, .9fr) minmax(0, 1.3fr); }
}

@media (max-width: 900px) {
	.sdb-footer__grid { grid-template-columns: repeat(2, 1fr); }
	.sdb-footer__brand { grid-column: 1 / -1; }
}

/* Phone: brand, quick links across the full width, then social as a row of
   chips (icon over label would crowd; icon beside label wraps cleanly). */
@media (max-width: 560px) {
	.sdb-footer__grid { grid-template-columns: 1fr; gap: var(--sdb-s4); padding-block: var(--sdb-s6); }
	.sdb-footer__social { grid-auto-flow: column; justify-content: start; gap: var(--sdb-s2); }
	.sdb-footer__social a { flex-direction: column; gap: 6px; font-size: 13px; }
	.sdb-footer__social .sdb-icon { width: 18px; height: 18px; padding: 13px; }
	.sdb-footer__legal-inner { flex-direction: column; align-items: flex-start; }
}


/* ==========================================================================
   TOUCH TARGETS (2026-10-14)
   On touch screens every control the thumb has to hit is at least 44px tall:
   the header phone and booking button (were 30px), footer links (29px), the
   legal links. Padding only, so nothing moves on desktop.
   ========================================================================== */
@media (pointer: coarse) {
	.sdb-header__tel { min-width: 44px; min-height: 44px; justify-content: center; }
	.sdb-header__cta { display: inline-flex; align-items: center; min-height: 44px; }
	.sdb-footer__quick { row-gap: 0; }
	.sdb-footer__quick a { min-height: 44px; }
	.sdb-footer__legal-list a { display: inline-flex; align-items: center; min-height: 44px; }
	.sdb-footer__social a { min-height: 44px; }
}

.sdb-nowrap { white-space: nowrap; }

/* ==========================================================================
   404 (404.php). The mobile drawer's rows and tiles, on a page.
   ========================================================================== */
.sdb-lost { padding-block: clamp(48px, 9vw, 112px); background: radial-gradient(120% 70% at 50% 0%, #2B2225 0%, var(--sdb-ink) 62%); }
.sdb-lost__inner { max-width: 680px; }
.sdb-lost__code { margin: 0 0 var(--sdb-s2); font-family: var(--sdb-font-display); font-variation-settings: "wdth" var(--sdb-display-wide); font-weight: 800; font-size: 13px; letter-spacing: .14em; color: var(--sdb-red-hot); }
.sdb-lost__title { font-size: clamp(1.9rem, 4.4vw, 3rem); max-width: 18ch; }
.sdb-lost__lead { margin: 0 0 var(--sdb-s5); color: var(--sdb-cr-2); }

.sdb-lost__svc { display: grid; gap: var(--sdb-s1); margin: 0; padding: 0; list-style: none; }
.sdb-lost__svc a { position: relative; display: grid; grid-template-columns: 64px 1fr auto; align-items: center; gap: var(--sdb-s3); padding: 12px 16px 12px 12px; border-radius: var(--sdb-radius-card); background: var(--sdb-well); text-decoration: none; transition: background .25s ease; }
.sdb-lost__svc a::after { content: ""; position: absolute; inset: 0; border-radius: inherit; padding: 1px; background: var(--sdb-chrome-edge); -webkit-mask: linear-gradient(#000 0 0) content-box, linear-gradient(#000 0 0); -webkit-mask-composite: xor; mask-composite: exclude; opacity: .35; pointer-events: none; transition: opacity .25s ease; }
.sdb-lost__svc a:hover { background: var(--sdb-raised); }
.sdb-lost__svc a:hover::after { opacity: .9; }
.sdb-lost__svc a:focus-visible { outline: var(--sdb-focus); outline-offset: var(--sdb-focus-offset); }
.sdb-lost__thumb { display: block; width: 64px; height: 64px; border-radius: 10px; overflow: hidden; background: var(--sdb-raised); }
.sdb-lost__thumb img { display: block; width: 100%; height: 100%; object-fit: cover; transition: transform .6s cubic-bezier(.2, .7, .2, 1); }
.sdb-lost__svc a:hover .sdb-lost__thumb img { transform: scale(1.08); }
.sdb-lost__txt { display: grid; gap: 2px; min-width: 0; }
.sdb-lost__label { font-family: var(--sdb-font-display); font-variation-settings: "wdth" var(--sdb-display-wide); font-weight: 700; font-size: 1.3rem; line-height: 1.1; color: var(--sdb-white); }
.sdb-lost__sub { font-size: 14px; color: var(--sdb-cr-3); }
.sdb-lost__chev { width: 20px; height: 20px; stroke: var(--sdb-red-hot); transition: transform .3s cubic-bezier(.2, .7, .2, 1); }
.sdb-lost__svc a:hover .sdb-lost__chev { transform: translateX(4px); }

.sdb-lost__more { display: grid; grid-template-columns: repeat(4, 1fr); gap: var(--sdb-s1); margin: var(--sdb-s3) 0 0; padding: 0; list-style: none; }
.sdb-lost__more a { display: flex; align-items: center; gap: 10px; min-height: 48px; padding: 12px; border-radius: var(--sdb-radius-card); background: var(--sdb-well); font-size: 15px; font-weight: 600; color: rgba(244, 247, 249, .86); text-decoration: none; white-space: nowrap; transition: background .25s ease, color .25s ease; }
.sdb-lost__more a:hover { background: var(--sdb-raised); color: var(--sdb-white); }
.sdb-lost__more .sdb-icon { width: 18px; height: 18px; flex: none; stroke: var(--sdb-red-hot); }

.sdb-lost__act { display: flex; flex-wrap: wrap; align-items: center; gap: var(--sdb-s2) var(--sdb-s4); margin-top: var(--sdb-s5); }
.sdb-lost__call { display: inline-flex; align-items: center; gap: 8px; min-height: 44px; font-weight: 600; color: var(--sdb-white); text-decoration: none; }
.sdb-lost__call .sdb-icon { width: 18px; height: 18px; stroke: var(--sdb-red-hot); }
.sdb-lost__call:hover span { text-decoration: underline; text-underline-offset: 4px; text-decoration-color: var(--sdb-red-hot); }

@media (max-width: 700px) {
  .sdb-lost__more { grid-template-columns: 1fr 1fr; }
  .sdb-lost__act { display: grid; grid-template-columns: 1fr; }
  .sdb-lost__act .sdb-btn { text-align: center; }
  .sdb-lost__call { justify-content: center; padding: 12px; border-radius: var(--sdb-radius-btn); background: var(--sdb-well); box-shadow: inset 0 0 0 1px rgba(244, 247, 249, .14); }
}
@media (prefers-reduced-motion: reduce) { .sdb-lost__thumb img, .sdb-lost__chev { transition: none; } }

/* Phone header fit, 2026-10-15. The 44px tap targets (pointer: coarse) made
   the actions 9px wider than a 390px screen, and iOS Safari then let the
   whole page slide sideways. The logo now gives up the width instead of the
   buttons, and html also clips sideways overflow as a backstop (body's clip
   alone does not stop iOS from widening the layout viewport). */
html { overflow-x: clip; }
@media (max-width: 480px) {
  .sdb-header__logo,
  .sdb-header__logo--custom { flex: 0 1 auto; min-width: 0; }
  .sdb-header__logo :where(a) { max-width: 100%; }
  .sdb-header__logo img { max-width: 100%; }
  .sdb-header__actions { flex: none; }
}

/* Header Book button: one sheen when the phone booking bar first comes up
   (assets/js/bookbar.js adds .is-lit once per visit). Same light as the
   logo and the close button. Never repeats, none under reduced motion. */
.sdb-header__cta.is-lit::after {
	transition: background-position 1800ms cubic-bezier(.3, .08, .2, 1) 250ms;
	background-position: -60% 0;
}
@media (prefers-reduced-motion: reduce) {
	.sdb-header__cta.is-lit::after { transition: none; background-position: 160% 0; }
}
