/* ==========================================================================
   PaveLocal — site styles
   Direction: the material, not the marketing. Graphite ground the colour of wet
   granite, one clay accent taken from the red end of a block-paving pallet, and
   a warm sand paper so the light pages do not read as clinical white. Grotesque
   display type for the weight, a plain sans for anything you actually read.

   Palette differs from every other Ivy Hive property on purpose. Identical
   styling across sites is a footprint that links them together.
   ========================================================================== */

:root {
  /* Colour ------------------------------------------------------------- */
  --graphite-900: #17191d;   /* ground — darkest surface */
  --graphite-850: #1c1f24;
  --graphite-800: #212429;   /* raised surface on dark */
  --graphite-700: #2b2f36;
  --graphite-600: #3a3f48;
  --graphite-crest: #2f353f; /* gradient crest on dark sections */
  --graphite-300: #a9a6a0;   /* muted text on dark — 7.25:1 on --graphite-900 */

  --sand:   #faf8f5;         /* page surface */
  --sand-2: #efeae2;         /* sunken surface on light */
  --line:   #ddd6ca;

  --clay:      #e2683a;      /* accent — 5.26:1 on --graphite-900, 4.65:1 on --graphite-800 */
  --clay-lift: #f07a3f;      /* hover only */
  /* Clay for text on light surfaces. Must clear WCAG AA (4.5:1) against BOTH
     --sand and the darker --sand-2, or eyebrows fail on the sunken sections.
     #a03f18 = 6.15 on sand, 5.45 on sand-2. Measured, not eyeballed. */
  --clay-deep: #a03f18;

  --ink:   #17191d;          /* 16.60:1 on --sand */
  --muted: #5c5751;          /* 6.74:1 on --sand, 5.97:1 on --sand-2 */

  /* Type ---------------------------------------------------------------- */
  --display: 'Bricolage Grotesque', 'Segoe UI', system-ui, sans-serif;
  --body:    'Inter', system-ui, -apple-system, 'Segoe UI', sans-serif;
  --mono:    'IBM Plex Mono', ui-monospace, 'Cascadia Mono', monospace;

  --step--1: clamp(0.82rem, 0.79rem + 0.14vw, 0.9rem);
  --step-0:  clamp(1rem, 0.96rem + 0.2vw, 1.12rem);
  --step-1:  clamp(1.2rem, 1.1rem + 0.5vw, 1.5rem);
  --step-2:  clamp(1.5rem, 1.3rem + 1vw, 2.1rem);
  --step-3:  clamp(1.95rem, 1.55rem + 2vw, 3.1rem);
  --step-4:  clamp(2.4rem, 1.75rem + 3.2vw, 4.6rem);

  /* Layout -------------------------------------------------------------- */
  --wrap: 1180px;
  --wrap-narrow: 760px;
  --gutter: clamp(1.15rem, 4vw, 2.5rem);
  --header-h: 70px;
  --callbar-h: 62px;   /* mobile sticky call bar */
  --radius: 5px;
}

/* Reset -------------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; }
body {
  margin: 0;
  background: var(--sand);
  color: var(--ink);
  font-family: var(--body);
  font-size: var(--step-0);
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
}
img, video { max-width: 100%; display: block; }
a { color: inherit; }
button, input, select, textarea { font: inherit; color: inherit; }

h1, h2, h3, h4 {
  font-family: var(--display);
  font-weight: 700;
  font-variation-settings: 'opsz' 48;
  line-height: 1.05;
  letter-spacing: -0.015em;
  margin: 0;
  text-wrap: balance;
}
h1 { font-size: var(--step-4); font-weight: 800; font-variation-settings: 'opsz' 96; letter-spacing: -0.025em; }
h2 { font-size: var(--step-3); }
h3 { font-size: var(--step-1); font-variation-settings: 'opsz' 24; letter-spacing: -0.005em; }
p  { margin: 0; text-wrap: pretty; }

:focus-visible {
  outline: 3px solid var(--clay);
  outline-offset: 3px;
  border-radius: 2px;
}

.skip-link {
  position: absolute; left: 0; top: 0;
  padding: 0.7rem 1.1rem;
  background: var(--clay); color: var(--graphite-900);
  font-weight: 700; z-index: 200;
  transform: translateY(-110%);
}
.skip-link:focus { transform: translateY(0); }

/* Utilities ---------------------------------------------------------------- */
.wrap { width: min(100% - (var(--gutter) * 2), var(--wrap)); margin-inline: auto; }
.visually-hidden {
  position: absolute; width: 1px; height: 1px; overflow: hidden;
  clip-path: inset(50%); white-space: nowrap;
}

/* Eyebrow: a docket label, not decoration. */
.eyebrow {
  font-family: var(--mono);
  font-size: var(--step--1);
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--clay-deep);
  margin: 0 0 1rem;
  display: flex; align-items: center; gap: 0.7rem;
}
.eyebrow::before {
  content: ''; width: 26px; height: 2px;
  background: var(--clay); flex: none;
}
.on-dark .eyebrow { color: var(--clay); }

.lede { font-size: var(--step-1); line-height: 1.45; color: var(--muted); max-width: 58ch; }
.on-dark .lede { color: var(--graphite-300); }

/* Display-weight opening line for a section whose real headings are the h2s
   inside it — the services block, where each service carries its own h2 and a
   wrapping "Services" heading would push those down a level. */
.statement {
  font-family: var(--display); font-weight: 700;
  font-variation-settings: 'opsz' 90;
  font-size: var(--step-2); line-height: 1.15; letter-spacing: -0.015em;
  color: var(--ink); max-width: 26ch;
}
.on-dark .statement { color: var(--sand); }

.section { padding-block: clamp(3.25rem, 8vw, 6.5rem); }
.section-dark { background: var(--graphite-900); color: var(--sand); }
.section-sunk { background: var(--sand-2); }
.section-head { max-width: 62ch; margin-bottom: clamp(2rem, 5vw, 3.25rem); }

/* Buttons ------------------------------------------------------------------ */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 0.55rem;
  padding: 0.9rem 1.5rem;
  font-family: var(--body);
  font-weight: 700;
  font-size: var(--step-0);
  line-height: 1.2;
  text-decoration: none;
  border: 2px solid transparent;
  border-radius: var(--radius);
  cursor: pointer;
  transition: transform 0.12s ease, background-color 0.15s ease, color 0.15s ease;
}
.btn:hover { transform: translateY(-2px); }
.btn:active { transform: translateY(0); }
.btn-primary { background: var(--clay); color: var(--graphite-900); border-color: var(--clay); }
.btn-primary:hover { background: var(--clay-lift); border-color: var(--clay-lift); }
.btn-ghost { background: transparent; color: var(--ink); border-color: var(--ink); }
.btn-ghost:hover { background: var(--ink); color: var(--sand); }
.on-dark .btn-ghost { color: var(--sand); border-color: rgba(250, 248, 245, 0.45); }
.on-dark .btn-ghost:hover { background: var(--sand); color: var(--graphite-900); border-color: var(--sand); }
.btn svg { width: 1.15em; height: 1.15em; flex: none; }
.btn-arrow { transition: transform 0.15s ease; }
.btn:hover .btn-arrow { transform: translateX(3px); }

/* Email button. Neutral surface rather than a second accent — one accent on the
   page keeps the primary CTA unambiguous. */
