/* generated from direction.json */
:root{
  --bg: #F5F8FA;
  --bg-alt: #E5EEF4;
  --surface: #FFFFFF;
  --primary: #14568C;
  --primary-dark: #0D3B61;
  --accent: #C9992E;
  --accent-dark: #A67A1E;
  --ink: #16232E;
  --ink-muted: #55636D;
  --on-dark: #F3F7FA;
  --on-dark-muted: rgba(243,247,250,.72);
  --soft: #7C8A93;
  --line: rgba(20,86,140,.14);
  --display: 'Archivo', system-ui, sans-serif;
  --body: 'Source Sans 3', system-ui, -apple-system, sans-serif;
  --wrap: 1200px;
  --pad: clamp(20px, 5vw, 48px);
  --r: 10px;
}

/* ==========================================================================
   partner-site kit :: base.css
   STRUCTURE ONLY. Carries no visual identity.

   build.py prepends a :root block from direction.json defining every token
   below. Nothing here hardcodes a colour or a typeface, which is why reusing
   this file across partners does not make their sites look alike.

   TOKEN CONTRACT (all required):
     --bg --bg-alt --surface --primary --primary-dark --accent --accent-dark
     --ink --ink-muted --on-dark --on-dark-muted --soft --line
     --display --body
     --wrap --pad --r

   FIXES ALREADY PAID FOR, DO NOT REGRESS:
     - img{height:auto}  or width/height attributes pin height and every
       aspect-ratio rule below is silently ignored
     - reveal/annotation elements drop out below 760px where pills clip
     - prefers-reduced-motion honoured throughout
   ========================================================================== */

*,*::before,*::after{ box-sizing:border-box; }

html{ scroll-behavior:smooth; }
@media (prefers-reduced-motion:reduce){ html{ scroll-behavior:auto; } }

body{
  margin:0;
  background:var(--bg);
  color:var(--ink);
  font-family:var(--body);
  font-size:16px;
  line-height:1.6;
  -webkit-font-smoothing:antialiased;
}

/* height:auto is required, otherwise the width/height HTML attributes pin the
   rendered height and every aspect-ratio rule below is silently ignored. */
img{ max-width:100%; display:block; height:auto; }
a{ color:inherit; }

:focus-visible{ outline:3px solid var(--accent); outline-offset:3px; }

.skip{
  position:absolute; left:-9999px; top:0; z-index:999;
  background:var(--primary); color:var(--on-dark);
  padding:12px 20px; border-radius:0 0 var(--r) 0; text-decoration:none;
}
.skip:focus{ left:0; }

.wrap{ max-width:var(--wrap); margin:0 auto; padding-left:var(--pad); padding-right:var(--pad); }

/* ---------- Type ---------- */
.eyebrow{
  font-size:11px; font-weight:600; letter-spacing:.16em; text-transform:uppercase;
  color:var(--accent); margin:0 0 12px; display:flex; align-items:center; gap:10px;
}
.eyebrow-light{ color:var(--soft); }

h1,h2,h3,h4{ font-family:var(--display); font-weight:800; letter-spacing:-.02em; line-height:1.1; margin:0; }
h1{ font-size:clamp(30px,4.6vw,52px); }
h2{ font-size:clamp(25px,3.4vw,38px); }
h3{ font-size:clamp(18px,2vw,21px); font-weight:700; }
h4{ font-size:16px; font-weight:700; letter-spacing:-.01em; }

.lede{ font-size:clamp(15px,1.6vw,18px); color:var(--ink-muted); max-width:62ch; margin:14px 0 0; }

