/* SG Refurbishments — design system ("works folio")
   White ground, SG-blue drawing boards. Two-tone: white + blue, nothing else.
   Squared corners throughout: this is a building firm, not a startup.

   THE PALETTE IS FIXED — white + blue per Kaj/Gary, 17 Jul. --navy is
   sampled from the SG logo (holding/sg-logo.png, solid-glyph average
   #323271). No gold, no cream, no warm hue anywhere — build.py gates it.

   Contrast rule: --sky (periwinkle) is the pop on blue boards only — rules,
   ticks, large display type and letterspaced caps (passes AA on navy-deep);
   on white grounds the accent is the brand blue itself. */

:root {
  /* ground + ink */
  --white: #FFFFFF;
  --paper: #F4F7FB;
  --ink: #17182A;
  --ink-soft: #555A75;

  /* the SG blue — sampled from the logo */
  --navy: #323271;
  --navy-deep: #212150;
  --navy-tint: #ECEFF7;

  /* line + accents (accent on white = brand blue; sky = the lift on navy) */
  --line: #DEE3EC;
  --accent: #323271;
  --sky: #A9B7E6;

  /* type */
  --serif: "Iowan Old Style", "Palatino Linotype", Palatino, Georgia, "Times New Roman", serif;
  --sans: system-ui, -apple-system, "Segoe UI", Roboto, Helvetica, Arial, sans-serif;

  /* scale */
  --wrap: 1180px;
  --gut: 24px;
  --step: 8px;

  /* board ink — cream-on-navy pairings used on every navy surface */
  --board-ink: rgba(255, 255, 255, .82);
  --board-line: rgba(169, 183, 230, .30);
}

/* ------------------------------------------------------------------ reset */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: .01ms !important; animation-iteration-count: 1 !important;
    transition-duration: .01ms !important; scroll-behavior: auto !important;
  }
}
body {
  margin: 0;
  background: var(--white);
  color: var(--ink);
  font-family: var(--sans);
  font-size: 17px;
  line-height: 1.6;
  -webkit-font-smoothing: antialiased;
  /* clip, not hidden: overflow-x:hidden makes body a scroll container and
     silently kills every position:sticky descendant (the hero stage). */
  overflow-x: hidden;
  overflow-x: clip;
}
img { max-width: 100%; height: auto; display: block; }
a { color: var(--navy); text-underline-offset: 3px; }
h1, h2, h3 { font-family: var(--serif); font-weight: 600; line-height: 1.12; text-wrap: balance; margin: 0 0 .5em; }
h1 { font-size: clamp(34px, 5.4vw, 62px); letter-spacing: -.015em; }
h2 { font-size: clamp(27px, 3.6vw, 44px); letter-spacing: -.01em; }
h3 { font-size: clamp(19px, 1.6vw, 23px); }
p { margin: 0 0 1em; }
::selection { background: var(--navy); color: var(--white); }
:focus-visible { outline: 3px solid var(--accent); outline-offset: 2px; }
[id] { scroll-margin-top: 96px; }

.wrap { width: min(100% - (var(--gut) * 2), var(--wrap)); margin-inline: auto; }
.prose { max-width: 68ch; }
.prose p { color: var(--ink-soft); }
.prose ul { padding-left: 0; list-style: none; margin: 0 0 1.2em; }
.prose ul li {
  position: relative; padding: 8px 0 8px 26px; color: var(--ink-soft);
  border-bottom: 1px solid var(--line);
}
.prose ul li::before {
  content: ""; position: absolute; left: 2px; top: 17px;
  width: 8px; height: 8px; background: var(--accent);
}
.prose ul li strong { color: var(--ink); }
.prose ol { counter-reset: item; list-style: none; padding: 0; margin: 0 0 1.2em; }
.prose ol li { counter-increment: item; position: relative; padding: 10px 0 10px 52px; color: var(--ink-soft); border-bottom: 1px solid var(--line); }
.prose ol li::before {
  content: counter(item, decimal-leading-zero);
  position: absolute; left: 0; top: 12px;
  font-family: var(--serif); font-size: 21px; color: var(--navy); font-weight: 600;
}
.prose ol li strong { color: var(--ink); }

/* skip link — keyboard users land on content, not the menu */
.skip {
  position: absolute; left: -9999px; top: 0; z-index: 999;
  background: var(--navy-deep); color: #fff; padding: 12px 18px; font-weight: 600;
}
.skip:focus { left: 8px; top: 8px; }

/* ---------------------------------------------------------------- eyebrow */
/* Brand blue: letterspaced caps hold AA on white at this size. */
.eyebrow {
  font-family: var(--sans); font-size: 12px; font-weight: 700;
  letter-spacing: .22em; text-transform: uppercase; color: var(--navy);
  display: inline-flex; align-items: center; gap: 10px; margin-bottom: 14px;
}
.eyebrow::before { content: ""; width: 22px; height: 2px; background: var(--accent); }
.rule { width: 56px; height: 2px; background: var(--accent); border: 0; margin: 0 0 22px; }

