  :root{
    --sf-ink:#0f1c26; --sf-blue:#1f6fb2; --sf-blue-d:#17578c; --sf-navy:#0d2942;
    --sf-amber:#f0972a; --sf-amber-d:#d97f14; --sf-line:#e2e9ef;
    --sf-bg:#fff; --sf-mut:#5a6b78; --sf-soft:#f4f9fd; --sf-rad:14px; --sf-max:1180px;
    --sf-sh-1:0 1px 2px rgba(13,41,66,.06),0 2px 8px rgba(13,41,66,.05);
    --sf-sh-2:0 8px 30px rgba(13,41,66,.10);
    --sf-sh-3:0 18px 50px rgba(13,41,66,.16);
    --sf-s:.5rem; --sf-m:1rem; --sf-l:2rem; --sf-xl:4rem;
  }
  *{box-sizing:border-box}
  html{-webkit-text-size-adjust:100%}
  body{font:17px/1.7 system-ui,-apple-system,"Segoe UI",Roboto,Helvetica,Arial,sans-serif;
    color:var(--sf-ink);background:var(--sf-bg);margin:0;-webkit-font-smoothing:antialiased;
    overflow-x:hidden}
  /* Nothing may force horizontal scroll on a phone. Long slugs, wide tables and oversized
     media are the usual culprits; this makes the failure impossible rather than unlikely. */
  img,video,table,pre{max-width:100%}
  img,video{height:auto}
  a{overflow-wrap:anywhere}
  .sf-wrap{max-width:var(--sf-max);margin:0 auto;padding:0 1.25rem}
  .sf-btn{display:inline-flex;align-items:center;gap:.5rem;padding:.95rem 1.6rem;border-radius:10px;
    font-weight:800;text-decoration:none;border:0;cursor:pointer;letter-spacing:.01em;
    transition:transform .15s ease,box-shadow .15s ease,background .15s ease}
  .sf-btn--primary{background:var(--sf-amber);color:#1a1200;box-shadow:0 6px 18px rgba(240,151,42,.35)}
  .sf-btn--primary:hover{background:var(--sf-amber-d);transform:translateY(-2px);box-shadow:0 10px 26px rgba(240,151,42,.42)}
  .sf-btn--ghost{background:rgba(255,255,255,.08);color:#fff;border:1.5px solid rgba(255,255,255,.55);backdrop-filter:blur(4px)}
  .sf-btn--ghost:hover{background:rgba(255,255,255,.18);transform:translateY(-2px)}
  .sf-h2{font-size:clamp(1.5rem,2.6vw,2rem);margin:0 0 .5rem;color:var(--sf-navy);letter-spacing:-.02em}
  h1{font-size:clamp(2rem,5vw,3.1rem);line-height:1.12;margin:0 0 .5em;color:var(--sf-navy);letter-spacing:-.03em;font-weight:800}
  h2{font-size:clamp(1.4rem,3vw,1.95rem);margin:1.8em 0 .5em;color:var(--sf-navy);letter-spacing:-.02em;font-weight:750}
  h3{font-size:1.13rem;margin:1.4em 0 .4em;color:var(--sf-navy);font-weight:700}
  p,li{margin:0 0 1.05em;max-width:72ch}
  a{color:var(--sf-blue)}
  strong,b{color:var(--sf-navy)}
  /* Section rhythm: alternating surfaces so the page reads as a site, not a document. */
  .sf-band{padding:var(--sf-xl) 0}
  .sf-band--soft{background:var(--sf-soft);border-block:1px solid var(--sf-line)}
  .sf-eyebrow{display:inline-block;font-size:.75rem;font-weight:800;letter-spacing:.12em;
    text-transform:uppercase;color:var(--sf-blue);margin:0 0 .5rem}
  .sf-lede{font-size:1.08rem;color:var(--sf-mut);max-width:62ch;margin:0 0 2rem}
  .skip{position:absolute;left:-9999px}.skip:focus{left:8px;top:8px;background:#fff;padding:10px;z-index:99}
  .sf-header{background:var(--sf-bg);border-bottom:1px solid var(--sf-line);position:sticky;top:0;z-index:50}
  /* The quote buttons scroll to the embedded form. The header is sticky, so without a
     scroll margin the form's heading lands underneath it and the click looks like it did
     nothing - which is the exact complaint this fix answers.
     --sf-header-h is MEASURED from the real header at the bottom of this page; 88px is only
     the fallback before that runs. It was a flat 88px guess until 2026-08-24, which was too
     short on a phone, where .sf-header__row wraps to two lines and the header is taller. */
  #sfia-quote{scroll-margin-top:calc(var(--sf-header-h, 88px) + 12px)}
  @media (prefers-reduced-motion:no-preference){html{scroll-behavior:smooth}}

  /* The trades-mesh block: one contextual hand-off to the drywall trade. Set apart from the
     body copy so it reads as a related note, not as another paragraph of our own sales copy. */
  .sf-partner{margin:2.5rem 0 0;padding:1.4rem 1.5rem;background:var(--sf-soft);
    border:1px solid var(--sf-line);border-left:3px solid var(--sf-blue);border-radius:var(--sf-rad)}
  .sf-partner .sf-h2{font-size:1.15rem;margin:0 0 .4rem}
  .sf-partner p{margin:0;color:var(--sf-mut);font-size:.97rem;max-width:68ch}
  .sf-partner a{font-weight:700}
  .sf-header__row{display:flex;align-items:center;justify-content:space-between;gap:1rem;padding:.7rem 1.1rem}
  /* Wordmark lockup - reads as a considered brand, not a missing asset. Swapped wholesale
     the moment biz.logo_url is set. */
  .sf-logo{display:inline-flex;align-items:center;gap:.6rem;text-decoration:none;line-height:1}
  .sf-logo__mark{display:inline-flex;align-items:center;justify-content:center;width:38px;height:38px;
    border-radius:10px;background:linear-gradient(140deg,var(--sf-navy),var(--sf-blue));
    color:#fff;font-weight:800;font-size:.95rem;letter-spacing:.02em;
    box-shadow:0 4px 12px rgba(13,41,66,.22)}
  .sf-logo__type{display:flex;flex-direction:column;gap:.12rem}
  .sf-logo__lead{font-size:.72rem;font-weight:700;letter-spacing:.09em;text-transform:uppercase;color:var(--sf-mut)}
  .sf-logo__accent{font-size:1.12rem;font-weight:800;letter-spacing:-.02em;color:var(--sf-navy)}
  .sf-logo:hover .sf-logo__accent{color:var(--sf-blue)}
  @media(max-width:520px){.sf-logo__lead{display:none}}
  /* 2026-08-22 Dustin: "make the main menu a bit more dense". Tighter gap + slightly smaller
     type so seven items sit comfortably instead of sprawling across the header. */
  .sf-nav{display:flex;gap:.62rem}
  .sf-nav a{color:var(--sf-ink);text-decoration:none;font-weight:600;font-size:.94rem}
/* Mega-menu (SFIA_SITE_STRUCTURE_SITEMAP.md s3). CSS-only: hover + focus-within, so it works
   with no JavaScript and stays keyboard accessible. Crawlers see every link in the markup
   regardless of hover state - that is the point of putting the silo in the header. */
.sf-mega{position:relative}
.sf-mega>a{display:inline-flex;align-items:center;gap:.25rem}
.sf-mega>a::after{content:"";border:.3rem solid transparent;border-top-color:currentColor;margin-top:.25rem}
/* 2026-08-22 Dustin: "the drop down window not so wide they are massive". The panel was a free
   flex row with a 1.6rem gap and 11rem columns, so a 3-column silo spanned ~40rem. Capped and
   tightened; max-width keeps it inside the viewport on small laptops instead of overflowing. */
.sf-mega__panel{position:absolute;top:100%;left:50%;transform:translateX(-50%);display:none;
  background:#fff;border:1px solid var(--sf-line);border-radius:10px;padding:.8rem .9rem;
  box-shadow:0 14px 40px rgba(10,22,40,.14);z-index:60;gap:1rem;
  max-width:min(34rem,calc(100vw - 2rem))}
.sf-mega:hover .sf-mega__panel,.sf-mega:focus-within .sf-mega__panel{display:flex}
/* CLICK MUST WORK, NOT JUST HOVER (Dustin reported it twice). The top-level item is a LINK,
   so clicking it navigates - which is correct for the label and useless as a disclosure. The
   caret is therefore shown on desktop as well: click the WORD to go to the hub page, click the
   CARET to open the panel. Hover still opens it for anyone who prefers that. */
/* inline-flex + nowrap: as a plain inline-block the caret wrapped to a second line under
   every menu item and made the whole header two rows tall. */
.sf-mega{position:relative;display:inline-flex;align-items:center;white-space:nowrap}
.sf-header__cta .sf-btn{white-space:nowrap}
.sf-mega__caret{display:inline-block;flex:0 0 1.35rem;width:1.35rem;height:1.35rem;cursor:pointer;
  position:relative;margin-left:.05rem;border-radius:4px}
/* 2026-08-22: the caret MEASURED 22x22 on desktop -- half the 44px touch minimum and under even
   the WCAG 2.2 AA 24px floor, which is why it read as "the menu does not work". This grows the
   HIT AREA to 44px without changing the arrow or the nav layout (the box stays 1.35rem). */
.sf-mega__caret::before{content:"";position:absolute;top:50%;left:50%;
  width:44px;height:44px;transform:translate(-50%,-50%)}
.sf-mega__caret::after{content:"";position:absolute;top:50%;left:50%;width:.42rem;height:.42rem;
  border-right:2px solid currentColor;border-bottom:2px solid currentColor;color:var(--sf-ink);
  transform:translate(-50%,-70%) rotate(45deg);transition:transform .18s ease}
.sf-mega__tog:checked ~ .sf-mega__caret::after{transform:translate(-50%,-30%) rotate(225deg)}
.sf-mega__caret:hover{background:rgba(13,41,66,.07)}
.sf-mega__tog:focus-visible ~ .sf-mega__caret{outline:2px solid var(--sf-blue);outline-offset:1px}
/* Clicking the caret pins the panel open; hover still works untouched. */
.sf-mega__tog:checked ~ .sf-mega__panel{display:flex;visibility:visible;opacity:1;pointer-events:auto;}
/* The link's own ::after arrow would now be a second chevron. */
.sf-mega>a::after{display:none}
.sf-mega__col{min-width:8.6rem}
.sf-mega__col b{display:block;font-size:.72rem;letter-spacing:.06em;text-transform:uppercase;
  color:var(--sf-mut);margin:0 0 .45rem}
.sf-mega__col a{display:block;padding:.22rem 0;font-weight:500;white-space:nowrap}
.sf-mega__col a:hover{color:var(--sf-blue)}
/* ---- MOBILE / TABLET NAV ------------------------------------------------------------
   Before 2026-08-02 the mega panels were display:block below 900px, so all 63 header links
   rendered expanded and stacked ABOVE the page content — a visitor had to scroll past the
   entire site map to reach the first sentence. Now: a CSS-only hamburger reveals the SEVEN
   top-level destinations, and the sub-panels collapse. The links stay in the DOM (crawlers
   still see the full silo); they are simply not shown until asked for. */
.sf-burger__btn{display:none;flex-direction:column;justify-content:center;gap:5px;
  width:46px;height:46px;padding:11px;cursor:pointer;border-radius:9px;border:1px solid var(--sf-line)}
.sf-burger__btn span{display:block;height:2px;background:var(--sf-navy);border-radius:2px;transition:.2s}
.sf-burger:checked ~ .sf-burger__btn span:nth-child(1){transform:translateY(7px) rotate(45deg)}
.sf-burger:checked ~ .sf-burger__btn span:nth-child(2){opacity:0}
.sf-burger:checked ~ .sf-burger__btn span:nth-child(3){transform:translateY(-7px) rotate(-45deg)}
@media(max-width:900px){
  .sf-header__row{flex-wrap:wrap;gap:.6rem}
  .sf-burger__btn{display:flex;order:3}
  .sf-nav{display:none;order:4;flex-basis:100%;flex-direction:column;gap:0;
    border-top:1px solid var(--sf-line);margin-top:.4rem;padding-top:.4rem}
  .sf-burger:checked ~ .sf-nav{display:flex}
  /* Sub-panels are hidden until the caret is tapped. They must be REACHABLE though: this
     block is width-gated, and a narrow window on a normal laptop lands here, so if the only
     escape hatch lived in the (hover:none) block the whole silo would still be a dead end at
     this size. The caret rules are therefore repeated in both branches deliberately. */
  .sf-mega__panel{display:none}
  .sf-mega:hover .sf-mega__panel{display:none}
  /* ABSOLUTE, not a flex sibling. As a flex item the 48px caret was pushed off the right
     edge of the drawer and clipped by body{overflow-x:hidden} - present in the DOM, and
     untappable. Anchored to .sf-mega (position:relative) it cannot be pushed anywhere. */
  .sf-mega{width:100%;display:block}
  .sf-mega>a{padding-right:52px}
  .sf-mega>a::after{display:none}
  .sf-mega__caret{display:block;position:absolute;right:0;top:0;width:48px;height:48px;
    cursor:pointer;z-index:2}
  .sf-mega__caret::after{content:"";position:absolute;top:50%;left:50%;width:.6rem;height:.6rem;
    border-right:2.5px solid var(--sf-navy);border-bottom:2.5px solid var(--sf-navy);
    transform:translate(-50%,-70%) rotate(45deg);transition:transform .2s ease}
  .sf-mega__tog:checked ~ .sf-mega__caret::after{transform:translate(-50%,-30%) rotate(225deg)}
  .sf-mega__tog:focus-visible ~ .sf-mega__caret{outline:2px solid var(--sf-blue);outline-offset:-2px}
  .sf-mega__tog:checked ~ .sf-mega__panel,
  .sf-mega:focus-within .sf-mega__panel{display:flex;visibility:visible;opacity:1;pointer-events:auto;position:static;transform:none;
    border:0;box-shadow:none;padding:.2rem 0 .8rem 1rem;flex-direction:column;gap:.9rem;
    flex-basis:100%}
  /* 48px tap targets - the desktop rule was ~24px, below the 44px accessibility minimum. */
  .sf-nav a,.sf-mega>a{display:flex;align-items:center;min-height:48px;padding:.2rem .1rem;
    border-bottom:1px solid var(--sf-line);white-space:normal}
  .sf-mega>a::after{margin-left:auto}
  .sf-header__cta{order:2;margin-left:auto}
}
@media(max-width:600px){
  .sf-header__cta .sf-btn{padding:.7rem 1rem;font-size:.9rem}
  .sf-hero__cta .sf-btn{width:100%;justify-content:center}
  .sf-stats{gap:1.2rem}
  .sf-stat{flex:1 1 40%}
}
  .sf-header__cta{display:flex;align-items:center;gap:.8rem}.sf-tel{font-weight:800;color:var(--sf-blue);text-decoration:none}
  .sf-crumb{font-size:.85rem;color:var(--sf-mut);padding:.7rem 0 0}.sf-crumb a{color:var(--sf-blue);text-decoration:none}
  /* Hero: layered depth instead of a flat gradient. The diagonal cell pattern is a nod to
     closed-cell foam structure and is pure CSS - no image request, nothing to 404, and it
     costs nothing on a site that has no photography yet. */
  .sf-hero{position:relative;overflow:hidden;color:#fff;padding:clamp(3rem,7vw,5.5rem) 0 clamp(3rem,6vw,4.5rem);
    background:linear-gradient(150deg,#0b2438 0%,var(--sf-navy) 45%,var(--sf-blue-d) 100%)}
  .sf-hero::before{content:"";position:absolute;inset:0;opacity:.16;
    background-image:radial-gradient(circle at 1px 1px,rgba(255,255,255,.9) 1px,transparent 0);
    background-size:22px 22px}
  .sf-hero::after{content:"";position:absolute;top:-30%;right:-10%;width:60%;height:160%;
    background:radial-gradient(closest-side,rgba(240,151,42,.28),transparent 70%);pointer-events:none}
  .sf-hero>*{position:relative;z-index:1}
  .sf-hero h1{color:#fff;max-width:20ch}
  .sf-hero__sub{font-size:clamp(1.05rem,1.6vw,1.22rem);opacity:.94;margin:0 0 1.8rem;max-width:58ch;line-height:1.6}
  .sf-hero__cta{display:flex;gap:.8rem;flex-wrap:wrap;align-items:center}
  /* Stat strip - every figure is REAL, from the StatCan-derived demand data. No invented proof. */
  .sf-stats{display:flex;flex-wrap:wrap;gap:2.4rem;margin:2.6rem 0 0;padding:1.6rem 0 0;
    border-top:1px solid rgba(255,255,255,.18)}
  .sf-stat b{display:block;font-size:clamp(1.5rem,3vw,2.1rem);font-weight:800;line-height:1;letter-spacing:-.02em}
  .sf-stat span{display:block;font-size:.82rem;opacity:.8;margin-top:.35rem;letter-spacing:.03em}
  .sf-trust{background:var(--sf-soft);border-bottom:1px solid var(--sf-line)}
  .sf-trust__row{display:flex;gap:.6rem;flex-wrap:wrap;padding:.85rem 1.25rem;justify-content:center;align-items:center}
  .sf-chip{background:var(--sf-bg);border:1px solid var(--sf-line);border-radius:99px;
    padding:.4rem 1rem;font-size:.83rem;font-weight:700;color:var(--sf-navy);box-shadow:var(--sf-sh-1)}
  main{padding:var(--sf-xl) 0 2rem}
  /* Inner-page article typography. 228 of 229 pages render through page.html, so this is where
     most of the site actually lives - it was plain prose with no rhythm. */
  article>p:first-of-type{font-size:1.15rem;line-height:1.65;color:#2b3d4c}
  article h2{padding-top:.4rem;border-top:1px solid var(--sf-line);margin-top:2.4em}
  article h2:first-of-type{border-top:0;padding-top:0}
  article ul,article ol{padding-left:1.2rem}
  article li{margin-bottom:.5em}
  article li::marker{color:var(--sf-blue)}
  /* A paragraph that opens with bold text is a key fact in this corpus - give it weight. */
  article p>strong:first-child{color:var(--sf-navy)}
  .sf-grid{display:grid;grid-template-columns:minmax(0,1fr) 320px;gap:3rem;align-items:start}
  @media(max-width:960px){.sf-grid{grid-template-columns:1fr;gap:2rem}}
  aside .sf-card{padding:1.25rem}
  aside .sf-card h2{font-size:1rem;margin:0 0 .6rem;border:0;padding:0;
    text-transform:uppercase;letter-spacing:.07em;color:var(--sf-mut)}
  aside .sf-card p{margin:.45rem 0;font-size:.93rem}
  aside .sf-card a{text-decoration:none;font-weight:600}
  aside .sf-card a:hover{text-decoration:underline}
  aside .sf-card::after{content:none}
  .sf-faq__item{border:1px solid var(--sf-line);border-radius:10px;padding:.9rem 1.1rem;
    margin:0 0 .6rem;background:#fff;box-shadow:var(--sf-sh-1)}
  .sf-faq__item summary{cursor:pointer;font-weight:700;color:var(--sf-navy)}
  .sf-faq__item[open]{border-color:#c2d8ea}
  .sf-cta{background:linear-gradient(140deg,#0b2438,var(--sf-navy) 60%,var(--sf-blue-d));color:#fff;margin-top:var(--sf-xl)}
  .sf-cta__row{padding:2.2rem 0}
  .sf-cta__hook{font-size:clamp(1.15rem,2.2vw,1.5rem);font-weight:750;letter-spacing:-.01em}
  /* Icons: a single inline SVG sprite. UI only - conveys nothing that isn't true. */
  .sf-ico{width:26px;height:26px;flex:0 0 26px;stroke:var(--sf-blue);fill:none;stroke-width:1.7;
    stroke-linecap:round;stroke-linejoin:round}
  .sf-ico--lg{width:34px;height:34px;flex-basis:34px}
  /* ---- MEDIA LAYER -------------------------------------------------------------
     Slots stay dormant until a real file with a complete manifest row exists, so the
     page never renders a broken image or an empty frame. width/height are always
     emitted to reserve space and avoid layout shift. */
  .sf-hero--img{padding:0}
  .sf-hero__media{position:relative;min-height:clamp(340px,46vw,520px);display:flex;align-items:flex-end}
  .sf-hero__media img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;z-index:0}
  .sf-hero__media::after{content:"";position:absolute;inset:0;z-index:1;
    background:linear-gradient(180deg,rgba(11,36,56,.42) 0%,rgba(11,36,56,.72) 55%,rgba(11,36,56,.90) 100%)}
  .sf-hero__media>.sf-wrap{position:relative;z-index:2;padding-top:3.5rem;padding-bottom:3rem;width:100%}
  .sf-figure{margin:2rem 0;border-radius:var(--sf-rad);overflow:hidden;box-shadow:var(--sf-sh-2);background:var(--sf-soft)}
  .sf-figure img{display:block;width:100%;height:auto}
  .sf-figure figcaption{font-size:.85rem;color:var(--sf-mut);padding:.7rem 1rem;background:#fff;border-top:1px solid var(--sf-line)}
  .sf-gallery{display:grid;grid-template-columns:repeat(3,1fr);gap:.9rem;margin:2rem 0}
  @media(max-width:820px){.sf-gallery{grid-template-columns:1fr 1fr}}
  .sf-gallery img{display:block;width:100%;height:100%;aspect-ratio:4/3;object-fit:cover;
    border-radius:10px;box-shadow:var(--sf-sh-1)}
  .sf-video{margin:2rem 0;border-radius:var(--sf-rad);overflow:hidden;box-shadow:var(--sf-sh-2);background:#0b2438}
  .sf-video video{display:block;width:100%;height:auto}
  .sf-card__thumb{display:block;width:100%;aspect-ratio:16/10;object-fit:cover;border-radius:10px;margin-bottom:.9rem}
  /* Social: brand marks are FILLED shapes, so they override the stroked .sf-ico defaults.
     Only profiles that are non-empty in the brand config render - the parked BC/SK/ON pages
     must never be linked until that province is genuinely live. */
  .sf-soc{display:flex;gap:.6rem;align-items:center;margin:.4rem 0 0}
  .sf-soc a{display:inline-flex;align-items:center;justify-content:center;width:38px;height:38px;
    border-radius:9px;background:rgba(255,255,255,.10);border:1px solid rgba(255,255,255,.22);
    transition:background .15s ease,transform .15s ease,border-color .15s ease}
  .sf-soc a:hover{background:rgba(255,255,255,.20);border-color:rgba(255,255,255,.45);transform:translateY(-2px)}
  .sf-soc svg{width:19px;height:19px;fill:#fff;stroke:none}
  /* The sidebar holds two ~320px cards and nothing else, so it must be a FIXED track.
     design v2 shipped it as `1.15fr .85fr`, which handed it ~42% of a 1180px wrap (~425px)
     for ~320px of content and squeezed the article to ~575px - the body copy read narrow
     and left-shifted with a dead gutter running the full height of every inner page.
     Back to a fixed track (the v1 value), with minmax so it can shrink before it wraps. */
  .sf-grid{display:grid;grid-template-columns:minmax(0,1fr) minmax(260px,320px);gap:2.6rem;align-items:start}
  @media(max-width:960px){.sf-grid{grid-template-columns:1fr;gap:2rem}}
  /* WHAT WE SPRAY band. Two columns of grouped applications; each row is a linked service
     name plus its organic term stack. Collapses to one column on tablet and below. */
  /* Top-of-page lead capture: copy left, form right, stacking on tablet. */
  .sf-quicklead{padding:2.6rem 0;background:var(--sf-soft);border-bottom:1px solid var(--sf-line)}
  .sf-quicklead .sf-wrap{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1fr);gap:2.4rem;align-items:start}
  @media(max-width:900px){.sf-quicklead .sf-wrap{grid-template-columns:1fr;gap:1.4rem}}
  .sf-quicklead__intro .sf-lede{margin-bottom:0}
  .sf-quicklead__intro h2{margin-top:.2rem}
  .sf-apps{padding:var(--sf-xl) 0;background:var(--sf-soft);border-block:1px solid var(--sf-line)}
  .sf-apps__group{margin:0 0 2.2rem}
  .sf-apps__group:last-child{margin-bottom:0}
  .sf-apps h3{font-size:1.05rem;margin:0 0 .25rem;color:var(--sf-navy);
    text-transform:uppercase;letter-spacing:.06em;font-size:.82rem}
  .sf-apps__lead{color:var(--sf-mut);margin:0 0 .9rem;max-width:80ch;font-size:.97rem}
  .sf-apps__list{list-style:none;padding:0;margin:0;display:grid;
    grid-template-columns:repeat(2,minmax(0,1fr));gap:.55rem 2.2rem}
  @media(max-width:860px){.sf-apps__list{grid-template-columns:1fr}}
  .sf-apps__list li{margin:0;padding:.5rem 0;border-top:1px solid var(--sf-line);
    font-size:.93rem;line-height:1.55;color:var(--sf-mut);max-width:none}
  .sf-apps__list a{text-decoration:none;font-weight:700}
  .sf-apps__list a:hover{text-decoration:underline}
  .sf-apps__list b{color:var(--sf-navy)}
  .sf-seg,.sf-rel,.sf-area,.sf-cost,.sf-faq,.sf-how{padding:var(--sf-xl) 0}
  .sf-seg__grid,.sf-rel__grid{display:grid;grid-template-columns:repeat(4,1fr);gap:1.1rem}
  @media(max-width:820px){.sf-seg__grid,.sf-rel__grid{grid-template-columns:1fr 1fr}}
  @media(max-width:480px){.sf-seg__grid,.sf-rel__grid{grid-template-columns:1fr}}
  /* Cards: real cards - icon, lift on hover, arrow affordance. Previously a bordered box of text. */
  .sf-card{position:relative;display:block;background:#fff;border:1px solid var(--sf-line);
    border-radius:var(--sf-rad);padding:1.5rem 1.35rem 1.6rem;text-decoration:none;color:var(--sf-ink);
    box-shadow:var(--sf-sh-1);transition:transform .18s ease,box-shadow .18s ease,border-color .18s ease}
  .sf-card:hover{border-color:#c2d8ea;transform:translateY(-3px);box-shadow:var(--sf-sh-2)}
  .sf-card h3{margin:.85rem 0 .35rem;color:var(--sf-navy);font-size:1.08rem}
  .sf-card p{margin:0;font-size:.9rem;color:var(--sf-mut);line-height:1.55}
  .sf-card__ico{display:inline-flex;align-items:center;justify-content:center;width:46px;height:46px;
    border-radius:12px;background:linear-gradient(140deg,#eaf3fa,#dcebf7);border:1px solid #d3e5f3}
  .sf-card::after{content:"\2192";position:absolute;right:1.2rem;bottom:1.15rem;color:var(--sf-blue);
    font-weight:800;opacity:0;transform:translateX(-4px);transition:opacity .18s ease,transform .18s ease}
  .sf-card:hover::after{opacity:1;transform:translateX(0)}
  /* Feature row - icon + copy, for "why" style sections that would otherwise be bullet lists. */
  .sf-feat{display:grid;grid-template-columns:repeat(3,1fr);gap:1.6rem}
  @media(max-width:820px){.sf-feat{grid-template-columns:1fr}}
  .sf-feat__item{display:flex;gap:.9rem;align-items:flex-start}
  .sf-feat__item h3{margin:0 0 .25rem;font-size:1.02rem}
  .sf-feat__item p{margin:0;font-size:.92rem;color:var(--sf-mut)}
  .sf-faq__item{border-bottom:1px solid var(--sf-line);padding:.7rem 0}
  .sf-faq__item summary{font-weight:700;cursor:pointer;color:var(--sf-navy)}
  .sf-area__cities{list-style:none;padding:0;display:flex;flex-wrap:wrap;gap:.5rem;margin:0}
  .sf-area__cities a{color:var(--sf-blue);text-decoration:none;font-size:.9rem}
  /* --wide: the homepage coverage block, where each entry is the full "Spray Foam Insulation
     <City>" phrase rather than a bare city name (2026-08-13). 54 long entries in a wrapping
     flex row read as a wall; multi-column runs them alphabetically DOWN each column, which is
     how a directory is actually scanned. `columns` rather than grid on purpose - grid flows
     across rows, which would break the A-Z reading order. Only the homepage uses this, so the
     short "Where we cover this" lists on the pillar pages are untouched. */
  /* 2026-08-23 Dustin: "improve the list function and looks", alongside restoring the full
     "Spray Foam Insulation <City>" anchor. CSS `columns` was the reason the anchors were being
     truncated: a fixed 3-column flow gives each item a third of the width whatever it says, so a
     longer label wrapped or collided. A GRID that auto-fits sizes itself to the content instead
     -- wide labels get fewer, wider columns; short ones get more. No media queries needed, and
     no reason left to shorten the anchor text. */
  .sf-area__cities--wide{display:grid;columns:initial;
    grid-template-columns:repeat(auto-fit,minmax(15.5rem,1fr));
    gap:0 1.5rem;align-items:stretch}
  .sf-area__cities--wide li{break-inside:avoid;padding:0;
    border-bottom:1px solid var(--sf-line)}
  /* Interactive: 54 links that only changed the mouse cursor did not read as clickable.
     The whole row is the target (not just the words), it lifts toward the reader on hover,
     and a chevron slides in to say "this goes somewhere". Keyboard focus gets the same
     treatment, so it is not a mouse-only affordance. */
  .sf-area__cities--wide a{position:relative;display:block;height:100%;line-height:1.35;
    font-size:.92rem;padding:.62rem 1.5rem .62rem .7rem;border-left:2px solid transparent;
    transition:background .15s ease,border-color .15s ease,padding-left .15s ease,color .15s ease}
  .sf-area__cities--wide a::after{content:"\203A";position:absolute;right:.65rem;top:50%;
    transform:translateY(-50%) translateX(-4px);opacity:0;font-weight:700;
    transition:opacity .15s ease,transform .15s ease}
  .sf-area__cities--wide a:hover,.sf-area__cities--wide a:focus-visible{
    background:var(--sf-bg);border-left-color:var(--sf-amber);
    padding-left:1rem;color:var(--sf-amber-d);outline:none}
  .sf-area__cities--wide a:hover::after,.sf-area__cities--wide a:focus-visible::after{
    opacity:1;transform:translateY(-50%) translateX(0)}
  .sf-area__cities--wide a:focus-visible{box-shadow:0 0 0 2px var(--sf-amber)}
  @media(prefers-reduced-motion:reduce){
    .sf-area__cities--wide a,.sf-area__cities--wide a::after{transition:none}
  }
  /* The homepage lead-in that wraps the inline quote form (wireframe §13). */
  .sf-leadin{padding:var(--sf-xl) 0}
  /* ---- SACRED COMPONENTS: repoint their accent at the site token (2026-08-13) ----
     The quote form and all three calculators each hardcode the PRE-v2 blue #1f6fb2 as their
     own accent. Neither the v2 redesign nor the red palette ever reached them, because a
     token change cannot reach a literal — the same defect class as the hardcoded spray gun
     and the inline hero eyebrow. It was invisible while the form lived only on /get-a-spray-foam-quote/;
     putting it on the homepage next to red buttons made it obvious.

     ⛔ The source files are SACRED SURFACES and are NOT edited — not here, not by the
     renderer. Every one of them already exposes its accent as a custom property on its own
     root, so retargeting that ONE variable moves every colour derived from it and touches
     nothing else. Fields, pathing and CTA text are untouched.

     `:root #sfia-quote` rather than `#sfia-quote`: the component's <style> block is inline in
     the body and therefore LATER in document order, so an equal-specificity rule up here
     would lose. The extra :root wins on specificity instead of reaching for !important.
     Revert by deleting this block. */
  :root #sfia-quote{--sfq-accent:var(--sf-amber);--sfq-ink:var(--sf-ink);--sfq-line:var(--sf-line)}
  :root #sfia-bf,:root #sfia-rv,:root #sfia-cond{
    --a:var(--sf-amber);--ink:var(--sf-ink);--line:var(--sf-line)}
  .sf-cta{background:var(--sf-navy);color:#fff;margin-top:2rem}
  .sf-cta__row{display:flex;align-items:center;justify-content:space-between;gap:1rem;padding:1.4rem 0;flex-wrap:wrap}
  .sf-cta__hook{margin:0;font-size:1.15rem;font-weight:700}
  .sf-card--quote{background:#fff;border-radius:var(--sf-rad);padding:1.4rem;box-shadow:0 12px 34px rgba(10,22,40,.14)}
  .sf-ryan{display:inline-block;background:#fff4e6;border:1px dashed var(--sf-amber);border-radius:6px;padding:0 .3em;font-size:.85em}
  .sf-footer{background:var(--sf-ink);color:#cdd8e0;padding:2rem 0 1rem;margin-top:2.5rem}
  .sf-footer__grid{display:grid;grid-template-columns:repeat(5,1fr);gap:1.2rem}
  @media(max-width:820px){.sf-footer__grid{grid-template-columns:1fr 1fr}}
  .sf-footer a{color:#cdd8e0;text-decoration:none;display:block;font-size:.9rem;margin:.2rem 0}
  .sf-footer b{color:#fff;display:block;margin-bottom:.4rem}
  .sf-footer__map{margin-top:1rem;max-width:340px}
  .sf-footer__bar{border-top:1px solid #26343f;margin-top:1.2rem;padding-top:1rem;font-size:.82rem}
  .sf-callbar{display:none;position:fixed;bottom:0;left:0;right:0;background:var(--sf-navy);z-index:60}
  .sf-callbar a{flex:1;text-align:center;padding:.9rem;color:#fff;text-decoration:none;font-weight:800}
  .sf-callbar__q{background:var(--sf-amber);color:#1a1200}
  /* WIDENED 480 -> 900, 2026-08-31. Measured with sfia_mobile_probe.py, which gets a REAL
     narrow viewport via an iframe (the old render check could never get below 504px, so none
     of this had ever been seen). At 375/390/412 the bar renders correctly: 87px tall, two
     ~190px targets, well above the 44px thumb floor - it is the best conversion asset on the
     site and the reason the quote form sitting 2,500px down the homepage on a phone does not
     cost every lead. But at 500px and 768px it was display:none, so large phones in landscape
     and every tablet got NO persistent call or quote action at all. 900px keeps it below the
     desktop layout while covering that whole dead band. */
  @media(max-width:900px){.sf-callbar{display:flex}}
  /* ---- HOMEPAGE WIREFRAME BLOCKS (2026-08-13) ----
     Three components the homepage wireframe (Briefs/SFIA_HOMEPAGE_WIREFRAME.md §6, §7, §8)
     specified and the template never carried. Token-driven on purpose: every value below
     resolves through the same custom properties the v2 block redefines, so these inherit the
     clean-lines look automatically and need no override of their own. */
  /* Applications: 6 routing links. The 4-up segment grid would leave a 4+2 orphan row. */
  .sf-seg__grid--3{grid-template-columns:repeat(3,1fr)}
  @media(max-width:820px){.sf-seg__grid--3{grid-template-columns:1fr 1fr}}
  @media(max-width:480px){.sf-seg__grid--3{grid-template-columns:1fr}}
  /* No icon tile on these — six 152px figure tiles would out-shout the four segment cards
     directly above them, and the segment cards are the primary routing decision. */
  .sf-card--slim{padding:1.2rem 1.25rem 1.35rem}
  .sf-card--slim h3{margin-top:0}
  /* Closed vs open cell: two columns carrying the SAME rows, so the eye compares across. */
  .sf-cmp{display:grid;grid-template-columns:1fr 1fr;gap:1.1rem;margin-top:1.6rem}
  @media(max-width:700px){.sf-cmp{grid-template-columns:1fr}}
  .sf-cmp__col{background:#fff;border:1px solid var(--sf-line);border-radius:var(--sf-rad);
    padding:1.5rem 1.4rem 1.35rem}
  .sf-cmp__col h3{margin:0;font-size:1.12rem;color:var(--sf-navy)}
  .sf-cmp__r{display:block;font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;
    font-size:1.45rem;font-weight:700;color:var(--sf-amber);letter-spacing:-.02em;margin:.5rem 0 .1rem}
  .sf-cmp__r small{display:block;font-size:.7rem;font-weight:600;letter-spacing:.12em;
    text-transform:uppercase;color:var(--sf-mut);font-family:var(--sans)}
  .sf-cmp__list{list-style:none;margin:1.15rem 0 0;padding:0}
  .sf-cmp__list li{display:flex;justify-content:space-between;align-items:baseline;gap:1.2rem;
    padding:.55rem 0;border-top:1px solid var(--sf-line);font-size:.9rem;line-height:1.45}
  .sf-cmp__list span{color:var(--sf-mut);flex:0 0 auto}
  .sf-cmp__list b{font-weight:600;text-align:right}
  .sf-cmp__foot{margin:1.5rem 0 0;font-size:.9rem;color:var(--sf-mut)}
  /* Cost band: the transparency wedge. Copy left, both CTAs right. */
  .sf-cost__row{display:grid;grid-template-columns:1.25fr .75fr;gap:2rem;align-items:center}
  @media(max-width:820px){.sf-cost__row{grid-template-columns:1fr;gap:1.4rem}}
  .sf-cost__figs{display:flex;flex-wrap:wrap;gap:.5rem;margin:1.1rem 0 0;padding:0;list-style:none}
  .sf-cost__figs li{border:1px solid var(--sf-line);border-radius:var(--sf-rad);background:#fff;
    padding:.5rem .8rem;font-size:.88rem}
  .sf-cost__figs b{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;color:var(--sf-amber)}
  .sf-cost__note{font-size:.82rem;color:var(--sf-mut);margin:1rem 0 0;max-width:62ch}
  .sf-cost__act{display:flex;flex-direction:column;gap:.9rem;align-items:flex-start}
  @media(max-width:820px){.sf-cost__act{flex-direction:row;flex-wrap:wrap;align-items:center}}
  :root{
    /* Ink and ground: bone and near-black, not white and navy. */
    --sf-ink:#0E0E0D; --sf-navy:#0E0E0D; --sf-bg:#FFFFFF; --sf-soft:#F2F0EC;
    --sf-mut:#585651; --sf-line:#DAD5CC;
    /* ONE accent. Blue is retired to the same value so a stray reference cannot
       reintroduce a second accent colour by the back door. */
    /* 2026-08-13, Dustin: match the logo. The accent was burnt orange #C2410C while the brand
       mark's accent is RED — sampled off Sprayfoaminsulationlogoblack.jpg at #B4090A. The site
       had never agreed with its own logo. Ground and ink are unchanged. */
    --sf-blue:#B4090A; --sf-blue-d:#8E0708; --sf-amber:#B4090A; --sf-amber-d:#8E0708;
    /* The three habits, switched off at the token. */
    --sf-rad:0px; --sf-sh-1:none; --sf-sh-2:none; --sf-sh-3:none;
  }
  body{background:var(--sf-soft)}
  /* Display type reads set rather than default: bigger, tighter, heavier. */
  h1{letter-spacing:-.045em;line-height:1.02}
  h2,.sf-h2{letter-spacing:-.035em}
  /* --- Hero: the gradient, the dot field and the amber glow all go. On a light ground
     the inherited white text would be invisible, so every colour is restated. --- */
  .sf-hero{background:var(--sf-soft);color:var(--sf-ink);
    border-bottom:1px solid var(--sf-ink);overflow:visible}
  .sf-hero::before,.sf-hero::after{display:none}
  .sf-hero h1{color:var(--sf-ink)}
  .sf-hero__sub{color:#3B3934;opacity:1}
  .sf-hero__cta{align-items:center}
  .sf-stats{border-top:1px solid var(--sf-line)}
  .sf-stat b{color:var(--sf-ink);font-variant-numeric:tabular-nums}
  .sf-stat span{color:var(--sf-mut);opacity:1}
  /* --- Buttons: flat, square, no lift, no glow. --- */
  .sf-btn{border-radius:0;transition:background .15s ease}
  .sf-btn--primary{background:var(--sf-amber);color:#fff;box-shadow:none}
  .sf-btn--primary:hover{background:var(--sf-amber-d);transform:none;box-shadow:none}
  .sf-btn--ghost{background:transparent;color:var(--sf-ink);border:0;border-bottom:2px solid var(--sf-amber);
    border-radius:0;padding:.6rem .1rem;backdrop-filter:none}
  .sf-btn--ghost:hover{background:transparent;transform:none;color:var(--sf-amber-d)}
  /* --- Everything that was a floating rounded card becomes a ruled surface. --- */
  .sf-chip{border-radius:0;box-shadow:none;background:var(--sf-bg);border:1px solid var(--sf-line);
    color:var(--sf-ink);font-weight:600}
  .sf-trust{background:var(--sf-soft);border-top:1px solid var(--sf-line)}
  .sf-mega__panel{border-radius:0;box-shadow:none;border:1px solid var(--sf-ink)}
  .sf-burger__btn{border-radius:0}
  .sf-burger__btn span{background:var(--sf-ink)}
  /* Wordmark: the gradient tile was the most template-looking object in the header. */
  .sf-logo__mark{border-radius:0;background:var(--sf-ink);box-shadow:none;font-weight:800}
  .sf-logo__lead{color:var(--sf-mut);letter-spacing:.14em;
    font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;font-size:.66rem}
  .sf-logo__accent{color:var(--sf-ink);letter-spacing:-.03em}
  .sf-logo:hover .sf-logo__accent{color:var(--sf-amber)}
  .sf-header{border-bottom:1px solid var(--sf-ink)}
  /* --- Body copy: the lede carries, section rules do the rhythm the tint band used to. --- */
  article>p:first-of-type{color:#3B3934;font-size:1.2rem}
  article h2{border-top:1px solid var(--sf-line);padding-top:.9rem}
  /* --- Eyebrows and small labels move to mono: the register of R-values and board feet,
     and the cheapest way to stop a heading row looking like a marketing template. --- */
  .sf-eyebrow{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;
    color:var(--sf-mut);letter-spacing:.16em;font-weight:600}
  .sf-crumb{font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;
    font-size:.72rem;letter-spacing:.1em;text-transform:uppercase;color:var(--sf-mut)}
  .sf-crumb a{color:var(--sf-mut)}
  .sf-band--soft{background:var(--sf-soft);border-block:1px solid var(--sf-line)}
  .sf-callbar__q{color:#fff}
  .sf-footer{background:var(--sf-ink)}

  /* ================= HEADER: 64 links need ORGANISING, not recolouring =================
     Round 1 of v2 changed the tokens and left the structure alone, so the header stayed a
     site-map wearing a new palette. The links are staying (the silo in the header is
     deliberate — crawlers see the whole structure); what changes is that they now read as
     a considered menu instead of a dump: mono labels at a small size with real letter-spacing,
     wide gaps, and one filled element on the whole bar. */
  /* MEASURED, not guessed. 7 top-level items — Commercial · Residential · Agricultural ·
     Vehicles · Spray Foam · Service Areas · About — plus a 200px wordmark and a 175px CTA.
     In uppercase mono at .74rem/.13em that row needs ~1375px inside an 1180px container,
     and the burger did not appear until 900px: the header WRAPPED on every viewport between
     900 and ~1475px, which is most laptops. Uppercase glyphs plus tracking were costing
     ~260px on their own.
     Fix is two-part: sentence case at a size that actually fits (~1069px required, 111px of
     headroom), and the burger raised to 1100px so the horizontal row is only ever shown when
     there is genuinely room for it. nowrap makes a future overflow visible instead of silently
     stacking. */
  /* 2026-08-22 "lets make the menu denser its largest": header padding and the nav<->CTA gap
     were the other half of the bulk. Measured before: nav row 84px tall, nav 777px wide. */
  .sf-header__row{padding:.6rem 1.1rem;gap:.9rem;flex-wrap:nowrap}
  /* 2026-08-22 "make the main menu a bit more dense". THIS is the rule that governs desktop -
     the base .sf-nav gap earlier in this file is overridden here, so changing that one alone did
     nothing (measured: computed gap stayed 21.6px). Same multi-branch trap as the mega panel. */
  .sf-nav{gap:.6rem;align-items:center;flex-wrap:nowrap}
  /* 2026-08-22 ROOT CAUSE of "the menu is largest": this rule used the `font:` SHORTHAND with
     `var(--sans)` -- and --sans IS NEVER DEFINED in this stylesheet. An invalid custom property
     inside a shorthand invalidates the WHOLE declaration, so the font-size was silently thrown
     away and the nav has been rendering at a 17px cascade fallback since the v2 design landed.
     Two earlier attempts to shrink it (.84rem, then .76rem) changed nothing for exactly this
     reason. Explicit longhand properties, no undefined variable, measured after. */
  .sf-nav a,.sf-mega>a{font-weight:600;font-size:.78rem;line-height:1;letter-spacing:.01em;
    text-transform:none;color:var(--sf-ink);white-space:nowrap}
  @media(max-width:1100px){
    .sf-header__row{flex-wrap:wrap;gap:.6rem}
    .sf-burger__btn{display:flex;order:3}
    .sf-header__cta{order:2;margin-left:auto}
    .sf-nav{display:none;order:4;flex-basis:100%;flex-direction:column;flex-wrap:wrap;gap:0;
      border-top:1px solid var(--sf-line);margin-top:.4rem;padding-top:.4rem}
    .sf-burger:checked ~ .sf-nav{display:flex}
    .sf-mega{width:100%}
    .sf-mega__panel{display:none}
    .sf-mega:hover .sf-mega__panel{display:none}
    .sf-mega:focus-within .sf-mega__panel{display:flex;position:static;transform:none;
      border:0;box-shadow:none;padding:.2rem 0 .8rem;flex-direction:column;gap:.9rem;min-width:0}
    .sf-mega__col+.sf-mega__col{border-left:0;padding-left:0}
    .sf-nav a,.sf-mega>a{display:flex;align-items:center;min-height:48px;padding:.2rem .1rem;
      border-bottom:1px solid var(--sf-line);white-space:normal}
    .sf-mega>a::after{margin-left:auto}
  }
  .sf-nav a:hover,.sf-mega:hover>a{color:var(--sf-amber)}
  /* The caret was a filled triangle on every item — seven of them reads as clutter. */
  .sf-mega>a::after{border:0;width:5px;height:5px;border-right:1.5px solid currentColor;
    border-bottom:1.5px solid currentColor;transform:rotate(45deg);margin:-3px 0 0 .15rem;
    opacity:.45;content:""}
  /* Panel: air and column rules, so 6 links in a column read as a group not a list.
     ANCHORED TO THE HEADER ROW, NOT THE ITEM. The panel was positioned
     left:50%;transform:translateX(-50%) against each nav item — fine under "Commercial" on
     the left, but under "Service Areas" and "About" a centred 640px+ panel runs past the
     right edge of the viewport, where body{overflow-x:hidden} silently CLIPS it. I made that
     worse by adding min-width:640px plus wider padding and gaps in the previous pass.
     Making .sf-mega static and stretching the panel across the header row removes the whole
     class of bug: every panel is the same width, aligned to the container, and cannot
     overflow regardless of which item opens it. */
  .sf-header__row{position:relative}
  .sf-mega{position:static}
  .sf-mega__panel{left:0;right:0;width:auto;transform:none;min-width:0;
    padding:1.6rem 1.8rem;gap:2.4rem;border:1px solid var(--sf-ink);
    box-shadow:none;background:var(--sf-bg)}
  .sf-mega__col{min-width:10.5rem}
  .sf-mega__col+.sf-mega__col{border-left:1px solid var(--sf-line);padding-left:2.4rem}
  .sf-mega__col b{font:700 .64rem/1 ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;
    letter-spacing:.15em;color:var(--sf-amber);margin:0 0 .9rem;padding-bottom:.55rem;
    border-bottom:1px solid var(--sf-line)}
  .sf-mega__col a{font-size:.9rem;font-weight:500;padding:.34rem 0;color:var(--sf-ink);
    text-transform:none;letter-spacing:0;font-family:inherit}
  .sf-mega__col a:hover{color:var(--sf-amber)}
  .sf-header__cta .sf-btn{font-size:.78rem;letter-spacing:.08em;text-transform:uppercase;padding:.85rem 1.4rem}

  /* ---- HOVER GRACE (Dustin 2026-08-12: "the main menu isnt to user freindly") ----
     The panel was toggled with display:none/flex, which has zero tolerance: the moment the
     pointer leaves the item — including the diagonal move every user makes to reach a link
     inside the panel — it vanishes. Swapping to visibility+opacity lets the CLOSE be delayed
     while the OPEN stays instant, which is the whole trick. 240ms is enough to cross a gap
     and not so long that the panel feels stuck open.
     Scoped above the burger breakpoint so none of it touches the mobile drawer. */
  @media(min-width:1101px){
    /* ONE MECHANISM. This block used to reveal the panel with visibility+opacity while three
       other branches used `display` - so a rule that opened it in one branch was inert in the
       next, and the menu was reported broken four times. It is now `display` everywhere, and
       the hover grace that the opacity fade was buying is provided by an invisible bridge
       (::before) that keeps the pointer "inside" the item while it crosses the gap to the
       panel. Less clever, and it actually opens. */
    .sf-mega__panel{display:none;visibility:visible;opacity:1;pointer-events:auto;
      transform:none;transition:none}
    .sf-mega>.sf-mega__panel::before{content:"";position:absolute;left:0;right:0;top:-12px;height:12px}
    .sf-mega:hover>.sf-mega__panel,
    .sf-mega:focus-within>.sf-mega__panel,
    .sf-mega.is-open>.sf-mega__panel{display:flex}
    .sf-mega:hover>a,.sf-mega:focus-within>a,.sf-mega.is-open>a{color:var(--sf-amber)}
  }
  @media(prefers-reduced-motion:reduce){
    .sf-mega__panel{transition:none!important;transform:none!important}
  }

  /* ================= FOOTER: a brand block, then the index =================
     34 links in five equal columns with no anchor read as a link dump. Giving the footer a
     masthead — wordmark, what this business is, the NAP — means the columns become a
     reference index BELOW something, instead of being the whole footer. */
  .sf-footer{padding:0 0 1.25rem;margin-top:4rem}
  /* ONE grid: identity column + the link index. No rule between them, no second full-width
     band — that separation is what made it read as two footers. */
  .sf-footer__top{display:grid;grid-template-columns:1fr;gap:2.5rem;padding:3rem 0 0}
  @media(min-width:940px){
    .sf-footer__top{grid-template-columns:minmax(230px,1fr) 2.5fr;gap:4rem;align-items:start}
  }
  /* The legal line was wrapping to three short lines inside a narrow column. It is a
     single full-width statement - let it use the whole footer width. */
  .sf-footer__legalline{max-width:none!important;width:100%}
  .sf-footer__grid{padding-top:0}
  .sf-footer__brand{display:flex;flex-direction:column;gap:1rem;align-items:flex-start}
  .sf-footer__brand h2{color:#fff;font-size:1.45rem;letter-spacing:-.03em;margin:0;font-weight:800}
  .sf-footer__brand p{color:#8A857C;font-size:.88rem;margin:0;max-width:40ch;line-height:1.6}
  .sf-footer__nap{font:600 .76rem/1.9 ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;
    color:#B9B4AB;letter-spacing:.04em}
  .sf-footer__nap a{display:inline;color:#B9B4AB;font-size:inherit;margin:0}
  .sf-footer__nap a:hover{color:var(--sf-amber)}
  .sf-footer a{font-size:.86rem;margin:0;padding:.26rem 0;line-height:1.45}

  /* ---- FOOTER: five rigid columns crushed the longest link labels
     ("Shipping Containers", "Vehicles & Containers") at every width between the
     820px breakpoint and the 1180px max. auto-fit lets the row reflow on its own
     instead of failing between two hard-coded states. ---- */
  /* FIVE groups, one row. auto-fit at minmax(165px) could only seat four in the space left
     beside the brand column, so CONTACT wrapped underneath SERVICES and punched a hole under
     the other three. Explicit 5-up above 1100px, then a graceful 2-up. */
  .sf-footer__grid{grid-template-columns:repeat(5,minmax(0,1fr));gap:1.6rem 1.1rem}
  @media(max-width:1100px){.sf-footer__grid{grid-template-columns:repeat(3,minmax(0,1fr))}}
  @media(max-width:760px){.sf-footer__grid{grid-template-columns:repeat(2,minmax(0,1fr))}}
  /* SCOPED TO THE GRID. Styling `.sf-footer b` hit the inline <b> in the legal bar too, which
     is what produced the stray "SPRAY FOAM INSULATION ALBERTA" with a half-width underline
     floating above the legal links. Column headings are a grid concern only. */
  .sf-footer__grid b{letter-spacing:.1em;text-transform:uppercase;font-size:.72rem;
    font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;color:#fff;
    padding-bottom:.5rem;border-bottom:1px solid #2E2D2A;margin-bottom:.6rem}
  .sf-footer a{color:#B9B4AB}
  .sf-footer a:hover{color:var(--sf-amber)}
  .sf-footer__bar{border-top:1px solid #2E2D2A;color:#8A857C;margin-top:2.25rem;padding-top:1.4rem;
    display:flex;flex-direction:column;gap:1rem;font-size:.8rem}
  /* The original rule sets `display:block` on EVERY footer link, which is right for the
     columns and wrong here: it stacked the legal links one per line and stranded each
     "&middot;" separator on a line of its own. The bar is a sentence, not a list. */
  .sf-footer__bar p{margin:0!important;line-height:1.9}
  .sf-footer__bar a{display:inline;margin:0;padding:0;font-size:inherit;color:#B9B4AB}
  /* SOCIAL: three bordered 38px tiles stacked above the legal links read as buttons for
     something important — they are secondary links. Boxing a glyph adds a rectangle for no
     information. Drop the box entirely: the mark IS the target, sized to keep a 44px tap
     area via padding, muted until hover. */
  /* ---- APPLICATION FIGURES in the segment cards ----
     Beyond Foam puts each figure in a white tile on a coloured band, divided by hairlines.
     Same idea, our language: square tile not rounded, bone not orange, and the divider is
     the card border we already have. The figure is 48x32 so a section reads at a glance. */
  /* flex must be reset: .sf-ico pins flex:0 0 26px, and the figure is a flex item inside
     .sf-card__ico, so the basis would win and squash a 76px drawing back to 26px. */
  .sf-fig{width:132px;height:99px;flex:0 0 auto;stroke-width:1.15;stroke:var(--sf-ink);fill:none;
    stroke-linecap:round;stroke-linejoin:round}
  /* Hover must not repaint the hose or the foam — only the structure. Scoping to paths that
     carry no inline style keeps the amber parts amber. */
  .sf-card:hover .sf-fig>path:not([style]){stroke:var(--sf-amber)}
  /* The tile: Beyond Foam frames each drawing in a bordered card on a coloured band. Same
     device, our language — square not rounded, white on bone, hairline border. */
  .sf-card__ico{display:inline-flex;align-items:center;justify-content:center;
    width:152px;height:112px;background:#fff;border:1px solid var(--sf-rule-2,#C0B9AD);
    border-radius:0;margin-bottom:1rem;transition:border-color .15s ease}
  .sf-card:hover .sf-card__ico{border-color:var(--sf-amber)}
  .sf-card{border-radius:0;box-shadow:none;border:1px solid var(--sf-line);background:#fff;
    transition:border-color .15s ease}
  .sf-card:hover{border-color:var(--sf-ink);transform:none;box-shadow:none}
  .sf-card h3{letter-spacing:-.02em;margin:0 0 .35rem}
  @media(max-width:480px){.sf-fig{width:64px;height:44px}.sf-card__ico{width:88px;height:62px}}

  /* Was fill:#7C776F on the near-black footer ground - technically present, visually gone.
     Brighter fill, larger glyph and a real 44px tap target; still unboxed, per the 08-12
     decision that they should not read as buttons. */
  .sf-soc{gap:1.15rem;margin:.35rem 0 0}
  .sf-soc a{width:auto;height:auto;padding:.55rem .35rem;border:0;background:transparent;
    border-radius:0}
  .sf-soc a:hover{background:transparent;transform:none;border:0}
  .sf-soc svg{width:23px;height:23px;fill:#C9C4BB;transition:fill .15s ease}
  .sf-soc a:hover svg{fill:var(--sf-amber)}
  .sf-soc a:focus-visible{outline:2px solid var(--sf-amber);outline-offset:3px}
  /* Footer logo: the wordmark IS the artwork, so the <h2> it replaces is gone. */
  .sf-footer__logo{display:block;height:auto;max-width:165px;margin:0}
  .sf-logo__img{display:block;height:52px;width:auto}
  @media(max-width:520px){.sf-logo__img{height:44px}}

  /* ---- MENU: the real defect, not a cosmetic one. ----
     The mega panels open on :hover, and the burger only appears at <=900px. A touch
     device WIDER than 900px — iPad landscape, any touch laptop — therefore gets no
     burger AND no hover: tapping a top-level item just navigates, and every sub-link
     in the silo is unreachable. It has been that way since the 08-02 mobile fix, which
     solved phones and left the gap above them.

     Gate on the INPUT DEVICE rather than the width: if the pointer cannot hover, use
     the burger no matter how wide the screen is. Desktop mouse behaviour is untouched. */
  @media (hover:none),(pointer:coarse){
    .sf-header__row{flex-wrap:wrap;gap:.6rem}
    .sf-burger__btn{display:flex;order:3}
    .sf-header__cta{order:2;margin-left:auto}
    .sf-nav{display:none;order:4;flex-basis:100%;flex-direction:column;gap:0;
      border-top:1px solid var(--sf-line);margin-top:.4rem;padding-top:.4rem}
    .sf-burger:checked ~ .sf-nav{display:flex}
    .sf-mega{width:100%}
    /* Hover can never open a panel on a touch device — stop pretending it can. */
    .sf-mega:hover .sf-mega__panel{display:none}
    /* Focus still opens it, but inline in the drawer rather than as a floating
       overlay positioned off the edge of a narrow screen. */
    .sf-mega__panel{display:none}
    /* The caret is the tap target that opens the panel. It sits at the end of the row, is
       48px so it clears the accessibility minimum, and draws its own chevron so no icon
       font or image is needed. The link text beside it still navigates normally. */
    .sf-mega{display:block}
    .sf-mega>a{padding-right:52px}
    .sf-mega__caret{display:block;position:absolute;right:0;top:0;width:48px;height:48px;
      cursor:pointer;z-index:2}
    .sf-mega__caret::after{content:"";position:absolute;top:50%;left:50%;width:.6rem;height:.6rem;
      border-right:2.5px solid var(--sf-navy);border-bottom:2.5px solid var(--sf-navy);
      transform:translate(-50%,-70%) rotate(45deg);transition:transform .2s ease}
    .sf-mega__tog:checked ~ .sf-mega__caret::after{transform:translate(-50%,-30%) rotate(225deg)}
    .sf-mega__tog:focus-visible ~ .sf-mega__caret{outline:2px solid var(--sf-blue);outline-offset:-2px}
    /* The original ::after chevron on the link itself would now be a second arrow. */
    .sf-mega>a::after{display:none}
    .sf-mega__tog:checked ~ .sf-mega__panel,
    .sf-mega:focus-within .sf-mega__panel{display:flex;visibility:visible;opacity:1;pointer-events:auto;position:static;transform:none;
      border:0;box-shadow:none;padding:.2rem 0 .8rem 1rem;flex-direction:column;gap:.9rem;
      flex-basis:100%}
    .sf-nav a,.sf-mega>a{display:flex;align-items:center;min-height:48px;
      padding:.2rem .1rem;border-bottom:1px solid var(--sf-line);white-space:normal}
    .sf-mega>a::after{margin-left:auto}
  }
  /* ============================================================================
     MENU OPEN STATE - THE ONE RULE THAT WINS.
     This menu was reported broken four times. The cause was never one bug: the panel is
     revealed by `display` in the v1 branch, by `visibility/opacity/pointer-events` in the
     design-v2 branch, and again differently inside @media(min-width:1101px),
     @media(max-width:900px) and @media(hover:none) - five branches, three mechanisms, each
     resetting what another set. A :checked rule that satisfied one was inert in the next.
     `.is-open` is set by script (below) and declared LAST with !important so no branch can
     take it back. The checkbox/:checked path stays as the no-JavaScript fallback.
     ============================================================================ */
  .sf-mega.is-open>.sf-mega__panel{
    display:flex!important;visibility:visible!important;opacity:1!important;
    pointer-events:auto!important;transform:none!important}
  .sf-mega.is-open>a{color:var(--sf-amber)}
  .sf-mega.is-open>.sf-mega__caret::after{transform:translate(-50%,-30%) rotate(225deg)}

  /* ================= v3 POLISH -- 2026-08-23 =====================================
     Appended last: earlier branches in this file have twice overridden edits made
     higher up (nav gap, nav font). Tokens only, no new colours, no new content. */

  /* --- TYPE: a real scale instead of browser defaults ------------------------- */
  .sf-hero h1{font-size:clamp(2.05rem,4.4vw,3.25rem);line-height:1.05;letter-spacing:-.022em;
    margin:.45rem 0 .7rem}
  .sf-hero__sub{font-size:clamp(1rem,1.35vw,1.12rem);line-height:1.55;color:var(--sf-mut);
    max-width:46ch;margin:0 0 1.4rem}
  .sf-eyebrow{font-size:.68rem;letter-spacing:.16em}
  .sf-band h2,section h2{letter-spacing:-.015em;line-height:1.15}

  /* --- HERO: two columns, and the stats become the object on the right -------- */
  .sf-hero{padding-block:clamp(2.4rem,5vw,4.2rem)}
  @media(min-width:1000px){
    .sf-hero:not(.sf-hero--img)>.sf-wrap{display:grid;
      grid-template-columns:minmax(0,1.08fr) minmax(0,.92fr);
      /* ROW-GAP MUST BE 0. The stats card spans several rows; any phantom row it spans still
         contributes a row-gap, which opened ~300px of dead space under the buttons on the first
         attempt. Column gap does the separating; the elements carry their own vertical margins. */
      column-gap:clamp(2rem,4.5vw,4rem);row-gap:0;align-items:center}
    .sf-hero:not(.sf-hero--img)>.sf-wrap>*{grid-column:1;min-width:0}
    .sf-hero:not(.sf-hero--img) .sf-stats{grid-column:2;grid-row:1/span 6;align-self:center;
      margin:0;border-top:0;
      background:var(--sf-bg);border:1px solid var(--sf-line);
      border-top:3px solid var(--sf-amber);
      box-shadow:0 22px 60px rgba(15,28,38,.11);
      padding:1.55rem 1.7rem;
      display:grid;grid-template-columns:1fr 1fr;gap:1.35rem 1.5rem}
  }
  /* --- STATS: give the numerals weight and the labels a register -------------- */
  .sf-stat{display:flex;flex-direction:column;gap:.2rem}
  .sf-stat b{font-size:clamp(1.6rem,2.5vw,2.1rem);line-height:1;letter-spacing:-.03em;
    font-variant-numeric:tabular-nums}
  .sf-stat span{font-size:.66rem;letter-spacing:.1em;color:var(--sf-mut);
    font-family:ui-monospace,SFMono-Regular,Menlo,Consolas,monospace;line-height:1.35}

  /* --- TRUST CHIPS: pills with a mark, not bordered boxes --------------------- */
  .sf-trust__row{gap:.55rem;flex-wrap:wrap}
  .sf-chip{display:inline-flex;align-items:center;gap:.5rem;border-radius:99px;
    padding:.44rem .95rem .44rem .8rem;font-size:.82rem;font-weight:600;
    border:1px solid var(--sf-line);background:var(--sf-bg);color:var(--sf-ink)}
  .sf-chip::before{content:"";flex:0 0 auto;width:.42rem;height:.42rem;border-radius:99px;
    background:var(--sf-amber)}

  /* --- BUTTONS: hierarchy, depth and a visible focus ring -------------------- */
  .sf-btn{border-radius:2px;font-weight:700;letter-spacing:.01em;
    transition:transform .14s ease,box-shadow .14s ease,background .14s ease}
  /* 🐛 padding is NOT cosmetic here, it is a leftover. The v2 block above styles the ghost
     button as a borderless underlined link and sets `padding:.6rem .1rem` to suit that -- no
     side border, so no side padding needed. This block then puts a full 1px BOX border back
     and never restored the horizontal padding, so the label sat 1.6px from its own border on
     every ghost button (visible on "Spray Foam Costs" in the hero). Restated from `.sf-btn`
     so the two button styles match. Found by screenshot 2026-08-28; no gate reads padding. */
  .sf-btn--ghost{background:transparent;border:1px solid var(--sf-line);color:var(--sf-ink);
    padding:.95rem 1.6rem;box-shadow:none}
  .sf-btn--ghost:hover{border-color:var(--sf-ink);transform:translateY(-1px)}
  .sf-btn:focus-visible{outline:3px solid var(--sf-amber);outline-offset:2px}

  /* --- SECTION RHYTHM: consistent vertical spacing, hairlines doing the work -- */
  .sf-band{padding-block:clamp(2.2rem,4.5vw,3.6rem)}
  .sf-wrap>section+section{margin-top:clamp(2rem,4vw,3.2rem)}
  article p{max-width:70ch}
  article li{max-width:68ch}

  /* --- PHOTO HERO: light type over the image --------------------------------- */
  /* 🚨 The v2 block sets `.sf-hero{color:var(--sf-ink)}` because for five weeks the hero was a
     PALE BAND with no photo. The moment a real photo landed (2026-08-28, Dustin's first two
     job photos) that rule put BLACK type over a dark image: the h1, the eyebrow and all four
     stats were near-illegible. The photo variant has to put the light type back.
     ⭐ Found by loading the built site over a local HTTP server and LOOKING. It could not be
     seen over file:// because the absolute /media/ path does not resolve there, and no gate
     grades contrast. */
  .sf-hero--img,
  .sf-hero--img h1,
  .sf-hero--img .sf-hero__sub,
  .sf-hero--img .sf-eyebrow,
  .sf-hero--img .sf-crumb,
  .sf-hero--img .sf-crumb a,
  .sf-hero--img .sf-stat b,
  .sf-hero--img .sf-stat span{color:#fff}
  .sf-hero--img .sf-stat span{opacity:.85}
  .sf-hero--img .sf-stats{border-top-color:rgba(255,255,255,.35)}
  /* the ghost button is outlined in ink for the pale band; over a photo it needs to be white */
  .sf-hero--img .sf-btn--ghost{border-color:rgba(255,255,255,.75);color:#fff}
  .sf-hero--img .sf-btn--ghost:hover{border-color:#fff;background:rgba(255,255,255,.12)}
  /* a touch more scrim on the left third, which is where every line of type sits */
  .sf-hero--img .sf-hero__media::before{content:"";position:absolute;inset:0;z-index:1;
    background:linear-gradient(90deg,rgba(11,36,56,.72) 0%,rgba(11,36,56,.45) 45%,rgba(11,36,56,0) 75%)}

  /* --- QUICKLEAD: stop the intro column ending in a hole ---------------------- */
  /* The band is two equal columns with align-items:start. The form runs ~600px tall and the
     intro is an eyebrow, an h2 and a three-line lede, so ~380px of the left column rendered
     as dead space -- the same defect class as the 08-23 hero, found the same way: by taking a
     screenshot and looking, not by a gate. Centring the short column splits the difference
     above and below instead of dumping it all at the bottom. Below 900px the band is already
     one column, so this only applies where the hole exists.
     ⛔ Nothing inside the form is touched: the form is a lead surface. */
  @media(min-width:901px){
    .sf-quicklead .sf-wrap{align-items:center}
  }

  /* --- HERO LEAD FORM (Dustin 2026-08-28) ------------------------------------------------ */
  /* "i want to reamov this from the herp sectio" (he pasted all four stats and all four trust
     chips) then "i want t a fom up there witha photo" / "in te hereo sectino". The homepage
     hero is now PHOTO + HEADLINE LEFT, QUOTE FORM RIGHT. Applies only where `.sf-hero--form`
     is set, which home.html sets only when a form is actually present, so every other hero on
     the site is untouched.
     ⛔ Nothing inside `#sfia-quote` is restyled except its width and margins — it is a lead
     surface and it carries its own scoped palette (`#sfia-quote{color:var(--sfq-ink)}`), which
     is an ID selector and therefore already beats `.sf-hero--img{color:#fff}`. That is why the
     card reads dark-on-white over the photo instead of inheriting the hero's light type. */
  /* 🐛 PRE-EXISTING, FOUND BY SCREENSHOT 2026-08-28. It hits EVERY `.sf-hero--img`, which today
     is exactly one page — the homepage is the only page whose media resolves to a hero photo
     (measured: 1 of 408). So this reads as a homepage fix now and becomes a fleet fix the day
     a second photo lands. `.sf-hero--img{padding:0}` is declared at the top of the photo
     block, but `.sf-hero{padding-block:clamp(2.4rem,5vw,4.2rem)}` is declared ~540 lines LATER
     in the same stylesheet. Both are single-class selectors, so specificity ties and SOURCE
     ORDER decides — the later `.sf-hero` won and put padding back on the photo variant. With
     `.sf-hero{background:var(--sf-soft)}` also in force, that padding rendered as a pale grey
     strip above AND below every hero photo, exactly like a broken image box.
     ⭐ No gate can see this: the markup is correct, the CSS parses, and both rules are
     intentional in isolation. It is only visible in a picture. */
  .sf-hero--img{padding-block:0}

  .sf-hero__form{margin-top:2rem}
  .sf-hero--form #sfia-quote{margin:0;max-width:540px}

  /* Two scrims stack on a photo hero: the ::after vertical wash (up to .90 at the foot) and
     the ::before left-side wash. Tuned separately they were fine; together, under a layout
     that now needs the photo legible on BOTH sides, they crushed the image to near-black.
     The white form card supplies its own contrast, so the right side barely needs a wash —
     only the left, where the white type sits, still does. */
  .sf-hero--form .sf-hero__media::after{
    background:linear-gradient(180deg,rgba(11,36,56,.34) 0%,rgba(11,36,56,.44) 55%,rgba(11,36,56,.58) 100%)}

  /* 2026-08-29 REBUILD - Dustin: title full width across the top, TWO BLOCKS below it.
     The grid moved off `.sf-wrap` (which also held the h1) and onto `.sf-hero__cols`, so the
     title now spans the whole hero and only the copy/form pair is columnar. */
  .sf-hero__head h1{max-width:none}
  .sf-hero__lede{font-size:1.02rem;line-height:1.6;margin:0 0 1.3rem;max-width:56ch}
  .sf-hero__cols{margin-top:1.6rem}
  /* 2026-08-29: the form moved OUT of the hero and into its own band below it, so the hero is
     a single column again. `.sf-hero--form` is no longer set by any template - the two-column
     hero rules below are kept only because the class still guards them and they cost nothing;
     nothing matches them today. The form band is styled at .sf-leadin__form further down. */
  .sf-hero__cols--solo{max-width:64ch}

  @media(min-width:981px){
    .sf-hero--form .sf-hero__cols{display:grid;
      grid-template-columns:minmax(0,1.02fr) minmax(0,.98fr);
      gap:clamp(1.8rem,3.4vw,3.4rem);align-items:start}
    .sf-hero--form .sf-hero__copy,
    .sf-hero--form .sf-hero__form{min-width:0}
    .sf-hero__form{margin-top:0}
    .sf-hero--form #sfia-quote{margin-left:auto}
    .sf-hero--form .sf-hero__sub{max-width:70ch}
    /* The photo scrim was a left-third gradient tuned for type on the left and bare image on
       the right. A white card now sits on the right, so the image needs cover the whole way
       across or the card floats on an unmuted photo and the edge contrast goes to mush. */
    .sf-hero--form.sf-hero--img .sf-hero__media::before{
      background:linear-gradient(90deg,rgba(11,36,56,.74) 0%,rgba(11,36,56,.38) 46%,rgba(11,36,56,.12) 100%)}
  }

  /* The media box was floored at 340-520px and bottom-aligned to sit a headline and a stats
     row on the lower third. The form card is taller than that floor, so the floor now only
     applies as a minimum and the content is centred rather than jammed to the bottom edge. */
  .sf-hero--form .sf-hero__media{align-items:center}
  .sf-hero--form .sf-hero__media>.sf-wrap{padding-top:clamp(2.2rem,4vw,3.4rem);
    padding-bottom:clamp(2.2rem,4vw,3.4rem)}

  /* =========================================================================================
     DARK BLUE TRIM  (Dustin 2026-08-29: "i want a dark blue trim in the theme to accent the
     red button")
     =========================================================================================
     ⚠️ READ THIS BEFORE CHANGING IT. The v2 block above deliberately RETIRED blue - "ONE
     accent. Blue is retired to the same value so a stray reference cannot reintroduce a second
     accent colour by the back door", because two accents competing for authority was one of
     the five habits that made the site read as generated. That rule still stands and this does
     not break it, because the trim is STRUCTURAL ONLY.
       ✅ navy may be: rules, borders, edges, the frame around things
       ⛔ navy may NEVER be: a button fill, a link colour, or anything a visitor can click
     RED REMAINS THE ONLY ACTION COLOUR. The trim exists to frame it, which is exactly what
     "accent the red button" asks for - the button reads louder against a navy frame than it
     did against a warm grey one. If you find yourself reaching for --sf-trim on something
     clickable, that is the back door the v2 comment is warning about. Use red.
     `--sf-navy` itself is NOT reused: v2 flattened it to near-black (#0E0E0D), so anything
     already pointing at it would silently change colour. A new token keeps this additive. */
  :root{ --sf-trim:#0E2A45; --sf-trim-soft:rgba(14,42,69,.16); }

  /* The frame of the page: top edge, hero edge, foot edge. */
  .sf-header{border-bottom:2px solid var(--sf-trim)}
  .sf-hero{border-bottom:3px solid var(--sf-trim)}
  .sf-band--soft{border-block-color:var(--sf-trim-soft)}
  .sf-footer{border-top:3px solid var(--sf-trim)}

  /* Cards get a navy top rule; on hover it goes red, so the trim hands authority to the
     action colour rather than competing with it. */
  .sf-card{border-color:var(--sf-trim-soft);border-top:3px solid var(--sf-trim)}
  .sf-card:hover{border-top-color:var(--sf-amber)}
  aside .sf-card{border-top:3px solid var(--sf-trim)}

  /* The lead surface is framed, never recoloured - nothing inside the form changes. */
  .sfq-card{border-top:3px solid var(--sf-trim)}

  /* ONE navy marker per block, never two. Every eyebrow gets the tick; an h2 gets the rule
     only when no eyebrow already marks that block, which `.sf-eyebrow + .sf-h2` detects
     directly rather than by listing sections by hand. The first version scoped the tick to
     .sf-seg/.sf-leadin only, so the quicklead's "FREE QUOTE" eyebrow was bare while its
     heading carried a rule - the same block marked two different ways on two templates. */
  .sf-eyebrow{border-left:3px solid var(--sf-trim);padding-left:.55rem}
  .sf-h2{padding-bottom:.45rem;border-bottom:2px solid var(--sf-trim-soft)}
  .sf-eyebrow + .sf-h2{border-bottom:0;padding-bottom:0}
  /* over a photo the tick would sit on a dark ground - lighten it so it still reads */
  .sf-hero--img .sf-eyebrow{border-left-color:rgba(255,255,255,.55)}

  /* The ghost button is outlined, not filled, so navy is legitimate here - it is a border,
     and the filled red primary still owns the action. */
  .sf-btn--ghost{border-color:var(--sf-trim);color:var(--sf-trim)}
  .sf-btn--ghost:hover{border-color:var(--sf-trim);background:rgba(14,42,69,.06)}
  /* over a photo the hero keeps its white outline - do not let navy-on-dark happen */
  .sf-hero--img .sf-btn--ghost{border-color:rgba(255,255,255,.75);color:#fff}

  .sf-gbadge{border-color:var(--sf-trim-soft)}

  /* =========================================================================================
     BLOCK RHYTHM  (Dustin 2026-08-29: "lets go through the main page ... really improve ech
     block"). Three defects, all MEASURED on the built page, not judged by eye.
     ========================================================================================= */

  /* 🐛 1. THE ALTERNATING BANDS NEVER ALTERNATED.
     Measured: all 9 homepage blocks painted rgb(242,240,236) - four `.sf-band--soft` sections,
     three transparent ones showing the body through, and the body itself. `.sf-band--soft`
     resolves to var(--sf-soft) and v2 also sets body{background:var(--sf-soft)}, so the band
     class has been a NO-OP since v2 landed and the page read as one undifferentiated column.
     ⛔ The fix is NOT to make the body white - "bone and near-black, not white and navy" is the
     v2 identity and it stays. Invert instead: bone ground, WHITE bands. Same markup, same
     token vocabulary, and the rhythm the sections were written to have comes back. */
  /* ⭐ FIRST ATTEMPT SHIPPED AND CHANGED NOTHING YOU COULD SEE. Inverting the bands to white
     left them 5.8% of luminance apart from the bone ground (242,240,236 vs 255,255,255) -
     technically alternating, perceptually identical. Dustin: "doesnt look like anythign
     changed", and he was right. A fix that is real in the stylesheet and invisible on screen
     is not a fix; VERIFY THE PIXELS, not the presence of the rule.
     Two changes make the rhythm actually readable:
       - the ground drops to a deeper bone, taking the separation to ~13% of luminance
       - each band carries a solid navy rule top and bottom, so the boundary is unmistakable
         even where the two fills are close. The rule is doing most of the work. */
  body{background:#E6E1D6}
  .sf-band--soft{background:var(--sf-bg);
    border-top:2px solid var(--sf-trim);border-bottom:2px solid var(--sf-trim)}

  /* 🐛 2. HEADINGS RAN TWICE THE WIDTH OF THE TEXT UNDER THEM.
     Measured on 6 of 9 blocks: h2=1140px over p=578px, a 562px delta. The heading spanned the
     whole container while its own lede wrapped at half of it, which is what made the page look
     left-weighted even though the wrap is perfectly centred (rightGutter=0 everywhere - the
     emptiness was never a gutter, it was this mismatch). Bring the two into the same column:
     the lede widens a little, the heading stops running the full width. Delta 562 -> ~220. */
  .sf-h2{max-width:900px}
  .sf-lede{max-width:73ch}
  /* Capping the width made two headings break with a single orphan word on line two
     ("...Vetted Crews Spray / It", "...Not The Same / Product"). Balanced wrapping splits the
     line at the sensible point instead of at the last word that happens to fit. Progressive:
     browsers without it simply keep the old greedy break, so nothing depends on it. */
  h1,h2,.sf-h2,.sf-hero__lede{text-wrap:balance}

  /* 🐛 3. A FIVE-ITEM GRID IN THREE COLUMNS LEAVES A HOLE.
     Measured: .sf-feat has cols=3, items=5, emptyCells=1 - the last row ran [item][item][gap].
     When the final item is the second in its row, let it take the empty cell instead of
     leaving one. Keyed on the count, so adding a sixth item makes the rule stop applying by
     itself rather than needing a hand edit. */
  .sf-feat>:last-child:nth-child(3n+2){grid-column:span 2}

  /* =========================================================================================
     FLOW PASS  (Dustin 2026-08-29): "instead of the black footer / black trim I want dark navy
     blue ... the theme kinda blue and then the button's red ... it was looking very HTML, very
     bones and old. We want it looking like a flow, everything functioning, everything flowing
     ... even the city list looks like an old city list, those links need to be better, denser.
     The blocks need to be denser. They need to hover better. A little more futuristic, a little
     more user friendly, that it draws you in."
     ========================================================================================= */

  /* --- 1. NAVY, NOT BLACK -----------------------------------------------------------------
     v2 flattened every dark surface to near-black (#0E0E0D) - footer, CTA strip and ink all
     the same value. The dark surfaces become navy; RED IS STILL THE ONLY ACTION COLOUR. */
  :root{ --sf-navy-deep:#0B2038; --sf-navy-line:#1D3A56; }
  .sf-footer{background:var(--sf-navy-deep);color:#C7D4E0;border-top:3px solid var(--sf-trim)}
  .sf-footer b{color:#fff}
  .sf-footer a{color:#C7D4E0;transition:color .15s ease,padding-left .15s ease}
  .sf-footer a:hover{color:#fff;padding-left:.25rem}
  .sf-footer__bar{border-top:1px solid var(--sf-navy-line)}
  .sf-cta{background:var(--sf-navy-deep);color:#fff}
  /* Body ink moves from pure near-black into the navy family so the type belongs to the
     palette instead of sitting on top of it. Still ~15:1 on the ground, so nothing is
     traded away for the tint. */
  body{color:#121A22}

  /* --- 2. DENSER BLOCKS -------------------------------------------------------------------
     Sections were a flat 4rem top and bottom (--sf-xl) at every viewport, which is what made
     the page feel like a stack of loose slabs rather than one document. */
  .sf-seg,.sf-rel,.sf-area,.sf-cost,.sf-faq,.sf-how,.sf-leadin{
    padding-block:clamp(2.2rem,3.6vw,3.1rem)}
  .sf-card{padding:1.15rem 1.2rem}
  .sf-seg__grid{gap:1rem}

  /* --- 3. THE CITY LIST -------------------------------------------------------------------
     It read as an old-fashioned link list because it was four wide columns of tall rows. Same
     markup, twice the density: narrower minimum column so more fit per row, tighter rows, and
     a hover that fills navy and slides the label rather than only recolouring the text. */
  .sf-area__cities--wide{grid-template-columns:repeat(auto-fit,minmax(10.5rem,1fr));
    gap:0 .9rem}
  .sf-area__cities--wide li{border-bottom:1px solid var(--sf-trim-soft)}
  .sf-area__cities--wide a{font-size:.86rem;padding:.46rem 1.35rem .46rem .55rem;
    border-left:2px solid transparent;color:var(--sf-trim)}
  .sf-area__cities--wide a:hover,.sf-area__cities--wide a:focus-visible{
    background:var(--sf-trim);border-left-color:var(--sf-amber);color:#fff;padding-left:.85rem}
  .sf-area__cities--wide a:focus-visible{box-shadow:0 0 0 2px var(--sf-amber)}

  /* --- 4. HOVER THAT ANSWERS ---------------------------------------------------------------
     v2 switched off the lift and the shadow to kill the generated look, which also removed
     every sign that a card was clickable. Give the response back as MOVEMENT AND COLOUR rather
     than as a drop shadow: the navy rule turns red, the card lifts a hair, the border darkens.
     One rule, one accent, no glow. */
  .sf-card{transition:transform .16s ease,border-color .16s ease,background .16s ease}
  .sf-card:hover{transform:translateY(-2px);border-color:var(--sf-trim);box-shadow:none}
  .sf-btn{transition:background .15s ease,transform .15s ease,border-color .15s ease}
  .sf-btn--primary:hover{transform:translateY(-1px)}
  .sf-gbadge{transition:transform .15s ease,border-color .15s ease}
  .sf-gbadge:hover{transform:translateY(-1px);border-color:var(--sf-trim)}
  @media(prefers-reduced-motion:reduce){
    .sf-card,.sf-btn,.sf-gbadge,.sf-footer a{transition:none}
    .sf-card:hover,.sf-btn--primary:hover,.sf-gbadge:hover{transform:none}
  }

  /* --- 8. THE TRUST STRIP (Dustin 2026-08-29) -----------------------------------------------
     Three blocks immediately under the hero: Google, Facebook, BBB. Sits on the navy band so it
     reads as part of the hero rather than as the first content section, which is what "right
     underneath the hero" asks for. Auto-fit so it re-flows to two blocks while BBB is hidden -
     no empty third cell, and no hand-editing when BBB is added later. */
  .sf-proof{background:var(--sf-navy-deep);border-bottom:3px solid var(--sf-trim);
    padding-block:1.05rem}
  .sf-proof__row{display:grid;grid-template-columns:repeat(auto-fit,minmax(15rem,1fr));
    gap:.8rem}
  .sf-proof__card{display:flex;align-items:center;gap:.75rem;text-decoration:none;
    background:rgba(255,255,255,.06);border:1px solid rgba(255,255,255,.14);
    border-radius:2px;padding:.7rem .9rem;
    transition:background .16s ease,border-color .16s ease,transform .16s ease}
  .sf-proof__card:hover{background:rgba(255,255,255,.12);border-color:rgba(255,255,255,.4);
    transform:translateY(-2px)}
  /* the brand marks keep their own colours, so they sit on white discs rather than on navy */
  .sf-proof__mark{display:grid;place-items:center;width:42px;height:42px;flex:0 0 42px;
    background:#fff;border-radius:50%}
  .sf-proof__mark--bbb{font:800 13px/1 system-ui,sans-serif;color:#0B2038;letter-spacing:.02em}
  .sf-proof__txt{display:flex;flex-direction:column;line-height:1.3;min-width:0}
  .sf-proof__txt b{color:#fff;font-size:.95rem;font-weight:700;letter-spacing:-.005em}
  .sf-proof__sub{color:#B9C7D6;font-size:.76rem}
  /* ⛔ Gold stars render ONLY when a real rating exists - see the guard in home.html. Sized to
     read as a rating rather than as decoration, so when they DO appear they carry weight. */
  .sf-proof__stars{color:#FBBC05;font-size:.95rem;letter-spacing:.1em;line-height:1.15;
    text-shadow:0 1px 0 rgba(0,0,0,.25)}
  /* slot 3 before BBB exists: a credential, not a link - no hover lift, no pointer */
  .sf-proof__card--static{cursor:default}
  .sf-proof__card--static:hover{background:rgba(255,255,255,.06);
    border-color:rgba(255,255,255,.14);transform:none}
  @media(prefers-reduced-motion:reduce){
    .sf-proof__card{transition:none}.sf-proof__card:hover{transform:none}
  }

  /* --- 7. THE COST BLOCK'S EMPTY RIGHT COLUMN -----------------------------------------------
     `.sf-cost__row` is a 1.25fr/.75fr grid whose right column held two buttons and nothing
     else, vertically centred - so the block read as copy on the left and a tall empty gutter on
     the right. It was the last visibly unbalanced band on the homepage.
     Frame the actions as a panel instead of leaving them floating: same card language as the
     rest of the page (navy top rule, tinted ground so it separates from the now-white band),
     with the buttons filling its width. No markup change - `.sf-cost__act` already exists. */
  .sf-cost__row{align-items:start}
  .sf-cost__act{background:var(--sf-soft);border:1px solid var(--sf-trim-soft);
    border-top:3px solid var(--sf-trim);padding:1.15rem 1.2rem;align-items:stretch;gap:.7rem}
  .sf-cost__act .sf-btn{width:100%;justify-content:center}
  @media(max-width:820px){
    .sf-cost__act{flex-direction:column;align-items:stretch}
  }

  /* --- 6. PORTRAIT PHOTOS WERE SWALLOWING THE PAGE ------------------------------------------
     🐛 MEASURED: segment-residential-1.jpg is 1080x1920 and segment-vehicles-1.jpg is
     1600x2133 - both PORTRAIT, because they came off a phone. `.sf-figure img` was
     `width:100%;height:auto`, so in a ~780px article column the residential photo rendered
     about 1,387px TALL and became the whole screen. On the segment hubs - the pages people
     actually land on - the body was one enormous phone photo with the copy pushed off below
     it.
     ⛔ Not fixed by editing the photos: the next portrait image dropped into media/ would do
     it again. Cap the BOX and let the image cover it, so any aspect ratio behaves. Landscape
     photos are unaffected - default-hero-1.jpg is 2000x1500 and never reaches the cap. */
  .sf-figure img{max-height:clamp(300px,34vw,460px);object-fit:cover;object-position:center}

  /* --- 5. THE PROSE BLOCK ------------------------------------------------------------------
     The markdown body renders as a bare <article> inside a bare <main> - no section, no band,
     no padding, no structure. On the homepage that is the single largest thing on the page and
     the only block left with none of the treatment the others now have, which is exactly the
     "wall of text" and part of what read as bones-HTML.
     ⛔ Scoped to `:not(.sf-grid)` so it applies to the single-column homepage article and NEVER
     to the core/location pages, where the article is a grid column beside the sticky aside and
     centring it would break that layout. */
  main > .sf-wrap:not(.sf-grid){padding-block:clamp(2.2rem,3.6vw,3.1rem)}
  main > .sf-wrap:not(.sf-grid) > article{max-width:74ch;margin-inline:auto}
  /* Sub-headings inside the prose get the same navy language as the section headings, so the
     article reads as part of the page instead of as dumped copy. */
  main > .sf-wrap:not(.sf-grid) > article > h2{margin-top:2.4rem;padding-bottom:.4rem;
    border-bottom:2px solid var(--sf-trim-soft)}
  main > .sf-wrap:not(.sf-grid) > article > h3{margin-top:1.8rem;
    border-left:3px solid var(--sf-trim);padding-left:.6rem}
  main > .sf-wrap:not(.sf-grid) > article > p{margin:0 0 1.05rem}
  /* Links inside prose were bare red text; give them a real underline that responds. */
  main > .sf-wrap > article a{color:var(--sf-amber-d);text-decoration:underline;
    text-underline-offset:.16em;text-decoration-thickness:1px;
    transition:color .15s ease,text-decoration-color .15s ease}
  main > .sf-wrap > article a:hover{color:var(--sf-trim);text-decoration-thickness:2px}

  /* --- THE LEFT-SHIFT (Dustin 2026-08-29: "the content shifted to the left side") ---------- */
  /* `.sf-wrap` IS centred - measured at 1920px, the wrap runs 391..1529 with 391 either side.
     What reads as a left shift is `.sf-grid`: a 1fr + 320px split where the aside is only
     ~470px tall against an article several thousand pixels long. Past the bottom of the aside
     the copy keeps its narrow column and the right third is simply empty, for most of the page.
     Making the aside sticky keeps that column occupied the whole way down instead of leaving a
     dead gutter. `align-items:start` is already on .sf-grid, which is what lets sticky work -
     a stretched grid item has no room to move within its track. */
  @media(min-width:961px){
    .sf-grid>aside{position:sticky;top:calc(var(--sf-header-h, 88px) + 1.25rem);
      max-height:calc(100vh - var(--sf-header-h, 88px) - 2.5rem);overflow-y:auto}
  }

  /* --- THE FORM BAND, DIRECTLY BELOW THE HERO (Dustin 2026-08-29) ------------------------- */
  /* The component caps itself at 640px and centres, which is right for a full-width band.
     The heading and lede stay left so they read as page copy rather than a centred banner. */
  .sf-leadin__form{margin-top:1.8rem}
  .sf-leadin__form #sfia-quote{margin:0 auto}

  /* --- GOOGLE BADGE ---------------------------------------------------------------------- */
  /* ⛔ Renders NO star count unless `trust_badges.rating` holds a real one - see home.html.
     Sized and coloured to read as a credential, not a third CTA competing with the button. */
  /* inside the hero CTA row it is a sibling of the buttons, so the stacked margin goes */
  .sf-hero__cta .sf-gbadge{margin-top:0;margin-left:.4rem}
  @media(max-width:560px){.sf-hero__cta .sf-gbadge{margin-left:0}}
  .sf-gbadge{display:inline-flex;align-items:center;gap:.6rem;margin-top:1.3rem;
    padding:.55rem .9rem .55rem .6rem;border-radius:999px;text-decoration:none;
    background:rgba(255,255,255,.94);border:1px solid rgba(0,0,0,.08);
    box-shadow:0 4px 14px rgba(11,36,56,.18)}
  .sf-gbadge:hover{background:#fff}
  /* Plain letter mark, not a reproduction of Google's logo - we are entitled to say the
     listing is on Google, not to redraw their trademark badly in CSS. */
  .sf-gbadge__g{display:grid;place-items:center;width:28px;height:28px;border-radius:50%;
    background:#fff;border:1px solid rgba(0,0,0,.10);color:#4285f4;
    font:700 16px/1 system-ui,sans-serif;flex:0 0 28px}
  .sf-gbadge__txt{display:flex;flex-direction:column;line-height:1.15}
  .sf-gbadge__txt b{color:#16232e;font-size:.92rem}
  .sf-gbadge__txt span{color:#5a6b78;font-size:.74rem}
  /* the badge is a white pill, so it keeps its own dark type even inside a photo hero */
  .sf-hero--img .sf-gbadge__txt b{color:#16232e}
  .sf-hero--img .sf-gbadge__txt span{color:#5a6b78}