.btn-mail { background: var(--graphite-700); color: #fff; border-color: var(--graphite-600); }
.btn-mail:hover { background: var(--graphite-600); border-color: var(--graphite-600); }

/* Header ------------------------------------------------------------------- */
.site-header {
  position: sticky; top: 0; z-index: 100;
  background: rgba(23, 25, 29, 0.94);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid rgba(250, 248, 245, 0.12);
  color: var(--sand);
}
.header-inner {
  display: flex; align-items: center; justify-content: space-between;
  gap: 1rem; height: var(--header-h);
}
.logo {
  display: inline-flex; align-items: center; gap: 0.65rem;
  text-decoration: none; color: var(--sand);
}
.logo-mark { width: 34px; height: 40px; flex: none; }
.logo-text { display: grid; line-height: 1; }
.logo-name {
  font-family: var(--display); font-weight: 800; font-variation-settings: 'opsz' 90;
  font-size: 1.28rem; letter-spacing: -0.02em;
}
.logo-name em { font-style: normal; color: var(--clay); }
.logo-sub {
  font-family: var(--mono); font-size: 0.6rem; font-weight: 500;
  letter-spacing: 0.28em; text-transform: uppercase;
  color: var(--graphite-300); margin-top: 0.28rem;
}

.nav { display: flex; align-items: center; gap: clamp(0.9rem, 2vw, 1.75rem); }
.nav-link {
  text-decoration: none; font-size: 0.95rem; font-weight: 500;
  color: var(--sand); opacity: 0.82; white-space: nowrap;
}
.nav-link:hover, .nav-link[aria-current='page'] { opacity: 1; color: var(--clay); }
.nav .btn { padding: 0.6rem 1.05rem; font-size: 0.93rem; }
.nav-phone {
  font-family: var(--mono); font-weight: 500; font-size: 0.95rem;
  text-decoration: none; white-space: nowrap;
  display: inline-flex; align-items: center; gap: 0.4rem;
}
.nav-phone:hover { color: var(--clay); }
.nav-phone svg { width: 15px; height: 15px; }

.nav-toggle {
  display: none; background: none; border: 0; padding: 0.4rem;
  color: var(--sand); cursor: pointer;
}
.nav-toggle svg { width: 26px; height: 26px; }

/* 1000, not 900: the Guides link pushed the desktop nav to within 16px of the
   logo at the old breakpoint. The call bar below uses the same value so the two
   mobile affordances always appear together. */
@media (max-width: 1000px) {
  .nav-toggle { display: block; }
  .nav {
    position: fixed; inset: var(--header-h) 0 auto 0;
    flex-direction: column; align-items: stretch; gap: 0;
    background: var(--graphite-900);
    border-bottom: 1px solid rgba(250, 248, 245, 0.14);
    padding: 0.5rem var(--gutter) 1.4rem;
    transform: translateY(-140%);
    transition: transform 0.28s cubic-bezier(0.4, 0, 0.2, 1);
    max-height: calc(100dvh - var(--header-h)); overflow-y: auto;
  }
  .nav[data-open='true'] { transform: translateY(0); }
  .nav-link { padding: 0.85rem 0; border-bottom: 1px solid rgba(250, 248, 245, 0.1); opacity: 1; }
  .nav-phone { padding: 0.95rem 0; }
  .nav .btn { margin-top: 1rem; }
}

/* Anchor targets must clear the sticky header. */
[id] { scroll-margin-top: calc(var(--header-h) + 20px); }

/* Hero --------------------------------------------------------------------- */
.hero {
  position: relative; isolation: isolate;
  background: var(--graphite-900); color: var(--sand);
  padding-block: clamp(3rem, 7vw, 5.5rem) clamp(3rem, 7vw, 5rem);
  overflow: hidden;
}
.hero-media {
  position: absolute; inset: 0; z-index: -2;
  width: 100%; height: 100%; object-fit: cover;
  /* Centre-weighted: the hero images here are surfaces and streets rather than a
     single subject, so an offset crop just loses the edges. */
  object-position: center;
}
.hero::after {
  content: ''; position: absolute; inset: 0; z-index: -1;
  background:
    linear-gradient(100deg,
      var(--graphite-900) 0%,
      rgba(23, 25, 29, 0.97) 42%,
      rgba(23, 25, 29, 0.80) 68%,
      rgba(23, 25, 29, 0.58) 100%),
    linear-gradient(to top, rgba(23, 25, 29, 0.9) 0%, rgba(23, 25, 29, 0) 45%);
}
.hero-grid {
  display: grid; gap: clamp(2.25rem, 5vw, 4rem);
  grid-template-columns: minmax(0, 1.12fr) minmax(0, 0.88fr);
  align-items: center;
}
@media (max-width: 960px) {
  .hero-grid { grid-template-columns: 1fr; }
  .hero-media { object-position: 72% center; }
  .hero::after {
    background:
      linear-gradient(180deg, rgba(23, 25, 29, 0.94) 0%, rgba(23, 25, 29, 0.9) 55%, rgba(23, 25, 29, 0.97) 100%);
  }
}

.hero h1 { margin-bottom: 1.3rem; }
.hero h1 .hl { color: var(--clay); }
.hero-sub { font-size: var(--step-1); color: var(--graphite-300); max-width: 48ch; margin-bottom: 1.9rem; }
.hero-actions { display: flex; flex-wrap: wrap; gap: 0.75rem; margin-bottom: 1.9rem; }
/* Three CTAs at three different widths reads as clutter on a phone. Stack them
   full-width instead — they are the whole point of the hero on mobile. */
@media (max-width: 600px) {
  .hero-actions, .service-actions { flex-direction: column; align-items: stretch; }
}

.hero-facts {
  display: flex; flex-wrap: wrap; gap: 0.5rem 1.5rem;
  font-family: var(--mono); font-size: var(--step--1);
  color: var(--graphite-300); letter-spacing: 0.02em;
  padding: 1.4rem 0 0; margin: 0;
  border-top: 1px solid rgba(250, 248, 245, 0.16);
}
.hero-facts li { list-style: none; }
.hero-facts li::before { content: '✓ '; color: var(--clay); }

/* Signature element: the quote docket. A worked example of the quote you get,
   labelled as a sample. It is not a price list and must never read as one. */
.docket {
  background: var(--sand); color: var(--ink);
  border-radius: var(--radius);
  box-shadow: 0 24px 60px -20px rgba(0, 0, 0, 0.7);
  overflow: hidden;
  max-width: 400px; margin-inline: auto; width: 100%;
}
.docket-top {
  background: var(--clay); color: var(--graphite-900);
  padding: 0.6rem 1.1rem;
  font-family: var(--mono); font-size: 0.72rem; font-weight: 500;
  letter-spacing: 0.12em; text-transform: uppercase;
  display: flex; justify-content: space-between; align-items: center; gap: 0.75rem;
}
.docket-body { padding: 1.25rem 1.35rem 1.4rem; }
.docket-title {
  font-family: var(--display); font-weight: 700;
  font-variation-settings: 'opsz' 24;
  font-size: 1.3rem; line-height: 1.05; letter-spacing: -0.01em;
  margin-bottom: 0.85rem;
}
.docket-rows { margin: 0 0 1.1rem; display: grid; gap: 0.55rem; }
.docket-rows div {
  display: grid; grid-template-columns: 92px 1fr; gap: 0.75rem;
  font-size: 0.92rem; align-items: baseline;
}
.docket-rows dt {
  font-family: var(--mono); font-size: 0.7rem; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--muted);
}
.docket-rows dd { margin: 0; font-weight: 600; }
.docket-note {
  font-size: 0.8rem; color: var(--muted); line-height: 1.45;
  border-top: 1px dashed var(--line); padding-top: 0.85rem;
}

