/* ============================================================
   CONSTRUCTION / GENERAL TRADES template
   Design: IRON NIGHT / HI-VIS. Cold steel darks, safety yellow,
   Anton + Barlow + JetBrains Mono. Dark-dominant, ticket cards,
   split hero. Deliberately NOT the Flores skin.
   ============================================================ */
:root{
  --coal:#0e1116;
  --coal-2:#141922;
  --panel:#1a212c;
  --panel-2:#202834;
  --white:#f2f5f7;
  --mut:#a8b2bc;
  --mut-2:#7f8a95;
  --accent:#0891b2;
  --accent-dark:#06718b;
  /* text-safe accent (2026-09-27): eyebrows, labels, outline text + outline-button borders use this;
     build_draft.js swapBrandColors() sets it to the brand colour lightened (dark theme) or darkened
     (light theme) until it reads at >= 4.5:1 on the section backgrounds. Fills and bars keep --accent. */
  --accent-text:#16a1c3;
  --accent-dim:color-mix(in srgb, var(--accent) 14%, transparent);
  --on-accent:#0e1116;
  --line:rgba(242,245,247,.13);
  --line-light:rgba(242,245,247,.13);
  --font-display:"Anton",sans-serif;
  --font-body:"Barlow",sans-serif;
  --font-mono:"JetBrains Mono",monospace;
  --max:1220px;
  --rad:0px;
  /* legacy aliases used by inline styles on inner pages */
  --ink:var(--coal);
  --ink-2:var(--coal-2);
  --paper:var(--panel);
  --paper-2:var(--panel);
  --bone:var(--panel);
  --bone-2:var(--coal-2);
  --red:var(--accent);
  --red-dark:var(--accent-dark);
  --steel:var(--mut-2);
}
*{margin:0;padding:0;box-sizing:border-box}
html{scroll-behavior:smooth}
html,body{overflow-x:clip}
body{
  font-family:var(--font-body);
  background:var(--coal);
  color:var(--white);
  font-size:16.5px;
  line-height:1.65;
  -webkit-font-smoothing:antialiased;
}
img{max-width:100%;display:block}
a{color:inherit;text-decoration:none}
ul{list-style:none}
::selection{background:var(--accent);color:var(--on-accent)}

/* ---------- type ---------- */
h1,h2,h3,h4{font-family:var(--font-display);font-weight:400;line-height:.95;letter-spacing:.015em;text-transform:uppercase}
.display-xl{font-size:clamp(3rem,8.4vw,7.2rem)}
.display-lg{font-size:clamp(2.3rem,5.2vw,4.4rem)}
.display-md{font-size:clamp(1.7rem,3.4vw,2.7rem)}
.display-sm{font-size:clamp(1.2rem,2.1vw,1.6rem)}
.kicker{
  font-family:var(--font-mono);font-size:.875rem;font-weight:500;
  letter-spacing:.26em;text-transform:uppercase;color:var(--accent-text);
  display:flex;align-items:center;gap:.65rem;margin-bottom:1.15rem;
}
.kicker::before{content:"//";font-weight:700;letter-spacing:0}
.kicker.center{justify-content:center}
.lead{font-size:clamp(1.03rem,1.4vw,1.22rem);color:var(--mut);max-width:58ch;font-weight:400}
.muted{color:var(--mut-2)}
.on-dark .lead,.on-dark .muted,.dark .lead,.dark .muted,.dark2 .lead,.dark2 .muted{color:var(--mut)}
.outline{color:transparent;-webkit-text-stroke:1.6px var(--accent-text)}
.acc,.red{color:var(--accent-text);-webkit-text-stroke:0}
.statement{font-family:var(--font-display);text-transform:uppercase;font-size:clamp(2rem,4.8vw,3.9rem);line-height:.96;max-width:20ch}
.statement em{font-style:normal;color:var(--accent-text)}

/* ---------- layout ---------- */
.wrap{max-width:var(--max);margin:0 auto;padding:0 clamp(1.1rem,4vw,2.6rem)}
.section{padding:clamp(4.2rem,8vw,7.5rem) 0;position:relative}
.section.tight{padding:clamp(2.6rem,5vw,4.2rem) 0}
.dark{background:var(--coal-2);border-top:1px solid var(--line);border-bottom:1px solid var(--line)}
.dark2{background:var(--panel)}
.grid-2{display:grid;grid-template-columns:1fr 1fr;gap:clamp(2rem,5vw,4.5rem);align-items:center}
.grid-2>*,.grid-3>*,.grid-4>*{min-width:0}
.grid-3{display:grid;grid-template-columns:repeat(3,1fr);gap:1.4rem}
.grid-4{display:grid;grid-template-columns:repeat(4,1fr);gap:1.4rem}
@media(max-width:940px){.grid-2{grid-template-columns:1fr}.grid-3{grid-template-columns:1fr 1fr}.grid-4{grid-template-columns:1fr 1fr}}
@media(max-width:560px){.grid-3,.grid-4{grid-template-columns:1fr}}

