/* 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, and
   they keep the shared height they had (site.js sets --rv-h on open; Evan, 11 Nov 2026: letting them drop back to
   their own height made the cards around it shrink, which looked broken). */
.rail:has(.rv.open){align-items:start}
.rail:has(.rv.open) .rv:not(.open){height:var(--rv-h,auto)}
.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)}
/* tiles in a row are one height: the span fills the grid cell, so a two-line tile beside a three-line one doesn't sit
   short (Evan, 11 Nov 2026, on MASH: "form looking bit weird when one field has more text") */
.tile{position:relative;display:flex;cursor:pointer}
.tile span{flex:1}
.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}
/* also any narrower window with a mouse (11 Nov 2026 audit: from 600 to 879 px a mouse user had no buttons and no
   scrollbar, so cards past the second couldn't be reached) */
@media (min-width:880px), (hover:hover) and (pointer:fine){
  .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). They sit on the stars
   line, so the name line is level on every card (11 Nov 2026 audit) */
.rv .rtop{display:flex;align-items:baseline;justify-content:space-between;gap:var(--s2)}
.rv .rtop time{font-size:.875rem;line-height:1;color:var(--muted);white-space:nowrap}
/* "Read all N reviews" under a rail: the Reviews page and the listing (11 Nov 2026 audit). site.js puts it on one
   row with the previous and next buttons (.railfoot), links left and buttons right */
.rv-all{display:flex;flex-wrap:wrap;gap:0 var(--s4);margin-top:var(--s3)}
.railfoot{display:flex;flex-wrap:wrap;align-items:center;justify-content:space-between;gap:var(--s2) var(--s4);margin-top:var(--s3)}
.railfoot>.rv-all,.railfoot>.railnav{margin-top:0}
.railfoot>.railnav{margin-left:auto}
/* text for screen readers only */
.vh{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}
@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}

/* Motif: ISO (Pure Design Constructions). Their mark is a ribbon in isometric projection: flat faces in two tones of
   silver, light and shaded, folding at crisp 30 degree angles (site logo, embroidered polo, ute livery). Black, silver
   and their copper are the brand's own colours (the copper is their site's button colour).
   Edge: a straight join with a faceted trim along it, a row of low two-tone facets, light face left and shaded face
   right, as the top fold of the mark is. Bullets: the mark's centre fold as a two-tone chevron. Why points: the mark.
   Step numbers: on a two-tone isometric tile. Owner: the photo in an offset silver frame with the mark on the corner.
   Type: Montserrat and Poppins, as on their site. */
:root{
  --r:.15rem;--btn-r:.15rem;
  --iso-l:#e4e4e6;--iso-s:#b9b6bb;
  --iso-trim:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 48 10' preserveAspectRatio='none'%3E%3Cpath fill='%23e4e4e6' d='M0 10L24 0V10Z'/%3E%3Cpath fill='%23b9b6bb' d='M24 0L48 10H24Z'/%3E%3C/svg%3E");
  --iso-chev:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 24'%3E%3Cpath fill='%23e4e4e6' d='M0 0L20 12V24L0 12Z'/%3E%3Cpath fill='%23b9b6bb' d='M0 12L10 18L0 24Z'/%3E%3C/svg%3E");
  --iso-chev-ink:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 20 24'%3E%3Cpath fill='%23383c40' d='M0 0L20 12V24L0 12Z'/%3E%3Cpath fill='%23926231' d='M0 12L10 18L0 24Z'/%3E%3C/svg%3E");
}
#isoMk .l{fill:var(--iso-l)}
#isoMk .s{fill:var(--iso-s)}

/* edge: a straight join with the faceted trim standing on it. The bottom 2px are the next section's colour and the
   edge overlaps it by 2px, so no seam shows at fractional scaling */