/* Trust bar ---------------------------------------------------------------- */
.trust {
  background: var(--graphite-800); color: var(--sand);
  border-block: 1px solid rgba(250, 248, 245, 0.1);
}
.trust-list {
  display: grid; grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: 1px; margin: 0; padding: 0; list-style: none;
  background: rgba(250, 248, 245, 0.1);
}
@media (max-width: 900px) { .trust-list { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 420px) { .trust-list { grid-template-columns: 1fr; } }
.trust-list li {
  background: var(--graphite-800);
  display: flex; align-items: center; gap: 0.8rem;
  padding: 1.15rem clamp(0.9rem, 2vw, 1.5rem);
}
.trust-list svg { width: 26px; height: 26px; flex: none; color: var(--clay); }
.trust-list b { display: block; font-size: 0.98rem; font-weight: 700; line-height: 1.25; }
.trust-list span { display: block; font-size: 0.82rem; color: var(--graphite-300); line-height: 1.35; }

/* Badge shelf — real credentials go here once supplied. */
.badge-shelf {
  display: flex; flex-wrap: wrap; align-items: center; gap: 0.6rem;
  padding: 1rem 0 0; margin: 1.5rem 0 0; list-style: none;
  border-top: 1px solid rgba(250, 248, 245, 0.14);
}
.badge-shelf li {
  display: inline-flex; align-items: center; gap: 0.45rem;
  font-family: var(--mono); font-size: 0.72rem; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--graphite-300);
  border: 1px dashed rgba(250, 248, 245, 0.3);
  border-radius: 3px; padding: 0.42rem 0.8rem;
}
/* Dashed = still pending. Solid = confirmed and safe to publish. The visual
   difference is the point: it should be obvious at a glance which claims are
   backed by something. */
.badge-shelf li.is-confirmed {
  border-style: solid;
  border-color: rgba(87, 201, 63, 0.55);
  color: var(--sand);
}
.badge-shelf li.is-confirmed svg { width: 13px; height: 13px; color: var(--clay); flex: none; }

/* About -------------------------------------------------------------------- */
.split {
  display: grid; gap: clamp(2rem, 5vw, 4rem);
  grid-template-columns: minmax(0, 1.05fr) minmax(0, 0.95fr);
  align-items: center;
}
@media (max-width: 880px) { .split { grid-template-columns: 1fr; } }

.figure-plain { margin: 0; }
.figure-plain img { border-radius: var(--radius); width: 100%; height: auto; }
.figure-plain figcaption {
  font-family: var(--mono); font-size: 0.74rem; letter-spacing: 0.06em;
  color: var(--muted); margin-top: 0.7rem;
}

/* A hairline label that splits a long text block in two. Used sparingly — the
   point is to give the eye a rest, not to decorate. */
.mini-label {
  display: flex; align-items: center; gap: 0.8rem;
  font-family: var(--mono); font-size: 0.68rem; font-weight: 500;
  letter-spacing: 0.14em; text-transform: uppercase; color: var(--muted);
  margin: 1.9rem 0 1.1rem;
}
.mini-label::after {
  content: ''; flex: 1; height: 1px; background: var(--line);
}
.on-dark .mini-label { color: var(--graphite-300); }
.on-dark .mini-label::after { background: rgba(250, 248, 245, 0.18); }

.checklist { margin: 0 0 2rem; padding: 0; list-style: none; display: grid; gap: 0.9rem; }
/* Each line gets its own icon rather than a repeated bullet — four identical
   squares read as one grey block at a glance; four different marks give the
   eye something to land on per line. */
.checklist li {
  display: grid; grid-template-columns: 22px 1fr; gap: 0.75rem;
  align-items: start;
}
.checklist svg {
  width: 20px; height: 20px; color: var(--clay-deep);
  margin-top: 0.15em; flex: none;
}
.on-dark .checklist svg { color: var(--clay); }

/* A block the client fills with a real photo. Deliberately obvious. */
.photo-slot {
  border: 2px dashed var(--line);
  border-radius: var(--radius);
  background: var(--sand-2);
  aspect-ratio: 4 / 3;
  display: grid; place-content: center; gap: 0.5rem;
  padding: 1.5rem; text-align: center;
}
.on-dark .photo-slot { border-color: rgba(250, 248, 245, 0.28); background: var(--graphite-800); }
.photo-slot b {
  font-family: var(--mono); font-size: 0.72rem; font-weight: 500;
  letter-spacing: 0.12em; text-transform: uppercase; color: var(--clay-deep);
}
.on-dark .photo-slot b { color: var(--clay); }
.photo-slot span { font-size: 0.9rem; color: var(--muted); max-width: 34ch; }
.on-dark .photo-slot span { color: var(--graphite-300); }

/* Services ----------------------------------------------------------------- */
.services { display: grid; gap: clamp(1.5rem, 3vw, 2rem); }
.service {
  display: grid; gap: 0;
  grid-template-columns: minmax(0, 0.85fr) minmax(0, 1.15fr);
  background: var(--sand);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  overflow: hidden;
}
.service:nth-child(even) { grid-template-columns: minmax(0, 1.15fr) minmax(0, 0.85fr); }
.service:nth-child(even) .service-media { order: 2; }
@media (max-width: 820px) {
  .service, .service:nth-child(even) { grid-template-columns: 1fr; }
  .service:nth-child(even) .service-media { order: 0; }
}
.service-media { position: relative; min-height: 260px; }
.service-media img { width: 100%; height: 100%; object-fit: cover; }
.service-no {
  position: absolute; left: 0; top: 0;
  background: var(--graphite-900); color: var(--clay);
  font-family: var(--mono); font-size: 0.78rem; font-weight: 500;
  letter-spacing: 0.12em; padding: 0.45rem 0.85rem;
}
.service-body { padding: clamp(1.5rem, 3.5vw, 2.6rem); display: flex; flex-direction: column; }
.service-body h2 { font-size: var(--step-2); margin-bottom: 0.85rem; }
.service-body h2 .sep { color: var(--clay-deep); font-weight: 400; }
.service-body > p { color: var(--muted); margin-bottom: 1.15rem; max-width: 54ch; }
.service-for {
  font-size: 0.92rem; color: var(--ink);
  background: var(--sand-2); border-left: 3px solid var(--clay);
  padding: 0.75rem 1rem; border-radius: 0 var(--radius) var(--radius) 0;
  margin-bottom: 1.5rem;
}
/* Same label treatment as .local-note on the town pages, so the two page types
   read as one system. */
.service-for b {
  display: flex; align-items: center; gap: 0.5rem;
  font-family: var(--mono); font-size: 0.68rem; font-weight: 500;
  letter-spacing: 0.12em; text-transform: uppercase; color: var(--clay-deep);
  margin-bottom: 0.35rem;
}
.service-for b svg { width: 14px; height: 14px; flex: none; }
.service-actions { display: flex; flex-wrap: wrap; gap: 0.7rem; margin-top: auto; }

/* Areas -------------------------------------------------------------------- */
.board {
  background: var(--graphite-900); color: var(--sand);
  border-radius: var(--radius); padding: clamp(1.6rem, 4vw, 2.6rem);
}
.board h3 { color: var(--sand); margin-bottom: 1.1rem; }
.board-list {
  display: flex; flex-wrap: wrap; gap: 0.5rem;
  margin: 0 0 1.5rem; padding: 0; list-style: none;
}
.board-list li {
  font-family: var(--mono); font-size: 0.88rem;
  border: 1px solid rgba(250, 248, 245, 0.28);
  padding: 0.4rem 0.8rem; border-radius: 3px;
}
.board-list li.is-home { background: var(--clay); color: var(--graphite-900); border-color: var(--clay); font-weight: 500; }
.board-list li.is-home:has(a):hover { background: var(--clay-lift); border-color: var(--clay-lift); color: var(--graphite-900); }
.board p { color: var(--graphite-300); max-width: 62ch; }

