/* The trades style (look.style: trades): a white top bar, photo-led sections, white and stone bands and a
   green quote band. Colours and fonts come from theme.css (the site's look in site.yaml). */

:root {
  --ease-out: cubic-bezier(0.23, 1, 0.32, 1);
  --ease-in-out: cubic-bezier(0.77, 0, 0.175, 1);
  --gutter: clamp(1.25rem, 4.5vw, 3.5rem);
  --bar: 4.75rem;
  /* the same mix site.yaml's check uses for soft text (sitekit/content.py: "soft text") */
  --colour-soft: color-mix(in srgb, var(--colour-text) 75%, var(--colour-background));
  --colour-line: color-mix(in srgb, var(--colour-text) 12%, var(--colour-background));
  --colour-press: color-mix(in srgb, var(--colour-accent) 84%, #000);
  --colour-error: #B3261E;
}

*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-padding-top: calc(var(--bar) + 1rem); }
@media (prefers-reduced-motion: no-preference) { html { scroll-behavior: smooth; } }
body {
  margin: 0;
  background: var(--colour-background);
  color: var(--colour-text);
  font-family: var(--font-body);
  font-size: 1.0625rem;
  line-height: 1.6;
  overflow-wrap: break-word;
}
h1, h2, h3 { margin: 0; font-family: var(--font-headings); font-weight: 500; letter-spacing: -0.022em; line-height: 1.1; }
h2 { font-size: clamp(1.875rem, 2.6vw + 1rem, 2.875rem); }
h3 { font-size: clamp(1.3125rem, 0.8vw + 1rem, 1.625rem); line-height: 1.2; }
p { margin: 0; }
img { max-width: 100%; }
a { color: inherit; }
[hidden] { display: none !important; }
/* for screen readers only */
.visually-hidden { position: absolute; width: 1px; height: 1px; margin: -1px; padding: 0; border: 0; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
:focus-visible { outline: 3px solid var(--colour-highlight); outline-offset: 3px; }
::selection { background: color-mix(in srgb, var(--colour-main) 30%, var(--colour-background)); color: var(--colour-text); }
input, textarea { caret-color: var(--colour-main); }

.wrap { width: min(100% - 2 * var(--gutter), 75rem); margin-inline: auto; }
main > section { padding-block: clamp(3.5rem, 7vw, 6.5rem); }
main > section.band { background: var(--colour-surface); }
main > section.ba { padding: 0; }

.skip-link {
  position: absolute; top: 0.5rem; left: 0.5rem; z-index: 50;
  padding: 0.75rem 1rem; border-radius: 0.5rem;
  background: var(--colour-text); color: var(--colour-background); font-weight: 700;
  transform: translateY(-200%);
}
.skip-link:focus-visible { transform: none; }

/* buttons and links */
.button {
  display: inline-flex; align-items: center; justify-content: center; gap: 0.5em;
  min-height: 3rem; padding: 0.75rem 1.5rem; border: 0; border-radius: 999px;
  background: var(--colour-accent); color: var(--colour-on-accent);
  font: 700 1rem/1.2 var(--font-body); text-decoration: none; white-space: nowrap; cursor: pointer;
  transition: transform 160ms var(--ease-out), background-color 200ms ease, color 260ms ease;
}
.button:active { transform: scale(0.97); }
.button--large { min-height: 3.25rem; padding-inline: 1.75rem; }
.button--ghost { background: transparent; color: #fff; box-shadow: inset 0 0 0 1.5px rgba(255, 255, 255, 0.9); }
.button--outline { background: transparent; color: var(--colour-text); box-shadow: inset 0 0 0 1.5px currentColor; }
.link {
  font-weight: 700; color: var(--colour-main);
  text-decoration: underline; text-decoration-thickness: 1.5px; text-underline-offset: 0.25em;
}
/* the logo's two slashes end every button and "see more" link and step forward when pointed at; pointing at a button
   also wipes a darker shade across it, leaning like the slashes (the cookie banner's buttons stay plain) */
.button:not(.cookies__button) { position: relative; isolation: isolate; overflow: hidden; }
.button:not(.cookies__button)::before {
  content: ""; position: absolute; inset: 0 -25%; z-index: -1; background: var(--colour-press);
  transform: translateX(-102%) skewX(-20deg); transition: transform 480ms var(--ease-out);
}
.button--outline::before { background: var(--colour-text) !important; }
.button--ghost::before { background: #fff !important; }
.button:not(.cookies__button)::after, .link::after {
  content: ""; flex: none; width: 2.5px; height: 0.8em; margin-right: 5.5px; border-radius: 1px;
  background: currentColor; box-shadow: 5.5px 0 currentColor; transform: skewX(-20deg); transition: transform 320ms var(--ease-out);
}
.link::after { display: inline-block; margin-left: 0.45em; vertical-align: -0.04em; }
@media (hover: hover) and (pointer: fine) {
  .button:not(.cookies__button, :disabled, [aria-disabled="true"]):hover::before { transform: translateX(0) skewX(-20deg); }
  .button:not(.cookies__button, :disabled, [aria-disabled="true"]):hover::after, .link:hover::after { transform: translateX(4px) skewX(-20deg); }
  .button--outline:hover { color: var(--colour-background); }
  .button--ghost:hover { color: #000; }
  .cookies__button:hover { background: var(--colour-press); }
}
.icon { width: 1.375rem; height: 1.375rem; flex: none; }
/* a page's small label, after the logo's two slashes */
.label { display: inline-flex; align-items: center; gap: 0.625rem; color: var(--colour-main); font: 700 0.9375rem/1.6 var(--font-body); letter-spacing: normal; }
/* inside a heading (so search engines read it with it), a label still sits on its own line above the words */
:is(h1, h2) > .label { display: flex; width: fit-content; }
.label__mark { display: inline-flex; gap: 3px; }
.label__mark::before, .label__mark::after { content: ""; width: 2.5px; height: 0.9375rem; border-radius: 1px; background: currentColor; transform: skewX(-20deg); }

/* photos: hover zoom, and uncovering from the bottom the first time they come into view (site.js) */
.photo { position: relative; overflow: hidden; border-radius: 0.375rem; background: var(--colour-surface); }
.photo img { display: block; width: 100%; height: 100%; object-fit: cover; }
@media (hover: hover) and (pointer: fine) {
  .what__card .photo img, .strip__photo img { transition: transform 600ms var(--ease-out); }
  .what__card:hover .photo img, .strip__item:hover .strip__photo img { transform: scale(1.035); }
}
@media (prefers-reduced-motion: no-preference) {
  [data-photo-reveal][data-waiting] { clip-path: inset(100% 0 0 0); }
  [data-photo-reveal][data-waiting] img { transform: scale(1.08); }
  [data-photo-reveal][data-waiting].is-in {
    clip-path: inset(0 0 0 0);
    transition: clip-path 900ms var(--ease-out) var(--d, 0ms);
  }
  [data-photo-reveal][data-waiting].is-in img { transform: none; transition: transform 1100ms var(--ease-out) var(--d, 0ms); }
  /* a photo that's a link (the projects page) drops its clip when focused: the clip would cut off its focus ring */
  [data-photo-reveal][data-waiting].is-in:focus-visible { clip-path: none; }
}

/* ---------- top bar ---------- */
.bar { position: sticky; top: 0; z-index: 20; background: var(--colour-background); }
.bar::after {
  content: ""; position: absolute; inset: auto 0 -0.875rem 0; height: 0.875rem; pointer-events: none;
  background: linear-gradient(rgba(0, 0, 0, 0.12), rgba(0, 0, 0, 0)); opacity: 0; transition: opacity 250ms ease;
}
.bar.is-scrolled::after { opacity: 1; }
.bar__inner { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 0.75rem 1.5rem; min-height: var(--bar); }
.bar__logo { display: block; flex: none; text-decoration: none; transform-origin: left center; transition: transform 300ms var(--ease-out); }
.bar.is-scrolled .bar__logo { transform: scale(0.86); }
.bar__logo img { display: block; width: auto; height: 2.875rem; }
.bar__name { font: 600 1.25rem/1 var(--font-headings); }
.bar__nav { display: flex; flex-wrap: wrap; align-items: center; gap: 0.5rem 1.5rem; padding-bottom: 0.75rem; }
.bar__links { display: flex; flex-wrap: wrap; gap: 0.25rem 1.5rem; margin: 0; padding: 0; list-style: none; }
.bar__links a {
  display: inline-block; padding: 0.375rem 0; text-decoration: none;
  background: linear-gradient(currentColor, currentColor) 0 100% / 0 1.5px no-repeat;
  transition: background-size 250ms var(--ease-out);
}
.bar__links a[aria-current] { background-size: 100% 1.5px; }
@media (hover: hover) and (pointer: fine) { .bar__links a:hover { background-size: 100% 1.5px; } }
/* laptops: the logo's two slashes mark the page you're on in place of the underline, and skip to the link pointed at
   or tabbed to (trades.js sets --x; without it, the underline stays) */
.bar__links { position: relative; }
.bar__mark { display: none; }
@media (min-width: 60rem) {
  .js .bar__links a { background: none; }
  .bar__mark { display: block; position: absolute; top: 50%; left: -1.25rem; height: 1rem; margin-top: -0.5rem; color: var(--colour-main); pointer-events: none; }
  .bar__mark i {
    position: absolute; top: 0; left: 0; width: 2.5px; height: 100%; border-radius: 1px; background: currentColor; opacity: 0;
    transform: translateX(var(--x, 0px)) skewX(-20deg); transition: transform 460ms var(--ease-out), opacity 200ms ease;
  }
  .bar__mark i + i { left: 6px; transition-delay: 45ms, 0ms; } /* the second slash follows a moment later */
  .bar__mark.is-on i { opacity: 1; }
  .bar__mark.is-still i { transition: none; }
}
/* a drop-down (top bar links with pages under them): listed under their link in the phone menu; on laptops a small
   panel under it that opens on hover, from its button (trades.js), and, without trades.js, when the keyboard reaches it */
.bar__sub { margin: 0; padding: 0; list-style: none; }
.bar__more { display: none; }
@media (min-width: 60rem) {
  .bar__group { position: relative; display: flex; align-items: center; gap: 0.125rem; }
  .bar__more {
    display: inline-grid; place-items: center; width: 1.5rem; height: 1.75rem; margin-right: -0.375rem; padding: 0;
    border: 0; border-radius: 0.25rem; background: none; color: inherit; cursor: pointer;
  }
  .bar__more svg { transition: transform 200ms var(--ease-out); }
  .bar__more[aria-expanded="true"] svg { transform: rotate(180deg); }
  .bar__sub {
    position: absolute; top: 100%; left: -1rem; z-index: 21; min-width: 15rem; padding: 0.5rem 0;
    background: var(--colour-background); border-radius: 0.5rem; box-shadow: 0 0.75rem 2rem rgba(0, 0, 0, 0.16);
    opacity: 0; visibility: hidden; transform: translateY(-4px);
    transition: opacity 150ms ease, transform 150ms var(--ease-out), visibility 0s linear 150ms;
  }
  .bar__more[aria-expanded="true"] + .bar__sub,
  .bar__group:not(.is-shut) .bar__sub:focus-within,
  html:not(.js) .bar__group:focus-within .bar__sub {
    opacity: 1; visibility: visible; transform: none; transition: opacity 180ms ease, transform 220ms var(--ease-out), visibility 0s;
  }
  .bar__sub a { display: block; padding: 0.5rem 1rem; white-space: nowrap; }
  .bar__sub a[aria-current] { color: var(--colour-main); }
}
@media (min-width: 60rem) and (hover: hover) and (pointer: fine) {
  .bar__group:not(.is-shut):hover .bar__sub {
    opacity: 1; visibility: visible; transform: none; transition: opacity 180ms ease, transform 220ms var(--ease-out), visibility 0s;
  }
  .bar__sub a:hover { color: var(--colour-main); }
}
.bar__links a[data-current-group] { background-size: 100% 1.5px; }
/* a call button: round, by the menu button on phones; the number by the quote button on laptops (just its icon until
   there's room for the number) */
.bar__call-icon {
  display: none; place-items: center; flex: none; width: 2.75rem; height: 2.75rem; margin-left: auto; border-radius: 50%;
  background: var(--colour-accent); color: var(--colour-on-accent); transition: transform 160ms var(--ease-out);
}
.bar__call-icon:active { transform: scale(0.94); }
.bar__call-icon .icon, .bar__call .icon { width: 1.25rem; height: 1.25rem; }
.bar__call { display: none; align-items: center; gap: 0.5rem; min-height: 2.75rem; font-weight: 700; text-decoration: none; white-space: nowrap; }
.bar__call .icon { color: var(--colour-main); }
@media (hover: hover) and (pointer: fine) { .bar__call:hover { color: var(--colour-main); } }
@media (max-width: 59.99rem) { .bar__call-icon { display: inline-grid; } }
@media (min-width: 60rem) { .bar__call { display: inline-flex; } }
@media (min-width: 60rem) and (max-width: 71.99rem) {
  .bar__call { min-width: 2.75rem; justify-content: center; }
  .bar__call-number { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); white-space: nowrap; }
}
/* a tape measure along the bar's foot, filling with green as you go down the page (trades.js sets --progress) */
.bar__tape, .bar__tape::after {
  position: absolute; left: 0; right: 0; bottom: 0; height: 9px; pointer-events: none;
  background:
    repeating-linear-gradient(90deg, var(--tick) 0 1px, transparent 1px 50px) left bottom / 100% 9px no-repeat,
    repeating-linear-gradient(90deg, var(--tick) 0 1px, transparent 1px 10px) left bottom / 100% 4px no-repeat;
}
.bar__tape { --tick: color-mix(in srgb, var(--colour-text) 22%, transparent); }
.bar__tape::after {
  content: ""; --tick: var(--colour-main);
  background:
    linear-gradient(var(--tick), var(--tick)) left bottom / 100% 2px no-repeat,
    repeating-linear-gradient(90deg, var(--tick) 0 1.5px, transparent 1.5px 50px) left bottom / 100% 9px no-repeat,
    repeating-linear-gradient(90deg, var(--tick) 0 1px, transparent 1px 10px) left bottom / 100% 4px no-repeat;
  clip-path: inset(0 calc(100% - var(--progress, 0) * 100%) 0 0);
}
.bar__burger {
  display: none; place-items: center; width: 3rem; height: 3rem; margin-right: -0.5rem; padding: 0; border: 0;
  border-radius: 50%; background: transparent; color: var(--colour-text); cursor: pointer;
  transition: transform 160ms var(--ease-out), background-color 200ms ease;
}
.bar__burger:active { transform: scale(0.94); }
@media (hover: hover) and (pointer: fine) { .bar__burger:hover { background: color-mix(in srgb, var(--colour-text) 6%, transparent); } }
.bar__burger span {
  grid-area: 1 / 1; display: block; width: 1.5rem; height: 2px; border-radius: 2px; background: currentColor;
  transition: transform 260ms var(--ease-out);
}
.bar__burger span:first-child { transform: translateY(-4px); }
.bar__burger span:last-child { transform: translateY(4px); }
.bar__burger[aria-expanded="true"] span:first-child { transform: rotate(45deg); }
.bar__burger[aria-expanded="true"] span:last-child { transform: rotate(-45deg); }

/* phones and small tablets with JavaScript: the links fold away behind the button and unroll from the bar. They're
   folded from the first paint (base.html marks html.js before anything draws), so nothing below the bar moves when
   site.js arrives; if site.js can't load, html.js goes and the links show again. */
@media (max-width: 59.99rem) {
  .js .bar--menu .bar__burger { display: inline-grid; }
  .js .bar--menu .bar__inner { flex-wrap: nowrap; }
  .js .bar--menu .bar__nav {
    position: absolute; top: 100%; left: 0; right: 0; z-index: 19;
    display: block; padding: 0.5rem var(--gutter) 1.75rem;
    background: var(--colour-background); box-shadow: 0 1.125rem 1.875rem rgba(0, 0, 0, 0.14);
    clip-path: inset(0 0 100% 0); visibility: hidden;
  }
  /* motion only once the page has drawn folded, so the menu never plays its closing on page load */
  .js .bar--menu[data-menu-ready] .bar__nav { transition: clip-path 200ms var(--ease-out), visibility 0s linear 200ms; }
  .js .bar--menu[data-open] .bar__nav { clip-path: inset(0 0 -2.5rem 0); visibility: visible; transition: clip-path 320ms var(--ease-out), visibility 0s; }
  .js .bar--menu[data-open] { z-index: 31; } /* over the cookie banner, so a short phone's last links aren't under it */
  .js .bar--menu .bar__links { display: block; }
  .js .bar--menu .bar__links a {
    display: block; padding: 0.75rem 0; border-bottom: 1px solid var(--colour-line); background: none;
    font: 500 1.625rem/1.2 var(--font-headings); letter-spacing: -0.02em;
  }
  .js .bar--menu .bar__links a[aria-current] { color: var(--colour-main); }
  .js .bar--menu .bar__links a[aria-current]::before {
    content: ""; display: inline-block; width: 2.5px; height: 1.25rem; margin-right: 1rem; border-radius: 1px;
    background: currentColor; box-shadow: 6px 0 currentColor; transform: skewX(-20deg);
  }
  .js .bar--menu .bar__button { width: 100%; margin-top: 1.375rem; }
  /* six more pages under one link can make the open menu taller than a small phone: it scrolls on its own */
  .js .bar--menu .bar__nav { max-height: calc(100dvh - var(--bar)); overflow-y: auto; overscroll-behavior: contain; }
  .js .bar--menu .bar__sub { padding-left: 1.25rem; }
  .js .bar--menu .bar__sub a { padding: 0.625rem 0; font-size: 1.125rem; }
  .js .bar--menu .bar__sub li { opacity: 1; transform: none; transition: none; } /* they come with the link they're under */
  .js .bar--menu .bar__links li, .js .bar--menu .bar__button { opacity: 0; transform: translateY(-6px); transition: opacity 150ms ease, transform 150ms var(--ease-out); }
  .js .bar--menu[data-open] .bar__links li, .js .bar--menu[data-open] .bar__button {
    opacity: 1; transform: none; transition-duration: 280ms; transition-delay: calc(60ms + var(--i) * 35ms);
  }
  .js .bar--menu[data-open] .bar__button:active { transform: scale(0.97); transition-delay: 0ms; transition-duration: 160ms; }
}
@media (min-width: 60rem) {
  .bar__nav { flex-wrap: nowrap; gap: 1.75rem; padding-bottom: 0; }
  .bar__links { flex-wrap: nowrap; gap: 1.75rem; }
}
/* narrow laptops: a drop-down's button takes room, so the links, number and quote button sit a little closer (the
   links keep their spacing, where the slashes go) */
@media (min-width: 60rem) and (max-width: 67.99rem) { .bar__nav { gap: 1rem; } }

/* ---------- the before-and-after opening ---------- */
.ba { position: relative; background: #000; color: #fff; }
.ba__stage {
  position: relative; overflow: hidden; background: #222;
  /* a set width: otherwise the height limits below would also stretch or shrink the width, through the shape */
  width: 100%; aspect-ratio: 4 / 3; max-height: calc(100svh - var(--bar)); /* phones: the whole garden shows */
}
.ba.is-live .ba__stage { cursor: ew-resize; touch-action: pan-y; user-select: none; -webkit-user-select: none; }
.ba__photo { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; object-position: var(--focus); pointer-events: none; }
/* Until site.js takes over, only the before photo shows. If it never does, the after photo appears after 3s. */
.js .ba:not(.is-live) .ba__photo--after { clip-path: inset(0 100% 0 0); animation: ba-show 0s 3s forwards; }
@keyframes ba-show { to { clip-path: inset(0 0 0 0); } }
.ba__shade {
  position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(0deg, rgba(0, 0, 0, 0.74) 0%, rgba(0, 0, 0, 0.42) 40%, rgba(0, 0, 0, 0) 64%);
}
.ba__divider {
  position: absolute; top: -6%; left: 0; width: 3px; height: 112%; margin-left: -1.5px;
  background: #fff; box-shadow: 0 0 0.875rem rgba(0, 0, 0, 0.35); pointer-events: none; opacity: 0;
}
.ba.is-live .ba__divider { opacity: 1; }
/* the handle moves along the line (site.js sets its transform); the knob inside it grows in and when held */
.ba__handle {
  position: absolute; top: 50%; left: 0; z-index: 2;
  width: 3.25rem; height: 3.25rem; margin: -1.625rem 0 0 -1.625rem; border-radius: 50%;
}
.ba__handle:focus-visible { outline-color: #fff; outline-offset: 4px; }
.ba__knob {
  display: grid; place-items: center; width: 100%; height: 100%; border-radius: 50%;
  background: #fff; color: var(--colour-main); box-shadow: 0 0.25rem 1.125rem rgba(0, 0, 0, 0.3);
  opacity: 0; transform: scale(0.9); transition: opacity 280ms var(--ease-out), transform 280ms var(--ease-out);
}
.ba__knob svg { width: 1.625rem; height: 1.625rem; }
.ba.is-ready .ba__knob { opacity: 1; transform: none; }
.ba.is-dragging .ba__knob { transform: scale(1.08); }
.ba__tag {
  position: absolute; top: 1.25rem; z-index: 1; padding: 0.375rem 0.75rem; border-radius: 999px;
  background: rgba(0, 0, 0, 0.6); color: #fff; font-size: 0.875rem; font-weight: 700; pointer-events: none;
  opacity: 0; transition: opacity 300ms ease;
}
.ba__tag--after { left: var(--gutter); }
.ba__tag--before { right: var(--gutter); }
.ba.is-ready .ba__tag { opacity: 1; }
/* the Google rating: on phones under the words, just above the quote button; on wider screens on the photo, under
   the After label (shown at once without the script, else with the labels). Only one of the two shows. */
.ba__badge {
  display: inline-flex; align-items: center; gap: 0.4375rem; padding: 0.4375rem 0.875rem 0.4375rem 0.625rem;
  border-radius: 999px; background: #fff; color: #000; font-size: 0.875rem; font-weight: 700; line-height: 1;
  text-decoration: none; box-shadow: 0 0.125rem 0.875rem rgba(0, 0, 0, 0.28); transition: opacity 300ms ease, box-shadow 200ms ease;
}
.ba__badge .icon--google { width: 1.125rem; height: 1.125rem; }
.ba__badge .stars--small .star { width: 0.875rem; height: 0.875rem; }
.ba__badge-count { font-weight: 500; color: #444; }
.ba__badge:focus-visible { outline: 3px solid #fff; outline-offset: 3px; }
@media (hover: hover) and (pointer: fine) { .ba__badge:hover { box-shadow: 0 0.25rem 1.25rem rgba(0, 0, 0, 0.36); } }
.ba__badge--words { display: flex; width: fit-content; margin-top: 1.25rem; pointer-events: auto; }
.ba__badge--words + .ba__actions { margin-top: 1rem; }
.ba__badge--photo { position: absolute; top: 3.875rem; left: var(--gutter); z-index: 2; }
.js .ba.is-live:not(.is-ready) .ba__badge--photo { opacity: 0; }
@media (max-width: 47.99rem) { .ba__badge--photo { display: none; } }
@media (min-width: 48rem) { .ba__badge--words { display: none; } }
.ba__words { position: absolute; left: var(--gutter); right: var(--gutter); bottom: clamp(1.75rem, 4.5vw, 3.5rem); z-index: 1; pointer-events: none; }
/* on phones the words sit under the photo, on the black band, so nothing covers the garden */
@media (max-width: 47.99rem) {
  .ba__shade { display: none; }
  .ba__words { position: static; padding: 1.5rem var(--gutter) 2.25rem; }
}
.ba__title { font-size: clamp(2.125rem, 3vw + 1.25rem, 3.75rem); line-height: 1.04; letter-spacing: -0.028em; }
.ba__label { margin-bottom: 0.875rem; color: #fff; }
.ba__row { display: block; overflow: hidden; padding-bottom: 0.1em; margin-bottom: -0.1em; }
.ba__row > span { display: block; }
.ba__subline { max-width: 46ch; margin-top: 1rem; font-size: clamp(1rem, 0.4vw + 0.9rem, 1.1875rem); }
.ba__actions { display: flex; flex-wrap: wrap; gap: 0.75rem; margin-top: 1.625rem; pointer-events: auto; }
@media (min-width: 48rem) {
  .ba__stage { aspect-ratio: 16 / 9; max-height: calc(100svh - var(--bar)); min-height: 30rem; }
  .ba__photo { object-position: 50% 50%; }
  .ba__shade {
    background:
      linear-gradient(90deg, rgba(0, 0, 0, 0.64) 0%, rgba(0, 0, 0, 0.3) 42%, rgba(0, 0, 0, 0) 68%),
      linear-gradient(0deg, rgba(0, 0, 0, 0.45) 0%, rgba(0, 0, 0, 0) 46%);
  }
  .ba__words { right: auto; max-width: min(34rem, 46%); }
}
@media (prefers-reduced-motion: no-preference) {
  /* the headline rises line by line as the line sweeps across (site.js); without JavaScript it simply shows */
  .js .ba__row > span { animation: ba-rise 800ms var(--ease-out) both; animation-delay: calc(1100ms + var(--i) * 70ms); }
  .js .ba__label { animation: ba-fade 500ms var(--ease-out) 1000ms both; }
  .js .ba__subline { animation: ba-fade 500ms var(--ease-out) 1360ms both; }
  .js .ba__badge--words { animation: ba-fade 500ms var(--ease-out) 1390ms both; }
  .js .ba__actions { animation: ba-fade 500ms var(--ease-out) 1420ms both; }
}
@keyframes ba-rise { from { transform: translateY(110%); } }
@keyframes ba-fade { from { opacity: 0; transform: translateY(8px); } }

/* ---------- what we do ---------- */
.what__heading { margin-bottom: clamp(2rem, 4vw, 3.25rem); }
.what__cards { display: grid; gap: 1.75rem; margin: 0; padding: 0; list-style: none; }
.what__photo { aspect-ratio: 4 / 5; }
.what__title { margin-top: 1.25rem; }
.what__text { margin-top: 0.5rem; color: var(--colour-soft); }
.what__card .link { display: inline-block; margin-top: 0.875rem; }
@media (min-width: 48rem) { .what__cards { grid-template-columns: repeat(3, minmax(0, 1fr)); } }

/* ---------- rows: the project strip and the reviews ---------- */
.arrows { display: flex; gap: 0.625rem; }
.arrows__button {
  display: grid; place-items: center; width: 3rem; height: 3rem; padding: 0; border: 0; border-radius: 50%;
  background: transparent; box-shadow: inset 0 0 0 1.5px currentColor; color: var(--colour-text); cursor: pointer;
  transition: transform 160ms var(--ease-out), opacity 200ms ease, background-color 200ms ease, color 200ms ease;
}
.arrows__button svg { width: 1.375rem; height: 1.375rem; }
.arrows__button:active { transform: scale(0.95); }
.arrows__button:disabled { opacity: 0.28; cursor: default; transform: none; }
@media (hover: hover) and (pointer: fine) { .arrows__button:not(:disabled):hover { background: var(--colour-text); color: var(--colour-background); } }
[data-slider] { scrollbar-width: none; }
[data-slider]::-webkit-scrollbar { display: none; }
[data-slider].is-grabbing { cursor: grabbing; scroll-snap-type: none; user-select: none; }

.strip__head { display: flex; flex-wrap: wrap; align-items: end; justify-content: space-between; gap: 1rem 2.5rem; margin-bottom: clamp(2rem, 4vw, 3.25rem); }
.strip__track {
  display: grid; grid-auto-flow: column; grid-auto-columns: 78%; gap: 1.125rem;
  margin: 0; padding: 0 var(--gutter); list-style: none;
  overflow-x: auto; scroll-snap-type: x mandatory; scroll-padding-inline: var(--gutter); overscroll-behavior-x: contain;
}
@media (min-width: 48rem) { .strip__track { grid-auto-columns: calc((min(100vw - 2 * var(--gutter), 75rem) - 3.375rem) / 3.4); } }
@media (min-width: 75rem) { .strip__track { padding-inline: calc((100% - 75rem) / 2); scroll-padding-inline: calc((100% - 75rem) / 2); } }
.strip__item { scroll-snap-align: start; }
.strip__item figure { margin: 0; }
.strip__photo { aspect-ratio: 4 / 5; }
.strip__photo img { -webkit-user-drag: none; }
/* photos far along the row wait until it's scrolled near them (site.js): a hidden lazy image isn't fetched */
.js .strip__item[data-later] .strip__photo img { display: none; }
.strip__caption { margin-top: 0.75rem; font-size: 0.9375rem; color: var(--colour-soft); }
.strip__foot { display: flex; flex-wrap: wrap; align-items: center; gap: 0.875rem 1.25rem; margin-top: 2.25rem; }
.social { display: inline-flex; align-items: center; gap: 0.5rem; min-height: 3rem; font-weight: 700; text-decoration: none; }

.reviews__inner { display: grid; gap: 2.5rem; }
@media (min-width: 60rem) { .reviews__inner { grid-template-columns: 4fr 8fr; gap: 3.5rem; align-items: start; } }
.reviews__label { display: inline-flex; align-items: center; gap: 0.625rem; font-weight: 700; }
.reviews__label .icon { width: 1.625rem; height: 1.625rem; }
.reviews__summary h2 { margin-top: 1.125rem; }
.reviews__score { display: flex; align-items: center; gap: 1.125rem; margin-top: 1.375rem; }
.reviews__rating { font: 500 4rem/1 var(--font-headings); letter-spacing: -0.03em; }
.reviews__count { margin-top: 0.375rem; font-size: 0.9375rem; color: var(--colour-soft); }
.reviews__mentions-heading { margin-top: 1.75rem; font-size: 0.9375rem; font-weight: 700; }
.reviews__mentions { display: flex; flex-wrap: wrap; gap: 0.5rem; margin: 0.625rem 0 0; padding: 0; list-style: none; }
.reviews__mentions li { padding: 0.375rem 0.75rem; border-radius: 999px; background: var(--colour-surface); font-size: 0.875rem; }
.reviews__mentions b { margin-left: 0.25rem; color: var(--colour-soft); }
.reviews__actions { display: flex; flex-wrap: wrap; align-items: center; gap: 0.75rem 1.25rem; margin-top: 1.75rem; }
.reviews__list { min-width: 0; }
.reviews__list .arrows { justify-content: flex-end; margin-bottom: 0.875rem; }
.reviews__track {
  display: grid; grid-auto-flow: column; grid-auto-columns: min(21.25rem, 86%); gap: 1rem; align-items: start;
  margin: 0; padding: 0 0 0.25rem; list-style: none;
  overflow-x: auto; scroll-snap-type: x mandatory; overscroll-behavior-x: contain;
}
.review { scroll-snap-align: start; padding: 1.375rem; border: 1px solid var(--colour-line); border-radius: 1rem; background: var(--colour-background); }
.review__who { display: flex; align-items: center; gap: 0.75rem; }
.review__initial {
  display: grid; place-items: center; flex: none; width: 2.5rem; height: 2.5rem; border-radius: 50%;
  background: hsl(var(--hue) 45% 30%); color: #fff; font: 600 1.0625rem/1 var(--font-headings);
}
.review__name b { display: block; line-height: 1.3; }
.review__name span { font-size: 0.875rem; color: var(--colour-soft); }
.review__who .icon { width: 1.25rem; height: 1.25rem; margin-left: auto; }
.review .stars { margin-top: 0.875rem; }
.review__text { margin-top: 0.625rem; overflow: hidden; }
.review__text.is-clamped { display: -webkit-box; -webkit-line-clamp: 6; -webkit-box-orient: vertical; }
.review__more { margin-top: 0.625rem; padding: 0.25rem 0; border: 0; background: none; color: var(--colour-main); font: 700 0.9375rem var(--font-body); cursor: pointer; }
.reviews__note { margin-top: 0.875rem; font-size: 0.8125rem; color: var(--colour-soft); }

/* stars: filled to the rating; ones that start below the screen fill one by one as they come into view */
.stars { display: inline-flex; gap: 0.375rem; }
.star { position: relative; width: 1.75rem; height: 1.75rem; }
.stars--small { gap: 0.125rem; }
.stars--small .star { width: 1.125rem; height: 1.125rem; }
.star svg { position: absolute; inset: 0; width: 100%; height: 100%; fill: color-mix(in srgb, var(--colour-text) 15%, var(--colour-background)); }
.star .star__fill { fill: #FBBC04; clip-path: inset(0 calc(100% - var(--f) * 100%) 0 0); }
@media (prefers-reduced-motion: no-preference) {
  .stars[data-waiting] .star__fill { clip-path: inset(0 100% 0 0); }
  .stars[data-waiting].is-in .star__fill { clip-path: inset(0 calc(100% - var(--f) * 100%) 0 0); transition: clip-path 420ms var(--ease-out) calc(var(--i) * 90ms); }
}

/* ---------- meet the owner ---------- */
.meet__inner { display: grid; gap: 2.5rem; align-items: center; }
@media (min-width: 56rem) { .meet__inner { grid-template-columns: 5fr 6fr; gap: 4.5rem; } }
.meet__photos { position: relative; max-width: 27.5rem; }
.meet__photos--two { margin-bottom: 1.75rem; }
.meet__photo { aspect-ratio: 4 / 5; }
.meet__photo img { object-position: 50% 30%; }
.meet__photo--small { position: absolute; right: -1.75rem; bottom: -1.75rem; width: 42%; aspect-ratio: 3 / 4; box-shadow: 0 0 0 6px var(--colour-surface); }
@media (max-width: 40rem) { .meet__photo--small { right: 0.5rem; } }
.meet__text { max-width: 50ch; margin-top: 1rem; }
.meet__signature { margin-top: 1rem; font-weight: 700; }
.meet__facts { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0.75rem 1.5rem; max-width: 32.5rem; margin: 1.5rem 0 0; padding: 0; list-style: none; }
.meet__facts li { display: flex; align-items: flex-start; gap: 0.625rem; }
.meet__facts .icon--tick { width: 1.25rem; height: 1.25rem; margin-top: 0.1875rem; color: var(--colour-main); }
.meet__action { margin-top: 1.75rem; }
@media (max-width: 26rem) { .meet__facts { grid-template-columns: minmax(0, 1fr); } }

/* ---------- the quote band (the shared form) ---------- */
.book { background: var(--colour-main); color: var(--colour-background); }
.book :focus-visible { outline-color: var(--colour-background); }
.book__inner { display: grid; gap: 2.5rem; }
@media (min-width: 60rem) { .book__inner { grid-template-columns: 5fr 7fr; gap: 4rem; } }
.book__text { max-width: 38ch; margin-top: 1rem; }
.book__points { display: grid; gap: 0.75rem; margin: 1.5rem 0 0; padding: 0; list-style: none; }
.book__points li::before { content: "\2713\00a0\00a0"; font-weight: 700; }
.enquiry { display: grid; gap: 0 1.125rem; align-content: start; }
.enquiry > * { grid-column: 1 / -1; }
@media (min-width: 38rem) { .enquiry { grid-template-columns: 1fr 1fr; } .enquiry > .field--half { grid-column: auto; } }
.enquiry__heading { margin-bottom: 1.25rem; font-size: 1.375rem; line-height: 1.2; }
.quote__heading { font-size: clamp(1.3125rem, 0.8vw + 1rem, 1.625rem); line-height: 1.2; } /* the same at either level (h2 on Contact) */
.field { margin-bottom: 1.125rem; }
.field label { display: block; margin-bottom: 0.5rem; font-size: 0.9375rem; font-weight: 700; }
.field input, .field textarea {
  width: 100%; padding: 0.8125rem 1rem; border: 2px solid transparent; border-radius: 0.875rem;
  background: var(--colour-background); color: var(--colour-text); font: 400 1.0625rem/1.4 var(--font-body);
  transition: border-color 200ms ease;
}
.field textarea { min-height: 7.5rem; resize: vertical; }
.field input:focus-visible, .field textarea:focus-visible { outline: none; border-color: var(--colour-text); }
.field [aria-invalid="true"] { border-color: var(--colour-error); }
.field__error { margin-top: 0.375rem; padding: 0.25rem 0.5rem; border-radius: 0.375rem; background: var(--colour-background); color: var(--colour-error); font-size: 0.875rem; font-weight: 700; }
.field--trap { position: absolute; left: -10000px; width: 1px; height: 1px; overflow: hidden; }
.cf-turnstile { max-width: 100%; overflow: hidden; }
.enquiry > .button { justify-self: start; min-width: 12rem; background: var(--colour-background); color: var(--colour-main); }
/* on hover the text darkens rather than the background tinting: a green tint behind green text drops below 4.5:1 */
@media (hover: hover) and (pointer: fine) { .enquiry > .button:hover { background: var(--colour-background); color: var(--colour-press); } }
.enquiry__note { margin-top: 1rem; font-size: 0.875rem; }
.enquiry__status { display: flex; gap: 0.625rem; align-items: center; margin-top: 1rem; padding: 0.875rem 1rem; border-radius: 0.75rem; background: var(--colour-background); color: var(--colour-main); font-weight: 700; }
.enquiry__status[data-kind="error"] { color: var(--colour-error); }
.enquiry__tick { flex: none; }
.enquiry__tick circle { fill: currentColor; opacity: 0.14; }
.enquiry__tick path { fill: none; stroke: currentColor; stroke-width: 2.4; stroke-linecap: round; stroke-linejoin: round; }
.enquiry__status:not([data-kind="ok"]) .enquiry__tick { display: none; }
.enquiry__status:focus { outline: none; }
.enquiry.is-sent .field, .enquiry.is-sent .cf-turnstile, .enquiry.is-sent .button, .enquiry.is-sent .enquiry__note { display: none; }
.enquiry.is-sent .enquiry__status { margin-top: 0; }
.enquiry__noscript a { color: var(--colour-background); }
@media (prefers-reduced-motion: no-preference) {
  .enquiry.is-sent .enquiry__status { animation: status-in 300ms var(--ease-out) both; }
  .enquiry__status[data-kind="ok"] .enquiry__tick path { stroke-dasharray: 1; animation: tick-draw 400ms var(--ease-out) 150ms both; }
}
@keyframes status-in { from { opacity: 0; transform: scale(0.97); } }
@keyframes tick-draw { from { stroke-dashoffset: 1; } to { stroke-dashoffset: 0; } }
.book__call { margin-top: 1.5rem; }
.book__call a { font-weight: 700; text-underline-offset: 0.25em; }
.book .label { margin-bottom: 1rem; color: inherit; }
.book h1 { font-size: clamp(2.5rem, 3.4vw + 1.25rem, 4.125rem); line-height: 1.04; letter-spacing: -0.03em; }

/* Contact: the quote first, with the other ways to get in touch beside it (under it on phones) */
.book--contact .book__inner { grid-template-areas: "words" "form" "reach"; }
.book--contact .book__words { grid-area: words; }
.book--contact [data-enquiry] { grid-area: form; }
.book--contact .reach { grid-area: reach; }
@media (min-width: 60rem) { .book--contact .book__inner { grid-template-areas: "words form" "reach form"; grid-template-rows: auto 1fr; } }
.reach { display: grid; align-content: start; margin: 0; padding: 0; list-style: none; }
.reach__link {
  display: flex; align-items: center; gap: 0.875rem; min-height: 3rem; padding: 0.625rem 0;
  border-top: 1px solid rgb(255 255 255 / 0.3); font-weight: 700; text-decoration: none; overflow-wrap: anywhere;
}
.reach__link--big { font: 500 clamp(1.375rem, 1vw + 1.1rem, 1.75rem)/1.2 var(--font-headings); letter-spacing: -0.01em; }
.reach__icon { display: grid; place-items: center; flex: none; width: 2.5rem; height: 2.5rem; border-radius: 50%; background: rgb(255 255 255 / 0.16); }
.reach__icon .icon { width: 1.25rem; height: 1.25rem; }
.reach__handle { margin-left: auto; padding-left: 0.75rem; font-size: 0.875rem; font-weight: 400; }
@media (hover: hover) and (pointer: fine) { .reach__link:hover { text-decoration: underline; text-decoration-thickness: 1.5px; text-underline-offset: 0.25em; } }

/* ---------- the step-by-step quote (form.steps): a white card on the green band ---------- */
.quote {
  --quote-line: color-mix(in srgb, var(--colour-text) 45%, var(--colour-background)); /* 3:1 on white */
  display: block; container: quote / inline-size;
  padding: clamp(1.25rem, 3vw, 2.25rem); border-radius: 1.375rem;
  background: var(--colour-background); color: var(--colour-text);
}
.quote :focus-visible { outline-color: var(--colour-main); }
.quote fieldset { min-width: 0; margin: 0; padding: 0; border: 0; }
.quote .field { margin-bottom: 0; }
.quote__head { display: flex; align-items: center; min-height: 2.75rem; color: var(--colour-soft); font-size: 0.9375rem; }
.quote__count { margin-left: auto; }
.quote__back {
  min-height: 2.75rem; margin-left: -0.25rem; padding: 0 0.25rem; border: 0; background: none;
  color: var(--colour-main); font: 700 0.9375rem/1 var(--font-body); cursor: pointer;
  transition: transform 160ms var(--ease-out);
}
.quote__back:active { transform: scale(0.97); }
.quote__bar { height: 0.25rem; margin: 0.5rem 0 1.5rem; border-radius: 0.25rem; background: var(--colour-line); overflow: hidden; }
.quote__fill { display: block; height: 100%; background: var(--colour-main); transform: scaleX(0); transform-origin: left; transition: transform 380ms var(--ease-out); }
.quote__hint { margin-top: 0.375rem; color: var(--colour-soft); }
.quote__step > .quote__question { margin-top: 1.25rem; }
.quote__step > .quote__question + .quote__question { margin-top: 1.75rem; }
.quote__label { display: block; margin-bottom: 0.5rem; font-size: 0.9375rem; font-weight: 700; }
legend.quote__label { margin-bottom: 0.75rem; padding: 0; font: 500 1.1875rem/1.3 var(--font-headings); letter-spacing: -0.01em; }
.quote__optional { color: var(--colour-soft); font-family: var(--font-body); font-size: 0.9375rem; font-weight: 400; letter-spacing: 0; }
.quote .field input, .quote .field textarea { border-color: var(--quote-line); }
.quote .field input:focus-visible, .quote .field textarea:focus-visible { border-color: var(--colour-main); }
.quote .field [aria-invalid="true"] { border-color: var(--colour-error); }
.quote .field__error { padding: 0; }
.quote__nav { display: flex; justify-content: flex-end; margin-top: 1.75rem; }
.quote__nav .button { min-width: 9rem; }
/* greyed until the step is answered (aria-disabled: still reachable, and a press says what's missing) */
.quote__next[aria-disabled="true"] {
  background: var(--colour-surface); color: color-mix(in srgb, var(--colour-text) 62%, var(--colour-surface)); cursor: default;
}
.quote__next[aria-disabled="true"]:active { transform: none; }
/* without site.js every step shows, one under another */
.quote:not(.is-stepped) .quote__step + .quote__step { margin-top: 2rem; padding-top: 2rem; border-top: 1px solid var(--colour-line); }
/* with it, one step at a time: the track slides and the window takes the height of the step on screen */
.quote.is-stepped .quote__viewport { margin-inline: -0.5rem; overflow: hidden; overflow: clip; transition: height 380ms var(--ease-out); }
.quote.is-stepped .quote__track { display: flex; align-items: flex-start; transition: transform 380ms var(--ease-out); }
.quote.is-stepped .quote__step { flex: 0 0 100%; min-width: 0; padding: 0.5rem; } /* room for focus rings */

/* job tiles: a photo you tick (a checkbox underneath, so it works by keyboard and without site.js) */
.tiles { display: grid; grid-template-columns: repeat(2, minmax(0, 1fr)); gap: 0.75rem; }
@container quote (min-width: 32rem) { .tiles { grid-template-columns: repeat(3, minmax(0, 1fr)); } }
.tile {
  position: relative; display: block; aspect-ratio: 5 / 4; border-radius: 0.875rem;
  background: #000; color: #fff; cursor: pointer; -webkit-tap-highlight-color: transparent;
  transition: transform 160ms var(--ease-out);
}
.tile:active { transform: scale(0.97); }
.tile__input, .chip__input { position: absolute; inset: 0; width: 100%; height: 100%; margin: 0; opacity: 0; cursor: pointer; }
.tile__photo { position: absolute; inset: 0; width: 100%; height: 100%; border-radius: inherit; object-fit: cover; opacity: 0.72; transition: opacity 200ms ease; }
.tile__face { position: absolute; inset: 0; border-radius: inherit; background: linear-gradient(to top, rgb(0 0 0 / 0.6), rgb(0 0 0 / 0) 65%); pointer-events: none; }
.tile__face::after { content: ""; position: absolute; inset: 0; border-radius: inherit; box-shadow: inset 0 0 0 4px var(--colour-main); opacity: 0; transition: opacity 200ms ease; }
.tile__label { position: absolute; right: 2.75rem; bottom: 0.625rem; left: 0.75rem; font-size: 0.9375rem; font-weight: 700; line-height: 1.25; text-shadow: 0 1px 8px rgb(0 0 0 / 0.5); }
.tile__tick {
  position: absolute; top: 0.625rem; right: 0.625rem; display: grid; place-items: center;
  width: 1.75rem; height: 1.75rem; border-radius: 50%; background: var(--colour-main);
  opacity: 0; transform: scale(0.7); transition: opacity 200ms ease, transform 240ms var(--ease-out);
}
.tile__tick .icon { width: 1rem; height: 1rem; }
.tile__input:checked ~ .tile__photo { opacity: 1; }
.tile__input:checked ~ .tile__face::after, .tile__input:checked ~ .tile__face .tile__tick { opacity: 1; transform: none; }
.tile__input:focus-visible ~ .tile__face { outline: 3px solid var(--colour-main); outline-offset: 3px; }
@media (hover: hover) and (pointer: fine) { .tile:hover .tile__photo { opacity: 0.88; } .tile:hover .tile__input:checked ~ .tile__photo { opacity: 1; } }

/* choices: pills with a ring that fills with a tick */
.chips { display: flex; flex-wrap: wrap; gap: 0.625rem; }
.quote__other { margin-top: 0.75rem; }
.chip { position: relative; display: inline-flex; max-width: 100%; }
.chip__face {
  display: inline-flex; align-items: center; gap: 0.5rem; min-height: 2.75rem; padding: 0.5rem 1rem 0.5rem 0.75rem;
  border-radius: 999px; box-shadow: inset 0 0 0 1.5px var(--quote-line);
  font-size: 0.9375rem; font-weight: 600; line-height: 1.25; pointer-events: none;
  transition: background-color 200ms ease, color 200ms ease, transform 160ms var(--ease-out);
}
.chip__face .icon { width: 1.125rem; height: 1.125rem; padding: 0.125rem; border-radius: 50%; box-shadow: inset 0 0 0 1.5px var(--quote-line); color: transparent; transition: color 200ms ease, background-color 200ms ease; }
.chip__input:checked + .chip__face { background: var(--colour-main); color: var(--colour-background); box-shadow: none; }
.chip__input:checked + .chip__face .icon { background: var(--colour-background); color: var(--colour-main); box-shadow: none; }
.chip__input:active + .chip__face { transform: scale(0.97); }
.chip__input:focus-visible + .chip__face { outline: 3px solid var(--colour-main); outline-offset: 3px; }

/* sent: the questions fold away and the answers are listed back */
.quote.is-sent .quote__head, .quote.is-sent .quote__viewport { display: none; }
.quote.is-sent .quote__bar { margin-bottom: 0; }
.quote__done { margin-top: 1.25rem; }
.quote__done[data-kind="ok"] { flex-direction: column; gap: 0.75rem; margin: 0; padding: 2rem 0 0.5rem; background: none; color: var(--colour-text); text-align: center; }
.quote__done[data-kind="ok"] .enquiry__tick { width: 3.5rem; height: 3.5rem; color: var(--colour-main); }
.quote__done[data-kind="ok"] [data-status-text] { max-width: 34ch; font: 500 1.25rem/1.35 var(--font-headings); }
.quote__summary { display: flex; flex-wrap: wrap; justify-content: center; gap: 0.5rem; margin: 0.25rem 0 0; padding: 0; list-style: none; }
.quote__summary li { padding: 0.375rem 0.75rem; border-radius: 999px; background: var(--colour-surface, var(--colour-line)); font-size: 0.875rem; font-weight: 600; }

/* ---------- a page's opening: label, main heading, words (and a photo on About) ---------- */
main > section.intro { padding-block: clamp(3rem, 7vw, 6.5rem) clamp(2.75rem, 6vw, 5.5rem); }
.intro__inner { display: grid; gap: 1.375rem 4.5rem; grid-template-areas: "head" "words"; }
.intro--photo .intro__inner { grid-template-areas: "photo" "head" "words"; }
.intro__head { grid-area: head; }
.intro__words { grid-area: words; }
.intro__photo { grid-area: photo; aspect-ratio: 4 / 3; }
.intro__photo img { object-position: 50% 30%; }
.intro__title { margin-top: 1rem; font-size: clamp(2.5rem, 3.4vw + 1.25rem, 4.125rem); line-height: 1.04; letter-spacing: -0.03em; }
.intro__title:has(> .label) { margin-top: 0; }
.intro__title > .label { margin-bottom: 1rem; }
.intro__rise { display: block; overflow: hidden; padding-bottom: 0.08em; margin-bottom: -0.08em; }
.intro__rise > span { display: block; }
.intro__subline { margin-top: 0.875rem; color: var(--colour-soft); font: 500 clamp(1.1875rem, 0.6vw + 1rem, 1.375rem)/1.35 var(--font-headings); letter-spacing: -0.01em; }
.intro__text { max-width: 62ch; color: var(--colour-soft); }
.intro__text:first-child { color: var(--colour-text); font-size: clamp(1.125rem, 0.4vw + 1rem, 1.25rem); }
.intro__text + .intro__text { margin-top: 1rem; }
.intro__signature { margin-top: 1.25rem; font-weight: 700; }
.intro__jump ul { display: flex; flex-wrap: wrap; gap: 0.625rem; margin: 1.75rem 0 0; padding: 0; list-style: none; }
/* the ring is a border, so its colour can change smoothly (motion stays on transform, opacity and colours) */
.intro__jump a {
  display: inline-flex; align-items: center; gap: 0.5rem; min-height: 2.75rem; padding: calc(0.5rem - 1.5px) calc(1rem - 1.5px) calc(0.5rem - 1.5px) calc(0.875rem - 1.5px);
  border: 1.5px solid color-mix(in srgb, var(--colour-text) 45%, var(--colour-background)); border-radius: 999px;
  font-size: 0.9375rem; font-weight: 700; text-decoration: none;
  transition: border-color 200ms ease, transform 160ms var(--ease-out);
}
.intro__jump a:active { transform: scale(0.97); }
.intro__jump .icon { width: 1rem; height: 1rem; }
@media (hover: hover) and (pointer: fine) { .intro__jump a:hover { border-color: var(--colour-text); } }
@media (min-width: 56rem) {
  .intro__inner { grid-template-columns: 5fr 7fr; grid-template-areas: "head words"; align-items: start; }
  .intro__words { padding-top: 2.5rem; } /* level with the heading, under the label */
  .intro--photo .intro__inner { grid-template-columns: 7fr 5fr; grid-template-areas: "head photo" "words photo"; grid-template-rows: auto 1fr; }
  .intro--photo .intro__words { padding-top: 0; }
  .intro__photo { align-self: center; justify-self: end; width: 100%; max-width: 27.5rem; aspect-ratio: 4 / 5; }
}
@media (prefers-reduced-motion: no-preference) {
  /* the heading rises into place as the page opens; the words follow */
  .js .intro__rise > span { animation: ba-rise 800ms var(--ease-out) 80ms both; }
  .js .intro__head .label, .js .intro__subline, .js .book .label { animation: ba-fade 500ms var(--ease-out) 220ms both; }
  .js .intro__words { animation: ba-fade 500ms var(--ease-out) 300ms both; }
}

/* ---------- a service: its photo across the page, its words on a card over the photo's foot ---------- */
main > section.service { padding-block: clamp(2.5rem, 5vw, 4.5rem); }
/* a link to a service (/services/#driveways, e.g. from an ad) lands on its photo, not the gap above it */
main > section.service { scroll-margin-top: calc(-1 * clamp(2.5rem, 5vw, 4.5rem)); }
/* a set width, so a height limit crops the photo instead of narrowing it */
.service__photo { width: 100%; aspect-ratio: 4 / 3; }
/* phones on their side: a shorter photo, so the heading shows under it */
@media (orientation: landscape) and (max-height: 30rem) { .service__photo { max-height: 45svh; } }
.service__card { margin-top: 1.375rem; }
.service__card .label { margin-bottom: 0.625rem; }
/* the label is read after the service's name ("Patios & Paving In Redditch") but shows above it */
.service__title { display: flex; flex-direction: column-reverse; align-items: flex-start; }
.service__text { max-width: 52ch; margin-top: 0.75rem; color: var(--colour-soft); }
.service__jobs { display: flex; flex-wrap: wrap; gap: 0.5rem; margin: 1.25rem 0 0; padding: 0; list-style: none; }
.service__jobs li { padding: 0.4375rem 0.875rem; border-radius: 999px; background: var(--colour-surface); font-size: 0.9375rem; font-weight: 600; }
@media (min-width: 56rem) {
  .service__photo { aspect-ratio: 21 / 9; }
  .service__card {
    position: relative; width: min(35rem, 48%); margin: -7.5rem 0 0 2.5rem; padding: 2rem 2.25rem;
    border-radius: 1rem; background: var(--colour-background); box-shadow: 0 1.125rem 3.125rem rgb(0 0 0 / 0.12);
  }
  .service--flip .service__card { margin-left: auto; margin-right: 2.5rem; }
}

/* lists that step in, item by item, the first time they come into view (site.js); at most ten steps */
@media (prefers-reduced-motion: no-preference) {
  [data-list-reveal][data-waiting] > li { opacity: 0; transform: translateY(6px); }
  [data-list-reveal][data-waiting].is-in > li {
    opacity: 1; transform: none;
    transition: opacity 300ms ease, transform 300ms var(--ease-out);
    transition-delay: calc(120ms + min(var(--i, 0), 10) * 40ms);
  }
}

/* ---------- the towns covered, as a plain list ---------- */
.area__inner { display: grid; gap: 1.5rem 4.5rem; }
@media (min-width: 56rem) { .area__inner { grid-template-columns: 5fr 7fr; } }
.area__text { max-width: 40ch; margin-top: 0.875rem; color: var(--colour-soft); }
.area__towns { margin: 0; padding: 0; list-style: none; columns: 2; column-gap: 1.75rem; }
@media (min-width: 38rem) { .area__towns { columns: 3; } }
.area__towns li {
  display: flex; flex-wrap: wrap; align-items: baseline; justify-content: space-between; gap: 0.25rem 0.5rem;
  padding: 0.6875rem 0; border-top: 1px solid color-mix(in srgb, var(--colour-text) 14%, transparent); break-inside: avoid;
  font: 500 1.125rem/1.3 var(--font-headings); letter-spacing: -0.01em;
}
.area__towns .area__base { font-weight: 600; }
.area__tag { padding: 0.125rem 0.5rem; border-radius: 999px; background: var(--colour-background); color: var(--colour-main); font: 700 0.75rem/1.4 var(--font-body); letter-spacing: 0; white-space: nowrap; }
.area__note { margin-top: 1.375rem; color: var(--colour-soft); font-size: 0.9375rem; }

/* a service's link to its projects, and to its own page */
.service__projects { display: inline-block; margin-top: 1.25rem; }
.service__more { display: inline-block; margin-top: 1.25rem; }
.service__projects + .service__more { margin-left: 1.5rem; }

/* ---------- a service page's questions (the shared faq block: they open and close without a script) ---------- */
main > section.faq { background: var(--colour-surface); }
.faq__inner { max-width: 52rem; }
.faq__list { display: grid; gap: 0.625rem; margin-top: clamp(1.5rem, 3vw, 2.25rem); }
.question { border-radius: 0.5rem; background: var(--colour-background); }
.question__summary {
  display: flex; align-items: center; justify-content: space-between; gap: 1rem; padding: 1.125rem 1.25rem;
  font: 600 1.125rem/1.35 var(--font-headings); list-style: none; cursor: pointer;
}
.question__summary::-webkit-details-marker { display: none; }
.question__icon { position: relative; flex: none; width: 0.875rem; height: 0.875rem; }
.question__icon::before, .question__icon::after {
  content: ""; position: absolute; top: 50%; left: 0; width: 100%; height: 2px; margin-top: -1px; border-radius: 1px;
  background: var(--colour-main); transition: transform 200ms var(--ease-out);
}
.question__icon::after { transform: rotate(90deg); }
.question[open] .question__icon::after { transform: rotate(0deg); }
.question__answer { max-width: 62ch; padding: 0 1.25rem 1.25rem; color: var(--colour-soft); }

/* ---------- a service page's other services: a photo card for each page in its drop-down ---------- */
.others h2 .label { display: flex; margin-bottom: 0.625rem; }
.others__grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 13rem), 1fr)); gap: 1rem; margin: clamp(1.5rem, 3vw, 2.25rem) 0 0; padding: 0; list-style: none; }
.others__grid li { display: flex; } /* the cards in a row are as tall as each other */
.others__card { display: block; flex: 1; overflow: hidden; border-radius: 0.5rem; background: var(--colour-surface); color: inherit; text-decoration: none; transition: transform 160ms var(--ease-out); }
.others__card:active { transform: scale(0.98); }
.others__photo { display: block; width: 100%; height: auto; aspect-ratio: 4 / 3; object-fit: cover; }
.others__name { display: flex; align-items: center; justify-content: space-between; gap: 0.75rem; padding: 0.875rem 1rem; font: 600 1.0625rem/1.3 var(--font-headings); }
/* the logo's two slashes, as every "see more" link has, at the card's edge so a long name never leaves them alone */
.others__name::after {
  content: ""; flex: none; width: 2.5px; height: 0.8em; margin-right: 5.5px; border-radius: 1px;
  background: var(--colour-main); box-shadow: 5.5px 0 var(--colour-main); transform: skewX(-20deg); transition: transform 320ms var(--ease-out);
}
@media (hover: hover) and (pointer: fine) {
  .others__card:hover .others__name { color: var(--colour-main); }
  .others__card:hover .others__name::after { transform: translateX(4px) skewX(-20deg); }
}

/* ---------- the projects page: filters, then one story per project ---------- */
main > section.stories { padding-top: 0; }
/* they need site.js, so they only show with JavaScript, but from the first paint, so the stories don't move down */
.stories__filters { display: none; padding-bottom: clamp(1.75rem, 3vw, 2.25rem); }
.js .stories__filters { display: block; }
.stories__chips { display: flex; flex-wrap: wrap; gap: 0.625rem; }
/* the ring is a border, so its colour can change smoothly (motion stays on transform, opacity and colours) */
.filter {
  min-height: 2.75rem; padding: calc(0.5rem - 1.5px) calc(1rem - 1.5px);
  border: 1.5px solid color-mix(in srgb, var(--colour-text) 45%, var(--colour-background)); border-radius: 999px;
  background: transparent; color: var(--colour-text); font: 700 0.9375rem/1.2 var(--font-body); cursor: pointer;
  transition: background-color 200ms ease, color 200ms ease, border-color 200ms ease, transform 160ms var(--ease-out);
}
.filter:active { transform: scale(0.97); }
.filter[aria-pressed="true"] { border-color: var(--colour-text); background: var(--colour-text); color: var(--colour-background); }
@media (hover: hover) and (pointer: fine) { .filter[aria-pressed="false"]:hover { border-color: var(--colour-text); } }
.stories__count { margin-top: 0.875rem; color: var(--colour-soft); font-size: 0.9375rem; }
/* a service page's few projects of one kind (service_projects): its own heading, then a button to all of them */
main > section.stories--kind { padding-top: clamp(3.5rem, 7vw, 6.5rem); }
.stories__head { padding-bottom: clamp(0.5rem, 1.5vw, 1rem); }
.stories__head .label { display: flex; margin-bottom: 0.625rem; }
.stories__all { display: flex; justify-content: center; padding-top: clamp(2rem, 3.5vw, 2.75rem); border-top: 1px solid var(--colour-line); }
.story { display: grid; gap: 1.5rem 3.5rem; padding-block: clamp(2.25rem, 4.5vw, 3.5rem); border-top: 1px solid var(--colour-line); }
.story__media { min-width: 0; }
.story__lead, .compare { display: block; width: 100%; aspect-ratio: 4 / 3; }
.story__lead, .story__thumb { cursor: zoom-in; }
.story :is(h2, h3) { font-size: clamp(1.625rem, 1.2vw + 1.25rem, 2.25rem); line-height: 1.12; } /* h3 under a service page's heading */
.story .label { margin-bottom: 0.75rem; }
.story__kinds { display: flex; flex-wrap: wrap; gap: 0.375rem; margin: 0.875rem 0 0; padding: 0; list-style: none; }
.story__kinds li { padding: 0.25rem 0.75rem; border-radius: 999px; background: var(--colour-surface); font-size: 0.875rem; font-weight: 700; }
.story__text { max-width: 46ch; margin-top: 1rem; color: var(--colour-soft); }
.story__thumbs { display: grid; grid-template-columns: repeat(4, minmax(0, 1fr)); gap: 0.625rem; margin: 1.375rem 0 0; padding: 0; list-style: none; }
.story__thumb { display: block; aspect-ratio: 1; }
/* with site.js four show, and the fourth says how many more the viewer holds; without it every photo shows */
.js .story__thumbs li:nth-child(n + 5) { display: none; }
.story__more { display: none; }
.js .story__more {
  position: absolute; inset: 0; display: grid; place-items: center;
  background: rgb(0 0 0 / 0.55); color: #fff; font: 600 1.25rem/1 var(--font-headings);
}
.story__quote { display: inline-block; margin-top: 1.375rem; }
@media (hover: hover) and (pointer: fine) {
  .story__lead img, .story__thumb img { transition: transform 600ms var(--ease-out); }
  .story__lead:hover img, .story__thumb:hover img { transform: scale(1.035); }
}
@media (min-width: 56rem) {
  .story { grid-template-columns: 7fr 5fr; align-items: center; }
  .story--flip { grid-template-columns: 5fr 7fr; }
  .story--flip .story__media { order: 2; }
}

/* a project's before-and-after: the opening's slanted line, resting half way (site.js); without it, the after photo */
.compare { background: #222; }
.compare__photo { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; pointer-events: none; }
.compare.is-live { cursor: ew-resize; touch-action: pan-y; user-select: none; -webkit-user-select: none; }
.compare__divider {
  position: absolute; top: -6%; left: 0; width: 3px; height: 112%; margin-left: -1.5px;
  background: #fff; box-shadow: 0 0 0.75rem rgba(0, 0, 0, 0.35); pointer-events: none; opacity: 0;
}
.compare__handle { position: absolute; top: 50%; left: 0; z-index: 2; width: 2.875rem; height: 2.875rem; margin: -1.4375rem 0 0 -1.4375rem; border-radius: 50%; }
.compare__handle:focus-visible { outline-color: #fff; outline-offset: 4px; }
.compare__knob {
  display: grid; place-items: center; width: 100%; height: 100%; border-radius: 50%;
  background: #fff; color: var(--colour-main); box-shadow: 0 0.25rem 1rem rgba(0, 0, 0, 0.3);
  transition: transform 200ms var(--ease-out);
}
.compare__knob svg { width: 1.375rem; height: 1.375rem; }
.compare.is-dragging .compare__knob { transform: scale(1.08); }
.compare__tag {
  position: absolute; top: 0.75rem; z-index: 1; display: none; padding: 0.3125rem 0.625rem; border-radius: 999px;
  background: rgba(0, 0, 0, 0.6); color: #fff; font-size: 0.8125rem; font-weight: 700; pointer-events: none;
}
.compare__tag--after { left: 0.75rem; }
.compare__tag--before { right: 0.75rem; }
.compare.is-live .compare__divider { opacity: 1; }
.compare.is-live .compare__tag { display: block; }

/* the full-screen photo viewer (site.js opens it; a native dialog, so the rest of the page waits behind it) */
html:has(.viewer[open]) { overflow: hidden; }
.viewer {
  position: fixed; inset: 0; width: 100%; max-width: none; height: 100%; max-height: none; margin: 0; padding: 0;
  border: 0; background: rgb(0 0 0 / 0.92); color: #fff;
}
.viewer[open] { display: grid; grid-template-rows: auto minmax(0, 1fr) auto; }
.viewer::backdrop { background: transparent; }
.viewer :focus-visible { outline-color: #fff; }
.viewer__top { display: flex; align-items: center; justify-content: space-between; gap: 1rem; padding: 0.875rem 1rem; font-size: 0.9375rem; }
/* one cell the size of the stage, measured as a container: the photo's size comes from its shape (--ratio, set by
   site.js) and the stage, before it has loaded, so it can grow from the photo tapped straight away */
.viewer__stage { position: relative; display: grid; grid-template: minmax(0, 1fr) / minmax(0, 1fr); place-items: center; min-height: 0; padding: 0 4.25rem; container-type: size; }
.viewer__photo { display: block; width: min(100cqw, 100cqh * var(--ratio, 1.5)); height: auto; aspect-ratio: var(--ratio, 1.5); object-fit: contain; transform-origin: 0 0; }
.viewer__button {
  display: grid; place-items: center; flex: none; width: 2.875rem; height: 2.875rem; padding: 0; border: 0; border-radius: 50%;
  background: rgb(255 255 255 / 0.14); color: #fff; cursor: pointer;
  transition: background-color 200ms ease, transform 160ms var(--ease-out);
}
.viewer__button:active { transform: scale(0.97); }
.viewer__button svg { width: 1.375rem; height: 1.375rem; }
@media (hover: hover) and (pointer: fine) { .viewer__button:hover { background: rgb(255 255 255 / 0.24); } }
.viewer__step { position: absolute; top: 50%; margin-top: -1.4375rem; }
.viewer__step:active { transform: scale(0.97); }
.viewer__step--back { left: 0.75rem; }
.viewer__step--next { right: 0.75rem; }
.viewer__caption { max-width: 60ch; margin: 0 auto; padding: 0.875rem 1rem 1.375rem; text-align: center; font-size: 0.9375rem; }
.viewer__caption strong { display: block; font: 600 1.0625rem/1.3 var(--font-headings); }
/* phones: the photo takes the whole width and the arrows sit over it */
@media (max-width: 40rem) {
  .viewer__stage { padding: 0; }
  .viewer__step { background: rgb(0 0 0 / 0.45); }
}

/* ---------- footer ---------- */
.foot { padding-block: 3.5rem 2.5rem; }
.foot__top { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 1.25rem 2.5rem; }
.foot__contact { display: flex; flex-wrap: wrap; gap: 0.75rem 2.5rem; font: 500 clamp(1.1875rem, 1.6vw + 0.9rem, 1.875rem)/1.2 var(--font-headings); }
.foot__contact a { min-width: 0; overflow-wrap: anywhere; } /* a long email address wraps on the smallest phones */
.foot__contact a { text-decoration: none; }
.foot__phone { color: var(--colour-main); }
.foot__email { text-decoration: underline !important; text-decoration-thickness: 1.5px !important; text-underline-offset: 0.3em; }
.foot__social { display: flex; gap: 0.75rem; margin: 0; padding: 0; list-style: none; }
.foot__social a { display: grid; place-items: center; width: 2.75rem; height: 2.75rem; border-radius: 50%; background: var(--colour-surface); }
.foot__social .icon { width: 1.25rem; height: 1.25rem; }
.foot__nav ul { display: flex; flex-wrap: wrap; gap: 0 1.625rem; margin: 2rem 0 0; padding: 1rem 0 0; border-top: 1px solid var(--colour-line); list-style: none; }
.foot__nav a { display: inline-flex; align-items: center; min-height: 2.75rem; font-weight: 700; text-decoration: none; }
.foot__nav a[aria-current] { color: var(--colour-main); }
@media (hover: hover) and (pointer: fine) { .foot__nav a:hover { text-decoration: underline; text-underline-offset: 0.25em; } }
.foot__area { max-width: 90ch; margin-top: 2rem; padding-top: 1.5rem; border-top: 1px solid var(--colour-line); color: var(--colour-soft); font-size: 0.9375rem; }
.foot__nav + .foot__area { margin-top: 0.75rem; padding-top: 0; border-top: 0; }
.foot__small { display: flex; flex-wrap: wrap; gap: 0.5rem 1.5rem; margin: 0.875rem 0 0; padding: 0; list-style: none; color: var(--colour-soft); font-size: 0.875rem; }

/* ---------- the cookie banner (sites with Google's tag): at the foot of the screen until the visitor chooses ---------- */
.cookies {
  position: fixed; inset: auto 0.75rem 0.75rem; z-index: 30; /* over the page and the top bar (not its open phone menu); under the skip link */
  max-width: 46rem; margin-inline: auto; padding: 1rem 1.125rem; border-radius: 1rem;
  background: var(--colour-background); color: var(--colour-text);
  box-shadow: 0 0 0 1px var(--colour-line), 0 1.25rem 2.5rem -1rem rgb(0 0 0 / 0.35);
}
.cookies__inner { display: grid; gap: 0.875rem; }
.cookies__text { font-size: 0.9375rem; line-height: 1.5; }
.cookies__text a { font-weight: 700; color: var(--colour-main); text-decoration-thickness: 1.5px; text-underline-offset: 0.2em; white-space: nowrap; }
.cookies__choices { display: flex; gap: 0.625rem; }
.cookies__button { flex: 1; } /* Accept and Reject look the same */
@media (min-width: 40rem) {
  .cookies__inner { grid-template-columns: minmax(0, 1fr) auto; align-items: center; gap: 1.5rem; }
  .cookies__button { flex: none; min-width: 7rem; }
}
@media (prefers-reduced-motion: no-preference) {
  .cookies:not([hidden]) { animation: cookies-in 320ms var(--ease-out) 400ms both; }
  .cookies[data-reopened]:not([hidden]) { animation-delay: 0ms; } /* asked for from the footer: no wait */
}
@keyframes cookies-in { from { opacity: 0; transform: translateY(0.75rem); } }
/* While it's up, the footer's last lines scroll clear of it, and nothing the keyboard moves to is hidden under it */
:root:has(.cookies:not([hidden])) { scroll-padding-bottom: calc(var(--cookies-room, 0px) + 1.5rem); }
:root:has(.cookies:not([hidden])) .foot { padding-bottom: calc(2.5rem + var(--cookies-room, 0px) + 0.75rem); }
.foot__button { padding: 0; border: 0; background: none; color: inherit; font: inherit; text-decoration: underline; text-underline-offset: 0.2em; cursor: pointer; }

/* ---------- the thank-you page (form.thanks_page) ---------- */
.thanks { padding-block: clamp(3.5rem, 9vw, 6.5rem); }
.thanks__inner { max-width: 42rem; }
.thanks h1 { font-size: clamp(2.25rem, 5vw, 3.25rem); }
.thanks__tick { display: block; width: 3.5rem; height: 3.5rem; margin-bottom: 1.5rem; color: var(--colour-main); }
.thanks__tick circle { fill: currentColor; opacity: 0.14; }
.thanks__tick path { fill: none; stroke: currentColor; stroke-width: 2.4; stroke-linecap: round; stroke-linejoin: round; }
.thanks__text { max-width: 50ch; margin-top: 1rem; font-size: 1.125rem; }
.thanks__summary { margin-top: 1.75rem; }
.thanks__label { margin-bottom: 0.625rem; font-weight: 700; }
.thanks__summary .quote__summary { justify-content: flex-start; }
.thanks__actions { margin-top: 2.25rem; }
@media (prefers-reduced-motion: no-preference) {
  .thanks__tick { animation: status-in 300ms var(--ease-out) both; }
  .thanks__tick path { stroke-dasharray: 1; animation: tick-draw 450ms var(--ease-out) 200ms both; }
}

/* ---------- privacy and not-found pages ---------- */
.privacy, .not-found { padding-block: clamp(3rem, 7vw, 5rem); }
.privacy__inner { max-width: 44rem; }
.privacy h1, .not-found h1 { font-size: clamp(2.25rem, 5vw, 3.25rem); }
.privacy h2 { margin-top: 2.25rem; font-size: 1.5rem; }
.privacy p, .privacy li { max-width: 65ch; }
.privacy p { margin-top: 1rem; }
.not-found__inner { max-width: 40rem; }
.not-found p { margin-top: 1rem; }

/* ---------- reduced motion and print ---------- */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after { transition-duration: 1ms !important; animation-duration: 1ms !important; animation-delay: 0ms !important; }
}
/* the phone menu fades instead of unrolling (only on phones: a laptop's links are always in the bar) */
@media (prefers-reduced-motion: reduce) and (max-width: 59.99rem) {
  .js .bar--menu .bar__nav { transition: opacity 200ms ease, visibility 0s !important; clip-path: none; opacity: 0; }
  .js .bar--menu[data-open] .bar__nav { opacity: 1; }
}
@media print {
  .bar { position: static; }
  .ba__stage { aspect-ratio: auto; height: 60vh; }
  [data-photo-reveal] { clip-path: none !important; }
  .arrows, .ba__handle, .compare__handle, .review__more { display: none !important; }
  .review__text.is-clamped { display: block; }
}