/* ---------- hazard / rules ---------- */
.hazard{height:14px;background:var(--accent);background-image:repeating-linear-gradient(135deg,var(--hazard-ink,#0a0d11) 0 14px,rgba(0,0,0,0) 14px,rgba(0,0,0,0) 28px)}
/* When the page's last section before the footer is itself a .cta-band (the common case --
   every page ends on a CTA), the footer's own .hazard stripe lands right under the
   cta-band's giant background text with almost no gap, reading as two stripes sandwiching
   a half-cut-off watermark instead of one clean transition (Wayne, live screenshot on
   Sarber Construction and Eco Lawn Pros, 2026-08-10). The cta-band's own accent-color
   block already IS the transition; a second stripe right after it is redundant. Use ~
   (general sibling) not + (adjacent) since <script src="site.js"> sits between them in the DOM. */
.cta-band ~ footer .hazard{display:none}
.rule{height:1px;background:var(--line)}

/* ---------- buttons ---------- */
.btn{
  display:inline-flex;align-items:center;justify-content:center;gap:.6rem;
  font-family:var(--font-body);font-weight:700;font-size:.95rem;
  letter-spacing:.06em;text-transform:uppercase;
  padding:1.02rem 1.75rem;border:2px solid transparent;border-radius:0;
  cursor:pointer;transition:transform .18s ease,background .18s ease,color .18s ease,border-color .18s ease,box-shadow .18s ease;
  position:relative;
}
.btn:active{transform:translateY(1px)}
.btn-solid,.btn-red{background:var(--accent);border-color:var(--accent);color:var(--on-accent)}
.btn-solid:hover,.btn-red:hover{background:var(--white);border-color:var(--white);color:var(--coal);box-shadow:0 8px 30px color-mix(in srgb, var(--accent) 18%, transparent)}
.btn-ink{background:transparent;border-color:var(--accent-text);color:var(--accent-text)}
.btn-ink:hover{background:var(--accent);color:var(--on-accent)}
.btn-ghost{border-color:var(--line);color:var(--white);background:transparent}
.btn-ghost:hover{border-color:var(--white);background:var(--white);color:var(--coal)}
.btn-ghost-light,.btn-light{border-color:rgba(242,245,247,.45);color:var(--white);background:transparent}
.btn-ghost-light:hover,.btn-light:hover{background:var(--white);border-color:var(--white);color:var(--coal)}
.btn-lightsolid{background:var(--white);border-color:var(--white);color:var(--coal)}
.btn-lightsolid:hover{background:var(--accent);border-color:var(--accent);color:var(--on-accent)}
.btn .arr{transition:transform .18s ease}
.btn:hover .arr{transform:translateX(4px)}

/* ---------- topbar ---------- */
.topbar{background:var(--accent);color:var(--on-accent);font-family:var(--font-mono);font-size:.875rem;font-weight:800;letter-spacing:.07em;text-transform:uppercase}
.topbar .wrap{display:flex;justify-content:space-between;align-items:center;min-height:38px;gap:1.5rem}.topbar .area{min-width:0;overflow:hidden;text-overflow:ellipsis;white-space:nowrap}.topbar a{flex:0 0 auto;white-space:nowrap}
.topbar a{color:var(--on-accent);font-weight:800}
.topbar a:hover{text-decoration:underline}
@media(max-width:720px){.topbar .area{display:none}.topbar .wrap{justify-content:center}}

/* ---------- header ---------- */
.site-header{
  position:sticky;top:0;z-index:80;background:rgba(14,17,22,.9);
  backdrop-filter:blur(12px);border-bottom:1px solid var(--line);
  transition:box-shadow .25s ease,background .25s ease;
}
.site-header.scrolled{box-shadow:0 10px 34px rgba(0,0,0,.5);background:rgba(14,17,22,.97)}
.site-header .wrap{display:flex;align-items:center;justify-content:space-between;gap:2rem;height:112px}
.logo{display:flex;align-items:center;gap:.7rem;flex:none}
.logo img{width:100%;height:auto;max-height:84px;max-width:300px;min-width:0;display:block;object-fit:contain}
/* dark logo on the dark nav -> white chip so it reads; light/white logos show bare */
/* 2026-09-26 (Southeastern Demo And Construction): site_qc.js flags any logo-chip under 80px as too small to read in the nav -- 66px was the shipped default on both master templates. Raised to 90px + grown the header row (92px -> 112px) to match, per the tool's own "raise to ~92-118px and grow the header bar" guidance. */
.logo img.logo-chip{background:#fff;border-radius:8px;padding:9px 13px;height:90px;box-shadow:0 2px 10px rgba(0,0,0,.18)}
.site-footer .logo img{height:100px}
.site-footer .logo img.logo-chip{height:84px}
/* wordmark logo (greenfield / no real logo image) */
.site-header .logo{margin-right:2.5rem;flex:0 1 auto;min-width:0}
.site-header .header-cta{margin-left:2.5rem;flex:0 0 auto}
.logo-word{font-family:var(--font-display);max-width:min(28vw,340px);white-space:nowrap;overflow:hidden;text-overflow:ellipsis;flex:0 1 auto;text-transform:uppercase;letter-spacing:.02em;line-height:.9;font-size:clamp(1.3rem,2.1vw,1.9rem);color:var(--white);display:inline-block;position:relative;padding-left:1rem}
.logo-word::before{content:"";position:absolute;left:0;top:50%;transform:translateY(-50%);width:4px;height:1.5em;background:var(--accent)}
.site-footer .logo-word{font-size:1.7rem;max-width:min(70vw,520px)}
@media(max-width:560px){.logo-word{font-size:1.3rem}.site-footer .logo-word{font-size:1.3rem;max-width:calc(100vw - 40px)}}
/* 2026-09-26 (Southeastern Demo And Construction): .logo img.logo-chip (specificity 0,0,2,1, defined outside any media query) beats this plain .logo img{height:54px} mobile override (specificity 0,0,1,1) regardless of source order -- so a dark logo using the white-chip treatment NEVER actually shrunk on mobile. Invisible at the old 66px chip height (fit inside the 78px mobile header by luck); became real visible clipping once the chip was raised to 90px for the logo-small desktop fix. Target .logo-chip directly here so it actually wins on mobile too. */
@media(max-width:560px){.logo img{height:54px}.logo img.logo-chip{height:48px;padding:6px 9px}.site-header .wrap{height:78px}}
.nav{display:flex;align-items:center;gap:1.45rem}
.nav>a{font-weight:600;font-size:.875rem;letter-spacing:.06em;text-transform:uppercase;padding:.4rem 0;position:relative;white-space:nowrap;color:#dfe5ea}
.nav>a::after{content:"";position:absolute;left:0;bottom:0;width:0;height:2px;background:var(--accent);transition:width .22s ease}
.nav>a:hover,.nav>a.active{color:var(--white)}
.nav>a:hover::after,.nav>a.active::after{width:100%}
.nav .has-drop{position:relative}
.nav .has-drop>a{display:inline-flex;align-items:center;gap:.35rem;font-weight:600;font-size:.875rem;letter-spacing:.06em;text-transform:uppercase;padding:.4rem 0;color:#dfe5ea;white-space:nowrap}
.nav .has-drop>a:hover,.nav .has-drop>a.active{color:var(--white)}
.drop{
  position:absolute;top:calc(100% + 16px);left:50%;transform:translate(-50%,8px);
  background:var(--panel);min-width:255px;padding:.55rem 0;border:1px solid var(--line);
  opacity:0;visibility:hidden;transition:all .22s ease;box-shadow:0 22px 50px rgba(0,0,0,.55);
}
.drop::before{content:"";position:absolute;top:0;left:0;right:0;height:3px;background:var(--accent)}
.has-drop:hover .drop,.has-drop:focus-within .drop{opacity:1;visibility:visible;transform:translate(-50%,0)}
.drop a{display:block;color:var(--white);padding:.55rem 1.2rem;font-size:.875rem;font-weight:600;letter-spacing:.03em}
.drop a:hover{background:var(--accent);color:var(--on-accent)}
.header-cta{display:flex;align-items:center;gap:2rem;flex:none}
.header-phone{font-family:var(--font-mono);font-weight:600;font-size:.875rem;white-space:nowrap;color:var(--white)}
.header-phone:hover{color:var(--accent-text)}
.btn-nav{padding:.72rem 1.25rem;font-size:.875rem}
.burger{display:none;background:none;border:0;cursor:pointer;width:44px;height:44px;position:relative;z-index:120}
.burger span{display:block;width:26px;height:3px;background:var(--white);margin:5px auto;transition:all .25s ease}
.burger.open span:nth-child(1){transform:translateY(8px) rotate(45deg)}
.burger.open span:nth-child(2){opacity:0}
.burger.open span:nth-child(3){transform:translateY(-8px) rotate(-45deg)}
@media(max-width:1120px){
  .nav,.header-phone{display:none}
  .burger{display:block}
}
@media(max-width:560px){.btn-nav{display:none}}

/* mobile menu */
/* justify-content:center (fixed here 2026-09-17, found live on Sunlife Pools) pushed
   content above y=0 -- unreachable -- and the CTA buttons far below the fold whenever
   services + service areas overflow the viewport, which is any business with a real
   number of services/towns. flex-start keeps it anchored top and properly scrollable.
   This shipped on every site built from this template until now, not a one-off. */
.mobile-menu{
  position:fixed;inset:0;background:var(--coal);z-index:110;color:var(--white);
  display:flex;flex-direction:column;justify-content:flex-start;padding:5rem clamp(1.4rem,7vw,3.5rem) 3rem;
  opacity:0;visibility:hidden;transition:opacity .28s ease;overflow-y:auto;
}
.mobile-menu::before{content:"";position:fixed;top:0;left:0;right:0;height:6px;background:repeating-linear-gradient(135deg,var(--accent) 0 14px,var(--coal) 14px 28px)}
.mobile-menu.open{opacity:1;visibility:visible}
.mobile-menu a.mm-link{
  font-family:var(--font-display);font-size:clamp(1.8rem,7vw,2.7rem);text-transform:uppercase;
  padding:.35rem 0;border-bottom:1px solid var(--line);display:block;
  transform:translateY(14px);opacity:0;transition:all .3s ease;
}
.mobile-menu.open a.mm-link{transform:none;opacity:1}
.mobile-menu a.mm-link:hover{color:var(--accent-text)}
.mobile-menu .mm-sub{font-family:var(--font-mono);font-size:.875rem;letter-spacing:.18em;text-transform:uppercase;color:var(--accent-text);margin:1.6rem 0 .5rem}
.mobile-menu .mm-svc a{display:block;padding:.3rem 0;font-weight:600;color:var(--mut)}
.mobile-menu .mm-svc a:hover{color:var(--accent-text)}
.mobile-menu .mm-cta{margin-top:2rem;display:flex;flex-wrap:wrap;gap:1rem}

/* ---------- HOME split hero ---------- */
.hero-split{position:relative;border-bottom:1px solid var(--line);overflow:clip}
.hero-split .hs-grid{display:grid;grid-template-columns:minmax(0,1.05fr) minmax(0,.95fr);min-height:min(86vh,780px)}
.hs-copy{display:flex;flex-direction:column;justify-content:center;padding:clamp(2.6rem,5vw,4rem) clamp(1.1rem,4vw,3.4rem) clamp(2.6rem,5vw,4rem) max(clamp(1.1rem,4vw,2.6rem),calc((100vw - var(--max))/2 + 2.6rem));position:relative}
.hs-copy::before{content:"42.02 N / 93.65 W";position:absolute;top:2rem;right:0;writing-mode:vertical-rl;font-family:var(--font-mono);font-size:.875rem;letter-spacing:.34em;color:var(--mut-2);text-transform:uppercase}
.hs-tag{font-family:var(--font-mono);font-size:.875rem;letter-spacing:.24em;text-transform:uppercase;color:var(--accent-text);margin-bottom:1.1rem;display:flex;gap:.65rem;align-items:center}
.hs-tag::before{content:"//";font-weight:700;letter-spacing:0}
.hs-copy h1{font-size:clamp(3.2rem,6.8vw,6.2rem);max-width:11ch;line-height:.94}
.hs-copy h1 .acc{color:var(--accent-text)}
.hs-copy::after{content:"AIRBORNE";position:absolute;left:-.04em;bottom:-.14em;font-family:var(--font-display);font-size:clamp(6rem,16vw,14rem);line-height:1;color:transparent;-webkit-text-stroke:1px rgba(255,255,255,.05);pointer-events:none;user-select:none;white-space:nowrap;z-index:0}
.hs-copy>*{position:relative;z-index:1}
.hl{display:block;overflow:hidden;padding-bottom:.42em;margin-bottom:-.34em}
.hl-in{display:inline-block;transform:translateY(112%);animation:heroLine .95s cubic-bezier(.19,.8,.22,1) .08s forwards}
.hl:nth-child(2) .hl-in{animation-delay:.2s}
.hl:nth-child(3) .hl-in{animation-delay:.32s}
@keyframes heroLine{to{transform:none}}
.hload{opacity:0;transform:translateY(20px);animation:heroFade .9s cubic-bezier(.2,.6,.2,1) .18s forwards}
.hload-d2{animation-delay:.52s}.hload-d3{animation-delay:.7s}.hload-d4{animation-delay:.88s}
@keyframes heroFade{to{opacity:1;transform:none}}
.hs-copy p{margin:1.4rem 0 1.9rem;max-width:50ch;font-size:clamp(1.02rem,1.4vw,1.16rem);color:var(--mut)}
.btn-hero{padding:1.05rem 1.7rem;font-size:1.02rem;box-shadow:0 12px 36px color-mix(in srgb, var(--accent) 22%, transparent)}
.hero-proof{margin-top:1.2rem;font-family:var(--font-mono);font-size:.875rem;letter-spacing:.05em;color:var(--mut);display:flex;align-items:center;gap:.55rem;flex-wrap:wrap}
.hero-proof .stars{color:var(--accent-text);letter-spacing:.14em;font-size:.9rem}
.hero-proof b{font-size:.95rem;color:var(--white)}
.hs-media{position:relative;min-height:420px;clip-path:polygon(11% 0,100% 0,100% 100%,0 100%);overflow:hidden}
.hs-imgwrap{position:absolute;inset:-8% 0;will-change:transform}
.hs-imgwrap img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;object-position:center 28%;filter:contrast(1.15) saturate(.8) brightness(.92) hue-rotate(-6deg);transform:scale(1.1);transform-origin:50% 26%;animation:hsKb 18s cubic-bezier(.22,.6,.3,1) forwards}
@keyframes hsKb{to{transform:scale(1.01)}}
.hs-grain{position:absolute;inset:0;z-index:1;pointer-events:none;opacity:.45;mix-blend-mode:overlay;background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='180' height='180'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/%3E%3CfeColorMatrix type='saturate' values='0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)' opacity='0.38'/%3E%3C/svg%3E");background-size:180px 180px}
.hs-media::before{content:"";position:absolute;inset:0;background:linear-gradient(115deg,rgba(14,17,22,.78) 0%,rgba(14,17,22,.1) 52%,rgba(18,28,44,.48) 100%),radial-gradient(120% 90% at 60% 20%,transparent 45%,rgba(10,13,18,.5) 100%);z-index:1}
.hs-media::after{content:"";position:absolute;left:0;top:0;bottom:0;width:12px;background:repeating-linear-gradient(135deg,var(--accent) 0 16px,var(--coal) 16px 32px);transform:skewX(-6.4deg);transform-origin:top;z-index:2}
.hs-plate{position:absolute;right:clamp(1rem,3vw,2.4rem);bottom:clamp(1rem,3vw,2.2rem);z-index:3;background:rgba(14,17,22,.86);backdrop-filter:blur(6px);border:1px solid var(--line);border-left:4px solid var(--accent);padding:.9rem 1.2rem;font-family:var(--font-mono);font-size:.875rem;letter-spacing:.16em;text-transform:uppercase;color:var(--white);max-width:min(320px,80%)}
.hs-plate b{color:var(--accent-text);font-weight:700;display:block;margin-bottom:.15rem}
.hero-strip{border-top:1px solid var(--line);display:flex;flex-wrap:wrap;gap:.4rem 2.6rem;padding:1.05rem 0;font-family:var(--font-mono);font-size:.875rem;letter-spacing:.18em;text-transform:uppercase;color:var(--mut-2)}
.hero-strip b{color:var(--accent-text);font-weight:700}
@media(max-width:940px){
  .hero-split .hs-grid{grid-template-columns:1fr;min-height:0}
  .hs-media{min-height:360px;clip-path:polygon(0 12%,100% 0,100% 100%,0 100%);order:2}
  .hs-media::after{display:none}
  .hs-copy{order:1;padding:clamp(2.6rem,8vw,4rem) clamp(1.1rem,4vw,2.6rem)}
  .hs-copy::before,.hs-copy::after{display:none}
}
@media(prefers-reduced-motion:reduce){.hs-imgwrap img{animation:none;transform:none}.hl-in{animation:none;transform:none}.hload{animation:none;opacity:1;transform:none}}
.hero-ctas{display:flex;flex-wrap:wrap;gap:1rem}

/* legacy hero classes (inner use) */
.hero-bg{position:absolute;inset:0;z-index:-2}
.hero-tag{font-family:var(--font-mono);font-size:.875rem;letter-spacing:.24em;text-transform:uppercase;color:var(--accent-text);margin-bottom:1.2rem;display:flex;gap:.7rem;align-items:center}

/* ---------- HOME full-bleed centered hero (Caruth skin) ---------- */
.hero{position:relative;min-height:min(88vh,820px);display:flex;align-items:center;color:var(--white);isolation:isolate;overflow:clip;text-align:center;border-bottom:1px solid var(--line)}
.hero .hero-bg{position:absolute;inset:0;z-index:-2;will-change:transform}
.hero .hero-bg img{width:100%;height:100%;object-fit:cover;object-position:center 44%;filter:contrast(1.04) saturate(1.14) brightness(1.06);transform:scale(1.08);transform-origin:50% 40%;animation:heroKb 16s cubic-bezier(.22,.6,.3,1) forwards}
.hero .hero-bg video{width:100%;height:100%;object-fit:cover;object-position:center 44%;filter:contrast(1.04) saturate(1.1) brightness(.95)}
.hero .hero-bg::after{content:"";position:absolute;inset:0;background:radial-gradient(ellipse 78% 62% at 50% 50%,rgba(14,17,22,.58) 0%,rgba(14,17,22,.40) 45%,rgba(14,17,22,.10) 75%,rgba(14,17,22,0) 100%),linear-gradient(180deg,rgba(14,17,22,.34) 0%,rgba(14,17,22,.12) 38%,rgba(14,17,22,.20) 62%,rgba(14,17,22,.58) 100%)}
.hero .wrap{padding-top:5.5rem;padding-bottom:clamp(1.5rem,3.5vh,2.6rem);width:100%;display:flex;flex-direction:column;align-items:center}
.hero .hero-tag{justify-content:center;margin-bottom:1.7rem;color:#fff;font-size:.875rem;text-shadow:0 1px 14px rgba(0,0,0,.92),0 0 4px rgba(0,0,0,.7)}
.hero .hero-tag::before,.hero .hero-tag::after{content:"";width:2.4rem;height:2px;background:var(--accent)}
.hero h1{max-width:none;margin-left:auto;margin-right:auto;font-size:clamp(2rem,5.6vw,5.2rem);line-height:1.1;letter-spacing:.01em;text-shadow:0 1px 3px rgba(0,0,0,.48)}
.hero h1 .hl-in{white-space:normal;overflow-wrap:break-word;text-wrap:balance}
.hero h1 .acc{color:var(--accent-text)}
.hero p{margin:1.7rem auto 2rem;max-width:46ch;font-size:clamp(1rem,1.5vw,1.15rem);color:#e7ebef;text-shadow:0 1px 10px rgba(0,0,0,.55)}
.hero .hero-ctas{justify-content:center}
.hero .hero-proof{margin-top:1.6rem;justify-content:center;color:#e7ebef;text-shadow:0 1px 10px rgba(0,0,0,.6)}
.hero .hero-strip{border-top:1px solid var(--line-light);margin-top:clamp(1.2rem,3vh,2rem);padding-top:1.1rem;justify-content:center}
.hero-scroll{position:absolute;right:clamp(1.1rem,3vw,2.6rem);bottom:0;height:5.5rem;width:2px;overflow:hidden;z-index:1}
.hero-scroll span{position:absolute;left:0;top:-100%;width:2px;height:100%;background:linear-gradient(180deg,transparent,var(--accent));animation:scrollCue 2.4s cubic-bezier(.6,.1,.3,.9) 1.4s infinite}
@keyframes heroKb{to{transform:scale(1)}}
@keyframes scrollCue{0%{top:-100%}55%{top:100%}100%{top:100%}}
@media(max-width:940px){.hero{min-height:min(92vh,760px)}.hero-scroll{display:none}}
@media(prefers-reduced-motion:reduce){.hero .hero-bg img{animation:none;transform:none}}

/* ---------- stat band ---------- */
.statband{background:var(--accent);color:var(--on-accent);position:relative;overflow:clip}
.statband .wrap{display:grid;grid-template-columns:repeat(4,1fr);gap:1.2rem;padding-top:clamp(1.8rem,4vw,2.8rem);padding-bottom:clamp(1.8rem,4vw,2.8rem)}
.stat{border-left:3px solid var(--on-accent);padding-left:1.1rem}
.stat .sv{font-family:var(--font-display);font-size:clamp(2rem,4.4vw,3.4rem);line-height:1}
.stat .sl{font-family:var(--font-mono);font-size:.875rem;font-weight:700;letter-spacing:.18em;text-transform:uppercase;margin-top:.35rem}
@media(max-width:940px){.statband .wrap{grid-template-columns:1fr 1fr}}
@media(max-width:480px){.statband .wrap{grid-template-columns:1fr 1fr;gap:1.4rem .9rem}.stat .sv{font-size:1.9rem}}

/* ---------- marquee (retired; safety stub) ---------- */
.marquee{display:none}

/* ---------- service ticket cards ---------- */
.svc-grid{display:grid;grid-template-columns:repeat(6,1fr);gap:1.3rem}
.svc-card{grid-column:span 2;position:relative;display:flex;flex-direction:column;background:var(--panel);border:1px solid var(--line);overflow:hidden;transition:transform .3s ease,border-color .3s ease,box-shadow .3s ease}
.svc-card.wide{grid-column:span 3}
/* 2026-09-09 (Arsen, recurring pattern -- A1 Patios, Custom Stone Tile "orphaned 6th image
   card"): the grid was designed around exactly 6 (or a multiple-of-3) service cards; any other
   real count left a broken/orphaned layout, previously fixed by hand per-site with the .wide
   class above. Now that retheme_agent.js consolidates near-duplicate services (so a business
   with fewer genuinely distinct services correctly gets FEWER cards, not padded to 6), this
   needs to lay out cleanly on its own for any real count, automatically -- not require a human
   to remember to add .wide. */
.svc-grid .svc-card.wide{grid-column:span 3}
.svc-grid:has(.svc-card.wide) .svc-card:not(.wide){grid-column:span 2}
/* 2 wide(span3) + 4 regular(span2) = 5 rows won't divide evenly (3+1 orphan); rebalance the
   4 regular cards to span3 too so they form two full rows matching the hero row's width
   instead of stranding a lone half-width card. Must stay unconditional (not gated to
   min-width:941px) or the tablet range (621-940px) falls back to the same orphan. */
.svc-grid:has(.svc-card.wide):has(.svc-card:nth-child(6):last-child) .svc-card:not(.wide){grid-column:span 3}
@media(min-width:941px){
.svc-grid:not(:has(.svc-card.wide)):has(.svc-card:only-child) .svc-card{grid-column:span 6}
.svc-grid:not(:has(.svc-card.wide)):has(.svc-card:nth-child(2):last-child) .svc-card{grid-column:span 3}
.svc-grid:not(:has(.svc-card.wide)):has(.svc-card:nth-child(3):last-child) .svc-card{grid-column:span 2}
.svc-grid:not(:has(.svc-card.wide)):has(.svc-card:nth-child(4):last-child) .svc-card{grid-column:span 3}
.svc-grid:not(:has(.svc-card.wide)):has(.svc-card:nth-child(5):last-child) .svc-card{grid-column:span 2}
.svc-grid:not(:has(.svc-card.wide)):has(.svc-card:nth-child(5):last-child) .svc-card:nth-last-child(-n+2){grid-column:span 3}
.svc-grid:not(:has(.svc-card.wide)):has(.svc-card:nth-child(6):last-child) .svc-card{grid-column:span 2}
/* 2026-09-29 (live_render_check grid-gap on blog.html): the blog grid ships 3 cards that are ALL .wide (span 3 of 6),
   which left a lone card and a half-empty row. When every card is .wide, lay out by count instead. */
.svc-grid:not(:has(.svc-card:not(.wide))) .svc-card:only-child{grid-column:span 6}
.svc-grid:not(:has(.svc-card:not(.wide))):has(.svc-card:nth-child(3):last-child) .svc-card{grid-column:span 2}
.svc-grid:not(:has(.svc-card:not(.wide))):has(.svc-card:nth-child(5):last-child) .svc-card:nth-child(-n+3){grid-column:span 2}
/* 2026-09-29 (live_render_check grid-gap, svc-grid FULL-ROW guarantee): every mix of .wide/normal cards for 1-8 cards
   now fills every row (verified by a 510-combination headless-Chrome harness at 1440/1000/800/390). Rules:
   - all-normal 7/8 cards and all-wide 7 cards: count layout extended (existing rules only went to 6).
   - HERO mix (every .wide card comes first, then normals): wides stay span 3 (an odd last wide goes span 6, or span 3 next to a
     lone normal); the k trailing normals are laid out by count k (1:6 2:3 3:2 4:3 5:2x3+3x2 6:2 7:2x3+3x4).
   - any other mix (a .wide after a normal card): .wide is ignored and ALL cards lay out by total count. */
.svc-grid:not(:has(.svc-card.wide)):has(.svc-card:nth-child(7):last-child) .svc-card{grid-column:span 2}
.svc-grid:not(:has(.svc-card.wide)):has(.svc-card:nth-child(7):last-child) .svc-card:nth-last-child(-n+4){grid-column:span 3}
.svc-grid:not(:has(.svc-card.wide)):has(.svc-card:nth-child(8):last-child) .svc-card{grid-column:span 3}
.svc-grid:not(:has(.svc-card:not(.wide))):has(.svc-card:nth-child(7):last-child) .svc-card:nth-child(-n+3){grid-column:span 2}
.svc-grid:has(.svc-card:not(.wide) ~ .svc-card.wide):has(.svc-card:nth-child(2):last-child) .svc-card{grid-column:span 3}
.svc-grid:has(.svc-card:not(.wide) ~ .svc-card.wide):has(.svc-card:nth-child(3):last-child) .svc-card{grid-column:span 2}
.svc-grid:has(.svc-card:not(.wide) ~ .svc-card.wide):has(.svc-card:nth-child(4):last-child) .svc-card{grid-column:span 3}
.svc-grid:has(.svc-card:not(.wide) ~ .svc-card.wide):has(.svc-card:nth-child(5):last-child) .svc-card{grid-column:span 2}
.svc-grid:has(.svc-card:not(.wide) ~ .svc-card.wide):has(.svc-card:nth-child(5):last-child) .svc-card:nth-last-child(-n+2){grid-column:span 3}
.svc-grid:has(.svc-card:not(.wide) ~ .svc-card.wide):has(.svc-card:nth-child(6):last-child) .svc-card{grid-column:span 2}
.svc-grid:has(.svc-card:not(.wide) ~ .svc-card.wide):has(.svc-card:nth-child(7):last-child) .svc-card{grid-column:span 2}
.svc-grid:has(.svc-card:not(.wide) ~ .svc-card.wide):has(.svc-card:nth-child(7):last-child) .svc-card:nth-last-child(-n+4){grid-column:span 3}
.svc-grid:has(.svc-card:not(.wide) ~ .svc-card.wide):has(.svc-card:nth-child(8):last-child) .svc-card{grid-column:span 3}
.svc-grid:has(.svc-card.wide):has(.svc-card:not(.wide)):not(:has(.svc-card:not(.wide) ~ .svc-card.wide)):has(.svc-card.wide:nth-last-child(2) + .svc-card:not(.wide)) .svc-card:not(.wide){grid-column:span 6}
.svc-grid:has(.svc-card.wide):has(.svc-card:not(.wide)):not(:has(.svc-card:not(.wide) ~ .svc-card.wide)):has(.svc-card.wide:nth-last-child(3) + .svc-card:not(.wide)) .svc-card:not(.wide){grid-column:span 3}
.svc-grid:has(.svc-card.wide):has(.svc-card:not(.wide)):not(:has(.svc-card:not(.wide) ~ .svc-card.wide)):has(.svc-card.wide:nth-last-child(4) + .svc-card:not(.wide)) .svc-card:not(.wide){grid-column:span 2}
.svc-grid:has(.svc-card.wide):has(.svc-card:not(.wide)):not(:has(.svc-card:not(.wide) ~ .svc-card.wide)):has(.svc-card.wide:nth-last-child(5) + .svc-card:not(.wide)) .svc-card:not(.wide){grid-column:span 3}
.svc-grid:has(.svc-card.wide):has(.svc-card:not(.wide)):not(:has(.svc-card:not(.wide) ~ .svc-card.wide)):has(.svc-card.wide:nth-last-child(6) + .svc-card:not(.wide)) .svc-card:not(.wide){grid-column:span 2}
.svc-grid:has(.svc-card.wide):has(.svc-card:not(.wide)):not(:has(.svc-card:not(.wide) ~ .svc-card.wide)):has(.svc-card.wide:nth-last-child(6) + .svc-card:not(.wide)) .svc-card:not(.wide):nth-last-child(-n+2){grid-column:span 3}
.svc-grid:has(.svc-card.wide):has(.svc-card:not(.wide)):not(:has(.svc-card:not(.wide) ~ .svc-card.wide)):has(.svc-card.wide:nth-last-child(7) + .svc-card:not(.wide)) .svc-card:not(.wide){grid-column:span 2}
.svc-grid:has(.svc-card.wide):has(.svc-card:not(.wide)):not(:has(.svc-card:not(.wide) ~ .svc-card.wide)):has(.svc-card.wide:nth-last-child(8) + .svc-card:not(.wide)) .svc-card:not(.wide){grid-column:span 2}
.svc-grid:has(.svc-card.wide):has(.svc-card:not(.wide)):not(:has(.svc-card:not(.wide) ~ .svc-card.wide)):has(.svc-card.wide:nth-last-child(8) + .svc-card:not(.wide)) .svc-card:not(.wide):nth-last-child(-n+4){grid-column:span 3}
.svc-grid:has(.svc-card.wide):has(.svc-card:not(.wide)):not(:has(.svc-card:not(.wide) ~ .svc-card.wide)) .svc-card.wide:nth-child(odd):has(+ .svc-card:not(.wide) + .svc-card){grid-column:span 6}
.svc-grid:has(.svc-card.wide):has(.svc-card:not(.wide)):not(:has(.svc-card:not(.wide) ~ .svc-card.wide)) .svc-card.wide:nth-child(odd) + .svc-card:not(.wide):last-child:nth-child(n){grid-column:span 3}
/* legacy 6-card mixed rule (2 wide + 4 normal, any order): every card span 3 = two full rows. Kept exactly as before; !important so the hero/other-mix rules above never re-lay it out. */
.svc-grid:has(.svc-card.wide):has(.svc-card:not(.wide)):has(.svc-card:nth-child(6):last-child) .svc-card{grid-column:span 3!important}
}
.svc-card::before{content:"";position:absolute;top:0;left:0;right:0;height:3px;background:var(--accent);transform:scaleX(0);transform-origin:left;transition:transform .35s ease;z-index:3}
.svc-card:hover{transform:translateY(-6px);border-color:color-mix(in srgb, var(--accent) 50%, transparent);box-shadow:0 24px 50px rgba(0,0,0,.45)}
.svc-card:hover::before{transform:scaleX(1)}
.svc-card img{position:relative;width:100%;height:clamp(210px,24vw,320px);object-fit:cover;filter:saturate(.82) contrast(1.04);transition:filter .4s ease,transform .6s cubic-bezier(.2,.6,.2,1)}
.svc-card:hover img{filter:saturate(1.05);transform:scale(1.04)}
.svc-card .imgbox,.svc-card>img{overflow:hidden}
.svc-body{position:relative;z-index:2;padding:1.45rem 1.45rem 1.55rem;display:flex;flex-direction:column;gap:.5rem;flex:1;background:var(--panel)}
.svc-num{font-family:var(--font-mono);font-size:.875rem;font-weight:700;letter-spacing:.2em;color:var(--accent-text)}
.svc-body h3{font-size:1.45rem;letter-spacing:.02em}
.svc-body p{font-size:.93rem;color:var(--mut)}
.svc-link{font-family:var(--font-mono);font-size:.875rem;letter-spacing:.14em;text-transform:uppercase;color:var(--accent-text);display:inline-flex;gap:.5rem;margin-top:auto;padding-top:.5rem}
@media(max-width:940px){.svc-card,.svc-card.wide{grid-column:span 3}}
/* 2026-09-29: tablet (621-940px) = 2 columns for every mix; an odd last card spans the full row (no half-empty row).
   !important because the unconditional wide/normal rules above out-rank the plain .svc-card rule. */
@media(min-width:621px) and (max-width:940px){.svc-grid .svc-card,.svc-grid .svc-card.wide{grid-column:span 3!important}.svc-grid .svc-card:last-child:nth-child(odd){grid-column:span 6!important}}
@media(max-width:620px){.svc-card,.svc-card.wide{grid-column:span 6!important}}

/* ---------- boom vs line selector (signature) ---------- */
.bvl{border:1px solid var(--line);background:var(--coal-2)}
.bvl-tabs{display:grid;grid-template-columns:1.05fr .95fr}/* MUST match .bvl-panel's columns. They were 1fr 1fr vs 1.05fr .95fr, so the Residential/Commercial tab divider sat ~25px off from the text/image divider underneath it on every contractor site (Wayne, 2026-08-06). */
.bvl-tab{font-family:var(--font-display);font-size:clamp(1.3rem,3vw,2.1rem);text-transform:uppercase;letter-spacing:.02em;padding:1.15rem 1rem;background:var(--panel);color:var(--mut-2);border:0;border-bottom:1px solid var(--line);cursor:pointer;transition:all .25s ease;position:relative}
.bvl-tab+.bvl-tab{border-left:1px solid var(--line)}
.bvl-tab.on{background:var(--accent);color:var(--on-accent)}
.bvl-tab:not(.on):hover{color:var(--white)}
.bvl-panel{display:none;grid-template-columns:1.05fr .95fr;gap:0;align-items:stretch}
.bvl-panel.on{display:grid}
.bvl-info{padding:clamp(1.6rem,4vw,2.8rem)}
.bvl-info h3{font-size:clamp(1.5rem,2.8vw,2.2rem);margin-bottom:.6rem}
.bvl-info>p{color:var(--mut);max-width:52ch}
.bvl-specs{margin-top:1.4rem;border-top:1px solid var(--line)}
.bvl-specs .row{display:grid;grid-template-columns:minmax(120px,38%) 1fr;gap:1rem;padding:.7rem .1rem;border-bottom:1px solid var(--line);font-size:.95rem}
.bvl-specs .row b{font-family:var(--font-mono);font-weight:500;font-size:.875rem;letter-spacing:.16em;text-transform:uppercase;color:var(--accent-text)}
.bvl-media{position:relative;min-height:300px}
.bvl-media img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}
.bvl-media::before{content:"";position:absolute;inset:0;background:linear-gradient(90deg,var(--coal-2) 0,rgba(14,17,22,0) 30%)}
@media(max-width:880px){.bvl-panel{grid-template-columns:1fr}.bvl-media{min-height:240px;order:-1}.bvl-media::before{background:linear-gradient(0deg,var(--coal-2) 0,rgba(14,17,22,0) 40%)}}

/* ---------- service rows (services index) ---------- */
.svc-row{display:grid;grid-template-columns:auto 1fr 1fr;gap:clamp(1.5rem,4vw,3.5rem);align-items:center;padding:clamp(2rem,4vw,3rem) 0;border-top:1px solid var(--line);position:relative}
.svc-row:last-of-type{border-bottom:1px solid var(--line)}
.svc-row .idx{font-family:var(--font-display);font-size:clamp(2.2rem,5vw,3.8rem);color:transparent;-webkit-text-stroke:1.5px var(--accent-text);line-height:1}
.svc-row h3{font-size:clamp(1.7rem,3.4vw,2.8rem)}
.svc-row h3 a{transition:color .2s ease}
.svc-row h3 a:hover{color:var(--accent-text)}
.svc-row p{color:var(--mut);max-width:48ch;margin-top:.6rem}
.svc-row .media{overflow:hidden}
.svc-row .media img{aspect-ratio:16/9;width:100%;object-fit:cover;filter:saturate(.85);transition:transform .6s cubic-bezier(.2,.6,.2,1),filter .4s ease}
.svc-row:hover .media img{transform:scale(1.05);filter:saturate(1.05)}
@media(max-width:820px){.svc-row{grid-template-columns:1fr}}
.go{font-family:var(--font-mono);font-size:.875rem;letter-spacing:.14em;text-transform:uppercase;color:var(--accent-text);display:inline-flex;gap:.5rem;margin-top:.9rem}
.go:hover{text-decoration:underline}

/* ---------- numbered feature rows ---------- */
.feat{display:grid;grid-template-columns:auto 1fr;gap:1.4rem;padding:1.8rem 0;border-top:1px solid var(--line);align-items:start}
.feat:last-child{border-bottom:1px solid var(--line)}
.feat .n{font-family:var(--font-display);font-size:2rem;color:transparent;-webkit-text-stroke:1.4px var(--accent-text);line-height:1}
.feat h3{font-size:1.28rem;letter-spacing:.02em;margin-bottom:.4rem}
.feat p{color:var(--mut);max-width:60ch}
.light .feat,.feat.light{border-color:var(--line)}
.light .feat p,.feat.light p{color:var(--mut)}

/* ---------- process timeline ---------- */
.steps{position:relative;counter-reset:step;display:grid;grid-template-columns:1fr;gap:0;max-width:820px}
.step{position:relative;padding:1.6rem 0 1.6rem 5.4rem;border:0;background:transparent;transition:none}
.step::after{content:"";position:absolute;left:1.55rem;top:0;bottom:0;width:2px;background:var(--line)}
.step:first-child::after{top:1.4rem}
.step:last-child::after{bottom:auto;height:1.4rem}
.step::before{
  counter-increment:step;content:"0" counter(step);
  position:absolute;left:0;top:1.15rem;width:3.15rem;height:3.15rem;
  display:flex;align-items:center;justify-content:center;
  font-family:var(--font-display);font-size:1.15rem;
  background:var(--coal);border:2px solid var(--accent);color:var(--accent-text);z-index:2;
  transition:background .25s ease,color .25s ease;
}
.step:hover::before{background:var(--accent);color:var(--on-accent)}
.step h3{font-size:1.35rem;letter-spacing:.02em;margin-bottom:.4rem}
.step p{font-size:.98rem;color:var(--mut);max-width:58ch}

/* ---------- gallery ---------- */
.gal-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:1rem}
.gal-item{position:relative;overflow:hidden;cursor:zoom-in;aspect-ratio:4/3;background:var(--panel);border:1px solid var(--line)}
.gal-item.tall{grid-row:span 2;aspect-ratio:auto}
.gal-item img{width:100%;height:100%;object-fit:cover;filter:saturate(.85);transition:transform .6s cubic-bezier(.2,.6,.2,1),filter .4s ease}
.gal-item:hover img{transform:scale(1.06);filter:saturate(1.08)}
.gal-item figcaption{position:absolute;left:0;right:0;bottom:0;padding:.55rem .9rem;background:var(--accent);color:var(--on-accent);font-family:var(--font-mono);font-size:.875rem;font-weight:700;letter-spacing:.12em;text-transform:uppercase;transform:translateY(101%);transition:transform .3s ease}
.gal-item:hover figcaption{transform:none} /* 2026-09-10: mobile/touch has no hover, so captions never showed on touch devices -- always reveal them when hover isn't available */
@media(hover:none){.gal-item figcaption{transform:none}}
@media(max-width:940px){.gal-grid{grid-template-columns:1fr 1fr}}
@media(max-width:520px){.gal-grid{grid-template-columns:1fr}.gal-item.tall{grid-row:span 1;aspect-ratio:4/3}}
/* 2026-09-29 (live_render_check grid-gap, FAIL on 4 client galleries): a photo grid never ends on a half-empty
   row. Desktop: 12 tracks, 4 tiles a row (span 3); the tail re-flows into rows of 3 wider tiles (span 4 at 16:9,
   the same height as a 4:3 tile in a 4-up row), so every count fills every row (n%4: 3 -> last row of 3,
   2 -> last 2 rows of 3, 1 -> last 3 rows of 3; 5 -> 3+2, 2 -> 2 wide, 1 -> full width). Tablet (2-up): an odd
   last tile spans the row. Grids with .tall tiles keep the old flow (their row spans are hand-placed).
   Browsers without :has() ignore all of it and keep the 4-column grid. Tested headless at 1440/800 for 1-15 and 31 tiles. */
@media(min-width:941px){
.gal-grid:not(:has(> .gal-item.tall)){grid-template-columns:repeat(12,1fr)}
.gal-grid:not(:has(> .gal-item.tall)) > .gal-item{grid-column:span 3}
.gal-grid:not(:has(> .gal-item.tall)):has(> .gal-item:last-child:nth-child(4n+3)) > .gal-item:nth-last-child(-n+3),
.gal-grid:not(:has(> .gal-item.tall)):has(> .gal-item:last-child:nth-child(4n+6)) > .gal-item:nth-last-child(-n+6),
.gal-grid:not(:has(> .gal-item.tall)):has(> .gal-item:last-child:nth-child(4n+9)) > .gal-item:nth-last-child(-n+9),
.gal-grid:not(:has(> .gal-item.tall)):has(> .gal-item:last-child:nth-child(5)) > .gal-item{grid-column:span 4;aspect-ratio:16/9}
.gal-grid:not(:has(> .gal-item.tall)):has(> .gal-item:last-child:nth-child(5)) > .gal-item:nth-last-child(-n+2),
.gal-grid:not(:has(> .gal-item.tall)):has(> .gal-item:last-child:nth-child(2)) > .gal-item{grid-column:span 6;aspect-ratio:8/3}
.gal-grid:not(:has(> .gal-item.tall)) > .gal-item:only-child{grid-column:1 / -1;aspect-ratio:3/1}
}
@media(min-width:521px) and (max-width:940px){
.gal-grid:not(:has(> .gal-item.tall)) > .gal-item:last-child:nth-child(odd){grid-column:1 / -1;aspect-ratio:8/3}
}
.lightbox{position:fixed;inset:0;background:rgba(8,10,13,.95);z-index:200;display:none;align-items:center;justify-content:center;padding:3rem 1rem}
.lightbox.open{display:flex}
.lightbox img{max-width:min(1100px,94vw);max-height:84vh;object-fit:contain}
.lb-close{position:absolute;top:1.2rem;right:1.4rem;background:none;border:2px solid var(--white);color:var(--white);width:46px;height:46px;font-size:1.2rem;cursor:pointer;transition:all .2s ease}
.lb-close:hover{background:var(--accent);border-color:var(--accent);color:var(--on-accent)}
.lb-nav{position:absolute;top:50%;transform:translateY(-50%);background:none;border:2px solid var(--white);color:var(--white);width:46px;height:46px;font-size:1.1rem;cursor:pointer;transition:all .2s ease}
.lb-nav:hover{background:var(--accent);border-color:var(--accent);color:var(--on-accent)}
.lb-prev{left:1.2rem}.lb-next{right:1.2rem}

/* Gallery auto-sliding strips (Wayne 2026-09-02, generalized for reuse on future template
   builds): matches rolluppainting.com's real Exterior/Interior gallery split, but also
   genuinely scrollable -- touch swipe, trackpad, mouse wheel, and click-drag all just work,
   because .slide-track-wrap is a REAL horizontal-scroll container, not a transform animation.
   wireSlideTracks() in site.js auto-advances scrollLeft on top of that and wraps it (the image
   list is duplicated once in the HTML) for a genuinely endless loop, pausing the moment a
   visitor touches it. Click a photo to open it in the existing lightbox (wireLightbox()
   already covers .slide-track img). Drop a `.slide-track-wrap` (optionally `.reverse`) with one
   `.slide-track` of <img>s (each duplicated once) into any template; no per-site JS needed. */
.slide-track-wrap{overflow:hidden;width:100%;padding:1.6rem 0}
.slide-track{display:flex;gap:1rem;width:max-content;animation-name:slideTrackAnim;animation-timing-function:linear;animation-iteration-count:infinite;will-change:transform}
.slide-track-wrap.reverse .slide-track{animation-direction:reverse}
.slide-track-wrap:hover .slide-track{animation-play-state:paused}
@keyframes slideTrackAnim{from{transform:translateX(0)}to{transform:translateX(-50%)}}
.slide-track img{height:320px;width:auto;max-width:none;border-radius:10px;object-fit:cover;flex:none;border:1px solid var(--line);-webkit-user-drag:none;user-select:none}
@media(max-width:760px){.slide-track img{height:220px}}

/* ---------- area chips + rows ---------- */
.area-list{display:flex;flex-wrap:wrap;gap:.7rem}
.area-chip{font-family:var(--font-mono);font-size:.875rem;letter-spacing:.08em;text-transform:uppercase;border:1px solid var(--line);padding:.55rem 1.05rem;background:transparent;color:var(--mut);transition:all .2s ease}
.area-chip:hover{background:var(--accent);color:var(--on-accent);border-color:var(--accent)}
.area-rows{border-top:1px solid var(--line)}
.area-row{display:flex;justify-content:space-between;align-items:baseline;gap:1rem;padding:1.05rem .2rem;border-bottom:1px solid var(--line);transition:background .2s ease,padding .2s ease}
.area-row:hover{background:var(--panel);padding-left:.8rem;padding-right:.4rem}
.area-row .nm{font-family:var(--font-display);text-transform:uppercase;font-size:clamp(1.3rem,2.7vw,2rem);letter-spacing:.02em}
.area-row .co{font-family:var(--font-mono);font-size:.875rem;letter-spacing:.16em;text-transform:uppercase;color:var(--accent-text);text-align:right}

/* ---------- trust ---------- */
.trust{display:grid;grid-template-columns:1fr 1fr;gap:1.4rem}
@media(max-width:820px){.trust{grid-template-columns:1fr}}
.trust-card{background:var(--panel);border:1px solid var(--line);border-top:3px solid var(--accent);padding:2.1rem;transition:transform .25s ease,box-shadow .25s ease,border-color .25s ease}
.trust-card:hover{transform:translateY(-5px);box-shadow:0 22px 50px rgba(0,0,0,.45);border-color:color-mix(in srgb, var(--accent) 45%, transparent)}
.tc-label{font-family:var(--font-mono);font-size:.875rem;font-weight:700;letter-spacing:.2em;text-transform:uppercase;color:var(--accent-text);margin-bottom:1rem;display:flex;align-items:center;gap:.6rem}
.tc-label::before{content:"//";letter-spacing:0}
.stars{color:var(--accent-text);letter-spacing:.18em;font-size:1.05rem}

/* ---------- CTA band (hi-vis) ---------- */
.cta-band{position:relative;isolation:isolate;color:var(--on-accent);text-align:center;overflow:clip;background:var(--accent)}
.cta-band .bgimg{display:none}
.cta-band::before{content:"";position:absolute;top:0;left:0;right:0;height:14px;background:var(--accent);background-image:repeating-linear-gradient(135deg,var(--coal-2) 0 14px,rgba(0,0,0,0) 14px,rgba(0,0,0,0) 28px)}
.cta-band .kicker{color:var(--on-accent)}
.cta-band h2{max-width:16ch;margin:0 auto}
.cta-band p{max-width:54ch;margin:1.2rem auto 2rem;color:var(--on-accent);font-weight:500} /* was rgba(14,17,22,.95): unreadable on a dark brand accent (Expert Fence maroon, 2026-09-27); --on-accent flips light/dark with the accent */
.cta-band .hero-ctas{justify-content:center}
.cta-band .btn-solid,.cta-band .btn-red{background:var(--coal);border-color:var(--coal);color:var(--accent-text)}
.cta-band .btn-solid:hover,.cta-band .btn-red:hover{background:#000;border-color:#000;color:var(--white);box-shadow:none}
.cta-band .btn-ghost-light,.cta-band .btn-light,.cta-band .btn-ghost{border-color:var(--coal);color:var(--on-accent)}
.cta-band .btn-ghost-light:hover,.cta-band .btn-light:hover,.cta-band .btn-ghost:hover{background:var(--coal);color:var(--accent-text)}
.cta-band .btn-ink{border-color:var(--coal);color:var(--on-accent);background:transparent}
.cta-band .btn-ink:hover{background:var(--coal);color:var(--accent-text)}
.cta-band .giant-bg{position:absolute;inset:auto 0 -1vw 0;z-index:-1;font-family:var(--font-display);text-transform:uppercase;font-size:clamp(4rem,15vw,13rem);line-height:.8;color:transparent;-webkit-text-stroke:1.6px rgba(14,17,22,.16);user-select:none;pointer-events:none;white-space:nowrap;overflow:hidden}

/* ---------- page hero (inner) ---------- */
.page-hero{position:relative;isolation:isolate;color:var(--white);padding:clamp(6rem,12vw,8.5rem) 0 clamp(3rem,6vw,4.5rem);overflow:clip;border-bottom:1px solid var(--line)}
.page-hero .bgimg{position:absolute;inset:0 0 0 30%;z-index:-2}
.page-hero .bgimg img{width:100%;height:100%;object-fit:cover;object-position:center;filter:saturate(.8)}
.page-hero::before{content:"";position:absolute;inset:0;z-index:-1;background:linear-gradient(100deg,var(--coal) 38%,rgba(14,17,22,.66) 70%,rgba(14,17,22,.45) 100%)}
.page-hero::after{content:"";position:absolute;left:0;right:0;bottom:0;height:12px;background:repeating-linear-gradient(135deg,var(--accent) 0 16px,var(--coal) 16px 32px)}
.page-hero.plain{background:var(--coal-2)}
.page-hero.plain::after{display:none}
.crumbs{font-family:var(--font-mono);font-size:.875rem;letter-spacing:.18em;text-transform:uppercase;color:var(--mut-2);margin-bottom:1.3rem}
.crumbs::before{content:"// ";color:var(--accent-text)}
.crumbs a:hover{color:var(--accent-text)}
.page-hero h1{max-width:17ch}
.page-hero .lead{color:var(--mut);margin-top:1.2rem}
.page-hero .lead a{color:var(--white)}

/* ---------- content blocks ---------- */
.media{overflow:hidden;position:relative}
.media img{width:100%;height:100%;object-fit:cover;transition:transform .7s cubic-bezier(.2,.6,.2,1)}
.media:hover img{transform:scale(1.04)}
.media.frame,.media.frame-red{border:1px solid var(--line);padding:0}
.media.frame::after,.media.frame-red::after{content:"";position:absolute;top:0;left:0;width:52px;height:8px;background:var(--accent);z-index:2}
.media.frame::before,.media.frame-red::before{content:"";position:absolute;bottom:0;right:0;width:52px;height:8px;background:var(--accent);z-index:2}
.hero-badge{display:inline-block;background:var(--accent);color:var(--on-accent);padding:.85rem 1.15rem;font-family:var(--font-mono);font-size:.875rem;font-weight:700;letter-spacing:.12em;text-transform:uppercase}
.check-list li{display:flex;gap:.85rem;padding:.5rem 0;align-items:flex-start;color:var(--mut)}
.check-list li::before{content:"";flex:none;width:20px;height:20px;margin-top:.25rem;background:var(--accent);clip-path:polygon(14% 44%,0 65%,50% 100%,100% 16%,80% 0,43% 62%)}
.spec-table{width:100%;border-collapse:collapse;font-size:.97rem}
.spec-table td{padding:.9rem .2rem;border-bottom:1px solid var(--line);vertical-align:top;color:var(--white)}
.spec-table td:first-child{font-family:var(--font-mono);font-size:.875rem;letter-spacing:.14em;text-transform:uppercase;color:var(--accent-text);width:40%}
.spec-table a{color:var(--white)}

/* ---------- FAQ ---------- */
.faq-item{border:1px solid var(--line);background:var(--panel);margin-bottom:.9rem;overflow:hidden;transition:border-color .25s ease}
.faq-item:hover,.faq-item[open]{border-color:color-mix(in srgb, var(--accent) 45%, transparent)}
.faq-item summary{cursor:pointer;list-style:none;display:flex;justify-content:space-between;align-items:center;gap:1rem;padding:1.2rem 1.4rem;font-weight:600;font-size:1.04rem;color:var(--white)}
.faq-item summary::-webkit-details-marker{display:none}
.faq-item summary::after{content:"+";font-family:var(--font-display);color:var(--accent-text);font-size:1.3rem;transition:transform .25s ease;flex:none}
.faq-item[open] summary::after{transform:rotate(45deg)}
.faq-item .faq-a{padding:0 1.4rem 1.3rem;color:var(--mut);max-width:75ch}

/* ---------- footer ---------- */
.site-footer{background:#0a0d11;color:var(--mut);border-top:0}
.footer-cta{border-bottom:1px solid var(--line);position:relative}
.footer-cta::before{content:none}
.footer-cta .wrap{display:flex;flex-wrap:wrap;justify-content:space-between;align-items:center;gap:1.4rem;padding-top:2.8rem;padding-bottom:2.8rem}
.footer-cta h2{color:var(--white);font-size:clamp(1.6rem,3vw,2.4rem);max-width:22ch}
.footer-grid{display:grid;grid-template-columns:2fr 1fr 1fr 1.3fr;gap:2.4rem;padding:3.4rem 0}
@media(max-width:940px){.footer-grid{grid-template-columns:1fr 1fr}}
@media(max-width:560px){.footer-grid{grid-template-columns:1fr}}
.site-footer h4{color:var(--accent-text);font-size:1rem;margin-bottom:1.1rem;letter-spacing:.08em}
.site-footer li{margin:.45rem 0}
.site-footer a:hover{color:var(--accent-text)}
.f-about{max-width:34ch;font-size:.94rem;margin-top:1.2rem}
.f-phone{font-family:var(--font-mono);color:var(--white);font-weight:600}
.footer-bottom{border-top:1px solid var(--line);padding:1.3rem 0;font-size:.875rem;color:var(--mut-2)}
.footer-bottom .wrap{display:flex;flex-wrap:wrap;justify-content:space-between;gap:.8rem}
.footer-bottom a:hover{color:var(--accent-text)}

/* ---------- modal (2-step quote) ---------- */
.modal-veil{position:fixed;inset:0;background:rgba(8,10,13,.82);backdrop-filter:blur(5px);z-index:300;display:none;align-items:center;justify-content:center;padding:1rem}
.modal-veil.open{display:flex}
.modal{background:var(--coal-2);border:1px solid var(--line);width:min(620px,100%);max-height:92vh;overflow-y:auto;position:relative;animation:modalIn .3s cubic-bezier(.2,.7,.3,1)}
@keyframes modalIn{from{transform:translateY(26px);opacity:0}to{transform:none;opacity:1}}
.modal-inner{padding:clamp(1.5rem,4vw,2.4rem)}
.modal-close{position:absolute;top:.95rem;right:.95rem;width:40px;height:40px;border:1px solid var(--line);background:var(--panel);color:var(--white);font-size:1.05rem;cursor:pointer;z-index:2;transition:all .2s ease}
.modal-close:hover{background:var(--accent);color:var(--on-accent);border-color:var(--accent)}
.m-steps{display:flex;gap:.5rem;margin-bottom:1.4rem;font-family:var(--font-mono);font-size:.875rem;letter-spacing:.14em;text-transform:uppercase;color:var(--mut-2);flex-wrap:wrap}
.m-steps span{display:flex;align-items:center;gap:.45rem}
.m-steps span::before{content:"";width:26px;height:3px;background:var(--line);transition:background .3s ease}
.m-steps span.on{color:var(--white)}
.m-steps span.on::before{background:var(--accent)}
.modal h3{font-size:1.5rem;letter-spacing:.02em;margin-bottom:.4rem}
.modal .m-sub{color:var(--mut);font-size:.94rem;margin-bottom:1.4rem}
.modal .m-sub a{color:var(--accent-text);font-weight:700}
.f-row{display:grid;grid-template-columns:1fr 1fr;gap:.9rem}
@media(max-width:520px){.f-row{grid-template-columns:1fr}}
.f-field{margin-bottom:.95rem}
.f-field label{display:block;font-family:var(--font-mono);font-size:.875rem;letter-spacing:.14em;text-transform:uppercase;color:var(--mut);margin-bottom:.4rem}
.f-field input,.f-field select,.f-field textarea{
  width:100%;padding:.85rem .95rem;border:1.5px solid var(--line);border-radius:0;
  background:var(--coal);font-family:var(--font-body);font-size:.98rem;color:var(--white);transition:border-color .2s ease;
}
.f-field select option{background:var(--coal);color:var(--white)}
.f-field input:focus,.f-field select:focus,.f-field textarea:focus{outline:none;border-color:var(--accent)}
.f-field textarea{min-height:92px;resize:vertical}
.f-err{color:var(--accent-text);font-size:.875rem;margin-top:.5rem;display:none;font-weight:600}
.day-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:.55rem;margin-bottom:1.1rem}
@media(max-width:520px){.day-grid{grid-template-columns:repeat(3,1fr)}}
.time-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:.55rem}
@media(max-width:520px){.time-grid{grid-template-columns:repeat(3,1fr)}}
.pick{border:1.5px solid var(--line);background:var(--coal);padding:.6rem .3rem;text-align:center;cursor:pointer;font-family:var(--font-mono);font-size:.875rem;transition:all .18s ease;color:var(--white)}
.pick small{display:block;font-size:.875rem;color:var(--mut-2);letter-spacing:.1em;text-transform:uppercase}
.pick:hover{border-color:var(--accent)}
.pick.sel{background:var(--accent);color:var(--on-accent);border-color:var(--accent)}
.pick.sel small{color:var(--on-accent);opacity:.8}
.m-actions{display:flex;gap:.8rem;margin-top:1.5rem;flex-wrap:wrap}
.m-back{background:none;border:0;cursor:pointer;font-family:var(--font-mono);font-size:.875rem;letter-spacing:.1em;text-transform:uppercase;color:var(--mut);padding:.9rem .4rem}
.m-back:hover{color:var(--accent-text)}
.m-confirm{background:var(--panel);border:1px solid var(--line);padding:1.1rem 1.2rem;margin-bottom:1.2rem}
.m-confirm .row{display:flex;justify-content:space-between;gap:1rem;padding:.35rem 0;font-size:.93rem}
.m-confirm .row b{font-family:var(--font-mono);font-weight:500;font-size:.875rem;letter-spacing:.1em;text-transform:uppercase;color:var(--accent-text)}
.m-done{text-align:center;padding:1.5rem 0 .5rem}
.m-done .big{width:72px;height:72px;margin:0 auto 1.2rem;background:var(--accent);color:var(--on-accent);display:flex;align-items:center;justify-content:center;font-size:1.9rem}

/* ---------- reveal motion ---------- */
.rv{opacity:0;transform:translateY(26px);transition:opacity .7s ease,transform .7s cubic-bezier(.2,.6,.2,1)}
.rv.in{opacity:1;transform:none}
.rv-d1{transition-delay:.08s}.rv-d2{transition-delay:.16s}.rv-d3{transition-delay:.24s}.rv-d4{transition-delay:.32s}
@media(prefers-reduced-motion:reduce){.rv{opacity:1;transform:none;transition:none}}

/* big outline word */
.giant{font-family:var(--font-display);text-transform:uppercase;font-size:clamp(2.8rem,7.5vw,6rem);line-height:.92;color:transparent;-webkit-text-stroke:1.6px color-mix(in srgb, var(--accent-text) 32%, transparent);user-select:none;max-width:100%;overflow:hidden}

/* util */
.mt-1{margin-top:1rem}.mt-2{margin-top:2rem}.mt-3{margin-top:3rem}
.mb-1{margin-bottom:1rem}.mb-2{margin-bottom:2rem}.mb-3{margin-bottom:3rem}
.center{text-align:center}
.sec-head{max-width:780px;margin-bottom:clamp(2rem,4vw,3.2rem)}
.sec-head.center{margin-left:auto;margin-right:auto}

/* ===== HERO DOMINANCE (permanent 2026-07-28) - centered, big, present; kills the narrow "prison box" (Eliot) ===== */
.hero .wrap{align-items:center!important;text-align:center!important;padding-top:7rem!important;padding-bottom:3.5rem!important;min-height:88vh!important;justify-content:center!important;max-width:min(1560px,95vw)!important;padding-left:clamp(1.5rem,4vw,3.5rem)!important;padding-right:clamp(1.5rem,4vw,3.5rem)!important}
.hero .wrap>*{margin-left:auto!important;margin-right:auto!important}
.hero .hero-tag{justify-content:center!important}
.hero h1{max-width:22ch!important;text-align:center!important;margin:0 auto!important;font-size:clamp(3rem,8.6vw,7.2rem)!important;line-height:1.0!important;letter-spacing:-.01em!important}
.hero p{max-width:58ch!important;text-align:center!important;margin:1.9rem auto 2.3rem!important;font-size:clamp(1.08rem,1.6vw,1.32rem)!important}
.hero .hero-strip{justify-content:center!important}
.hero .hero-bg::after{background:linear-gradient(180deg,rgba(9,11,15,.44),rgba(9,11,15,.32) 50%,rgba(9,11,15,.66))!important}
/* readability: brighten the accent eyebrow + proof text so it reads cleanly on the photo
   instead of just relying on the dark gradient above (Sarber Construction real-client
   fix, 2026-08-10 -- was hand-applied there only, generalizing it here). */
.hero .hero-tag{color:#f4f0ee!important;text-shadow:0 1px 3px rgba(0,0,0,.9),0 2px 14px rgba(0,0,0,.7)!important;font-weight:600!important}
.hero .hero-tag::before,.hero .hero-tag::after{background:var(--accent)!important}
.hero .hero-proof{color:#f1eeec!important;text-shadow:0 1px 3px rgba(0,0,0,.9),0 2px 12px rgba(0,0,0,.65)!important}
.hero .hero-proof b{color:#fff!important}

/* ===== HERO v3 (Eliot 2026-07-28): stretch WIDER horizontally (was cramped in a narrow center column) + fit a longer headline ===== */
.hero .wrap{max-width:min(1560px,95vw)!important;padding-left:clamp(1.5rem,4vw,3.5rem)!important;padding-right:clamp(1.5rem,4vw,3.5rem)!important}
.hero h1{max-width:min(1320px,94vw)!important;font-size:clamp(2.5rem,6.6vw,5.9rem)!important;line-height:1.03!important}
.hero p{max-width:64ch!important}

/* ===== HERO CONTRAST SCRIM (permanent 2026-07-30): always-readable text on ANY hero photo, esp. bright/orange (Money Saving amber-on-sunset). Soft bottom-up gradient above image, below text. ===== */
.hero::before{content:"";position:absolute;inset:0;z-index:-1;pointer-events:none;background:linear-gradient(to top,rgba(8,10,13,.52) 0%,rgba(8,10,13,.24) 40%,rgba(8,10,13,.05) 72%,transparent 100%)}

/* the hazard band IS the divider; a section border-bottom on top of it draws a
   hairline between the section and the stripes (Wayne, 2026-08-06) */
.section:has(+ .cta-band){border-bottom:0}
.cta-band{border-top:0}

/* HEADER OVERFLOW (2026-08-06). A long business name pushed the nav + phone + CTA past the
   1220px wrap: "Gotham Restoration Group Inc" overflowed by 147px and its Get-a-Free-Quote
   button ran off the right edge of a 1440px viewport. Let the wordmark shrink instead of the
   CTA, and drop the duplicate header phone before anything can clip (the topbar still shows it). */
.site-header .wrap{gap:1rem;min-width:0;max-width:1400px}
.site-header .logo{flex:0 0.15 auto;min-width:0;overflow:hidden}
.site-header .logo-word{display:block;white-space:nowrap;overflow:hidden;text-overflow:clip;max-width:min(40vw,600px)}
/* On a phone the brand owns the row apart from the burger, so 30vw (117px at 390) cut
   "Teddy's Cleaning" to "Teddy'". Give it the row minus the burger + padding. */
/* 2026-08-09: 132px only reserved room for the burger. The new .btn-mobook
   (below 1300px, so always present at this width) needed room too -- found live
   via nav_check.js flagging a clipped wordmark on the light-template-demo site
   the moment the mobile book button was added. */
@media(max-width:760px){.site-header .logo-word{max-width:calc(100vw - 210px)}}
.site-header .nav{flex:0 0 auto;min-width:0}
.site-header .header-cta{flex:0 0 auto}
/* header-phone shown by default (2026-08-17, Wayne): number belongs next to the book button on every site, not hidden behind the topbar alone.
   2026-09-04: nav's own flex-shrink caused its rendered <a> links to overflow past its shrunk box (proven via getBoundingClientRect on Alta Vista) --
   nav no longer shrinks at all; the logo (overflow:hidden + safe text/image truncation above) absorbs 100% of any squeeze instead. */
@media(max-width:1320px){.site-header .nav{gap:1.05rem}.site-header .nav>a,.site-header .nav .has-drop>a{font-size:.875rem}}

/* HERO HEADLINE ON SAME-HUE PHOTOS (2026-08-06). A green accent word sat on a green lawn and
   was unreadable (Eliot on T.N.A). Scoped per-site via .hero-acc-neutral on <body>. */
.hero h1 .acc{color:#fff;text-shadow:0 2px 10px rgba(0,0,0,.55),0 1px 3px rgba(0,0,0,.5)}

/* Small hero copy needs its own shadow: on a bright hero photo the scrim alone is not
   enough (Eliot 2026-08-06, Eddie Jaguar sunlit canopy). */
.hero p,.hero .hero-tag,.hero .hero-proof{text-shadow:0 1px 8px rgba(0,0,0,.75),0 1px 2px rgba(0,0,0,.55)}

/* ---- MOBILE FIXES (2026-08-09, ported from ACBrise/Sarber real-client fixes) ----------
   Placed at the END of this file on purpose: HERO DOMINANCE/v3/v4 above are unconditional
   !important rules, so a same-specificity mobile override declared earlier in the
   cascade loses and silently never applies. Confirmed real on Sarber Construction: the
   hero rendered with the full desktop 7rem top padding + 88vh min-height on every phone,
   so the hero + its own CTA button could not fit one mobile screen without scrolling, on
   EVERY site built from this template, since day one -- this is not a one-off bug. */
.btn-mobook{display:none}
/* tap-to-call icon replaces the full phone number on mobile (2026-08-17, Wayne) -- no room for the full number in the mobile header, but the number must always be one tap away. */
.btn-callicon{display:none}
.mm-close{display:none}
@media(max-width:1300px){
  .btn-mobook{display:inline-flex;align-items:center;margin-right:1.1rem;
    padding:.7rem 1.05rem;font-size:.875rem;min-height:44px;white-space:nowrap}
  .site-header .header-cta{display:flex;align-items:center;gap:.9rem}
  /* those 2.5rem margins exist to clear the desktop nav, which is display:none here --
     left in place they reserve 80px of dead space the mobile header no longer needs, and
     with the call-icon added (2026-08-17) that was enough to push the burger off-screen
     on real logos/business names (Creative Homes: burger clipped to 8px visible). */
  .site-header .logo{margin-right:0}
  .site-header .header-cta{margin-left:0}
  .site-header .header-cta .btn-nav{display:none}
  .site-header .header-phone{display:none}
  .btn-callicon{display:inline-flex;align-items:center;justify-content:center;width:44px;height:44px;
    margin-right:.6rem;border:1px solid var(--line);border-radius:8px;color:var(--white);flex:none}
  .btn-callicon:hover,.btn-callicon:active{border-color:var(--accent);color:var(--accent-text)}
  .btn-callicon svg{width:19px;height:19px}
}
@media(max-width:720px){
  .site-header .header-cta{gap:.45rem}
  .btn-mobook{margin-right:.4rem;padding:.42rem .38rem;font-size:.875rem;letter-spacing:0}
  .btn-callicon{margin-right:.4rem}
  .burger{width:32px;height:32px;margin-left:.1rem}
  /* 2026-08-17 fix froze the logo at its natural width (flex:0 0 auto) to stop it crushing to
     a sliver -- but freezing it means when header-cta (book button + call icon + burger) needs
     more room than is left, there is NOTHING to shrink, and the whole row overflows off-screen
     instead: "Ironclad Contracting" (21 chars, an entirely normal business name) pushed the
     burger to x=411 on a 390px screen -- fully off-screen, unclickable, no way to open the menu
     (Arsen, 2026-09-17, real screenshot). flex-shrink with a min-width FLOOR does both jobs:
     it shrinks under real pressure (so the burger always stays on-screen) but never crushes
     past a legible minimum the way the old unbounded flex-shrink:.15 did. */
  .logo{flex:1 1 60px!important;min-width:60px!important;overflow:hidden!important}
  /* the wordmark fallback (no real logo yet) can still clip a long placeholder
     name at this width once burger+book both compete for room; a real logo
     image is unaffected since it sizes off .logo img, not this rule */
  .site-header .logo-word{font-size:1.05rem!important;max-width:100%!important;text-overflow:ellipsis!important}
  .mm-close{display:flex;align-items:center;justify-content:center;position:fixed;
    top:.6rem;right:.9rem;z-index:140;background:rgba(255,255,255,.10);border:0;border-radius:50%;
    color:var(--white);font-size:2rem;line-height:1;cursor:pointer;width:46px;height:46px}
  /* dvh so iOS Safari's URL bar cannot clip the menu or the hero */
  .mobile-menu{overflow-y:auto;-webkit-overflow-scrolling:touch;
    padding-top:5rem;padding-bottom:3rem;height:100vh;height:100dvh}
  /* Hero spacing rules used to live here, but this whole block is same-specificity and
     declared EARLIER than the "MOBILE HERO REFLOW" block near the true end of this file
     (2026-08-28b) -- that later block silently wins the cascade for every hero property, so
     editing anything hero-related here is a no-op in the real browser. Go edit the block
     after the .rev-src rule instead (search "MOBILE HERO REFLOW"). Confirmed exactly this
     shadowing bug live on Redbone Woodworks 2026-08-29 -- don't re-add hero rules here. */
  .modal{max-height:88vh;max-height:88dvh}
  .modal-veil{align-items:flex-start;padding:1rem .75rem}
  .modal .m-actions{position:sticky;bottom:0;background:var(--coal-2);
    padding:.9rem 0 .2rem;margin-top:.6rem;border-top:1px solid var(--line);z-index:5}
  .modal .m-inner,.modal form,.modal-inner{padding-bottom:.2rem}
}

/* Mobile menu: Services expands in place instead of a duplicate "Our Services" list below */
.mobile-menu .mm-toggle{background:none;border:0;width:100%;text-align:left;cursor:pointer;
  display:flex;align-items:center;justify-content:space-between;color:inherit;
  font-family:var(--font-display);font-size:clamp(1.8rem,7vw,2.7rem);line-height:1.1;
  padding:.35rem 0;border-bottom:1px solid var(--line)}
.mobile-menu .mm-caret{font-size:.6em;transition:transform .25s ease;opacity:.7;margin-left:.6rem}
.mobile-menu .mm-toggle.open .mm-caret{transform:rotate(180deg)}
.mobile-menu .mm-svc{display:none}
.mobile-menu .mm-svc.open{display:block}
.mobile-menu .mm-svc a{display:block;padding:.55rem 0 .55rem 1rem;font-weight:600;color:var(--mut);
  border-bottom:1px solid var(--line)}
.mobile-menu .mm-svc a:hover{color:var(--accent-text)}


/* ---------- reviews (real reviews, any source) - injected by populate_reviews.js ---------- */
.reviews{display:grid;grid-template-columns:repeat(3,1fr);gap:1.4rem}
@media(max-width:900px){.reviews{grid-template-columns:1fr 1fr}}
@media(max-width:640px){.reviews{grid-template-columns:1fr}}
.reviews:has(.rev-card:only-child){grid-template-columns:1fr;max-width:480px;margin:0 auto}
.rev-card{display:flex;flex-direction:column;background:var(--panel,#161a21);border:1px solid var(--line,rgba(255,255,255,.08));border-top:3px solid var(--accent);padding:1.9rem;transition:transform .25s ease,box-shadow .25s ease,border-color .25s ease}
.rev-card:hover{transform:translateY(-5px);box-shadow:0 22px 50px rgba(0,0,0,.45);border-color:var(--accent)}
.rev-card .stars{margin-bottom:1rem}
.rev-quote{font-size:1.02rem;line-height:1.6;flex:1;display:-webkit-box;-webkit-box-orient:vertical;-webkit-line-clamp:6;overflow:hidden}
.rev-quote.expanded{-webkit-line-clamp:unset;overflow:visible}
.rev-more{background:none;border:0;color:var(--accent-text);font-family:var(--font-mono,monospace);font-size:.875rem;letter-spacing:.1em;text-transform:uppercase;cursor:pointer;padding:.5rem 0 0;text-align:left}
.rev-meta{display:flex;justify-content:space-between;align-items:baseline;gap:1rem;margin-top:1.4rem;padding-top:1.1rem;border-top:1px solid var(--line,rgba(255,255,255,.08))}
.rev-author{font-family:var(--font-display,inherit);text-transform:uppercase;letter-spacing:.02em;font-size:1.05rem}
.rev-date{font-family:var(--font-mono,monospace);font-size:.875rem;letter-spacing:.14em;text-transform:uppercase;color:var(--accent-text);text-align:right;white-space:nowrap}
.rev-src{font-family:var(--font-mono,monospace);font-size:.875rem;letter-spacing:.16em;text-transform:uppercase;color:var(--mut-2,#8b93a1);text-align:center;margin-top:2rem}

/* MOBILE HERO REFLOW (2026-08-28, moved to end of file 2026-08-28b): placed HERE, after the
   HERO DOMINANCE/v3/v4 blocks above, on purpose -- those are unconditional !important rules
   declared later in the file than this used to be, so a same-specificity override placed
   earlier lost the cascade and silently never applied (measured live: .hero .wrap was still
   rendering min-height:742px/justify-content:center/padding-top:112px on a real phone-width
   viewport despite this exact block existing higher up in the file). Confirmed fixed only by
   moving it to the true end and re-measuring, not by assuming source order didn't matter. */
@media(max-width:760px){
  /* Spacing tuned live on Redbone Woodworks (2026-08-29, Wayne feedback): the old numbers
     packed tag+title+text+buttons+proof into one tight clump near the top. Two deliberate
     gaps -- tag-to-title and text-to-buttons -- push the buttons/rating proof down and give
     the title room, WITHOUT tying the hero to a fixed total height (a fixed px total only
     works for one specific headline/description length; these are content-length-agnostic
     margin bumps, so they hold up for any business's copy). */
  .hero{min-height:auto!important}
  .hero .wrap{min-height:auto!important;justify-content:flex-start!important;padding-top:calc(2.6rem + 30px)!important;padding-bottom:calc(2.8rem + 30px)!important}
  .hero .hero-tag{margin-bottom:calc(2.4rem + 35px)!important;font-size:.875rem!important}
  .hero h1{font-size:clamp(1.8rem,8.4vw,2.5rem)!important;line-height:1.05!important}
  .hero p{font-size:.94rem!important;margin:1.5rem auto 1.75rem!important}
  .hero-ctas{gap:.8rem;margin-top:35px}
  .hero .hero-proof{margin-top:2.1rem!important;font-size:.875rem!important}
}

/* ---- DESKTOP HERO VERTICAL DISTRIBUTION (2026-08-29, Wayne feedback on Redbone Woodworks)
   HERO DOMINANCE above centers the whole tag+title+text+buttons+proof block as one clump in
   the middle of the 88vh hero -- Wayne: "it's all like one big clump," wanted the location
   tag near the top and the buttons/rating pushed down instead. Two flex auto-margins split
   whatever slack the hero's 88vh min-height has into two gaps (above the title, above the
   buttons) -- desktop only, min-width matches where the mobile block above stops applying,
   since mobile's hero has no min-height slack (it's sized to content) and uses fixed margin
   bumps instead (see the block above). Placed at the true end of the file on purpose, same
   reason as MOBILE HERO REFLOW above: a same-specificity !important rule declared earlier
   silently loses to one declared later. */
@media(min-width:761px){
  .hero h1{margin-top:auto!important}
  .hero .hero-ctas{margin-top:auto!important}
}

/* CLS: reserves the JS-injected topbar+header's real height so the hero is not shoved down when site.js runs (was a ~0.14 CLS on every build).
   MUST equal topbar min-height + .site-header .wrap height (+1px border) at each breakpoint. If you change .site-header .wrap{height}, .topbar min-height, or the logo size that drives them, update these two values too. */
#siteHeaderPlaceholder{height:151px}
@media(max-width:560px){#siteHeaderPlaceholder{height:117px}}

/* 2026-09-27: on <=430px phones the header row (logo + callback + call icon + burger) overflowed and pushed
   the menu button off-screen. Tighten spacing, cap/wrap the logo, and drop the duplicate call icon (the
   full-width topbar right above already has tap-to-call). */
@media(max-width:430px){
  .site-header .header-cta{gap:.5rem}
  .btn-mobook{margin-right:0}
  .btn-callicon{width:38px;height:38px;margin-right:0}
  .btn-callicon svg{width:17px;height:17px}
  .site-header .logo{flex:0 1 auto;min-width:0}
  .site-header .logo img{max-width:118px;height:auto;max-height:40px}
  .site-header .logo-word{white-space:normal!important;max-width:9.5rem!important;line-height:1!important;text-overflow:clip!important;overflow:visible!important}
}

/* 2026-09-27 (template audit): fractional rating stars -- site.js renderStars() draws the real
   rating (4.3 -> 86% filled) on any .stars[data-rating]. */
.stars.stars-frac{position:relative;display:inline-block;white-space:nowrap;line-height:1}
.stars.stars-frac .s-off{opacity:.28}
.stars.stars-frac .s-on{position:absolute;left:0;top:0;width:var(--pct,100%);overflow:hidden;white-space:nowrap}
/* long-name wordmark short form: only shown when fitLogoWord() adds .lw-use-short (header only) */
.logo-word .lw-short{display:none}
.site-header .logo-word.lw-use-short .lw-full{display:none}
.site-header .logo-word.lw-use-short .lw-short{display:inline}

/* 2026-09-27 HEADER-FIT (site_gate standard block). Every rule here fixes a header bug that shipped:
   menu button pushed off-screen on phones, business name cut off with "...", call icon past the edge at
   tablet widths, nav/phone/CTA colliding on desktop. The topbar already shows tap-to-call everywhere. */
.site-header .logo-word{white-space:normal!important;max-width:15.5rem!important;line-height:.98!important;text-overflow:clip!important;overflow:visible!important}
.site-header .nav{flex:0 0 auto}
.site-header .logo{flex:0 1 auto;min-width:0}
@media(min-width:1301px){.site-header .wrap{max-width:1440px}}
@media(max-width:1640px) and (min-width:721px){.site-header .header-phone{display:none}}
@media(max-width:1300px){.site-header .header-cta{gap:.6rem}.btn-mobook{margin-right:0}}
@media(max-width:430px){
  .site-header .header-cta{gap:.5rem}
  .site-header .logo img{max-width:118px;height:auto;max-height:40px}
  .site-header .logo-word{max-width:9.5rem!important;line-height:1!important}
}

/* ==== 2026-09-27 QC ROUND (5 booked-call demos failed QC on the same template defects) ==== */
/* ghost watermark words (outlined, faint) behind CTA buttons and in sections: removed.
   build_draft.js also strips the elements; this is the belt-and-braces for old drafts. */
.giant,.giant-bg{display:none!important}
/* hero readability: a DARK gradient centred behind the copy (plus a base top/bottom scrim), so a
   bright photo can never wash out the subtitle. Verified >=4.5:1 on a pure-white test photo at
   390 and 1440. */
.hero .hero-bg::after{background:radial-gradient(ellipse 70% 68% at 50% 52%,rgba(9,11,15,.7) 0%,rgba(9,11,15,.6) 55%,rgba(9,11,15,.24) 100%),linear-gradient(180deg,rgba(9,11,15,.42) 0%,rgba(9,11,15,.32) 50%,rgba(9,11,15,.64) 100%)!important}
.hero h1,.hero p,.hero .hero-proof,.hero .hero-tag{text-shadow:0 1px 3px rgba(0,0,0,.85),0 2px 16px rgba(0,0,0,.55)!important}
/* hero rating line: "5.0 on Google (N reviews)" never wraps; the secondary text gets its own line on phones */
.hero-proof .hp-rate{white-space:nowrap;display:inline-flex;align-items:center;gap:.5rem}
.hero-proof .hp-rest{display:inline}
@media(max-width:560px){.hero .hero-proof{flex-direction:column;gap:.3rem}.hero-proof .hp-sep{display:none}}
/* rating badge (outside the review grid; the grid holds real reviews only) */
.rating-badge{display:flex;width:fit-content;max-width:100%;margin:0 auto 1.6rem;align-items:center;justify-content:center;flex-wrap:wrap;gap:.35rem .6rem;padding:.8rem 1.25rem;border:1px solid var(--line);background:var(--panel);color:var(--white);text-decoration:none;font-family:var(--font-mono);font-size:.875rem;letter-spacing:.04em}
.rating-badge .stars{color:var(--accent-text);letter-spacing:.12em}
.rating-badge b{font-size:1.05rem}
a.rating-badge:hover{border-color:var(--accent)}
/* generated icon mark + wordmark when research has no real logo */
.logo-mark{width:40px;height:40px;flex:none;display:block}
.logo-word.has-mark{padding-left:0!important}
.logo-word.has-mark::before{display:none}
.site-footer .logo-mark{width:46px;height:46px}
@media(max-width:899px){.site-header .logo-mark{width:34px;height:34px}.site-header .logo{gap:.55rem!important}}
/* callback modal: step bar clear of the close button, fallback (lead not sent) state */
.modal .m-steps{padding-right:3.2rem}
.m-fail .big{background:transparent;color:var(--accent-text);border:2px solid var(--accent)}
.btn-call-big{display:flex!important;justify-content:center;width:100%;font-size:1.12rem;padding:1.1rem 1rem;margin:1.1rem 0 .7rem}
.btn[disabled]{opacity:.7;cursor:progress}
/* text-only service cards (not enough distinct photos for one per service) */
.svc-card.no-img::before{transform:scaleX(1)}
.svc-card.no-img .svc-body{padding-top:2rem;min-height:12rem}
/* outlined (transparent-fill) heading words read as faint ghost text on phones and bright screens: solid accent instead */
.outline{color:var(--accent-text)!important;-webkit-text-stroke:0!important}
.svc-row:not(:has(.media)){grid-template-columns:auto 1fr}

/* ==== 2026-09-28 BUILD-FIX (Cardwell Roofing timed build) ==== */
/* header controls: nav_check needs >= 12px between the callback button and the menu button at every
   width <= 1300 (the gaps were .6rem/.5rem + a 1.6px burger margin = 9.6-10px). */
@media(max-width:1300px){.site-header .header-cta{gap:.85rem}.site-header .header-cta .burger{margin-left:0}}
@media(max-width:430px){.site-header .header-cta{gap:.8rem}}
/* DESIGNED HERO: no landscape photo wide enough for the home hero (and no stock) -> an intentional
   brand panel (accent glow + fine diagonal texture + blueprint grid + hazard band), never a flat dark block.
   build_draft.js adds .hero-designed to .hero-bg (and .bgimg-designed to an empty page-hero .bgimg). */
.hero .hero-bg.hero-designed,.page-hero .bgimg.bgimg-designed{background:
  radial-gradient(ellipse 60% 70% at 12% 8%,color-mix(in srgb,var(--accent) 42%,transparent) 0%,transparent 62%),
  radial-gradient(ellipse 55% 60% at 92% 96%,color-mix(in srgb,var(--accent) 28%,transparent) 0%,transparent 60%),
  repeating-linear-gradient(135deg,rgba(255,255,255,.035) 0 2px,transparent 2px 18px),
  linear-gradient(rgba(255,255,255,.045) 1px,transparent 1px) 0 0/72px 72px,
  linear-gradient(90deg,rgba(255,255,255,.045) 1px,transparent 1px) 0 0/72px 72px,
  linear-gradient(160deg,#18202b 0%,#0d1117 58%,#080a0e 100%)}
.hero .hero-bg.hero-designed::before{content:"";position:absolute;left:0;right:0;bottom:0;height:10px;z-index:1;background:repeating-linear-gradient(135deg,var(--accent) 0 16px,transparent 16px 32px);opacity:.9}
.hero .hero-bg.hero-designed::after{background:radial-gradient(ellipse 60% 55% at 50% 50%,rgba(8,10,14,.55) 0%,rgba(8,10,14,.15) 70%,rgba(8,10,14,0) 100%)!important}
.page-hero .bgimg.bgimg-designed{inset:0 0 0 40%;-webkit-mask-image:linear-gradient(90deg,transparent 0,#000 45%);mask-image:linear-gradient(90deg,transparent 0,#000 45%)}
/* a photo slot removed because no real photo exists: the remaining column takes the row */
.grid-2>:only-child{grid-column:1/-1;max-width:62rem}
.bvl-panel.on:not(:has(.bvl-media)){grid-template-columns:1fr}

/* ON-ACCENT CONTRAST GUARD (2026-09-28). Text/icons painted ON an accent fill (.btn-solid/.btn-red:
   the "View us on Google" review button, hero CTA, callback buttons; topbar, statband, cta-band,
   gallery captions, booking picks) used a fixed --on-accent that a later accent change never
   re-derived, so ~55 live pages read at 1.7-4.4:1 (dark ink on navy, light ink on green/orange).
   Derive it from the LIVE --accent: WCAG relative luminance Y in srgb-linear, then the template
   ink that clears 4.5:1 (light #f2f5f7 if Y<=.160, dark #0e1116 if Y>=.203), else pure white/black
   split at Y=.1791 (always >=4.58:1). Browsers without relative colour keep the hex fallback that
   build_draft.js sets by the same rule. */
@supports (color: color(from red srgb-linear clamp(0, calc((0.5 - r) * 10), 1) g b)) {
  :root{--on-accent:color(from var(--accent) srgb-linear calc(0.888 - 0.888 * clamp(0, calc(((0.2126 * r + 0.7152 * g + 0.0722 * b) - 0.16) * 100000), 1) + clamp(0, calc(((0.2126 * r + 0.7152 * g + 0.0722 * b) - 0.16) * 100000), 1) - clamp(0, calc(((0.2126 * r + 0.7152 * g + 0.0722 * b) - 0.1791) * 100000), 1) + 0.00439 * clamp(0, calc(((0.2126 * r + 0.7152 * g + 0.0722 * b) - 0.203) * 100000), 1)) calc(0.913 - 0.913 * clamp(0, calc(((0.2126 * r + 0.7152 * g + 0.0722 * b) - 0.16) * 100000), 1) + clamp(0, calc(((0.2126 * r + 0.7152 * g + 0.0722 * b) - 0.16) * 100000), 1) - clamp(0, calc(((0.2126 * r + 0.7152 * g + 0.0722 * b) - 0.1791) * 100000), 1) + 0.00561 * clamp(0, calc(((0.2126 * r + 0.7152 * g + 0.0722 * b) - 0.203) * 100000), 1)) calc(0.93 - 0.93 * clamp(0, calc(((0.2126 * r + 0.7152 * g + 0.0722 * b) - 0.16) * 100000), 1) + clamp(0, calc(((0.2126 * r + 0.7152 * g + 0.0722 * b) - 0.16) * 100000), 1) - clamp(0, calc(((0.2126 * r + 0.7152 * g + 0.0722 * b) - 0.1791) * 100000), 1) + 0.00803 * clamp(0, calc(((0.2126 * r + 0.7152 * g + 0.0722 * b) - 0.203) * 100000), 1)))}
}

/* ON-ACCENT CONTRAST GUARD, PART 2 (2026-09-28): the CTA band. Older builds painted the band paragraph
   in fixed dark ink rgba(14,17,22,.78) (1.6:1 on navy) and the band button text in raw --accent on the
   dark --coal button (1.7:1 on navy, 3.9:1 on red). Paragraph -> --on-accent (derived above). Button
   text -> --accent-text when the build defined it (already >= 4.5:1 on --coal), else the accent hue
   lifted to OKLCH lightness >= .70, which is >= 5.2:1 on #0e1116 for every hue. */
@supports (color: oklch(from red max(l, 0.7) c h)) and (color: color(from red srgb-linear r g b)) {
  .cta-band p{color:var(--on-accent)}
  .cta-band .btn-solid,.cta-band .btn-red{color:var(--accent-text, oklch(from var(--accent) max(l, 0.7) c h))}
  .cta-band .btn-ghost-light:hover,.cta-band .btn-light:hover,.cta-band .btn-ghost:hover,.cta-band .btn-ink:hover{color:var(--accent-text, oklch(from var(--accent) max(l, 0.7) c h))}
}

/* ON-ACCENT CONTRAST GUARD, PART 3 (2026-09-28): accent-coloured TEXT on the dark sections (eyebrow
   .kicker/.hs-tag labels, stars, .svc-link/.go links, .acc headline words, outline numerals, footer
   h4, form errors, hover states). Builds before 2026-09-27 paint these in raw --accent, 1.4-1.9:1 on
   navy/maroon. --g-at = --accent-text when the build defined it (derived >= 4.5:1 on every dark
   section), else the accent hue lifted to OKLCH lightness >= .70 (>= 5.2:1 on #0e1116-#202834).
   These families have no light-background sections (measured), so no darkened variant is applied;
   if one is added, set --g-at on it to oklch(from var(--accent) min(l, .46) c h) (>= 5.2:1 on
   #f2f5f7). Selectors = the rules that use raw --accent for text on the
   construction/concrete dark family; .hero h1 .acc (white on construction builds, accent on concrete) and the decorative .giant
   stroke are left alone; the .cta-band button rules are in PART 2. */
@supports (color: oklch(from red max(l, 0.7) c h)) and (color: color(from red srgb-linear r g b)) {
  :root{--g-at:var(--accent-text, oklch(from var(--accent) max(l, 0.7) c h))}
  .kicker{color:var(--g-at)}
  .acc,.red{color:var(--g-at)}
  .statement em{color:var(--g-at)}
  .btn-ink{color:var(--g-at)}
  .header-phone:hover{color:var(--g-at)}
  .mobile-menu a.mm-link:hover{color:var(--g-at)}
  .mobile-menu .mm-sub{color:var(--g-at)}
  .mobile-menu .mm-svc a:hover{color:var(--g-at)}
  .hs-tag{color:var(--g-at)}
  .hs-copy h1 .acc{color:var(--g-at)}
  .hero-proof .stars{color:var(--g-at)}
  .hs-plate b{color:var(--g-at)}
  .hero-strip b{color:var(--g-at)}
  .hero-tag{color:var(--g-at)}
  .svc-num{color:var(--g-at)}
  .svc-link{color:var(--g-at)}
  .bvl-specs .row b{color:var(--g-at)}
  .svc-row .idx{-webkit-text-stroke:1.5px var(--g-at)}
  .svc-row h3 a:hover{color:var(--g-at)}
  .go{color:var(--g-at)}
  .feat .n{-webkit-text-stroke:1.4px var(--g-at)}
  .step::before{color:var(--g-at)}
  .area-row .co{color:var(--g-at)}
  .tc-label{color:var(--g-at)}
  .stars{color:var(--g-at)}
  .crumbs::before{color:var(--g-at)}
  .crumbs a:hover{color:var(--g-at)}
  .spec-table td:first-child{color:var(--g-at)}
  .faq-item summary::after{color:var(--g-at)}
  .site-footer h4{color:var(--g-at)}
  .site-footer a:hover{color:var(--g-at)}
  .footer-bottom a:hover{color:var(--g-at)}
  .modal .m-sub a{color:var(--g-at)}
  .f-err{color:var(--g-at)}
  .m-back:hover{color:var(--g-at)}
  .m-confirm .row b{color:var(--g-at)}
  .rev-date{color:var(--g-at)}
  .rev-more{color:var(--g-at)}
  @media(max-width:1300px){.btn-callicon:hover,.btn-callicon:active{color:var(--g-at)}}
}

/* step indicator: keep "1 The Project / 2 Pick a Time / 3 Done" on ONE line on phones (2026-09-28) */
@media (max-width:520px){
  .m-steps{flex-wrap:nowrap;gap:.4rem;font-size:.875rem;letter-spacing:.08em}
  .m-steps span{gap:.3rem;white-space:nowrap}
  .m-steps span::before{width:12px}
}

/* 2026-09-29 (Arsen): tap-to-call icon stays in the mobile header. Later than the header-fit hides so it wins; the
   logo shrinks (never the icon or burger) so the menu button is always on screen (measured 320-768px). */
@media(max-width:430px){
  .site-header .logo{flex:0 1 auto!important;min-width:0!important}
  .site-header .header-cta{flex:none}
  .site-header .logo-word{max-width:100%!important}
  .site-header .logo img{max-width:min(118px,100%)!important;height:auto}
}
@media(max-width:340px){.site-header .btn-mobook{display:none}}
@media(max-width:1300px){.btn-callicon{display:inline-flex}}

/* 2026-09-29 reviews grid: every row fills for ANY review count (no half-empty last row).
   6-col base, cards span 2 (3 per row); a last row of 2 becomes 3+3, a last row of 1 spans all 6. */
.reviews{grid-template-columns:repeat(6,1fr)}
.reviews>.rev-card{grid-column:span 2}
.reviews>.rev-card:nth-child(3n+1):nth-last-child(2){grid-column:span 3}
.reviews>.rev-card:nth-child(3n+2):last-child{grid-column:span 3}
.reviews>.rev-card:nth-child(3n+1):last-child{grid-column:span 6}
.reviews:has(.rev-card:only-child){grid-template-columns:1fr}
.reviews:has(.rev-card:only-child)>.rev-card{grid-column:auto}
@media(max-width:900px){
  .reviews{grid-template-columns:1fr 1fr}
  .reviews>.rev-card,.reviews>.rev-card:nth-child(3n+1):nth-last-child(2),.reviews>.rev-card:nth-child(3n+2):last-child,.reviews>.rev-card:nth-child(3n+1):last-child{grid-column:span 1}
  .reviews>.rev-card:last-child:nth-child(odd){grid-column:span 2}
}
@media(max-width:640px){
  .reviews{grid-template-columns:1fr}
  .reviews>.rev-card,.reviews>.rev-card:last-child:nth-child(odd){grid-column:auto}
}

/* 2026-09-29: the Services entry is a <button class="mm-link mm-toggle">, so the a.mm-link-only uppercase rule never matched it */
.mobile-menu a.mm-link,.mobile-menu .mm-toggle{text-transform:uppercase!important}

/* phonebtn-desktop 2026-09-29: nav phone button on desktop (outline, icon + number); icon only where the number does not fit; mobile keeps the icon-only .btn-callicon */
@media(min-width:1121px){
  .site-header .header-phone{display:inline-flex;align-items:center;gap:.5rem;box-sizing:border-box;border:1px solid var(--line);border-radius:8px;padding:0 .95rem;min-height:44px;margin-right:.2rem;color:var(--white);font-size:.875rem;letter-spacing:.02em;background:transparent;white-space:nowrap}
  .site-header .header-phone svg{width:17px;height:17px;flex:none}
  .site-header .header-phone:hover,.site-header .header-phone:focus-visible{border-color:var(--accent);color:var(--accent-text)}
  .site-header .btn-callicon{display:none}
  .site-header .header-phone.hp-compact .hp-num{display:none}
  .site-header .header-phone.hp-compact{padding:0;width:44px;justify-content:center}
}
@media(min-width:1121px) and (max-width:1300px){
  .site-header .header-phone .hp-num{display:none}
  .site-header .header-phone{padding:0;width:44px;justify-content:center}
}

.footer-bottom{color:#b4bcc6}.footer-bottom a{color:#d6dce3;text-decoration:underline}
.a2p-page{background:var(--coal);color:var(--white);font-family:'Barlow',sans-serif}.a2p-page .a2p-wrap{max-width:760px;margin:0 auto;padding:56px 22px 72px;line-height:1.7;color:#d6dce3}.a2p-page h1{font-family:'Anton',sans-serif;font-weight:400;letter-spacing:.02em;text-transform:uppercase;color:#fff;font-size:2.4rem;margin:0 0 8px}.a2p-page h2{font-family:'Anton',sans-serif;font-weight:400;color:#fff;font-size:1.3rem;letter-spacing:.02em}.a2p-page .a2p-meta{color:#9aa4b0}.a2p-page .a2p-wrap a{color:var(--accent-text,#2dd4bf)}.a2p-page .site-header a,.a2p-page .site-footer a{color:inherit}.a2p-page input[type=text],.a2p-page input[type=tel],.a2p-page input[type=email]{background:var(--panel);border:1px solid var(--line);border-radius:8px;color:#fff;font:inherit;padding:12px!important;box-sizing:border-box}.a2p-page button[type=submit]{background:var(--accent,#14b8a6);color:#04141a;border:0;border-radius:8px;font:700 1rem 'Barlow',sans-serif;padding:14px 28px!important;cursor:pointer}.a2p-page p[style*='color:#666']{color:#9aa4b0!important}.a2p-page .a2p-fail{background:var(--panel);border-color:var(--accent)!important}.a2p-page .a2p-fail a{color:#04141a}
/* get-started: contained form card at every width */
.a2p-page .a2p-wrap{width:100%;box-sizing:border-box;max-width:720px;margin:0 auto;padding:48px 24px 56px}
.a2p-page .a2p-wrap input[type=text],.a2p-page .a2p-wrap input[type=tel],.a2p-page .a2p-wrap input[type=email]{width:100%;box-sizing:border-box}
.a2p-page .a2p-wrap a{color:var(--accent-text,#2dd4bf)}

/* 2026-09-29 MOBILE CALL ICON 44x44 (tap target). The <=430px rule made it 38x38; restore 44x44 and give the logo the slack. */
@media(max-width:430px){
  .site-header .header-cta .btn-callicon{width:44px;height:44px;min-width:44px;flex:none;margin:0;box-sizing:border-box}
  .site-header .header-cta .btn-callicon svg{width:19px;height:19px}
  .site-header .wrap{gap:.5rem}
  .site-header .header-cta{gap:.4rem}
}
@media(max-width:360px){
  .site-header .header-cta .btn-mobook{max-width:78px;white-space:normal;text-align:center;line-height:1.05;padding:.3rem .35rem}
}
/* 2026-09-29 header fit after type floor: keep the small callback label (tf-keep) so the logo name is not cut to "HUMBLE" on phones */


/* 2026-09-29 humble header: FULL business name at every width, one header row.
   Desktop/tablet: one line up to 26rem; below 1024 it may wrap to two lines ("HUMBLE EXTERIOR / CLEANING"), never truncated.
   Phones: the text callback button is dropped below 431px (44px call icon + burger menu 'Request a Callback' + hero buttons cover it),
   so the wordmark gets the room; no header text is under 14px. */
.site-header .logo-word{max-width:26rem!important}
@media(max-width:1023px){.site-header .logo-word{max-width:15.5rem!important;font-size:1.25rem!important;line-height:1!important}}
@media(max-width:430px){
  .site-header .header-cta .btn-mobook{display:none!important}
  .site-header .logo-word{max-width:100%!important;font-size:1.0625rem!important;line-height:1.02!important}
  .site-header .logo{flex:1 1 auto!important;min-width:0!important}
  .site-header .header-cta{flex:none}
  .site-header .header-cta .burger,.burger{width:44px;height:44px;margin-left:0}
  .site-header .header-cta .btn-callicon,.btn-callicon{width:44px;height:44px}
}
@media(max-width:340px){.site-header .logo-word{font-size:.9375rem!important}}
@media(max-width:560px){.site-header .wrap{height:72px}#siteHeaderPlaceholder{height:110px}}
