/* =====================================================================
   Castle Skylights Colchester — Design System
   Architectural slate + warm daylight. Fraunces / Inter.
   Mobile-first. Built ONCE here; every page inherits it.
   ===================================================================== */

/* ---------- Tokens ---------- */
:root {
  /* Brand palette (from STYLE-GUIDE.md) */
  --brand-primary:        #1F3350;  /* primary */
  --brand-primary-soft:    #2C4568;
  --brand-deep:    #131F2E;
  --accent:        #A32B3C;  /* decorative accent (icons, borders, rules) — graphical 3:1 */
  --accent-deep:    #7E1F2D;  /* button bg — white text passes AA (4.83:1) */
  --accent-text:    #8E2434;  /* brass TEXT + button hover — AA on light (4.9:1) */
  --brand-support:     #8FA8C4;  /* soft secondary */
  --brand-support-wash: #E9EEF5;

  /* Warm neutrals */
  --white:    #FFFFFF;
  --surface:    #FBFAF7;  /* page bg — warm off-white */
  --surface-alt:  #F1EDE5;  /* alt section bg */
  --ink:      #262C35;  /* body text */
  --ink-heading:  #1F3350;  /* headings */
  --ink-muted:    #5A6472;  /* AA on light bg (4.9:1) */
  --hairline: #E0DACE;

  /* Semantic */
  --success: #2E7D52;
  --warning: #B07D18;
  --danger:  #B3261E;

  /* Type */
  --font-display: "Fraunces", Georgia, "Times New Roman", serif;
  --font-body: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;

  /* Spacing / layout */
  --container: 1200px;
  --radius: 14px;
  --radius-sm: 8px;
  --shadow-sm: 0 1px 2px rgba(14,36,45,.06), 0 2px 8px rgba(14,36,45,.05);
  --shadow-md: 0 8px 30px rgba(14,36,45,.10);
  --shadow-lg: 0 24px 60px rgba(14,36,45,.16);
  --ease: cubic-bezier(.22,.61,.36,1);
}

/* ---------- Reset ---------- */
*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
body {
  font-family: var(--font-body);
  font-size: 1.0625rem;
  line-height: 1.7;
  color: var(--ink);
  background: var(--surface);
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}
img, video, iframe, svg { max-width: 100%; height: auto; display: block; }
a { color: var(--brand-primary); text-decoration: none; transition: color .2s var(--ease); }
a:hover { color: var(--accent); }
ul { list-style: none; padding: 0; }

/* ---------- Typography ---------- */
h1, h2, h3, h4 {
  font-family: var(--font-display);
  color: var(--ink-heading);
  line-height: 1.08;
  font-weight: 540;
  letter-spacing: -0.01em;
  font-optical-sizing: auto;
  overflow-wrap: break-word;
}
h1 { font-size: clamp(2rem, 6vw, 4.25rem); }
h2 { font-size: clamp(1.9rem, 4vw, 3rem); }
h3 { font-size: clamp(1.3rem, 2.4vw, 1.7rem); }
p { max-width: 68ch; }
.eyebrow {
  font-family: var(--font-body);
  font-size: .8rem;
  font-weight: 600;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--accent-text);
  display: inline-block;
}
.lead { font-size: clamp(1.1rem, 1.6vw, 1.3rem); color: var(--brand-primary-soft); }

