/* Preview engine base CSS. Mobile first, single classes, colours and fonts only through :root tokens.
   Adapted from the approved Ask 4 Harry home, service and suburb designs, with the lawn-only parts removed.
   Per-client tokens are written into a second :root block by the build (from client.json "theme"). */
:root{
  --dark:#24292a;--dark-2:#2f3536;--dark-3:#1b1f20;--accent:#8DC63F;--accent-ink:#006838;
  --ink:#172019;--muted:#56615a;--paper:#fff;--mist:#f3f1ec;--line:#e0dcd3;--star:#f2b318;--on-dark:#d4d6d2;
  --head:Arial,sans-serif;--body:Arial,sans-serif;
  --s1:.25rem;--s2:.5rem;--s3:.75rem;--s4:1rem;--s5:1.5rem;--s6:2rem;--s7:3rem;--s8:4rem;
  --sec:3.5rem;--gut:max(1rem,env(safe-area-inset-left,0px));--r:.875rem;
}
*{box-sizing:border-box;margin:0;padding:0}
html{scroll-behavior:smooth;-webkit-text-size-adjust:100%;scroll-padding-bottom:calc(5rem + env(safe-area-inset-bottom,0px))}
body{font:1.0625rem/1.55 var(--body);color:var(--ink);background:var(--paper);-webkit-font-smoothing:antialiased}
img{display:block;max-width:100%;height:auto}
/* crop point from photo.focus, with photo.focus_phone on phones */
img[style*="--pos"]{object-position:var(--pos)}
@media (max-width:879px){img[style*="--pos"]{object-position:var(--pos-m,var(--pos))}}
svg{display:block}
a{color:inherit}
button,input,select,textarea{font:inherit;color:inherit}
ul,ol{list-style:none}
.in{max-width:72.5rem;margin:0 auto;padding-inline:var(--gut)}
h1,h2,h3{font-family:var(--head);letter-spacing:-.02em;text-wrap:balance}
/* card and list titles are bold spans, not headings: balance them too so none ends on one word ("...to prove / it") */
.why b,.steps b,.jcard b,.rv .job,.faq summary,.tile span,.ilist b,.tour-t{text-wrap:balance}
/* body copy: no one-word last lines ("insured." alone). Browsers without it just wrap as before */
p,blockquote,li{text-wrap:pretty}
::selection{background:var(--accent);color:var(--dark)}
:focus-visible{outline:3px solid var(--dark);outline-offset:2px;box-shadow:0 0 0 7px var(--accent);border-radius:4px}
svg.g{width:1.125rem;height:1.125rem;flex:none}
.tlink{display:inline-flex;align-items:center;gap:var(--s2);min-height:2.75rem;font-weight:700;color:var(--accent-ink)}
.dark .tlink{color:var(--accent)}