.e-iso{display:block;height:.8rem;margin-bottom:-2px;
  background:linear-gradient(var(--to,#fff),var(--to,#fff)) 0 100%/100% 3px no-repeat,
             var(--iso-trim) 0 0/2.6rem 100% repeat-x}
.hero .e-iso{position:relative}

/* type: their site's Montserrat, set tight */
.sec h2,.hero.svc h1,.hero.plain h1{letter-spacing:-.02em}
.slogan{letter-spacing:-.03em}
.btn{letter-spacing:.01em}

/* bullets: the mark's centre fold, a two-tone chevron */
.ilist li::before{top:.3rem;width:.7rem;height:.85rem;border-radius:0;background:var(--iso-chev-ink) center/contain no-repeat}
.dark .ilist li::before{background-image:var(--iso-chev)}
/* why points: quiet cards with the chevron, and a silver top line */
.why li{border-radius:var(--r);border-top:2px solid var(--iso-s)}
.why li::before{top:1.5rem;width:1rem;height:1.2rem;border-radius:0;background:var(--iso-chev-ink) center/contain no-repeat}
.dark .why li::before{background-image:var(--iso-chev)}

/* process: the number on a two-tone isometric tile, light face over a shaded fold */
.steps li::before{border-radius:0;color:var(--dark);font-weight:700;
  background:linear-gradient(150deg,var(--iso-l) 0 58%,var(--iso-s) 58%);
  clip-path:polygon(50% 0,100% 25%,100% 75%,50% 100%,0 75%,0 25%)}
section:not(.dark) .steps li::before{color:#fff;background:linear-gradient(150deg,var(--dark) 0 58%,var(--dark-2) 58%)}

/* credentials are facts, not links: white, so the copper stays on things to tap */
.creds{color:#fff}
/* cards: crisp corners like the mark */
.rv,.door,.jcard,.faq details,.map,.sc-item,.chips li,.gbadge{border-radius:var(--r)}
.door img,.jcard img,.prail img,.incl img,.map{border-radius:var(--r)}

/* owner: the photo in a silver frame offset behind it, the mark on the corner */
.isofr{position:relative;max-width:30rem;margin:var(--s3) auto var(--s5);padding:0 .9rem .9rem 0}
.isofr::before{content:"";position:absolute;inset:.9rem 0 0 .9rem;border:2px solid var(--iso-s);pointer-events:none}
.isofr img,.isofr .ownph{position:relative;display:block;width:100%;aspect-ratio:3/2;height:auto;object-fit:cover;border:0;border-radius:0;transform:none;box-shadow:0 14px 30px rgba(0,0,0,.4)}
.isocorner{position:absolute;right:-.4rem;bottom:-.4rem;width:2rem;height:2.6rem;padding:.35rem .45rem;box-sizing:content-box;background:var(--dark)}

/* phones: photo first, so the build reads clearly before the headline */
@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 70%,color-mix(in srgb,var(--dark) 60%,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)}
  .hero.home .slogan{font-size:clamp(2rem,10vw,3rem)}
}
@media (min-width:880px){
  .e-iso{height:1rem;background-size:100% 3px,3.4rem 100%}
  /* the full-bleed photo stops above the trim so the facets stand on the dark, not on the photo */
  .hero-media{bottom:.9rem}
  /* their builds are mostly white weatherboard and pale boards, so the scrim holds further across behind the text */
  .hero-media::after{background:linear-gradient(90deg,var(--dark) 0%,color-mix(in srgb,var(--dark) 88%,transparent) 40%,color-mix(in srgb,var(--dark) 45%,transparent) 62%,transparent 88%)}
  .slogan{font-size:clamp(2.6rem,min(4.4vw,8vh),4.4rem)}
  .isofr{margin-inline:0 auto;max-width:28rem}
}

:root{--dark:#17191b;--dark-2:#25282b;--dark-3:#0e0f10;--accent:#CA924A;--accent-ink:#8a5a22;--mist:#f3f2ef;--line:#dedad3;--head:Montserrat,Arial,sans-serif;--body:Poppins,Arial,sans-serif}