/* How it works ------------------------------------------------------------- */
.steps { display: grid; gap: 1.25rem; grid-template-columns: repeat(4, minmax(0, 1fr)); }
@media (max-width: 940px) { .steps { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (max-width: 540px) { .steps { grid-template-columns: 1fr; } }
.step { border-top: 2px solid var(--clay); padding-top: 1.1rem; }
.step-no {
  font-family: var(--mono); font-size: 0.76rem; letter-spacing: 0.12em;
  text-transform: uppercase; color: var(--graphite-300); display: block; margin-bottom: 0.6rem;
}
.step h3 { margin-bottom: 0.5rem; }
.step p { color: var(--graphite-300); font-size: 0.96rem; }

/* Testimonials ------------------------------------------------------------- */
.quotes { display: grid; gap: 1.25rem; grid-template-columns: repeat(3, minmax(0, 1fr)); }
@media (max-width: 880px) { .quotes { grid-template-columns: 1fr; } }
.quote {
  border: 2px dashed var(--line); border-radius: var(--radius);
  background: var(--sand); padding: clamp(1.4rem, 3vw, 1.9rem);
  display: flex; flex-direction: column; gap: 0.9rem;
}
.quote-mark {
  font-family: var(--display); font-size: 2.6rem; font-weight: 800;
  line-height: 0.6; color: var(--line);
}
.quote p { color: var(--muted); font-style: italic; }
.quote footer {
  font-family: var(--mono); font-size: 0.74rem; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--clay-deep); margin-top: auto;
}

/* Form --------------------------------------------------------------------- */
.form-grid {
  display: grid; gap: clamp(2rem, 5vw, 4rem);
  grid-template-columns: minmax(0, 0.85fr) minmax(0, 1.15fr); align-items: start;
}
@media (max-width: 900px) { .form-grid { grid-template-columns: 1fr; } }

.form-card {
  background: var(--sand); color: var(--ink);
  border-radius: var(--radius); padding: clamp(1.4rem, 3.5vw, 2.2rem);
}
.field { display: grid; gap: 0.4rem; margin-bottom: 1rem; }
.field label { font-size: 0.88rem; font-weight: 600; }
.field .hint { font-size: 0.8rem; color: var(--muted); font-weight: 400; }
.field input, .field select, .field textarea {
  width: 100%; padding: 0.75rem 0.9rem;
  background: #fff; border: 1px solid var(--line); border-radius: var(--radius);
  font-size: 1rem;
}
.field input:focus, .field select:focus, .field textarea:focus { border-color: var(--graphite-600); }
.field textarea { resize: vertical; min-height: 92px; }
.field-row { display: grid; gap: 0 1rem; grid-template-columns: repeat(2, minmax(0, 1fr)); }
@media (max-width: 560px) { .field-row { grid-template-columns: 1fr; } }
.form-card .btn { width: 100%; margin-top: 0.4rem; }
.form-small { font-size: 0.82rem; color: var(--muted); margin-top: 0.9rem; text-align: center; }
.hp { position: absolute; left: -9999px; }

/* Contact-method picker: all three channels, pick any. */
.choice-set { border: 0; padding: 0; margin: 0 0 1.15rem; }
.choice-set legend { font-size: 0.88rem; font-weight: 600; padding: 0; margin-bottom: 0.5rem; }
.choices { display: flex; flex-wrap: wrap; gap: 0.5rem; }
.choice {
  display: inline-flex; align-items: center; gap: 0.5rem;
  border: 1px solid var(--line); background: #fff;
  border-radius: 999px; padding: 0.5rem 0.95rem;
  font-size: 0.92rem; cursor: pointer;
}
.choice input { width: 1rem; height: 1rem; margin: 0; accent-color: var(--clay-deep); }
.choice:hover { border-color: var(--graphite-600); }
.choice:has(input:checked) { border-color: var(--clay-deep); background: #fbeee7; font-weight: 600; }

.assurances { margin: 1.75rem 0 0; padding: 0; list-style: none; display: grid; gap: 0.9rem; }
.assurances li { padding-left: 1.9rem; position: relative; color: var(--graphite-300); }
.assurances strong { color: var(--sand); display: block; font-weight: 600; }
.assurances li::before {
  content: ''; position: absolute; left: 0; top: 0.35em;
  width: 11px; height: 11px; background: var(--clay); border-radius: 1px;
}

/* Location pages ----------------------------------------------------------- */
/* Shares every token, component and breakpoint above. Nothing here forks the
   design — it only adds the three shapes the town pages need that the homepage
   does not: the hero facts card, the service summary cards, and the area links. */

/* Hero side card: the same frame as the quote docket, carrying local facts
   instead of a sample quote. */
.local-card { max-width: 400px; margin-inline: auto; width: 100%; }
.local-facts { margin: 0; display: grid; gap: 0.7rem; }
.local-facts div {
  display: grid; grid-template-columns: 104px 1fr; gap: 0.75rem;
  align-items: baseline; font-size: 0.93rem;
}
.local-facts dt {
  font-family: var(--mono); font-size: 0.68rem; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--muted);
}
.local-facts dd { margin: 0; font-weight: 600; }
.local-facts dd .mono { font-family: var(--mono); font-weight: 500; }
/* On a narrow phone a 104px label column leaves too little for the value —
   "Adeyfield, Grovehill, Boxmoor…" ends up one word per line. Stack instead. */
@media (max-width: 400px) {
  .local-facts div { grid-template-columns: 1fr; gap: 0.15rem; }
}

/* A practical, town-specific note — narrow streets, permit bays, lift access.
   This is the part of each page that has to be genuinely different. */
.local-note {
  border-left: 3px solid var(--clay);
  background: var(--sand-2);
  border-radius: 0 var(--radius) var(--radius) 0;
  padding: 1.1rem 1.3rem;
  margin-top: 1.75rem;
  max-width: 62ch;
}
.local-note b {
  display: flex; align-items: center; gap: 0.5rem;
  font-family: var(--mono); font-size: 0.68rem; font-weight: 500;
  letter-spacing: 0.12em; text-transform: uppercase; color: var(--clay-deep);
  margin-bottom: 0.4rem;
}
.local-note b svg { width: 14px; height: 14px; flex: none; }
.local-note p { color: var(--muted); font-size: 0.96rem; }

/* Service summaries. Deliberately lighter than the homepage .service blocks —
   these are pointers back to the full copy, not a second copy of it. */
.svc-cards { display: grid; gap: 1.25rem; grid-template-columns: repeat(3, minmax(0, 1fr)); }
@media (max-width: 900px) { .svc-cards { grid-template-columns: 1fr; } }
.svc-card {
  background: var(--sand); border: 1px solid var(--line);
  border-radius: var(--radius); padding: clamp(1.3rem, 3vw, 1.8rem);
  display: flex; flex-direction: column; gap: 0.8rem;
}
.svc-card-icon {
  width: 34px; height: 34px; color: var(--clay-deep);
  border: 1px solid var(--line); border-radius: var(--radius);
  padding: 0.3rem; background: var(--sand-2);
}
.svc-card h2 { font-size: var(--step-1); }
.svc-card p { color: var(--muted); font-size: 0.96rem; }
.svc-card a {
  margin-top: auto; font-weight: 600; font-size: 0.94rem;
  color: var(--clay-deep); text-decoration: none;
  display: inline-flex; align-items: center; gap: 0.4rem;
}
.svc-card a:hover { text-decoration: underline; text-underline-offset: 3px; }
.svc-card a span { transition: transform 0.15s ease; }
.svc-card a:hover span { transform: translateX(3px); }

/* Area chips become links on the town pages and on the homepage. */
.board-list a {
  text-decoration: none; display: block;
  margin: -0.4rem -0.8rem; padding: 0.4rem 0.8rem;
}
.board-list li:has(a):hover { border-color: var(--clay); color: var(--clay); }
.board-list li.is-current { background: var(--sand); color: var(--graphite-900); border-color: var(--sand); font-weight: 600; }

/* Blog + long-form guides --------------------------------------------------- */
/* A guide is far more text than a location page, so it gets a reading column, a
   contents list and a checklist treatment that turns prose into something you
   can work down. Same tokens as everything else — no new palette, no new type. */

.article-layout {
  display: grid; gap: clamp(2rem, 4vw, 3.5rem);
  grid-template-columns: 230px minmax(0, 1fr);
  align-items: start;
}
@media (max-width: 1040px) { .article-layout { grid-template-columns: 1fr; } }

.article { max-width: 68ch; }
.article > p { color: var(--muted); margin-bottom: 1.1rem; }
.article > p strong { color: var(--ink); font-weight: 600; }
.article a { color: var(--clay-deep); text-underline-offset: 3px; }

/* Contents. Sticky beside the article on a wide screen, a plain card above it
   on anything narrower — one piece of markup, placed differently. */
.toc { font-size: 0.94rem; }
@media (min-width: 1041px) {
  .toc { position: sticky; top: calc(var(--header-h) + 1.5rem); }
}
@media (max-width: 1040px) {
  .toc {
    border: 1px solid var(--line); border-radius: var(--radius);
    background: var(--sand); padding: 1.2rem 1.4rem;
  }
}
.toc h2 {
  font-family: var(--mono); font-size: 0.7rem; font-weight: 500;
  letter-spacing: 0.14em; text-transform: uppercase; color: var(--muted);
  margin-bottom: 0.9rem;
}
.toc ol { list-style: none; margin: 0; padding: 0; counter-reset: toc; }
.toc li { counter-increment: toc; }
.toc a {
  display: grid; grid-template-columns: 1.9rem 1fr; gap: 0.3rem;
  padding: 0.42rem 0; text-decoration: none; color: var(--muted);
  border-bottom: 1px solid var(--line);
}
.toc a::before {
  content: counter(toc, decimal-leading-zero);
  font-family: var(--mono); font-size: 0.76rem; color: var(--clay-deep);
}
.toc a:hover { color: var(--ink); }

/* One block per time period. The number comes from a counter so it cannot
   drift out of step with the headings if a stage is added or moved. */
.stages { counter-reset: stage; }
.stage {
  counter-increment: stage;
  padding-top: clamp(2rem, 4vw, 2.75rem);
  margin-top: clamp(2rem, 4vw, 2.75rem);
  border-top: 1px solid var(--line);
}
.stage:first-child { border-top: 0; margin-top: 0; padding-top: 0; }
.stage h2 {
  font-size: var(--step-2);
  display: grid; grid-template-columns: auto 1fr; gap: 0.85rem; align-items: center;
  margin-bottom: 0.9rem;
}
.stage h2::before {
  content: counter(stage, decimal-leading-zero);
  font-family: var(--mono); font-size: 0.8rem; font-weight: 500;
  letter-spacing: 0.06em; color: var(--clay-deep);
  background: var(--sand-2); border: 1px solid var(--line);
  border-radius: var(--radius); padding: 0.32rem 0.55rem;
  line-height: 1;
}
.stage > p { color: var(--muted); margin-bottom: 1.25rem; max-width: 66ch; }

/* Tickable checklist. Real checkboxes, so keyboard and screen-reader behaviour
   comes for free; js/checklist.js only layers persistence on top. */
.task-list { list-style: none; margin: 0 0 1rem; padding: 0; }
.task-list li {
  display: grid; grid-template-columns: auto 1fr; gap: 0.8rem;
  align-items: start; border-bottom: 1px solid var(--line);
}
.task-list li:first-child { border-top: 1px solid var(--line); }
.task-list input[type='checkbox'] {
  width: 1.05rem; height: 1.05rem; margin: 0.95rem 0 0;
  accent-color: var(--clay-deep); cursor: pointer;
}
/* The whole label row is the real tap target, but people aim at the box, and
   17px is fiddly with a thumb. */
@media (max-width: 640px) {
  .task-list input[type='checkbox'] { width: 1.3rem; height: 1.3rem; margin-top: 0.85rem; }
}
.task-list label { padding: 0.75rem 0; cursor: pointer; }
.task-list label em {
  display: block; font-style: normal; font-size: 0.88rem;
  color: var(--muted); margin-top: 0.15rem;
}
.task-list li:has(input:checked) label { color: var(--muted); }
.task-list li:has(input:checked) label > span { text-decoration: line-through; }

/* Progress readout. Hidden until the script fills it in, so it never shows a
   wrong count with JavaScript off. */
.task-progress {
  display: none; align-items: center; justify-content: space-between;
  gap: 1rem; flex-wrap: wrap;
  font-family: var(--mono); font-size: 0.76rem; letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--muted);
  border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--sand-2); padding: 0.7rem 1rem; margin-bottom: 1.6rem;
}
.task-progress[data-ready='true'] { display: flex; }
.task-progress b { color: var(--clay-deep); font-weight: 500; }
.task-progress button {
  background: none; border: 0; padding: 0; cursor: pointer;
  font-family: var(--mono); font-size: 0.76rem; letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--muted); text-decoration: underline;
  text-underline-offset: 3px;
}
.task-progress button:hover { color: var(--ink); }