/* ---------- Layout primitives ---------- */
.container {
  width: 100%;
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: clamp(16px, 5vw, 48px);
}
.section { padding-block: clamp(56px, 9vw, 120px); }
.section--paper2 { background: var(--surface-alt); }
.section--brand-primary { background: var(--brand-primary); color: #d8e2e7; }
.grid { display: grid; gap: clamp(20px, 3vw, 32px); }
.grid-2 { grid-template-columns: 1fr; }
.grid-3 { grid-template-columns: 1fr; }
.grid-4 { grid-template-columns: 1fr; }
@media (min-width: 768px) {
  .grid-2 { grid-template-columns: repeat(2, 1fr); }
  .grid-3 { grid-template-columns: repeat(3, 1fr); }
  .grid-4 { grid-template-columns: repeat(2, 1fr); }
}
@media (min-width: 1024px) {
  .grid-4 { grid-template-columns: repeat(4, 1fr); }
}
.center { text-align: center; }
/* Compact hero (contact page) */
.page-hero--tight { padding-block: clamp(24px, 4vw, 44px) !important; }
.page-hero--tight .container { padding-block: 0; }
/* Contact page — contact-point cards + coverage map */
.contact-grid { display: grid; gap: 16px; grid-template-columns: 1fr; }
@media (min-width: 600px) { .contact-grid { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 980px) { .contact-grid { grid-template-columns: repeat(4, 1fr); } }
.contact-card { display: flex; flex-direction: column; gap: 6px; padding: 22px; border-radius: 14px; background: #fff; border: 1px solid var(--brand-support-wash, #e7ecea); box-shadow: 0 6px 20px rgba(21,50,63,.06); color: inherit; text-decoration: none; transition: transform .2s ease, box-shadow .2s ease; }
a.contact-card:hover { transform: translateY(-3px); box-shadow: 0 12px 28px rgba(21,50,63,.12); }
.contact-card svg { color: var(--brand, var(--brand-primary)); }
.contact-card__k { font-size: .8rem; text-transform: uppercase; letter-spacing: .04em; color: var(--ink-muted, #5a6b73); margin-top: 6px; }
.contact-card__v { font-weight: 600; font-size: 1.05rem; word-break: break-word; }
.map-embed { border-radius: 16px; overflow: hidden; box-shadow: 0 8px 28px rgba(21,50,63,.12); line-height: 0; }
.map-embed iframe { display: block; width: 100%; }
/* Inline content figures — images scattered through the body copy, magazine-style */
.content-figure { margin: 20px 0; border-radius: 14px; overflow: hidden; background: #eef1f0; box-shadow: 0 6px 20px rgba(21,50,63,.08); }
.content-figure img { width: 100%; height: auto; display: block; aspect-ratio: 4 / 3; object-fit: cover; transition: transform .5s ease; }
.content-figure:hover img { transform: scale(1.04); }
.content-figure figcaption { font-size: .82rem; line-height: 1.4; color: #5a6b73; padding: 8px 12px 10px; background: #f6f8f7; }
@media (min-width: 900px) {
  /* Floats removed, appendix 3.4. A float landing after a short paragraph or
   * before a heading has no text to wrap it and leaves a large empty gap, and
   * with automated placement that recurs across the whole site. A block image
   * structurally cannot orphan. */
  .content-figure { width: 100%; }
}
/* Keep headings clear of floated figures, and contain floats within the body */
.prose h2 { clear: both; }
.service-body.prose::after, .prose::after { content: ""; display: block; clear: both; }
.section-head { max-width: 720px; margin-bottom: clamp(32px, 5vw, 56px); }
.section-head.center { margin-inline: auto; }
.section-head h2 { margin-top: 10px; }
.section-head p { margin-top: 14px; }

/* ---------- Buttons ---------- */
.btn {
  display: inline-flex; align-items: center; gap: 10px;
  font-family: var(--font-body); font-weight: 600; font-size: 1rem;
  padding: 15px 26px; border-radius: 999px; border: 1.5px solid transparent;
  cursor: pointer; transition: transform .25s var(--ease), box-shadow .25s var(--ease), background .25s var(--ease), color .2s var(--ease);
  line-height: 1; white-space: nowrap;
}
.btn svg { width: 18px; height: 18px; }
.btn--primary { background: var(--accent-deep); color: #fff; box-shadow: 0 6px 18px rgba(148,106,34,.32); }
.btn--primary:hover { background: var(--accent-text); color: #fff; transform: translateY(-2px); box-shadow: 0 12px 28px rgba(148,106,34,.45); }
.btn--ghost { background: transparent; color: var(--brand-primary); border-color: var(--brand-primary); }
.btn--ghost:hover { background: var(--brand-primary); color: #fff; transform: translateY(-2px); }
.btn--light { background: #fff; color: var(--brand-primary); }
.btn--light:hover { transform: translateY(-2px); box-shadow: var(--shadow-md); color: var(--brand-primary); }
.btn--lg { padding: 18px 34px; font-size: 1.05rem; }

/* ---------- Header ---------- */
.site-header {
  position: sticky; top: 0; z-index: 50;
  background: rgba(246,244,239,.82);
  backdrop-filter: saturate(140%) blur(12px);
  border-bottom: 1px solid var(--hairline);
}
.site-header .container { display: flex; align-items: center; justify-content: space-between; gap: 20px; min-height: 74px; }
.brand { display: flex; align-items: center; gap: 11px; font-family: var(--font-display); font-weight: 600; font-size: 1.25rem; color: var(--brand-primary); letter-spacing: -.01em; }
.brand:hover { color: var(--brand-primary); }
.brand__mark { width: 40px; height: 40px; flex: 0 0 40px; }
.brand small { display: block; font-family: var(--font-body); font-weight: 500; font-size: .62rem; letter-spacing: .16em; text-transform: uppercase; color: var(--accent-text); margin-top: 2px; }
.nav { display: none; align-items: center; gap: 30px; }
.nav a { font-weight: 500; font-size: .98rem; color: var(--brand-primary-soft); }
.nav a:hover { color: var(--accent); }
.header-cta { display: none; }
.header-actions { display: flex; align-items: center; gap: 14px; }
.header-tel { display: none; font-weight: 600; color: var(--brand-primary); }
.header-tel svg { width: 18px; height: 18px; display: inline; vertical-align: -3px; margin-right: 6px; }
.menu-toggle { display: inline-flex; background: none; border: 0; padding: 8px; cursor: pointer; color: var(--brand-primary); }
.menu-toggle svg { width: 26px; height: 26px; }
@media (min-width: 1024px) {
  .nav { display: flex; }
  .header-cta { display: inline-flex; }
  .header-tel { display: inline-flex; align-items: center; }
  .menu-toggle { display: none; }
}

/* ---------- Hero ---------- */
.hero { position: relative; overflow: hidden; background: linear-gradient(180deg, var(--surface) 0%, var(--brand-support-wash) 100%); }
.hero .container { display: grid; gap: clamp(32px, 5vw, 56px); padding-block: clamp(48px, 8vw, 96px); grid-template-columns: 1fr; align-items: center; }
.hero .container > * { min-width: 0; }
.hero__eyebrow { margin-bottom: 18px; }
.hero h1 { margin-bottom: 22px; }
.hero h1 .hl { color: var(--accent-text); font-style: italic; }
.hero__sub { font-size: clamp(1.08rem, 1.7vw, 1.3rem); color: var(--brand-primary-soft); max-width: 30ch; }
.hero__cta { display: flex; flex-wrap: wrap; gap: 14px; margin-top: 30px; }
.hero__media { position: relative; }
.hero__media img { border-radius: var(--radius); box-shadow: var(--shadow-lg); width: 100%; aspect-ratio: 4 / 5; object-fit: cover; }
.hero__badge {
  position: absolute; left: -10px; bottom: 24px; background: #fff; border-radius: var(--radius-sm);
  box-shadow: var(--shadow-md); padding: 14px 18px; display: flex; align-items: center; gap: 12px; max-width: 260px;
}
.hero__badge .stars { color: var(--accent); font-size: 1rem; letter-spacing: 2px; }
.hero__badge strong { color: var(--brand-primary); display:block; font-size:.95rem; }
.hero__badge span { font-size: .8rem; color: var(--ink-muted); }
@media (min-width: 900px) {
  .hero .container { grid-template-columns: 1.05fr .95fr; }
  .hero__media img { aspect-ratio: 4 / 5; }
}

/* ---------- Trust strip ---------- */
.trust-strip { background: var(--brand-primary); }
.trust-strip .container { display: flex; flex-wrap: wrap; gap: 18px 36px; align-items: center; justify-content: center; padding-block: 22px; }
.trust-strip .ti { display: flex; align-items: center; gap: 10px; color: #cfdae0; font-weight: 500; font-size: .92rem; }
.trust-strip .ti svg { width: 22px; height: 22px; color: var(--brand-support); flex: 0 0 22px; }

/* ---------- Pillars / specialist difference ---------- */
.pillar { background: #fff; border: 1px solid var(--hairline); border-radius: var(--radius); padding: clamp(24px, 3vw, 34px); box-shadow: var(--shadow-sm); transition: transform .3s var(--ease), box-shadow .3s var(--ease); }
.pillar:hover { transform: translateY(-4px); box-shadow: var(--shadow-md); }
.pillar__icon { width: 52px; height: 52px; max-width: 52px; max-height: 52px; color: var(--accent); margin-bottom: 16px; }
.pillar__icon svg { width: 52px; height: 52px; }
.pillar h3 { margin-bottom: 10px; }

/* ---------- Service cards ---------- */
.svc { position: relative; background: #fff; border: 1px solid var(--hairline); border-radius: var(--radius); overflow: hidden; box-shadow: var(--shadow-sm); transition: transform .3s var(--ease), box-shadow .3s var(--ease); display: flex; flex-direction: column; }
.svc:hover { transform: translateY(-5px); box-shadow: var(--shadow-md); }
.svc__media { aspect-ratio: 16/10; background: var(--brand-support-wash); overflow: hidden; }
.svc__media img { width: 100%; height: 100%; object-fit: cover; transition: transform .5s var(--ease); }
.svc:hover .svc__media img { transform: scale(1.05); }
.svc__body { padding: 24px; display: flex; flex-direction: column; gap: 10px; flex: 1; }
.svc__body h3 { font-size: 1.3rem; }
.svc__link { margin-top: auto; font-weight: 600; color: var(--accent-text); display: inline-flex; align-items: center; gap: 6px; }
.svc__link svg { width: 16px; height: 16px; transition: transform .25s var(--ease); }
.svc:hover .svc__link svg { transform: translateX(4px); }

/* ---------- Process steps ---------- */
.step { position: relative; padding-left: 0; }
.step__n { font-family: var(--font-display); font-size: 2.6rem; color: var(--brand-support); line-height: 1; margin-bottom: 10px; display: block; }
.step h3 { font-size: 1.25rem; margin-bottom: 8px; }

/* ---------- Stats ---------- */
.stats { display: grid; gap: 24px; grid-template-columns: repeat(2,1fr); }
@media (min-width: 768px){ .stats { grid-template-columns: repeat(4,1fr); } }
.stat { text-align: center; }
.stat__num { font-family: var(--font-display); font-size: clamp(2.4rem,5vw,3.4rem); color: var(--accent); line-height: 1; }
.stat__label { color: var(--ink-muted); font-size: .92rem; margin-top: 8px; letter-spacing: .02em; }

/* ---------- Testimonials ---------- */
.quote { background: #fff; border: 1px solid var(--hairline); border-radius: var(--radius); padding: 28px; box-shadow: var(--shadow-sm); }
.quote .stars { color: var(--accent); letter-spacing: 2px; margin-bottom: 12px; }
.quote blockquote { font-family: var(--font-display); font-size: 1.15rem; line-height: 1.45; color: var(--brand-primary); margin-bottom: 16px; }
.quote cite { font-style: normal; font-weight: 600; color: var(--brand-primary); }
.quote cite span { display: block; font-weight: 400; font-size: .88rem; color: var(--ink-muted); }

/* ---------- Areas ---------- */
.areas { display: flex; flex-wrap: wrap; gap: 10px; }
.areas a { background: #fff; border: 1px solid var(--hairline); border-radius: 999px; padding: 8px 16px; font-size: .92rem; font-weight: 500; color: var(--brand-primary-soft); }
.areas a:hover { border-color: var(--accent); color: var(--accent); }

/* ---------- CTA band ---------- */
.cta-band { background: linear-gradient(120deg, var(--brand-primary) 0%, var(--brand-primary-soft) 100%); color: #fff; border-radius: clamp(16px, 3vw, 28px); padding: clamp(36px, 6vw, 72px); text-align: center; box-shadow: var(--shadow-lg); }
.cta-band h2 { color: #fff; margin-bottom: 14px; }
.cta-band p { color: #cfdae0; margin: 0 auto 28px; }
.cta-band .hero__cta { justify-content: center; }

/* ---------- Footer ---------- */
.site-footer { background: var(--brand-deep); color: #aebcc3; padding-block: clamp(48px, 6vw, 72px) 28px; font-size: .95rem; }
.site-footer a { color: #cfdae0; }
.site-footer a:hover { color: var(--accent); }
.footer-grid { display: grid; gap: 36px; grid-template-columns: 1fr; }
@media (min-width: 768px){ .footer-grid { grid-template-columns: 1.4fr 1fr 1fr 1.2fr; } }
.footer-grid h3 { color: #fff; font-family: var(--font-body); font-size: .8rem; font-weight: 600; letter-spacing: .12em; text-transform: uppercase; margin-bottom: 16px; }
.footer-grid li { margin-bottom: 9px; }
.footer-brand .brand { color: #fff; }
.footer-brand p { color: #94a4ac; margin-top: 14px; font-size: .92rem; }
.footer-bottom { border-top: 1px solid rgba(255,255,255,.1); margin-top: 40px; padding-top: 22px; display: flex; flex-wrap: wrap; gap: 12px 18px; justify-content: space-between; align-items: center; font-size: .85rem; color: #7f9099; }
.footer-legal { display: flex; flex-wrap: wrap; gap: 8px 18px; }
.footer-legal a { color: #9fb0b8; }
.footer-legal a:hover { color: var(--accent); }
.footer-builtby { color: #7f9099; }
.footer-builtby a { color: #9fb0b8; text-decoration: none; }
.footer-builtby a:hover { color: var(--accent); }

/* ---------- Sticky mobile CTA (added properly in Sonic Boom; base here) ---------- */
.mobile-cta { position: fixed; left: 0; right: 0; bottom: 0; z-index: 60; display: flex; gap: 1px; background: var(--hairline); box-shadow: 0 -4px 20px rgba(14,36,45,.14); }
.mobile-cta a { flex: 1; text-align: center; padding: 15px 8px; font-weight: 600; font-size: .98rem; display: flex; align-items: center; justify-content: center; gap: 8px; }
.mobile-cta a svg { width: 18px; height: 18px; }
.mobile-cta .mc-call { background: #fff; color: var(--brand-primary); }
.mobile-cta .mc-quote { background: var(--accent-deep); color: #fff; }
.mobile-cta .mc-quote:hover, .mobile-cta .mc-call:hover { color: inherit; }
body { padding-bottom: 0; }
@media (max-width: 1023px){ body.has-mobile-cta { padding-bottom: 58px; } }
@media (min-width: 1024px){ .mobile-cta { display: none; } }

/* ---------- Cookie consent banner ---------- */
.cookie-banner { position: fixed; z-index: 70; left: 12px; right: 12px; bottom: 64px; }
.cookie-banner[hidden] { display: none; }
.cookie-banner__inner { max-width: 720px; margin: 0 auto; background: #fff; border: 1px solid var(--hairline); border-radius: 14px; box-shadow: 0 12px 40px rgba(14,36,45,.22); padding: 18px 20px; display: flex; flex-wrap: wrap; align-items: center; gap: 14px 20px; }
.cookie-banner__text { flex: 1 1 300px; min-width: 0; margin: 0; font-size: .92rem; color: var(--brand-primary-soft); }
.cookie-banner__actions { display: flex; flex-wrap: wrap; gap: 10px; }
.cookie-banner__actions .btn { padding: 11px 20px; font-size: .95rem; }
@media (min-width: 1024px){ .cookie-banner { left: 20px; right: 20px; bottom: 20px; } }

/* ---------- Motion (on-load, subtle). Content visible by default; JS adds .is-armed to animate. ---------- */
.sonic-fade-up { opacity: 1; }
.js .sonic-fade-up.is-armed { opacity: 0; transform: translateY(16px); }
.js .sonic-fade-up.is-played { opacity: 1; transform: translateY(0); transition: opacity .7s var(--ease), transform .7s var(--ease); }
.sonic-stagger-children > * { opacity: 1; }
.js .sonic-stagger-children.is-armed > * { opacity: 0; transform: translateY(18px); }
.js .sonic-stagger-children.is-played > * { opacity: 1; transform: translateY(0); transition: opacity .6s var(--ease), transform .6s var(--ease); }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, .js .sonic-fade-up.is-armed, .js .sonic-stagger-children.is-armed > * { opacity: 1 !important; transform: none !important; transition: none !important; }
}

/* ---------- Generic page (service pages inherit) ---------- */
.page-hero { background: linear-gradient(180deg, var(--surface) 0%, var(--brand-support-wash) 100%); padding-block: clamp(48px, 7vw, 90px); }
.breadcrumbs { font-size: .85rem; color: var(--ink-muted); margin-bottom: 16px; }
.breadcrumbs a { color: var(--brand-primary-soft); }
.prose h2 { margin-top: 2em; margin-bottom: .5em; }
.prose h3 { margin-top: 1.6em; margin-bottom: .4em; }
.prose p, .prose ul { margin-bottom: 1.1em; }
.prose ul li { position: relative; padding-left: 28px; margin-bottom: 10px; }
.prose ul li::before { content: ""; position: absolute; left: 4px; top: 11px; width: 8px; height: 8px; border-radius: 2px; background: var(--accent); transform: rotate(45deg); }

/* =====================================================================
   SONIC BOOM — conversion layer (Stage 3.5)
   ===================================================================== */

/* Hero trust row */
.hero__trust { display: flex; flex-wrap: wrap; gap: 10px 22px; margin-top: 24px; align-items: center; }
.hero__trust .ht { display: inline-flex; align-items: center; gap: 7px; font-size: .9rem; font-weight: 500; color: var(--brand-primary-soft); }
.hero__trust .ht svg { width: 18px; height: 18px; color: var(--accent); flex: 0 0 18px; }
.hero__trust .ht .stars { color: var(--accent); letter-spacing: 1px; }

/* Problem section */
.pains { display: grid; gap: 16px; grid-template-columns: 1fr; }
@media (min-width: 768px){ .pains { grid-template-columns: repeat(2,1fr); } }
.pain { display: flex; gap: 14px; align-items: flex-start; background: #fff; border: 1px solid var(--hairline); border-left: 3px solid var(--accent); border-radius: var(--radius-sm); padding: 18px 20px; box-shadow: var(--shadow-sm); }
.pain svg { width: 24px; height: 24px; color: var(--accent); flex: 0 0 24px; margin-top: 2px; }
.pain strong { color: var(--brand-primary); display: block; margin-bottom: 2px; }
.pain span { font-size: .96rem; color: var(--ink); }
.pain-pivot { text-align: center; margin-top: 34px; font-family: var(--font-display); font-size: clamp(1.3rem,2.4vw,1.7rem); color: var(--brand-primary); }
.pain-pivot b { color: var(--accent-text); font-style: italic; font-weight: 540; }

/* Named process badge */
.process-name { display:inline-flex; align-items:center; gap:8px; background: rgba(143,180,206,.16); border:1px solid rgba(143,180,206,.4); color:#cfe0ec; padding:6px 14px; border-radius:999px; font-size:.82rem; font-weight:600; letter-spacing:.08em; text-transform:uppercase; }

/* Testimonial avatar */
.quote cite { display: flex; align-items: center; gap: 12px; }
.quote .avatar { width: 44px; height: 44px; flex: 0 0 44px; border-radius: 50%; background: var(--brand-primary); color:#fff; display:flex; align-items:center; justify-content:center; font-family: var(--font-display); font-size: 1.05rem; }
.quote cite .meta { display: flex; flex-direction: column; }

/* ---- Multi-step quote form (Action) ---- */
.quote-wrap { display: grid; gap: clamp(28px,4vw,48px); grid-template-columns: 1fr; align-items: start; }
@media (min-width: 900px){ .quote-wrap { grid-template-columns: .9fr 1.1fr; } }
.quote-aside h2 { margin-bottom: 14px; }
.quote-aside .lead { color: var(--brand-primary-soft); margin-bottom: 22px; }
.quote-reassure { list-style: none; padding: 0; margin: 22px 0 0; display: grid; gap: 12px; }
.quote-reassure li { display: flex; gap: 10px; align-items: center; font-weight: 500; color: var(--brand-primary); }
.quote-reassure li svg { width: 20px; height: 20px; color: var(--success); flex: 0 0 20px; }
.quote-call { margin-top: 26px; padding-top: 22px; border-top: 1px solid var(--hairline); }
.quote-call span { display:block; color: var(--ink-muted); font-size:.85rem; margin-bottom: 4px; letter-spacing:.04em; text-transform:uppercase; }
.quote-call a { font-family: var(--font-display); font-size: clamp(1.5rem,3vw,2rem); color: var(--brand-primary); }
.quote-call a:hover { color: var(--accent); }

.qform { background: #fff; border: 1px solid var(--hairline); border-radius: var(--radius); box-shadow: var(--shadow-md); padding: clamp(22px,3vw,32px); }
.qform__progress { display: flex; align-items: center; gap: 10px; margin-bottom: 22px; }
.qform__bar { flex: 1; height: 6px; background: var(--surface-alt); border-radius: 999px; overflow: hidden; }
.qform__bar i { display: block; height: 100%; width: 33%; background: var(--accent); border-radius: 999px; transition: width .35s var(--ease); }
.qform__step-label { font-size: .82rem; font-weight: 600; color: var(--ink-muted); white-space: nowrap; }
.qstep { display: none; }
.qstep.active { display: block; animation: qfade .35s var(--ease); }
@keyframes qfade { from { opacity: 0; transform: translateY(8px);} to {opacity:1; transform:none;} }
.qstep h3 { font-size: 1.3rem; margin-bottom: 4px; }
.qstep p.hint { color: var(--ink-muted); font-size: .92rem; margin-bottom: 18px; }
.chips { display: flex; flex-wrap: wrap; gap: 10px; }
.chip { position: relative; }
.chip input { position: absolute; opacity: 0; inset: 0; cursor: pointer; }
.chip span { display: inline-flex; align-items: center; gap: 8px; padding: 11px 16px; border: 1.5px solid var(--hairline); border-radius: 999px; font-weight: 500; font-size: .96rem; cursor: pointer; transition: all .2s var(--ease); }
.chip input:checked + span { border-color: var(--accent); background: rgba(189,139,60,.08); color: var(--accent-text); }
.chip input:focus-visible + span { outline: 2px solid var(--brand-primary); outline-offset: 2px; }
.qfield { margin-bottom: 16px; }
.qfield label { display: block; font-weight: 600; font-size: .9rem; margin-bottom: 6px; color: var(--brand-primary); }
.qfield input { width: 100%; padding: 13px 15px; border: 1.5px solid var(--hairline); border-radius: var(--radius-sm); font: inherit; font-size: 1rem; background: var(--surface); transition: border-color .2s var(--ease); }
.qfield input:focus { outline: none; border-color: var(--accent); background: #fff; }
.qfield-row { display: grid; gap: 16px; grid-template-columns: 1fr; }
@media (min-width: 560px){ .qfield-row { grid-template-columns: 1fr 1fr; } }
.qform__nav { display: flex; justify-content: space-between; gap: 12px; margin-top: 24px; }
.qform__nav .btn { flex: 0 0 auto; }
.qback { background: none; border: 0; color: var(--ink-muted); font-weight: 600; cursor: pointer; padding: 10px; }
.qback:hover { color: var(--brand-primary); }
.qform__done { text-align: center; padding: 20px 0; }
.qform__done .tick { width: 64px; height: 64px; margin: 0 auto 16px; border-radius: 50%; background: rgba(46,125,91,.12); color: var(--success); display: flex; align-items: center; justify-content: center; }
.qform__done .tick svg { width: 34px; height: 34px; }
.qform__done h3 { margin-bottom: 8px; }
.qerror { color: var(--danger); font-size: .88rem; margin-top: 8px; display: none; }
.qerror.show { display: block; }

/* =====================================================================
   SERVICE / LOCATION PAGE TEMPLATE (Stage 4)
   ===================================================================== */
.page-hero .hero__cta { margin-top: 26px; }
.page-hero .hero__trust { margin-top: 22px; }
.page-hero__media { margin-top: 28px; border-radius: var(--radius); overflow: hidden; box-shadow: var(--shadow-lg); max-height: 420px; }
.page-hero__media img { width: 100%; height: 100%; object-fit: cover; aspect-ratio: 21/9; }

.service-layout { display: grid; gap: clamp(28px,4vw,56px); grid-template-columns: 1fr; align-items: start; }
@media (min-width: 980px){ .service-layout { grid-template-columns: 1fr 340px; } }

.service-body .prose > h2:first-child { margin-top: 0; }
.service-body .benefit-grid { display: grid; gap: 16px; grid-template-columns: 1fr; margin: 1.5em 0; }
@media (min-width: 600px){ .service-body .benefit-grid { grid-template-columns: 1fr 1fr; } }
.benefit { display: flex; gap: 12px; align-items: flex-start; background: #fff; border: 1px solid var(--hairline); border-radius: var(--radius-sm); padding: 16px 18px; box-shadow: var(--shadow-sm); }
.benefit svg { width: 22px; height: 22px; color: var(--accent); flex: 0 0 22px; margin-top: 3px; }
.benefit strong { display:block; color: var(--brand-primary); }
.benefit span { font-size: .95rem; }

/* sticky sidebar quote card */
.service-aside { position: sticky; top: 96px; }
.aside-card { background: var(--brand-primary); color: #d8e2e7; border-radius: var(--radius); padding: 26px; box-shadow: var(--shadow-md); }
.aside-card h3 { color: #fff; font-size: 1.35rem; margin-bottom: 8px; }
.aside-card p { color: #b9c7ce; font-size: .96rem; margin-bottom: 18px; }
.aside-card .btn { width: 100%; justify-content: center; margin-bottom: 10px; }
.aside-card .aside-tel { display:block; text-align:center; color:#fff; font-family:var(--font-display); font-size:1.4rem; margin-top:10px; }
.aside-card .aside-tel:hover { color: var(--accent); }
.aside-trust { list-style:none; padding:0; margin:18px 0 0; display:grid; gap:9px; }
.aside-trust li { display:flex; gap:9px; align-items:center; font-size:.92rem; color:#cfdae0; }
.aside-trust li svg { width:18px; height:18px; color: var(--brand-support); flex:0 0 18px; }

/* FAQ */
.faq-list { max-width: 820px; margin-inline: auto; }
.faq-item { border-bottom: 1px solid var(--hairline); }
.faq-item summary { cursor: pointer; padding: 20px 0; font-family: var(--font-display); font-size: 1.15rem; color: var(--brand-primary); list-style: none; display: flex; justify-content: space-between; gap: 16px; align-items: center; }
.faq-item summary::-webkit-details-marker { display: none; }
.faq-item summary::after { content: "+"; font-size: 1.6rem; color: var(--accent); line-height: 1; transition: transform .2s var(--ease); }
.faq-item[open] summary::after { transform: rotate(45deg); }
.faq-item p { padding: 0 0 20px; color: var(--ink); max-width: none; }

/* related services */
.related-grid { display:grid; gap:14px; grid-template-columns:1fr; }
@media (min-width:600px){ .related-grid { grid-template-columns:1fr 1fr; } }
@media (min-width:900px){ .related-grid { grid-template-columns:1fr 1fr 1fr; } }
.related-card { display:flex; align-items:center; gap:12px; background:#fff; border:1px solid var(--hairline); border-radius:var(--radius-sm); padding:16px 18px; box-shadow:var(--shadow-sm); font-weight:600; color:var(--brand-primary); transition:transform .25s var(--ease), box-shadow .25s var(--ease); }
.related-card:hover { transform:translateY(-3px); box-shadow:var(--shadow-md); color:var(--accent-text); }
.related-card svg { width:22px; height:22px; color:var(--accent); flex:0 0 22px; }

/* service card links (Stage 4 nav fix) */
a.svc__media { display: block; }
.svc__body h3 a { color: inherit; }
.svc__body h3 a:hover { color: var(--accent); }

/* =====================================================================
   ACCESSIBILITY — visible focus (WCAG 2.4.7) + reduced motion already handled
   ===================================================================== */
a:focus-visible,
button:focus-visible,
.btn:focus-visible,
summary:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
[tabindex]:focus-visible {
  outline: 3px solid var(--brand-primary);
  outline-offset: 2px;
  border-radius: 3px;
}
/* On dark sections, use a light ring so it stays visible */
.section--brand-primary a:focus-visible,
.trust-strip a:focus-visible,
.site-footer a:focus-visible,
.cta-band a:focus-visible,
.aside-card a:focus-visible,
.mobile-cta a:focus-visible {
  outline-color: #fff;
}

/* AKA cluster cards + all-services card */
.related-card { align-items: center; }
.related-card__text { display: flex; flex-direction: column; line-height: 1.3; }
.related-card__kicker { font-size: .68rem; text-transform: uppercase; letter-spacing: .09em; color: var(--accent-text); font-weight: 700; margin-bottom: 2px; }
.related-card--all { background: var(--brand-primary); color: #fff; }
.related-card--all:hover { background: var(--brand-primary-soft); color: #fff; }
.related-card--all svg { color: var(--accent); }

/* =====================================================================
   DROPDOWN NAVIGATION
   ===================================================================== */
.menu { list-style: none; margin: 0; padding: 0; }
.menu-item > a { color: var(--brand-primary-soft); font-weight: 500; font-size: .98rem; }
.menu-item > a:hover { color: var(--accent-text); }
.submenu { list-style: none; margin: 0; padding: 0; }
.submenu-all { font-weight: 600; color: var(--accent-text) !important; }
.sub-toggle { background: none; border: 0; cursor: pointer; color: var(--brand-primary); }

/* Desktop: horizontal menu with hover/focus dropdowns */
@media (min-width: 1024px) {
  .menu { display: flex; align-items: center; gap: 28px; }
  .menu-item { position: relative; }
  .menu-item.has-sub > a::after { content: "\25BE"; font-size: .7em; margin-left: 5px; color: var(--ink-muted); }
  .sub-toggle { display: none; }
  .submenu {
    position: absolute; top: 100%; left: 50%; transform: translateX(-50%) translateY(10px);
    min-width: 290px; background: #fff; border: 1px solid var(--hairline); border-radius: var(--radius-sm);
    box-shadow: var(--shadow-md); padding: 8px; opacity: 0; visibility: hidden; transition: opacity .18s var(--ease), transform .18s var(--ease); z-index: 60;
  }
  .menu-item.has-sub:hover > .submenu,
  .menu-item.has-sub:focus-within > .submenu { opacity: 1; visibility: visible; transform: translateX(-50%) translateY(0); }
  .submenu li a { display: block; padding: 10px 14px; border-radius: 6px; font-size: .95rem; color: var(--brand-primary); white-space: nowrap; }
  .submenu li a:hover { background: var(--surface-alt); color: var(--accent-text); }
  .submenu-all { border-top: 1px solid var(--hairline); margin-top: 4px; padding-top: 6px; }
}

/* Mobile: slide-down panel + tap-to-expand submenus */
@media (max-width: 1023px) {
  .nav { position: fixed; left: 0; right: 0; top: 74px; background: #fff; border-bottom: 1px solid var(--hairline); box-shadow: var(--shadow-md); display: none; max-height: calc(100dvh - 74px); overflow-y: auto; }
  .nav.open { display: block; }
  .menu { display: flex; flex-direction: column; padding: 6px 0; }
  .menu-item { border-bottom: 1px solid var(--hairline); display: flex; flex-wrap: wrap; align-items: center; }
  .menu-item > a { flex: 1; padding: 15px 22px; display: block; }
  .sub-toggle { padding: 15px 22px; font-size: 1.05rem; }
  .submenu { display: none; flex-basis: 100%; width: 100%; background: var(--surface); padding: 4px 0 10px; }
  .menu-item.sub-open .submenu { display: block; }
  .menu-item.sub-open .sub-toggle { transform: rotate(180deg); }
  .submenu li a { display: block; padding: 12px 34px; color: var(--brand-primary); font-size: .96rem; }
  .submenu li a:hover { color: var(--accent-text); }
}

/* AKA parent-hub link on Knowledge pages */
.hub-link { display: inline-flex; align-items: center; gap: 6px; font-size: .92rem; color: var(--brand-primary-soft); margin-top: 10px; }
.hub-link svg { width: 16px; height: 16px; color: var(--accent); transform: rotate(180deg); }
.hub-link a { color: var(--accent-text); font-weight: 600; }

/* =====================================================================
   LONG-READ TREATMENT LIBRARY
   Appendix section 2. One treatment per page ROLE, so no single reading
   device appears on more than one tier and no route lands on undesigned
   prose. Routed by page.php from the manifest tier, never guessed.
   ===================================================================== */

:root {
  /* Spacing scale. Section 3.1 requires ONE system; the theme previously
     used ad-hoc pixel values. Everything below derives from this. */
  --s-1: 4px;  --s-2: 8px;  --s-3: 12px; --s-4: 16px;
  --s-5: 24px; --s-6: 32px; --s-7: 48px; --s-8: 64px; --s-9: 96px;

  /* Container widths. Section 3.2: prose is measured in characters, not
     pixels, so the line length stays in the 60-75ch band at any root size. */
  --w-prose: 68ch;
  --w-standard: 1140px;
  --w-wide: 1320px;
}

/* Breadcrumbs ------------------------------------------------------- */
.breadcrumbs__sep { color: var(--ink-muted); margin: 0 2px; }
.breadcrumbs [aria-current="page"] { color: var(--ink-muted); }

/* Router layout ------------------------------------------------------ */
.tr__layout {
  display: grid;
  /* NAME THE SINGLE COLUMN. An implicit `auto` track is free to resolve to the
     max-content of its item, so a 520px-wide specification table inside it
     dragged the whole grid — and with it the container, the body images and the
     document — out to 543px in a 390px viewport. `min-width:0` on the ITEM does
     not fix this; the TRACK is what has to be told it may be narrower. */
  grid-template-columns: minmax(0, 1fr);
  gap: var(--s-7);
}
.tr__body { max-width: var(--w-prose); }

/* =====================================================================
   EDITORIAL STRUCTURE — the section wrapper and its components

   Content authored as nothing but headings and paragraphs cannot be
   designed. A stylesheet has no way to address "this h2 and the prose
   belonging to it": sibling combinators reach the next element, never the
   group. Five long-read treatments were built on that stream and every one
   of them resolved to the same column of text with different heading
   decoration, which is exactly what the operator saw.

   build/enrich-content.mjs wraps each h2 section in .ed-sec and groups
   parallel h3 subsections into .ed-panels. Everything below is only
   possible because those wrappers exist.
   ===================================================================== */

.ed-sec { position: relative; }
.ed-sec + .ed-sec { margin-top: var(--s-8); }
.ed-sec > h2:first-child { margin-top: 0; }
.ed-sec > *:last-child { margin-bottom: 0; }

/* The lede. ONE per page, on the opening paragraph. Applied to every
   section opener it caught 88% of them, which is not a device, it is a
   second body style. */
.ed-lede {
  font-size: 1.14rem; line-height: 1.62; color: var(--ink-heading);
}

/* The statement. A short declarative that already closed its section,
   lifted in place — never copied out of the flow and repeated, which is
   what a pull quote usually does to a page that is already long. */
.ed-statement {
  font-family: var(--font-display);
  font-size: clamp(1.18rem, 2.4vw, 1.5rem);
  line-height: 1.32; color: var(--ink-heading);
  margin-block: var(--s-6); padding-left: var(--s-5);
  border-left: 3px solid var(--accent);
  max-width: 34ch;
}

/* The numbers paragraph, set apart from the argument around it. */
.ed-note {
  background: var(--brand-support-wash);
  border: 1px solid var(--hairline);
  border-radius: var(--radius-sm);
  padding: var(--s-5);
  margin-block: var(--s-6);
  font-size: .98rem;
}

/* Parallel h3 subsections as panels rather than more prose. */
.ed-panels { display: grid; gap: var(--s-4); margin-block: var(--s-6); }
.ed-panel {
  background: var(--white); border: 1px solid var(--hairline);
  border-radius: var(--radius); padding: var(--s-5) var(--s-5) var(--s-4);
}
.ed-panel > h3:first-child { margin-top: 0; margin-bottom: var(--s-3); font-size: 1.12rem; }
.ed-panel > *:last-child { margin-bottom: 0; }
.ed-panel .ed-statement { margin-block: var(--s-4); font-size: 1.08rem; max-width: none; }

/* Body figures, injected by castle_body_figures() at section boundaries.
   Block level and centred, never floated — a floated square generated
   image at column width is the defect appendix section 3 bans. */
.ed-figure { margin-block: var(--s-7); }
.ed-figure img {
  display: block; width: 100%; height: auto;
  border-radius: var(--radius); background: var(--surface-alt);
}
.ed-figure figcaption {
  margin-top: var(--s-3); font-size: .88rem; color: var(--ink-muted);
  padding-left: var(--s-3); border-left: 2px solid var(--accent);
}

/* 1. INDEX DOSSIER — homepage and service pages only.
      A sticky contents rail earns its place on deep reference pages and
      nowhere else; putting it site-wide is the template-rhythm defect
      section 2 bans, just at site scale. */
.tr--dossier .tr__layout { grid-template-columns: 1fr; }
@media (min-width: 1024px) {
  .tr--dossier .tr__layout {
    /* Explicit placement, not declaration order. Section 7c.2: relying on
       source order to fill tracks put an article in a 250px column and
       produced a 39,480px page. */
    grid-template-columns: 260px minmax(0, 1fr);
  }
  .tr--dossier .tr__rail { grid-column: 1; }
  .service-body.tr__body,
.tr--dossier .tr__body { grid-column: 2; }
}
.tr__rail-inner { position: sticky; top: 96px; }
.tr__rail-title {
  display: block; font-size: .78rem; letter-spacing: .08em; text-transform: uppercase;
  color: var(--ink-muted); margin-bottom: var(--s-3);
}
.tr__toc { display: flex; flex-direction: column; gap: var(--s-2); border-left: 2px solid var(--hairline); }
.tr__toc a {
  padding: var(--s-1) 0 var(--s-1) var(--s-4); margin-left: -2px;
  border-left: 2px solid transparent; color: var(--ink-muted);
  font-size: .92rem; line-height: 1.4; text-decoration: none;
}
.tr__toc a:hover { color: var(--accent-text); }
.tr__toc a[aria-current="true"] { color: var(--ink-heading); border-left-color: var(--accent); font-weight: 600; }

/* Dossier sections are banded. Alternate sections take a tinted ground
   that bleeds past the prose measure, so scrolling a 2,400-word page
   passes through visible stages instead of one uninterrupted column. */
.tr--dossier .tr__body {
  /* The banded sections below pull out by exactly this much, so the band
     edges land on the body box and nothing escapes the grid track. A bare
     negative margin here overflows the page, which is how a 462px
     horizontal overflow reached a 390px viewport earlier in this build. */
  --ed-gutter: var(--s-6);
  padding-inline: var(--ed-gutter);
  max-width: calc(var(--w-prose) + var(--s-6) * 2);
}
@media (max-width: 720px) {
  .service-body.tr__body,
  .tr--dossier .tr__body { --ed-gutter: var(--s-4); }
}
/* The service layout already sets this column's width, so the prose cap
   above must not fight it. Only the gutter carries over. */
.service-body.tr__body { max-width: none; }
.prose--dossier .ed-sec { padding-block: var(--s-6); }
.prose--dossier .ed-sec:nth-of-type(even) {
  background: var(--surface-alt);
  border-radius: var(--radius);
  padding-inline: var(--ed-gutter);
  margin-inline: calc(var(--ed-gutter) * -1);
}
.prose--dossier .ed-sec > h2 {
  font-size: clamp(1.45rem, 3vw, 1.9rem);
}
.prose--dossier .ed-sec > h2::before {
  content: ""; display: block; width: 40px; height: 3px;
  background: var(--accent); border-radius: 2px; margin-bottom: var(--s-3);
}
@media (min-width: 700px) {
  .prose--dossier .ed-panels { grid-template-columns: repeat(auto-fit, minmax(min(280px, 100%), 1fr)); }
}

/* 2. EDITORIAL CHAPTERS — area pages.
      The heading moves into its own gutter column on wide screens, so the
      page reads as chapters with a margin rather than as a column. The
      ghost numeral stays, now anchored to the section. */
.prose--chapters { counter-reset: chapter; }
.prose--chapters .ed-sec { counter-increment: chapter; }
.prose--chapters .ed-sec + .ed-sec {
  margin-top: var(--s-9); padding-top: var(--s-6); border-top: 1px solid var(--hairline);
}
.prose--chapters .ed-sec > h2 { position: relative; z-index: 1; }
.prose--chapters .ed-sec > h2::before {
  content: counter(chapter, decimal-leading-zero);
  display: block;
  font-family: var(--font-display); font-size: clamp(2rem, 5vw, 3rem);
  line-height: 1; color: var(--brand-support);
  margin-bottom: var(--s-2);
}
@media (min-width: 1080px) {
  /* The gutter is EXTRA width, not width taken from the prose. Without this
     the 280px column and its gap came out of the 68ch measure and left the
     body running at about 40ch with half the container empty beside it. */
  .tr--chapters .tr__body {
    max-width: calc(var(--w-prose) + 280px + var(--s-7));
  }
  .prose--chapters .ed-sec {
    display: grid; grid-template-columns: 280px minmax(0, 1fr);
    /* COLUMN gap only. `gap` also sets the row gap, and since every paragraph
       is its own auto row here, that put 48px between every paragraph in the
       section on top of their own margins. */
    column-gap: var(--s-7); row-gap: 0;
    align-items: start;
  }
  /* A gutter heading has to be SET for the gutter. Left at the body h2 size
     it broke "Skylight and rooflight work we cover in Lexden" over six lines
     in a 200px column with a dead gap beneath it — the column got narrower
     but the type never did. */
  .prose--chapters .ed-sec > h2 {
    grid-column: 1; grid-row: 1; margin-top: 0;
    font-size: clamp(1.15rem, 1.5vw, 1.4rem); line-height: 1.22;
    hyphens: none; overflow-wrap: break-word;
  }
  .prose--chapters .ed-sec > h2::before { font-size: 2rem; margin-bottom: var(--s-1); }
  /* Every non-heading child lands in its own auto row of column 2, in
     source order, so reading order is unchanged. */
  .prose--chapters .ed-sec > *:not(h2) { grid-column: 2; }
}

/* 3. FEATURE FLOW — guide pages.
      Single elegant column, drop cap, centred chapter rules, and panels
      set as a numbered sequence rather than cards. */
.prose--feature .ed-sec--open > p:first-of-type::first-letter,
.prose--feature .ed-sec:first-child > p:first-of-type::first-letter {
  float: left; font-family: var(--font-display); font-size: 3.4em;
  line-height: .82; padding: 0.06em var(--s-3) 0 0; color: var(--accent-text);
}
.prose--feature .ed-sec + .ed-sec {
  margin-top: var(--s-8); padding-top: var(--s-5); border-top: 1px solid var(--hairline);
}
.prose--feature .ed-sec > h2 { text-align: center; }
.prose--feature .ed-statement { text-align: center; border-left: 0; padding-left: 0; max-width: none; }
.prose--feature .ed-statement::after {
  content: ""; display: block; width: 56px; height: 2px; background: var(--accent);
  margin: var(--s-4) auto 0; border-radius: 2px;
}
.prose--feature .ed-panels { counter-reset: fpanel; gap: 0; }
.prose--feature .ed-panel {
  counter-increment: fpanel; background: none; border: 0; border-radius: 0;
  border-top: 1px solid var(--hairline); padding: var(--s-5) 0 0;
  display: grid; grid-template-columns: 48px minmax(0, 1fr); gap: var(--s-4);
}
.prose--feature .ed-panel::before {
  content: counter(fpanel); grid-column: 1; grid-row: 1 / span 99;
  font-family: var(--font-display); font-size: 1.6rem; line-height: 1;
  color: var(--accent-text);
}
.prose--feature .ed-panel > * { grid-column: 2; }

/* 4. DIRECT ANSWER — answer pages.
      The answer is foregrounded before anything else, then short sections
      marked by a square rather than banded. */
.prose--answer .ed-sec:first-child > p:first-of-type,
.prose--answer > .ed-sec--open > p:first-of-type {
  font-size: 1.16rem; line-height: 1.6; color: var(--ink-heading);
  background: var(--brand-support-wash);
  border-left: 4px solid var(--accent);
  border-radius: 0 var(--radius-sm) var(--radius-sm) 0;
  padding: var(--s-5);
  margin-bottom: var(--s-6);
}
.prose--answer .ed-sec + .ed-sec { margin-top: var(--s-7); }
.prose--answer .ed-sec > h2 { display: flex; align-items: baseline; gap: var(--s-3); font-size: 1.32rem; }
.prose--answer .ed-sec > h2::before {
  content: ""; flex: 0 0 10px; width: 10px; height: 10px;
  background: var(--accent); border-radius: 2px; transform: rotate(45deg);
}

/* 5. DESIGNED ARTICLE — core pages, hubs, legal.
      Centred measure with kicker headings. Read start to finish. */
/* `margin-inline: auto` alone turns a grid item into a shrink-to-fit box: it
   stops stretching to its track and is sized fit-content instead. The track
   here was 351px, but the specification table sets min-width 520px, so the
   body's min-content floor became 520 and it overflowed its own track by 171px
   in a 390px viewport — while every ancestor measured a correct 390. State the
   width, and the auto margins go back to being decoration. */
.prose--article { width: 100%; margin-inline: auto; }
.prose--article .ed-sec + .ed-sec { margin-top: var(--s-8); }
.prose--article .ed-sec > h2 { font-size: 1.5rem; }
.prose--article .ed-sec > h2::after {
  content: ""; display: block; width: 48px; height: 3px;
  background: var(--accent); margin-top: var(--s-3); border-radius: 2px;
}
@media (min-width: 700px) {
  .prose--article .ed-panels { grid-template-columns: repeat(auto-fit, minmax(min(260px, 100%), 1fr)); }
}

/* Read-next block ---------------------------------------------------- */
.related-title { margin-bottom: var(--s-5); }
.related-grid { list-style: none; padding: 0; }
.related-grid li { padding: 0; margin: 0; }
.related-grid li::before { content: none; }
.related-grid a {
  display: block; padding: var(--s-4) var(--s-5);
  background: var(--white); border: 1px solid var(--hairline);
  border-radius: var(--radius-sm); color: var(--ink-heading);
  font-weight: 600; line-height: 1.35; text-decoration: none;
  transition: border-color .2s var(--ease), transform .2s var(--ease);
}
.related-grid a:hover { border-color: var(--accent); transform: translateY(-2px); }
.related-all { margin-top: var(--s-5); }

/* =====================================================================
   GRID MINIMUMS — appendix section 7c.1
   1fr is minmax(auto, 1fr) and that auto minimum resolves to min-content,
   so a track holding a wide table refuses to shrink and the page overflows
   horizontally. Name the minimum and cap it against the container.
   ===================================================================== */
.grid-2 { grid-template-columns: repeat(auto-fit, minmax(min(420px, 100%), 1fr)); }
.grid-3 { grid-template-columns: repeat(auto-fit, minmax(min(300px, 100%), 1fr)); }
.grid-4 { grid-template-columns: repeat(auto-fit, minmax(min(240px, 100%), 1fr)); }
@media (min-width: 600px) { .related-grid { grid-template-columns: repeat(auto-fit, minmax(min(260px, 100%), 1fr)); } }

/* min-width:0 breaks the min-content chain between a grid and a wide child.
   Without it the child's min-content still wins and the fix above does
   nothing. */
.tr__layout > *, .related-grid > *, .grid-2 > *, .grid-3 > *, .grid-4 > * { min-width: 0; }
.service-layout > *, .ed-sec, .ed-sec > *, .ed-panels > *, .prose--chapters .ed-sec > * { min-width: 0; }
.prose table { display: block; overflow-x: auto; max-width: 100%; }

/* =====================================================================
   SPECIFICATION MATRICES — appendix section 2 (long-read design)

   The build shipped with 0 tables across 415 pages, because a writing
   agent asked for prose produces prose. These are authored in
   build/data/tables.json and placed by build/add-tables.mjs.

   A table is the one editorial device that genuinely cannot survive a
   390px viewport unchanged: five columns of specification will not fit,
   and shrinking the type until it does is not a fix. So the wide form
   scrolls inside its own container, and the caption says so.
   ===================================================================== */

.spec-table {
  margin-block: var(--s-7);
  /* The scroll container only contains the table if the container itself is
     allowed to be narrower than its content. A grid or flex item defaults to
     min-width:auto, which resolves to min-content, so the 520px min-width below
     was propagating out through the service-page grid track and overflowed a
     390px viewport by 168px. Name the minimum on the wrapper AND on every
     ancestor that is a grid item. */
  min-width: 0;
  width: 100%;
  max-width: 100%;
  /* Its own scroll container. .prose table already sets display:block and
     overflow-x, which breaks table layout semantics; scrolling the WRAPPER
     keeps the table a table. */
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  border: 1px solid var(--hairline);
  border-radius: var(--radius);
  background: var(--white);
}

/* Undo the blunt global rule for tables that now have a proper wrapper.
   `display:block` on a <table> collapses the column model, so headers stop
   aligning with their cells the moment the content is uneven. */
.spec-table table {
  display: table;
  width: 100%;
  border-collapse: collapse;
  margin: 0;
  font-size: .93rem;
  line-height: 1.45;
}

.spec-table caption {
  caption-side: top;
  text-align: left;
  font-family: var(--font-display);
  font-size: 1.08rem;
  color: var(--ink-heading);
  padding: var(--s-5) var(--s-5) var(--s-3);
  border-bottom: 1px solid var(--hairline);
}

.spec-table thead th {
  background: var(--brand-support-wash);
  color: var(--ink-heading);
  font-size: .8rem;
  letter-spacing: .04em;
  text-transform: uppercase;
  text-align: left;
  vertical-align: bottom;
  padding: var(--s-3) var(--s-4);
  border-bottom: 1px solid var(--hairline);
}
.spec-table thead td { background: var(--brand-support-wash); border-bottom: 1px solid var(--hairline); }

.spec-table tbody th,
.spec-table tbody td {
  padding: var(--s-4);
  text-align: left;
  vertical-align: top;
  border-bottom: 1px solid var(--hairline);
}
.spec-table tbody th {
  color: var(--ink-heading);
  font-weight: 600;
  width: 1%;
  white-space: normal;
  min-width: 150px;
}
.spec-table tbody tr:last-child th,
.spec-table tbody tr:last-child td { border-bottom: 0; }
.spec-table tbody tr:nth-child(even) th,
.spec-table tbody tr:nth-child(even) td { background: var(--surface-alt); }

.spec-table figcaption {
  padding: var(--s-4) var(--s-5);
  border-top: 1px solid var(--hairline);
  font-size: .88rem;
  color: var(--ink-muted);
  background: var(--surface-alt);
  /* The wrapper scrolls, so a long note must not stretch it. */
  position: sticky;
  left: 0;
}
.spec-table caption { position: sticky; left: 0; }

/* Inside the area-page gutter layout the table is one grid child and must
   not force the track open. */
.prose--chapters .ed-sec > .spec-table { grid-column: 2; }

/* How wide the table insists on being, by how many columns it has. Two
   columns fit a 390px phone and must not scroll; five columns of specification
   cannot, and shrinking the type until they do is not a fix. */
.spec-table[data-cols="2"] table { min-width: 0; }
.spec-table[data-cols="3"] table { min-width: 460px; }
.spec-table[data-cols="4"] table { min-width: 560px; }
.spec-table[data-cols="5"] table { min-width: 680px; }
.spec-table[data-cols="2"] tbody th { width: 38%; }

@media (max-width: 620px) {
  .spec-table table { font-size: .88rem; }
  .spec-table tbody th { min-width: 120px; }
  .spec-table caption,
  .spec-table figcaption { padding-inline: var(--s-4); }
}

/* =====================================================================
   LARGE EDITORIAL INDEX — appendix section 4c
   Above ~48 entries a card grid cannot work: 320 entries at two uses per
   image would need 160 photographs. Six featured cards carry the images,
   the rest are compact titled entries grouped by Authority hub.
   ===================================================================== */

.idx__count { color: var(--ink-muted); font-size: .95rem; margin-top: var(--s-4); }

.idx__featured {
  display: grid; gap: var(--s-5);
  grid-template-columns: repeat(auto-fit, minmax(min(280px, 100%), 1fr));
}
.idx__feature {
  display: flex; flex-direction: column; overflow: hidden;
  background: var(--white); border: 1px solid var(--hairline);
  border-radius: var(--radius); text-decoration: none; color: inherit;
  transition: border-color .2s var(--ease), transform .2s var(--ease), box-shadow .2s var(--ease);
}
.idx__feature:hover { border-color: var(--accent); transform: translateY(-3px); box-shadow: var(--shadow-md); }
.idx__feature-media { display: block; background: var(--surface-alt); }
.idx__feature-media img { width: 100%; height: auto; display: block; aspect-ratio: 16 / 10; object-fit: cover; }
.idx__feature-body { padding: var(--s-5); }
.idx__feature-title { font-family: var(--font-display); font-size: 1.12rem; line-height: 1.3; color: var(--ink-heading); }

/* Jump row -------------------------------------------------------- */
.idx__jumpband { padding-block: var(--s-6); }
.idx__jump { display: flex; flex-wrap: wrap; gap: var(--s-3); }
.idx__jump a {
  display: inline-flex; align-items: center; gap: var(--s-2);
  padding: var(--s-2) var(--s-4); border-radius: 999px;
  background: var(--white); border: 1px solid var(--hairline);
  color: var(--ink-heading); font-size: .9rem; font-weight: 600; text-decoration: none;
}
.idx__jump a:hover { border-color: var(--accent); color: var(--accent-text); }
.idx__jump span {
  font-size: .78rem; font-weight: 700; color: var(--ink-muted);
  background: var(--brand-support-wash); border-radius: 999px; padding: 1px var(--s-2);
}

/* Clusters -------------------------------------------------------- */
.idx__cluster { padding-block: var(--s-7); border-top: 1px solid var(--hairline); scroll-margin-top: 96px; }
.idx__cluster:first-child { border-top: 0; padding-top: 0; }
.idx__cluster-head { display: flex; flex-wrap: wrap; align-items: baseline; gap: var(--s-4); margin-bottom: var(--s-5); }
.idx__cluster-head h2 { margin: 0; font-size: clamp(1.3rem, 2.4vw, 1.65rem); }
.idx__cluster-head h2 a { color: var(--ink-heading); text-decoration: none; }
.idx__cluster-head h2 a:hover { color: var(--accent-text); }
.idx__cluster-count { color: var(--ink-muted); font-size: .88rem; }

.idx__sub {
  font-size: .78rem; letter-spacing: .08em; text-transform: uppercase;
  color: var(--ink-muted); margin: var(--s-5) 0 var(--s-3);
}
.idx__list {
  list-style: none; padding: 0; margin: 0;
  display: grid; gap: var(--s-2) var(--s-6);
  grid-template-columns: repeat(auto-fit, minmax(min(280px, 100%), 1fr));
}
.idx__list li { padding: 0; margin: 0; }
.idx__list li::before { content: none; }
.idx__list a {
  display: block; padding: var(--s-2) 0;
  color: var(--ink); text-decoration: none; line-height: 1.4;
  border-bottom: 1px solid transparent;
}
.idx__list a:hover { color: var(--accent-text); border-bottom-color: var(--hairline); }
.idx__list--q a { color: var(--ink-muted); font-size: .95rem; }
.idx__list--q a:hover { color: var(--accent-text); }

/* =====================================================================
   FLOATING WHATSAPP WIDGET — appendix 4g
   Sits above the mobile CTA bar, collapses to icon-only on small screens,
   and the panel caps its height and scrolls so it can never run off the
   viewport on a short phone.
   ===================================================================== */
.wa { position: fixed; right: 16px; bottom: 16px; z-index: 120; }
@media (max-width: 900px) {
  /* Clear the sticky call/quote bar rather than overlapping it. */
  .wa { bottom: calc(64px + 12px); }
}
.wa__fab {
  display: inline-flex; align-items: center; gap: var(--s-2);
  padding: 12px 18px; border: 0; border-radius: 999px; cursor: pointer;
  background: #25D366; color: #06301A; font-weight: 700; font-size: .95rem;
  box-shadow: var(--shadow-md);
}
.wa__fab:hover { background: #1FBE5A; }
.wa__fab:focus-visible { outline: 3px solid var(--brand-primary); outline-offset: 2px; }
@media (max-width: 480px) {
  .wa__fab-label { position: absolute; width: 1px; height: 1px; overflow: hidden; clip-path: inset(50%); }
  .wa__fab { padding: 14px; }
}
.wa__panel {
  position: absolute; right: 0; bottom: calc(100% + 10px);
  width: min(320px, calc(100vw - 32px));
  max-height: min(70vh, 520px); overflow-y: auto; overscroll-behavior: contain;
  background: var(--white); border: 1px solid var(--hairline);
  border-radius: var(--radius); box-shadow: var(--shadow-lg);
  padding: var(--s-5);
}
.wa__head { display: flex; justify-content: space-between; align-items: center; margin-bottom: var(--s-3); }
.wa__close { background: transparent; border: 0; font-size: 22px; line-height: 1; cursor: pointer; color: var(--ink-muted); padding: var(--s-1) var(--s-2); }
.wa__intro { font-size: .82rem; color: var(--ink-muted); margin-bottom: var(--s-4); }
.wa label { display: block; font-size: .78rem; font-weight: 700; color: var(--ink-heading); margin-bottom: var(--s-1); }
.wa input, .wa textarea, .wa select {
  width: 100%; padding: 9px 10px; margin-bottom: var(--s-3);
  border: 1px solid var(--hairline); border-radius: var(--radius-sm);
  font: inherit; font-size: .92rem; color: var(--ink); background: var(--white);
}
.wa__row { display: grid; grid-template-columns: repeat(auto-fit, minmax(min(120px, 100%), 1fr)); gap: var(--s-3); }
.btn--wa { width: 100%; background: #25D366; color: #06301A; border: 0; }
.btn--wa:hover { background: #1FBE5A; color: #06301A; }


/* Content figures: block-level centred banners, 16:9 from a square source. */
.content-figure { margin: var(--s-7) auto; max-width: 100%; }
.content-figure img { aspect-ratio: 16 / 9; object-fit: cover; object-position: center 40%; width: 100%; height: auto; display: block; }

/* Coverage map (contact page) ---------------------------------------- */
.osm { height: clamp(320px, 46vw, 460px); border-radius: var(--radius); overflow: hidden; border: 1px solid var(--hairline); background: var(--surface-alt); }
.osm__fallback { display: grid; place-items: center; height: 100%; margin: 0; padding: var(--s-5); text-align: center; }
.osm__note { margin-top: var(--s-4); text-align: center; color: var(--ink-muted); font-size: .9rem; }
.leaflet-container { font: inherit; }

/* =====================================================================
   AREA PAGE — the homepage shell applied to a location landing page.
   These were the plainest pages on the site and they are the ones local
   search lands on. Reuses the homepage hero, trust strip and proof band.
   ===================================================================== */
.hero--area .breadcrumbs { margin-bottom: var(--s-4); }
.hero--area h1 .hl { display: inline; }

/* Service cards. Distinct from .related-grid: these carry an image and are
   a navigational grid, not a link list. */
.svc-card {
  display: flex; flex-direction: column; overflow: hidden;
  background: var(--white); border: 1px solid var(--hairline);
  border-radius: var(--radius); text-decoration: none; color: inherit;
  transition: border-color .2s var(--ease), transform .2s var(--ease), box-shadow .2s var(--ease);
}
.svc-card:hover { border-color: var(--accent); transform: translateY(-3px); box-shadow: var(--shadow-md); }
.svc-card__media { display: block; background: var(--surface-alt); }
.svc-card__media img { width: 100%; height: auto; display: block; aspect-ratio: 16 / 10; object-fit: cover; }
.svc-card__body { padding: var(--s-5); display: flex; flex-direction: column; gap: var(--s-2); }
.svc-card__title { font-family: var(--font-display); font-size: 1.08rem; line-height: 1.3; color: var(--ink-heading); }
.svc-card__go { font-size: .85rem; font-weight: 600; color: var(--accent-text); display: inline-flex; align-items: center; gap: 6px; }
.svc-card__go svg { width: 14px; height: 14px; }

/* The proof band sits on the dark ground here, so it needs the .on-dark
   corrections rather than inheriting light-ground colours. */



/* =====================================================================
   BUTTONS MUST NOT OVERFLOW THEIR VIEWPORT
   A button with a long label is a single unwrappable line by default, so
   it sets the document's min-content width and takes the whole page with
   it. The visual gate measured 462px inside a 390px viewport from exactly
   one such button. Cap the width and let long labels wrap.
   ===================================================================== */
.btn { max-width: 100%; white-space: normal; text-wrap: balance; }

/* The consent banner outranks the WhatsApp widget.
 *
 * Both are fixed to the bottom of the viewport, and at z-index 70 against the
 * widget's 120 the FAB sat on top of the banner's "Accept all" button at 390px.
 * A consent control that another element covers is not a consent control, and
 * it is the one thing on the page a visitor must be able to act on before
 * anything else. The banner is transient; the widget can wait behind it. */
.cookie-banner { z-index: 130; }

/* Lock the document while the mobile menu is open (appendix 7b.5).
   Without this, a swipe over the open panel scrolls the page behind it. */
html.nav-open { overflow: hidden; }
html.nav-open body { overflow: hidden; }

/* =====================================================================
   DARK GROUNDS — ONE MECHANISM. Appendix 7c.3.
   ---------------------------------------------------------------------
   WHAT WENT WRONG, measured rather than described.

   .section--slate is used by front-page.php, template-service.php and
   template-area.php, so it is on effectively every page of the site, and
   it had NO background rule anywhere. It was never defined. Text styled
   for a dark ground therefore rendered on the light page background:

     .stat__num   white   on cream   1.04:1   (needs 3)
     .stat__label #8FA8C4 on cream   2.35:1   (needs 4.5)
     .step__n     #8FA8C4 on cream   2.35:1   (needs 3)
     .process-name pale   on pale    1.16:1   (needs 4.5)

   1.04:1 is invisible. Meanwhile the corrections that DID exist were
   enumerated one element at a time against .section--brand-primary,
   which is the pattern that guarantees the next dark band forgets one.

   So: every dark band shares this block, and it is the only place dark
   ground colours are set. Adding a band means adding its selector here,
   not writing a new set of overrides.

   MEASURED PAIRS (checked, not assumed):
     white         on #1F3350  12.75:1     on #131F2E  16.63:1
     brand-support on #1F3350   5.20:1     on #131F2E   6.78:1
     wash          on #1F3350  10.93:1     on #131F2E  14.26:1
     ACCENT        on #1F3350   1.80:1  <- never text on dark
   ===================================================================== */

.section--slate { background: var(--brand-primary); }

.section--slate,
.section--brand-primary,
.site-footer {
  color: var(--brand-support);
}

/* Headings and display numerals take white: the largest contrast available,
   and these carry the page. */
.section--slate h2, .section--slate h3, .section--slate .stat__num,
.section--brand-primary h2, .section--brand-primary h3, .section--brand-primary .stat__num,
.site-footer h2, .site-footer h3 {
  color: var(--white);
}

/* Body copy and labels. */
.section--slate p, .section--slate li, .section--slate .stat__label, .section--slate .step p,
.section--brand-primary p, .section--brand-primary li, .section--brand-primary .stat__label, .section--brand-primary .step p {
  color: var(--brand-support);
}

/* Step numerals are large decorative figures, so they take the 3:1 large-text
   threshold, but ACCENT measures 1.80:1 on this ground and cannot be used.
   The wash reads as a numeral without competing with the heading. */
.section--slate .step__n,
.section--brand-primary .step__n {
  color: var(--brand-support-wash);
}

/* :not(.btn) is load-bearing. A button brings its own ground with it, so
   repainting every descendant link would turn primary buttons into pale text
   on claret. Appendix 7c.3 names this exact mistake. */
.section--slate a:not(.btn),
.section--brand-primary a:not(.btn),
.site-footer a:not(.btn) {
  color: var(--brand-support-wash);
}
.section--slate a:not(.btn):hover,
.section--brand-primary a:not(.btn):hover,
.site-footer a:not(.btn):hover {
  color: var(--white);
}

/* The eyebrow pill sits on a translucent ground inside a dark band; on the
   light ground it was pale-on-pale at 1.16:1. */
.section--slate .process-name,
.section--brand-primary .process-name {
  color: var(--brand-support-wash);
  background: rgba(143, 168, 196, .18);
  border-color: rgba(143, 168, 196, .45);
}

/* The footer lockup's location line was ACCENT on the deep ground: 1.94:1.
   It is small text, so it needs the full 4.5:1. */
.site-footer .brand small,
.site-footer .footer-brand small {
  color: var(--brand-support);
}