/* ---------- Buttons ---------- */
.btn{
  display:inline-block; font-family:var(--display); font-weight:700; font-size:15px;
  padding:16px 26px; border-radius:var(--r); text-decoration:none; border:2px solid transparent;
  transition:background .18s ease, transform .18s ease, color .18s ease, border-color .18s ease;
  cursor:pointer; text-align:center;
}
.btn-primary{ background:var(--accent); color:#fff; }
.btn-primary:hover{ background:var(--accent-dark); transform:translateY(-2px); }
.btn-secondary{ background:transparent; border-color:var(--line); color:var(--ink); }
.btn-secondary:hover{ background:var(--bg-alt); }
.cta-band .btn-secondary{ background:#fff; border-color:#fff; color:var(--ink); }
.cta-band .btn-secondary:hover{ background:var(--bg-alt); }
.cta-band .btn-primary{ background:transparent; border-color:#fff; color:#fff; }
.cta-band .btn-primary:hover{ background:rgba(255,255,255,.14); }
.btn-ghost{ background:transparent; color:var(--on-dark); border-color:rgba(243,239,228,.45); }
.btn-ghost:hover{ background:rgba(243,239,228,.12); transform:translateY(-2px); }
.btn-light{ background:var(--on-dark); color:var(--primary); }
.btn-light:hover{ background:#fff; transform:translateY(-2px); }
.btn-dark{ background:var(--primary); color:var(--on-dark); }
.btn-dark:hover{ background:var(--primary-dark); transform:translateY(-2px); }

/* ---------- Header ---------- */
.site-header{
  position:sticky; top:0; z-index:100; background:rgba(231,225,211,.94);
  backdrop-filter:blur(10px); border-bottom:1px solid var(--line);
}
.header-inner{ display:flex; align-items:center; justify-content:space-between; gap:20px; padding-top:14px; padding-bottom:14px; }

.brand{ display:flex; align-items:center; gap:11px; text-decoration:none; flex:none; }

/* Every partner's logo, whatever size or shape the supplied file is, must
   never break the header layout. This is unconditional for every site. */
.brand img{ max-height:40px; width:auto; display:block; }
.brand svg{ height:40px; width:auto; display:block; }

/* Reusable contrast plate. Use this when the supplied logo is light-colored
   or on a transparent background and would be hard to see against the
   header's own background (see references/site-config.md and SKILL.md's
   logo-authoring rule). Wrap the logo markup with
   <span class="mark-plate">...</span> in the site's "mark" field; this class
   is defined once here so no partner needs its own custom CSS for it. */
.mark-plate{ display:inline-flex; align-items:center; justify-content:center;
  background:var(--primary); border-radius:8px; padding:6px 10px; flex:none; }
.mark-plate img{ max-height:30px; }
.mark-plate svg{ height:30px; }

.brand-name{ font-family:var(--display); font-weight:800; font-size:16px; line-height:1.15; letter-spacing:-.02em; }
.brand-name span{ display:block; font-family:var(--body); font-weight:500; font-size:10.5px; letter-spacing:.13em;
  text-transform:uppercase; color:var(--accent); margin-top:2px; }

.nav{ display:flex; align-items:center; gap:26px; }
.nav a{ font-size:14.5px; font-weight:500; text-decoration:none; color:var(--ink); padding:6px 0; position:relative; }
.nav a::after{
  content:""; position:absolute; left:0; right:0; bottom:0; height:2px; background:var(--accent);
  transform:scaleX(0); transform-origin:left; transition:transform .2s ease;
}
.nav a:hover::after, .nav a[aria-current="page"]::after{ transform:scaleX(1); }

.header-cta{ display:flex; align-items:center; gap:16px; flex:none; }
.header-phone{ font-family:var(--display); font-weight:700; font-size:15px; text-decoration:none; white-space:nowrap; }
.header-phone small{ display:block; font-family:var(--body); font-weight:400; font-size:10.5px; color:var(--ink-muted); letter-spacing:.04em; }
.header-cta .btn{ padding:12px 20px; font-size:14px; }

.nav-toggle{
  display:none; background:none; border:1px solid var(--line); border-radius:8px;
  width:44px; height:44px; cursor:pointer; padding:0; place-items:center;
}
.nav-toggle span{ display:block; width:20px; height:2px; background:var(--ink); position:relative; }
.nav-toggle span::before,.nav-toggle span::after{ content:""; position:absolute; left:0; width:20px; height:2px; background:var(--ink); }
.nav-toggle span::before{ top:-6px; } .nav-toggle span::after{ top:6px; }

@media (max-width:1000px){
  .nav-toggle{ display:grid; }
  .nav{
    position:absolute; top:100%; left:0; right:0; background:var(--surface);
    flex-direction:column; align-items:stretch; gap:0; padding:8px var(--pad) 20px;
    border-bottom:1px solid var(--line); display:none;
  }
  .nav.open{ display:flex; }
  .nav a{ padding:14px 0; border-bottom:1px solid var(--line); }
  .header-cta .btn{ display:none; }
}
@media (max-width:560px){ .header-phone{ display:none; } }

/* Nav dropdown (service areas, and reusable for any future grouped nav
   items). Desktop: a positioned menu under the toggle. Mobile: an inline
   expanding section inside the same slide-down nav panel, matching how the
   rest of the mobile nav already behaves (display toggling, not opacity). */
.nav-dropdown{ position:relative; }
.nav-dropdown-toggle{
  font:inherit; font-size:14.5px; font-weight:500; color:var(--ink); background:none; border:none;
  padding:6px 0; cursor:pointer; display:inline-flex; align-items:center; gap:5px;
}
.nav-dropdown-caret{ width:11px; height:11px; transition:transform .15s ease; }
.nav-dropdown.is-open .nav-dropdown-caret{ transform:rotate(180deg); }
.nav-dropdown-menu{
  position:absolute; top:100%; left:0; margin-top:10px; background:var(--surface);
  border:1px solid var(--line); border-radius:var(--r); padding:8px; min-width:210px;
  max-height:340px; overflow-y:auto; display:grid; gap:2px; box-shadow:0 16px 40px rgba(0,0,0,.14);
  opacity:0; visibility:hidden; transform:translateY(-6px); transition:opacity .15s ease, transform .15s ease;
  z-index:60;
}
.nav-dropdown.is-open .nav-dropdown-menu{ opacity:1; visibility:visible; transform:translateY(0); }
.nav-dropdown-menu a{ padding:9px 10px; border-radius:7px; font-size:14px; text-decoration:none; color:var(--ink); }
.nav-dropdown-menu a:hover, .nav-dropdown-menu a:focus-visible{ background:var(--bg-alt); }

@media (max-width:1000px){
  .nav-dropdown-menu{
    position:static; margin-top:6px; box-shadow:none; border:none; padding:0 0 6px 14px;
    max-height:none; opacity:1; visibility:visible; transform:none; display:none;
  }
  .nav-dropdown.is-open .nav-dropdown-menu{ display:grid; }
  .nav-dropdown-toggle{ width:100%; justify-content:space-between; padding:14px 0; border-bottom:1px solid var(--line); }
}

/* ---------- Hero ---------- */
.hero{ display:flex; align-items:stretch; min-height:min(84vh,660px); background:var(--primary); }
.hero-panel{
  flex:0 0 42%; background:var(--primary); color:var(--on-dark);
  padding:clamp(36px,4.5vw,64px) clamp(24px,3.4vw,56px);
  display:flex; flex-direction:column; justify-content:center; gap:18px;
}
.hero-panel h1{ color:var(--on-dark); }
.hero-panel p{ font-size:16px; line-height:1.62; color:var(--on-dark-muted); margin:0; max-width:44ch; }
.hero-actions{ display:flex; flex-direction:column; gap:12px; align-items:flex-start; margin-top:4px; }
.hero-tel{ font-size:14px; color:var(--soft); text-decoration:none; }
.hero-tel b{ color:var(--on-dark); font-size:15px; }

/* reveal stage */
.stage{ flex:1 1 auto; position:relative; overflow:hidden; background:var(--primary-dark); }
.reveal{ position:absolute; inset:0; cursor:ew-resize; touch-action:none; --pos:0; }
.reveal-layer{ position:absolute; inset:0; overflow:hidden; }
.reveal-layer img{ width:100%; height:100%; object-fit:cover; }
.reveal-after{ clip-path:inset(0 calc(100% - var(--pos) * 1%) 0 0); }
/* Placeholder treatment: the "before" is the same photo aged with filters so the
   geometry matches. Replace both with real matched project photos when available. */
.reveal-before img{ filter:sepia(.30) saturate(.66) contrast(.90) brightness(.76) hue-rotate(-6deg); }
.reveal-before::after{
  content:""; position:absolute; inset:0; background:linear-gradient(180deg,rgba(124,98,44,.20),rgba(58,46,22,.30));
}
.reveal-vignette{
  position:absolute; inset:0; pointer-events:none; z-index:4;
  background:radial-gradient(ellipse at 50% 45%,transparent 56%,rgba(42,38,34,.24) 100%);
}

.reveal-handle{
  position:absolute; top:0; bottom:0; left:calc(var(--pos) * 1%); width:2px; background:var(--on-dark);
  box-shadow:0 0 0 1px rgba(42,38,34,.18); opacity:0; transition:opacity .45s ease; z-index:6;
}
.reveal-handle.on{ opacity:1; }
.reveal-grip{
  position:absolute; top:50%; left:50%; transform:translate(-50%,-50%);
  width:54px; height:54px; border-radius:50%; background:var(--on-dark); color:var(--primary);
  display:grid; place-items:center; box-shadow:0 6px 22px rgba(42,38,34,.4); border:none; cursor:ew-resize;
}

.reveal-tag{
  position:absolute; top:20px; z-index:5; font-family:var(--display); font-size:11px; font-weight:700;
  letter-spacing:.14em; padding:6px 13px; border-radius:999px; transition:opacity .4s ease;
}
.tag-before{ right:20px; background:rgba(42,38,34,.6); color:var(--on-dark); }
.tag-after{ left:20px; background:var(--on-dark); color:var(--primary); opacity:0; }
.tag-before.off{ opacity:0; }
.tag-after.on{ opacity:1; }

.reveal-pin{
  position:absolute; z-index:5; transform:translate(-50%,-50%); opacity:0; transition:opacity .5s ease;
  display:flex; align-items:center; gap:8px; pointer-events:none;
}
.reveal-pin.on{ opacity:1; }
.reveal-pin i{ width:11px; height:11px; border-radius:50%; background:var(--accent);
  box-shadow:0 0 0 4px rgba(243,239,228,.9); flex:none; }
.reveal-pin b{ font-size:11.5px; font-weight:600; background:rgba(243,239,228,.95);
  padding:5px 10px; border-radius:6px; white-space:nowrap; }
.reveal-pin.flip{ transform:translate(-100%,-50%); flex-direction:row-reverse; }

@media (max-width:980px){
  .hero{ flex-direction:column; min-height:0; }
  .hero-panel{ flex:none; width:100%; }
  .stage{ flex:none; height:min(58vw,360px); }
  /* Three pins crowd each other once the stage narrows. */
  .reveal-pin[data-x="50"]{ display:none; }
}
@media (max-width:760px){
  /* Pills are wider than the space left beside them and clip at the frame edge,
     so the annotations drop entirely. The sweep and drag still carry the section. */
  .reveal-pin{ display:none; }
}

/* ---------- Service area strip ---------- */
.area-strip{ background:var(--bg-alt); border-bottom:1px solid var(--line); }
.area-inner{ display:flex; align-items:center; gap:14px; flex-wrap:wrap; padding-top:18px; padding-bottom:18px; }
.area-label{ font-size:12px; font-weight:600; letter-spacing:.1em; text-transform:uppercase; color:var(--ink-muted); }
.chip{
  font-size:12.5px; background:var(--surface); border:1px solid var(--line);
  padding:6px 13px; border-radius:999px; text-decoration:none; transition:background .16s ease, border-color .16s ease;
}
a.chip:hover{ background:#fff; border-color:var(--accent); }
.chip-more{ background:transparent; border-style:dashed; color:var(--accent); font-weight:600; }

/* ---------- Sections ---------- */
.section{ padding-top:clamp(52px,7vw,92px); padding-bottom:clamp(52px,7vw,92px); }
.section-surface{ background:var(--surface); }
.section-alt{ background:var(--bg-alt); }
.section-forest{ background:var(--primary); color:var(--on-dark); }
.section-forest h2{ color:var(--on-dark); }
.section-forest .lede{ color:var(--on-dark-muted); }

.section-head{ max-width:66ch; margin-bottom:clamp(28px,3.6vw,46px); }

/* ---------- Services ---------- */
.services{ display:grid; grid-template-columns:repeat(auto-fit,minmax(300px,1fr)); gap:22px; }
.service-card{
  background:var(--surface); border-radius:var(--r); overflow:hidden;
  border:1px solid var(--line); display:flex; flex-direction:column;
  transition:transform .2s ease, box-shadow .2s ease;
}
.section-surface .service-card{ background:var(--bg); }
.service-card:hover{ transform:translateY(-4px); box-shadow:0 14px 34px rgba(42,38,34,.13); }
.service-card img{ width:100%; aspect-ratio:4/3; object-fit:cover; }
.service-body{ padding:24px; display:flex; flex-direction:column; gap:12px; flex:1; }
.service-body h3{ color:var(--ink); }
.service-body p{ margin:0; font-size:14.5px; color:var(--ink-muted); }
.service-list{ margin:0; padding-left:18px; font-size:14px; color:var(--ink-muted); display:grid; gap:5px; }
.service-link{
  margin-top:auto; font-family:var(--display); font-weight:700; font-size:14.5px;
  color:var(--accent); text-decoration:none; display:inline-flex; align-items:center; gap:7px;
}
.service-link:hover{ gap:12px; }

/* ---------- Process ---------- */
.process{ display:grid; grid-template-columns:repeat(auto-fit,minmax(210px,1fr)); gap:20px; counter-reset:step; }
.step{ background:var(--surface); border-radius:var(--r); padding:26px 22px; border-top:4px solid var(--accent); }
.section-surface .step{ background:var(--bg); }
.step-num{ font-family:var(--display); font-weight:800; font-size:30px; color:var(--accent); line-height:1; }
.step h3{ margin:10px 0 7px; }
.step p{ margin:0; font-size:14px; color:var(--ink-muted); }

/* ---------- Why local ---------- */
.why{ display:grid; grid-template-columns:repeat(auto-fit,minmax(250px,1fr)); gap:26px; }
.why-item{ padding-left:20px; border-left:3px solid var(--soft); }
.section-forest .why-item{ border-left-color:var(--accent); }
.why-item h3{ margin-bottom:8px; }
.why-item p{ margin:0; font-size:14.5px; color:var(--ink-muted); }
.section-forest .why-item p{ color:var(--on-dark-muted); }

/* ---------- Gallery ---------- */
.gallery{ display:grid; grid-template-columns:repeat(auto-fit,minmax(320px,1fr)); gap:22px; }
.ba{ border-radius:var(--r); overflow:hidden; border:1px solid var(--line); background:var(--surface); }
.ba-stage{ position:relative; aspect-ratio:4/3; overflow:hidden; cursor:ew-resize; touch-action:none; --pos:50; }
.ba-stage img{ width:100%; height:100%; object-fit:cover; }
.ba-layer{ position:absolute; inset:0; }
.ba-after{ clip-path:inset(0 calc(100% - var(--pos) * 1%) 0 0); }
.ba-before img{ filter:sepia(.30) saturate(.66) contrast(.90) brightness(.76) hue-rotate(-6deg); }
.ba-handle{ position:absolute; top:0; bottom:0; left:calc(var(--pos) * 1%); width:2px; background:var(--on-dark); z-index:3;
  box-shadow:0 0 0 1px rgba(42,38,34,.2); }
.ba-grip{
  position:absolute; top:50%; left:50%; transform:translate(-50%,-50%); width:42px; height:42px;
  border-radius:50%; background:var(--on-dark); color:var(--primary); display:grid; place-items:center;
  box-shadow:0 4px 16px rgba(42,38,34,.36); border:none; cursor:ew-resize;
}
.ba-caption{ padding:16px 20px; display:flex; justify-content:space-between; align-items:center; gap:12px; }
.ba-caption h3{ font-size:16px; }
.ba-caption span{ font-size:12.5px; color:var(--ink-muted); }
.ba-tag{
  position:absolute; top:14px; left:14px; z-index:3; font-family:var(--display); font-size:10px;
  font-weight:700; letter-spacing:.12em; padding:5px 11px; border-radius:999px;
  background:rgba(42,38,34,.62); color:var(--on-dark);
}

.filters{ display:flex; gap:10px; flex-wrap:wrap; margin-bottom:26px; }
.filter{
  font-family:var(--display); font-weight:700; font-size:13.5px; padding:10px 20px; border-radius:999px;
  border:1px solid var(--line); background:transparent; color:var(--ink); cursor:pointer;
  transition:background .16s ease, color .16s ease, border-color .16s ease;
}
.filter:hover{ border-color:var(--accent); }
.filter[aria-pressed="true"]{ background:var(--primary); color:var(--on-dark); border-color:var(--primary); }

/* ---------- Reviews slot ---------- */
.reviews-slot{
  background:var(--surface); border:2px dashed var(--accent); border-radius:var(--r);
  padding:clamp(28px,4vw,44px); text-align:center;
}
.reviews-slot h3{ margin-bottom:10px; }
.reviews-slot p{ margin:0 auto; max-width:52ch; font-size:14.5px; color:var(--ink-muted); }

/* ---------- FAQ ---------- */
.faq{ max-width:820px; }
.faq-item{ border-bottom:1px solid var(--line); }
.faq-q{
  width:100%; background:none; border:none; text-align:left; cursor:pointer;
  font-family:var(--display); font-weight:700; font-size:clamp(15px,1.7vw,17.5px); color:var(--ink);
  padding:22px 44px 22px 0; position:relative; line-height:1.35;
}
.faq-q::after{
  content:""; position:absolute; right:8px; top:50%; width:12px; height:12px; margin-top:-6px;
  border-right:2px solid var(--accent); border-bottom:2px solid var(--accent);
  transform:rotate(45deg); transition:transform .22s ease;
}
.faq-q[aria-expanded="true"]::after{ transform:rotate(-135deg); }
.faq-a{ display:none; padding:0 44px 24px 0; }
.faq-a.open{ display:block; }
.faq-a p{ margin:0; font-size:15px; color:var(--ink-muted); }

/* ---------- CTA band ---------- */
.cta-band{ background:var(--accent); color:#fff; text-align:center; padding:clamp(48px,6vw,80px) 0; }
.cta-band h2{ color:#fff; max-width:20ch; margin:0 auto; }
.cta-band p{ max-width:52ch; margin:16px auto 26px; color:rgba(255,255,255,.9); font-size:16px; }
.cta-actions{ display:flex; gap:14px; justify-content:center; flex-wrap:wrap; }

/* ---------- Reviews embed (Trustindex injects here) ---------- */
.reviews-embed{ min-height:220px; }

/* ---------- Call card (replaces the booking form) ---------- */
.call-card{
  background:var(--primary); color:var(--on-dark); border-radius:var(--r);
  padding:clamp(30px,4vw,46px); display:flex; flex-direction:column; align-items:flex-start; gap:14px;
}
.call-card .eyebrow{ color:var(--soft); }
.call-card h2{ color:var(--on-dark); font-size:clamp(23px,2.7vw,32px); }
.call-card p{ margin:0; color:var(--on-dark-muted); font-size:15.5px; line-height:1.6; max-width:44ch; }
.btn-big{ font-size:17px; padding:18px 30px; margin-top:4px; }
.call-hours{ font-size:13.5px !important; color:var(--soft) !important; }
.call-alt{ font-size:13.5px !important; }
.call-alt a{ color:var(--on-dark); font-weight:600; }

/* ---------- Page hero (inner pages) ---------- */
.page-hero{ background:var(--primary); color:var(--on-dark); padding:clamp(48px,6vw,86px) 0; position:relative; }
.page-hero h1{ color:var(--on-dark); max-width:19ch; }
.page-hero .lede{ color:var(--on-dark-muted); }
.page-hero-grid{ display:grid; grid-template-columns:1.1fr .9fr; gap:clamp(28px,4vw,56px); align-items:center; }
.page-hero-grid img{ width:100%; aspect-ratio:4/3; object-fit:cover; border-radius:var(--r); }
@media (max-width:860px){ .page-hero-grid{ grid-template-columns:1fr; } }

/* Page hero with a real photo as its full-bleed background (a partner's
   own photo behind the H1/lede, not a plain color). This is a shared,
   reusable pattern: <section class="page-hero photo-hero"><img ...>
   <div class="wrap">...</div></section>. A dark tint sits over the photo
   so the on-dark heading/lede text stays readable against any image. */
.photo-hero{ overflow:hidden; }
.photo-hero > img{
  position:absolute; inset:0; width:100%; height:100%; object-fit:cover; z-index:0;
}
.photo-hero::after{
  content:""; position:absolute; inset:0; z-index:1;
  background:linear-gradient(180deg, rgba(0,0,0,.38), rgba(0,0,0,.58));
}
.photo-hero .wrap{ position:relative; z-index:2; }
.photo-hero-center{ text-align:center; }
.photo-hero-center .wrap{ max-width:760px; margin-left:auto; margin-right:auto; }
.photo-hero-center .lede{ margin-left:auto; margin-right:auto; }

/* ---------- Towns grid ---------- */
.towns{ display:grid; grid-template-columns:repeat(auto-fill,minmax(190px,1fr)); gap:14px; }
.town{
  background:var(--surface); border:1px solid var(--line); border-radius:var(--r);
  padding:18px 20px; display:flex; align-items:center; gap:11px;
}
.section-surface .town{ background:var(--bg); }
.town i{ width:9px; height:9px; border-radius:50%; background:var(--accent); flex:none; }
.town b{ font-family:var(--display); font-weight:700; font-size:15px; }

/* ---------- Split content ---------- */
.split{ display:grid; grid-template-columns:1fr 1fr; gap:clamp(28px,4vw,56px); align-items:center; }
.split img{ width:100%; aspect-ratio:4/3; object-fit:cover; border-radius:var(--r); }
@media (max-width:860px){ .split{ grid-template-columns:1fr; } }

/* ---------- Contact ---------- */
.contact-grid{ display:grid; grid-template-columns:.85fr 1.15fr; gap:clamp(28px,4vw,52px); align-items:start; }
@media (max-width:900px){ .contact-grid{ grid-template-columns:1fr; } }
.contact-block{ margin-bottom:28px; }
.contact-block h3{ margin-bottom:8px; }
.contact-block p, .contact-block a{ margin:0; font-size:15.5px; color:var(--ink-muted); text-decoration:none; }
.contact-block a:hover{ color:var(--accent); }
.contact-big{ font-family:var(--display); font-weight:800; font-size:clamp(22px,2.6vw,29px); color:var(--accent); text-decoration:none; }

/* ---------- Footer ---------- */
.site-footer{ background:var(--ink); color:var(--on-dark-muted); padding:clamp(44px,5vw,68px) 0 0; }
.footer-grid{ display:grid; grid-template-columns:1.5fr 1fr 1fr 1.2fr; gap:34px; padding-bottom:38px; }
@media (max-width:900px){ .footer-grid{ grid-template-columns:1fr 1fr; } }
@media (max-width:520px){ .footer-grid{ grid-template-columns:1fr; } }
.site-footer h4{ color:var(--on-dark); margin-bottom:14px; font-size:13px; letter-spacing:.1em; text-transform:uppercase; }
.footer-links{ list-style:none; margin:0; padding:0; display:grid; gap:9px; }
.footer-links a{ font-size:14px; text-decoration:none; color:var(--on-dark-muted); }
.footer-links a:hover{ color:var(--on-dark); }
.footer-brand .brand-name{ color:var(--on-dark); font-size:17px; }
.social-links{ list-style:none; margin:16px 0 0; padding:0; display:flex; gap:10px; flex-wrap:wrap; }
.social-links:empty{ display:none; margin:0; }
.social-link{ display:inline-flex; align-items:center; justify-content:center;
  width:36px; height:36px; border-radius:999px; border:1px solid var(--on-dark-muted);
  color:var(--on-dark-muted); text-decoration:none; transition:border-color .15s, color .15s; }
.social-link:hover{ border-color:var(--on-dark); color:var(--on-dark); }
.social-link .ico{ width:17px; height:17px; stroke:currentColor; }

/* Map widget. build.py always fills this via {{map_embed}}, either a real
   Google Maps iframe (no API key needed, it is the public embed share link)
   or a keyless "Open in Google Maps" fallback derived from the NAP address.
   Never ships empty; see audit.py check_map_embed. */
.map-embed{ width:100%; border-radius:var(--r); overflow:hidden; }
.map-embed iframe{ width:100%; aspect-ratio:16/9; border:0; display:block; }
.map-embed-fallback{ aspect-ratio:auto; display:flex; align-items:center; justify-content:center;
  min-height:160px; background:var(--bg-alt); padding:24px; text-align:center; }

/* Trust badges + NAP block, used on service-area "mini funnel" pages. Only
   ever rendered from real, existing partner data (see trust_badges_html and
   nap_block_html in build.py), never a fabricated claim. */
/* Trust stats row (reuses the site's own .stat cell styling from
   visuals.css) and NAP block, used on service-area "mini funnel" pages.
   Only ever rendered from real, existing partner data (see
   trust_stats_html and nap_block_html in build.py), never a fabricated
   claim. */
.trust-stats{ display:grid; grid-template-columns:repeat(auto-fit,minmax(160px,1fr)); gap:0; }
.nap-block{ list-style:none; margin:10px 0 0; padding:0; display:grid; gap:10px; }
.nap-block li{ display:flex; align-items:center; gap:9px; font-size:14.5px; color:var(--ink); }
.nap-block a{ color:inherit; text-decoration:none; }
.nap-block a:hover{ color:var(--accent); }
.nap-block .ico{ stroke:var(--accent); flex:none; }

/* A plain photo with a visible caption underneath, used for the
   service-area "recent work" gallery. Distinct from .ba, which is the
   before/after drag-slider component and needs a different inner
   structure: this is just a real, properly cropped/framed photo. */
.photo-card{ border-radius:var(--r); overflow:hidden; border:1px solid var(--line); background:var(--surface); }
.photo-card img{ width:100%; aspect-ratio:4/3; object-fit:cover; display:block; }
.photo-card figcaption{ padding:14px 16px; font-size:13.5px; color:var(--ink-muted); }
.lead-form-copy img{ width:100%; aspect-ratio:16/10; object-fit:cover; border-radius:var(--r); margin-bottom:18px; }
.footer-about{ font-size:14px; line-height:1.6; margin:14px 0 0; max-width:36ch; }
.footer-bottom{
  border-top:1px solid rgba(243,239,228,.14); padding:20px 0 28px;
  display:flex; justify-content:space-between; gap:16px; flex-wrap:wrap; font-size:12.5px;
}

/* ---------- Scroll reveal ---------- */
.reveal-up{ opacity:0; transform:translateY(20px); transition:opacity .6s ease, transform .6s ease; }
.reveal-up.in{ opacity:1; transform:none; }
@media (prefers-reduced-motion:reduce){
  .reveal-up{ opacity:1; transform:none; transition:none; }
  .btn:hover, .service-card:hover{ transform:none; }
}

/* ---------- Lead form ---------- */
.lead-form-section{ border-top:1px solid var(--line); }
.lead-form-shell{ display:grid; grid-template-columns:.8fr 1.2fr; gap:clamp(28px,5vw,64px); align-items:start; }
.lead-form-copy{ position:sticky; top:110px; }
.lead-form-copy h2{ max-width:12ch; }
.lead-form{ background:var(--surface); border:1px solid var(--line); border-radius:var(--r); padding:clamp(24px,4vw,40px); box-shadow:0 16px 40px rgba(42,38,34,.08); }
.lead-form-grid{ display:grid; grid-template-columns:1fr 1fr; gap:18px; }
.lead-form label{ display:grid; gap:7px; font-family:var(--display); font-weight:700; font-size:13px; color:var(--ink); }
.lead-form input,.lead-form select,.lead-form textarea{
  width:100%; border:1px solid var(--line); border-radius:8px; background:var(--bg); color:var(--ink);
  font:500 15px/1.45 var(--body); padding:12px 13px; min-height:48px;
}
.lead-form textarea{ resize:vertical; min-height:132px; }
.lead-form input:focus,.lead-form select:focus,.lead-form textarea:focus{ border-color:var(--accent); outline:3px solid var(--accent); outline-offset:2px; }
.lead-form-wide{ grid-column:1/-1; }
.lead-form-note{ color:var(--ink-muted); font-size:12.5px; line-height:1.5; margin:18px 0; }
.lead-form-status{ min-height:1.4em; color:var(--ink-muted); font-size:13px; margin:10px 0 0; }
.honeypot{ position:absolute !important; left:-10000px !important; top:auto !important; width:1px !important; height:1px !important; overflow:hidden !important; }
.footer-form-cta{ margin:18px 0 0; }
.footer-form-cta .btn{ padding:10px 15px; font-size:13px; }

/* ---------- Legal and utility pages ---------- */
.legal-page{ min-height:60vh; }
.prose{ max-width:820px; }
.prose h1{ max-width:18ch; margin-bottom:18px; }
.prose h2{ margin-top:34px; margin-bottom:10px; }
.prose p,.prose li{ color:var(--ink-muted); }
.prose ul{ color:var(--ink-muted); }

@media (max-width:900px){
  .lead-form-shell{ grid-template-columns:1fr; }
  .lead-form-copy{ position:static; }
}
@media (max-width:620px){
  .lead-form-grid{ grid-template-columns:1fr; }
  .lead-form-wide{ grid-column:auto; }
  .lead-form{ padding:22px; }
}


/* ==========================================================================
   Visual devices
   --------------------------------------------------------------------------
   Structure only. Every device below draws itself from the partner tokens, so
   the same device looks like a different studio made it once the palette and
   type change.

   This library exists because of one specific failure. A partner arrived with
   no photography, the build had no vocabulary for "make something to look at",
   and it shipped seven pages of stacked text with zero images, zero graphics
   and zero texture. It passed every audit, because nothing measured whether
   there was anything to see.

   These are NOT signatures. The signature is one bespoke thing per partner and
   still gets designed from scratch. These are the supporting texture around it.
   ========================================================================== */

/* ---------------------------------------------------------------- figures ---
   A framed image. The offset accent panel behind it is what separates a
   designed figure from a bare img dropped on a page. */
.figure{ position:relative; margin:0; }
.figure img{ width:100%; border-radius:var(--radius); position:relative; z-index:1; }
.figure figcaption{
  margin-top:10px; font-size:12.5px; color:var(--ink-muted); line-height:1.5;
}
.figure-offset::before{
  content:""; position:absolute; z-index:0; inset:auto auto -14px -14px;
  width:58%; height:62%; background:var(--accent); border-radius:var(--radius);
  opacity:.16;
}
.figure-rule img{ border:1px solid var(--line); }
.figure-tall img{ aspect-ratio:3/4; object-fit:cover; }
.figure-wide img{ aspect-ratio:16/9; object-fit:cover; }
.figure-square img{ aspect-ratio:1/1; object-fit:cover; }

/* A full width atmospheric band. Never a portfolio claim, so it carries no
   caption naming a place or a project. */
.band{ position:relative; overflow:hidden; background:var(--primary-dark); }
.band img{ width:100%; height:100%; object-fit:cover; position:absolute; inset:0; }
.band-inner{ position:relative; z-index:2; padding-top:clamp(64px,9vw,132px); padding-bottom:clamp(64px,9vw,132px); }
.band::after{
  content:""; position:absolute; inset:0; z-index:1;
  background:linear-gradient(100deg,var(--primary) 8%,rgba(0,0,0,.42) 62%,rgba(0,0,0,.16));
}
.band h2,.band h3,.band p{ color:var(--on-dark); }
.band p{ color:var(--on-dark-muted); }
.band-tint::after{ background:linear-gradient(180deg,rgba(0,0,0,.30),rgba(0,0,0,.62)); }

/* -------------------------------------------------------------- stat band ---
   Numbers set large enough to work as graphics. Only ever fed by fields the
   brief actually supports, never invented to fill the row. */
.statband{ display:grid; grid-template-columns:repeat(auto-fit,minmax(150px,1fr)); gap:1px; background:var(--line); }
.stat{ background:var(--bg); padding:clamp(22px,3vw,34px) clamp(16px,2vw,24px); }
.section-forest .stat,.band .stat{ background:transparent; }
.stat b{
  display:block; font-family:var(--display); font-weight:800;
  font-size:clamp(34px,5.2vw,60px); line-height:1; letter-spacing:-.03em;
  color:var(--accent); font-variant-numeric:tabular-nums;
}
.stat span{ display:block; margin-top:9px; font-size:13px; line-height:1.45; color:var(--ink-muted); }
.section-forest .stat span,.band .stat span{ color:var(--on-dark-muted); }
/* A stat whose value is a word rather than a figure. Numerals stay huge,
   but a word at 60px wraps inside the cell and reads as clipped. */
.stat b.stat-word{ font-size:clamp(21px,2.6vw,32px); letter-spacing:-.01em; }

.statband-bare{ background:transparent; gap:clamp(18px,3vw,40px); }
.statband-bare .stat{ padding:0; }

/* --------------------------------------------------------------- marquee ---
   A moving strip of the things this business actually does or the towns it
   covers. The duplicated half is aria-hidden so it is announced once. */
.marquee{ overflow:hidden; position:relative; padding:15px 0; border-block:1px solid var(--line); }
.marquee-track{ display:flex; width:max-content; gap:0; animation:marquee 42s linear infinite; }
.marquee:hover .marquee-track,.marquee:focus-within .marquee-track{ animation-play-state:paused; }
.marquee-track span{
  display:flex; align-items:center; gap:clamp(20px,3vw,42px); padding-right:clamp(20px,3vw,42px);
  font-family:var(--display); font-weight:700; letter-spacing:-.01em;
  font-size:clamp(15px,2.1vw,22px); white-space:nowrap; color:var(--ink);
}
.marquee-track span i{ font-style:normal; color:var(--accent); font-size:.8em; }
.section-forest .marquee-track span,.band .marquee-track span{ color:var(--on-dark); }
@keyframes marquee{ to{ transform:translateX(-50%); } }
@media (prefers-reduced-motion:reduce){
  .marquee-track{ animation:none; flex-wrap:wrap; width:auto; }
}

/* ---------------------------------------------------------- section edges ---
   Sections that merely stack read as a document. An edge between them reads as
   a designed page, and it costs nothing to render. */
.edge{ position:relative; }
.edge-top-angle{ clip-path:polygon(0 3.2vw,100% 0,100% 100%,0 100%); margin-top:-3.2vw; padding-top:calc(3.2vw + clamp(52px,7vw,92px)); }
.edge-bot-angle{ clip-path:polygon(0 0,100% 0,100% calc(100% - 3.2vw),0 100%); padding-bottom:calc(3.2vw + clamp(52px,7vw,92px)); }
.edge-top-notch{ clip-path:polygon(0 0,42% 0,47% 2.4vw,100% 2.4vw,100% 100%,0 100%); margin-top:-2.4vw; padding-top:calc(2.4vw + clamp(52px,7vw,92px)); }
.edge-top-round{ border-radius:clamp(28px,4vw,64px) clamp(28px,4vw,64px) 0 0; margin-top:clamp(-64px,-4vw,-28px); position:relative; z-index:2; padding-top:calc(clamp(52px,7vw,92px) + 18px); }
.edge-top-step{ clip-path:polygon(0 2.6vw,33% 2.6vw,33% 1.3vw,66% 1.3vw,66% 0,100% 0,100% 100%,0 100%); margin-top:-2.6vw; padding-top:calc(2.6vw + clamp(52px,7vw,92px)); }

/* ------------------------------------------------------------ photo hero ---
   A hero standing on a photograph rather than a flat panel. Asked for
   directly in review: "theres an image in the background, which also makes it
   look a lot better".

   The scrim is not decoration. Type over an unmodified photograph fails
   contrast somewhere in the frame no matter which colour it is, because the
   photograph varies and the type does not. The gradient guarantees a floor
   under the copy side while leaving the far side of the image open. */
.photo-hero{ position:relative; overflow:hidden; background:var(--primary-dark); }
.photo-hero > img{
  position:absolute; inset:0; width:100%; height:100%; object-fit:cover;
  z-index:0;
}
.photo-hero::after{
  content:""; position:absolute; inset:0; z-index:1;
  background:linear-gradient(96deg,
    var(--primary) 0%,
    color-mix(in srgb,var(--primary) 82%,transparent) 38%,
    color-mix(in srgb,var(--primary) 34%,transparent) 66%,
    rgba(0,0,0,.22) 100%);
}
.photo-hero > .wrap{ position:relative; z-index:2; }
.photo-hero h1,.photo-hero h2{ color:var(--on-dark); }
.photo-hero .lede,.photo-hero p{ color:var(--on-dark-muted); }
.photo-hero .eyebrow,.photo-hero .eyebrow-light{ color:var(--soft); }
/* Centre weighted variant, for a page hero with no side by side content. */
.photo-hero-center::after{
  background:linear-gradient(180deg,rgba(0,0,0,.30),
             color-mix(in srgb,var(--primary) 78%,transparent));
}

/* Light variant. Puts a photograph behind a hero that already has dark type
   and its own signature element, without inverting either. The wash stays
   near opaque over the copy and thins towards the far edge, so the picture
   reads as depth rather than as a subject competing with the headline.
   Use when the hero has content that cannot flip to light type. */
.photo-hero-soft{ background:var(--bg); }
.photo-hero-soft::after{
  background:linear-gradient(100deg,
    var(--bg) 0%,
    color-mix(in srgb,var(--bg) 94%,transparent) 34%,
    color-mix(in srgb,var(--bg) 80%,transparent) 62%,
    color-mix(in srgb,var(--bg) 62%,transparent) 100%);
}
.photo-hero-soft h1,.photo-hero-soft h2{ color:var(--ink); }
.photo-hero-soft .lede,.photo-hero-soft p{ color:var(--ink-muted); }
.photo-hero-soft .eyebrow,.photo-hero-soft .eyebrow-light{ color:var(--ink-muted); }

/* A photograph carrying a section rather than sitting beside it. Lighter than
   .band: the image stays legible and the copy sits on a panel over it. */
.photo-panel{ position:relative; overflow:hidden; border-radius:var(--radius); }
.photo-panel > img{ width:100%; height:100%; object-fit:cover; display:block; }
.photo-panel-copy{
  position:absolute; left:0; right:0; bottom:0; z-index:2;
  padding:clamp(20px,3vw,34px);
  background:linear-gradient(0deg,rgba(0,0,0,.78),rgba(0,0,0,.34) 62%,transparent);
  color:var(--on-dark);
}
.photo-panel-copy h3{ color:var(--on-dark); margin:0 0 6px; }
.photo-panel-copy p{ color:var(--on-dark-muted); margin:0; font-size:14.5px; }

/* ---------------------------------------------------- coloured sections ---
   Review note was that the palette read as bland. It was not the palette, it
   was that nine of eleven sections were white or near white and the accent
   only ever appeared as a thin icon stroke. These give a section real colour
   without inventing a new one. */
.section-accent{ background:var(--accent); color:#fff; }
.section-accent h2,.section-accent h3{ color:#fff; }
.section-accent p,.section-accent .lede{ color:rgba(255,255,255,.88); }
.section-accent .eyebrow,.section-accent .eyebrow-light{ color:rgba(255,255,255,.72); }

.section-tint{ background:color-mix(in srgb,var(--accent) 11%,var(--bg)); }
.section-deep{ background:var(--primary-dark); color:var(--on-dark); }
.section-deep h2,.section-deep h3{ color:var(--on-dark); }
.section-deep p,.section-deep .lede{ color:var(--on-dark-muted); }
.section-deep .eyebrow,.section-deep .eyebrow-light{ color:var(--soft); }

/* -------------------------------------------------------------- patterns ---
   Pure gradient texture. Trade flavoured, so pick the one that belongs to the
   work rather than the one that looks nicest in isolation. Applied to a
   section, they sit under the content at low opacity. */
.pat{ position:relative; }
.pat > *{ position:relative; z-index:1; }
.pat::before{ content:""; position:absolute; inset:0; z-index:0; opacity:var(--pat-a,.055); pointer-events:none; }

/* blueprint, for anyone who works from drawings */
.pat-blueprint::before{
  background-image:linear-gradient(var(--pat-c,currentColor) 1px,transparent 1px),
                   linear-gradient(90deg,var(--pat-c,currentColor) 1px,transparent 1px);
  background-size:34px 34px;
}
/* subway tile, for tile setters, bath remodels, backsplash work */
.pat-tile::before{
  background-image:linear-gradient(var(--pat-c,currentColor) 1.5px,transparent 1.5px),
                   linear-gradient(90deg,var(--pat-c,currentColor) 1.5px,transparent 1.5px);
  background-size:76px 38px; background-position:0 0,38px 0;
}
/* brushed, for painters */
.pat-brush::before{
  background-image:repeating-linear-gradient(96deg,var(--pat-c,currentColor) 0 1px,transparent 1px 7px);
}
/* diagonal hatch, general trades */
.pat-diag::before{
  background-image:repeating-linear-gradient(45deg,var(--pat-c,currentColor) 0 2px,transparent 2px 13px);
}
/* board and batten, for siding, decks, fencing, carpentry */
.pat-board::before{
  background-image:repeating-linear-gradient(90deg,var(--pat-c,currentColor) 0 2px,transparent 2px 58px);
}
/* dots, quietest option when the trade suggests nothing in particular */
.pat-dots::before{
  background-image:radial-gradient(var(--pat-c,currentColor) 1.4px,transparent 1.4px);
  background-size:24px 24px;
}
/* shingle scallop, for roofers */
.pat-shingle::before{
  background-image:radial-gradient(circle at 50% 100%,transparent 13px,var(--pat-c,currentColor) 13px 14px,transparent 14px);
  background-size:32px 20px;
}
.pat-strong{ --pat-a:.10; }
.pat-faint{ --pat-a:.03; }

/* ----------------------------------------------------------- sticky split ---
   One panel pins while the detail beside it scrolls. Reads as considered and
   costs no JavaScript. Collapses to plain stacking on narrow screens, where
   sticky behaviour is mostly unwanted. */
.split-sticky{ display:grid; grid-template-columns:minmax(0,.9fr) minmax(0,1.1fr); gap:clamp(28px,5vw,72px); align-items:start; }
.split-pin{ position:sticky; top:calc(var(--header-h,72px) + 26px); }
.split-flow > * + *{ margin-top:clamp(28px,4vw,52px); }
.split-flow article{ padding-bottom:clamp(28px,4vw,52px); border-bottom:1px solid var(--line); }
.split-flow article:last-child{ border-bottom:0; padding-bottom:0; }
@media (max-width:900px){
  .split-sticky{ grid-template-columns:1fr; }
  .split-pin{ position:static; }
}

/* -------------------------------------------------------------- step flow ---
   Process as a path rather than a numbered list. The connector line is what
   makes it read as a sequence. */
.stepflow{ display:grid; grid-template-columns:repeat(auto-fit,minmax(190px,1fr)); gap:clamp(20px,3vw,34px); position:relative; }
.stepflow .step{ position:relative; padding-top:52px; }
.stepflow .step::before{
  content:""; position:absolute; top:19px; left:0; right:0; height:2px;
  background:repeating-linear-gradient(90deg,var(--line) 0 7px,transparent 7px 13px);
}
.stepflow .step:last-child::before{ right:50%; }
.stepflow .step:first-child::before{ left:50%; }
.stepflow .step-num{
  position:absolute; top:0; left:0; width:40px; height:40px; border-radius:50%;
  display:grid; place-items:center; background:var(--accent); color:#fff;
  font-family:var(--display); font-weight:800; font-size:15px; z-index:1;
}
.stepflow .step h3{ font-size:17px; margin:0 0 7px; }
.stepflow .step p{ font-size:14.5px; color:var(--ink-muted); margin:0; line-height:1.6; }
@media (max-width:640px){
  .stepflow .step::before{ display:none; }
}

/* -------------------------------------------------------------- big quote ---
   One sentence at a size that makes it an image. Use once per site at most. */
/* The measure lives on the p, never on the wrapper. ch resolves against the
   font of the element it is declared on, and the wrapper inherits body text
   at 16px while the p runs up to 54px display. Declaring 22ch on the wrapper
   measured it in body type and produced a 219px column, which broke a 54px
   sentence across nine lines on four pages of a live partner site. */
.bigquote{ max-width:100%; }
.bigquote p{
  font-family:var(--display); font-weight:700; letter-spacing:-.028em;
  font-size:clamp(27px,4.6vw,54px); line-height:1.12; margin:0; color:var(--ink);
  max-width:22ch; text-wrap:balance;
}
.section-forest .bigquote p,.band .bigquote p,
.section-deep .bigquote p{ color:var(--on-dark); }
.bigquote .bq-mark{ color:var(--accent); }
.bigquote cite{
  display:block; margin-top:20px; font-family:var(--body); font-style:normal;
  font-size:13px; letter-spacing:.09em; text-transform:uppercase; color:var(--ink-muted);
}

/* ------------------------------------------------------------ swatch wall ---
   Material or colour fields. For a painter these are paint colours, for a
   remodeler the finishes actually installed. Labels come from the brief. */
.swatchwall{ display:grid; grid-template-columns:repeat(auto-fit,minmax(128px,1fr)); gap:12px; }
.swatch{
  border-radius:var(--radius); overflow:hidden; background:var(--surface);
  border:1px solid var(--line); transition:transform .3s ease, box-shadow .3s ease;
}
.swatch:hover{ transform:translateY(-4px); box-shadow:0 12px 26px rgba(0,0,0,.13); }
.swatch i{ display:block; height:96px; background:var(--sw,var(--accent)); }
.swatch b{ display:block; padding:11px 12px 3px; font-family:var(--display); font-weight:700; font-size:13.5px; }
.swatch span{ display:block; padding:0 12px 12px; font-size:11.5px; color:var(--ink-muted); letter-spacing:.05em; }
/* material fills, so a swatch can read as oak or stone rather than flat paint */
.sw-wood{ background:
  repeating-linear-gradient(93deg,rgba(0,0,0,.07) 0 1px,transparent 1px 6px),
  linear-gradient(160deg,#b8895a,#95653c); }
.sw-stone{ background:
  radial-gradient(circle at 30% 25%,rgba(255,255,255,.5),transparent 42%),
  radial-gradient(circle at 72% 68%,rgba(0,0,0,.10),transparent 38%),
  linear-gradient(150deg,#d9d6cf,#b3aea4); }
.sw-tile{ background:
  linear-gradient(rgba(255,255,255,.42) 2px,transparent 2px) 0 0/44px 22px,
  linear-gradient(90deg,rgba(255,255,255,.42) 2px,transparent 2px) 22px 0/44px 22px,
  linear-gradient(160deg,#9fb2b4,#7d9396); }
.sw-metal{ background:linear-gradient(103deg,#8f979c,#c9ced1 42%,#7d858a); }

/* --------------------------------------------------------- annotated spec ---
   A drawing with numbered call-outs. Carries real information, which is what
   separates it from decoration. */
.spec{ position:relative; }
.spec svg{ width:100%; height:auto; display:block; }
.spec-pin{
  position:absolute; transform:translate(-50%,-50%); display:flex; align-items:center; gap:8px;
}
.spec-pin i{
  width:25px; height:25px; border-radius:50%; background:var(--accent); color:#fff;
  display:grid; place-items:center; font-style:normal; font-family:var(--display);
  font-weight:800; font-size:12px; flex:none;
}
.spec-pin b{
  font-size:12px; font-weight:600; background:var(--surface); color:var(--ink);
  padding:5px 10px; border-radius:100px; border:1px solid var(--line); white-space:nowrap;
}
@media (max-width:720px){ .spec-pin b{ display:none; } }

/* ------------------------------------------------------------------ icons ---
   Referenced from the sprite the build injects:
   <svg class="ico" aria-hidden="true"><use href="#ico-roller"></use></svg> */
.ico{ width:26px; height:26px; stroke:var(--accent); fill:none; stroke-width:1.6;
      stroke-linecap:round; stroke-linejoin:round; display:block; }
.ico-lg{ width:38px; height:38px; }
.ico-sm{ width:19px; height:19px; }
.icobox{
  width:52px; height:52px; border-radius:var(--radius); background:var(--bg-alt);
  display:grid; place-items:center; margin-bottom:16px;
}
.section-forest .icobox,.band .icobox{ background:rgba(255,255,255,.09); }
.section-forest .ico,.band .ico{ stroke:var(--on-dark); }

/* ------------------------------------------------------------ card polish ---
   Applied on top of the existing service card. An index numeral and an accent
   rule give a card a top and a bottom instead of it being a floating box. */
.card-num{
  font-family:var(--display); font-weight:800; font-size:12px; letter-spacing:.14em;
  color:var(--accent); display:block; margin-bottom:12px;
}
.card-accent{ border-top:3px solid var(--accent); }
.card-hover{ transition:transform .32s cubic-bezier(.2,.8,.2,1), box-shadow .32s ease; }
.card-hover:hover{ transform:translateY(-6px); box-shadow:0 18px 40px rgba(0,0,0,.13); }

/* Heading with a rule running out to the margin. */
.rule-head{ display:flex; align-items:center; gap:18px; }
.rule-head::after{ content:""; flex:1 1 auto; height:1px; background:var(--line); }

/* ----------------------------------------------------------- coverage map ---
   Towns positioned on a plotted field. Every partner has a service area, so
   this device is available even with no photography at all. */
.covermap{
  position:relative; aspect-ratio:4/3; border-radius:var(--radius);
  background:var(--bg-alt); border:1px solid var(--line); overflow:hidden;
}
.covermap::before{
  content:""; position:absolute; inset:0; opacity:.5;
  background-image:linear-gradient(var(--line) 1px,transparent 1px),
                   linear-gradient(90deg,var(--line) 1px,transparent 1px);
  background-size:46px 46px;
}
.covermap-pin{ position:absolute; transform:translate(-50%,-50%); display:flex; align-items:center; gap:7px; }
.covermap-pin i{
  width:10px; height:10px; border-radius:50%; background:var(--accent); flex:none;
  box-shadow:0 0 0 0 color-mix(in srgb,var(--accent) 55%,transparent);
  animation:pin-pulse 2.6s ease-out infinite;
}
.covermap-pin b{ font-size:11.5px; font-weight:600; color:var(--ink); white-space:nowrap; }
.covermap-pin.hq i{ width:15px; height:15px; }
.covermap-pin:nth-child(2) i{ animation-delay:.4s; }
.covermap-pin:nth-child(3) i{ animation-delay:.8s; }
.covermap-pin:nth-child(4) i{ animation-delay:1.2s; }
.covermap-pin:nth-child(5) i{ animation-delay:1.6s; }
@keyframes pin-pulse{
  0%{ box-shadow:0 0 0 0 color-mix(in srgb,var(--accent) 55%,transparent); }
  70%{ box-shadow:0 0 0 15px transparent; }
  100%{ box-shadow:0 0 0 0 transparent; }
}
@media (prefers-reduced-motion:reduce){ .covermap-pin i{ animation:none; } }

/* ------------------------------------------------------------- reveal set ---
   The kit already reveals on scroll. This staggers children of one container
   so a grid arrives as a group rather than all at once. */
.stagger > *{ transition-delay:calc(var(--i,0) * 70ms); }


/* ------------------------------------------------------------------ legal ---
   Privacy policy, terms and anything else that is a document rather than a
   sales page. One readable column, generous spacing, no devices. */
.legal{ max-width:68ch; }
.legal h2{ font-size:clamp(19px,2.2vw,24px); margin:clamp(30px,4vw,44px) 0 10px; }
.legal h2:first-of-type{ margin-top:0; }
.legal p{ margin:0 0 14px; line-height:1.72; color:var(--ink-muted); }
.legal a{ color:var(--accent); font-weight:600; }
.legal-updated{
  font-size:12.5px; letter-spacing:.06em; text-transform:uppercase;
  color:var(--ink-muted); margin:0 0 clamp(24px,3vw,34px);
}
.legal-list{ margin:0 0 16px; padding-left:20px; }
.legal-list li{ margin-bottom:10px; line-height:1.7; color:var(--ink-muted); }
.legal-list b{ color:var(--ink); }


/* ---- signature, this partner only ---- */
/* ==========================================================================
   Signature: The Rounds
   The partner's own gnome mascot, cropped from their supplied logo, stands
   on a line-art house and moves between four pin stops. Four real radio
   inputs form a native browser radio group, so Tab and the arrow keys
   already move the selection with no custom JavaScript. The checked radio
   is targeted with :has() to both slide the gnome to that pin and swap the
   visible readout card, so the mechanic is correct before any script runs.
   Without :has() support the page still shows stop one, static and complete.
   JavaScript only keeps an aria-live status line in sync for screen readers.
   ========================================================================== */
.rounds-stage{
  position:relative; aspect-ratio:600/360; width:100%; max-width:560px; margin:0 auto;
}
.rounds-input{
  position:absolute; width:1px; height:1px; padding:0; margin:-1px;
  overflow:hidden; clip:rect(0,0,0,0); white-space:nowrap; border:0;
}
.rounds-scene{ position:absolute; inset:0; }
.rounds-scene svg{ width:100%; height:100%; display:block; }

.rounds-pin{
  position:absolute; z-index:3; transform:translate(-50%,-50%);
  display:flex; align-items:center; justify-content:center;
  width:30px; height:30px; border-radius:50%; cursor:pointer;
  background:var(--surface); border:2.5px solid var(--primary); color:var(--primary);
  font-family:var(--display); font-weight:700; font-size:13px;
  box-shadow:0 6px 14px rgba(0,0,0,.16); transition:background .18s ease, color .18s ease, transform .18s ease;
}
.rounds-pin-1{ left:20%; top:56%; }
.rounds-pin-2{ left:47%; top:79%; }
.rounds-pin-3{ left:72%; top:61%; }
.rounds-pin-4{ left:14%; top:88%; }
.rounds-pin:hover{ transform:translate(-50%,-50%) scale(1.08); }
.rounds-input:checked + .rounds-pin{ background:var(--accent); border-color:var(--accent-dark); color:#fff; }
.rounds-input:focus-visible + .rounds-pin{ outline:3px solid var(--primary); outline-offset:3px; }

.rounds-gnome{
  position:absolute; z-index:2; width:64px; height:64px;
  background:url("/images/logo-mark.png") center / contain no-repeat;
  left:20%; top:70%; transform:translate(-50%,-88%);
  transition:left .5s cubic-bezier(.4,.15,.2,1), top .5s cubic-bezier(.4,.15,.2,1);
  filter:drop-shadow(0 8px 10px rgba(0,0,0,.22));
}
.rounds-stage:has(#rounds-2:checked) .rounds-gnome{ left:47%; top:92%; }
.rounds-stage:has(#rounds-3:checked) .rounds-gnome{ left:72%; top:75%; }
.rounds-stage:has(#rounds-4:checked) .rounds-gnome{ left:14%; top:100%; }

.rounds-cards{ margin-top:clamp(24px,4vw,40px); max-width:520px; margin-left:auto; margin-right:auto; text-align:center; }
.rounds-card{ display:none; }
.rounds-card[data-card="1"]{ display:block; }
.rounds:has(#rounds-1:checked) .rounds-card[data-card="1"]{ display:block; }
.rounds:has(#rounds-1:checked) .rounds-card[data-card="2"],
.rounds:has(#rounds-1:checked) .rounds-card[data-card="3"],
.rounds:has(#rounds-1:checked) .rounds-card[data-card="4"]{ display:none; }
.rounds:has(#rounds-2:checked) .rounds-card[data-card="1"]{ display:none; }
.rounds:has(#rounds-2:checked) .rounds-card[data-card="2"]{ display:block; }
.rounds:has(#rounds-2:checked) .rounds-card[data-card="3"],
.rounds:has(#rounds-2:checked) .rounds-card[data-card="4"]{ display:none; }
.rounds:has(#rounds-3:checked) .rounds-card[data-card="1"],
.rounds:has(#rounds-3:checked) .rounds-card[data-card="2"]{ display:none; }
.rounds:has(#rounds-3:checked) .rounds-card[data-card="3"]{ display:block; }
.rounds:has(#rounds-3:checked) .rounds-card[data-card="4"]{ display:none; }
.rounds:has(#rounds-4:checked) .rounds-card[data-card="1"],
.rounds:has(#rounds-4:checked) .rounds-card[data-card="2"],
.rounds:has(#rounds-4:checked) .rounds-card[data-card="3"]{ display:none; }
.rounds:has(#rounds-4:checked) .rounds-card[data-card="4"]{ display:block; }

.rounds-card h3{ display:flex; align-items:center; justify-content:center; gap:9px; margin:2px 0 8px; }
.rounds-card .ico{ width:22px; height:22px; flex:none; }
.rounds-card .service-link{ display:inline-block; margin-top:6px; }

.rounds-status{
  margin:18px 0 0; text-align:center; font-size:12.5px; font-weight:600; letter-spacing:.04em;
  color:var(--ink-muted); text-transform:uppercase;
}

@media (prefers-reduced-motion:reduce){
  .rounds-gnome{ transition:none; }
}
@media (max-width:520px){
  .rounds-pin{ width:26px; height:26px; font-size:11.5px; }
  .rounds-gnome{ width:50px; height:50px; }
}
