/* ============ Family Locksmith — warm/light design system ============ */
:root{
  --paper:#FFFFFF; --paper-2:#F6F7F9; --paper-3:#EEF0F3;
  --card:#FFFFFF; --card-soft:#F8F9FB;
  --espresso:#17181C; --espresso-2:#202128;
  --ink:#121319; --text-2:#3C3F47; --muted:#65676E; --faint:#9A9CA3;
  --line:#EAEBEE; --line-2:#DCDEE4; --line-3:#CBCED6;
  --amber:#F5A524; --amber-2:#EA9310; --amber-3:#FFBB45; --amber-deep:#B4770A;
  --amber-ink:#3E2803; --amber-tint:#FDEFD5;
  --cream:#F0E8D8; --cream-2:#C6B9A3; --ink-2:#F6F7F9;
  --ok:#2E9E68; --ok-tint:#E6F3EC; --wa:#25D366;
  --maxw:1200px;
  --r-sm:10px; --r:14px; --r-lg:22px; --r-xl:30px;
  --sans:"Manrope",-apple-system,BlinkMacSystemFont,"Segoe UI",Arial,sans-serif;
  --display:"Archivo","Manrope",-apple-system,BlinkMacSystemFont,Arial,sans-serif;
  --shadow:0 22px 46px -22px rgba(18,20,35,.16);
  --shadow-sm:0 8px 22px -12px rgba(18,20,35,.12);
  --shadow-amber:0 18px 40px -16px rgba(234,143,12,.4);
  /* motion: strong curves, because the browser defaults feel weak */
  --hero-scrim:linear-gradient(95deg, #fff 0%, rgba(255,255,255,.97) 30%, rgba(255,255,255,.84) 46%, rgba(255,255,255,.38) 64%, rgba(255,255,255,0) 84%);
  --hero-scrim-v:linear-gradient(180deg, rgba(255,255,255,.97) 0%, rgba(255,255,255,.9) 46%, rgba(255,255,255,.45) 100%);
  --ease-out:cubic-bezier(.23,1,.32,1);
  --ease-in-out:cubic-bezier(.77,0,.175,1);
}
*{box-sizing:border-box}
html{scroll-behavior:smooth}
@media (prefers-reduced-motion:reduce){html{scroll-behavior:auto}}
body{
  margin:0; background:var(--paper); color:var(--text-2);
  font-family:var(--sans); font-size:17px; line-height:1.65;
  -webkit-font-smoothing:antialiased; overflow-x:hidden;
}
a{color:inherit; text-decoration:none}
img{max-width:100%; display:block}
h1,h2,h3,h4{font-family:var(--display); font-weight:800; line-height:1.05; letter-spacing:-.02em; margin:0; color:var(--ink); text-wrap:balance}
p{margin:0}
.container{width:100%; max-width:var(--maxw); margin:0 auto; padding:0 clamp(18px,4vw,40px)}
.amber{color:var(--amber-deep)}
.sr-only{position:absolute; width:1px; height:1px; padding:0; margin:-1px; overflow:hidden; clip:rect(0,0,0,0); border:0}

/* ---- buttons ---- */
.btn{
  display:inline-flex; align-items:center; gap:9px; font-family:var(--sans);
  font-weight:700; font-size:16px; padding:14px 22px; border-radius:999px;
  border:1.5px solid transparent; cursor:pointer;
  transition:transform .14s var(--ease-out), box-shadow .2s var(--ease-out), background .2s, border-color .2s;
  white-space:nowrap; line-height:1;
}
/* the one animation an emergency visitor genuinely benefits from: proof of the tap */
.btn:active{transform:scale(.97)}
.btn:focus-visible{outline:none; box-shadow:0 0 0 3px var(--amber-tint), 0 0 0 5px var(--amber-2)}
.btn svg{width:19px; height:19px}
.btn-amber{background:var(--amber); color:var(--amber-ink); box-shadow:var(--shadow-amber)}
.btn-amber:hover{transform:translateY(-2px); background:var(--amber-3)}
.btn-ghost{background:var(--card); border-color:var(--line-2); color:var(--ink)}
.btn-ghost:hover{border-color:var(--amber-2); color:var(--amber-deep); transform:translateY(-2px)}
.btn-wa{background:var(--wa); color:#04220f}
.btn-wa:hover{transform:translateY(-2px); filter:brightness(1.04)}
.btn-lg{font-size:18px; padding:17px 30px}
.btn-block{width:100%; justify-content:center}
.btn-dark{background:var(--espresso); color:#fff}
.btn-dark:hover{transform:translateY(-2px); background:#161210}

/* ---- eyebrow / labels ---- */
.eyebrow{display:inline-flex; align-items:center; gap:9px; font-family:var(--sans); font-weight:700;
  font-size:13px; letter-spacing:.14em; text-transform:uppercase; color:var(--amber-deep)}
.live-dot{width:9px; height:9px; border-radius:50%; background:var(--ok); box-shadow:0 0 0 0 rgba(46,158,104,.5); animation:pulse 2s infinite}
@keyframes pulse{0%{box-shadow:0 0 0 0 rgba(46,158,104,.5)}70%{box-shadow:0 0 0 9px rgba(46,158,104,0)}100%{box-shadow:0 0 0 0 rgba(46,158,104,0)}}
@media (prefers-reduced-motion:reduce){.live-dot{animation:none}}
.section-tag{color:var(--amber-deep); letter-spacing:.14em; text-transform:uppercase; font-size:13px; font-weight:700; font-family:var(--sans)}

/* ---- header ---- */
.header{position:sticky; top:0; z-index:60; transition:background .3s, border-color .3s, backdrop-filter .3s, box-shadow .3s;
  border-bottom:1px solid transparent}
.header.scrolled{background:rgba(255,255,255,.85); backdrop-filter:blur(14px); border-bottom-color:var(--line); box-shadow:var(--shadow-sm)}
.header-inner{display:flex; align-items:center; justify-content:space-between; height:76px; gap:20px}
.logo{display:flex; align-items:center; gap:12px}
.logo-badge{width:44px; height:44px; border-radius:12px; flex:none}
.logo-wm{display:flex; flex-direction:column; line-height:.92}
.logo-wm .l1{font-family:var(--sans); font-weight:600; font-size:11px; letter-spacing:.34em; color:var(--muted); margin-left:1px}
.logo-wm .l2{font-family:var(--display); font-weight:800; font-size:20px; letter-spacing:.01em; color:var(--ink)}
.nav{display:flex; align-items:center; gap:28px}
.nav a{font-size:15.5px; font-weight:600; color:var(--muted); transition:color .18s; position:relative}
.nav a:hover,.nav a.active{color:var(--ink)}
.nav a.active::after{content:""; position:absolute; left:0; right:0; bottom:-6px; height:2px; background:var(--amber); border-radius:2px}
.header-cta{display:flex; align-items:center; gap:12px}
.header-phone{display:flex; align-items:center; gap:9px; font-weight:800; font-family:var(--display); color:var(--ink); font-size:17px}
.header-phone .ico{width:34px; height:34px; border-radius:50%; background:var(--amber-tint); display:grid; place-items:center; color:var(--amber-deep)}
.header-phone .ico svg{width:17px;height:17px}
/* Header actions: the number is the emergency path, so the button beside it must
   do something different. Below 1000px the number is hidden, so the call button
   takes its place there. */
.btn-quote{display:inline-flex}
.btn-call-sm{display:none; padding:14px 16px}
.btn-call-sm svg{width:20px; height:20px}

.burger{display:none; background:var(--card); border:1.5px solid var(--line-2); border-radius:10px; width:44px; height:44px; color:var(--ink); cursor:pointer}
.burger svg{width:22px;height:22px; margin:0 auto}

/* mobile nav panel */
.mnav{position:fixed; inset:76px 0 auto 0; background:var(--card); border-bottom:1px solid var(--line); box-shadow:var(--shadow);
  transform:translateY(-120%); transition:transform .32s cubic-bezier(.4,0,.2,1); z-index:55; padding:14px 0 22px}
.mnav.open{transform:translateY(0)}
.mnav a{display:block; padding:13px clamp(18px,4vw,40px); font-size:18px; font-weight:600; color:var(--ink); border-bottom:1px solid var(--line)}
.mnav .mnav-cta{padding:16px clamp(18px,4vw,40px) 0; display:flex; flex-direction:column; gap:10px}

/* ---- hero ---- */
.hero{position:relative; padding:clamp(48px,7vw,104px) 0 clamp(50px,7vw,92px); overflow:hidden}
.hero::before{content:""; position:absolute; top:-26%; right:-8%; width:66vw; height:66vw; max-width:760px; max-height:760px;
  background:radial-gradient(circle, rgba(245,165,36,.26), transparent 62%); pointer-events:none}
.hero::after{content:""; position:absolute; inset:0; background:
  linear-gradient(180deg, transparent, var(--paper) 97%),
  repeating-linear-gradient(0deg, rgba(18,20,35,.03) 0 1px, transparent 1px 46px),
  repeating-linear-gradient(90deg, rgba(18,20,35,.03) 0 1px, transparent 1px 46px);
  pointer-events:none}
.hero-grid{position:relative; z-index:2; display:grid; grid-template-columns:1.08fr .92fr; gap:clamp(30px,5vw,68px); align-items:center}
.hero h1{font-size:clamp(38px,6.4vw,74px); font-weight:900; letter-spacing:-.03em}
.hero h1 .hl{color:var(--amber-deep); position:relative; white-space:nowrap}
.hero .lead{margin-top:22px; font-size:clamp(17px,1.7vw,20px); color:var(--text-2); max-width:36ch; line-height:1.6}
.hero .lead b{color:var(--ink)}
.hero-cta{display:flex; flex-wrap:wrap; gap:14px; margin-top:32px}
.hero-chips{display:flex; flex-wrap:wrap; gap:10px 20px; margin-top:30px}
.hero-chip{display:flex; align-items:center; gap:9px; font-size:14.5px; color:var(--muted); font-weight:600}
.hero-chip svg{width:18px; height:18px; color:var(--amber-deep); flex:none}

/* hero visual */
.hero-visual{position:relative; min-height:340px; display:grid; place-items:center}
/* hero video: the poster paints instantly as a background, the clip fades in over it */
.hero-keymark{width:52%; filter:drop-shadow(0 18px 30px rgba(18,20,35,.2)); position:relative; z-index:2}

/* ---- trust bar ---- */
.trust{border-top:1px solid var(--line); border-bottom:1px solid var(--line); background:var(--paper-2)}
.trust-grid{display:grid; grid-template-columns:repeat(4,1fr)}
.trust-item{display:flex; align-items:center; gap:13px; padding:26px 22px; border-right:1px solid var(--line)}
.trust-item:last-child{border-right:none}
.trust-item .ic{width:42px; height:42px; border-radius:11px; background:var(--amber-tint); color:var(--amber-deep); display:grid; place-items:center; flex:none}
.trust-item .ic svg{width:22px;height:22px}
.trust-item .t{font-weight:800; color:var(--ink); font-family:var(--display); font-size:16px; line-height:1.1}
.trust-item .s{font-size:13px; color:var(--muted)}

/* ---- section scaffolding ---- */
/* padding-block, not the shorthand: several blocks carry both .container and
   .section, and the shorthand's horizontal 0 was wiping out the container's
   gutter, so those blocks sat flush against the screen edge on mobile. */
.section{padding-block:clamp(56px,8vw,104px)}
.section-head{max-width:660px; margin-bottom:clamp(34px,5vw,54px)}
.section-head.center{margin-left:auto; margin-right:auto; text-align:center}
.section-head h2{font-size:clamp(30px,4.4vw,50px); margin-top:14px}
.section-head p{margin-top:16px; color:var(--muted); font-size:18px}

/* ---- services ---- */
.services-grid{display:grid; grid-template-columns:repeat(3,1fr); gap:18px}
.svc{position:relative; background:var(--card); border:1px solid var(--line); border-radius:var(--r-lg);
  padding:28px 26px 26px; overflow:hidden; box-shadow:var(--shadow-sm)}
.svc:hover{border-color:var(--line-3); box-shadow:var(--shadow)}
.svc .ic{width:54px; height:54px; border-radius:14px; background:var(--amber-tint); color:var(--amber-deep); display:grid; place-items:center; margin-bottom:18px}
.svc .ic svg{width:28px; height:28px}
.svc h3{font-size:21px; margin-bottom:8px}
.svc p{color:var(--muted); font-size:15.5px; line-height:1.55}
.svc .more{display:inline-flex; align-items:center; gap:7px; margin-top:16px; color:var(--amber-deep); font-weight:700; font-size:15px}
.svc .more svg{width:16px; height:16px; transition:transform .2s var(--ease-out)}
/* The whole card is the link, not just the two words at the bottom. A card that
   lifts under the cursor but only answers one line of text reads as broken.
   Stretching the existing anchor keeps it to one link per card, so screen
   readers and search engines still see a single destination. */
.svc{cursor:pointer}
.svc .more::after{content:""; position:absolute; inset:0; z-index:1}
.svc :where(h3,p,.svc-thumb){position:relative}
.svc:hover .more svg{transform:translateX(4px)}
/* photo-led service cards: the picture does the work the icon used to */
.svc.has-thumb{padding-top:0}
.svc.has-thumb .ic{display:none}
/* max-width:none is load-bearing: the global img{max-width:100%} was clamping
   this back to the content box, so the thumbnail sat flush on the left and
   stopped 53px short on the right. That gap is what read as a cropped photo. */
.svc-thumb{width:calc(100% + 52px); max-width:none; margin:0 -26px 20px; height:180px;
  object-fit:cover; display:block; background:var(--paper-2)}
.svc.badge-hot::before{content:"Most requested"; position:absolute; top:18px; right:18px; font-size:11px; font-weight:700;
  letter-spacing:.06em; text-transform:uppercase; color:var(--amber-ink); background:var(--amber); padding:5px 10px; border-radius:999px}

/* ---- steps ---- */
.steps{display:grid; grid-template-columns:repeat(3,1fr); gap:20px}
.step{position:relative; background:var(--card); border:1px solid var(--line); box-shadow:var(--shadow-sm);
  border-radius:var(--r-lg); padding:30px 28px}
.step .ic{width:44px; height:44px; border-radius:13px; background:var(--amber); color:var(--amber-ink);
  display:grid; place-items:center; margin-bottom:18px}
.step .ic svg{width:22px; height:22px}
.step h3{font-size:20px; margin-bottom:8px}
.step p{color:var(--muted); font-size:15.5px}
.step .line{position:absolute; top:52px; right:-11px; width:22px; height:2px; background:var(--line-3); z-index:2}
.step:last-child .line{display:none}

/* ---- why ---- */
.why{display:grid; grid-template-columns:1fr 1fr; gap:clamp(30px,5vw,64px); align-items:center}
.why-list{list-style:none; padding:0; margin:26px 0 0; display:flex; flex-direction:column; gap:18px}
.why-list li{display:flex; gap:14px; align-items:flex-start}
.why-list .ic{width:30px;height:30px;border-radius:9px;background:var(--ok-tint);color:var(--ok);display:grid;place-items:center;flex:none;margin-top:2px}
.why-list .ic svg{width:17px;height:17px}
.why-list h4{color:var(--ink); font-family:var(--display); font-size:17px; margin-bottom:2px}
.why-list p{color:var(--muted); font-size:15px}
.why-visual{display:grid; grid-template-columns:1fr 1fr; gap:16px}
.stat{background:var(--card); border:1px solid var(--line); border-radius:var(--r-lg); padding:26px 24px; box-shadow:var(--shadow-sm)}
.stat.tall{grid-row:span 2; display:flex; flex-direction:column; justify-content:center}
.stat .num{font-family:var(--display); font-weight:900; font-size:clamp(34px,4vw,48px); color:var(--amber-deep); line-height:1}
.stat .lbl{color:var(--muted); font-size:14.5px; margin-top:8px}
.stat.amber-fill{background:linear-gradient(155deg,var(--amber),var(--amber-2)); border-color:transparent; box-shadow:var(--shadow-amber)}
.stat.amber-fill .num,.stat.amber-fill .lbl{color:var(--amber-ink)}
.stat.amber-fill .lbl{opacity:.9; font-weight:600}

/* ---- coverage ---- */
.coverage{background:var(--paper-2); border-top:1px solid var(--line); border-bottom:1px solid var(--line)}
.cov-grid{display:grid; grid-template-columns:.9fr 1.1fr; gap:clamp(30px,5vw,60px); align-items:center}
.cov-map{position:relative; display:grid; place-items:center; padding:10px}
.cov-map svg{width:100%; max-width:360px; height:auto}
.cov-badge{position:absolute; background:var(--card); border:1px solid var(--line-2); border-radius:14px;
  padding:10px 14px; font-weight:800; font-family:var(--display); color:var(--ink); font-size:14px; box-shadow:var(--shadow)}
.cov-cities{display:flex; flex-wrap:wrap; gap:10px; margin-top:24px}
.chip{background:var(--card); border:1px solid var(--line-2); border-radius:999px; padding:9px 16px; font-size:14.5px; font-weight:600; color:var(--ink); transition:border-color .18s,color .18s}
.chip:hover{border-color:var(--amber-2); color:var(--amber-deep)}
.cov-note{margin-top:22px; display:flex; align-items:center; gap:11px; color:var(--muted); font-size:15px}
.cov-note svg{color:var(--amber-deep); width:20px;height:20px; flex:none}

/* ---- reviews ---- */
.rev-grid{display:grid; grid-template-columns:repeat(3,1fr); gap:18px}
.rev{background:var(--card); border:1px solid var(--line); border-radius:var(--r-lg); padding:26px 24px; display:flex; flex-direction:column; gap:14px; box-shadow:var(--shadow-sm)}
.rev .stars{color:var(--amber-2); letter-spacing:3px; font-size:16px}
.rev .quote{color:var(--text-2); font-size:16px; line-height:1.6; flex:1}
.rev .who{display:flex; align-items:center; gap:12px}
.rev .av{width:42px;height:42px;border-radius:50%; background:linear-gradient(155deg,var(--amber),var(--amber-2)); color:var(--amber-ink); display:grid; place-items:center; font-weight:800; font-family:var(--display)}
.rev .who .nm{font-weight:700; color:var(--ink); font-size:15px}
.rev .who .lo{font-size:13px; color:var(--muted)}
.rev-foot{display:flex; align-items:center; justify-content:center; gap:10px; margin-top:30px; color:var(--muted); font-size:15px}
.rev-foot b{color:var(--ink)}
/* testimonials ride the same .rail track as the other two carousels */
.rail-quotes .rail-track{grid-auto-columns:clamp(268px,80vw,380px)}
.rail-quotes .rev{scroll-snap-align:start; gap:16px}
.rail-quotes .rev .quote{font-size:16.5px}
.rail-quotes .rev .who{padding-top:16px; border-top:1px solid var(--line); margin-top:2px}
/* town and job sit on one line so the attribution stays two lines deep */
.rail-quotes .rev .meta{display:flex; align-items:baseline; gap:7px; flex-wrap:wrap; margin-top:1px}
.rail-quotes .rev .jb{font-size:12.5px; color:var(--amber-deep); font-weight:700}
.rail-quotes .rev .meta .jb::before{content:"·"; margin-right:7px; color:var(--line-3); font-weight:400}

/* the design-preview banner, only ever seen on testimonials-preview.html */
.mock-note{background:var(--amber); color:var(--amber-ink); padding:14px 0; font-weight:700; font-size:15px}
.mock-note .container{display:flex; align-items:center; gap:11px}
.mock-note svg{width:20px; height:20px; flex:none}
.mock-note span{font-weight:500}

/* ---- rail: horizontal scroll-snap carousel --------------------------------
   Native scrolling, so a thumb, a trackpad and the keyboard all work before
   rail.js loads. The arrows are enhancement, not the mechanism. */
.rail-head{display:flex; align-items:flex-end; justify-content:space-between; gap:28px; margin-bottom:26px}
.rail-head .section-head{margin-bottom:0}
.rail-nav{display:none; gap:8px; flex:none; padding-bottom:6px}
.rail-nav.on{display:flex}
.rail-btn{width:46px; height:46px; border-radius:50%; border:1.5px solid var(--line-2); background:var(--card);
  color:var(--ink); display:grid; place-items:center; cursor:pointer; padding:0;
  transition:transform .16s var(--ease-out), border-color .16s var(--ease-out), opacity .18s var(--ease-out)}
.rail-btn svg{width:19px; height:19px}
.rail-btn:active{transform:scale(.94)}
.rail-btn:disabled{opacity:.3; cursor:default}
@media (hover:hover) and (pointer:fine){
  .rail-btn:not(:disabled):hover{border-color:var(--amber); color:var(--amber-deep)}
}
/* a fixed track width, not minmax(0,...) — auto columns would otherwise shrink
   to fit the container and the rail would never overflow, so never scroll */
.rail-track{display:grid; grid-auto-flow:column; grid-auto-columns:clamp(258px,78vw,330px); gap:18px;
  /* proximity, not mandatory: mandatory re-snaps mid-flight and cancels the
     arrows' smooth scroll, dragging the track back to where it started */
  overflow-x:auto; overscroll-behavior-x:contain; scroll-snap-type:x proximity;
  padding:4px 4px 10px; margin:-4px -4px -10px; scrollbar-width:none}
.rail-track::-webkit-scrollbar{display:none}
.rail-card{scroll-snap-align:start; background:var(--card); border:1px solid var(--line);
  border-radius:var(--r-lg); padding:26px 24px 22px; box-shadow:var(--shadow-sm);
  display:flex; flex-direction:column; gap:12px}
.rail-card .rc-tag{align-self:flex-start; background:var(--amber-tint); color:var(--amber-deep);
  font-size:12.5px; font-weight:700; letter-spacing:.04em; padding:6px 12px; border-radius:999px}
.rail-card h3{font-size:20px; line-height:1.28; margin:2px 0 0}
.rail-card p{color:var(--muted); font-size:15.5px; line-height:1.62; flex:1; margin:0}
.rail-card .rc-foot{display:flex; align-items:center; gap:9px; margin-top:4px; padding-top:15px;
  border-top:1px solid var(--line); color:var(--text-2); font-size:14px; font-weight:600}
.rail-card .rc-foot svg{width:17px; height:17px; flex:none; color:var(--amber-deep)}
/* let the cards run to the screen edge on phones so the next one peeks through */
@media (max-width:640px){
  .rail-head{flex-direction:column; align-items:stretch; gap:18px}
  .rail-nav{padding-bottom:0}
  .rail-track{padding-inline:clamp(18px,4vw,40px); margin-inline:calc(clamp(18px,4vw,40px) * -1)}
}

/* ---- gallery: photographs from actual jobs --------------------------------
   A carousel rather than a grid: these are portrait phone photos, so they want
   to be shown large and one at a time, not shrunk into a wall of thumbnails.
   It rides the .rail track, so the arrows and snapping come for free. */
.rail-photos .rail-track{grid-auto-columns:clamp(250px,72vw,352px); gap:20px}
.gal-item{position:relative; margin:0; scroll-snap-align:start; border-radius:var(--r-lg);
  overflow:hidden; border:1px solid var(--line-2); background:var(--paper-2);
  aspect-ratio:3/4; box-shadow:var(--shadow-sm); cursor:zoom-in}
.gal-item img{width:100%; height:100%; object-fit:cover; display:block;
  transition:transform .55s var(--ease-out)}
.gal-item::after{content:""; position:absolute; inset:0; border-radius:inherit;
  box-shadow:inset 0 0 0 1px rgba(255,255,255,.07); pointer-events:none}
@media (hover:hover) and (pointer:fine){
  .gal-item:hover img{transform:scale(1.05)}
}

/* lightbox. <dialog> gives us focus trapping and Esc for free. */
.lb{border:none; padding:0; background:transparent; max-width:min(94vw,760px); max-height:94vh; overflow:visible}
.lb::backdrop{background:rgba(12,13,18,.86)}
.lb-fig{margin:0; background:var(--card); border-radius:var(--r-lg); overflow:hidden}
.lb-fig img{display:block; width:100%; max-height:78vh; object-fit:contain; background:#0E0F13}
.lb-fig figcaption{padding:16px 20px; color:var(--text-2); font-size:15px; line-height:1.55}
.lb-close{position:absolute; top:-14px; right:-14px; width:40px; height:40px; border-radius:50%;
  border:none; background:var(--card); color:var(--ink); display:grid; place-items:center; cursor:pointer;
  box-shadow:0 6px 20px -6px rgba(0,0,0,.5); transition:transform .16s var(--ease-out)}
.lb-close:active{transform:scale(.93)}
.lb-close svg{width:19px; height:19px}
@media (prefers-reduced-motion:reduce){
  .gal-item img,.lb-close{transition:none}
}

/* ---- home hero as a photograph --------------------------------------------
   Same treatment as the inner pages, so all four heroes share one composition
   rule (subject right, copy left under the scrim) and their art is
   interchangeable. The decorative glow and grid are switched off: they were
   there to fill an empty background, and there is no empty background now. */
.hero.has-photo{--hero-img:url("images/hero-home.jpg");
  background-image:var(--hero-scrim), var(--hero-img);
  background-size:cover; background-position:right center; background-repeat:no-repeat;
  overflow:hidden}
.hero.has-photo::before,.hero.has-photo::after{display:none}
.hero.has-photo .hero-grid{grid-template-columns:1fr}
.hero.has-photo .hero-copy{max-width:min(620px,100%)}
.hero.has-photo h1,.hero.has-photo .lead{text-shadow:0 1px 10px rgba(255,255,255,.85)}
@media (max-width:860px){
  /* On a phone the copy fills the box top to bottom, so a photograph behind it
     can only ever be a wash. It gets its own strip instead: full width, whole
     image, nothing cropped and no scrim over it. */
  /* A portrait crop of the same photograph, so the background fills the tall
     box with nothing lost sideways and the subject stays framed. The wash is
     kept light and the copy carries its own halo, rather than bleaching the
     picture to make text readable. */
  .hero.has-photo{--hero-img:url("images/hero-home-m.jpg");
    background-image:linear-gradient(180deg, rgba(255,255,255,.94) 0%, rgba(255,255,255,.9) 34%, rgba(255,255,255,.62) 62%, rgba(255,255,255,.12) 100%), var(--hero-img);
    background-size:cover; background-position:center 18%; background-repeat:no-repeat;
    padding-bottom:clamp(150px,42vw,220px)}
  .hero.has-photo h1,.hero.has-photo .lead{text-shadow:0 1px 2px #fff, 0 2px 14px rgba(255,255,255,.95)}
  .hero.has-photo .hero-chips{display:none}
  .hero.has-photo h1,.hero.has-photo .lead{text-shadow:none}
}


/* ---- brand key: the empty half of the story column -------------------------
   Purely decorative, so aria-hidden. It earns its place here and nowhere else:
   the About page is where a brand may speak about itself, and this column was
   blank. The key turns, holds, turns back, which is what a key does. */
.story{display:grid; grid-template-columns:1.15fr .85fr; gap:clamp(28px,5vw,64px); align-items:center}
.brandkey{background:var(--ink); border-radius:var(--r-lg); display:grid; place-items:center;
  padding:clamp(28px,4vw,48px); aspect-ratio:1/.82; overflow:hidden}
.brandkey svg{width:min(230px,74%); height:auto}
.bk-face{fill:none; stroke:#24262D; stroke-width:2}
.bk-inner{fill:none; stroke:#1E2027; stroke-width:1.5}
/* the arc is the cylinder turning: a quarter of the circumference, drawn in
   step with the key rather than on a timer of its own */
.bk-arc{fill:none; stroke:var(--amber); stroke-width:3.5; stroke-linecap:round;
  stroke-dasharray:91.1 364.4; stroke-dashoffset:91.1;
  transform:rotate(-90deg); transform-origin:70px 70px;
  animation:bkArc 5.6s cubic-bezier(.23,1,.32,1) infinite}
/* pivot at the key's own centre, not its tip: rotating about the tip swung the
   whole key out of the viewBox, which is what clipped it */
/* the placing translate lives on a wrapper group: a CSS transform on this
   element would replace the transform attribute outright, not add to it */
.bk-key{transform-origin:50px 70px; animation:bkTurn 5.6s cubic-bezier(.23,1,.32,1) infinite}
@keyframes bkTurn{
  0%,14%   {transform:rotate(0deg)}
  36%,62%  {transform:rotate(90deg)}
  84%,100% {transform:rotate(0deg)}
}
@keyframes bkArc{
  0%,14%   {stroke-dashoffset:91.1}
  36%,62%  {stroke-dashoffset:0}
  84%,100% {stroke-dashoffset:91.1}
}
@media (max-width:860px){
  .story{grid-template-columns:1fr}
  .brandkey{aspect-ratio:3/2; padding:32px}
  .brandkey svg{width:min(170px,48%)}
}
@media (prefers-reduced-motion:reduce){
  .bk-key{animation:none; transform:rotate(90deg)}
  .bk-arc{animation:none; stroke-dashoffset:0}
}

/* ---- ticker: a brand band directly under the hero -------------------------
   Decorative, so it is aria-hidden and carries no links: a link that slides
   away under the cursor is a link nobody can hit. The item list is rendered
   twice and the rail travels exactly -50%, which is what makes the loop
   seamless; translate only, so it stays on the compositor. */
.ticker{background:var(--ink); overflow:hidden; border-bottom:1px solid rgba(255,255,255,.09)}
.ticker-rail{display:flex; width:max-content; animation:tickerRun 70s linear infinite}
/* the gap sits before the diamond, the padding after it, so the marker gets the
   same air on both sides instead of butting up against the next word */
.ticker-item{display:inline-flex; align-items:center; gap:34px; white-space:nowrap;
  color:#E9EAEE; font-family:var(--display); font-weight:700; font-size:18px;
  letter-spacing:.01em; padding:16px 34px 16px 0}
.ticker-item::after{content:"◆"; color:var(--amber); font-size:10px; position:relative; top:-1px}
@keyframes tickerRun{from{transform:translateX(0)} to{transform:translateX(-50%)}}
@media (hover:hover) and (pointer:fine){
  .ticker:hover .ticker-rail{animation-play-state:paused}
}
@media (prefers-reduced-motion:reduce){
  .ticker-rail{animation:none}
}
@media (max-width:640px){.ticker-item{font-size:15.5px; gap:24px; padding:13px 24px 13px 0}}

/* ---- promise panel: the honest answer to "will I get ripped off" ----------
   Sits on its own amber panel so it reads as a guarantee, not another card row.
   The neighbouring sections are tinted full-bleed, so this one stays contained. */
.promise{display:grid; grid-template-columns:repeat(2,1fr); gap:14px;
  background:linear-gradient(150deg, var(--amber-tint), #FFF7E7);
  border:1px solid #F1DDB4; border-radius:var(--r-xl); padding:clamp(16px,2.2vw,22px)}
.promise-item{position:relative; background:var(--card); border:1px solid rgba(255,255,255,.9);
  border-radius:var(--r-lg); padding:26px 26px 28px; box-shadow:0 2px 10px -6px rgba(74,46,2,.25);
  transition:transform .22s var(--ease-out), box-shadow .22s var(--ease-out)}
.promise-item .pi-ic{display:grid; place-items:center; width:46px; height:46px; border-radius:14px;
  background:var(--amber-tint); color:var(--amber-deep); margin-bottom:16px;
  transition:background .22s var(--ease-out), color .22s var(--ease-out), transform .22s var(--ease-out)}
.promise-item .pi-ic svg{width:23px; height:23px}
.promise-item b{display:block; font-family:var(--display); font-size:18.5px; color:var(--ink);
  margin-bottom:7px; letter-spacing:-.015em}
.promise-item .pi-txt{display:block; color:var(--muted); font-size:15px; line-height:1.62}
@media (hover:hover) and (pointer:fine){
  .promise-item:hover{transform:translateY(-3px); box-shadow:0 16px 30px -18px rgba(74,46,2,.4)}
  .promise-item:hover .pi-ic{background:var(--amber); color:var(--amber-ink); transform:scale(1.06)}
}
@media (max-width:720px){
  .promise{grid-template-columns:1fr; gap:12px}
  .promise-item{padding:22px 22px 24px}
}

/* ---- faq ---- */
.faq{max-width:820px}
.faq-item{border:1px solid var(--line); border-radius:var(--r); margin-bottom:12px; background:var(--card); overflow:hidden; box-shadow:var(--shadow-sm)}
.faq-q{width:100%; text-align:left; background:none; border:none; color:var(--ink); font-family:var(--sans); font-weight:700;
  font-size:17px; padding:20px 22px; cursor:pointer; display:flex; align-items:center; justify-content:space-between; gap:16px}
.faq-q .pm{width:26px;height:26px;border-radius:8px;background:var(--amber-tint);color:var(--amber-deep);display:grid;place-items:center;flex:none;transition:transform .24s var(--ease-out)}
.faq-q .pm svg{width:16px;height:16px}
.faq-item.open .faq-q .pm{transform:rotate(45deg)}
.faq-a{max-height:0; overflow:hidden; transition:max-height .24s var(--ease-out)}
.faq-a p{padding:0 22px 20px; color:var(--muted); font-size:15.5px; line-height:1.65}

/* ---- CTA band ---- */
.cta-band{position:relative; overflow:hidden}
.cta-inner{background:linear-gradient(135deg,var(--amber-3),var(--amber-2)); border-radius:var(--r-xl); padding:clamp(38px,6vw,64px) clamp(28px,5vw,64px);
  display:flex; align-items:center; justify-content:space-between; gap:32px; flex-wrap:wrap; position:relative; overflow:hidden; box-shadow:var(--shadow)}
.cta-inner::before{content:""; position:absolute; right:-40px; bottom:-60px; width:280px; height:280px;
  background:radial-gradient(circle,rgba(255,255,255,.32),transparent 65%)}
.cta-inner h2{color:var(--amber-ink); font-size:clamp(28px,4vw,44px); max-width:16ch; position:relative}
.cta-inner p{color:#6a4708; font-weight:600; margin-top:10px; position:relative}
.cta-actions{display:flex; flex-direction:column; gap:12px; position:relative}

/* ---- footer (light) ---- */
.footer{background:var(--paper-2); border-top:1px solid var(--line); padding:clamp(48px,6vw,72px) 0 30px}
.foot-grid{display:grid; grid-template-columns:1.4fr 1fr 1fr 1.2fr; gap:36px}
.footer .logo-wm .l1{color:var(--muted)}
.footer .logo-wm .l2{color:var(--ink)}
.foot-about p{color:var(--muted); font-size:14.5px; margin-top:16px; max-width:34ch}
.foot h4{color:var(--ink); font-family:var(--display); font-size:15px; letter-spacing:.02em; margin-bottom:16px}
.foot ul{list-style:none; padding:0; margin:0; display:flex; flex-direction:column; gap:10px}
.foot a,.foot li{color:var(--muted); font-size:14.5px; transition:color .18s}
.foot a:hover{color:var(--amber-deep)}
.foot-contact a{display:flex; align-items:center; gap:10px; font-weight:600; color:var(--ink)}
.foot-contact a:hover{color:var(--amber-deep)}
/* on a phone the contact column is the last thing before the small print, and
   stacking two short links wastes a whole row each. Side by side, they read as
   one pair of actions. */
@media (max-width:640px){
  .foot-contact ul{display:flex; flex-wrap:wrap; gap:10px 26px}
  .foot-contact li{margin:0}
}
.foot-contact svg{width:17px;height:17px;color:var(--amber-deep);flex:none}
.foot-bottom{display:flex; align-items:center; justify-content:space-between; gap:16px; flex-wrap:wrap;
  margin-top:44px; padding-top:24px; border-top:1px solid var(--line); color:var(--faint); font-size:13.5px}
.foot-bottom a{color:var(--faint)} .foot-bottom a:hover{color:var(--amber-deep)}

/* ---- floating call buttons, phones only ------------------------------------
   Was a full-width bar across the bottom, which cost 74px of a 812px screen
   for its whole life. Two discs in the thumb corner cost nothing and never
   hide, which matters more here than anywhere: the call is the conversion.
   The class name stays .mobile-bar because track.js reads it to label taps. */
.mobile-bar{position:fixed; left:auto; right:16px; z-index:70; display:none; gap:12px;
  bottom:calc(16px + env(safe-area-inset-bottom))}
.fab{width:58px; height:58px; border-radius:50%; display:grid; place-items:center; flex:none;
  box-shadow:0 12px 28px -8px rgba(18,20,35,.5);
  transition:transform .16s var(--ease-out), filter .2s}
.fab svg{width:26px; height:26px}
.fab:active{transform:scale(.93)}
.fab:focus-visible{outline:none; box-shadow:0 0 0 3px #fff, 0 0 0 6px var(--amber-2)}
.fab-call{background:var(--amber); color:var(--amber-ink)}
.fab-wa{background:var(--wa); color:#04220f}
@media (hover:hover) and (pointer:fine){.fab:hover{filter:brightness(1.05)}}
@media (prefers-reduced-motion:reduce){.fab{transition:none}}

/* ---- motion ----------------------------------------------------------------
   Rule for this site: motion should make it feel crafted and responsive, never
   make a panicking visitor wait. Nothing animates between them and the phone
   number, and the sticky call bar is deliberately never hidden or delayed.     */
.reveal{opacity:0; transform:translateY(20px); transition:opacity .5s var(--ease-out), transform .5s var(--ease-out)}
.reveal.in{opacity:1; transform:none}

@media (prefers-reduced-motion:no-preference){
  /* hero reads in order on first paint, then never repeats */
  .hero-copy>*,.page-hero .inner>*{animation:riseIn .42s var(--ease-out) both}
  .hero-copy>*:nth-child(2),.page-hero .inner>*:nth-child(2){animation-delay:.06s}
  .hero-copy>*:nth-child(3),.page-hero .inner>*:nth-child(3){animation-delay:.12s}
  .hero-copy>*:nth-child(4),.page-hero .inner>*:nth-child(4){animation-delay:.18s}
  .hero-copy>*:nth-child(5),.page-hero .inner>*:nth-child(5){animation-delay:.24s}
  @keyframes riseIn{from{opacity:0; transform:translateY(10px)} to{opacity:1; transform:none}}

  /* photographs wipe open rather than fade, which reads photographic not generic */
  @supports (animation-timeline: view()){
    .photo-wide img{animation:wipeIn linear both; animation-timeline:view(); animation-range:entry 8% entry 55%}
    @keyframes wipeIn{from{clip-path:inset(0 0 100% 0)} to{clip-path:inset(0 0 0 0)}}
  }
}

/* hover effects only where there is a real pointer, so taps do not trigger them */
@media (hover:hover) and (pointer:fine){
  .svc:hover{transform:translateY(-4px)}
}
.svc{transition:transform .2s var(--ease-out), border-color .2s, box-shadow .2s}

@media (prefers-reduced-motion:reduce){
  .reveal{opacity:1; transform:none; transition:none}
  .btn:active{transform:none}
}

/* ============ inner pages ============ */
.page-hero{position:relative; padding:clamp(40px,6vw,72px) 0 clamp(34px,5vw,54px); overflow:hidden; border-bottom:1px solid var(--line)}
.page-hero::before{content:""; position:absolute; top:-40%; right:-6%; width:60vw; height:60vw; max-width:640px; max-height:640px;
  background:radial-gradient(circle, rgba(245,165,36,.22), transparent 62%); pointer-events:none}
.page-hero .inner{position:relative; z-index:2; max-width:var(--maxw)}
.page-hero h1{font-size:clamp(32px,5.2vw,58px); font-weight:900; letter-spacing:-.03em; margin-top:14px; max-width:min(720px,100%)}
.page-hero .lead{margin-top:18px; font-size:clamp(17px,1.7vw,20px); color:var(--text-2); max-width:52ch; line-height:1.6}
.page-hero .lead b{color:var(--ink)}
.page-hero .hero-cta{margin-top:28px}
.breadcrumb{display:flex; align-items:center; gap:8px; font-size:13.5px; color:var(--faint); font-weight:600}
.breadcrumb a{color:var(--muted)} .breadcrumb a:hover{color:var(--amber-deep)}
.breadcrumb svg{width:14px;height:14px;opacity:.6}

/* service page layout */
.svc-layout{display:grid; grid-template-columns:1fr 340px; gap:clamp(30px,4vw,54px); align-items:start}
.prose h2{font-size:clamp(24px,3.2vw,34px); margin:0 0 16px}
.prose h3{font-size:20px; margin:32px 0 10px; color:var(--ink)}
.prose p{color:var(--text-2); font-size:17px; line-height:1.75; margin:0 0 16px}
.prose p b,.prose li b{color:var(--ink)}
.prose>p:first-of-type{font-size:19px; color:var(--ink)}
.prose ul{list-style:none; padding:0; margin:8px 0 24px; display:flex; flex-direction:column; gap:12px}
.prose ul li{position:relative; padding-left:32px; color:var(--text-2); font-size:16.5px; line-height:1.6}
.prose ul li::before{content:""; position:absolute; left:0; top:3px; width:20px; height:20px; border-radius:6px;
  background:var(--amber-tint) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='13' height='13' viewBox='0 0 24 24' fill='none' stroke='%23C0730B' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E") center/13px no-repeat}
.includes{display:grid; grid-template-columns:1fr 1fr; gap:12px 26px; margin:10px 0 26px}
.includes div{position:relative; padding-left:32px; color:var(--ink); font-size:16px}
.includes div::before{content:""; position:absolute; left:0; top:2px; width:20px; height:20px; border-radius:6px;
  background:var(--amber-tint) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='13' height='13' viewBox='0 0 24 24' fill='none' stroke='%23C0730B' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E") center/13px no-repeat}

/* sticky side card */
.side-card{position:sticky; top:96px; background:var(--card); border:1px solid var(--line-2);
  border-radius:var(--r-lg); padding:26px 24px; box-shadow:var(--shadow)}
.side-card .eyebrow{margin-bottom:12px}
.side-card h3{font-size:22px; margin-bottom:6px}
.side-card .ph{font-family:var(--display); font-weight:900; font-size:26px; color:var(--amber-deep); margin:14px 0 4px; display:block}
.side-card .sub{color:var(--muted); font-size:14px; margin-bottom:18px}
.side-card .btn{margin-bottom:10px}
.side-card ul{list-style:none; padding:18px 0 0; margin:18px 0 0; border-top:1px solid var(--line); display:flex; flex-direction:column; gap:11px}
.side-card ul li{display:flex; align-items:center; gap:10px; font-size:14.5px; color:var(--ink)}
.side-card ul li svg{width:18px;height:18px;color:var(--ok);flex:none}

/* emergency page: what-happens timeline */
.timeline{list-style:none; padding:0; margin:10px 0 30px; display:flex; flex-direction:column; gap:0}
.timeline li{display:grid; grid-template-columns:104px 1fr; gap:20px; padding:18px 0; border-bottom:1px solid var(--line)}
.timeline li:last-child{border-bottom:none}
.timeline .tl-when{font-family:var(--display); font-weight:800; font-size:13px; letter-spacing:.02em; color:var(--amber-deep); padding-top:2px}
.timeline b{display:block; color:var(--ink); font-family:var(--display); font-size:17px; margin-bottom:4px}
.timeline p{color:var(--muted); font-size:15px; margin:0}

@media (max-width:560px){.timeline li{grid-template-columns:1fr; gap:4px}}

/* uPVC page: symptom to cause table */
.symptoms{margin:10px 0 30px; border:1px solid var(--line-2); border-radius:var(--r); overflow:hidden}
.sym-row{display:grid; grid-template-columns:1fr 1.15fr; gap:18px; padding:14px 18px; border-bottom:1px solid var(--line); font-size:15px}
.sym-row:last-child{border-bottom:none}
.sym-row span:first-child{color:var(--ink); font-weight:600}
.sym-row span:last-child{color:var(--muted)}
.sym-head{background:var(--paper-2); font-size:12px; text-transform:uppercase; letter-spacing:.07em}
.sym-head span{color:var(--faint) !important; font-weight:700 !important}
@media (max-width:560px){.sym-row{grid-template-columns:1fr; gap:3px}.sym-head{display:none}}

.mini-faq{margin-top:14px}
.mini-faq .faq{margin:0}

/* trust strip inside pages */
.trust-cards{display:grid; grid-template-columns:repeat(3,1fr); gap:16px; margin:6px 0 0}
.trust-card{background:var(--card); border:1px solid var(--line); border-radius:var(--r); padding:22px 20px; box-shadow:var(--shadow-sm)}
.trust-card .ic{width:40px;height:40px;border-radius:11px;background:var(--amber-tint);color:var(--amber-deep);display:grid;place-items:center;margin-bottom:12px}
.trust-card .ic svg{width:21px;height:21px}
.trust-card h4{color:var(--ink);font-family:var(--display);font-size:16px;margin-bottom:4px}
.trust-card p{color:var(--muted);font-size:14px}

/* areas hub */
/* ---- how we reach you -----------------------------------------------------
   Replaces a grid of 49 town names that all linked to the same phone number.
   The response time carries the section as a single figure, and the rest of
   the answer sits beside it as a list, rather than four equal cards in a row. */
.reach{display:grid; grid-template-columns:.85fr 1.15fr; gap:clamp(18px,2.6vw,32px); align-items:stretch}
.reach-figure{background:var(--ink); border-radius:var(--r-lg); padding:clamp(26px,3.2vw,40px);
  display:flex; flex-direction:column; justify-content:center}
.reach-figure .big{font-family:var(--display); font-weight:800; letter-spacing:-.035em;
  font-size:clamp(52px,6.6vw,82px); line-height:.9; color:var(--amber)}
.reach-figure .unit{color:#E9EAEE; font-size:17px; font-weight:600; margin-top:10px}
.reach-figure .note{color:#9A9CA3; font-size:14.5px; line-height:1.55;
  margin-top:18px; padding-top:18px; border-top:1px solid rgba(255,255,255,.13)}
/* ---- call flow: the first 25 minutes, as its own band --------------------
   Sits on the contact page, directly under the form, because that is where
   somebody hesitates. Horizontal on a wide screen with the connector running
   behind the dots; the dots punch themselves out of it with a ring of the
   panel colour rather than a gap in the line. */
.callflow{background:var(--ink); border-radius:var(--r-lg); padding:clamp(28px,4vw,44px)}
.callflow .section-tag{color:var(--amber)}
.callflow h2{color:#fff; font-size:clamp(24px,3vw,34px); margin-top:12px}
.callflow .sub{color:#9A9CA3; font-size:16px; margin-top:12px; max-width:56ch}
.flow{position:relative; list-style:none; padding:0; display:grid;
  grid-template-columns:repeat(4,1fr); gap:22px; margin:34px 0 0}
.flow::before{content:""; position:absolute; left:7px; right:7px; top:6px; height:2px;
  background:rgba(255,255,255,.16)}
.flow li{position:relative; padding-top:30px}
.flow .dot{position:absolute; left:0; top:0; width:14px; height:14px; border-radius:50%;
  background:var(--amber); box-shadow:0 0 0 5px var(--ink)}
.flow li:last-child .dot{background:#fff}
.flow .when{display:block; font-family:var(--display); font-weight:800; font-size:12px;
  letter-spacing:.09em; color:var(--amber); margin-bottom:5px}
.flow li:last-child .when{color:#fff}
.flow .what{display:block; color:#E9EAEE; font-size:15.5px; line-height:1.4; font-weight:600}
/* stops arrive one just behind the other, once, when the band scrolls in */
.flow li{opacity:0; transform:translateY(9px);
  transition:opacity .45s var(--ease-out), transform .45s var(--ease-out)}
.reveal.in .flow li{opacity:1; transform:none}
.reveal.in .flow li:nth-child(2){transition-delay:.09s}
.reveal.in .flow li:nth-child(3){transition-delay:.18s}
.reveal.in .flow li:nth-child(4){transition-delay:.27s}
@media (max-width:760px){
  /* vertical: the connector turns to run down the left of the stops */
  .flow{grid-template-columns:1fr; gap:0; margin-top:28px}
  .flow::before{left:6px; right:auto; top:8px; bottom:14px; width:2px; height:auto}
  .flow li{padding:0 0 24px 32px}
  .flow li:last-child{padding-bottom:0}
  .flow .dot{top:4px}
}
@media (prefers-reduced-motion:reduce){
  .flow li{opacity:1; transform:none; transition:none}
}

.reach-body{display:flex; flex-direction:column; justify-content:center}
.reach-body .section-head{margin-bottom:0}
.reach-list{list-style:none; padding:0; margin:24px 0 0; display:flex; flex-direction:column; gap:15px}
.reach-list li{display:flex; gap:14px; align-items:flex-start}
.reach-list .ic{flex:none; width:38px; height:38px; border-radius:11px; background:var(--amber-tint);
  color:var(--amber-deep); display:grid; place-items:center}
.reach-list .ic svg{width:19px; height:19px}
.reach-list b{display:block; font-family:var(--display); font-size:16.5px; color:var(--ink); margin-bottom:2px}
.reach-list span{color:var(--muted); font-size:14.5px; line-height:1.55}
@media (max-width:860px){
  .reach{grid-template-columns:1fr}
  .reach-figure{padding:26px}
  .reach-figure .big{font-size:clamp(48px,13vw,64px)}
}

/* contact */
.contact-layout{display:grid; grid-template-columns:1fr 1fr; gap:clamp(28px,4vw,50px); align-items:start}
.contact-info{display:flex; flex-direction:column; gap:16px}
.ci-card{display:flex; gap:16px; align-items:flex-start; background:var(--card); border:1px solid var(--line); border-radius:var(--r); padding:20px 22px; box-shadow:var(--shadow-sm)}
.ci-card .ic{width:46px;height:46px;border-radius:12px;background:var(--amber-tint);color:var(--amber-deep);display:grid;place-items:center;flex:none}
.ci-card .ic svg{width:23px;height:23px}
.ci-card h4{color:var(--ink);font-family:var(--display);font-size:17px;margin-bottom:3px}
.ci-card p{color:var(--muted);font-size:15px}
.ci-card a{color:var(--amber-deep);font-weight:700;font-size:15px}
.form-card{background:var(--card); border:1px solid var(--line-2); border-radius:var(--r-lg); padding:clamp(24px,3vw,34px); box-shadow:var(--shadow)}
.field{margin-bottom:16px}
.field label{display:block; font-size:14px; font-weight:600; color:var(--ink); margin-bottom:7px}
.field input,.field textarea,.field select{width:100%; background:var(--paper); border:1px solid var(--line-2); border-radius:10px; padding:13px 15px;
  color:var(--ink); font-family:var(--sans); font-size:15.5px; transition:border-color .18s, box-shadow .18s}
.field input::placeholder,.field textarea::placeholder{color:var(--faint)}
.field input:focus,.field textarea:focus,.field select:focus{outline:none; border-color:var(--amber-2); box-shadow:0 0 0 3px var(--amber-tint)}
.field textarea{resize:vertical; min-height:120px}
.form-note{font-size:13px; color:var(--faint); margin-top:6px}
.hp{position:absolute; left:-9999px; width:1px; height:1px; overflow:hidden}
.form-alert{display:none; align-items:center; gap:10px; margin-top:16px; padding:14px 16px; border-radius:10px; font-weight:600; font-size:15px}
.form-alert svg{width:20px; height:20px; flex:none}
.form-alert-ok{background:var(--ok-tint); border:1px solid rgba(46,158,104,.35); color:#1c6b45}
.form-alert-err{background:#FBECE7; border:1px solid #EEC7B9; color:#8A3520}
.form-alert-err a{color:inherit; text-decoration:underline}

/* about */
.about-values{display:grid; grid-template-columns:repeat(3,1fr); gap:18px}
.val{background:var(--card); border:1px solid var(--line); border-radius:var(--r-lg); padding:26px 24px; box-shadow:var(--shadow-sm)}
.val .ic{width:50px;height:50px;border-radius:13px;background:var(--amber-tint);color:var(--amber-deep);display:grid;place-items:center;margin-bottom:16px}
.val .ic svg{width:26px;height:26px}
.val h3{font-size:19px;margin-bottom:8px}
.val p{color:var(--muted);font-size:15px}

/* reviews wall */
.reviews-wall{columns:3; column-gap:18px}
.reviews-wall .rev{break-inside:avoid; margin-bottom:18px; display:block}
.reviews-wall .rev .quote{display:block; margin-bottom:14px}

/* ---- real photos ---- */
.page-hero.has-photo{overflow:hidden; border-bottom-color:transparent;
  --hero-img:url("images/hero-service.jpg");
  background-image:var(--hero-scrim), var(--hero-img);
  background-size:cover; background-position:right center; background-repeat:no-repeat}
.page-hero.has-photo::before,.page-hero.has-photo::after{display:none}
.page-hero.has-photo .inner{max-width:var(--maxw)}
.page-hero.has-photo h1,.page-hero.has-photo .lead{max-width:min(560px,100%)}
/* the artwork is bright with a clear left edge, so dark type on a white wash reads
   better than white type on a dark scrim, and keeps the photographs feeling airy */
.page-hero.has-photo h1,.page-hero.has-photo .lead{text-shadow:0 1px 10px rgba(255,255,255,.85)}
.page-hero.hero-areas{--hero-img:url("images/hero-areas.jpg")}
.page-hero.hero-about{--hero-img:url("images/hero-about.jpg")}
.page-hero.hero-reviews{--hero-img:url("images/hero-reviews.jpg")}

/* service page layout */
.svc-layout{display:grid; grid-template-columns:1fr 340px; gap:clamp(30px,4vw,54px); align-items:start}
.prose h2{font-size:clamp(24px,3.2vw,34px); margin:0 0 16px}
.prose h3{font-size:20px; margin:32px 0 10px; color:var(--ink)}
.prose p{color:var(--text-2); font-size:17px; line-height:1.75; margin:0 0 16px}
.prose p b,.prose li b{color:var(--ink)}
.prose>p:first-of-type{font-size:19px; color:var(--ink)}
.prose ul{list-style:none; padding:0; margin:8px 0 24px; display:flex; flex-direction:column; gap:12px}
.prose ul li{position:relative; padding-left:32px; color:var(--text-2); font-size:16.5px; line-height:1.6}
.prose ul li::before{content:""; position:absolute; left:0; top:3px; width:20px; height:20px; border-radius:6px;
  background:var(--amber-tint) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='13' height='13' viewBox='0 0 24 24' fill='none' stroke='%23C0730B' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E") center/13px no-repeat}
.includes{display:grid; grid-template-columns:1fr 1fr; gap:12px 26px; margin:10px 0 26px}
.includes div{position:relative; padding-left:32px; color:var(--ink); font-size:16px}
.includes div::before{content:""; position:absolute; left:0; top:2px; width:20px; height:20px; border-radius:6px;
  background:var(--amber-tint) url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='13' height='13' viewBox='0 0 24 24' fill='none' stroke='%23C0730B' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpath d='M20 6 9 17l-5-5'/%3E%3C/svg%3E") center/13px no-repeat}

/* sticky side card */
.side-card{position:sticky; top:96px; background:var(--card); border:1px solid var(--line-2);
  border-radius:var(--r-lg); padding:26px 24px; box-shadow:var(--shadow)}
.side-card .eyebrow{margin-bottom:12px}
.side-card h3{font-size:22px; margin-bottom:6px}
.side-card .ph{font-family:var(--display); font-weight:900; font-size:26px; color:var(--amber-deep); margin:14px 0 4px; display:block}
.side-card .sub{color:var(--muted); font-size:14px; margin-bottom:18px}
.side-card .btn{margin-bottom:10px}
.side-card ul{list-style:none; padding:18px 0 0; margin:18px 0 0; border-top:1px solid var(--line); display:flex; flex-direction:column; gap:11px}
.side-card ul li{display:flex; align-items:center; gap:10px; font-size:14.5px; color:var(--ink)}
.side-card ul li svg{width:18px;height:18px;color:var(--ok);flex:none}

/* emergency page: what-happens timeline */
@media (max-width:560px){.timeline li{grid-template-columns:1fr; gap:4px}}

/* uPVC page: symptom to cause table */
.symptoms{margin:10px 0 30px; border:1px solid var(--line-2); border-radius:var(--r); overflow:hidden}
.sym-row{display:grid; grid-template-columns:1fr 1.15fr; gap:18px; padding:14px 18px; border-bottom:1px solid var(--line); font-size:15px}
.sym-row:last-child{border-bottom:none}
.sym-row span:first-child{color:var(--ink); font-weight:600}
.sym-row span:last-child{color:var(--muted)}
.sym-head{background:var(--paper-2); font-size:12px; text-transform:uppercase; letter-spacing:.07em}
.sym-head span{color:var(--faint) !important; font-weight:700 !important}
@media (max-width:560px){.sym-row{grid-template-columns:1fr; gap:3px}.sym-head{display:none}}

.mini-faq{margin-top:14px}
.mini-faq .faq{margin:0}

/* trust strip inside pages */
.trust-cards{display:grid; grid-template-columns:repeat(3,1fr); gap:16px; margin:6px 0 0}
.trust-card{background:var(--card); border:1px solid var(--line); border-radius:var(--r); padding:22px 20px; box-shadow:var(--shadow-sm)}
.trust-card .ic{width:40px;height:40px;border-radius:11px;background:var(--amber-tint);color:var(--amber-deep);display:grid;place-items:center;margin-bottom:12px}
.trust-card .ic svg{width:21px;height:21px}
.trust-card h4{color:var(--ink);font-family:var(--display);font-size:16px;margin-bottom:4px}
.trust-card p{color:var(--muted);font-size:14px}

/* areas hub */

/* contact */
.contact-layout{display:grid; grid-template-columns:1fr 1fr; gap:clamp(28px,4vw,50px); align-items:start}
.contact-info{display:flex; flex-direction:column; gap:16px}
.ci-card{display:flex; gap:16px; align-items:flex-start; background:var(--card); border:1px solid var(--line); border-radius:var(--r); padding:20px 22px; box-shadow:var(--shadow-sm)}
.ci-card .ic{width:46px;height:46px;border-radius:12px;background:var(--amber-tint);color:var(--amber-deep);display:grid;place-items:center;flex:none}
.ci-card .ic svg{width:23px;height:23px}
.ci-card h4{color:var(--ink);font-family:var(--display);font-size:17px;margin-bottom:3px}
.ci-card p{color:var(--muted);font-size:15px}
.ci-card a{color:var(--amber-deep);font-weight:700;font-size:15px}
.form-card{background:var(--card); border:1px solid var(--line-2); border-radius:var(--r-lg); padding:clamp(24px,3vw,34px); box-shadow:var(--shadow)}
.field{margin-bottom:16px}
.field label{display:block; font-size:14px; font-weight:600; color:var(--ink); margin-bottom:7px}
.field input,.field textarea,.field select{width:100%; background:var(--paper); border:1px solid var(--line-2); border-radius:10px; padding:13px 15px;
  color:var(--ink); font-family:var(--sans); font-size:15.5px; transition:border-color .18s, box-shadow .18s}
.field input::placeholder,.field textarea::placeholder{color:var(--faint)}
.field input:focus,.field textarea:focus,.field select:focus{outline:none; border-color:var(--amber-2); box-shadow:0 0 0 3px var(--amber-tint)}
.field textarea{resize:vertical; min-height:120px}
.form-note{font-size:13px; color:var(--faint); margin-top:6px}
.hp{position:absolute; left:-9999px; width:1px; height:1px; overflow:hidden}
.form-alert{display:none; align-items:center; gap:10px; margin-top:16px; padding:14px 16px; border-radius:10px; font-weight:600; font-size:15px}
.form-alert svg{width:20px; height:20px; flex:none}
.form-alert-ok{background:var(--ok-tint); border:1px solid rgba(46,158,104,.35); color:#1c6b45}
.form-alert-err{background:#FBECE7; border:1px solid #EEC7B9; color:#8A3520}
.form-alert-err a{color:inherit; text-decoration:underline}

/* about */
.about-values{display:grid; grid-template-columns:repeat(3,1fr); gap:18px}
.val{background:var(--card); border:1px solid var(--line); border-radius:var(--r-lg); padding:26px 24px; box-shadow:var(--shadow-sm)}
.val .ic{width:50px;height:50px;border-radius:13px;background:var(--amber-tint);color:var(--amber-deep);display:grid;place-items:center;margin-bottom:16px}
.val .ic svg{width:26px;height:26px}
.val h3{font-size:19px;margin-bottom:8px}
.val p{color:var(--muted);font-size:15px}

/* reviews wall */
.reviews-wall{columns:3; column-gap:18px}
.reviews-wall .rev{break-inside:avoid; margin-bottom:18px; display:block}
.reviews-wall .rev .quote{display:block; margin-bottom:14px}

/* ---- real photos ---- */
.photo-frame{position:relative; aspect-ratio:4/3.3; border-radius:var(--r-lg); overflow:hidden; border:1px solid var(--line-2); box-shadow:var(--shadow)}
.photo-frame img{position:absolute; inset:0; width:100%; height:100%; object-fit:cover; object-position:center 62%; display:block}
.photo-frame.photo-wide{aspect-ratio:3/2; margin:8px 0 30px}
.photo-frame.photo-wide img{object-position:center 40%}
.photo-cap{font-size:13px; color:var(--faint); margin:-20px 0 28px}
.photo-pair{display:grid; grid-template-columns:1fr 1fr; gap:16px; margin:0 0 30px}
.photo-pair .photo-frame{aspect-ratio:4/3}
@media (max-width:640px){.photo-pair{grid-template-columns:1fr}}
.photo-badge{position:absolute; left:16px; bottom:16px; background:var(--card); border:1px solid var(--line); border-radius:14px; padding:10px 14px; box-shadow:var(--shadow); display:flex; align-items:center; gap:11px}
.photo-badge .st{color:var(--amber-2); font-size:13px; letter-spacing:1px}
.photo-badge b{font-family:var(--display); font-weight:800; color:var(--ink); font-size:18px; line-height:1; display:block}
.photo-badge .rv{font-size:12px; color:var(--muted)}
@media (max-width:860px){
  /* A portrait crop of the same photograph, so the background fills the tall
     box with nothing lost sideways and the subject stays framed. The wash is
     kept light and the copy carries its own halo, rather than bleaching the
     picture to make text readable. */
  .page-hero.has-photo{--hero-img:url("images/hero-reviews-m.jpg");
    background-image:linear-gradient(180deg, rgba(255,255,255,.94) 0%, rgba(255,255,255,.9) 34%, rgba(255,255,255,.62) 62%, rgba(255,255,255,.12) 100%), var(--hero-img);
    background-size:cover; background-position:center 18%; background-repeat:no-repeat;
    padding-bottom:clamp(150px,42vw,220px)}
  .page-hero.has-photo h1,.page-hero.has-photo .lead{text-shadow:0 1px 2px #fff, 0 2px 14px rgba(255,255,255,.95)}
  .page-hero.has-photo h1,.page-hero.has-photo .lead{max-width:100%}
  .page-hero.has-photo h1,.page-hero.has-photo .lead{max-width:100%; text-shadow:none}
}

/* ============ responsive ============ */
@media (max-width:1000px){
  .nav,.header-phone{display:none}
  .btn-quote{display:none}
  .btn-call-sm{display:inline-flex}
  .burger{display:grid; place-items:center}
  .svc-layout{grid-template-columns:1fr}
  .side-card{position:static; margin-top:8px}
  .contact-layout{grid-template-columns:1fr}
  .trust-cards,.about-values{grid-template-columns:repeat(2,1fr)}
  .reviews-wall{columns:2}
  .hero-grid{grid-template-columns:1fr; gap:36px}
  /* copy first on small screens: a panicking visitor should see the headline and
     the call button without scrolling, not a photograph */
  .hero-visual{order:1; min-height:0}
  .services-grid,.rev-grid{grid-template-columns:repeat(2,1fr)}
  .why,.cov-grid{grid-template-columns:1fr}
  .trust-grid{grid-template-columns:repeat(2,1fr)}
  .trust-item:nth-child(2){border-right:none}
  .trust-item:nth-child(1),.trust-item:nth-child(2){border-bottom:1px solid var(--line)}
  .foot-grid{grid-template-columns:1fr 1fr}
  .steps{grid-template-columns:1fr}
  .step .line{display:none}
}
@media (max-width:620px){
  body{font-size:16px}
  .header-cta .btn span{display:none}
  .services-grid,.rev-grid{grid-template-columns:1fr}
  .trust-cards,.about-values,.includes{grid-template-columns:1fr}
  .reviews-wall{columns:1}
  .why-visual{grid-template-columns:1fr 1fr}
  .foot-grid{grid-template-columns:1fr}
  .cta-inner{flex-direction:column; align-items:flex-start}
  .cta-actions{width:100%}
  .mobile-bar{display:flex}
  body{padding-bottom:18px}
}