/* guided tour for the prospect (site.js): a card plus a spotlight ring that dims the rest of the page */
.tour{position:fixed;left:.75rem;right:.75rem;bottom:calc(.75rem + env(safe-area-inset-bottom,0px));z-index:80;background:#fff;color:var(--ink);border-radius:1rem;padding:1.125rem 1.25rem 1rem;box-shadow:0 18px 50px rgba(0,0,0,.4);transform:translateY(1.5rem);opacity:0;transition:transform .3s ease,opacity .3s ease}
.tour.show{transform:none;opacity:1}
.tour-n{font:700 .8125rem var(--body);letter-spacing:.08em;text-transform:uppercase;color:var(--accent-ink);min-height:1em}
.tour-t{font:800 1.375rem/1.1 var(--head);color:var(--dark);margin-top:var(--s1);padding-right:2rem}
.tour-b p{line-height:1.45;margin-top:var(--s2);max-width:42ch}
.tour-b .tour-sig{font:italic 700 1.0625rem var(--head);color:var(--ink)}
.tour-nav{display:grid;grid-template-columns:auto 1fr;gap:var(--s2);margin-top:var(--s4)}
.tour-nav .b-ghost{width:auto;padding:0 var(--s4);color:var(--ink);box-shadow:inset 0 0 0 2px var(--line)}
.tour-x{position:absolute;top:.375rem;right:.375rem;width:2.75rem;height:2.75rem;border:0;background:none;font-size:1.75rem;line-height:1;color:var(--muted);cursor:pointer}
.tour-ring{position:fixed;z-index:75;pointer-events:none;border-radius:.75rem;box-shadow:0 0 0 3px var(--accent),0 0 0 9999px rgba(0,0,0,.55);transition:width .25s ease,height .25s ease}
.touring .bar{display:none}
.tour.first .tour-x,.tour.first [data-tour="back"]{display:none}
.tour.first .tour-nav{grid-template-columns:1fr}
.tour{max-height:calc(100dvh - 1.5rem);overflow:auto}
.tour-text{margin-top:var(--s4)}
.tour.last:has(.tour-text) [data-tour="next"]{background:none;color:var(--ink);box-shadow:inset 0 0 0 2px var(--line)}
.tour-num{font-size:.9375rem;color:var(--muted);text-align:center;margin-top:var(--s2)!important;max-width:none!important}
.tour.last.hello .tour-nav{grid-template-columns:auto 1fr}
.tour-again{position:fixed;z-index:29;left:max(.75rem,env(safe-area-inset-left,0px));bottom:calc(4.75rem + env(safe-area-inset-bottom,0px));min-height:2.75rem;padding:0 1rem;border:0;border-radius:99px;background:#fff;color:var(--dark);font:800 .9375rem var(--head);box-shadow:0 6px 20px rgba(0,0,0,.28);cursor:pointer}
.tour.hello{box-shadow:0 18px 50px rgba(0,0,0,.4),0 0 0 9999px rgba(0,0,0,.45)}

/* buttons: Call is always the primary */
.btn{display:flex;align-items:center;justify-content:center;gap:var(--s2);min-height:3.25rem;padding:0 1rem;font:800 1.0625rem/1.1 var(--head);text-decoration:none;text-align:center;border-radius:var(--btn-r,.625rem);border:0;cursor:pointer;width:100%}
.btn svg{width:1.125rem;height:1.125rem;flex:none}
.b-acc{background:var(--accent);color:var(--dark)}
/* Secondary buttons are filled, not outline-only (Evan, 10 Nov 2026, D3): weak-looking buttons took people 22% longer
   to find (NN/g eye-tracking; principles CD-09). A quieter fill than Call keeps Call first. */
.b-ghost{background:rgba(255,255,255,.14);box-shadow:inset 0 0 0 2px rgba(255,255,255,.45);color:#fff}
/* secondary button for light sections: a light tint of the dark colour plus its edge */
.b-line{background:color-mix(in srgb,var(--dark) 9%,#fff);box-shadow:inset 0 0 0 2px var(--dark);color:var(--dark)}
/* hover text a shade darker than accent-ink: accent-ink is set to pass on white, and this button's 9% tint took
   Hemmens' teal to 4.4:1 (hover contrast check, 11 Nov 2026) */
.b-line:hover{box-shadow:inset 0 0 0 2px var(--accent-ink);color:color-mix(in srgb,var(--accent-ink) 80%,#000)}
/* the first step band on Home (a consultation or feasibility page; Evan, 10 Nov 2026) */
.fstep{display:grid;gap:var(--s5)}
.fstep .cta2{margin-top:var(--s5)}
.fstep .ilist{align-self:center}
/* project showcase on Home: the first project large, the next two beside it. Not ".show": the tour uses that class
   for its card, and a project rule on it once pushed the tour card off screen (10 Nov 2026) */
.showcase{display:grid;gap:var(--s3)}
.sc-item{position:relative;margin:0;overflow:hidden;border-radius:var(--r);background:var(--dark-2)}
.sc-item img{display:block;width:100%;aspect-ratio:4/3;object-fit:cover;transition:scale .6s ease}
.sc-item figcaption{position:absolute;inset:auto 0 0;padding:var(--s6) var(--s4) var(--s4);background:linear-gradient(180deg,transparent,color-mix(in srgb,var(--dark) 88%,transparent));color:#fff}
.sc-item b{display:block;font:600 1.25rem/1.15 var(--head)}
.sc-item b a{color:#fff;text-decoration:none}
.sc-item b a::before{content:"";position:absolute;inset:0;z-index:1}
.sc-item b a::after{content:"\2192";margin-left:.35em;color:var(--accent)}
.sc-item span{display:block;margin-top:var(--s1);color:var(--on-dark);font-size:.9375rem}
.sc-item:hover img{scale:1.04}
#work .tlink{margin-top:var(--s4)}
.b-dark{background:var(--dark);color:#fff}
.btn[disabled]{opacity:.55;cursor:not-allowed}

/* header */
.top{background:var(--dark);color:#fff;position:relative;z-index:40}
.top .in{display:flex;align-items:center;gap:var(--s3);min-height:3.75rem}
.logo{margin-right:auto;display:flex;align-items:center;min-height:2.75rem;gap:var(--s2);text-decoration:none;font:800 1.125rem/1 var(--head);letter-spacing:-.01em}
.logo img{width:2.5rem;height:2.5rem;border-radius:50%;background:#fff}
.logo.wide img{width:auto;max-width:11rem;height:2.5rem;border-radius:0;background:none;object-fit:contain}
.logo.full img{width:auto;max-width:12.5rem;height:2.625rem;border-radius:0;background:none;object-fit:contain}
.logo.full.round img{width:3.5rem;height:3.5rem}
.legal a{text-decoration:underline}
.tel{display:flex;align-items:center;justify-content:center;gap:var(--s2);min-height:2.75rem;min-width:2.75rem;font:800 1rem var(--head);text-decoration:none;white-space:nowrap}
.tel svg{width:1.125rem;height:1.125rem;color:var(--accent);flex:none}
.tog{display:flex;align-items:center;gap:var(--s2);min-height:2.75rem;padding:0 0 0 .25rem;background:none;border:0;font:800 1rem var(--head);color:#fff;cursor:pointer}
.tog svg{width:1.125rem;height:1.125rem}
.nav{display:none;background:var(--dark);position:absolute;left:0;right:0;top:100%;max-height:calc(100dvh - 3.75rem);overflow:auto;padding:var(--s4) var(--gut) var(--s6);border-top:1px solid rgba(255,255,255,.14)}
.nav.open{display:block}
.nav .top-q{margin-bottom:var(--s3)}
.nav a:not(.btn),.nav summary{display:flex;align-items:center;justify-content:space-between;min-height:3rem;padding:0 var(--s2);font-weight:700;text-decoration:none;cursor:pointer;color:#fff;border-radius:6px}
.nav summary{list-style:none}
.nav summary::-webkit-details-marker{display:none}
.nav summary::after{content:"";width:.5rem;height:.5rem;border-right:2px solid var(--accent);border-bottom:2px solid var(--accent);transform:rotate(45deg);margin-right:.25rem}
.nav details[open]>summary::after{transform:rotate(-135deg)}
.nav details ul{padding-left:var(--s4);border-left:2px solid rgba(255,255,255,.14);margin-left:var(--s2)}
.nav a:not(.btn):hover,.nav summary:hover{color:var(--accent)}

/* swoosh at the foot of a dark panel */
.swoosh{width:100%;height:2.25rem;color:var(--to,#fff)}
.swoosh .fill{fill:currentColor}
.swoosh .stripe{fill:none;stroke:var(--accent);stroke-width:6}

/* sections */
.sec{padding-block:var(--sec)}
.sec h2{font-size:clamp(1.875rem,8vw,3.25rem);font-weight:800;line-height:1.02;color:var(--dark)}
/* The accent word in section headings keeps its colour but isn't italic by default (Evan, 10 Nov 2026, D4): on every
   site it was a big part of the sameness, and critics now call it an AI tell (principles TR). A motif can opt back in
   with its own `.sec h2 em{font-style:italic}`. Hero headlines and slogans keep it. */
.sec h2 em{font-style:normal;color:var(--accent-ink)}
.hero h1 em{font-style:italic;color:var(--accent-ink)}
.dark{background:var(--dark);color:#fff}
.dark h2,.sec.dark h2{color:#fff}
.dark h2 em,.sec.dark h2 em,.hero h1 em{color:var(--accent)}
.mist{background:var(--mist)}
.lede{max-width:58ch;margin-top:var(--s3)}
.dark .lede{color:var(--on-dark)}
.shead{margin-bottom:var(--s5)}
.prose p{max-width:62ch;margin-top:var(--s3)}
.prose p:first-child{margin-top:0}
.prose .ilist{margin-top:var(--s5)}

/* hero. Default layout: the job photo fills the panel, text sits on a scrim at the foot.
   Motif files can switch to a split layout (photo framed in the brand shape beside the text). */
.hero{position:relative;overflow:hidden}
.hero.home,.hero.svc:not(.noimg){display:grid;grid-template-rows:1fr auto;min-height:min(calc(100svh - 3.75rem - 4.25rem),48rem)}
.hero.svc:not(.noimg){min-height:min(calc(100svh - 3.75rem - 4.25rem),40rem)}
.hero-media{position:absolute;inset:0}
.hero-media img{width:100%;height:100%;object-fit:cover}
.hero-media::after{content:"";position:absolute;inset:0;background:linear-gradient(180deg,color-mix(in srgb,var(--dark) 10%,transparent) 0%,color-mix(in srgb,var(--dark) 25%,transparent) 28%,color-mix(in srgb,var(--dark) 86%,transparent) 58%,var(--dark) 100%)}
.hero>.in{position:relative;z-index:2;align-self:end;width:100%}
.hero .edge,.hero .swoosh{position:relative;z-index:3}
.hero-text{padding-block:var(--s4) var(--s5)}
.hero.home .hero-text,.hero.svc:not(.noimg) .hero-text{padding-top:10rem}
.hero.plain .hero-text,.hero.noimg .hero-text{padding-bottom:var(--s7)}
.hero.plain h1{font:800 clamp(2.125rem,9vw,3.75rem)/1.02 var(--head);letter-spacing:-.02em;margin-top:var(--s4)}
.hero.plain h1.long{font-size:clamp(1.75rem,7vw,3rem)}  /* long carried-over blog titles: five lines on a phone otherwise */
.hero-text .crumb ol{padding-top:0;margin-bottom:var(--s3)}
.crumb ol{display:flex;flex-wrap:wrap;gap:var(--s2);font-size:.9375rem;color:var(--on-dark);padding-top:var(--s3)}
.crumb li+li::before{content:"/";margin-right:var(--s2);opacity:.6}
.crumb a{text-decoration:none;color:#fff;display:inline-block;padding:.25rem 0}
.gbadge{display:inline-flex;align-items:center;gap:var(--s2);background:var(--dark-2);box-shadow:inset 0 0 0 1.5px rgba(255,255,255,.22);color:#fff;border-radius:99px;min-height:2.75rem;padding:0 .75rem 0 .5rem;font-weight:700;font-size:.9375rem;text-decoration:none;white-space:nowrap}
.gbadge .st{color:var(--star);letter-spacing:1px}
.gbadge .n{color:var(--on-dark);font-weight:400}
.slogan{font:800 clamp(2.375rem,12.5vw,4.75rem)/1 var(--head);letter-spacing:-.02em;margin-top:var(--s4)}
.slogan em{display:block;font-style:italic;color:var(--accent);padding-left:.04em}
.hero h1{font:700 1.0625rem/1.3 var(--body);letter-spacing:0;margin-top:var(--s3);color:#fff}
.hero.svc h1{font:800 clamp(2rem,9vw,3.5rem)/1.02 var(--head);letter-spacing:-.02em;margin-top:var(--s4)}
.hero .sub{color:#e6e7e4;margin-top:var(--s2);max-width:44ch;line-height:1.45}
.btns{display:grid;grid-template-columns:1.35fr 1fr;gap:var(--s2);margin-top:var(--s5)}
.btns .call{min-height:3.5rem}
.btns .call span{display:none}
.btns .b-ghost{min-height:3.5rem}
.prom{margin-top:var(--s3);font-size:.9375rem;line-height:1.4;color:var(--on-dark)}
/* phones: Call and Quote come straight after the headline, so they sit on the first screen above the call bar */
@media (max-width:879px){
  .hero.home .hero-text,.hero.svc .hero-text{display:flex;flex-direction:column}
  .hero-text>.gbadge{align-self:flex-start}
  .hero-text>.btns{order:5}
  .hero-text>.sub{order:6;margin-top:var(--s4)}
  .hero-text>.prom{order:7}
}

/* reviews */
.score{display:inline-grid;grid-template-columns:auto minmax(0,1fr);column-gap:var(--s4);align-items:center}
.score .big{grid-row:1/3;font:800 4.5rem/.85 var(--head);color:var(--dark);letter-spacing:-.04em}
.score .st{color:#b57f00;font-size:1.375rem;letter-spacing:2px;line-height:1.1}
.score .src{display:flex;align-items:center;gap:var(--s2);font-weight:700;min-height:1.75rem}
.score-h{margin:var(--s4) 0 var(--s5)}
.rail{display:grid;grid-auto-flow:column;grid-auto-columns:86%;gap:var(--s3);align-items:stretch;overflow-x:auto;scroll-snap-type:x mandatory;scroll-padding-inline:var(--gut);padding-inline:var(--gut);margin-inline:calc(-1 * var(--gut));padding-block:2px 6px;scrollbar-width:none}
.rail::-webkit-scrollbar{display:none}
/* cards in a rail are one height at every width (Evan, 10 Nov 2026: "The boxes don't line up, so longer reviews have
   bigger boxes"; this replaces the phone-only align-items:start). The quote grows and the name and date sit at the foot,
   so a short review's spare room reads as layout, not a gap. Opening one long review doesn't stretch the others. */
.rail:has(.rv.open){align-items:start}
.rv{scroll-snap-align:start;background:#fff;border:1.5px solid var(--line);border-radius:var(--r);padding:var(--s4);display:flex;flex-direction:column;gap:var(--s3)}
.rv .stars{color:#b57f00;letter-spacing:1px;line-height:1}
.rv .job{display:block;margin-top:var(--s2);font:800 1.125rem/1.15 var(--head);color:var(--accent-ink)}
.rv blockquote{line-height:1.45;flex:1}
.rv blockquote p+p{margin-top:var(--s2)}
.rv figcaption{font-size:.9375rem;color:var(--muted);display:flex;align-items:center;gap:var(--s2);flex-wrap:wrap}
.rv figcaption b{color:var(--ink)}
/* long reviews in a rail fold with "Read more" (site.js); the fade shows there's more */
.rv.long blockquote{flex:none;max-height:calc(1.45em * 9);overflow:hidden;-webkit-mask-image:linear-gradient(180deg,#000 62%,transparent);mask-image:linear-gradient(180deg,#000 62%,transparent)}
.rv.long.open blockquote{max-height:none;-webkit-mask-image:none;mask-image:none}
/* phones fold a little earlier (site.js: over 9 lines, shown as 7), so one long review doesn't make every card tall */
@media (max-width:879px){.rv.long blockquote{max-height:calc(1.45em * 7)}}
.rv .more{align-self:flex-start;margin:calc(-1 * var(--s2)) 0 auto;min-height:2.75rem;padding:0;background:none;border:0;font:700 1rem var(--body);color:var(--accent-ink);text-decoration:underline;text-underline-offset:3px;cursor:pointer}
.rlist{display:grid;gap:var(--s4)}
.rlist .rv{max-width:48rem}
/* few reviews (under 4 in total, Hemmens 9 Nov 2026): no rail and no folding; every review in full, the first as a
   large lead quote, the others beside it on desktop */
.rail.few{grid-auto-flow:row;grid-auto-columns:auto;grid-template-columns:minmax(0,1fr);overflow:visible;margin-inline:0;padding-inline:0;scroll-snap-type:none;align-items:start}
.rail.few .rv:first-child blockquote{font:500 clamp(1.1875rem,4.8vw,1.5rem)/1.4 var(--head);color:var(--dark)}
@media (min-width:880px){
  .rail.few{align-items:stretch}
  .rail.few.n2,.rail.few.n3{grid-template-columns:1.3fr 1fr}
  .rail.few.n3 .rv:first-child{grid-row:1/3}
  .rail.few .rv:first-child{padding:var(--s5)}
}

/* service doors */
.doors{display:grid;gap:var(--s4)}
.door{position:relative;background:#fff;border-radius:var(--r);overflow:hidden;display:flex;flex-direction:column;border:1.5px solid var(--line)}
.door h3 a::before{content:"";position:absolute;inset:0;z-index:1}
.door:hover{border-color:var(--accent-ink)}
.also{margin-top:var(--s5)}
.door img{width:100%;aspect-ratio:16/10;object-fit:cover}
.door .dh{padding:var(--s4);flex:1}
.door h3{font-size:1.375rem;font-weight:800;line-height:1.1}
.door h3 a{color:var(--dark);text-decoration:none}
.door h3 a::after{color:var(--accent-ink)}
.door p{margin-top:var(--s2);line-height:1.45}

/* photo rail and job cards */
.prail{display:grid;grid-auto-flow:column;grid-auto-columns:78%;gap:var(--s3);overflow-x:auto;scroll-snap-type:x mandatory;padding-inline:var(--gut);margin-inline:calc(-1 * var(--gut));scrollbar-width:none;margin-top:var(--s5)}
.prail::-webkit-scrollbar{display:none}
.prail figure{scroll-snap-align:start;position:relative}
.prail img{border-radius:var(--r);aspect-ratio:1/1;object-fit:cover;width:100%}
.prail figcaption{font-size:.9375rem;color:var(--muted);margin-top:var(--s2);line-height:1.35}
.tag{position:absolute;top:var(--s2);left:var(--s2);background:var(--dark-3);color:#fff;font:italic 800 .9375rem var(--head);padding:.2rem .6rem;border-radius:.375rem}
.tag.after{background:var(--accent);color:var(--dark)}
.prail .tag{color:#fff;margin-top:0}
.prail .tag.after{color:var(--dark)}
.jcards{display:grid;gap:var(--s4)}
.jcard{display:block;background:#fff;border-radius:var(--r);overflow:hidden;border:1.5px solid var(--line)}
.jcard img{aspect-ratio:4/3;object-fit:cover;width:100%}
.jcard figcaption{padding:var(--s4)}
.jcard b{display:block;font:800 1.25rem/1.15 var(--head);color:var(--dark)}
.jcard span{display:block;margin-top:var(--s1);color:var(--muted);font-size:.9375rem}
/* call-to-action card in the spare space of the last row: message and buttons centred in the card, the rating pinned
   to the foot. A short accent rule opens it, so it reads as a designed panel rather than an empty card. */
.door.dcta{background:var(--dark);border-color:var(--dark);color:var(--on-dark)}
.door.dcta .dh{display:flex;flex-direction:column;padding:var(--s5)}
.door.dcta h3{color:#fff;font-size:clamp(1.375rem,5.5vw,1.625rem);margin-top:auto}
.door.dcta h3::before{content:"";display:block;width:2.5rem;height:.25rem;border-radius:99px;background:var(--accent);margin-bottom:var(--s3)}
.door.dcta p{color:var(--on-dark);max-width:40ch}
.door.dcta .cta2{margin-top:var(--s5);display:grid;grid-template-columns:repeat(auto-fit,minmax(8.5rem,1fr));gap:var(--s2);justify-content:stretch}
.door.dcta .cta2 .btn{width:100%;min-height:3.25rem;padding:0 var(--s3);white-space:nowrap}
.door.dcta .dproof{display:flex;align-items:center;gap:var(--s2);flex-wrap:wrap;margin-top:auto;padding-top:var(--s5);font-size:.9375rem;line-height:1.3;color:var(--on-dark);max-width:none}
.door.dcta .dproof .st{color:var(--star);letter-spacing:1px}
.door.dcta .dproof::before{content:"";flex-basis:100%;height:1px;background:rgba(255,255,255,.16);margin-bottom:var(--s3)}
.door.dcta:hover{transform:none;box-shadow:none;border-color:var(--dark)}
.jcard.proj{position:relative}
.jcard.proj b a{color:var(--dark);text-decoration:none;display:inline-block;padding:.5rem 0}
.jcard.proj b{margin-top:-.5rem}
.jcard.proj b a::before{content:"";position:absolute;inset:0;z-index:1}
.jcard.proj b a::after{content:"\2192";margin-left:.3em;color:var(--accent-ink)}
.jcard.proj span{display:-webkit-box;-webkit-line-clamp:3;-webkit-box-orient:vertical;overflow:hidden}
.machines{margin-top:var(--s5)}
.door.mach h2{font-size:1.5rem;line-height:1.1}
.door.mach .specs{margin-top:var(--s3);font-size:.9375rem}
.door.mach .specs li{padding-top:var(--s1);padding-bottom:var(--s1)}
.morelist{margin-top:var(--s5);display:flex;flex-wrap:wrap;gap:var(--s2) var(--s4);align-items:baseline}
.morelist b{flex-basis:100%}
/* the services after the first six: tidy pill links (loose underlined links wrapped unevenly on phones) */
.morelist{gap:var(--s2)}
.morelist b{margin-bottom:var(--s1)}
.morelist a{display:inline-flex;align-items:center;gap:.4em;min-height:2.75rem;padding:0 1rem;font-weight:700;color:var(--dark);text-decoration:none;background:#fff;border:1.5px solid var(--line);border-radius:99px;transition:border-color .18s ease}
.morelist a::after{content:"\2192";color:var(--accent-ink)}
.morelist a:hover{border-color:var(--accent-ink)}

/* includes list */
.incl{display:grid;gap:var(--s5)}
.incl img{border-radius:var(--r);aspect-ratio:4/3;object-fit:cover;width:100%}
.ilist{display:grid;gap:var(--s3);margin-top:var(--s4)}
.ilist li{padding-left:1.75rem;position:relative;line-height:1.45}
.ilist li::before{content:"";position:absolute;left:0;top:.45rem;width:.75rem;height:.75rem;border-radius:2px;background:var(--accent);transform:rotate(45deg)}
.ilist b{font-weight:700}

/* how it works */
.steps{display:grid;gap:var(--s5);margin-top:var(--s6);counter-reset:s}
.steps li{position:relative;padding-left:4rem;min-height:3rem;counter-increment:s}
.steps li::before{content:counter(s);position:absolute;left:0;top:0;width:3rem;height:3rem;border-radius:50%;background:var(--accent);color:var(--dark);display:grid;place-items:center;font:800 1.25rem var(--head)}
.steps b{font:800 1.25rem/1.15 var(--head);display:block;margin-bottom:var(--s2)}
.steps span{line-height:1.45;display:block;color:var(--on-dark)}
.cta2{display:grid;gap:var(--s2);margin-top:var(--s6)}

/* meet the owner */
.meet{display:grid;gap:var(--s5)}
.meet .pics img{border:.3125rem solid #fff;border-radius:.5rem;object-fit:cover;box-shadow:0 10px 24px rgba(0,0,0,.35);aspect-ratio:4/3;width:100%;transform:rotate(1deg)}
.meet h3{margin-top:var(--s2);font-size:clamp(1.375rem,5.8vw,1.75rem);font-weight:800;line-height:1.15;color:#fff}
.meet .lede{color:#e6e7e4}
.meet .btn{margin-top:var(--s5);max-width:16rem}
.creds span{display:inline-block}  /* each credential stays on one line where it fits ("$20 / million" split it) */
.creds{margin-top:var(--s5);padding-top:var(--s4);border-top:1px solid rgba(255,255,255,.2);font-weight:700;color:var(--accent);line-height:1.6}

/* FAQ */
.faqwrap{display:grid;gap:var(--s5)}
.faq{display:grid;gap:var(--s2)}
/* open item: white with a full accent border, not a one-side stripe (a common template tell) */
.faq details{background:var(--mist);border-radius:var(--r);border:2px solid transparent}
.faq details[open]{background:#fff;border-color:var(--accent-ink)}
.faq summary{display:flex;align-items:center;justify-content:space-between;gap:var(--s3);min-height:4rem;padding:var(--s3) var(--s4);font:800 1.125rem/1.2 var(--head);color:var(--dark);cursor:pointer;list-style:none}
.faq summary::-webkit-details-marker{display:none}
.faq summary::after{content:"+";flex:none;width:2rem;height:2rem;border-radius:50%;background:var(--dark);color:#fff;display:grid;place-items:center;font:800 1.25rem/1 var(--body)}
.faq details[open] summary::after{content:"\2212";background:var(--accent-ink)}
.faq details p{padding:0 var(--s4) var(--s4);max-width:58ch}
.faq details a{color:var(--accent-ink);font-weight:700}

/* areas */
.chips{display:flex;flex-wrap:wrap;gap:var(--s2);margin-top:var(--s4)}
.chips li{display:inline-flex;align-items:center;min-height:2.5rem;padding:0 var(--s4);border-radius:99px;background:#fff;border:1.5px solid var(--line);font-weight:700;color:var(--dark)}

/* why choose us: cards with the motif bullet as an icon (motif files restyle .why li::before) */
.why{display:grid;gap:var(--s4);counter-reset:w}
.why li{position:relative;background:var(--mist);border-radius:var(--r);padding:var(--s5) var(--s5) var(--s5) 4.25rem;counter-increment:w}
.why li::before{content:"";position:absolute;left:var(--s5);top:1.55rem;width:1.5rem;height:1.5rem;border-radius:3px;background:var(--accent);transform:rotate(45deg)}
.why b{display:block;font:800 1.25rem/1.15 var(--head);color:var(--dark)}
.why span{display:block;margin-top:var(--s2);line-height:1.5}

/* where we work: copy plus one map of the whole area */
.areas{display:grid;gap:var(--s5)}
.areas .tlink{margin-top:var(--s3)}
.map{position:relative;border-radius:var(--r);overflow:hidden;aspect-ratio:4/3;background:var(--line);box-shadow:0 10px 30px rgba(0,0,0,.12)}
/* Google's "Open in Maps" place card sits at the top of every embed and gets cut off by shaped map frames
   (Evan, 8 Nov 2026), so the iframe starts above the frame and that card stays out of view. Attribution stays at the foot. */
.map iframe{position:absolute;left:0;right:0;bottom:0;top:-6.5rem;width:100%;height:calc(100% + 6.5rem);border:0;filter:saturate(.85)}

/* owner photo stand-in */
.ownph{display:grid;place-items:center;align-content:center;gap:var(--s3);aspect-ratio:4/3;width:100%;background:linear-gradient(160deg,var(--dark-2),var(--dark-3));color:var(--on-dark);border-radius:.5rem;font-weight:700;text-align:center;padding:var(--s4)}
.ownph svg{width:4.5rem;height:4.5rem;fill:var(--accent);opacity:.85}
.meet .pics .ownph{border:.3125rem solid #fff;box-shadow:0 10px 24px rgba(0,0,0,.35);transform:rotate(1deg)}

/* service photos when there are only 1 to 3 */
.pgrid{display:grid;gap:var(--s3);margin-top:var(--s5)}
.pgrid figure{position:relative}
.pgrid img{width:100%;border-radius:var(--r);aspect-ratio:4/3;object-fit:cover}
.pgrid.n3{grid-template-columns:1fr 1fr}
.pgrid.n3 figure:first-child{grid-column:1/-1}
.pgrid.n3 figure:first-child img{aspect-ratio:16/9}
.pgrid.n1 img{aspect-ratio:16/9}

/* multi-step quote form */
.qprog{display:flex;align-items:center;gap:var(--s3)}
.qbar{flex:1;height:.375rem;border-radius:99px;background:rgba(255,255,255,.16);overflow:hidden}
.qbar i{display:block;height:100%;background:var(--accent);transform:scaleX(.334);transform-origin:left;transition:transform .25s ease}
.qcount{font-size:.875rem;color:var(--on-dark);white-space:nowrap}
.qs{display:grid;gap:var(--s4)}
.qs legend{padding:0;margin-bottom:var(--s4)}
.ms.js .qs{display:none}
.ms.js .qs.on{display:grid}
.ms:not(.js) .qprog,.ms:not(.js) [data-next],.ms:not(.js) [data-back]{display:none}
.qnav{display:grid;grid-template-columns:auto 1fr;gap:var(--s2)}
.qnav .btn:only-child{grid-column:1/-1}
.qnav .b-ghost{width:auto;padding:0 var(--s5)}
.q3 textarea::placeholder{color:#6b716b}

/* contact page */
.cgrid{display:grid;gap:var(--s4)}
.cbox{background:var(--mist);border-radius:var(--r);padding:var(--s5)}
.cbox p{margin-top:var(--s1)}
.cbox .chips li{background:#fff}
.ct{font:800 .9375rem var(--head);color:var(--accent-ink);text-transform:uppercase;letter-spacing:.06em;margin:0 0 var(--s2)!important}
.cbig{display:inline-block;font:800 clamp(2rem,9vw,3rem)/1.05 var(--head);color:var(--dark);text-decoration:none;white-space:nowrap}
.cmail{font-weight:700;color:var(--dark);overflow-wrap:anywhere;display:inline-block;padding:.25rem 0}

/* quote form (inactive in previews) */
.qwrap{display:grid;gap:var(--s6)}
.door-no{margin-top:var(--s5)}
.door-no small{display:block;font:700 1rem var(--body);color:var(--on-dark);margin-bottom:var(--s2)}
.door-no a{display:inline-block;font:800 clamp(2.25rem,11vw,4rem)/1 var(--head);color:#fff;text-decoration:none;padding-bottom:var(--s2);border-bottom:6px solid var(--accent);white-space:nowrap}
.qproof{display:flex;align-items:center;gap:var(--s2);margin-top:var(--s5);font-size:.9375rem;color:var(--on-dark)}
.q3{background:var(--dark-2);border:1.5px solid rgba(255,255,255,.14);border-radius:var(--r);padding:var(--s5) var(--s4);display:grid;gap:var(--s4)}
.q3 h3{font-size:1.375rem;font-weight:800;line-height:1.1}
.q3 fieldset{border:0;min-width:0}
.q3 .lab{font:600 1rem/1.3 var(--body);color:#fff;display:block;margin-bottom:var(--s2)}
.q3 input[type=text],.q3 input[type=tel],.q3 textarea{width:100%;min-height:3.25rem;font:1.0625rem var(--body);padding:.5rem .875rem;border:0;border-radius:.625rem;background:#fff;color:var(--ink)}
.q3 textarea{min-height:5.5rem;resize:vertical}
.tiles{display:grid;grid-template-columns:1fr 1fr;gap:var(--s2)}
.tile{position:relative;display:block;cursor:pointer}
.tile input{position:absolute;opacity:0;inset:0;width:100%;height:100%;cursor:pointer;margin:0}
.tile span{display:flex;align-items:center;min-height:3.5rem;padding:.5rem .75rem;background:var(--dark);border:2px solid rgba(255,255,255,.26);border-radius:.75rem;font:800 1rem/1.15 var(--head);color:#fff}
.tile input:checked+span{border-color:var(--accent);box-shadow:inset 0 0 0 1px var(--accent)}
.tile input:focus-visible+span{outline:3px solid #fff;outline-offset:2px}
.fine{font-size:.9375rem;color:var(--on-dark);line-height:1.4}
.pvnote{background:#fff4c7;color:#3a2f00;border-radius:.5rem;padding:var(--s3);font-size:.9375rem;line-height:1.35}

/* footer */
/* phones: the room for the sticky call bar is part of the footer, so the page ends in footer colour, not a white strip */
footer{background:var(--dark-3);color:#d9dbd7;padding-block:var(--s6) calc(var(--s6) + 4.5rem + env(safe-area-inset-bottom,0px));font-size:1rem}
footer .grid{display:grid;gap:var(--s5)}
footer a{color:#d9dbd7;text-decoration:none}
footer a:hover{color:#fff;text-decoration:underline}
.ft{font:800 1.0625rem var(--head);color:var(--accent);margin-bottom:var(--s2)}
.flist a{display:flex;align-items:center;min-height:2.5rem;padding-block:.3rem;line-height:1.3}  /* a name on two lines keeps clear of the next */
.fcols{display:grid;grid-template-columns:1fr 1fr;gap:var(--s5) var(--s4)}
.fbrand b{display:block;font:800 1.25rem var(--head);color:#fff;margin-bottom:var(--s2)}
.flogo{height:3.25rem;width:auto;margin-bottom:var(--s4)}
.flogo.round{height:6rem}
.fbrand p{line-height:1.6}
.fbrand p a{display:inline-flex;align-items:center;min-height:2.75rem}
.legal{border-top:1px solid rgba(255,255,255,.12);margin-top:var(--s5);padding-top:var(--s3);font-size:.875rem;color:#b9bdb8;line-height:1.5}

/* sticky call bar on phones */
.bar{position:fixed;left:0;right:0;bottom:0;z-index:30;background:var(--dark);border-top:3px solid var(--accent);padding:.5rem max(.5rem,env(safe-area-inset-right,0px)) calc(.5rem + env(safe-area-inset-bottom,0px)) max(.5rem,env(safe-area-inset-left,0px));display:grid;grid-template-columns:1fr 1fr;gap:.5rem}
.bar .btn{min-height:3rem;padding:0 .25rem}
.bar.t3{grid-template-columns:1fr auto 1fr}
.bar.t3 .btn[href^="sms:"]{padding:0 1rem}
/* "Prefer to text?" under the hero buttons (D5): only when business.text_ok and a mobile number */
.hero .txt{margin-top:var(--s3);font-size:1rem;color:var(--on-dark)}
.hero .txt a{color:#fff;font-weight:700;white-space:nowrap}
/* out of the way while the hero's own Call and Quote buttons show, or while someone types in a form (site.js) */
.bar{transition:transform .25s ease,visibility .25s}
.bar.hide{transform:translateY(100%);visibility:hidden}
.bar.hide~.tour-again{bottom:calc(1rem + env(safe-area-inset-bottom,0px))}
@media (prefers-reduced-motion:reduce){.bar{transition:none}}

/* narrow phones: the business name keeps its room; the number stays on the hero button and the sticky bar */
@media (max-width:429px){.tel span{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0)}.logo{font-size:1rem;line-height:1.1;min-width:0}}
@media (min-width:560px){
  .rail{grid-auto-columns:46%}
  .prail{grid-auto-columns:40%}
  .btns,.cta2{grid-template-columns:auto auto;justify-content:start}
  .btns .btn,.cta2 .btn{width:auto;min-height:3.5rem;padding:0 var(--s5)}
  .jcards,.doors{grid-template-columns:1fr 1fr}
  /* two across: a CTA card that would start a row on its own spans the row instead of leaving a hole */
  .doors>.dcta:nth-child(odd){grid-column:1/-1}
  /* an odd machine card left over at the end becomes a wide card (photo beside text). Project and blog cards are
     articles and stay one column wide, with any spare space left empty (Evan, 10 Nov 2026) */
  .machines>.door:last-child:nth-child(odd):not(:first-child){grid-column:1/-1;display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);align-items:center}
  .machines>.door:last-child:nth-child(odd):not(:first-child) img{height:100%}
}
@media (min-width:880px){
  :root{--sec:5.5rem}
  footer{padding-bottom:var(--s6)}
  .bar{display:none}
  .top{position:sticky;top:0}
  .top .in{min-height:5rem}
  /* a jump to #quote or an FAQ lands below the sticky header, not under it (design-skill dig, 11 Nov 2026) */
  main [id]{scroll-margin-top:6rem}
  .logo{font-size:1.375rem}
  .logo img{width:3.25rem;height:3.25rem}
  .tel{font-size:1.1875rem;order:3}
  .tog{order:4}
}
/* The full menu only from 1180 px. Between 880 and 1180 the menu, the header button and the phone number don't fit
   on one line, and wrapped labels ("Book a / consultation", "Our / projects") looked "super ugly" (Evan, 10 Nov 2026),
   so tablets and small laptops keep the menu button. Labels never wrap; render audit FAILs nav-wrap. */
@media (min-width:1180px){
  .tog{display:none}
  .nav{order:2;display:block;position:static;max-height:none;overflow:visible;background:none;border:0;padding:0}
  .nav>ul{display:flex;align-items:center;gap:var(--s1)}
  .nav>ul>li{position:relative}
  .nav a:not(.btn),.nav summary{font:700 1rem var(--body);padding:0 var(--s2);min-height:2.75rem;gap:var(--s2)}
  .nav>ul>li>a,.nav summary,.nav .top-q .btn{white-space:nowrap}
  .nav .top-q{order:9;margin:0 0 0 var(--s2)}
  .nav .top-q .btn{min-height:2.75rem;width:auto;font-size:1rem}
  .nav details ul{position:absolute;top:100%;left:0;min-width:17rem;background:var(--dark);border:1px solid rgba(255,255,255,.18);border-radius:.625rem;padding:var(--s2);margin:0;box-shadow:0 14px 30px rgba(0,0,0,.3)}
}
@media (min-width:880px){
  .swoosh{height:4rem}
  .logo.full img{height:3.25rem;max-width:16rem}
  .logo.full.round img{width:4.25rem;height:4.25rem}
  .hero.home,.hero.svc:not(.noimg){min-height:40rem}
  .hero.svc:not(.noimg){min-height:34rem}
  .hero-media::after{background:linear-gradient(90deg,var(--dark) 0%,color-mix(in srgb,var(--dark) 82%,transparent) 34%,color-mix(in srgb,var(--dark) 20%,transparent) 66%,transparent 100%)}
  .hero>.in{align-self:center}
  .hero-text{max-width:38rem}
  .hero.home .hero-text,.hero.svc:not(.noimg) .hero-text{padding:var(--s7) 0 var(--s8)}
  .hero.plain .hero-text,.hero.noimg .hero-text{padding:var(--s6) 0 var(--s7);max-width:48rem}
  .hero h1{font-size:1.375rem;margin-top:var(--s4)}
  .hero .sub{font-size:1.1875rem}
  .btns{grid-template-columns:auto auto}
  .btns .call span{display:inline}
  .tour{left:auto;right:1.5rem;bottom:1.5rem;width:24rem}
  .tour.hello{right:50%;bottom:50%;transform:translate(50%,50%)}
  .tour.hello:not(.show){transform:translate(50%,calc(50% + 1.5rem))}
  .cgrid{grid-template-columns:1fr 1fr}
  /* three contact boxes: the phone box runs down the left beside email and hours, so no box sits alone on a row */
  .cgrid:has(>.cbox:nth-child(3))>.cbox:first-child{grid-row:span 2;display:flex;flex-direction:column;justify-content:center}
  .faqwrap h2{font-size:clamp(1.875rem,3.4vw,2.75rem);hyphens:auto}
  .why{grid-template-columns:repeat(2,1fr);gap:var(--s5)}
  .areas{grid-template-columns:minmax(0,.9fr) minmax(0,1.1fr);gap:var(--s8);align-items:center}
  .pgrid.n2,.pgrid.n3{grid-template-columns:repeat(var(--cols,2),1fr)}
  .pgrid.n3{--cols:3}
  .pgrid.n3 figure:first-child{grid-column:auto}
  .pgrid.n3 figure:first-child img{aspect-ratio:4/3}
  .pgrid.n1{max-width:48rem}
  .flogo{height:4rem}
  .flogo.round{height:7.5rem}
  .rail{grid-auto-columns:calc((100% - 2 * var(--s3)) / 3);margin-inline:0;padding-inline:0}
  .prail{grid-auto-columns:calc((100% - 3 * var(--s3)) / 4);margin-inline:0;padding-inline:0}
  /* 3 across, left-aligned. A short last row of service cards gets a call-to-action card in the spare space
     (Evan, 8 Nov 2026: no centred rows); with one card left over, the CTA takes both spare columns */
  .doors{grid-template-columns:repeat(3,1fr);gap:var(--s5)}
  .doors>.dcta:nth-child(odd){grid-column:auto}
  .door.dcta.r1{grid-column:span 2}
  /* two or four services: two across, bigger photos (Evan, 10 Nov 2026: a layout made for the count) */
  .doors.n2,.doors.n4{grid-template-columns:repeat(2,1fr)}
  .doors.n2 .door img,.doors.n4 .door img{aspect-ratio:16/9}
  .doors.n2 .door .dh,.doors.n4 .door .dh{padding:var(--s5)}
  .fstep{grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:var(--s8);align-items:center}
  .showcase.n3{grid-template-columns:minmax(0,1.6fr) minmax(0,1fr);grid-template-rows:1fr 1fr}
  .showcase.n3 .lead{grid-row:1/3}
  .showcase .lead img{height:100%;aspect-ratio:auto;min-height:30rem}
  .showcase.n2{grid-template-columns:1fr 1fr}
  .sc-item figcaption{padding:var(--s7) var(--s5) var(--s5)}
  .sc-item.lead b{font-size:1.75rem}
  .door.dcta .dh{padding:var(--s6)}
  .tour-again{bottom:1.5rem;left:1.5rem}
  .jcards{grid-template-columns:repeat(3,1fr)}
  .machines>.door:last-child:nth-child(odd):not(:first-child){grid-column:auto;display:flex}
  .machines>.door:last-child:nth-child(odd):not(:first-child) img{height:auto}
  /* three across: one machine alone on the last row becomes a wide card, photo the width of one column */
  .machines>.door:last-child:nth-child(3n+1):not(:first-child){grid-column:1/-1;display:grid;grid-template-columns:minmax(0,1fr) minmax(0,2fr);align-items:center}
  .machines>.door:last-child:nth-child(3n+1):not(:first-child) img{height:100%}
  .incl{grid-template-columns:minmax(0,.9fr) minmax(0,1.1fr);gap:var(--s8);align-items:center}
  /* steps are a sequence, read left to right: one row when they fit (Evan, 8 Nov 2026: a centred second row zig-zagged
     the numbers on Treeworx), wrapping left-aligned on narrower screens. Not the doors' centring trick. */
  .steps{grid-template-columns:repeat(3,1fr);gap:var(--s6) var(--s7)}  /* always three steps (model) */
  /* the owner stand-in stays a framed card, not a big empty panel (review, 8 Nov 2026) */
  .meet .pics .ownph{aspect-ratio:16/9}
  .steps li{padding:4.25rem 0 0}
  .faqwrap{grid-template-columns:minmax(0,.8fr) minmax(0,1.2fr);gap:var(--s8);align-items:start}
  .meet{grid-template-columns:minmax(0,1fr) minmax(0,1.05fr);gap:var(--s4) var(--s8);align-items:center}
  .qwrap{grid-template-columns:minmax(0,1fr) minmax(0,1.1fr);gap:var(--s8);align-items:start}
  .q3{padding:var(--s6)}
  footer .grid{grid-template-columns:minmax(0,.9fr) minmax(0,2fr);gap:var(--s7)}
  .fcols{grid-template-columns:repeat(3,1fr)}
}
@media (prefers-reduced-motion:reduce){html{scroll-behavior:auto}}

/* Feedback and motion. Hover and press feedback everywhere. Entrance and scroll motion only under html.motion, which
   <head> sets unless the visitor prefers reduced motion or the URL has ?nopop/?shots (screenshots and checks measure
   the settled page). Uses the separate translate/scale properties so motif transforms (rotated bullets) survive. */
.btn{transition:background-color .18s ease,box-shadow .18s ease,color .18s ease,transform .12s ease}
.btn:active{transform:translateY(1px) scale(.985)}
.btn:focus-visible,.door a:focus-visible,.gbadge:focus-visible{outline:3px solid var(--accent);outline-offset:3px}
.gbadge{transition:box-shadow .18s ease}
.door,.jcard{transition:transform .2s ease,box-shadow .2s ease,border-color .2s ease}
.door img,.jcard img{transition:scale .6s ease}
.door h3 a::after{content:"\2192";display:inline-block;margin-left:.3em;transition:translate .2s ease}
@media (hover:hover){
  .b-acc:hover{background:color-mix(in srgb,var(--accent) 80%,#fff)}
  .b-ghost:hover{background:rgba(255,255,255,.08);box-shadow:inset 0 0 0 2px var(--accent)}
  .b-dark:hover{background:color-mix(in srgb,var(--dark) 78%,#fff)}
  .gbadge:hover{box-shadow:inset 0 0 0 1.5px var(--accent)}
  .door:hover,.jcard:hover{transform:translateY(-4px);box-shadow:0 14px 30px rgba(0,0,0,.14)}
  .door:hover img,.jcard:hover img{scale:1.04}
  .door:hover h3 a::after{translate:5px 0}
}
/* reduced motion: no card lift, photo zoom or arrow nudge on hover (principles VD-26/27, 10 Nov 2026) */
@media (prefers-reduced-motion:reduce){
  .door:hover,.jcard:hover{transform:none}
  .door:hover img,.jcard:hover img{scale:none}
  .door:hover h3 a::after{translate:none}
}
/* review and photo rails on desktop: previous and next buttons (site.js), so cards past the third aren't hidden
   behind a scrollbar that isn't shown (principles CD-55, 10 Nov 2026). Phones keep the swipe, with the next card
   peeking in. */
.railnav{display:none}
@media (min-width:880px){
  .railnav{display:flex;justify-content:flex-end;gap:.5rem;margin-top:var(--s3)}
  .railnav[hidden]{display:none}
}
.railnav button{width:2.75rem;height:2.75rem;border-radius:50%;border:1px solid var(--line);background:#fff;color:var(--ink);font:600 1.5rem/1 var(--body);cursor:pointer;display:grid;place-items:center;padding:0}
.railnav button:disabled{opacity:.35;cursor:default}
@media (hover:hover){.railnav button:hover:not(:disabled){border-color:var(--ink)}}
/* Accent buttons on light sections take the dark colour (Evan, 10 Nov 2026, D10): most accents are only 1.4 to 3.6:1
   on white (principles VD-11/12). Dark panels inside a light section (the services call-to-action card) keep the accent. */
.sec .b-acc:not(:is(.dark,.dcta,.hero,.bar) .b-acc){background:var(--dark);color:#fff}
@media (hover:hover){
  .sec .b-acc:not(:is(.dark,.dcta,.hero,.bar) .b-acc):hover{background:color-mix(in srgb,var(--dark) 78%,#fff)}
}
/* review dates (D6; principles CD-19): month and year, only when reliable (build.review_date) */
.rv figcaption time{flex-basis:100%;font-size:.875rem}
@keyframes rise{from{opacity:0;translate:0 14px}}
@keyframes settle{from{scale:1.06}}
/* The hero's text and buttons are simply there when the page appears (Evan, 10 Nov 2026, D2): animating the headline
   and Call slows people down (NN/g; principles VD-26). The photo still settles; cards still fade up on scroll. */
.motion .hero-media img{animation:settle 1.4s cubic-bezier(.2,.7,.2,1) both}
/* scroll reveal: site.js adds .rv-in (so nothing hides without JS) and .seen once it's on screen */
.motion .rv-in{opacity:0;translate:0 18px;transition:opacity .6s ease var(--d,0s),translate .6s cubic-bezier(.2,.7,.2,1) var(--d,0s),transform .2s ease,box-shadow .2s ease,border-color .2s ease}
.motion .rv-in.seen{opacity:1;translate:none}
/* keyboard: a card that takes focus before it has faded in shows at once, so focus is never on something invisible (WCAG 2.4.7) */
.motion .rv-in:focus-within{opacity:1;translate:none;transition:none}
/* why-us bullets pop in after their card; process steps light up one by one as you scroll, like Harry's mower */
.motion .why li::before{transition:scale .45s cubic-bezier(.3,1.6,.5,1) calc(var(--d,0s) + .25s)}
.motion .why li.rv-in:not(.seen)::before{scale:0}
.motion .steps li::before{transition:filter .4s ease,opacity .4s ease,scale .45s cubic-bezier(.3,1.6,.5,1);transition-delay:calc(var(--d,0s) + .15s)}
.motion .steps li.rv-in:not(.on)::before{filter:grayscale(1);opacity:.45;scale:.85}

/* Job types (README "Job types", 10 Nov 2026). Added to site.css straight after base.css, only for a client that uses a
   job type or one of these sections (build.uses_job_types), so the other sites stay byte for byte as they were. */

/* the hero's proof line (job type `proof`): the real hours, how often, or the page's own hero_line, under the headline */
.hrs,.often,.pline{display:flex;align-items:center;gap:var(--s2);margin-top:var(--s3);font-weight:700;line-height:1.35;color:#fff;text-wrap:balance}
.hrs::before,.pline::before{content:"";flex:none;width:.625rem;height:.625rem;border-radius:50%;background:var(--accent);
  box-shadow:0 0 0 4px color-mix(in srgb,var(--accent) 30%,transparent)}
.often::before{content:"\21bb";flex:none;font-size:1.125rem;line-height:1;color:var(--accent)}
@media (max-width:559px){.btns.one{grid-template-columns:1fr}}  /* Call alone: full width on phones only */

/* `short_hero`: a shorter hero photo on phones, so the proof line and Call sit well above the call bar */
@media (max-width:879px){
  .hero.svc.short:not(.noimg){min-height:min(calc(100svh - 3.75rem - 4.25rem),32rem)}
  .hero.svc.short:not(.noimg) .hero-text{padding-top:6rem;--hero-top:6rem}
}

/* what to do right now (urgent pages: general safety steps) */
.rnow{display:grid;gap:var(--s4);margin-top:var(--s5);counter-reset:r}
.rnow li{position:relative;padding-left:3.25rem;min-height:2.25rem;counter-increment:r;line-height:1.45}
.rnow li::before{content:counter(r);position:absolute;left:0;top:0;width:2.25rem;height:2.25rem;border-radius:50%;
  background:var(--dark);color:#fff;display:grid;place-items:center;font:800 1rem var(--head)}
.rnow b{display:block;font:800 1.125rem/1.2 var(--head);color:var(--dark)}
.rnow span{display:block;margin-top:var(--s1)}
#right-now .cta2{margin-top:var(--s5)}

/* contact "call_first": the block leads with Call; the form is the "Not urgent?" route */
.qwrap.callfirst .door-no{margin-top:var(--s4)}
.qwrap .txt{margin-top:var(--s3);color:var(--on-dark)}
.qwrap .txt a{color:#fff;font-weight:700;white-space:nowrap}
.nurg{margin-bottom:var(--s4);color:var(--on-dark);font-size:1.0625rem}
.nurg b{color:#fff}

/* build: related projects (1 to 3 of this service's jobs) */
#projects .tlink{margin-top:var(--s4)}
@media (min-width:560px){
  .pjs.n1{grid-template-columns:1fr}
}
@media (min-width:880px){
  .pjs.n2{grid-template-columns:repeat(2,minmax(0,1fr))}
  .pjs.n1 .jcard{display:grid;grid-template-columns:minmax(0,1.3fr) minmax(0,1fr);align-items:center}
  .pjs.n1 .jcard img{height:100%;aspect-ratio:auto;min-height:20rem}
  .pjs.n1 figcaption{padding:var(--s6)}
  .pjs.n1 .jcard.proj span{-webkit-line-clamp:6}
  #price .ilist{grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--s4) var(--s7)}
  .rnow{grid-template-columns:repeat(2,minmax(0,1fr));gap:var(--s5) var(--s7)}
}

/* Motif: SPLITGABLE (Coast Roof Tiling). The house in their logo is two nested outlines, each split down the ridge:
   left half blue, right half black. On the dark site the black half is white, as in the logo made for the header.
   The motif is the split, not a roof shape:
   - edge: a straight line, blue on the left and white on the right, rising to one small ridge where they meet
   - hero: their roof photo first on phones with the same two-tone bar along its foot; full bleed from 880 px
   - bullets: the split ridge; why points: the logo's two nested ridges, split the same way
   - steps: numbers in a square with a two-tone border; Dave's photo in a two-tone frame with the ridge on top
   Type: Unbounded for headings, a wide rounded face close to the logo's extended lettering; Manrope for text. */
:root{--r:.25rem;--btn-r:.25rem;--sgb:var(--dark);--sga:var(--accent-ink)}
.dark,.sec.dark,.hero{--sgb:#fff;--sga:var(--accent)}

/* edge: grid of left line, ridge, right line. Sizes are in em so the ridge keeps its pitch at every width.
   The fill (the next section's colour) runs 1px past the foot so no seam shows at fractional scaling. */
.e-splitgable{display:grid;grid-template-columns:1fr 5em 1fr;width:100%;height:2.75em;font-size:16px;margin-bottom:-1px}
.e-splitgable .sgl,.e-splitgable .sgr{display:block;--c:var(--accent);
  background:linear-gradient(transparent 1.375em,var(--c) 1.375em 1.625em,transparent 1.625em 2.0625em,var(--to,#fff) 2.0625em)}
.e-splitgable .sgr{--c:#fff}
.e-splitgable .sgpk{display:block;width:5em;height:2.75em;overflow:visible}
.e-splitgable .f{fill:var(--to,#fff)}
.e-splitgable .a{fill:var(--accent)}
.e-splitgable .b{fill:#fff}
.hero .e-splitgable{position:relative;z-index:3}
/* the hero's dark ends under the edge's fill, so its fractional last row can't show as a seam at 125% */
.hero.dark{background:linear-gradient(var(--dark) calc(100% - 1rem),transparent calc(100% - 1rem))}

/* type */
.slogan{font-weight:700;letter-spacing:-.015em;line-height:1.04}
.slogan em,.sec h2 em,.hero h1 em,.score-h em,.qwrap h2 em{font-style:normal}
.sec h2,.hero.svc h1,.hero.plain h1{font-weight:600;letter-spacing:-.015em;line-height:1.12}
.why b,.door h3,.jcard b,.steps b{font-weight:600;letter-spacing:-.01em}
.btn{font-weight:800;letter-spacing:0;white-space:nowrap}
.sec h2,.incl h2{text-wrap:balance}
.gbadge,.chips li{border-radius:.25rem}
.rv,.door,.jcard,.faq details,.map,.sc-item{border-radius:.25rem}

/* bullets: the split ridge */
.ilist li::before{top:.42rem;width:1.05rem;height:.66rem;border-radius:0;transform:none;
  background:linear-gradient(90deg,var(--sga) 50%,var(--sgb) 50%);
  clip-path:polygon(0 100%,50% 0,100% 100%,77% 100%,50% 40%,23% 100%)}
/* why points: the logo's two nested ridges, split down the middle */
.why li{border-radius:.25rem;border-top:3px solid;border-image:linear-gradient(90deg,var(--accent-ink) 50%,var(--dark) 50%) 1}
.why li::before{top:1.5rem;width:2rem;height:1.625rem;border-radius:0;transform:none;
  background:linear-gradient(90deg,var(--accent-ink) 50%,var(--dark) 50%);
  clip-path:path("M0 17L16 1L32 17L27 17L16 6L5 17Z M7 26L16 16.5L25 26L20.5 26L16 21L11.5 26Z")}
/* step numbers: a square with a two-tone border, blue on the left and white on the right */
.steps li::before{border-radius:0;border:3px solid transparent;color:#fff;font:600 1.125rem var(--head);
  background:linear-gradient(var(--dark-2),var(--dark-2)) padding-box,linear-gradient(90deg,var(--accent) 50%,#fff 50%) border-box}

/* hero: their roof first on phones, with the two-tone bar along the photo's foot */
.sgbar{position:absolute;left:0;right:0;bottom:0;height:5px;z-index:2;background:linear-gradient(90deg,var(--accent) 50%,#fff 50%)}
@media (max-width:879px){
  .hero.home,.hero.svc:not(.noimg){display:block;min-height:0}
  .hero-media{position:relative;inset:auto}
  .hero-media::after{background:linear-gradient(180deg,transparent 72%,color-mix(in srgb,var(--dark) 45%,transparent) 100%)}
  .hero-media img{display:block;aspect-ratio:16/10;height:auto;max-height:34svh}
  .hero.home .hero-text,.hero.svc:not(.noimg) .hero-text{padding-top:var(--s4)}
  .slogan{font-size:clamp(1.875rem,9.2vw,2.75rem)}
  .hero.svc h1{font-size:clamp(1.625rem,7.4vw,2.5rem)}
  .hero.plain h1{font-size:clamp(1.75rem,8vw,2.75rem)}
  .sec h2{font-size:clamp(1.5rem,6.6vw,2rem)}
}

/* Dave in a two-tone frame: blue down the left, white down the right, and the split ridge above */
.sgframe{position:relative;max-width:22rem;margin:2.25rem auto 0;padding:.6rem}
.sgframe::before{content:"";position:absolute;inset:0;border:4px solid transparent;pointer-events:none;
  background:linear-gradient(90deg,var(--accent) 50%,var(--sgb) 50%) border-box;
  -webkit-mask:linear-gradient(#000 0 0) padding-box,linear-gradient(#000 0 0);-webkit-mask-composite:xor;mask-composite:exclude}
/* Unbounded is wide: the big phone numbers need a smaller size to fit a 375 screen */
.door-no a{font-size:clamp(1.75rem,8.4vw,3.5rem)}
.cbig{font-size:clamp(1.625rem,7.8vw,2.75rem)}
.sgframe img,.sgframe .ownph,.meet .sgframe img,.meet .sgframe .ownph{position:relative;display:block;width:100%;aspect-ratio:4/5;height:auto;object-fit:cover;object-position:50% 22%;border:0;border-radius:0;transform:none;box-shadow:0 14px 30px rgba(0,0,0,.35)}
.sgtop{position:absolute;left:50%;top:-1.55rem;width:5rem;height:1.625rem;transform:translateX(-50%)}
.sgtop path{fill:none;stroke-width:4;stroke-linecap:butt}
.sgtop .a{stroke:var(--accent)}
.sgtop .b{stroke:var(--sgb)}

@media (min-width:880px){
  .e-splitgable{font-size:20px;grid-template-columns:1fr 5em 3fr}
  .sgbar{display:none}
  /* the full-bleed photo stops inside the edge's fill, so no hairline shows at 125% */
  .hero-media{bottom:.4rem}
  .slogan{font-size:clamp(2.5rem,min(4.2vw,8vh),4rem)}
  .sec h2{font-size:clamp(2rem,3.1vw,3rem)}
  .hero.svc h1{font-size:clamp(2.25rem,3.6vw,3.25rem)}
  .sgframe{margin:2.25rem 0 0}
}

:root{--dark:#141d26;--dark-2:#1d2833;--dark-3:#0e151c;--accent:#0a9ad0;--accent-ink:#00719c;--mist:#eef3f6;--line:#d3dde4;--head:'Unbounded', 'Arial Black', sans-serif;--body:'Manrope', system-ui, sans-serif}