/* Pull-out for the thing people most often get wrong at that stage. */
.callout {
  border-left: 3px solid var(--clay);
  background: var(--sand-2);
  border-radius: 0 var(--radius) var(--radius) 0;
  padding: 1.1rem 1.3rem; margin: 1.6rem 0;
}
.callout b {
  display: flex; align-items: center; gap: 0.5rem;
  font-family: var(--mono); font-size: 0.68rem; font-weight: 500;
  letter-spacing: 0.12em; text-transform: uppercase; color: var(--clay-deep);
  margin-bottom: 0.4rem;
}
.callout b svg { width: 14px; height: 14px; flex: none; }
.callout p { color: var(--muted); font-size: 0.96rem; }
.callout p + p { margin-top: 0.6rem; }

.article-meta {
  display: flex; flex-wrap: wrap; gap: 0.4rem 1.1rem;
  font-family: var(--mono); font-size: 0.76rem; letter-spacing: 0.04em;
  color: var(--graphite-300); margin-top: 1.3rem;
}
.article-meta span { display: inline-flex; align-items: center; gap: 0.4rem; }
.article-meta svg { width: 14px; height: 14px; }

/* Closing CTA on a guide — quieter than the homepage form section. */
.article-cta {
  border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--sand-2); padding: clamp(1.5rem, 3vw, 2.1rem);
  margin-top: clamp(2.5rem, 5vw, 3.5rem);
}
.article-cta h2 { font-size: var(--step-1); margin-bottom: 0.6rem; }
.article-cta p { color: var(--muted); margin-bottom: 1.3rem; max-width: 60ch; }
.article-cta .hero-actions { margin-bottom: 0; }

/* Blog index --------------------------------------------------------------- */
.post-cards { display: grid; gap: 1.25rem; grid-template-columns: repeat(2, minmax(0, 1fr)); }
@media (max-width: 820px) { .post-cards { grid-template-columns: 1fr; } }
.post-card {
  border: 1px solid var(--line); border-radius: var(--radius);
  background: var(--sand); padding: clamp(1.4rem, 3vw, 1.9rem);
  display: flex; flex-direction: column; gap: 0.75rem;
}
.post-card h2 { font-size: var(--step-1); }
.post-card h2 a { text-decoration: none; }
.post-card h2 a:hover { color: var(--clay-deep); }
.post-card p { color: var(--muted); font-size: 0.96rem; }
.post-card-meta {
  display: flex; flex-wrap: wrap; gap: 0.35rem 0.9rem;
  font-family: var(--mono); font-size: 0.72rem; letter-spacing: 0.06em;
  text-transform: uppercase; color: var(--muted);
}
.post-card-more {
  margin-top: auto; font-weight: 600; font-size: 0.94rem;
  color: var(--clay-deep); text-decoration: none;
  display: inline-flex; align-items: center; gap: 0.4rem;
}
.post-card-more:hover { text-decoration: underline; text-underline-offset: 3px; }
.post-card-more span { transition: transform 0.15s ease; }
.post-card-more:hover span { transform: translateX(3px); }