/* ---------------------------------------------------------------- buttons */
.btn {
  display: inline-flex; align-items: center; gap: 10px;
  font-family: var(--sans); font-size: 16px; font-weight: 600;
  padding: 14px 26px; border: 1px solid transparent; cursor: pointer;
  text-decoration: none; transition: transform .18s ease, box-shadow .18s ease, background .18s ease, color .18s ease;
}
.btn-solid { background: var(--navy); color: #fff; }
.btn-solid:hover { background: var(--navy-deep); transform: translateY(-2px); box-shadow: 5px 5px 0 var(--sky); }
.btn-ghost { background: transparent; color: var(--navy); border-color: var(--navy); }
.btn-ghost:hover { background: var(--navy); color: #fff; transform: translateY(-2px); }
/* inverse pair for navy boards — the primary CTA is white-on-blue */
.btn-bright { background: var(--white); color: var(--navy-deep); }
.btn-bright:hover { background: var(--sky); color: var(--navy-deep); transform: translateY(-2px); box-shadow: 5px 5px 0 rgba(0,0,0,.28); }
.btn-ghost-inv { background: transparent; color: var(--white); border-color: rgba(255, 255, 255,.55); }
.btn-ghost-inv:hover { background: var(--white); color: var(--navy-deep); transform: translateY(-2px); }
.btn-row { display: flex; gap: 12px; flex-wrap: wrap; }

/* --------------------------------------------------------------- sections */
.sec { padding: clamp(60px, 9vw, 112px) 0; position: relative; }
.sec-paper { background: var(--paper); border-block: 1px solid var(--line); }
.sec-tight { padding: clamp(40px, 6vw, 72px) 0; }
.sec-head { max-width: 760px; margin-bottom: clamp(28px, 4vw, 48px); }
.sec-head-c { margin-inline: auto; text-align: center; }
.sec-head-c .eyebrow { justify-content: center; }
.sec-head-c .rule { margin-inline: auto; }

/* Folio numbering — counts real sections, so the number means something. */
.folio-scope { counter-reset: folio; }
.folio { counter-increment: folio; }
.folio .folio-no::before { content: "Folio " counter(folio, decimal-leading-zero); }
.folio-no {
  font-family: var(--sans); font-size: 11px; font-weight: 700;
  letter-spacing: .2em; text-transform: uppercase; color: var(--ink-soft);
  display: inline-flex; align-items: center; gap: 8px;
}
.folio-no::after { content: ""; width: 34px; height: 1px; background: var(--accent); }

/* Navy feature panel with drafting hairlines — the "drawing board" motif. */
.panel {
  background: var(--navy-deep); color: var(--white);
  padding: clamp(32px, 5vw, 64px); position: relative; overflow: hidden;
}
.panel::before {
  content: ""; position: absolute; inset: 0; pointer-events: none; opacity: .18;
  background-image:
    linear-gradient(to right, rgba(169, 183, 230,.28) 1px, transparent 1px),
    linear-gradient(to bottom, rgba(169, 183, 230,.28) 1px, transparent 1px);
  background-size: 48px 48px;
  mask-image: radial-gradient(ellipse at 70% 30%, #000 20%, transparent 78%);
  -webkit-mask-image: radial-gradient(ellipse at 70% 30%, #000 20%, transparent 78%);
}
.panel > * { position: relative; }
.panel h2, .panel h3 { color: var(--white); }
.panel p { color: var(--board-ink); }
.panel .folio-no { color: var(--sky); }

/* Card — the sky offset on hover is the one flourish, used sparingly. */
.card {
  background: #fff; border: 1px solid var(--line); padding: 26px;
  transition: transform .22s ease, box-shadow .22s ease;
  text-decoration: none; color: inherit; display: block; position: relative;
}
.card:hover { transform: translateY(-4px); box-shadow: 8px 8px 0 var(--sky); }
.card h3 { margin-bottom: 6px; }
.card .card-no {
  font-family: var(--sans); font-size: 11px; font-weight: 700; letter-spacing: .18em;
  color: var(--ink-soft); display: block; margin-bottom: 12px; text-transform: uppercase;
}
.card p { font-size: 14px; color: var(--ink-soft); margin: 0; }
.card .card-go {
  display: inline-block; margin-top: 14px; font-size: 13px; font-weight: 700;
  letter-spacing: .08em; text-transform: uppercase; color: var(--navy);
}

.grid { display: grid; gap: 18px; }
.grid-3 { grid-template-columns: repeat(3, 1fr); }
.grid-2 { grid-template-columns: repeat(2, 1fr); }
@media (max-width: 900px) { .grid-3 { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 620px) { .grid-3, .grid-2 { grid-template-columns: 1fr; } }

/* chip links — town lists, quick picks */
.chips { display: flex; flex-wrap: wrap; gap: 10px; padding: 0; margin: 0; list-style: none; }
.chip {
  display: inline-block; padding: 9px 16px; border: 1px solid var(--line);
  background: #fff; color: var(--navy); text-decoration: none;
  font-size: 14px; font-weight: 600;
  transition: transform .16s ease, box-shadow .16s ease;
}
.chip:hover { transform: translateY(-2px); box-shadow: 4px 4px 0 var(--accent); }

/* ------------------------------------------------------------- breadcrumbs */
.crumb { font-family: var(--sans); font-size: 13px; color: var(--ink-soft); margin: 18px auto; }
.crumb a { color: var(--ink-soft); }
.crumb span { color: var(--accent); margin: 0 8px; }

/* ------------------------------------------------------------------ header */
.hdr {
  position: sticky; top: 0; z-index: 50;
  background: rgba(255, 255, 255, .94); backdrop-filter: saturate(1.4) blur(8px);
  border-bottom: 1px solid var(--line);
}
.hdr-in { display: flex; align-items: center; gap: 14px; height: 72px; flex-wrap: nowrap; }
.brand { display: flex; align-items: center; gap: 12px; text-decoration: none; color: var(--ink); }
/* Header brand removed on Gary's instruction — no mark, no wordmark. The nav
   sits left as a result. Home is still reachable from the breadcrumb on every
   inner page and from the footer. */
.brand-name { font-family: var(--serif); font-size: 19px; white-space: nowrap; }
/* With the brand gone there is nothing on the left for the nav to clear, so
   margin-left:auto was leaving a third of the header empty. The nav sits left
   now and the phone + CTA are pushed right instead. */
.nav { margin-right: auto; }
.nav ul { display: flex; align-items: center; gap: 2px; list-style: none; margin: 0; padding: 0; flex-wrap: nowrap; }
.nav a {
  display: block; padding: 10px 11px; text-decoration: none; color: var(--ink); white-space: nowrap;
  font-size: 15px; font-weight: 500; position: relative;
}
.nav a::after {
  content: ""; position: absolute; left: 14px; right: 14px; bottom: 6px; height: 2px;
  background: var(--accent); transform: scaleX(0); transform-origin: left;
  transition: transform .22s ease;
}
.nav a:hover::after, .nav a[aria-current="page"]::after { transform: scaleX(1); }
.nav a:hover, .nav a[aria-current="page"] { color: var(--navy); }
.hdr .btn { padding: 12px 20px; }
.burger { display: none; }

@media (max-width: 1000px) {
  .nav { display: none; }
  .burger {
    display: grid; place-items: center; margin-left: auto; width: 44px; height: 44px;
    background: none; border: 1px solid var(--line); cursor: pointer;
  }
  .burger span { display: block; width: 20px; height: 2px; background: var(--ink); margin: 2px 0; transition: transform .2s ease, opacity .2s ease; }
  .burger[aria-expanded="true"] span:nth-child(1) { transform: translateY(6px) rotate(45deg); }
  .burger[aria-expanded="true"] span:nth-child(2) { opacity: 0; }
  .burger[aria-expanded="true"] span:nth-child(3) { transform: translateY(-6px) rotate(-45deg); }
  .nav.open {
    display: block; position: fixed; inset: 72px 0 auto 0; background: var(--white);
    border-bottom: 1px solid var(--line); padding: 12px; max-height: calc(100dvh - 72px); overflow-y: auto;
    box-shadow: 0 20px 40px rgba(23, 24, 42,.14);
  }
  .nav.open ul { flex-direction: column; align-items: stretch; }
  .nav.open a { padding: 14px 12px; border-bottom: 1px solid var(--line); font-size: 17px; }
  .nav.open a::after { display: none; }
  .hdr .btn { display: none; }
}

/* ==================================================================== HERO
   "The drawing board." A navy board; scrolling draws a house elevation in
   gold linework, three proof lines set as the drawing completes, then the
   board releases into the page.

   Progressive by construction:
   - Default (no JS, or prefers-reduced-motion): a static composed hero —
     drawing complete, all copy visible. --hp defaults to 1.
   - html.js.motion-ok + .hero-live: the section grows a scroll track,
     the stage goes sticky, and site.js drives --hp from 0 to 1.           */
.hero { background: var(--navy-deep); position: relative; --hp: 1; }
.hero-track { position: relative; }
/* The film needs room to play. At 320vh it finished after ~1.9 screens and
   left a dead tail you scrolled through with nothing happening. At 700vh the
   hero is roughly half the page's scroll, which is what the client asked for,
   and the beats below are spaced to use the whole of it. */
.hero-live .hero-track { height: 700vh; }
.hero-stage { position: relative; min-height: 100svh; display: flex; flex-direction: column; }
.hero-live .hero-stage { position: sticky; top: 0; height: 100svh; overflow: hidden; }

.hero-board {
  flex: 1; position: relative; display: grid;
  grid-template-columns: minmax(0, 1.05fr) minmax(0, .95fr);
  align-items: center; gap: clamp(16px, 3vw, 48px);
  width: min(100% - (var(--gut) * 2), var(--wrap)); margin-inline: auto;
  padding: clamp(84px, 12vh, 128px) 0 clamp(56px, 9vh, 96px);
}
/* drafting grid on the board */
.hero::before {
  content: ""; position: absolute; inset: 0; pointer-events: none; opacity: .16;
  background-image:
    linear-gradient(to right, rgba(169, 183, 230,.28) 1px, transparent 1px),
    linear-gradient(to bottom, rgba(169, 183, 230,.28) 1px, transparent 1px);
  background-size: 56px 56px;
  mask-image: radial-gradient(ellipse at 72% 34%, #000 24%, transparent 80%);
  -webkit-mask-image: radial-gradient(ellipse at 72% 34%, #000 24%, transparent 80%);
}
/* corner ticks — sheet corners of the drawing */
.hero-corners { position: absolute; inset: clamp(14px, 2vw, 26px); pointer-events: none; opacity: .6; }
.hero-corners i { position: absolute; width: 22px; height: 22px; border: 0 solid var(--board-line); border-width: 2px 0 0 2px; }
.hero-corners i:nth-child(1) { left: 0; top: 0; }
.hero-corners i:nth-child(2) { right: 0; top: 0; transform: rotate(90deg); }
.hero-corners i:nth-child(3) { right: 0; bottom: 0; transform: rotate(180deg); }
.hero-corners i:nth-child(4) { left: 0; bottom: 0; transform: rotate(270deg); }

/* The wordmark, matched to the sign on SG's office wall: interlocking S-over-G
   monogram, "Refurbishments / Ltd" stacked beside it, letterspaced EST 2005
   underneath. Sizes are in em off the parent so the whole lockup scales as one
   unit — change --mark-size and everything holds its proportions. */
.est-mark {
  --mark-size: clamp(15px, 2.1vw, 23px);
  display: inline-flex; align-items: center; gap: .7em;
  font-size: var(--mark-size); color: var(--white);
}
.est-mono { width: 3.6em; height: 3.4em; flex: none; overflow: visible; }
.est-mono path { fill: currentColor; }
/* The S sits over the G and slightly left, as on the sign. Its own fill knocks
   a clean edge out of the G beneath it so the two read as interlocked rather
   than muddled — same trick as the metal letters overlapping on the wall.
   stroke-width is in glyph units: the group is scaled by ~0.045, so 110 glyph
   units ≈ the 5px knockout the old text version carried. */
.est-mono .mono-s path {
  paint-order: stroke fill;
  stroke: var(--navy-deep); stroke-width: 110px; stroke-linejoin: round;
}
/* .mono-flourish removed with its markup — James, 22 Jul: no flicks on the S */
.est-words { display: grid; gap: .04em; }
.est-words b {
  font-family: var(--serif); font-weight: 600; line-height: 1.02;
  font-size: 1.32em; letter-spacing: .005em;
}
.est-year {
  font-family: var(--serif); font-size: .74em; letter-spacing: .42em;
  text-transform: uppercase; color: var(--sky); margin-top: .34em;
}
/* Mobile: the mark was only using about half the screen width, which lost the
   detail in the monogram. Step it up so the lockup fills the column, then a
   second step for narrow handsets so "Refurbishments" never has to wrap. */
@media (max-width: 620px) { .est-mark { --mark-size: 18px; gap: .6em; } }
@media (max-width: 380px) { .est-mark { --mark-size: 16px; gap: .5em; } }
@media (max-width: 340px) { .est-mark { --mark-size: 14px; gap: .45em; } }

.hero-copy { position: relative; color: var(--white); max-width: 640px; }
.hero-copy .eyebrow { color: var(--sky); }
.hero-copy .eyebrow::before { background: var(--sky); }
.hero-copy h1 { color: var(--white); font-size: clamp(38px, 5.6vw, 72px); margin-bottom: 18px; }
.hero-copy h1 .hw { display: inline-block; }
.hero-sub { color: var(--board-ink); font-size: clamp(16px, 1.5vw, 19px); max-width: 46ch; }

/* load-in: word-by-word settle. Gated on .js.motion-ok so static = visible. */
@keyframes hw-set { from { opacity: 0; transform: translateY(.5em); } to { opacity: 1; transform: none; } }
html.js.motion-ok .hero-copy .hw { opacity: 0; animation: hw-set .7s cubic-bezier(.2,.7,.2,1) forwards; animation-delay: calc(.15s + var(--wi) * .07s); }
html.js.motion-ok .hero-copy .eyebrow,
html.js.motion-ok .hero-copy .rule,
html.js.motion-ok .hero-copy .hero-sub,
html.js.motion-ok .hero-copy .btn-row { opacity: 0; animation: hw-set .7s cubic-bezier(.2,.7,.2,1) forwards; }
html.js.motion-ok .hero-copy .eyebrow { animation-delay: .05s; }
html.js.motion-ok .hero-copy .rule { animation-delay: .5s; }
html.js.motion-ok .hero-copy .hero-sub { animation-delay: .62s; }
html.js.motion-ok .hero-copy .btn-row { animation-delay: .78s; }

/* the elevation drawing */
.hero-draw { position: relative; align-self: stretch; display: grid; align-items: center; min-width: 0; }
.hero-draw svg { width: 100%; height: auto; max-height: min(64vh, 640px); overflow: visible; }
.hero-draw [pathLength] { fill: none; stroke: var(--sky); stroke-width: 2; stroke-linecap: square; stroke-linejoin: miter; }
.hero-draw .dz-soft { stroke: var(--board-line); }
.hero-draw .dz-dash { stroke-dasharray: 7 6; }
.hero-draw .dz-fine { stroke-width: 1.25; }
/* the pencil setting-out: a faint copy of the elevation that is always there,
   so the sheet reads as "set out" before the ink draws over it */
/* The blueprint. Every drawn stroke starts fully dash-offset, so at the top of
   the page the panel was effectively EMPTY until you had scrolled a long way —
   which read as "the animation isn't there". The underlay now shows a proper
   ghosted setting-out from the first frame, and the ink draws over it. */
.hero-draw .under { stroke: var(--sky); stroke-width: 1.25; opacity: .34; }
/* scroll-drawn strokes: each group has an --a (start) and --b (end) window of --hp */
.hero-live .hero-draw .dz {
  stroke-dasharray: 1;
  stroke-dashoffset: calc(1px * clamp(0, calc((var(--b) - var(--hp)) / (var(--b) - var(--a))), 1));
}
.hero-live .hero-draw .dz-dash { stroke-dasharray: none; }
/* dashed strokes cannot double as draw-on strokes; fade them instead */
.hero-live .hero-draw .dz-fade { opacity: clamp(0, calc((var(--hp) - var(--a)) / (var(--b) - var(--a))), 1); }

/* hero media beats — the video-ready layer over the drawing pane.
   DORMANT until HERO_BEATS in build.py declares a clip or still: with the
   list empty no markup exists. Scroll decides which beat is visible
   (crossfade via the same --a/--b windows as the drawing); site.js plays a
   video beat while active and pauses it outside its window. No JS, or
   prefers-reduced-motion -> .hero-live never engages, beats stay hidden and
   the static drawing carries the hero, so nothing heavy ever loads. */
.hero-media { position: absolute; inset: 0; pointer-events: none; }
.hm-beat {
  position: absolute; inset: 0; margin: 0; opacity: 0; overflow: hidden;
  border: 1px solid var(--board-line); background: var(--navy-deep);
}
.hero-live .hm-beat {
  opacity: calc(clamp(0, calc((var(--hp) - var(--a)) / .06), 1) * (1 - clamp(0, calc((var(--hp) - var(--b)) / .06), 1)));
}
.hm-beat img, .hm-beat video { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
/* slow Ken Burns on stills only — videos move by themselves */
html.js.motion-ok .hero-live .hm-beat > img:only-child { animation: hm-kb 16s linear infinite alternate; }
@keyframes hm-kb { from { transform: scale(1); } to { transform: scale(1.06); } }
/* the poster <img> sits beneath; video fades over it once playable */
.hm-beat video { opacity: 0; transition: opacity .4s ease; }
.hm-beat video.is-ready { opacity: 1; }

/* proof beats — annotation cards that stamp in as the drawing completes */
.hero-beats { position: relative; display: grid; gap: 12px; margin-top: 26px; max-width: 560px; }
.hero-beat {
  display: grid; grid-template-columns: auto 1fr; gap: 14px; align-items: baseline;
  border: 1px solid var(--board-line); background: rgba(33, 33, 80, .72);
  padding: 13px 16px;
}
.hero-beat b {
  font-family: var(--sans); font-size: 11px; font-weight: 700; letter-spacing: .2em;
  text-transform: uppercase; color: var(--sky); white-space: nowrap;
}
.hero-beat span { font-family: var(--serif); font-size: clamp(15px, 1.35vw, 18px); color: var(--white); line-height: 1.4; }
.hero-live .hero-beat {
  opacity: clamp(0, calc((var(--hp) - var(--a)) / .08), 1);
  transform: translateY(calc((1 - clamp(0, calc((var(--hp) - var(--a)) / .08), 1)) * 14px));
}

/* scroll cue + release */
.hero-cue {
  position: absolute; left: 50%; bottom: 18px; transform: translateX(-50%);
  display: none; align-items: center; gap: 10px; color: var(--board-ink);
  font-size: 11px; font-weight: 700; letter-spacing: .22em; text-transform: uppercase;
  opacity: calc(1 - clamp(0, calc(var(--hp) / .1), 1));
}
.hero-live .hero-cue { display: inline-flex; }
.hero-cue::after { content: ""; width: 1px; height: 34px; background: var(--sky); animation: cue-drop 1.6s ease-in-out infinite; transform-origin: top; }
@keyframes cue-drop { 0% { transform: scaleY(.2); opacity: 0; } 45% { transform: scaleY(1); opacity: 1; } 100% { transform: scaleY(1) translateY(8px); opacity: 0; } }
.hero-live .hero-board { opacity: calc(1 - clamp(0, calc((var(--hp) - .92) / .08), 1) * .35); }

/* ---------------------------------------------------------------- the film
   gets the whole stage.

   It used to live in the right-hand column of the two-column board, which drew
   it at 540x329 in a 1440x900 stage — 37% of the viewport height. That is why
   the animation read as a thumbnail: the binding constraint was the COLUMN
   WIDTH, not the max-height on the svg, so raising max-height alone did
   nothing. Now the drawing is absolutely positioned across the full stage and
   the headline holds the opening moment, then clears out of the way.

   Scoped to .hero-live so the no-JS and reduced-motion fallback keeps the
   original side-by-side board, which is a perfectly good static poster. */
.hero-live .hero-board { grid-template-columns: minmax(0, 1fr); }

/* The hero copy is now just the EST mark, and a centred grid was dropping it
   into the middle of the film. Pin it to the top of the stage instead. */
.hero-live .hero-copy { align-self: start; }

.hero-live .hero-draw {
  position: absolute; inset: 0;
  display: grid; place-items: center;
  padding: clamp(64px, 9vh, 104px) clamp(16px, 4vw, 64px) clamp(44px, 7vh, 80px);
}
.hero-live .hero-draw svg {
  width: 100%; height: 100%; max-height: none;
}

/* The headline owns the first beat, then hands the stage to the drawing.
   pointer-events is switched off by the .film-running class from site.js —
   opacity alone would leave invisible buttons still catching clicks. */
.hero-live .hero-copy,
.hero-live .hero-cue {
  position: relative; z-index: 2;
  opacity: clamp(0, calc((.15 - var(--hp)) / .10), 1);
}
.hero-live.film-running .hero-copy,
.hero-live.film-running .hero-cue { pointer-events: none; }

@media (max-width: 880px) {
  .hero-board { grid-template-columns: 1fr; align-content: start; gap: 8px; padding-top: 96px; }
  .hero-draw svg { max-height: 34svh; }
  .hero-draw { order: 2; }
  /* Same trade on a phone: the drawing takes the stage once the film starts,
     rather than sharing a short screen with the headline. */
  .hero-live .hero-draw { padding: 76px 14px 56px; }
  .hero-live .hero-draw svg { max-height: none; }
  .hero-copy { order: 1; }
  .hero-beats { order: 3; margin-top: 10px; gap: 8px; }
  .hero-beat { padding: 10px 13px; }
  .hero-live .hero-track { height: 420vh; }   /* longer, but a phone is more effort to scroll */
  .hero-copy h1 { font-size: clamp(34px, 9.4vw, 46px); }
}
@media (max-height: 640px) {
  .hero-beats { display: none; }
}

/* ================================================================== PROOF
   Trust without badges: four exhibits, presented like a works folio.      */
.proof-lead { font-size: clamp(18px, 1.9vw, 23px); font-family: var(--serif); color: var(--ink); max-width: 30em; line-height: 1.5; }
.proof-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: clamp(18px, 2.6vw, 34px); margin-top: clamp(30px, 4vw, 52px); }
@media (max-width: 880px) { .proof-grid { grid-template-columns: 1fr; } }
.exhibit { border: 1px solid var(--line); background: var(--paper); padding: clamp(22px, 3vw, 36px); display: flex; flex-direction: column; gap: 16px; }
.exhibit-tag {
  font-family: var(--sans); font-size: 11px; font-weight: 700; letter-spacing: .2em;
  text-transform: uppercase; color: var(--ink-soft);
  display: flex; align-items: center; gap: 10px;
}
.exhibit-tag::before { content: ""; width: 8px; height: 8px; background: var(--accent); }
.exhibit h3 { font-size: clamp(21px, 2vw, 27px); margin: 0; }
.exhibit p { color: var(--ink-soft); margin: 0; }
.exhibit-art { margin-top: auto; padding-top: 10px; }
/* the years exhibit: the art stretches to soak up the row height the patch
   map sets, so the date plate fills its cell instead of stranding at the foot */
.exhibit-art-fill { flex: 1 1 auto; display: flex; flex-direction: column; }
.exhibit-art-fill .since { flex: 1 1 auto; }

/* exhibit A — subcontractor chain vs one team */

/* exhibit B — the itemised quote, as a document */
.quote-doc {
  background: #fff; border: 1px solid var(--line); box-shadow: 6px 6px 0 var(--line);
  padding: 22px 24px; font-family: var(--serif); position: relative;
}
/* The margin rule belongs beside the priced ROWS only. As a full-height rule on
   .quote-doc it cut straight through the header and footer text, which have no
   left padding. Drawn per-row instead: rows are adjacent, so it still reads as
   one continuous line. */
.qd-row::before {
  content: ""; position: absolute; left: 42px; top: 0; bottom: 0; width: 1px; background: var(--line);
}
.qd-head { display: flex; justify-content: space-between; align-items: baseline; border-bottom: 2px solid var(--navy); padding-bottom: 10px; margin-bottom: 4px; }
.qd-head b { font-size: 15px; letter-spacing: .02em; color: var(--navy-deep); }
.qd-head span { font-family: var(--sans); font-size: 10px; font-weight: 700; letter-spacing: .18em; text-transform: uppercase; color: var(--ink-soft); }
.qd-row { display: flex; justify-content: space-between; gap: 16px; align-items: baseline; padding: 9px 0 9px 34px; border-bottom: 1px solid var(--line); font-size: 14.5px; color: var(--ink); position: relative; }
.qd-row::before { content: attr(data-n); position: absolute; left: 0; font-family: var(--sans); font-size: 10px; font-weight: 700; color: var(--ink-soft); top: 12px; }
.qd-row i { flex: 1; border-bottom: 1px dotted var(--line); transform: translateY(-4px); }
.qd-row em { font-style: normal; color: var(--ink-soft); font-family: var(--sans); font-size: 12px; letter-spacing: .06em; }
.qd-foot { padding: 12px 0 2px 34px; font-family: var(--sans); font-size: 12.5px; color: var(--ink-soft); }

/* exhibit C — since 2005 as a drawn date plate: a navy board (same drafting
   grid + corner ticks as the hero) with the founding year set huge, one
   plain start-to-now rule ("and counting" — deliberately NO intermediate
   ticks: there are no confirmed milestones to hang a timeline on), then a
   short ruled ledger of checkable facts, dotted leaders echoing the quote
   specimen. All colours are the locked palette or rgba() of it. */
.since {
  position: relative; overflow: hidden;
  background: var(--navy-deep); color: var(--board-ink);
  padding: clamp(20px, 2.4vw, 30px) clamp(20px, 2.6vw, 32px) clamp(16px, 2vw, 24px);
  display: flex; flex-direction: column; min-height: 360px;
}
.since::before { /* the drafting grid, as on the hero board */
  content: ""; position: absolute; inset: 0; pointer-events: none; opacity: .14;
  background-image:
    linear-gradient(to right, rgba(169, 183, 230,.28) 1px, transparent 1px),
    linear-gradient(to bottom, rgba(169, 183, 230,.28) 1px, transparent 1px);
  background-size: 48px 48px;
  mask-image: radial-gradient(ellipse at 30% 38%, #000 24%, transparent 82%);
  -webkit-mask-image: radial-gradient(ellipse at 30% 38%, #000 24%, transparent 82%);
}
.since-corners { position: absolute; inset: 9px; pointer-events: none; opacity: .8; }
.since-corners i { position: absolute; width: 16px; height: 16px; border: 0 solid var(--board-line); border-width: 2px 0 0 2px; }
.since-corners i:nth-child(1) { left: 0; top: 0; }
.since-corners i:nth-child(2) { right: 0; top: 0; transform: rotate(90deg); }
.since-corners i:nth-child(3) { right: 0; bottom: 0; transform: rotate(180deg); }
.since-corners i:nth-child(4) { left: 0; bottom: 0; transform: rotate(270deg); }
.since-head {
  position: relative; display: flex; justify-content: space-between; align-items: baseline;
  gap: 12px; border-bottom: 1px solid var(--board-line); padding-bottom: 10px;
}
.since-head b { font-family: var(--serif); font-weight: 600; font-size: 15px; letter-spacing: .02em; color: var(--white); }
.since-head span { font-family: var(--sans); font-size: 10px; font-weight: 700; letter-spacing: .18em; text-transform: uppercase; color: var(--sky); white-space: nowrap; }
.since-year {
  position: relative; flex: 1 1 auto; display: flex; flex-direction: column;
  justify-content: center; align-items: flex-start; padding: clamp(18px, 2.6vw, 30px) 0;
}
.since-est {
  font-family: var(--sans); font-size: 11px; font-weight: 700; letter-spacing: .3em;
  text-transform: uppercase; color: var(--sky);
  display: inline-flex; align-items: center; gap: 12px; margin-bottom: 6px;
}
.since-est::after { content: ""; width: 44px; height: 1px; background: var(--board-line); }
.since-year > b {
  font-family: var(--serif); font-weight: 600; line-height: .84;
  font-size: clamp(92px, 10.5vw, 148px); color: var(--white); letter-spacing: -.02em;
  font-variant-numeric: lining-nums;
}
.since-count { /* one plain start-to-now rule — no ticks, no milestones */
  width: 100%; margin-top: 18px;
  font-family: var(--sans); font-size: 11px; font-weight: 700; letter-spacing: .24em;
  text-transform: uppercase; color: var(--sky);
  display: flex; align-items: center; gap: 14px;
}
.since-count::before { content: ""; flex: 1 1 auto; height: 2px; background: var(--sky); }
.since-rows { position: relative; list-style: none; margin: 0; padding: 0; font-family: var(--sans); }
.since-rows li {
  display: flex; align-items: baseline; gap: 12px; padding: 8px 0;
  border-top: 1px solid rgba(169, 183, 230, .18);
}
.since-rows b { font-size: 10.5px; font-weight: 700; letter-spacing: .14em; text-transform: uppercase; color: var(--board-ink); white-space: nowrap; }
.since-rows i { flex: 1 1 auto; border-bottom: 1px dotted var(--board-line); transform: translateY(-3px); }
.since-rows span { font-size: 13px; font-weight: 600; color: var(--white); text-align: right; }

/* exhibit D — the patch map (shared with areas pages) */
.patch { position: relative; }
.patch svg { width: 100%; height: auto; }
.patch text {
  font-family: var(--sans); font-size: 11.5px; font-weight: 600; fill: var(--ink);
  letter-spacing: .02em;
}
.patch .pm-ring { fill: none; stroke: var(--line); stroke-dasharray: 4 5; }
.patch .pm-dot { fill: var(--navy); }
.patch .pm-base-dot { fill: var(--accent); }
.patch .pm-base-text { font-weight: 800; fill: var(--navy-deep); font-size: 13px; letter-spacing: .04em; }
.patch .pm-hl circle { fill: var(--sky); stroke: var(--navy); stroke-width: 2; }
.patch .pm-hl text { fill: var(--navy-deep); font-weight: 800; }
.patch a:hover text, .patch a:focus text { fill: var(--accent); text-decoration: underline; }
.patch-note { font-family: var(--sans); font-size: 11px; letter-spacing: .16em; text-transform: uppercase; color: var(--ink-soft); margin-top: 6px; }
.patch-board { background: var(--navy-deep); }
.patch-board text { fill: var(--board-ink); }
.patch-board .pm-ring { stroke: var(--board-line); }
.patch-board .pm-dot { fill: var(--sky); }
.patch-board .pm-base-dot { fill: var(--sky); }
.patch-board .pm-base-text { fill: var(--white); }
.patch-board .pm-hl text { fill: var(--sky); }

/* ================================================================== WORK
   Gallery, honest placeholders, before/after.                             */
.work-grid { display: grid; grid-template-columns: repeat(12, 1fr); gap: 18px; margin-top: clamp(28px, 4vw, 44px); }
.work-item { grid-column: span 4; margin: 0; position: relative; }
.work-item.w-wide { grid-column: span 8; }
@media (max-width: 880px) { .work-item, .work-item.w-wide { grid-column: span 12; } }
.work-item img { width: 100%; aspect-ratio: 3 / 2; object-fit: cover; border: 1px solid var(--line); }
.work-item figcaption { display: flex; gap: 10px; align-items: baseline; margin-top: 10px; font-size: 13.5px; color: var(--ink-soft); }
.work-item figcaption b { font-family: var(--sans); font-size: 11px; font-weight: 700; letter-spacing: .16em; text-transform: uppercase; color: var(--navy); white-space: nowrap; }

/* An indicative image is NOT one of SG's jobs, and has to be readable as that
   without anyone hunting for the caption. The corner tag does that work on the
   image itself; the caption then says it in full. Do not remove the tag and
   leave the image — that turns the page back into the thing this site was
   rebuilt to stop doing. When a real photograph lands for that category the
   whole cell is replaced by it and the tag goes with it. */
.ind-tag {
  position: absolute; top: 10px; left: 10px; z-index: 2;
  font-family: var(--sans); font-size: 10px; font-weight: 700;
  letter-spacing: .16em; text-transform: uppercase;
  padding: 5px 9px; color: var(--white);
  background: rgba(33, 33, 80, .82);
  backdrop-filter: saturate(140%) blur(2px);
}
.ba-stage .ind-tag { top: 12px; left: 12px; }

/* the honest placeholder — a reserved photo plate, not a bare empty box:
   a hatched mount card (poché — "area reserved" in drawing language) with
   a calm clearing at the centre, gold photo-mounting corners waiting for
   the print, the SG plate mark and the honest label. No stock, no
   pretending — an <img> still replaces the div one-for-one. */
.frame {
  aspect-ratio: 3 / 2; border: 1px solid var(--line); background: var(--paper);
  position: relative; display: grid; place-content: center; text-align: center;
  padding: 18px; gap: 8px; overflow: hidden;
}
.frame::before, .wk-slot-frame::before { /* the hatched ground */
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: repeating-linear-gradient(-45deg, rgba(222, 227, 236, .55) 0 1px, transparent 1px 9px);
}
.frame::after, .wk-slot-frame::after { /* the clearing the label sits in */
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: radial-gradient(ellipse 64% 56% at 50% 50%, rgba(244, 247, 251, .96) 32%, rgba(244, 247, 251, 0) 74%);
}
/* The drawn plate that carries a slot with no photograph yet. Sits UNDER the
   hatching's clearing gradient (.frame::after) so the label stays readable on
   top of it — hence z-index 0 against the corners' 1 and the label's own stack.
   Same line language as the hero film: this is unmistakably a drawing, never a
   photograph pretending to be one of SG's jobs. */
.plate-art {
  position: absolute; inset: 0; width: 100%; height: 100%; z-index: 0;
  fill: none; stroke: var(--navy); stroke-width: 1.4;
  stroke-linecap: square; stroke-linejoin: miter;
  opacity: .38;
}
.plate-art .dz-fine { stroke-width: .9; opacity: .8; }

.frame-corners { position: absolute; inset: 11px; pointer-events: none; z-index: 1; }
.frame-corners i { position: absolute; width: 15px; height: 15px; border: 0 solid var(--accent); border-width: 2px 0 0 2px; opacity: .8; }
.frame-corners i:nth-child(1) { left: 0; top: 0; }
.frame-corners i:nth-child(2) { right: 0; top: 0; transform: rotate(90deg); }
.frame-corners i:nth-child(3) { right: 0; bottom: 0; transform: rotate(180deg); }
.frame-corners i:nth-child(4) { left: 0; bottom: 0; transform: rotate(270deg); }
.frame-mark {
  position: relative; z-index: 1; font-style: normal; font-family: var(--serif);
  font-weight: 600; font-size: 18px; letter-spacing: .08em; color: var(--navy);
  justify-self: center; display: inline-flex; flex-direction: column; align-items: center; gap: 7px;
}
.frame-mark::after { content: ""; width: 26px; height: 2px; background: var(--accent); }
.frame b {
  position: relative; z-index: 1; font-family: var(--sans); font-size: 11px; font-weight: 700;
  letter-spacing: .18em; text-transform: uppercase; color: var(--navy); justify-self: center;
}
.frame-note {
  position: relative; z-index: 1; font-size: 12.5px; color: var(--ink-soft);
  justify-self: center; max-width: 30ch;
}
.work-note { margin-top: 18px; font-size: 13.5px; color: var(--ink-soft); max-width: 62ch; }

/* before / after — a working slider whose photos drop straight in.
   Replace each .ba-side .frame with an <img> when real pairs exist. */
.ba { position: relative; margin-top: clamp(28px, 4vw, 44px); }
.ba-stage { position: relative; overflow: hidden; border: 1px solid var(--line); aspect-ratio: 16 / 8; background: var(--paper); }
.ba-side { position: absolute; inset: 0; }
.ba-side .frame, .ba-side img { position: absolute; inset: 0; width: 100%; height: 100%; aspect-ratio: auto; object-fit: cover; }
.ba-after { clip-path: inset(0 0 0 var(--ba, 50%)); background: var(--navy-deep); }
/* each side's label sits centred in ITS OWN half, so nothing straddles the
   divider at the resting 50% position */
.ba-before .frame { padding-right: 52%; }
.ba-before .frame::after { background: radial-gradient(ellipse 38% 56% at 25% 50%, rgba(244, 247, 251, .96) 32%, rgba(244, 247, 251, 0) 74%); }
.ba-after .frame { padding-left: 52%; }
.ba-after .frame { background: var(--navy-deep); border: 0; }
.ba-after .frame::before { background: repeating-linear-gradient(-45deg, rgba(169, 183, 230, .22) 0 1px, transparent 1px 9px); }
.ba-after .frame::after { background: radial-gradient(ellipse 38% 56% at 75% 50%, rgba(33, 33, 80, .96) 32%, rgba(33, 33, 80, 0) 74%); }
.ba-after .frame-corners i { border-color: var(--sky); }
.ba-after .frame-mark { color: var(--white); }
.ba-after .frame-mark::after { background: var(--sky); }
.ba-after .frame b { color: var(--sky); }
.ba-after .frame-note { color: var(--board-ink); }
.ba-handle {
  position: absolute; top: 0; bottom: 0; left: var(--ba, 50%); width: 2px; background: var(--navy);
  box-shadow: 0 0 0 1px rgba(255, 255, 255, .55); /* keeps the divider legible on the navy half */
  pointer-events: none; z-index: 2;
}
.ba-handle::after {
  content: "\2194"; position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%);
  width: 44px; height: 44px; background: var(--navy); color: var(--white);
  border: 2px solid var(--white);
  display: grid; place-items: center; font-size: 19px; border-radius: 50%;
  box-shadow: 0 6px 18px rgba(23, 24, 42,.3);
}
.ba input[type="range"] {
  position: absolute; inset: 0; width: 100%; height: 100%; opacity: 0; cursor: ew-resize; z-index: 3; margin: 0;
}
.ba input[type="range"]:focus-visible ~ .ba-handle::after { outline: 3px solid var(--sky); outline-offset: 2px; }
.ba-tags { position: absolute; z-index: 2; inset: 14px 14px auto; display: flex; justify-content: space-between; pointer-events: none; }
.ba-tags b {
  font-family: var(--sans); font-size: 11px; font-weight: 700; letter-spacing: .2em;
  text-transform: uppercase; padding: 6px 12px;
}
.ba-tags b:first-child { background: var(--white); color: var(--navy-deep); border: 1px solid var(--line); }
.ba-tags b:last-child { background: var(--navy-deep); color: var(--white); border: 1px solid var(--board-line); }
@media (max-width: 680px) {
  /* small screens: the plates keep the mark and label; the longer note is
     carried by the .work-note line under the slider instead */
  .ba-side .frame-note { display: none; }
}

/* ============================================================ TITLE BLOCK
   The drawing-sheet corner stamp used on service and town pages.          */
.sheet { display: grid; grid-template-columns: minmax(0, 1.25fr) minmax(280px, .75fr); gap: clamp(28px, 4vw, 64px); align-items: start; }
@media (max-width: 880px) { .sheet { grid-template-columns: 1fr; } }
.tblock { border: 1px solid var(--ink); background: var(--paper); font-family: var(--sans); position: sticky; top: 96px; }
@media (max-width: 880px) { .tblock { position: static; } }
.tblock-head {
  display: flex; justify-content: space-between; align-items: center;
  background: var(--navy-deep); color: var(--white); padding: 12px 16px;
  font-size: 11px; font-weight: 700; letter-spacing: .2em; text-transform: uppercase;
}
.tblock-head i { font-style: normal; color: var(--sky); }
.tblock-rows { display: grid; }
.tblock-row { display: grid; grid-template-columns: 96px 1fr; border-top: 1px solid var(--line); }
.tblock-row dt {
  padding: 11px 14px; font-size: 10.5px; font-weight: 700; letter-spacing: .14em;
  text-transform: uppercase; color: var(--ink-soft); border-right: 1px solid var(--line);
}
.tblock-row dd { margin: 0; padding: 10px 14px; font-size: 14px; color: var(--ink); }
.tblock-cta { border-top: 1px solid var(--ink); padding: 14px; display: grid; gap: 8px; }
.tblock-cta .btn { justify-content: center; }

/* ================================================================= STEPS */
.steps { counter-reset: step; display: grid; gap: 0; margin-top: clamp(24px, 3vw, 40px); }
.step-it { counter-increment: step; display: grid; grid-template-columns: 72px 1fr; gap: 18px; padding: 22px 0; border-top: 1px solid var(--line); position: relative; }
.step-it:last-child { border-bottom: 1px solid var(--line); }
.step-it::before {
  content: counter(step, decimal-leading-zero); font-family: var(--serif);
  font-size: clamp(28px, 3vw, 40px); line-height: 1; color: var(--navy); font-weight: 600;
}
.step-it h3 { margin-bottom: 6px; }
.step-it p { color: var(--ink-soft); margin: 0; }

/* =============================================================== ACCORDION */
.faq { display: grid; gap: 0; margin-top: clamp(20px, 3vw, 36px); border-top: 1px solid var(--line); }
.faq details { border-bottom: 1px solid var(--line); }
.faq summary {
  cursor: pointer; list-style: none; display: flex; justify-content: space-between; gap: 18px;
  align-items: baseline; padding: 18px 2px; font-family: var(--serif);
  font-size: clamp(17px, 1.6vw, 20px); font-weight: 600; color: var(--ink);
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after {
  content: "+"; font-family: var(--sans); color: var(--navy); font-size: 22px; line-height: 1;
  transition: transform .2s ease; flex: none;
}
.faq details[open] summary::after { transform: rotate(45deg); }
.faq details > div { padding: 0 2px 20px; color: var(--ink-soft); max-width: 68ch; }
.faq details > div p:last-child { margin-bottom: 0; }

/* ================================================================= WIZARD
   The quote wizard — a job sheet being opened, not a form.
   Default (no JS): every fieldset is visible and the form posts by mail.
   With JS (.wz-live): stepped, one panel at a time, instrumented by
   measure.js via [data-quote-wizard] / [data-quote-step].                 */
.wizard {
  background: var(--navy-deep); color: var(--white); position: relative; overflow: hidden;
  border: 1px solid var(--navy-deep);
}
.wizard::before {
  content: ""; position: absolute; inset: 0; pointer-events: none; opacity: .14;
  background-image:
    linear-gradient(to right, rgba(169, 183, 230,.28) 1px, transparent 1px),
    linear-gradient(to bottom, rgba(169, 183, 230,.28) 1px, transparent 1px);
  background-size: 48px 48px;
  mask-image: radial-gradient(ellipse at 80% 10%, #000 15%, transparent 70%);
  -webkit-mask-image: radial-gradient(ellipse at 80% 10%, #000 15%, transparent 70%);
}
.wizard > * { position: relative; }
.wz-head { padding: clamp(24px, 3.4vw, 40px) clamp(22px, 3.4vw, 44px) 0; display: flex; flex-wrap: wrap; gap: 14px 24px; align-items: baseline; justify-content: space-between; }
.wz-head h2 { color: var(--white); font-size: clamp(24px, 2.6vw, 34px); margin: 0; }
.wz-head .wz-kicker {
  font-family: var(--sans); font-size: 11px; font-weight: 700; letter-spacing: .2em;
  text-transform: uppercase; color: var(--sky); display: block; margin-bottom: 8px;
}
.wz-sub { color: var(--board-ink); font-size: 15px; max-width: 56ch; margin: 6px 0 0; }

.wz-rail { display: none; padding: 20px clamp(22px, 3.4vw, 44px) 0; gap: 0; }
.wz-live .wz-rail { display: flex; }
.wz-rail li {
  list-style: none; flex: 1; display: grid; gap: 8px; padding: 0 10px 0 0;
  font-family: var(--sans); font-size: 11px; font-weight: 700; letter-spacing: .14em;
  text-transform: uppercase; color: var(--board-ink);
}
.wz-rail li::before { content: ""; height: 3px; background: rgba(255, 255, 255,.22); }
.wz-rail li.done::before, .wz-rail li.now::before { background: var(--sky); }
.wz-rail li.now { color: var(--sky); }
.wz-rail { margin: 0; padding-left: clamp(22px, 3.4vw, 44px); }

.wz-body { padding: clamp(20px, 3vw, 36px) clamp(22px, 3.4vw, 44px) clamp(26px, 3.4vw, 44px); }
.wz-step { border: 0; padding: 0; margin: 0 0 30px; min-width: 0; }
.wz-live .wz-step { display: none; margin: 0; }
.wz-live .wz-step.now { display: block; animation: wz-in .35s ease; }
@keyframes wz-in { from { opacity: 0; transform: translateX(18px); } to { opacity: 1; transform: none; } }
.wz-step legend {
  font-family: var(--serif); font-size: clamp(20px, 2vw, 26px); font-weight: 600;
  color: var(--white); padding: 0; margin-bottom: 4px;
}
.wz-step .wz-hint { font-size: 14px; color: var(--board-ink); margin: 0 0 18px; }

.wz-opts { display: grid; grid-template-columns: repeat(auto-fill, minmax(168px, 1fr)); gap: 10px; }
.wz-opt { position: relative; }
.wz-opt input { position: absolute; opacity: 0; inset: 0; pointer-events: none; }
.wz-opt label {
  display: block; padding: 15px 16px 13px; border: 1px solid var(--board-line);
  background: rgba(255, 255, 255,.04); cursor: pointer; user-select: none;
  font-family: var(--serif); font-size: 17px; color: var(--white); line-height: 1.3;
  transition: background .16s ease, border-color .16s ease, transform .16s ease;
}
.wz-opt label small { display: block; font-family: var(--sans); font-size: 11.5px; color: var(--board-ink); margin-top: 3px; }
.wz-opt label:hover { transform: translateY(-2px); border-color: var(--sky); }
.wz-opt input:checked + label { background: var(--accent); border-color: var(--sky); color: var(--white); }
.wz-opt input:checked + label small { color: var(--navy-deep); }
.wz-opt input:focus-visible + label { outline: 3px solid var(--sky); outline-offset: 2px; }

.wz-fields { display: grid; grid-template-columns: 1fr 1fr; gap: 14px; }
@media (max-width: 680px) { .wz-fields { grid-template-columns: 1fr; } }
.wz-field { display: grid; gap: 6px; }
.wz-field.wide { grid-column: 1 / -1; }
.wz-field label { font-family: var(--sans); font-size: 12px; font-weight: 700; letter-spacing: .12em; text-transform: uppercase; color: var(--board-ink); }
.wz-field label em { font-style: normal; text-transform: none; letter-spacing: 0; font-weight: 500; color: rgba(255, 255, 255,.55); }
.wz-field input, .wz-field textarea, .wz-field select {
  font: inherit; color: var(--white); background: rgba(255, 255, 255,.06);
  border: 1px solid var(--board-line); padding: 13px 14px; width: 100%;
}
.wz-field input::placeholder, .wz-field textarea::placeholder { color: rgba(255, 255, 255,.38); }
.wz-field input:focus, .wz-field textarea:focus { outline: 2px solid var(--sky); outline-offset: 0; background: rgba(255, 255, 255,.1); }
.wz-err { display: none; font-size: 13.5px; color: var(--sky); font-weight: 600; margin-top: 10px; }
.wz-err.show { display: block; }

.wz-nav { display: none; margin-top: 26px; gap: 12px; align-items: center; }
.wz-live .wz-nav { display: flex; }
.wz-back {
  background: none; border: 0; color: var(--board-ink); font: inherit; font-size: 14px;
  cursor: pointer; padding: 12px 8px; text-decoration: underline; text-underline-offset: 3px;
}
.wz-back:hover { color: var(--white); }
.wz-send { display: flex; flex-wrap: wrap; gap: 12px; margin-top: 26px; }
.wz-alt { font-size: 13.5px; color: var(--board-ink); margin: 18px 0 0; }
.wz-alt a { color: var(--white); }

/* review line on the final step */
.wz-review { border: 1px dashed var(--board-line); padding: 14px 16px; margin: 0 0 20px; font-size: 14px; color: var(--board-ink); display: none; }
.wz-live .wz-review { display: block; }
.wz-review b { color: var(--white); font-weight: 600; }

/* done state */
.wz-done { display: none; padding: clamp(30px, 5vw, 56px) clamp(22px, 3.4vw, 44px); text-align: left; }
.wz-done h3 { color: var(--white); font-size: clamp(22px, 2.4vw, 30px); }
.wz-done p { color: var(--board-ink); max-width: 56ch; }
.wizard.is-done .wz-body, .wizard.is-done .wz-rail, .wizard.is-done .wz-head { display: none; }
.wizard.is-done .wz-done { display: block; }
.wz-done .tick {
  width: 52px; height: 52px; border: 2px solid var(--accent); border-radius: 50%;
  display: grid; place-items: center; color: var(--sky); font-size: 24px; margin-bottom: 18px;
}

/* ============================================================== CTA BAND */
.cta-band { background: var(--navy-deep); color: var(--white); position: relative; overflow: hidden; }
.cta-band::before {
  content: ""; position: absolute; inset: 0; pointer-events: none; opacity: .16;
  background-image:
    linear-gradient(to right, rgba(169, 183, 230,.28) 1px, transparent 1px),
    linear-gradient(to bottom, rgba(169, 183, 230,.28) 1px, transparent 1px);
  background-size: 52px 52px;
  mask-image: radial-gradient(ellipse at 25% 40%, #000 20%, transparent 75%);
  -webkit-mask-image: radial-gradient(ellipse at 25% 40%, #000 20%, transparent 75%);
}
.cta-band .wrap { position: relative; display: grid; grid-template-columns: minmax(0, 1fr) auto; gap: 24px 48px; align-items: center; padding-block: clamp(48px, 7vw, 84px); }
@media (max-width: 780px) { .cta-band .wrap { grid-template-columns: 1fr; } }
.cta-band h2 { color: var(--white); margin-bottom: 8px; }
.cta-band p { color: var(--board-ink); margin: 0; max-width: 52ch; }

/* ------------------------------------------------------------------ footer */
.ftr { background: var(--navy-deep); color: var(--board-ink); padding: 64px 0 28px; border-top: 1px solid var(--board-line); }
.ftr .foot-h { font-family: var(--sans); font-size: 12px; letter-spacing: .18em; text-transform: uppercase; color: var(--sky); margin: 0 0 14px; }
.ftr a { color: var(--board-ink); text-decoration: none; }
.ftr a:hover { color: #fff; text-decoration: underline; }
.ftr ul { list-style: none; margin: 0; padding: 0; }
.ftr li { margin-bottom: 8px; font-size: 14px; }
.ftr-grid { display: grid; grid-template-columns: 1.4fr 1fr 1fr 1fr; gap: 32px; }
.ftr-btm { margin-top: 44px; padding-top: 20px; border-top: 1px solid rgba(255, 255, 255, .16); font-size: 13px; display: flex; flex-wrap: wrap; gap: 12px; justify-content: space-between; }
@media (max-width: 860px) { .ftr-grid { grid-template-columns: 1fr 1fr; } }
@media (max-width: 520px) { .ftr-grid { grid-template-columns: 1fr; } }

/* ------------------------------------------------------- floating actions */
.wa {
  position: fixed; right: 20px; bottom: 20px; z-index: 60;
  width: 56px; height: 56px; border-radius: 50%; background: #25D366;
  display: grid; place-items: center; box-shadow: 0 8px 22px rgba(0, 0, 0, .22);
}
.wa svg { width: 30px; height: 30px; fill: #fff; }

/* Sticky mobile call bar — on a phone, the call IS the conversion. */
.quotebar { display: none; }
@media (max-width: 760px) {
  .quotebar {
    display: grid; grid-template-columns: 1fr 1fr; gap: 1px;
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 55;
    background: var(--line); border-top: 1px solid var(--line);
  }
  .quotebar a {
    background: var(--navy); color: #fff; text-align: center; padding: 15px 8px;
    font-weight: 600; font-size: 15px; text-decoration: none;
  }
  .quotebar a.alt { background: var(--sky); color: var(--navy-deep); }
  body { padding-bottom: 56px; }
  .wa { bottom: 70px; }
}

/* ---------------------------------------------------------- consent banner */
#sg-consent {
  position: fixed; left: 16px; right: 16px; bottom: 16px; z-index: 200;
  background: #fff; border: 1px solid var(--line); box-shadow: 0 14px 40px rgba(0, 0, 0, .2);
  padding: 18px 20px; display: flex; flex-wrap: wrap; gap: 14px;
  align-items: center; justify-content: space-between; max-width: 720px; margin-inline: auto;
}
#sg-consent p { margin: 0; font-size: 14px; color: var(--ink-soft); flex: 1 1 320px; }
.sg-consent-btns { display: flex; gap: 8px; }
#sg-consent button { font-family: var(--sans); font-size: 14px; font-weight: 600; padding: 10px 18px; cursor: pointer; border: 1px solid var(--navy); }
.sg-c-solid { background: var(--navy); color: #fff; }
.sg-c-ghost { background: transparent; color: var(--navy); }
@media (max-width: 760px) { #sg-consent { bottom: 72px; } }

/* ------------------------------------------------------------ demo banner */
/* Navy text on sky: readable at this size, and clearly not the header. */
.demo-banner {
  background: var(--sky); color: var(--navy-deep); text-align: center; padding: 9px 16px;
  font-size: 11px; font-weight: 700; letter-spacing: .12em; text-transform: uppercase;
}

/* ----------------------------------------------------------- scroll reveal
   Elements carry data-reveal; site.js swaps .rv for .rv.in as they enter.
   Hidden states apply ONLY under html.js.motion-ok, so no JS and reduced
   motion both mean: everything visible, nothing waiting on a script.      */
/* Scroll-LINKED reveal. --rp (0..1) comes from site.js and tracks the element's
   own position in the viewport, so motion follows the scroll continuously
   instead of firing once and stopping. --rs shifts a member's start point to
   stagger a group (built from the old --rd), so items in a row arrive in turn.
   No transition here on purpose: the scroll IS the timeline. */
html.js.motion-ok .rv {
  --rs: calc(var(--rd, 0s) * 1.6 / 1s);
  --p: clamp(0, calc((var(--rp, 1) - var(--rs)) / (1 - var(--rs))), 1);
  opacity: var(--p);
  transform: translateY(calc((1 - var(--p)) * 22px));
  will-change: opacity, transform;
}
/* No-JS and the IntersectionObserver fallback both land fully visible. */
html.js.motion-ok .rv.in { opacity: 1; transform: none; }

/* ------------------------------------------------------------- utilities */
.lead { font-size: clamp(17px, 1.7vw, 20px); }
.center { text-align: center; }
.mt-0 { margin-top: 0; } .mb-0 { margin-bottom: 0; }

/* ========================================================= FOLIO INTERIOR
   Components added when the homepage standard was carried through the rest
   of the folio: pull-leads, the works-covered card, the numbered FAQ, the
   sheet closes, the works programme, the gazetteer and the plate slots.
   Same locked palette, same drafting language — nothing new is invented. */

/* pull-lead — a section's strongest line, set like an annotation on the
   sheet. The words are the approved copy verbatim; only the size changes. */
.pull {
  font-family: var(--serif); font-size: clamp(20px, 2.3vw, 29px);
  line-height: 1.38; color: var(--ink); max-width: 26em;
  margin: 0 0 20px; padding-left: 20px; border-left: 3px solid var(--accent);
  text-wrap: balance;
}
.pull strong { font-weight: 600; }
.pull a { color: var(--navy); }

/* two-column section layout — heading + lead on the left, an exhibit on
   the right (the works-covered card, a map, a document). */
.duo { display: grid; grid-template-columns: minmax(0, .85fr) minmax(0, 1.15fr); gap: clamp(28px, 4.5vw, 72px); align-items: start; }
.duo > .duo-copy { position: sticky; top: 104px; }
@media (max-width: 880px) {
  .duo { grid-template-columns: 1fr; }
  .duo > .duo-copy { position: static; }
}

/* works-covered card — the scope of a service set out like the itemised
   paperwork SG actually produces. Sibling of .quote-doc on the homepage. */
.spec {
  background: #fff; border: 1px solid var(--line); box-shadow: 8px 8px 0 var(--line);
  padding: clamp(20px, 2.6vw, 30px) clamp(20px, 2.8vw, 36px);
}
.spec-head {
  display: flex; justify-content: space-between; align-items: baseline; gap: 16px;
  border-bottom: 2px solid var(--navy); padding-bottom: 10px; margin-bottom: 4px;
}
.spec-head b { font-family: var(--serif); font-size: 15.5px; font-weight: 700; color: var(--navy-deep); letter-spacing: .02em; }
.spec-head span { font-family: var(--sans); font-size: 10px; font-weight: 700; letter-spacing: .18em; text-transform: uppercase; color: var(--ink-soft); white-space: nowrap; }
.spec ul { list-style: none; margin: 0; padding: 0; }
.spec li {
  position: relative; padding: 12px 0 12px 44px;
  border-bottom: 1px solid var(--line); color: var(--ink-soft); font-size: 15px; line-height: 1.55;
}
.spec li:last-child { border-bottom: 0; }
.spec li::before {
  content: counter(spec-i, decimal-leading-zero); counter-increment: spec-i;
  position: absolute; left: 0; top: 13px;
  font-family: var(--serif); font-size: 18px; font-weight: 600; color: var(--navy);
}
.spec ul { counter-reset: spec-i; }
.spec li strong { color: var(--ink); }
.spec-note { margin: 0; padding-top: 14px; font-family: var(--sans); font-size: 13px; color: var(--ink-soft); }

/* note strip — a one-line section (e.g. references on request) set as a
   quiet ruled aside instead of pretending to be a full section. */
.note-strip {
  border-block: 1px solid var(--line); padding: 22px 0;
  display: flex; flex-wrap: wrap; gap: 10px 18px; align-items: baseline;
}
.note-strip b {
  font-family: var(--sans); font-size: 11px; font-weight: 700;
  letter-spacing: .2em; text-transform: uppercase; color: var(--navy);
  display: inline-flex; align-items: center; gap: 10px; white-space: nowrap;
}
.note-strip b::before { content: ""; width: 8px; height: 8px; background: var(--accent); }
.note-strip p { margin: 0; font-family: var(--serif); font-size: clamp(16px, 1.5vw, 19px); color: var(--ink); }

/* panel prose — body copy set on the navy board */
.panel .prose p, .panel .prose li { color: var(--board-ink); }
.panel .prose ul li { border-bottom-color: rgba(255, 255, 255, .16); }
.panel .prose ul li::before { background: var(--sky); }
.panel .prose ol li { border-bottom-color: rgba(255, 255, 255, .16); }
.panel .prose ol li::before { color: var(--sky); }
.panel .prose strong, .panel strong { color: var(--white); }
.panel a { color: var(--white); }
.panel .pull { color: var(--white); border-left-color: var(--sky); }
.panel .eyebrow { color: var(--sky); }
.panel .eyebrow::before { background: var(--sky); }

/* numbered FAQ — questions a homeowner actually reads down the page */
.faq summary { position: relative; padding-left: 62px; }
.faq .faq-n {
  position: absolute; left: 2px; top: 21px;
  font-family: var(--sans); font-style: normal; font-size: 10.5px; font-weight: 700;
  letter-spacing: .16em; color: var(--ink-soft);
}
.faq details > div { padding-left: 62px; }
.faq details[open] summary { color: var(--navy); }
.faq details[open] .faq-n { color: var(--navy); }
@media (max-width: 620px) {
  .faq summary { padding-left: 0; padding-top: 34px; }
  .faq .faq-n { top: 16px; }
  .faq details > div { padding-left: 0; }
}

/* sheet close — "the folio continues": neighbouring sheets by number */
.sheet-card {
  border: 1px solid var(--line); background: #fff; padding: 24px;
  display: flex; flex-direction: column; gap: 8px; text-decoration: none; color: inherit;
  transition: transform .22s ease, box-shadow .22s ease; position: relative;
}
.sheet-card:hover { transform: translateY(-4px); box-shadow: 8px 8px 0 var(--accent); }
.sheet-card .sc-no {
  font-family: var(--serif); font-size: clamp(30px, 3vw, 40px); line-height: 1;
  color: var(--navy); font-weight: 600;
}
.sheet-card .sc-kind {
  font-family: var(--sans); font-size: 10.5px; font-weight: 700; letter-spacing: .18em;
  text-transform: uppercase; color: var(--ink-soft);
}
.sheet-card h3 { margin: 2px 0 0; font-size: clamp(19px, 1.8vw, 23px); }
.sheet-card .card-go { margin-top: 10px; }

/* svc-side — the homepage service cards, grouped under the two halves of the
   business rather than run together. The heading rule carries the eye across so
   each group reads as a set. */
.svc-side + .svc-side { margin-top: clamp(30px, 4vw, 48px); }
.svc-side-head {
  display: flex; align-items: baseline; justify-content: space-between;
  gap: 16px; flex-wrap: wrap;
  padding-bottom: 10px; margin-bottom: 18px;
  border-bottom: 1px solid var(--line);
}
.svc-side-head .sc-kind {
  font-family: var(--sans); font-size: 11px; font-weight: 700; letter-spacing: .18em;
  text-transform: uppercase; color: var(--navy);
}
.svc-side-head a { font-size: 14px; }

/* ─── the blueprint layout (the /domestic/ page) ───────────────────────────
   Taken from the section rhythm Gary picked out of SG's Framer draft: an airy
   hero, then eyebrow + one large statement + a grid of blocks that each carry a
   real paragraph and their own link. Set in this site's white-and-blue palette,
   not the Framer cream — Gary moved off that deliberately. */
.bp-hero { padding-block: clamp(48px, 9vh, 104px) clamp(30px, 5vh, 56px); }
.bp-hero h1 {
  font-size: clamp(40px, 6.4vw, 88px); line-height: 1.02;
  letter-spacing: -.015em; margin: 14px 0 22px; max-width: 15ch;
}
.bp-hero .lead { max-width: 56ch; font-size: clamp(16px, 1.35vw, 19px); }

.bp-statement {
  font-size: clamp(27px, 3.5vw, 46px); line-height: 1.1;
  letter-spacing: -.01em; margin: 12px 0 0; max-width: 20ch;
}
.bp-grid {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(24px, 3.4vw, 52px); margin-top: clamp(30px, 4vw, 52px);
}
.bp-svc, .bp-why { margin: 0; padding-top: 22px; border-top: 2px solid var(--navy); }
.bp-svc h3, .bp-why h3 {
  font-size: clamp(21px, 2.1vw, 28px); margin: 0 0 10px; line-height: 1.15;
}
.bp-svc h3 a { text-decoration: none; color: inherit; }
.bp-svc h3 a:hover { color: var(--navy); }
.bp-svc p, .bp-why p { color: var(--ink-soft); margin: 0; font-size: 15.5px; line-height: 1.62; }
.bp-svc .card-go { margin-top: 14px; display: inline-block; }
.bp-all { margin-top: clamp(30px, 4vw, 46px); font-size: 16px; }

/* the arrow-in-a-square CTA from the same template */
.btn-arrow { display: inline-flex; align-items: center; gap: 12px; padding-left: 0; }
.btn-arrow i {
  display: grid; place-items: center; width: 42px; height: 42px;
  background: var(--navy); color: var(--white); font-style: normal; font-size: 17px;
  flex: 0 0 auto;
}
@media (max-width: 780px) {
  .bp-grid { grid-template-columns: minmax(0, 1fr); gap: 26px; }
  .bp-statement, .bp-hero h1 { max-width: none; }
}

/* door — one of the two halves of the business, on the homepage fork.
   Commercial left, domestic right. Each lists sectors or works in the words a
   caller would use, then states its own patch, because the two patches are
   genuinely different: commercial travels, domestic stays local. */
/* Pre-qualification certificates. The reserved state is styled as an obvious
   empty slot — a dashed hold, not a badge — so nobody mistakes it for a claim.
   The filled state leads on the certificate number and expiry date rather than
   a logo, because those are the bits a client can actually check. NOTE: this
   file ships verbatim, so the build gate reads these comments too — keep the
   banned trade-body words out of them. */
.accr-grid {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: 18px; margin-top: clamp(26px, 3.4vw, 40px);
}
.accr-item {
  border: 1px solid var(--line); background: #fff; padding: 24px;
  display: flex; flex-direction: column; gap: 10px;
}
.accr-item.is-reserved { border-style: dashed; background: transparent; }
.accr-reserved {
  font-family: var(--sans); font-size: 10px; font-weight: 700; letter-spacing: .18em;
  text-transform: uppercase; color: var(--ink-soft);
}
.accr-item h3 { margin: 0; font-size: clamp(19px, 1.8vw, 24px); }
.accr-item p { margin: 0; font-size: 14.5px; color: var(--ink-soft); line-height: 1.6; }
.accr-meta { margin: 6px 0 0; display: grid; grid-template-columns: auto 1fr; gap: 5px 14px; }
.accr-meta dt {
  font-family: var(--sans); font-size: 10px; font-weight: 700; letter-spacing: .14em;
  text-transform: uppercase; color: var(--ink-soft); align-self: center;
}
.accr-meta dd { margin: 0; font-size: 15px; font-variant-numeric: tabular-nums; }
.accr-item .card-go { margin-top: auto; padding-top: 12px; }

/* The commercial specialist box — Gary's sector line, in its own box on the
   main page rather than buried inside the commercial door. Navy so it reads as
   a statement, not another card. */
.spec-box {
  background: var(--navy-deep); color: var(--white);
  padding: clamp(26px, 4vw, 46px);
  display: flex; flex-direction: column; gap: 16px; align-items: flex-start;
}
.spec-tag {
  font-family: var(--sans); font-size: 10.5px; font-weight: 700;
  letter-spacing: .2em; text-transform: uppercase; color: var(--sky);
}
.spec-line {
  margin: 0; max-width: 30ch;
  font-family: var(--serif); font-size: clamp(23px, 3.1vw, 40px);
  line-height: 1.2; letter-spacing: -.005em; color: var(--white);
}
.spec-line strong { color: var(--white); font-weight: 600; }
.spec-box .card-go { color: var(--sky); }
.spec-box .card-go:hover { color: var(--white); }

/* The patch statement inside each door — labelled and given weight, because
   the two sides travel very different distances and that difference is a
   promise, not a detail. */
.door-patch {
  margin-top: 16px; padding-top: 14px; border-top: 1px solid var(--line);
}
.door-patch span {
  display: block; font-family: var(--sans); font-size: 9.5px; font-weight: 700;
  letter-spacing: .18em; text-transform: uppercase; color: var(--navy);
  margin-bottom: 6px;
}
.door-patch p { margin: 0; font-size: 13.5px; line-height: 1.55; color: var(--ink-soft); }
.door-patch strong { color: var(--ink); }

/* Commercial LEFT, domestic RIGHT — at every width, phones included.
   These deliberately do NOT use .grid-2, which collapses to a single column
   under 620px and stacked the two sides on a phone. Gary's instruction is
   left/right, so the columns hold and the type steps down instead. */
.doors {
  display: grid; grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: clamp(10px, 2.6vw, 34px);
}

/* The minimal door (James, 22 Jul): the word is the button. One big centred
   word, whole box clickable, nothing else inside. */
.door-min {
  align-items: center; justify-content: center; text-align: center;
  text-decoration: none; min-height: clamp(96px, 14vh, 150px);
}
.door-min h2, .door-min h3 { margin: 0; font-size: clamp(30px, 4.2vw, 52px); }
/* the word carries the box: white on the navy board, sky on hover — the old
   rules coloured an inner link that no longer exists */
.hero .door-min h2, .hero .door-min h3 { color: var(--white); transition: color .2s ease; }
.hero .door-min:hover h2, .hero .door-min:hover h3 { color: var(--sky); }

/* ---- the fork, sitting in the blue under the drawing -----------------------
   The drawing only ever fills the middle of the sheet. The two doors take the
   run beneath it rather than opening a new section below the fold, so the
   choice between the two halves of the business is on screen from the start.
   On the board they are drawn as sheet panels — ruled in the light blue of the
   drawing, not white cards, which would punch two holes in the board. */
.hero-doors {
  position: relative; z-index: 2;
  width: min(100% - (var(--gut) * 2), var(--wrap));
  margin-inline: auto;
  padding-bottom: clamp(20px, 3.2vh, 34px);
}
.hero .door {
  background: rgba(255, 255, 255, .045);
  border-color: rgba(169, 183, 230, .34);
  padding: clamp(16px, 1.9vw, 24px);
  gap: 6px;
  backdrop-filter: blur(2px);
  transition: background .25s ease, border-color .25s ease, transform .25s ease;
}
.hero .door:hover {
  background: rgba(255, 255, 255, .085);
  border-color: rgba(169, 183, 230, .62);
  transform: translateY(-2px);
}
.hero .door .sc-kind { color: var(--sky); }
.hero .door h3 { font-size: clamp(22px, 2.5vw, 32px); }
.hero .door h3 a { color: var(--white); }
.hero .door h3 a:hover { color: var(--sky); }
.hero .door-line { color: var(--board-ink); font-size: 14px; }
.hero .door-covers {
  margin-top: 10px; padding-top: 10px;
  border-top: 1px solid rgba(169, 183, 230, .28);
}
.hero .door-covers span { color: var(--sky); }
.hero .door-covers p { color: var(--board-ink); font-size: 13.5px; line-height: 1.55; }
.hero .door .card-go { color: var(--white); padding-top: 12px; }
.hero .door .card-go:hover { color: var(--sky); }

/* The board now shares its height with the fork, so the drawing takes the room
   it needs and no more.

   The film is normally absolute (inset:0 of the board) so it can fill the whole
   sheet. Absolute means it contributes NO height, so the board stretched on
   flex:1 and dropped the doors to the foot of the stage — the big blue gap.
   With the fork present the drawing goes back into flow: the board is then
   exactly as tall as the mark plus the drawing, and the doors sit directly
   beneath it whatever the screen height. Kept `relative`, not `static`, because
   .hero-media anchors to it. */
.hero-stage:has(.hero-doors) { justify-content: center; }
.hero-stage:has(.hero-doors) .hero-board {
  flex: 0 1 auto;
  padding: clamp(16px, 2.6vh, 30px) 0 0;
}
.hero-live .hero-stage:has(.hero-doors) .hero-draw {
  position: relative; inset: auto; padding: clamp(6px, 1.4vh, 16px) 0 0;
}
/* mark + drawing + fork all have to clear 100svh, so the drawing takes what is
   left rather than a fixed share of the viewport */
.hero-stage:has(.hero-doors) .hero-draw svg { max-height: min(36vh, 340px); }
/* The doors sit directly under the drawn LINE, not under the svg box. At rest
   the svg carries roughly 11% of its rendered height as empty room below the
   ink, because later beats of the film use that part of the sheet — left alone
   it reads as a gap. The pull-up cancels that dead room and leaves ~12px, so the
   fork tucks under the drawing without cropping the legs of it.
   It is set in px per height band rather than in vh because the drawing's
   height is px-capped at each band, so the dead room does not scale with vh. */
.hero-doors { padding-top: 0; margin-top: -25px; }

/* The cue sat at the foot of the stage, which is now where the fork lives — it
   landed on top of the doors and ran off the bottom. The doors themselves show
   there is more page here, so the cue is not needed once they are present. */
.hero-stage:has(.hero-doors) .hero-cue { display: none; }

/* Short screens — a 1280x700 laptop is the tight case, not a narrow one. What
   each side covers is the first thing to go: it is named again in full on that
   side's own page, one click away, whereas a door clipped by the fold is a
   dead end. Keyed to height because that is the constraint that actually
   binds here. */
/* 1440x900 is the commonest desktop and the drawing at full size left only
   19px under the doors — enough to clip on a different font render. The
   drawing gives up the room before the copy does. */
@media (max-height: 940px) {
  .hero-stage:has(.hero-doors) .hero-draw svg { max-height: min(30vh, 250px); }
  .hero-doors { margin-top: -17px; }
}
@media (max-height: 860px) {
  .hero .door-covers { display: none; }
}
@media (max-height: 700px) {
  .hero .door-line { display: none; }
  .hero-stage:has(.hero-doors) .hero-draw svg { max-height: min(24vh, 190px); }
  .hero-doors { margin-top: -10px; }
}

@media (max-width: 900px) {
  .hero-stage:has(.hero-doors) .hero-draw svg { max-height: min(28vh, 260px); }
  .hero .door h3 { font-size: clamp(18px, 4.4vw, 26px); }
  .hero .door-covers { display: none; }   /* the one-line summary carries it on small screens */
}
/* Phones: the stage has to hold the mark, the drawing and both doors above the
   fixed call bar, so the doors carry only what a thumb needs — which side this
   is, and the way in. */
@media (max-width: 620px) {
  .hero-stage:has(.hero-doors) .hero-draw svg { max-height: min(22vh, 200px); }
  /* clear the fixed .quotebar (55px) so the second door's link is tappable */
  .hero-doors { padding-bottom: 74px; margin-top: -12px; }
  .hero .door { padding: 12px 11px; gap: 4px; }
  /* The word IS the box here, and each box is only half the screen. At the base
     30px floor "Commercial" (10 letters) is wider than its half-width box and
     spilled into the Domestic box. Scale the word to the viewport so the longest
     one always fits; both doors share the rule so the pair stays balanced. */
  .hero .door-min h2, .hero .door-min h3 { font-size: clamp(21px, 6.6vw, 30px); }
  /* "For operators, estates teams and managing agents" wraps to three lines at
     this width while "For homeowners, direct" takes one, which pushed the two
     titles out of line with each other. The titles say which side is which on
     their own, so the qualifier goes and the pair reads level. */
  .hero .door .sc-kind { display: none; }
  .hero .door-line { display: none; }
  .hero .door .card-go { font-size: 12px; padding-top: 10px; }
}
.door {
  border: 1px solid var(--line); background: #fff; padding: clamp(22px, 3vw, 34px);
  display: flex; flex-direction: column; gap: 10px;
}
.door-line { font-size: 15px; color: var(--ink-soft); margin: 0; }
.door .sc-kind {
  font-family: var(--sans); font-size: 10.5px; font-weight: 700; letter-spacing: .18em;
  text-transform: uppercase; color: var(--ink-soft);
}
.door h3 { margin: 2px 0 0; font-size: clamp(26px, 3.2vw, 40px); line-height: 1.05; }
/* Phones. "Commercial" is one unbreakable word: two columns on a 375px screen
   leave it ~138px, and the base rule's 26px floor needs 150px, so it clipped.
   This override MUST sit after the base rule — the earlier 620px block above is
   before it in the file, and at equal specificity the later rule wins. */
.door-h {
  font-family: var(--sans); font-size: 10.5px; font-weight: 700; letter-spacing: .16em;
  text-transform: uppercase; color: var(--navy); margin: 14px 0 0;
  padding-top: 14px; border-top: 1px solid var(--line);
}
.door-covers { margin-top: 14px; padding-top: 14px; border-top: 1px solid var(--line); }
.door-patch span {
  display: block; font-family: var(--sans); font-size: 10px; font-weight: 700;
  letter-spacing: .16em; text-transform: uppercase; color: var(--navy);
  margin-bottom: 6px;
}
.door-covers p { margin: 0; font-size: 14.5px; line-height: 1.6; color: var(--ink-soft); }
.door-geo {
  margin: 16px 0 0; padding-top: 14px; border-top: 1px solid var(--line);
  font-size: 13.5px; color: var(--ink-soft);
}
.door .card-go { margin-top: auto; padding-top: 18px; }
@media (max-width: 620px) {
  .door h3 { font-size: clamp(13px, 3.9vw, 22px); line-height: 1.1; }
  .doors { gap: 8px; }
  .door { padding: 14px 10px; gap: 7px; }
  .door .sc-kind { font-size: 8.5px; letter-spacing: .12em; }
  .door-line { font-size: 13px; }
  .door-h { font-size: 9px; margin-top: 10px; padding-top: 10px; }
  .door-list { gap: 5px; margin-top: 8px; }
  .door-list li { font-size: 13px; padding-left: 13px; line-height: 1.4; }
  .door-list li::before { width: 5px; }
  .door-patch { margin-top: 11px; padding-top: 10px; }
  .door-patch span { font-size: 8.5px; }
  .door-patch p { font-size: 11.5px; line-height: 1.45; }
  .door .card-go { font-size: 12px; padding-top: 12px; }
}
.door h3 a { text-decoration: none; color: inherit; }
.door h3 a:hover { color: var(--navy); }
/* The door now names what a side covers in one line rather than listing every
   subcategory — the full list lives on that side's own page (.sub-grid). */
/* Label above the one-line "what this side covers" summary. It shared a rule
   with .door-patch span; that rule was split when the base .door rules were
   reordered, leaving this selector dangling with no declaration block — which
   silently swallowed the rule after it. Kept complete on its own now. */
.door-covers span {
  display: block; font-family: var(--sans); font-size: 10px; font-weight: 700;
  letter-spacing: .16em; text-transform: uppercase; color: var(--navy);
  margin-bottom: 6px;
}

/* .quick — the jump row at the top of a side page. Small links, so every option
   is reachable without scrolling past the intro copy to find it. Sticks under
   the header on the way down so it stays available while you read. */
.quick {
  position: sticky; top: 0; z-index: 40;
  background: var(--paper); border-bottom: 1px solid var(--line);
  padding: 11px 0;
}
.quick .wrap { display: flex; align-items: center; gap: 14px; }
.quick-lab {
  flex: none;
  font-family: var(--sans); font-size: 10px; font-weight: 700; letter-spacing: .16em;
  text-transform: uppercase; color: var(--ink-soft);
}
.quick ul {
  list-style: none; margin: 0; padding: 0;
  display: flex; gap: 7px; flex-wrap: nowrap;
  overflow-x: auto; scrollbar-width: none; -webkit-overflow-scrolling: touch;
}
.quick ul::-webkit-scrollbar { display: none; }
.quick li { flex: none; }
.quick a {
  display: block; white-space: nowrap;
  padding: 6px 12px; font-size: 13px; text-decoration: none;
  color: var(--ink); background: #fff; border: 1px solid var(--line);
  transition: border-color .16s ease, color .16s ease;
}
.quick a:hover, .quick a:focus-visible { border-color: var(--navy); color: var(--navy); }
@media (max-width: 700px) {
  .quick .wrap { gap: 10px; }
  .quick-lab { display: none; }
}

/* .sub-grid — the subcategories laid out on the side page. This is what you get
   for clicking a door: one card per sector or work, each going somewhere it is
   written about. */
.sub-grid {
  display: grid; grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: 18px; margin-top: clamp(26px, 3.4vw, 42px);
}
.sub-card {
  border: 1px solid var(--line); background: #fff; padding: 26px 24px 24px;
  display: flex; flex-direction: column; gap: 9px;
  text-decoration: none; color: inherit; position: relative;
  transition: transform .2s ease, box-shadow .2s ease;
}
.sub-card:hover { transform: translateY(-3px); box-shadow: 7px 7px 0 var(--accent); }
.sub-no {
  font-family: var(--serif); font-size: 26px; line-height: 1;
  color: var(--navy); font-weight: 600;
}
.sub-card h3 { margin: 0; font-size: clamp(19px, 1.9vw, 23px); line-height: 1.2; }
.sub-card p { margin: 0; font-size: 14.5px; line-height: 1.6; color: var(--ink-soft); }
.sub-card .card-go { margin-top: auto; padding-top: 12px; }
/* Scoped to a RANGE, not just max-width. As a plain max-width:780px rule it
   also matched phones, and being later in the file with equal specificity it
   beat the 620px rule below and clipped "Commercial". Tablets only. */
@media (min-width: 621px) and (max-width: 780px) { .door h3 { font-size: 30px; } }

/* side — one half of the business on the homepage. Deliberately NOT a
   .sheet-card: a sheet-card is itself a link, and this block contains a list of
   links, which cannot be nested inside an anchor. Same visual language, real
   markup. margin-top:auto on the closing link keeps both blocks' "Open the …"
   sitting on the same line when one side lists more pages than the other. */
.side {
  border: 1px solid var(--line); background: #fff; padding: 26px;
  display: flex; flex-direction: column; gap: 10px;
}
.side .sc-kind {
  font-family: var(--sans); font-size: 10.5px; font-weight: 700; letter-spacing: .18em;
  text-transform: uppercase; color: var(--ink-soft);
}
.side h3 { margin: 2px 0 0; font-size: clamp(21px, 2vw, 26px); }
.side h3 a { text-decoration: none; color: inherit; }
.side h3 a:hover { color: var(--navy); }
.side > p { font-size: 14.5px; color: var(--ink-soft); margin: 0; }
.side-links {
  list-style: none; padding: 0; margin: 4px 0 0;
  display: flex; flex-wrap: wrap; gap: 8px;
}
.side-links a {
  display: inline-block; padding: 6px 11px; border: 1px solid var(--line);
  font-size: 13px; text-decoration: none; color: var(--ink); background: var(--paper);
  transition: border-color .18s ease, color .18s ease;
}
.side-links a:hover { border-color: var(--navy); color: var(--navy); }
.side .card-go { margin-top: auto; padding-top: 14px; }

/* plate — a reserved photography slot, honestly labelled. A real photo of
   SG's own work replaces the .frame; the caption panel stays. */
.plate { display: grid; grid-template-columns: minmax(0, 1.1fr) minmax(0, .9fr); border: 1px solid var(--line); background: var(--paper); }
.plate .frame { aspect-ratio: 16 / 9; border: 0; border-right: 1px solid var(--line); height: 100%; }
.plate-cap { padding: clamp(22px, 3vw, 36px); display: flex; flex-direction: column; gap: 10px; justify-content: center; }
.plate-cap .folio-no { color: var(--ink-soft); }
.plate-cap h3 { margin: 4px 0 0; font-size: clamp(20px, 1.9vw, 25px); }
.plate-cap p { margin: 0; font-size: 14px; color: var(--ink-soft); max-width: 44ch; }
@media (max-width: 720px) {
  .plate { grid-template-columns: 1fr; }
  .plate .frame { border-right: 0; border-bottom: 1px solid var(--line); }
}

/* works programme — the five steps as stations on a drawn line */
.prog { position: relative; margin-top: clamp(28px, 4vw, 52px); }
.prog::before {
  content: ""; position: absolute; left: 27px; top: 10px; bottom: 10px; width: 1px;
  background: var(--line);
}
.prog-step { position: relative; display: grid; grid-template-columns: 76px 1fr; gap: clamp(16px, 2.5vw, 30px); padding: clamp(20px, 3vw, 32px) 0; }
.prog-no {
  position: relative; font-family: var(--serif); font-size: clamp(30px, 3.4vw, 44px);
  line-height: 1; color: var(--navy); font-weight: 600;
  background: transparent; align-self: start;
}
.prog-no::before {
  content: ""; position: absolute; left: 21px; top: -12px; width: 13px; height: 13px;
  background: var(--white); border: 1px solid var(--accent);
}
/* the numeral masks the drawn line as it passes behind (steps sit on cream) */
.prog-no b { position: relative; display: inline-block; background: var(--white); padding-right: 8px; }
.prog-body h3 { font-size: clamp(21px, 2vw, 27px); margin-bottom: 8px; }
.prog-body p { color: var(--ink-soft); max-width: 62ch; }
.prog-body p:last-child { margin-bottom: 0; }
.prog-step.is-feature { grid-template-columns: 1fr; padding-block: clamp(10px, 1.6vw, 18px); }
.prog-step.is-feature .prog-board {
  background: var(--navy-deep); color: var(--white); position: relative; overflow: hidden;
  padding: clamp(26px, 4vw, 48px); display: grid;
  grid-template-columns: minmax(0, 1fr); align-items: center;
}
.prog-step.is-feature .prog-board::before {
  content: ""; position: absolute; inset: 0; pointer-events: none; opacity: .16;
  background-image:
    linear-gradient(to right, rgba(169, 183, 230,.28) 1px, transparent 1px),
    linear-gradient(to bottom, rgba(169, 183, 230,.28) 1px, transparent 1px);
  background-size: 48px 48px;
  mask-image: radial-gradient(ellipse at 75% 25%, #000 20%, transparent 78%);
  -webkit-mask-image: radial-gradient(ellipse at 75% 25%, #000 20%, transparent 78%);
}
.prog-step.is-feature .prog-board > * { position: relative; }
.prog-step.is-feature h3 { color: var(--white); }
.prog-step.is-feature p { color: var(--board-ink); }
.prog-step.is-feature .prog-tag {
  font-family: var(--sans); font-size: 11px; font-weight: 700; letter-spacing: .2em;
  text-transform: uppercase; color: var(--sky); display: block; margin-bottom: 10px;
}
@media (max-width: 880px) {
  .prog::before { left: 17px; }
  .prog-step { grid-template-columns: 52px 1fr; }
  .prog-no { font-size: 27px; }
  .prog-no::before { left: 11px; }
  .prog-step.is-feature { grid-template-columns: 1fr; }
  .prog-step.is-feature .prog-board { grid-template-columns: 1fr; }
}

/* gazetteer — the areas index: every town, one line each, from its own sheet */
.gaz { margin-top: clamp(22px, 3vw, 38px); border-top: 1px solid var(--line); display: grid; grid-template-columns: 1fr 1fr; column-gap: clamp(28px, 5vw, 80px); }
@media (max-width: 880px) { .gaz { grid-template-columns: 1fr; } }
.gaz a {
  display: grid; grid-template-columns: 44px minmax(0, 1fr) auto; gap: 14px; align-items: baseline;
  padding: 15px 2px; border-bottom: 1px solid var(--line);
  text-decoration: none; color: inherit; transition: background .16s ease;
}
.gaz a:hover { background: #fff; }
.gaz .gz-no { font-family: var(--sans); font-size: 10.5px; font-weight: 700; letter-spacing: .14em; color: var(--ink-soft); }
.gaz .gz-town { font-family: var(--serif); font-size: clamp(18px, 1.7vw, 22px); font-weight: 600; color: var(--ink); display: block; }
.gaz .gz-line { display: block; font-size: 13px; color: var(--ink-soft); margin-top: 2px; }
.gaz .gz-go { font-size: 15px; color: var(--navy); transition: transform .16s ease; }
.gaz a:hover .gz-go { transform: translateX(4px); }
.gaz a:hover .gz-town { color: var(--navy); }

/* service hub — grouped sheets */
.svc-group { display: flex; align-items: baseline; gap: 18px; margin: clamp(40px, 6vw, 64px) 0 20px; }
.svc-group:first-of-type { margin-top: 0; }
.svc-group h2 { font-size: clamp(22px, 2.3vw, 30px); margin: 0; white-space: nowrap; }
.svc-group i {
  font-style: normal; font-family: var(--sans); font-size: 10.5px; font-weight: 700;
  letter-spacing: .18em; text-transform: uppercase; color: var(--ink-soft); white-space: nowrap;
}
.svc-group::after { content: ""; flex: 1; height: 1px; background: var(--line); transform: translateY(-4px); }

/* feature card — the commercial sheet, carried by a real photograph */
.feature-card {
  display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  background: var(--navy-deep); color: var(--white); text-decoration: none;
  position: relative; overflow: hidden; margin-top: 20px;
  transition: box-shadow .22s ease, transform .22s ease;
}
.feature-card:hover { transform: translateY(-4px); box-shadow: 10px 10px 0 var(--accent); }
.feature-card figure { margin: 0; position: relative; min-height: 260px; }
.feature-card img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.feature-card figcaption {
  position: absolute; left: 0; bottom: 0; right: 0; padding: 10px 16px;
  background: rgba(33, 33, 80, .82); color: var(--board-ink);
  font-family: var(--sans); font-size: 11px; font-weight: 700; letter-spacing: .14em; text-transform: uppercase;
}
.fc-copy { position: relative; padding: clamp(26px, 4vw, 52px); display: flex; flex-direction: column; gap: 10px; justify-content: center; }
.fc-copy::before {
  content: ""; position: absolute; inset: 0; pointer-events: none; opacity: .16;
  background-image:
    linear-gradient(to right, rgba(169, 183, 230,.28) 1px, transparent 1px),
    linear-gradient(to bottom, rgba(169, 183, 230,.28) 1px, transparent 1px);
  background-size: 48px 48px;
  mask-image: radial-gradient(ellipse at 80% 20%, #000 20%, transparent 75%);
  -webkit-mask-image: radial-gradient(ellipse at 80% 20%, #000 20%, transparent 75%);
}
.fc-copy > * { position: relative; }
.fc-copy .sc-kind { color: var(--sky); font-family: var(--sans); font-size: 10.5px; font-weight: 700; letter-spacing: .18em; text-transform: uppercase; }
.fc-copy h3 { color: var(--white); font-size: clamp(23px, 2.4vw, 32px); margin: 0; }
.fc-copy p { color: var(--board-ink); font-size: 15px; margin: 0; max-width: 46ch; }
.fc-copy .card-go { color: var(--sky); margin-top: 8px; font-size: 13px; font-weight: 700; letter-spacing: .08em; text-transform: uppercase; }
@media (max-width: 780px) {
  .feature-card { grid-template-columns: 1fr; }
  .feature-card figure { min-height: 210px; }
}

/* mini patch — "you are here" board pinned under a town's title block */
.sheet-side { position: sticky; top: 96px; }
.sheet-side .tblock { position: static; }
@media (max-width: 880px) { .sheet-side { position: static; } }
.patch-mini { margin-top: 16px; border: 1px solid var(--ink); pointer-events: none; }
.patch-mini .patch { padding: 10px 10px 2px; }
.patch-mini .patch text { display: none; }
.patch-mini .patch .pm-hl text, .patch-mini .patch .pm-base-text { display: block; }
.patch-mini .patch .pm-hl text { font-size: 23px; font-weight: 800; }
.patch-mini .patch .pm-base-text { font-size: 19px; }
.patch-mini .patch .pm-dot { fill: rgba(255, 255, 255, .5); r: 6px; }
.patch-mini .patch .pm-hl .pm-dot { fill: var(--sky); r: 8px; }
.patch-mini .patch .pm-base-dot { r: 9px; }
.patch-mini .patch-note {
  margin: 0; padding: 8px 12px 10px; border-top: 1px solid var(--board-line);
  color: var(--board-ink); background: var(--navy-deep);
}
.patch-mini .patch-board { padding-bottom: 4px; }

/* map card — the office on a real map, privacy-clean (a still image built
   from OpenStreetMap tiles; Google Maps only opens on the visitor's click) */
.map-card { margin-top: 16px; border: 1px solid var(--ink); background: var(--paper); }
.map-card > a { display: block; }
.map-card img { display: block; width: 100%; aspect-ratio: 4 / 3; object-fit: cover; }
.map-cap { border-top: 1px solid var(--ink); padding: 14px 16px; display: flex; flex-wrap: wrap; gap: 12px 18px; align-items: center; justify-content: space-between; }
.map-cap p { margin: 0; font-family: var(--sans); font-size: 13.5px; color: var(--ink); font-weight: 600; }
.map-cap p span { display: block; font-weight: 400; font-size: 11px; color: var(--ink-soft); margin-top: 3px; }
.map-cap .btn { padding: 11px 18px; font-size: 14px; }

/* privacy — contents list and reading measure */
.toc { border: 1px solid var(--line); background: #fff; padding: 22px 26px; max-width: 68ch; }
.toc b {
  display: block; font-family: var(--sans); font-size: 11px; font-weight: 700;
  letter-spacing: .2em; text-transform: uppercase; color: var(--navy); margin-bottom: 12px;
}
.toc ol { list-style: none; margin: 0; padding: 0; columns: 2; column-gap: 36px; }
.toc li { break-inside: avoid; border-bottom: 1px solid var(--line); }
.toc li:last-child { border-bottom: 0; }
.toc a {
  display: flex; gap: 10px; align-items: baseline; padding: 8px 2px;
  font-size: 14px; text-decoration: none; color: var(--ink);
}
.toc a i { font-style: normal; font-family: var(--sans); font-size: 10px; font-weight: 700; color: var(--ink-soft); letter-spacing: .1em; }
.toc a:hover { color: var(--navy); text-decoration: underline; }
@media (max-width: 620px) { .toc ol { columns: 1; } }
.legal .prose h2 { font-size: clamp(21px, 2vw, 27px); margin-top: 0; }
.legal .sec-tight { padding-block: clamp(22px, 3.4vw, 40px); }

/* ========================================================= THE WORKS LEDGER
   /work/ hub, /work/<slug>/ job records, the homepage journey and the
   testimonial ledger. Same locked palette, same drafting language: records
   are numbered, reserved slots are drawn empty plates, the during-the-build
   stage sits on the navy board. Nothing here invents a colour or a corner. */

.wk-kicker {
  font-family: var(--sans); font-size: 11px; font-weight: 700;
  letter-spacing: .18em; text-transform: uppercase; color: var(--ink-soft);
  display: block;
}

/* filter rail — drafting tab-stops on a ruled baseline. Pure enhancement:
   without JS the rail does not show and every record is simply visible. */
.wk-filter { display: none; }
html.js .wk-filter {
  display: flex; flex-wrap: wrap; align-items: baseline; gap: 2px 6px;
  border-bottom: 1px solid var(--line); padding-bottom: 0;
  margin-bottom: clamp(24px, 3.4vw, 40px);
}
.wk-tab {
  appearance: none; background: none; border: 0; cursor: pointer;
  font-family: var(--sans); font-size: 13.5px; font-weight: 600; color: var(--ink-soft);
  padding: 10px 12px 12px; position: relative;
}
.wk-tab::after {
  content: ""; position: absolute; left: 12px; right: 12px; bottom: -1px; height: 2px;
  background: var(--accent); transform: scaleX(0); transform-origin: left; transition: transform .2s ease;
}
.wk-tab:hover { color: var(--navy); }
.wk-tab:hover::after { transform: scaleX(1); }
.wk-tab[aria-pressed="true"] { color: var(--navy); }
.wk-tab[aria-pressed="true"]::after { transform: scaleX(1); }
.wk-status {
  margin-left: auto; font-family: var(--sans); font-size: 11px; font-weight: 700;
  letter-spacing: .14em; text-transform: uppercase; color: var(--ink-soft); padding: 10px 0 12px;
}
@media (max-width: 680px) { .wk-status { display: none; } }

/* the ledger grid — real records large, reserved slots quarter-width */
.wk-grid { display: grid; grid-template-columns: repeat(12, 1fr); gap: 18px; }
.wk-grid [hidden] { display: none !important; }
.wk-card {
  grid-column: span 6; background: #fff; border: 1px solid var(--line);
  display: flex; flex-direction: column; text-decoration: none; color: inherit;
  transition: transform .22s ease, box-shadow .22s ease;
}
.wk-card:hover { transform: translateY(-4px); box-shadow: 8px 8px 0 var(--sky); }
.wk-card figure { margin: 0; position: relative; }
.wk-card img { width: 100%; aspect-ratio: 3 / 2; object-fit: cover; border-bottom: 1px solid var(--line); }
.wk-card figcaption {
  position: absolute; left: 0; right: 0; bottom: 0; padding: 8px 16px;
  background: rgba(33, 33, 80, .84); color: var(--board-ink);
  font-family: var(--sans); font-size: 10.5px; font-weight: 700; letter-spacing: .14em; text-transform: uppercase;
}
.wk-card-copy { padding: 22px 24px 24px; display: flex; flex-direction: column; gap: 8px; }
.wk-card-copy h3 { margin: 0; font-size: clamp(21px, 2vw, 27px); }
.wk-card-copy p { margin: 0; font-size: 14.5px; color: var(--ink-soft); }
.wk-card-copy .card-go { margin-top: 8px; }
.wk-card:hover h3 { color: var(--navy); }

/* reserved slot — the honest empty plate. Deliberate, drawn, labelled;
   it disappears the moment a real record of its type exists. */
.wk-slot {
  grid-column: span 3; background: var(--paper); border: 1px solid var(--line);
  padding: 16px 16px 20px; display: flex; flex-direction: column; gap: 8px;
}
/* the plate grows to soak up any spare height (grid rows stretch), so a
   tall slot reads as a bigger reserved plate, never as a stranded gap.
   Shares the reserved-plate treatment with .frame: hatched ground +
   clearing (the grouped ::before/::after rules), mounting corners, mark. */
.wk-slot-frame {
  position: relative; flex: 1 1 auto; min-height: 180px; margin-bottom: 8px;
  border: 1px solid var(--line); background: var(--paper);
  display: grid; place-content: center; overflow: hidden;
}
.wk-slot-frame .frame-corners { inset: 8px; }
.wk-slot-frame .frame-corners i { width: 12px; height: 12px; }
.wk-slot-frame .frame-mark { font-size: 16px; }
/* An indicative image carrying a reserved slot: the photograph fills the
   plate edge to edge; the hatched ground and clearing are suppressed so the
   image reads clean under its corners, mark and Indicative tag. */
.wk-slot-img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.wk-slot.has-ind .wk-slot-frame::before,
.wk-slot.has-ind .wk-slot-frame::after { content: none; }
.wk-slot.has-ind .wk-slot-frame .ind-tag { top: auto; bottom: 8px; left: 8px; }
.frame.is-ind { padding: 0; display: block; }
.frame.is-ind::before, .frame.is-ind::after { content: none; }
.plate-img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.wk-slot h3 { margin: 0; font-size: clamp(18px, 1.6vw, 21px); }
.wk-slot p { margin: 0; font-size: 13px; color: var(--ink-soft); }
.wk-slot a {
  margin-top: auto; padding-top: 10px; font-family: var(--sans); font-size: 12.5px;
  font-weight: 700; color: var(--navy); text-decoration: none;
}
.wk-slot a:hover { text-decoration: underline; }
@media (max-width: 980px) {
  .wk-card { grid-column: span 12; }
  .wk-slot { grid-column: span 6; }
}
@media (max-width: 560px) {
  /* one line each: the plate at the left, the record's label beside it */
  .wk-slot { grid-column: span 12; display: grid; grid-template-columns: 96px minmax(0, 1fr); column-gap: 16px; row-gap: 4px; align-items: start; }
  .wk-slot-frame { grid-row: 1 / span 4; align-self: stretch; min-height: 96px; margin: 0; }
  .wk-slot > :not(.wk-slot-frame) { grid-column: 2; }
  .wk-slot a { margin-top: 4px; padding-top: 0; }
}

/* stage tag + the during-the-build board */
.wk-stage-tag {
  display: inline-flex; align-items: center; gap: 10px; margin-top: 12px;
  font-family: var(--sans); font-size: 11px; font-weight: 700; letter-spacing: .2em;
  text-transform: uppercase; color: var(--ink-soft);
}
.wk-stage-tag::before { content: ""; width: 8px; height: 8px; background: var(--accent); }
.wk-board { padding: clamp(24px, 3.6vw, 52px); }
.wk-board .wk-stage-tag { color: var(--sky); }
.wk-board .folio-no { color: var(--sky); }
.wk-board .prose p { color: var(--board-ink); }
.wk-board .work-item img { border-color: var(--board-line); }
.wk-board .work-item figcaption { color: var(--board-ink); }
.wk-board .work-item figcaption b { color: var(--sky); }

/* stage-band composition — full plates and pairs (see stage_band in build.py) */
.work-item.w-full { grid-column: span 12; }
.work-item.w-half { grid-column: span 6; }
.work-item.w-full img { aspect-ratio: 16 / 9; }
@media (max-width: 880px) { .work-item.w-full, .work-item.w-half { grid-column: span 12; } }

/* the job story — brief / challenge / what we did / outcome as stations
   on the same drawn line the works programme uses */
.cs { position: relative; margin-top: clamp(24px, 3.4vw, 44px); }
.cs::before { content: ""; position: absolute; left: 27px; top: 10px; bottom: 10px; width: 1px; background: var(--line); }
.cs-step { position: relative; display: grid; grid-template-columns: 76px 1fr; gap: clamp(16px, 2.5vw, 30px); padding: clamp(18px, 2.6vw, 28px) 0; }
.cs-no { position: relative; font-family: var(--serif); font-size: clamp(30px, 3.4vw, 44px); line-height: 1; color: var(--navy); font-weight: 600; align-self: start; }
.cs-no::before { content: ""; position: absolute; left: 21px; top: -12px; width: 13px; height: 13px; background: var(--white); border: 1px solid var(--accent); }
.cs-no b { position: relative; display: inline-block; background: var(--white); padding-right: 8px; }
.cs-body .wk-kicker { margin-bottom: 6px; }
.cs-body h3 { font-size: clamp(21px, 2vw, 27px); margin-bottom: 8px; }
.cs-body p { color: var(--ink-soft); max-width: 62ch; margin: 0; }
@media (max-width: 880px) {
  .cs::before { left: 17px; }
  .cs-step { grid-template-columns: 52px 1fr; }
  .cs-no { font-size: 27px; }
  .cs-no::before { left: 11px; }
}

/* ================================================================ JOURNEY
   How your project runs — four stations set out on a drawn line.
   Desktop: the line runs horizontally through the number stamps.
   Mobile: it turns vertical, the stations stacking down the sheet.        */
.jny {
  position: relative; list-style: none; margin: clamp(28px, 4vw, 52px) 0 0; padding: 0;
  display: grid; grid-template-columns: repeat(4, 1fr); gap: clamp(18px, 2.6vw, 34px);
}
.jny::before {
  content: ""; position: absolute; left: 0; right: 6px; top: 27px;
  border-top: 1px dashed var(--accent); opacity: .6;
}
.jny::after {
  content: ""; position: absolute; right: -1px; top: 23px; width: 9px; height: 9px;
  background: var(--accent); transform: rotate(45deg);
}
.jny-step { position: relative; }
.jny-no {
  position: relative; display: inline-grid; place-items: center;
  width: 54px; height: 54px; background: var(--paper); border: 1px solid var(--navy);
  margin-bottom: 14px;
}
.jny-no::after { content: ""; position: absolute; inset: 4px; border: 1px solid var(--board-line); pointer-events: none; }
.jny-no b { font-family: var(--serif); font-size: 22px; font-weight: 600; color: var(--navy); }
.jny-step h3 { font-size: clamp(19px, 1.7vw, 23px); margin-bottom: 8px; }
.jny-step > p { font-size: 14.5px; color: var(--ink-soft); margin: 0; }
.jny-get { margin: 14px 0 0 !important; border-top: 1px solid var(--line); padding-top: 12px; }
.jny-get b {
  display: flex; align-items: center; gap: 8px;
  font-family: var(--sans); font-size: 10.5px; font-weight: 700; letter-spacing: .18em;
  text-transform: uppercase; color: var(--navy); margin-bottom: 4px;
}
.jny-get b::before { content: ""; width: 7px; height: 7px; background: var(--accent); }
.jny-get span { font-family: var(--serif); font-size: 15.5px; color: var(--ink); line-height: 1.45; }
@media (max-width: 880px) {
  .jny { grid-template-columns: 1fr; gap: 30px; }
  .jny::before { left: 27px; right: auto; top: 10px; bottom: 4px; border-top: 0; border-left: 1px dashed var(--accent); }
  .jny::after { right: auto; left: 23px; top: auto; bottom: -4px; }
  .jny-step { display: grid; grid-template-columns: 54px 1fr; column-gap: 16px; }
  .jny-step > :not(.jny-no) { grid-column: 2; }
  .jny-no { margin-bottom: 0; }
}

/* ============================================================ TESTIMONIALS
   The review ledger. This CSS is dormant until REVIEWS in build.py holds a
   real quote — nothing renders while the list is empty. Quotes set in serif
   with the attribution ruled off beneath; no stars, no ratings, ever.     */
.rev-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: 18px; }
@media (max-width: 880px) { .rev-grid { grid-template-columns: 1fr; } }
.rev {
  margin: 0; background: #fff; border: 1px solid var(--line);
  padding: clamp(24px, 3vw, 36px); position: relative;
}
.rev::before {
  content: "\201C"; position: absolute; top: 10px; right: 18px;
  font-family: var(--serif); font-size: 64px; line-height: 1; color: var(--accent); opacity: .5;
}
.rev blockquote { margin: 0 0 18px; }
.rev blockquote p { margin: 0; font-family: var(--serif); font-size: clamp(17px, 1.7vw, 21px); line-height: 1.5; color: var(--ink); }
.rev figcaption { border-top: 1px solid var(--line); padding-top: 14px; display: grid; gap: 2px; }
.rev figcaption b { font-family: var(--sans); font-size: 14px; font-weight: 700; color: var(--ink); }
.rev figcaption span { font-size: 13px; color: var(--ink-soft); }
.rev figcaption i { font-style: normal; font-family: var(--sans); font-size: 11px; font-weight: 600; letter-spacing: .08em; text-transform: uppercase; color: var(--ink-soft); margin-top: 4px; }

/* ------------------------------------------- commercial client marquee
   Wordmarks, not logos: SG hold no logo files, and a borrowed logo would be a
   claim we cannot verify. Set in the serif so the names carry real weight.
   The track holds the client set repeated 6x so half of it always exceeds the
   viewport — that is what makes the loop continuous rather than snapping back. */
.marquee { position: relative; overflow: hidden;
  margin-top: clamp(26px, 3.4vw, 40px);
  border-top: 1px solid var(--line); border-bottom: 1px solid var(--line);
  -webkit-mask-image: linear-gradient(to right, transparent 0, #000 9%, #000 91%, transparent 100%);
          mask-image: linear-gradient(to right, transparent 0, #000 9%, #000 91%, transparent 100%); }
.marquee-track { display: flex; width: max-content; list-style: none; margin: 0; padding: 0;
  animation: sg-marquee 46s linear infinite; }
.marquee:hover .marquee-track,
.marquee:focus-within .marquee-track { animation-play-state: paused; }
.marquee-track li { flex: 0 0 auto; }
.marquee-track span { display: flex; align-items: center; min-height: 108px;
  padding: 24px clamp(34px, 4.4vw, 68px); white-space: nowrap;
  font-family: var(--serif); font-size: clamp(21px, 2vw, 28px);
  color: var(--navy); letter-spacing: .01em; }
@keyframes sg-marquee { from { transform: translateX(0); } to { transform: translateX(-50%); } }

/* Reduced motion: no scroll, no repeats — just the real names, once. */
@media (prefers-reduced-motion: reduce) {
  .marquee { -webkit-mask-image: none; mask-image: none; }
  .marquee-track { animation: none; width: 100%; flex-wrap: wrap; justify-content: center; }
  .marquee-track li[data-dup] { display: none; }
}

.sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0 0 0 0); white-space: nowrap; border: 0; }

/* Buttons carry their own colour pair. `.panel a { color: var(--white) }` above
   is meant for prose links inside a navy panel, but its higher specificity was
   repainting BUTTON text white too — so every .btn-bright inside a panel
   rendered white-on-white and the call to action disappeared entirely.
   Restore the button's own colour. (Found on "How a job runs, step by step"
   and the materials CTA after the white+blue recolour.) */
.panel a.btn-bright,
.panel a.btn-bright:hover { color: var(--navy-deep); }

/* Header phone. For a trade business the call IS the conversion, but a desktop
   visitor previously had to scroll to find the number. Compact and nowrap: the
   header row is capped at 1180px, so a bordered pill here pushed the nav onto a
   second line and the CTA overflowed the 72px band on every page. No
   margin-left:auto — .nav already carries it, and two fought each other. */
.hdr-tel { display: none; font-family: var(--sans); font-size: 15px; font-weight: 600;
  color: var(--navy); text-decoration: none; white-space: nowrap; padding: 6px 2px; }
.hdr-tel:hover { text-decoration: underline; }
@media (min-width: 1120px) { .hdr-tel { display: inline-block; } }


/* Coverage map at phone size: the labels are hidden, which left ~19 invisible
   5px tap targets stacked in the middle of the page and 19 unlabelled stops in
   the tab order. The chip list directly beneath repeats every one of these
   links, so the map becomes purely decorative below 700px. */
@media (max-width: 700px) {
  .patch svg a { pointer-events: none; }
  .patch text:not(.pm-base-text) { display: none; }
}

/* Honeypot: off-screen rather than display:none, because some bots deliberately
   skip hidden fields. Never focusable, never announced. */
.hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

/* ------------------------------------------------ scroll-scrubbed footage
   The track is tall; the stage pins inside it and the clip advances with the
   scroll. Copy lines fade up in turn against --sbp (0..1) from site.js.
   Renders only when SCRUB has a src — otherwise the section is not emitted. */
.sec-scrub { position: relative; background: var(--navy-deep); }
.sb-track { height: 300vh; }
.sb-stage { position: sticky; top: 0; height: 100vh; overflow: hidden;
  display: grid; place-items: center; }
.sb-video { position: absolute; inset: 0; width: 100%; height: 100%;
  object-fit: cover; opacity: .58; }
.sb-copy { position: relative; text-align: center; max-width: 22ch;
  padding: 0 24px; color: var(--white); }
.sb-kicker { display: block; font-family: var(--sans); font-size: 11px;
  font-weight: 700; letter-spacing: .2em; text-transform: uppercase;
  color: var(--sky); margin-bottom: 18px; }
.sb-line { font-family: var(--serif); font-size: clamp(28px, 4.4vw, 56px);
  line-height: 1.08; margin: 0 0 .28em; color: var(--white); }
/* Each line owns a slice of the scrub: it arrives, holds, then hands over. */
html.js.motion-ok .sb-line {
  --start: calc(var(--i) * .26);
  --p: clamp(0, calc((var(--sbp, 1) - var(--start)) / .18), 1);
  opacity: var(--p);
  transform: translateY(calc((1 - var(--p)) * 16px));
}
@media (prefers-reduced-motion: reduce) {
  .sb-track { height: auto; }
  .sb-stage { position: static; height: auto; padding: clamp(64px, 12vw, 140px) 0; }
  .sb-line { opacity: 1; transform: none; }
}

/* ----------------------------------------------------------- newsletter */
.nl { display: grid; gap: clamp(24px, 4vw, 48px); align-items: start; }
@media (min-width: 900px) { .nl { grid-template-columns: 1.1fr .9fr; } }
.nl-copy h2 { margin: 10px 0 12px; }
.nl-form { display: grid; gap: 12px; border: 1px solid var(--line);
  background: var(--paper); padding: clamp(20px, 3vw, 30px); }
.nl-form label[for] { font-family: var(--sans); font-size: 12px; font-weight: 700;
  letter-spacing: .14em; text-transform: uppercase; color: var(--navy); }
.nl-form input[type="email"] { width: 100%; padding: 13px 14px; font-size: 16px;
  font-family: var(--sans); color: var(--ink); background: var(--white);
  border: 1px solid var(--line); }
.nl-form input[type="email"]:focus { outline: 2px solid var(--navy); outline-offset: 1px; }
.nl-consent { display: flex; gap: 10px; align-items: flex-start;
  font-family: var(--sans); font-size: 13.5px; line-height: 1.5; color: var(--ink-soft); }
.nl-consent input { margin-top: 3px; width: 18px; height: 18px; flex: 0 0 auto; }
.nl-form .btn { justify-self: start; }
.nl-msg { font-family: var(--sans); font-size: 14px; margin: 0; min-height: 1.2em; }
.nl-msg.ok { color: var(--navy); font-weight: 600; }
.nl-msg.bad { color: #8A1C1C; }

/* ===== the Kind additions (Gary, 22 Jul) — history, news, sector rail ===== */

/* the axis divider between the type tabs and the sector tabs on /work/ */
.wk-axis {
  font-family: var(--sans); font-size: 10.5px; font-weight: 700;
  letter-spacing: .16em; text-transform: uppercase; color: var(--ink-soft);
  align-self: center; padding-left: 14px; border-left: 1px solid var(--line);
  margin-left: 6px;
}

/* /about/history/ — the dated record. Year in the margin, fact beside it,
   ruled like a ledger line. */
.hist { display: grid; gap: 0; border-top: 1px solid var(--line); }
.hist-row {
  display: grid; grid-template-columns: 110px minmax(0, 1fr);
  gap: 18px; padding: 22px 0; border-bottom: 1px solid var(--line);
}
.hist-year {
  font-family: var(--sans); font-weight: 700; font-size: 22px; color: var(--navy);
  font-variant-numeric: tabular-nums; line-height: 1.2;
}
.hist-row h3 { margin: 0 0 6px; font-size: 19px; }
.hist-row p { margin: 0; font-size: 14.5px; line-height: 1.6; color: var(--ink-soft); max-width: 62ch; }
.hist-row.is-reserved .hist-year { color: var(--ink-soft); opacity: .6; }
.hist-row.is-reserved h3 { color: var(--ink-soft); }
@media (max-width: 620px) {
  .hist-row { grid-template-columns: 64px minmax(0, 1fr); gap: 12px; padding: 16px 0; }
  .hist-year { font-size: 17px; }
}

/* /terms/ — a section awaiting the office's confirmed wording. Same visual
   language as the reserved cards: plainly labelled, never pretending. */
.terms-reserved { color: var(--ink-soft); font-style: italic; }
.terms-reserved span {
  display: inline-block; font-family: var(--sans); font-style: normal;
  font-size: 10px; font-weight: 700; letter-spacing: .14em; text-transform: uppercase;
  color: var(--navy); border: 1px solid var(--line); border-radius: 3px;
  padding: 2px 7px; margin-right: 8px; vertical-align: 1px;
}

/* /news/ — dated rows, kind-build's list shape in this site's ruling */
.news-list { display: grid; gap: 0; }
.news-row {
  display: grid; grid-template-columns: 150px minmax(0, 1fr);
  gap: 18px; padding: 24px 0; border-bottom: 1px solid var(--line);
}
.news-row time {
  font-family: var(--sans); font-size: 13px; font-weight: 700;
  letter-spacing: .04em; color: var(--ink-soft); padding-top: 4px;
  font-variant-numeric: tabular-nums;
}
.news-row h2 { font-size: clamp(19px, 2.2vw, 24px); margin: 0 0 8px; }
.news-row h2 a { text-decoration: none; color: inherit; }
.news-row h2 a:hover { color: var(--navy); }
.news-row p { margin: 0 0 10px; font-size: 14.5px; line-height: 1.6; color: var(--ink-soft); max-width: 68ch; }
@media (max-width: 620px) {
  .news-row { grid-template-columns: 1fr; gap: 6px; padding: 18px 0; }
}

/* ================================================= the hero scroll film
   Scene motion, all driven by --hp (0..1) from site.js. Every rule below is a
   pure function of scroll position — nothing is time-based, so the scroll is
   genuinely the playhead and it can be scrubbed backwards. */

/* helper: 0..1 progress inside a group's own --a/--b window */
.hero-live .hero-draw .van,
.hero-live .hero-draw .sign-board,
.hero-live .hero-draw .lit {
  --t: clamp(0, calc((var(--hp) - var(--a)) / (var(--b) - var(--a))), 1);
}

/* THE VAN — drives in from off-frame right and settles. */
.hero-live .hero-draw .van {
  transform: translateX(calc((1 - var(--t)) * 430px));
  opacity: clamp(0, calc(var(--t) * 4), 1);
}

/* THE SIGN BOARD — swings down on its bracket rather than just appearing. */
.hero-live .hero-draw .sign-board {
  transform: rotate(calc((1 - var(--t)) * -26deg));
  transform-origin: 116px 250px;
  transform-box: view-box;
}

/* THE LIGHT — sign, then glass, then the room inside. Warm fill, no new hue:
   --sky at low alpha reads as light without breaking the locked palette. */
.hero-live .hero-draw .lit rect {
  fill: var(--sky);
  stroke: none;
}
.hero-live .hero-draw .lit { opacity: calc(var(--t) * .30); }
.hero-live .hero-draw .lit-sign { opacity: calc(var(--t) * .55); }
.hero-live .hero-draw .lit-inside { opacity: calc(var(--t) * .18); }

/* GOING IN — the frontage opens out past the viewer while the room scales down
   into place. A move through the door, not a cut. Origin is the pub doorway. */
.hero-live .hero-draw .exterior {
  --e: clamp(0, calc((var(--hp) - .62) / .20), 1);
  opacity: calc(1 - var(--e));
  transform: scale(calc(1 + var(--e) * .85));
  transform-origin: 335px 400px;
  transform-box: view-box;
}
/* (The .interior rule that used to sit here was dead — a later rule of equal
   specificity overrode every one of its declarations. The live one is further
   down, next to .finale. Do not reinstate a copy here.) */
/* Before the film starts the interior must not sit on top of the frontage. */
.hero-draw .interior { opacity: 0; }
.hero-draw .lit { opacity: 0; }

/* Reduced motion: no scene moves at all — the finished frontage, drawn. */
@media (prefers-reduced-motion: reduce) {
  .hero-draw .exterior { opacity: 1; transform: none; }
  .hero-draw .interior { display: none; }
  .hero-draw .van { transform: none; opacity: 1; }
  .hero-draw .sign-board { transform: none; }
  .hero-draw .lit { opacity: .22; }
}

/* ============================================ the film: crew, light, finale
   Scene motion, all driven by --hp. Scoped to .hero-draw because the film
   lives in the hero. NOTE: there is deliberately NO separate "reset to 0" rule
   after these — an equal-specificity reset placed later silently pinned the
   finale at opacity 0 last time. Each calc already evaluates to 0 before its
   window opens. */
.hero-live .hero-draw .van,
.hero-live .hero-draw .sign-board,
.hero-live .hero-draw .lit {
  --t: clamp(0, calc((var(--hp) - var(--a)) / (var(--b) - var(--a))), 1);
}

/* the van drives in from off-frame right and settles */
.hero-live .hero-draw .van {
  transform: translateX(calc((1 - var(--t)) * 430px));
  opacity: clamp(0, calc(var(--t) * 4), 1);
}
/* the sign board swings down on its bracket */
.hero-live .hero-draw .sign-board {
  transform: rotate(calc((1 - var(--t)) * -26deg));
  transform-origin: 116px 250px; transform-box: view-box;
}
/* the hammer swings on the shoulder as the crew work */
.hero-live .hero-draw .swing {
  --s: clamp(0, calc((var(--hp) - .33) / .09), 1);
  transform: rotate(calc(-38deg + var(--s) * 38deg));
  transform-origin: 252px 440px; transform-box: view-box;
}
/* light: sign, then glass, then the room, then the finished frontage */
.hero-live .hero-draw .lit rect { fill: var(--sky); stroke: none; }
.hero-live .hero-draw .lit { opacity: calc(var(--t) * .30); }
.hero-live .hero-draw .lit-sign { opacity: calc(var(--t) * .55); }
.hero-live .hero-draw .lit-inside { opacity: calc(var(--t) * .18); }
.hero-live .hero-draw .lit-final { opacity: calc(var(--t) * .34); }
/* scale figures draw thin so they read as people, not structure */
.hero-live .hero-draw .fig path { stroke-width: 1.15; }

/* in through the door, then back out to the finished pub */
.hero-live .hero-draw .exterior {
  --e: clamp(0, calc((var(--hp) - .44) / .06), 1);
  opacity: calc(1 - var(--e));
  transform: scale(calc(1 + var(--e) * .7));
  transform-origin: 335px 400px; transform-box: view-box;
}
/* The bar interior. Its paths are authored across x 120..624 of a 920-wide
   view-box — 504 units wide, centred on 372, where the exterior and the finale
   are 808 wide and centred on 460. Left as drawn it settled 88 units left of
   centre and visibly smaller, so the film appeared to shrink and slide sideways
   the moment you went inside. --base scales it up to sit with the other scenes
   and the translate puts it on the centre line. Height is the binding limit
   (404 * 1.2 = 485 of 560), which is why --base is not higher.
   This rule supersedes an earlier duplicate further up the file. */
.hero-live .hero-draw .interior {
  --base: 1.2;
  --i: clamp(0, calc((var(--hp) - .69) / .05), 1);
  --o: clamp(0, calc((var(--hp) - .84) / .05), 1);
  opacity: calc(var(--i) * (1 - var(--o)));
  transform: translate(88px, 0)
             scale(calc((1.25 - var(--i) * .25 + var(--o) * .5) * var(--base)));
  transform-origin: 372px 298px; transform-box: view-box;
}
.hero-live .hero-draw .finale {
  --f: clamp(0, calc((var(--hp) - .855) / .045), 1);
  opacity: var(--f);
  transform: scale(calc(1.12 - var(--f) * .12));
  transform-origin: 335px 360px; transform-box: view-box;
}

@media (prefers-reduced-motion: reduce) {
  .hero-draw .exterior { opacity: 0; }
  .hero-draw .interior { display: none; }
  .hero-draw .finale { opacity: 1; transform: none; }
  .hero-draw .van, .hero-draw .sign-board, .hero-draw .swing { transform: none; opacity: 1; }
  .hero-draw .lit { opacity: .24; }
}


/* The two trade shots — hanging a door, then a bathroom going in. Each fades
   up, holds while it draws, then hands to the next. Same pattern as .interior:
   an in-ramp and an out-ramp multiplied together, so no separate reset rule is
   needed (that is what silently killed the finale before). */
.hero-live .hero-draw .shot {
  --in:  clamp(0, calc((var(--hp) - var(--s0)) / .04), 1);
  --out: clamp(0, calc((var(--s1) - var(--hp)) / .04), 1);
  opacity: min(var(--in), var(--out));
  transform: scale(calc(1.06 - var(--in) * .06));
  transform-origin: 460px 340px; transform-box: view-box;
}
.hero-live .hero-draw .shot-door { --s0: .45; --s1: .60; }
.hero-live .hero-draw .shot-bath { --s0: .57; --s1: .72; }

/* the door leaf swings to true as it is hung */
.hero-live .hero-draw .door-leaf {
  --d: clamp(0, calc((var(--hp) - .50) / .07), 1);
  transform: rotate(calc((1 - var(--d)) * -4deg));
  transform-origin: 372px 500px; transform-box: view-box;
}

@media (prefers-reduced-motion: reduce) {
  .hero-draw .shot { display: none; }
}

/* =====================================================================
   DESIGN PASS (23 Jul) — approved from the preview build
   Applied from taste-skill (redesign-preserve: match system, motion +1;
   tactile states; tinted shadows; shape lock stays all-sharp) and
   hallmark (locked tokens — every value below is a var() or an rgba of
   one; no italic headers; no re-drawn chrome; no copy or layout change).
   ===================================================================== */

/* -- typography craft: tighter display tracking, balanced wraps -------- */
h1, h2, .bp-statement { letter-spacing: -0.015em; text-wrap: balance; }
h3 { letter-spacing: -0.008em; }
p, figcaption, li { text-wrap: pretty; }
.folio-no, .sc-no, .accr-meta dd { font-variant-numeric: tabular-nums; }

/* -- selection + focus: the system's own blue, never browser default --- */
::selection { background: var(--navy); color: var(--white); }
:focus-visible { outline: 2px solid var(--navy); outline-offset: 3px; }
.btn:focus-visible, .chip:focus-visible { outline-color: var(--sky); }

/* -- tactile buttons: hover lift, press feedback, tinted shadow -------- */
.btn { transition: transform .18s cubic-bezier(.2,.6,.2,1), box-shadow .18s cubic-bezier(.2,.6,.2,1), background .18s ease, color .18s ease; }
.btn:hover { transform: translateY(-1px); box-shadow: 0 4px 14px rgba(33, 33, 80, .16); }
.btn:active { transform: translateY(0) scale(.985); box-shadow: 0 1px 4px rgba(33, 33, 80, .12); transition-duration: .06s; }

/* -- link underline draw: prose + footer links earn a moving line ------ */
.prose a, .ftr a, .work-note a {
  text-decoration: none;
  background-image: linear-gradient(currentColor, currentColor);
  background-repeat: no-repeat; background-position: 0 100%;
  background-size: 0% 1px; transition: background-size .28s cubic-bezier(.2,.6,.2,1);
}
.prose a:hover, .ftr a:hover, .work-note a:hover { background-size: 100% 1px; }
.card-go { transition: letter-spacing .2s ease, color .2s ease; }
a:hover .card-go, .card-go:hover { letter-spacing: .02em; }

/* -- photography: slow scale on hover, caption stays put --------------- */
.work-item { overflow: hidden; }
.work-item img { transition: transform .7s cubic-bezier(.2,.6,.2,1); }
.work-item:hover img { transform: scale(1.035); }
.wk-slot-frame { overflow: hidden; }
.wk-slot-img { transition: transform .7s cubic-bezier(.2,.6,.2,1); }
.wk-slot:hover .wk-slot-img { transform: scale(1.035); }
.frame.is-ind .plate-img { transition: transform .7s cubic-bezier(.2,.6,.2,1); }
.plate:hover .plate-img { transform: scale(1.03); }

/* -- cards: hairline sharpens + navy-tinted elevation on hover --------- */
.sheet-card, .bp-svc, .accr-item:not(.is-reserved), .wk-card, .map-card {
  transition: transform .22s cubic-bezier(.2,.6,.2,1), box-shadow .22s cubic-bezier(.2,.6,.2,1), border-color .22s ease;
}
.sheet-card:hover, .bp-svc:hover, .wk-card:hover {
  transform: translateY(-2px);
  border-color: var(--navy);
  box-shadow: 0 10px 28px rgba(33, 33, 80, .10);
}

/* -- rules draw in with their section ---------------------------------- */
html.js.motion-ok .rv hr.rule, html.js.motion-ok .rv .rule {
  transform-origin: left center;
  transform: scaleX(var(--p, 1));
}

/* -- indicative tag: settles in rather than popping -------------------- */
.ind-tag { transition: opacity .3s ease, transform .3s ease; }
.work-item:hover .ind-tag, .wk-slot:hover .ind-tag { transform: translateY(-1px); }

/* -- before/after handle: invites the drag ----------------------------- */
.ba-handle { transition: transform .2s ease; }
.ba:hover .ba-handle { transform: scale(1.06); }

/* -- header nav: underline draw + a calmer arrival --------------------- */
.nav a:not(.btn) {
  background-image: linear-gradient(var(--navy), var(--navy));
  background-repeat: no-repeat; background-position: 0 calc(100% - 2px);
  background-size: 0% 1.5px; transition: background-size .24s cubic-bezier(.2,.6,.2,1);
}
.nav a:not(.btn):hover { background-size: 100% 1.5px; }

/* -- chips: press feedback matching buttons ---------------------------- */
.chip { transition: transform .16s ease, border-color .16s ease, background .16s ease, color .16s ease; }
.chip:hover { transform: translateY(-1px); }
.chip:active { transform: translateY(0) scale(.97); }

/* -- scrollbar joins the drawing --------------------------------------- */
* { scrollbar-width: thin; scrollbar-color: var(--line) transparent; }
*:hover { scrollbar-color: var(--sky) transparent; }

/* -- doors: the two big words breathe ----------------------------------- */
.hero .door-min h2 { transition: color .22s ease, letter-spacing .3s cubic-bezier(.2,.6,.2,1); }
.hero .door-min:hover h2 { letter-spacing: .015em; }

/* reduced motion: the global kill-switch at the top of this file already
   flattens every transition/animation above to .01ms — nothing extra needed. */

/* ---------------------------------------------------- analytics preview
   Internal show-and-tell page (/analytics/). Tokens only, SG palette. */
.an-banner {
  border: 1px solid var(--navy); background: var(--navy-tint);
  padding: 16px 18px; margin: 22px 0 4px; font-size: 15px; line-height: 1.55;
  border-radius: 0;
}
.an-banner b { color: var(--navy-deep); }
.an-kpis { display: grid; grid-template-columns: repeat(4, 1fr); gap: 18px; margin-top: 28px; }
.an-kpi {
  position: relative; border: 1px solid var(--line); background: #fff;
  padding: 22px 20px; display: flex; flex-direction: column; gap: 6px;
}
.an-tag {
  position: absolute; top: 12px; right: 12px; font-family: var(--sans);
  font-size: 9px; font-weight: 700; letter-spacing: .16em; text-transform: uppercase;
  color: var(--ink-soft); border: 1px solid var(--line); padding: 3px 6px;
}
.an-num { font-family: var(--serif); font-size: clamp(30px, 3.4vw, 42px); line-height: 1; color: var(--navy); font-variant-numeric: tabular-nums; }
.an-label { font-weight: 700; font-size: 15px; color: var(--ink); }
.an-note { font-size: 13px; color: var(--ink-soft); line-height: 1.5; }
.an-bars { display: flex; flex-direction: column; gap: 14px; margin-top: 26px; }
.an-bar-row { display: grid; grid-template-columns: minmax(0, 220px) 1fr auto; align-items: center; gap: 14px; }
.an-bar-label { font-size: 14.5px; color: var(--ink); }
.an-bar { height: 12px; background: var(--navy-tint); position: relative; overflow: hidden; }
.an-bar i { display: block; height: 100%; background: var(--navy); }
.an-bar-val { font-family: var(--sans); font-size: 13px; font-weight: 700; color: var(--navy); font-variant-numeric: tabular-nums; min-width: 40px; text-align: right; }
.an-list { margin-top: 24px; border-top: 1px solid var(--line); }
.an-list-row { display: flex; justify-content: space-between; align-items: center; padding: 13px 2px; border-bottom: 1px solid var(--line); font-size: 15.5px; }
.an-list-val { font-family: var(--sans); font-size: 13px; color: var(--ink-soft); font-variant-numeric: tabular-nums; }
.an-events { display: grid; grid-template-columns: repeat(2, 1fr); gap: 16px; margin-top: 26px; }
.an-ev { border: 1px solid var(--line); background: #fff; padding: 18px 20px; }
.an-ev h3 { margin: 0 0 6px; font-size: 16px; }
.an-ev p { margin: 0; font-size: 14px; color: var(--ink-soft); line-height: 1.55; }
.an-samplenote { margin-top: 16px; font-family: var(--sans); font-size: 11px; letter-spacing: .04em; text-transform: uppercase; color: var(--ink-soft); }
@media (max-width: 900px) { .an-kpis { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 620px) {
  .an-kpis, .an-events { grid-template-columns: 1fr; }
  .an-bar-row { grid-template-columns: 1fr auto; }
  .an-bar { grid-column: 1 / -1; order: 3; }
}

/* --- South East map (/domestic/) ------------------------------------- */
/* Real coordinates, distance-true near Godstone — unlike .patch, which is a
   deliberately abstract not-to-scale diagram. */
.se-map { width: 100%; height: auto; display: block; }
.se-land { fill: var(--navy-tint); stroke: var(--line); stroke-width: 1.5; }
.se-thames { fill: none; stroke: var(--sky); stroke-width: 2.5; opacity: .7; }
.se-ring { fill: rgba(50,50,113,.07); stroke: var(--navy); stroke-width: 1.5;
           stroke-dasharray: 5 5; }
.se-dot { fill: var(--navy); }
.se-town { font-size: 13px; font-weight: 600; fill: var(--ink); }
.se-map a:hover .se-dot { fill: var(--navy-deep); r: 5.5; }
.se-map a:hover .se-town { fill: var(--navy-deep); text-decoration: underline; }
.se-city-dot { fill: var(--ink-soft); opacity: .55; }
.se-city { font-size: 12px; fill: var(--ink-soft); letter-spacing: .06em;
           text-transform: uppercase; opacity: .8; }
.se-base { fill: var(--accent); stroke: var(--white); stroke-width: 2.5; }
.se-base-text { font-size: 13px; font-weight: 800; fill: var(--navy-deep);
                letter-spacing: .05em; }
.se-ring-label { font-size: 12px; fill: var(--ink-soft); font-style: italic; }
@media (max-width: 640px) {
  .se-town { font-size: 15px; }
  .se-city { font-size: 13px; }
}
.se-map-wrap { margin: 26px 0 0; }
.se-map-wrap figcaption { margin-top: 10px; font-size: 14px; color: var(--ink-soft);
                          max-width: 62ch; }
.se-leader { stroke: var(--navy); stroke-width: 1; opacity: .5; }