/* Says what is coming next, rather than padding the grid with filler cards. */
.post-card-empty {
  border-style: dashed; background: var(--sand-2);
  justify-content: center; gap: 0.5rem;
}
.post-card-empty b {
  font-family: var(--mono); font-size: 0.72rem; font-weight: 500;
  letter-spacing: 0.12em; text-transform: uppercase; color: var(--clay-deep);
}

/* Breadcrumb --------------------------------------------------------------- */
.breadcrumb {
  font-family: var(--mono); font-size: 0.74rem; letter-spacing: 0.06em;
  margin-bottom: 1.1rem;
}
.breadcrumb ol { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: 0.5rem; }
.breadcrumb li:not(:last-child)::after { content: '/'; margin-left: 0.5rem; opacity: 0.5; }
.breadcrumb a { color: var(--graphite-300); text-decoration: none; }
.breadcrumb a:hover { color: var(--clay); }
.breadcrumb [aria-current] { color: var(--sand); }

/* Print. A moving checklist is something people actually print. */
@media print {
  .site-header, .callbar, .toc, .article-cta, .site-footer,
  .hero-media, .skip-link, .task-progress, .breadcrumb { display: none !important; }
  body { background: #fff; color: #000; padding-bottom: 0; }
  .hero, .section, .section-dark, .section-sunk {
    background: #fff !important; color: #000 !important; padding-block: 0.5rem;
  }
  .hero::after { display: none; }
  .hero h1, .on-dark h1, .on-dark h2, .on-dark p, .on-dark .lede { color: #000 !important; }
  .article-layout { grid-template-columns: 1fr; }
  .article { max-width: none; }
  .stage, .task-list li, .callout { break-inside: avoid; }
  a[href^='http']::after { content: ' (' attr(href) ')'; font-size: 0.8em; color: #555; }
  a[href^='#']::after, a[href^='/']::after { content: ''; }
}

/* Prose pages -------------------------------------------------------------- */
.prose { max-width: 68ch; }
.prose h2 { font-size: var(--step-2); margin: 2.5rem 0 0.9rem; }
.prose h3 { margin: 1.75rem 0 0.6rem; }
.prose p, .prose li { color: var(--muted); }
.prose p { margin-bottom: 1rem; }
.prose ul { padding-left: 1.2rem; margin-bottom: 1rem; display: grid; gap: 0.4rem; }
.prose a { color: var(--clay-deep); text-underline-offset: 3px; }

.page-head { background: var(--graphite-900); color: var(--sand); padding-block: clamp(2.75rem, 6vw, 4.5rem); }
.page-head p { color: var(--graphite-300); }

/* Footer ------------------------------------------------------------------- */
.site-footer { background: var(--graphite-900); color: var(--graphite-300); padding-block: clamp(2.5rem, 5vw, 4rem) 2rem; }
.footer-grid {
  display: grid; gap: 2rem;
  grid-template-columns: minmax(0, 1.4fr) repeat(3, minmax(0, 1fr));
  padding-bottom: 2.25rem; border-bottom: 1px solid rgba(250, 248, 245, 0.14);
}
/* Four columns need real room — the email address is long enough to collide
   with the next column before this. */
@media (max-width: 1060px) { .footer-grid { grid-template-columns: 1fr 1fr; } .footer-brand { grid-column: 1 / -1; } }
@media (max-width: 520px) { .footer-grid { grid-template-columns: 1fr; } }
.footer-logo { width: 132px; height: auto; margin-bottom: 1rem; }
.footer-brand p { max-width: 42ch; font-size: 0.94rem; }
/* Footer column labels are h2, not h4 — an h4 here follows the page's last h2
   and skips two levels, which breaks heading navigation for screen readers. */
.site-footer h2 {
  font-family: var(--mono); font-size: 0.74rem; font-weight: 500;
  letter-spacing: 0.12em; text-transform: uppercase; color: var(--sand);
  line-height: 1.4; margin: 0 0 0.9rem;
}
.footer-list { margin: 0; padding: 0; list-style: none; display: grid; gap: 0.55rem; font-size: 0.94rem; }
.footer-list li { overflow-wrap: anywhere; }
.footer-list a { text-decoration: none; }
.footer-list a:hover { color: var(--clay); }
.footer-list .mono { font-family: var(--mono); }
.footer-legal {
  padding-top: 1.5rem; display: flex; flex-wrap: wrap; gap: 0.5rem 1.5rem;
  justify-content: space-between; font-size: 0.84rem;
}
.footer-legal p { margin: 0; }
.footer-legal .co-no { font-family: var(--mono); }

/* Mobile sticky call bar --------------------------------------------------- */
.callbar {
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 120;
  display: none;
  grid-template-columns: repeat(3, 1fr);
  gap: 1px;
  background: rgba(250, 248, 245, 0.15);
  border-top: 1px solid rgba(250, 248, 245, 0.15);
  padding-bottom: env(safe-area-inset-bottom);
}
.callbar a {
  display: flex; align-items: center; justify-content: center; gap: 0.45rem;
  height: var(--callbar-h);
  background: var(--graphite-900); color: var(--sand);
  text-decoration: none; font-size: 0.9rem; font-weight: 700;
}
.callbar a svg { width: 18px; height: 18px; }
.callbar .cb-call { background: var(--clay); color: var(--graphite-900); }
.callbar .cb-mail { background: var(--graphite-700); color: #fff; }

/* Must match the nav breakpoint above. */
@media (max-width: 1000px) {
  .callbar { display: grid; }
  body { padding-bottom: calc(var(--callbar-h) + env(safe-area-inset-bottom)); }
}

/* Motion ------------------------------------------------------------------- */
.reveal { opacity: 0; transform: translateY(18px); }
.reveal-in { opacity: 1; transform: none; transition: opacity 0.6s ease, transform 0.6s cubic-bezier(0.2, 0.7, 0.3, 1); }

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
  .reveal { opacity: 1; transform: none; }
}

/* ==========================================================================
   PaveLocal additions
   Components the PrimeGuard stylesheet did not have. Everything above this
   line is inherited from that build with the palette and type swapped.
   ========================================================================== */

.wrap-narrow { width: min(100% - (var(--gutter) * 2), var(--wrap-narrow)); margin-inline: auto; }
.section-tight { padding-block: clamp(2.2rem, 5vw, 3.4rem); }
.btn-block { width: 100%; justify-content: center; }

/* The current town in an areas list. PrimeGuard's markup emitted .is-current
   while its stylesheet only defined .is-home, so the chip never highlighted.
   Both are defined here. */
.board-list li.is-current {
  background: var(--clay); color: var(--graphite-900);
  border-color: var(--clay); font-weight: 600;
}
.board-nearby {
  margin-top: 1.4rem; padding-top: 1.2rem;
  border-top: 1px solid rgba(250, 248, 245, 0.16);
  font-size: 0.94rem;
}
.board-nearby b {
  display: flex; align-items: center; gap: 0.5rem;
  font-family: var(--mono); font-size: 0.68rem; font-weight: 500;
  letter-spacing: 0.12em; text-transform: uppercase; color: var(--clay);
  margin-bottom: 0.45rem;
}
.board-nearby b svg { width: 14px; height: 14px; flex: none; }

/* NAP ---------------------------------------------------------------------- */
/* Name, address, phone. Identical on all pages because it is rendered once in
   tools/chrome.mjs. Pending lines are visibly pending rather than blank — an
   empty address block reads as broken, a labelled one reads as honest. */
.nap {
  margin-top: 1.3rem; padding-top: 1.2rem;
  border-top: 1px solid rgba(250, 248, 245, 0.14);
  font-size: 0.9rem; line-height: 1.55;
}
.nap-name {
  font-family: var(--mono); font-size: 0.72rem; font-weight: 500;
  letter-spacing: 0.14em; text-transform: uppercase;
  color: var(--clay); margin-bottom: 0.55rem;
}
.nap-line { color: var(--graphite-300); }
.nap-line + .nap-line { margin-top: 0.35rem; }
.nap-line a { text-decoration: none; border-bottom: 1px solid rgba(250, 248, 245, 0.28); }
.nap-line a:hover { color: var(--clay); border-bottom-color: var(--clay); }
.nap-pending {
  font-style: italic;
  color: #8f8b85;   /* 4.6:1 on --graphite-900 — quieter than live detail, still legible */
}

.footer-areas { columns: 2; column-gap: 1.2rem; }
.footer-nearby {
  margin-top: 0.9rem; font-size: 0.82rem; line-height: 1.5;
  color: #8f8b85;
}

.quote-alt { margin-top: 1.4rem; color: var(--graphite-300); font-size: 0.95rem; }
.quote-alt a { color: var(--clay); text-underline-offset: 3px; }

.step-when {
  margin-top: 0.7rem; font-family: var(--mono); font-size: 0.76rem;
  letter-spacing: 0.02em; color: var(--clay-deep);
}
.on-dark .step-when { color: var(--clay); }

/* FAQ ---------------------------------------------------------------------- */
/* Plain <details>. No script, so it works with JS blocked and the answers are
   in the DOM for crawlers either way. */
.faq { border-top: 1px solid var(--line); }
.faq-item { border-bottom: 1px solid var(--line); }
.faq-item summary {
  cursor: pointer; list-style: none; padding: 1.1rem 2.4rem 1.1rem 0;
  position: relative; font-weight: 600; font-size: 1.02rem;
}
.faq-item summary::-webkit-details-marker { display: none; }
.faq-item summary::after {
  content: ''; position: absolute; right: 0.4rem; top: 1.45rem;
  width: 11px; height: 11px; border-right: 2px solid var(--clay-deep);
  border-bottom: 2px solid var(--clay-deep); transform: rotate(45deg);
  transition: transform 0.18s ease;
}
.faq-item[open] summary::after { transform: rotate(-135deg); top: 1.7rem; }
.faq-item summary:hover { color: var(--clay-deep); }
.faq-body { padding: 0 0 1.3rem; }
.faq-body p { color: var(--muted); max-width: 68ch; }

/* Related links ------------------------------------------------------------ */
.related-head { font-size: var(--step-1); margin-bottom: 1.1rem; }
.related-list {
  display: grid; gap: 0.7rem; padding: 0; margin: 0; list-style: none;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
}
.related-list a {
  display: block; height: 100%; text-decoration: none;
  border: 1px solid var(--line); border-left: 3px solid var(--clay);
  background: var(--sand); border-radius: 0 var(--radius) var(--radius) 0;
  padding: 0.9rem 1.1rem; transition: border-color 0.15s ease, background 0.15s ease;
}
.related-list a:hover { background: var(--sand-2); border-left-color: var(--clay-deep); }
.related-list b { display: block; font-size: 0.98rem; }
.related-list span { display: block; margin-top: 0.25rem; font-size: 0.86rem; color: var(--muted); }

/* Attribution -------------------------------------------------------------- */
.attribution {
  margin-top: 2.4rem; padding: 1.3rem 1.5rem;
  background: var(--sand-2); border-radius: var(--radius);
  border-left: 3px solid var(--clay);
}
.attribution p { font-size: 0.93rem; color: var(--muted); max-width: 72ch; }
.attribution b { color: var(--ink); }
.attribution-meta { margin-top: 0.6rem; }
.attribution-meta .mono { font-size: 0.76rem; letter-spacing: 0.04em; }

/* Photo slot frame --------------------------------------------------------- */
.photo-slot { margin: 1.8rem 0; }
.photo-slot-frame {
  border: 2px dashed var(--line); border-radius: var(--radius);
  background: var(--sand-2); aspect-ratio: 4 / 3;
  display: grid; place-content: center; padding: 1.5rem;
}
.photo-slot-frame span {
  font-family: var(--mono); font-size: 0.72rem; font-weight: 500;
  letter-spacing: 0.12em; text-transform: uppercase; color: var(--clay-deep);
}
.photo-slot figcaption {
  margin-top: 0.6rem; font-size: 0.86rem; color: var(--muted); text-align: center;
}


/* Shorter hero for the non-location content pages — no video, less height,
   so the reader reaches the actual content sooner. */
.hero-compact { min-height: 0; padding-block: clamp(3rem, 8vw, 5.5rem); }
.hero-compact .docket-top span:last-child { text-transform: capitalize; }

/* Standard body paragraph inside a section. The location and service builders
   emit these for every prose paragraph after the lede. */
.body-p { max-width: 68ch; color: var(--muted); margin-top: 1.1rem; }
.body-p + .body-p { margin-top: 0.9rem; }
.wrap-narrow > h2 { margin-bottom: 0.4rem; }
.wrap-narrow > h2 + .body-p { margin-top: 0.9rem; }

/* Type cards — the six driveway surfaces ----------------------------------- */
.type-cards {
  display: grid; gap: 1.1rem;
  grid-template-columns: repeat(auto-fit, minmax(270px, 1fr));
}
.type-card {
  background: var(--sand); border: 1px solid var(--line);
  border-radius: var(--radius); padding: 1.4rem 1.5rem;
  display: flex; flex-direction: column; gap: 0.6rem;
}
.section-sunk .type-card { background: #fff; }
.type-card h3 { font-size: var(--step-1); }
.type-card > p { color: var(--muted); font-size: 0.95rem; }
.type-card dl {
  display: grid; grid-template-columns: auto 1fr; gap: 0.3rem 0.9rem;
  margin: 0.3rem 0 0; font-size: 0.86rem;
}
.type-card dt {
  font-family: var(--mono); font-size: 0.7rem; letter-spacing: 0.1em;
  text-transform: uppercase; color: var(--muted); padding-top: 0.15rem;
}
.type-card dd { margin: 0; font-weight: 500; }
.type-card .type-more {
  margin-top: auto; padding-top: 0.9rem; font-weight: 600;
  color: var(--clay-deep); text-decoration: none; font-size: 0.94rem;
}
.type-card .type-more:hover { text-decoration: underline; text-underline-offset: 3px; }

/* Spec list — what is actually under the surface --------------------------- */
.spec-list { display: grid; gap: 0; margin: 1.6rem 0 0; padding: 0; list-style: none; }
.spec-list li {
  display: grid; grid-template-columns: minmax(140px, 200px) 1fr;
  gap: 0.4rem 1.4rem; padding: 0.9rem 0; border-top: 1px solid var(--line);
}
.spec-list li:last-child { border-bottom: 1px solid var(--line); }
@media (max-width: 620px) { .spec-list li { grid-template-columns: 1fr; } }
.spec-list b {
  font-family: var(--mono); font-size: 0.76rem; font-weight: 500;
  letter-spacing: 0.08em; text-transform: uppercase; color: var(--clay-deep);
}
.spec-list p { color: var(--muted); font-size: 0.95rem; }

/* Data tables — costs, comparisons ----------------------------------------- */
.table-scroll { overflow-x: auto; margin: 1.6rem 0; -webkit-overflow-scrolling: touch; }
.data-table { width: 100%; min-width: 540px; border-collapse: collapse; font-size: 0.94rem; }
.data-table caption {
  text-align: left; font-size: 0.86rem; color: var(--muted); padding-bottom: 0.7rem;
}
.data-table th, .data-table td {
  text-align: left; padding: 0.75rem 0.9rem; border-bottom: 1px solid var(--line);
  vertical-align: top;
}
.data-table thead th {
  font-family: var(--mono); font-size: 0.72rem; font-weight: 500;
  letter-spacing: 0.1em; text-transform: uppercase; color: var(--ink);
  border-bottom: 2px solid var(--graphite-900);
}
.data-table tbody th { font-weight: 600; }
.data-table tbody tr:nth-child(even) { background: var(--sand-2); }
.section-sunk .data-table tbody tr:nth-child(even) { background: #fff; }
.data-table .num { font-family: var(--mono); white-space: nowrap; }

/* Gallery ------------------------------------------------------------------ */
.gallery-grid {
  display: grid; gap: 1rem;
  grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
}
.gallery-grid .photo-slot { margin: 0; }

/* Area map — the plain-text alternative to an embedded map iframe ----------- */
/* A Google Maps embed costs a few hundred KB and a consent prompt on a page
   whose whole job is to load fast on a phone. A postcode-district list carries
   the same information for a reader and more of it for a crawler. */
.area-map {
  display: grid; gap: 1.4rem;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  margin-top: 1.6rem;
}
.area-map > div { border-top: 2px solid var(--clay); padding-top: 0.9rem; }
.area-map h3 { font-size: 1.05rem; margin-bottom: 0.5rem; }
.area-map p { font-size: 0.92rem; color: var(--muted); }
.area-map .mono { font-size: 0.84rem; letter-spacing: 0.02em; }

/* Pending / honesty notice ------------------------------------------------- */
/* Used where a section is deliberately empty. Visibly a placeholder, so it can
   never be mistaken for finished content in a screenshot or a review. */
.pending-note {
  border: 2px dashed var(--line); border-radius: var(--radius);
  background: var(--sand-2); padding: 1.4rem 1.6rem; margin: 1.6rem 0;
}
.pending-note b {
  display: block; font-family: var(--mono); font-size: 0.7rem; font-weight: 500;
  letter-spacing: 0.12em; text-transform: uppercase; color: var(--clay-deep);
  margin-bottom: 0.5rem;
}
.pending-note p { color: var(--muted); font-size: 0.95rem; max-width: 68ch; }
.pending-note p + p { margin-top: 0.6rem; }

/* Accessibility fixes ------------------------------------------------------ */
/* Both of these were measured in the browser at 375px rather than assumed, and
   both are inherited from the reference stylesheet. */

/* WCAG 2.5.5 / Apple HIG want a 44px minimum touch target. The header CTA was
   landing at 41px because .nav .btn overrides the base padding — measured, not
   estimated. min-height fixes it without disturbing the desktop proportions,
   which are set by padding rather than height. */
.btn { min-height: 44px; }
.nav-toggle { min-width: 44px; min-height: 44px; }
.callbar a { min-height: 48px; }

/* The mobile nav drawer is hidden by translating it off-screen, which leaves its
   links visible to the accessibility tree and reachable by Tab — so keyboard
   focus can land on a control nobody can see. visibility:hidden removes them
   from the tab order while the transform still animates, because visibility is
   a transitionable property and the delay lets the slide finish before the
   drawer is hidden. */
@media (max-width: 1000px) {
  .nav {
    visibility: hidden;
    transition: transform 0.28s cubic-bezier(0.4, 0, 0.2, 1),
                visibility 0s linear 0.28s;
  }
  .nav[data-open='true'] {
    visibility: visible;
    transition: transform 0.28s cubic-bezier(0.4, 0, 0.2, 1),
                visibility 0s linear 0s;
  }
}

/* ==========================================================================
   Media
   Every image here is licensed stock used illustratively — a surface, a
   material or a stage of work. None of it is presented as a PaveLocal project.
   Attribution is on /credits.
   ========================================================================== */

/* Hero background image. Sits in the same slot as .hero-media so the existing
   scrim does the legibility work for both photo and video heroes. */
.hero-photo { position: absolute; inset: 0; z-index: -2; }
.hero-photo img,
.hero-photo picture { width: 100%; height: 100%; object-fit: cover; display: block; }

/* A hero carrying media needs a heavier scrim than a flat one — the text sits
   directly over photography and has to clear 4.5:1 against the lightest part of
   it, not the average. */
.hero.has-media::after {
  background:
    linear-gradient(100deg,
      rgba(23, 25, 29, 0.97) 0%,
      rgba(23, 25, 29, 0.93) 44%,
      rgba(23, 25, 29, 0.74) 72%,
      rgba(23, 25, 29, 0.55) 100%),
    linear-gradient(to top, rgba(23, 25, 29, 0.92) 0%, rgba(23, 25, 29, 0) 48%);
}
@media (max-width: 860px) {
  .hero.has-media::after {
    background: linear-gradient(180deg,
      rgba(23, 25, 29, 0.95) 0%, rgba(23, 25, 29, 0.92) 55%, rgba(23, 25, 29, 0.97) 100%);
  }
}

/* Full-width media band between sections. */
.media-band {
  position: relative;
  margin: 0;
  overflow: hidden;
  background: var(--graphite-900);
}
.media-band picture, .media-band img, .media-band video {
  display: block; width: 100%;
  height: clamp(220px, 34vw, 420px);
  object-fit: cover;
}
.media-band figcaption {
  position: absolute; left: 0; right: 0; bottom: 0;
  padding: 2.2rem var(--gutter) 1.1rem;
  background: linear-gradient(to top, rgba(23, 25, 29, 0.92), rgba(23, 25, 29, 0));
  color: var(--sand); font-size: 0.9rem;
}
.media-band figcaption b {
  display: block; font-family: var(--mono); font-size: 0.68rem; font-weight: 500;
  letter-spacing: 0.12em; text-transform: uppercase; color: var(--clay);
  margin-bottom: 0.3rem;
}
.media-band figcaption span { color: var(--graphite-300); }

/* Image inside a prose column — blog lead images, section illustrations. */
.figure-inline { margin: 1.8rem 0; }
.figure-inline picture, .figure-inline img {
  display: block; width: 100%; border-radius: var(--radius);
}
.figure-inline figcaption {
  margin-top: 0.6rem; font-size: 0.85rem; color: var(--muted); line-height: 1.5;
}

/* Type cards on the homepage get a surface photo above the heading. */
.type-card-media {
  margin: -1.4rem -1.5rem 0.9rem;
  border-radius: var(--radius) var(--radius) 0 0;
  overflow: hidden;
}
.type-card-media picture, .type-card-media img {
  display: block; width: 100%; height: 168px; object-fit: cover;
}

/* Gallery. Real images, labelled as surface and process examples. */
.gallery-item {
  margin: 0; background: var(--sand); border: 1px solid var(--line);
  border-radius: var(--radius); overflow: hidden;
}
.section-sunk .gallery-item { background: #fff; }
.gallery-item picture, .gallery-item img {
  display: block; width: 100%; height: 200px; object-fit: cover;
}
.gallery-item figcaption { padding: 1rem 1.15rem 1.2rem; }
.gallery-item figcaption b { display: block; font-size: 0.98rem; margin-bottom: 0.3rem; }
.gallery-item figcaption span { font-size: 0.88rem; color: var(--muted); line-height: 1.5; }

/* Credits table. */
.credits-list { display: grid; gap: 0; margin: 1.6rem 0 0; padding: 0; list-style: none; }
.credits-list li {
  display: grid; grid-template-columns: 96px 1fr; gap: 1rem;
  padding: 0.85rem 0; border-top: 1px solid var(--line); align-items: center;
}
.credits-list li:last-child { border-bottom: 1px solid var(--line); }
.credits-list img { width: 96px; height: 64px; object-fit: cover; border-radius: 3px; display: block; }
.credits-list p { font-size: 0.92rem; }
.credits-list .credit-alt { color: var(--muted); font-size: 0.86rem; margin-top: 0.2rem; }
.credits-list a { color: var(--clay-deep); text-underline-offset: 3px; }

/* Reduced motion: a decorative loop is exactly what this setting is for. */
@media (prefers-reduced-motion: reduce) {
  .hero-media, .media-band video { display: none; }
}

/* Credits whose source could not be verified. Visibly pending rather than
   silently blank, same rule as the pending NAP lines. */
.credit-pending { font-style: italic; color: #6b645c; }
.credit-pending .mono { font-style: normal; font-size: 0.8rem; }
