/* ============================================================================================
   Indoor Experts — UTILITY + LEGAL layer (ie-util.css)
   Built 2026-08-18 for the six pages that sit outside the build waves:
   /contact-us/ · /schedule/ · /thank-you/ · /privacy-policy/ · /terms-and-conditions/ · /sitemap/

   WHY A THIRD FILE: ie.css is the shared site system and ie-v16.css is the sub-service page
   layer. These six pages need components no money page needs (a legal document column, a
   day/time slot picker, a sitemap index, a confirmation panel) and none of them belong in the
   layer every service page loads. Same precedent as ie-v16.css: additive, linked only where used.

   Load order on every page here:  ie.css  >  ie-v16.css  >  ie-util.css
   ⚠ ie-v16.css is required, not optional: `.chap`, `.head.center` and the `--ie-arc` marks used
     by these pages are defined there. Dropping it renders the chapter markers as empty gaps.

   Everything below is built on the locked tokens (--navy / --gold / --canvas / --disp / --body).
   No new colour is introduced anywhere in this file.
   ============================================================================================ */

/* ───────── COMPACT DOCUMENT HERO ─────────
   Legal pages and the sitemap get a short dark band instead of the tall photo hero. A privacy
   policy behind a lifestyle photograph reads as marketing, and these pages are not marketing.
   The gold arc glow is the same brand device the rest of the site uses, so the band still
   belongs to this site rather than looking like an unstyled WordPress default. */
.leghero{position:relative;overflow:hidden;
  background:linear-gradient(158deg,#0a1c3f 0%,#143883 58%,#0f2a5e 100%);color:#c9d5ea}
.leghero::before{content:"";position:absolute;top:-190px;right:-140px;width:460px;height:460px;
  border-radius:50%;background:radial-gradient(circle,rgba(252,201,82,.15),transparent 68%);pointer-events:none}
.leghero::after{content:"";position:absolute;left:-150px;bottom:-240px;width:480px;height:480px;
  border-radius:50%;background:radial-gradient(circle,rgba(255,255,255,.07),transparent 66%);pointer-events:none}
.leghero .wrap{padding:56px 28px 62px;position:relative}
.leghero h1{font-family:var(--disp);font-weight:700;color:#fff;margin:16px 0 0;
  font-size:clamp(30px,3.9vw,48px);letter-spacing:-.022em;max-width:20ch}
.leghero .sub{color:#b9c7e0;font-size:clamp(15.5px,1.35vw,17.5px);margin:18px 0 0;max-width:62ch}
.leghero .eyebrow{color:var(--gold-2)}
.leghero .eyebrow::before{background:var(--gold-2)}
/* the "last updated" stamp. A legal document without a date is not a legal document. */
.legstamp{display:inline-flex;align-items:center;gap:10px;margin-top:26px;padding:9px 16px;
  border:1px solid rgba(252,201,82,.36);border-radius:999px;background:rgba(252,201,82,.09);
  font-family:var(--disp);font-weight:600;font-size:12.5px;letter-spacing:.06em;color:var(--gold-2)}
.legstamp svg{width:14px;height:14px;flex:none}

/* ───────── LEGAL DOCUMENT: sticky contents rail + prose column ─────────
   ⚠ The rail is a <nav>, not decoration. These documents run past 1,700 words and the SMS
   sections are the part people actually arrive looking for, so they need to be reachable
   without a scroll hunt. */
.legal .wrap{display:grid;grid-template-columns:250px 1fr;gap:clamp(34px,5vw,78px);align-items:start}
.legtoc{position:sticky;top:100px}
.legtoc b{display:block;font-family:var(--disp);font-weight:700;font-size:11.5px;letter-spacing:.16em;
  text-transform:uppercase;color:var(--muted);padding-bottom:12px;border-bottom:1px solid var(--line)}
.legtoc ol{list-style:none;margin:0;padding:0;counter-reset:toc}
.legtoc li{counter-increment:toc;border-bottom:1px solid var(--line)}
.legtoc a{display:grid;grid-template-columns:26px 1fr;gap:10px;padding:11px 0;
  font-size:14px;color:var(--muted);transition:color .16s}
.legtoc a::before{content:counter(toc,decimal-leading-zero);font-family:var(--disp);font-weight:700;
  font-size:11px;color:var(--line-2);letter-spacing:.06em;padding-top:2px}
.legtoc a:hover{color:var(--navy)}
.legtoc a:hover::before{color:var(--gold)}

.legdoc{max-width:72ch}
.legdoc>section{scroll-margin-top:110px}
.legdoc>section+section{margin-top:clamp(34px,4vw,54px);padding-top:clamp(30px,3.4vw,46px);
  border-top:1px solid var(--line)}
.legdoc h2{font-family:var(--disp);font-weight:700;color:var(--navy);
  font-size:clamp(21px,2.1vw,26px);letter-spacing:-.012em;margin:0}
.legdoc h3{font-family:var(--disp);font-weight:600;color:var(--ink);font-size:16.5px;margin:26px 0 0}
.legdoc p{font-size:15.6px;line-height:1.78;color:var(--muted);margin:15px 0 0}
.legdoc a{color:var(--navy);text-decoration:underline;text-underline-offset:3px;
  text-decoration-color:var(--line-2)}
.legdoc a:hover{text-decoration-color:var(--gold)}
.legdoc ul{margin:16px 0 0;padding:0;list-style:none;display:grid;gap:9px}
.legdoc ul li{position:relative;padding-left:22px;font-size:15.2px;line-height:1.7;color:var(--muted)}
.legdoc ul li::before{content:"";position:absolute;left:0;top:.62em;width:7px;height:7px;
  border-radius:50%;border:1.6px solid var(--gold);background:transparent}
/* a pulled-out clause, for the lines a reader is most likely to be looking for (STOP / HELP) */
.legcall{margin:20px 0 0;padding:18px 22px;background:var(--gold-soft);
  border:1px solid rgba(225,165,12,.28);border-radius:var(--r)}
.legcall p{margin:0;color:#4a3a10;font-size:15.2px}
.legcall p+p{margin-top:10px}
.legcall b{color:#2f2508;font-weight:600}
.legcall a{color:#4a3a10}
/* the contact block that closes both legal documents */
.legnap{margin-top:20px;padding:22px 24px;background:#fff;border:1px solid var(--line);border-radius:var(--r)}
.legnap b{display:block;font-family:var(--disp);font-weight:700;color:var(--navy);font-size:16px}
.legnap span{display:block;font-size:15px;color:var(--muted);margin-top:5px}
.legnap a{color:var(--navy)}

/* ───────── CONTACT METHOD CARDS ─────────
   Four ways in, ranked by how fast they actually get answered. Flat hairline cards, no shadow
   stack: the locked direction calls for hairline depth, not floating panels. */
.cxgrid{display:grid;grid-template-columns:repeat(4,1fr);gap:18px;margin-top:40px}
/* 🔴 A MODIFIER, NOT AN INLINE STYLE. The thank-you page originally set its three-up grid with
   style="grid-template-columns:repeat(3,1fr)" on the element. An inline declaration outranks every
   rule in this file, INCLUDING the @media blocks that collapse the grid on small screens, so the
   cards stayed three across at 390px and spilled 36px off the side of the page. sweep.mjs caught
   it at 390 and 360. Never set a grid template inline on a component that has breakpoints. */
.cxgrid.three{grid-template-columns:repeat(3,1fr)}
/* ⚠ `.cxgrid` DEFAULTS TO FOUR COLUMNS. A two-card band without this modifier sits in half the
   width and leaves the right side of the section empty, which is how /financing/'s reach band
   first shipped. Added 2026-08-25 for that band. */
.cxgrid.two{grid-template-columns:repeat(2,1fr)}
.cxcard{background:#fff;border:1px solid var(--line);border-radius:var(--r);padding:26px 24px 24px;
  display:flex;flex-direction:column;transition:border-color .18s,transform .18s}
.cxcard:hover{border-color:var(--line-2);transform:translateY(-2px)}
.cxcard .ic{width:42px;height:42px;border-radius:11px;background:var(--gold-soft);
  display:grid;place-items:center;margin-bottom:16px}
.cxcard .ic svg{width:19px;height:19px;color:var(--gold)}
.cxcard h3{font-family:var(--disp);font-weight:700;font-size:15px;color:var(--navy);margin:0}
.cxcard .v{display:block;font-family:var(--disp);font-weight:700;font-size:17.5px;color:var(--ink);
  margin-top:9px;letter-spacing:-.012em;overflow-wrap:anywhere}
.cxcard a.v{color:var(--ink)}
/* ⚠ Long unbreakable values, i.e. the email address. At four cards across, a .cxcard is ~285px
   wide and ~237px inside its padding. "service@indoorexperts.com" at 17.5px Montserrat 700 is
   about 230px, so it fit at 1440 and broke MID-WORD one notch narrower, rendering as
   "service@indoorexperts.c / om". overflow-wrap cannot help: there is no legal break point in
   the string, so it breaks wherever it runs out. The fix is to make the value fit, not to give
   the breaking better manners. */
.cxcard .v.long{font-size:14.6px;letter-spacing:0}
.cxcard a.v:hover{color:var(--navy)}
.cxcard p{font-size:13.6px;color:var(--muted);margin:10px 0 0;line-height:1.6}
/* the response-speed line pins to the bottom so the four cards agree across uneven copy */
.cxcard .sp{margin-top:auto;padding-top:16px;font-size:12px;font-weight:500;letter-spacing:.04em;
  color:var(--muted);display:inline-flex;align-items:center;gap:7px}
.cxcard .sp::before{content:"";width:6px;height:6px;border-radius:50%;background:var(--gold);flex:none}

/* ───────── NAP + HOURS PANEL (contact page, beside the van photo) ───────── */
.napx{display:grid;grid-template-columns:1.06fr .94fr;gap:clamp(28px,3.6vw,56px);align-items:center;margin-top:44px}
.napx .pic{position:relative;border-radius:20px;overflow:hidden;border:1px solid var(--line);aspect-ratio:16/10.4}
.napx .pic img{width:100%;height:100%;object-fit:cover}
.napcard{background:#fff;border:1px solid var(--line);border-radius:var(--r);padding:clamp(24px,2.6vw,34px)}
.napcard .row{display:grid;grid-template-columns:38px 1fr;gap:16px;padding:18px 0;border-bottom:1px solid var(--line)}
.napcard .row:first-of-type{padding-top:0}
.napcard .row:last-of-type{border-bottom:0;padding-bottom:0}
.napcard .row .ic{width:34px;height:34px;border-radius:9px;background:var(--canvas-2);display:grid;place-items:center}
.napcard .row .ic svg{width:16px;height:16px;color:var(--navy)}
.napcard .row b{display:block;font-family:var(--disp);font-weight:700;font-size:11.5px;letter-spacing:.14em;
  text-transform:uppercase;color:var(--muted)}
.napcard .row span{display:block;font-size:15.4px;color:var(--ink);margin-top:5px;line-height:1.55}
.napcard .row a{color:var(--ink)}
.napcard .row a:hover{color:var(--navy)}
.napcard .go{margin-top:22px;width:100%;justify-content:center}
/* the in-scope coverage list. PLAIN TEXT ON PURPOSE — the nine location pages are not built yet
   and /service-area/ was deleted, so every one of these would be a link into a 404. */
.hoodwrap{margin-top:26px;padding-top:22px;border-top:1px solid var(--line)}
.hoodwrap b{font-family:var(--disp);font-weight:700;font-size:11.5px;letter-spacing:.14em;
  text-transform:uppercase;color:var(--muted)}
.hoodpills{display:flex;flex-wrap:wrap;gap:8px;margin-top:14px}
.hoodpills span{padding:7px 13px;border:1px solid var(--line);border-radius:999px;
  background:var(--canvas);font-size:13px;color:var(--ink)}

/* the real social row, replacing the {{NEEDS_SOURCE}} pill that .rch-social ships by default.
   The five profile URLs are published on the live site, so this is a sourced fact, not a guess. */
.rch-social .links{display:flex;flex-wrap:wrap;gap:8px}
.rch-social .links a{padding:7px 15px;border-radius:999px;font-size:13.2px;color:#e3eaf7;
  border:1px solid rgba(255,255,255,.24);background:rgba(255,255,255,.05);
  transition:border-color .16s,background .16s,color .16s}
.rch-social .links a:hover{color:#1c1403;background:var(--gold-2);border-color:var(--gold-2)}

/* ───────── FORM CONSENT ROW, WITH REAL COMPLIANCE COPY IN IT ─────────
   🔴 THIS EXISTS BECAUSE OF A REAL BUG, CAUGHT ON THE FIRST SCREENSHOT PASS.
   `.qform label` in ie.css is `text-transform:uppercase; letter-spacing:.09em; font-size:11.5px`,
   which is correct for a four-word field label. `.rch-consent` was designed when its only content
   was a short {{NEEDS_SOURCE}} pill, so nothing ever tested it with prose. The moment the real
   40-word SMS consent sentence went in, it rendered as a wall of tracked-out capitals that filled
   a third of the form and could not be read. Compliance copy nobody reads is compliance theatre,
   so it is reset to sentence case here.
   ⚠ Scoped to `.rch-consent label` so genuine field labels keep their uppercase treatment. */
.rch-consent label{text-transform:none;letter-spacing:0;font-family:var(--body);font-weight:400;
  font-size:12.2px;line-height:1.58;color:var(--muted);margin:0}
.rch-consent label a{color:var(--navy);text-decoration:underline;text-underline-offset:2px}

/* ───────── SCHEDULE: day + time-slot picker ─────────
   Radio inputs styled as chips. Real <input type=radio> under each chip, not a div listener:
   the picker has to arrow-key and submit like a form control because it is one.
   ⚠ Same uppercase inheritance as above: these are <label>s inside a .qform, so they arrive
   capitalised and tracked out. "AS SOON AS POSSIBLE" in a chip shouts, and the locked direction is
   sentence case. Reset here, not by weakening the shared field-label rule. */
.slotpick{margin-top:4px}
.slotpick .lg{display:block;font-family:var(--disp);font-weight:600;font-size:12.5px;
  letter-spacing:.05em;color:#0f2a5e;margin-bottom:9px}
.chips{display:flex;flex-wrap:wrap;gap:8px}
.chips input{position:absolute;opacity:0;width:0;height:0}
.chips label{display:inline-flex;align-items:center;padding:9px 14px;border:1px solid var(--line-2);
  border-radius:999px;background:#fff;cursor:pointer;margin:0;
  text-transform:none;letter-spacing:0;font-family:var(--body);font-weight:500;
  font-size:13.4px;color:var(--ink);
  transition:border-color .16s,background .16s,color .16s}
.chips label:hover{border-color:var(--gold)}
.chips input:checked+label{background:var(--navy);border-color:var(--navy);color:#fff}
/* keyboard focus must stay visible once the native input is hidden */
.chips input:focus-visible+label{outline:2px solid var(--gold);outline-offset:2px}
/* forces the next chip onto a new line without leaving the radiogroup */
.chips .brk{flex-basis:100%;height:0;margin:0}

/* ───────── THANK YOU: confirmation panel ───────── */
.tyx{max-width:760px;margin:0 auto;text-align:center}
.tyx .seal{width:76px;height:76px;margin:0 auto;border-radius:50%;display:grid;place-items:center;
  background:rgba(252,201,82,.14);border:1.6px solid rgba(252,201,82,.5)}
.tyx .seal svg{width:34px;height:34px;color:var(--gold-2)}
.tyx h1{font-family:var(--disp);font-weight:700;color:#fff;margin:26px 0 0;
  font-size:clamp(31px,4.1vw,50px);letter-spacing:-.024em}
.tyx .sub{color:#b9c7e0;font-size:clamp(16px,1.4vw,18px);margin:18px auto 0;max-width:54ch}
.tyx .cta{display:flex;flex-wrap:wrap;gap:14px;justify-content:center;margin-top:32px}
/* the three next-step cards, on the dark field under the seal */
.tysteps{display:grid;grid-template-columns:repeat(3,1fr);gap:16px;margin-top:46px;text-align:left}
.tystep{padding:24px 22px;border:1px solid rgba(255,255,255,.16);border-radius:var(--r);
  background:rgba(255,255,255,.045)}
.tystep .n{font-family:var(--disp);font-weight:700;font-size:12.5px;letter-spacing:.12em;color:var(--gold-2)}
.tystep h2{font-family:var(--disp);font-weight:700;font-size:16.5px;color:#fff;margin:11px 0 0}
.tystep p{font-size:14.2px;color:#b3c1dc;margin:9px 0 0;line-height:1.66}

/* ───────── SITEMAP INDEX ───────── */
/* no .head above this grid, so it owns no top margin: the section padding is the whole gap. */
.smap{display:grid;grid-template-columns:repeat(3,1fr);gap:clamp(24px,3vw,44px);align-items:start}
.smcol{display:flex;flex-direction:column;gap:clamp(30px,3.2vw,46px)}
.smgroup h2{font-family:var(--disp);font-weight:700;font-size:13px;letter-spacing:.14em;
  text-transform:uppercase;color:var(--navy);padding-bottom:12px;border-bottom:2px solid var(--gold);margin:0}
.smgroup h3{font-family:var(--disp);font-weight:600;font-size:13.5px;color:var(--ink);margin:24px 0 0}
.smgroup ul{list-style:none;margin:10px 0 0;padding:0}
.smgroup li{border-bottom:1px solid var(--line)}
.smgroup li a{display:block;padding:9px 0;font-size:14.4px;color:var(--muted);transition:color .16s,padding .16s}
.smgroup li a:hover{color:var(--navy);padding-left:5px}
/* a planned URL that has no page on disk yet. Visible on purpose: an index that silently lists
   dead links is worse than one that admits which shelves are still empty. */
.smgroup li span[data-planned]{display:flex;justify-content:space-between;gap:12px;align-items:baseline;
  padding:9px 0;font-size:14.4px;color:var(--line-2)}
.smgroup li span[data-planned]::after{content:"in progress";font-size:10px;
  font-family:var(--disp);font-weight:700;letter-spacing:.1em;text-transform:uppercase;
  color:var(--line-2);flex:none}
.smnote{margin-top:44px;padding:22px 26px;background:#fff;border:1px solid var(--line);border-radius:var(--r)}
.smnote p{font-size:14.6px;color:var(--muted);margin:0;line-height:1.7}
.smnote p+p{margin-top:10px}
.smnote a{color:var(--navy);text-decoration:underline;text-underline-offset:3px}

/* ───────── RESPONSIVE ─────────
   ⚠ Restate, do not rely on cascade order: ie.css closes with unconditional rules, so a media
   block written earlier than those would lose. This file loads last, which keeps these winning. */
@media(max-width:1080px){
  .cxgrid,.cxgrid.three{grid-template-columns:repeat(2,1fr)}
  .smap{grid-template-columns:repeat(2,1fr)}
}
@media(max-width:900px){
  .legal .wrap{grid-template-columns:1fr}
  .legtoc{position:static;top:auto;margin-bottom:34px}
  .legtoc ol{columns:2;column-gap:26px}
  .napx{grid-template-columns:1fr}
  .tysteps{grid-template-columns:1fr}
}
@media(max-width:640px){
  .cxgrid,.cxgrid.three,.cxgrid.two{grid-template-columns:1fr}
  .smap{grid-template-columns:1fr}
  .legtoc ol{columns:1}
  .leghero .wrap{padding:42px 20px 46px}
  .legdoc{max-width:none}
}

/* ============================================================================================
   v2 — CONTACT + SCHEDULE REDESIGN (2026-08-18, same day)

   🔴 WHY v1 WAS REJECTED. Both pages were built on the MONEY-PAGE SPINE: a photo hero with the
   quote form sitting in its right column. That is correct on a service page, where the form is an
   interruption CTA competing with the copy. It is wrong on a contact or booking page, where the
   form IS the content. The result read as a lead-gen landing page: the hero carried no proof, the
   form was cut in half by the fold, and the ways to reach us were scattered across four equal
   cards further down.

   WHAT THE OTHER RSG SITES DO, checked before rebuilding — Lexany /contact-us/, Precision Air
   /contact/, Alamo Comfort /contact/. All three, independently, do the same three things:
     1. NO FORM IN THE HERO. The hero right column is a proof or reach object instead: Lexany uses
        a stacked console card, Precision a review cluster, Alamo a three-up NAP strip.
     2. THE FORM GETS ITS OWN SECTION, paired side by side with a reach or next-steps panel.
     3. A REAL MAP, not a photograph of a van.
   This layer follows that shape in IE's own locked language rather than cloning any of them: warm
   off-white panels, navy and gold, hairline depth, sentence case, and no shape dividers (the owner
   has ruled against those once already, on the AC repair page).
   ============================================================================================ */

/* ───────── HERO REACH CONSOLE — the object that replaces the form in the hero ─────────
   A warm off-white panel floating on the dark hero. Warm rather than pure white on purpose: the
   locked direction names the warm canvas as the welcoming lever, and a stark white card on navy is
   the generic look this brand has rejected three times.
   Every row is a real link. A reach panel whose rows are not clickable is a picture of a phone
   number, which on a phone is worse than useless. */
.rconsole{background:var(--canvas);border:1px solid rgba(255,255,255,.22);border-radius:20px;
  padding:8px 22px 20px;box-shadow:0 26px 54px rgba(0,0,0,.30)}
.rc-hd{display:flex;align-items:center;justify-content:space-between;gap:14px;
  padding:16px 0 14px;border-bottom:1px solid var(--line)}
.rc-hd b{font-family:var(--disp);font-weight:700;font-size:11.5px;letter-spacing:.16em;
  text-transform:uppercase;color:var(--muted)}
.rc-hd .hrs{font-size:12.5px;color:var(--muted)}
.rc-row{display:grid;grid-template-columns:42px 1fr auto;gap:15px;align-items:center;
  padding:15px 0;border-bottom:1px solid var(--line);transition:transform .16s}
.rc-row:hover{transform:translateX(3px)}
.rc-row .ic{width:40px;height:40px;border-radius:11px;background:var(--gold-soft);
  display:grid;place-items:center}
.rc-row .ic svg{width:18px;height:18px;color:var(--gold)}
.rc-row .tx{display:block;min-width:0}
.rc-row .tx b{display:block;font-family:var(--disp);font-weight:700;font-size:16.5px;
  color:var(--navy);letter-spacing:-.012em;overflow-wrap:anywhere}
.rc-row .tx span{display:block;font-size:12.8px;color:var(--muted);margin-top:3px;line-height:1.45}
.rc-row .tag{font-family:var(--disp);font-weight:700;font-size:9.5px;letter-spacing:.12em;
  text-transform:uppercase;color:var(--gold);background:rgba(225,165,12,.12);
  border:1px solid rgba(225,165,12,.3);border-radius:999px;padding:5px 10px;white-space:nowrap}
/* the email row value is long and has no legal break point, same problem the contact cards had */
.rc-row .tx b.long{font-size:14.2px}
/* the score foot closes the panel on proof rather than on another link */
.rc-foot{display:flex;align-items:center;gap:13px;padding-top:16px}
.rc-foot .sc{font-family:var(--disp);font-weight:700;font-size:27px;color:var(--navy);line-height:1}
.rc-foot .st{color:var(--gold);font-size:13px;letter-spacing:1.5px;line-height:1}
.rc-foot .sm{display:block;font-size:12.2px;color:var(--muted);margin-top:3px}

/* ───────── PROOF RAIL — under the hero copy, and again in the closing CTA ─────────
   Alamo closes its contact page on a rail of credentials rather than on a bare button. Same idea
   here, in IE's hairline language. Four facts, every one of them already stated on the site. */
/* ⚠ ONE ROW, NOT flex-wrap. A wrapping rail put a single orphaned item on a second line the
   moment the hero column got narrower than the four items, which reads as a bug rather than as a
   wrap. auto-fit columns keep it honest: it is a row or it is nothing. */
.proofrail{display:grid;grid-auto-flow:column;grid-auto-columns:max-content;gap:0 30px;
  margin-top:30px;padding-top:22px;border-top:1px solid rgba(255,255,255,.16)}
.proofrail .pr{display:flex;flex-direction:column;padding:4px 0}
.proofrail .pr b{font-family:var(--disp);font-weight:700;font-size:15.5px;color:#fff;line-height:1.15}
.proofrail .pr span{font-size:11.8px;color:#9dafd1;margin-top:4px;letter-spacing:.02em}
.close .proofrail{justify-content:center;gap:0 38px;margin-top:36px}
.close .proofrail .pr{align-items:center}

/* ───────── GET IN TOUCH — the form gets its own section ─────────
   The pattern all three reference sites use. The form is a real card with room to breathe, and the
   column beside it answers the question a form always raises: what happens after I press send. */
.gtouch{display:grid;grid-template-columns:1.02fr .98fr;gap:clamp(30px,3.8vw,62px);align-items:start;margin-top:44px}
.gtouch .formcard{background:#fff;border:1px solid var(--line);border-radius:20px;
  padding:clamp(26px,2.8vw,38px);box-shadow:0 20px 44px rgba(20,56,131,.07)}
.gtouch .formcard h3{font-family:var(--disp);font-weight:700;font-size:21px;color:var(--navy);margin:0}
.gtouch .formcard .qs{font-size:14.5px;color:var(--muted);margin:9px 0 22px;line-height:1.6}
/* the form inside is the shared .qform stripped of its own panel chrome: the card IS the panel now */
.gtouch .qform{background:none;border:0;padding:0;box-shadow:none;border-radius:0}
/* side column: numbered steps straight on the warm ground, no card, so the form card stays the
   only object in the band and the eye knows where to go first */
.gtside .lb{font-family:var(--disp);font-weight:700;font-size:11.5px;letter-spacing:.16em;
  text-transform:uppercase;color:var(--muted)}
.gtside h3{font-family:var(--disp);font-weight:700;font-size:clamp(21px,2.2vw,27px);
  color:var(--ink);letter-spacing:-.015em;margin:14px 0 0}
.gtside .lede{font-size:15.4px;color:var(--muted);margin:14px 0 0;line-height:1.7;max-width:46ch}
.gtsteps{margin-top:30px;border-top:1px solid var(--line)}
.gtstep{display:grid;grid-template-columns:38px 1fr;gap:16px;padding:19px 0;
  border-bottom:1px solid var(--line);align-items:start}
.gtstep .n{font-family:var(--disp);font-weight:700;font-size:12.5px;color:var(--gold);
  letter-spacing:.1em;padding-top:3px}
/* h3 as well as h4: on /reviews/ these steps sit directly under the section h2, so an h4 is a
   skipped heading level (seocheck.mjs flags h2 -> h4). The rail is the same object either way,
   so the selector takes both and the page uses whichever level is correct in its outline. */
.gtstep h4,.gtstep h3{font-family:var(--disp);font-weight:700;font-size:16px;color:var(--ink);margin:0;line-height:1.3}
.gtstep p{font-size:14.4px;color:var(--muted);margin:7px 0 0;line-height:1.65}
/* the escape hatch, because a form is not everyone's first choice and the phone is faster */
.gtcall{margin-top:26px;padding:20px 22px;background:#fff;border:1px solid var(--line);
  border-left:3px solid var(--gold);border-radius:var(--r)}
.gtcall b{display:block;font-family:var(--disp);font-weight:700;font-size:15.5px;color:var(--ink)}
.gtcall p{font-size:14px;color:var(--muted);margin:7px 0 14px;line-height:1.6}
.gtcall a.t{display:inline-flex;align-items:center;gap:9px;font-family:var(--disp);font-weight:700;
  font-size:19px;color:var(--navy);letter-spacing:-.015em}
.gtcall a.t svg{width:17px;height:17px;color:var(--gold)}

/* ───────── PRICE CARDS (schedule) ─────────
   v1 rendered the money facts as a .factrow, one line of small text on a dark band. For the single
   question every booking form raises, what is this going to cost me, that was far too quiet. */
.pricegrid{display:grid;grid-template-columns:repeat(3,1fr);gap:20px;margin-top:44px}
.pricecard2{background:#fff;border:1px solid var(--line);border-radius:var(--r);padding:30px 28px;
  display:flex;flex-direction:column}
.pricecard2.lead{border-color:rgba(225,165,12,.45);background:linear-gradient(180deg,var(--gold-soft),#fff 58%)}
.pricecard2 .lb{font-family:var(--disp);font-weight:700;font-size:11px;letter-spacing:.15em;
  text-transform:uppercase;color:var(--muted)}
.pricecard2 .amt{font-family:var(--disp);font-weight:700;font-size:clamp(30px,3.2vw,40px);
  color:var(--navy);letter-spacing:-.028em;margin:12px 0 0;line-height:1}
.pricecard2 .amt small{font-size:15px;font-weight:600;color:var(--muted);letter-spacing:0}
.pricecard2 p{font-size:14.4px;color:var(--muted);margin:14px 0 0;line-height:1.65}
.pricecard2 .fine{margin-top:auto;padding-top:18px;font-size:12.4px;color:var(--muted);
  display:inline-flex;align-items:center;gap:8px}
.pricecard2 .fine::before{content:"";width:6px;height:6px;border-radius:50%;background:var(--gold);flex:none}

/* ───────── MAP BAND on these two pages ─────────
   Reuses the owner-approved .axm composition from the AC hub verbatim (ie.css v23). It was built
   there on an explicit "make this section exact" instruction, so it is the one map treatment on
   this site that is already signed off. Only the top margin differs, since here it follows a
   section head rather than a note card. */
.sec .axm{margin-top:44px}

/* ───────── RESPONSIVE (v2) ───────── */
@media(max-width:1080px){
  .gtouch{grid-template-columns:1fr}
  .pricegrid{grid-template-columns:1fr}
}
@media(max-width:900px){
  .proofrail{gap:0 24px}
  .proofrail .pr b{font-size:14px}
}
@media(max-width:640px){
  /* the rail becomes a 2x2 grid rather than a squeezed single row */
  .proofrail{grid-auto-flow:row;grid-template-columns:1fr 1fr;gap:16px 20px}
  .close .proofrail{grid-template-columns:1fr 1fr;gap:16px 20px}
  .rconsole{padding:6px 17px 17px}
  .rc-row{grid-template-columns:36px 1fr;gap:12px}
  .rc-row .tag{grid-column:2;justify-self:start;margin-top:2px}
  .proofrail{gap:0 20px}
  .close .proofrail{gap:0 22px}
}

/* ============================================================================================
   CAREERS BLOCK — /careers/ only, added 2026-08-18
   ============================================================================================
   Built for W2 item 27 once the client supplied the careers content. It sits in this file rather
   than in a fourth stylesheet for the same reason the utility block does: these are components no
   money page loads, and the careers page already links all three layers.

   REUSED RATHER THAN REBUILT, so the page cannot drift from the approved system:
     · the hero, `.rconsole` / `.rc-row` (open positions read as the same object as the reach
       console on /contact-us/, which is exactly what they are: a list of ways in)
     · `.tstrip`, `.head.center`, `.chap`, `.proofrail`, `.close`
     · `.signs` / `.sign` for the nine things we look for
     · `.pricegrid` / `.pricecard2` for the referral milestones. A referral bonus IS a price ladder
     · `.ownr` / `.own-media` / `.own-cred` for the owner's message, so Anderson's block on this
       page is the same object readers already met on the money pages
     · `.gtouch` / `.gtside` / `.gtsteps` / `.gtcall` for the apply band
   Genuinely new below: the reason cards, the role cards, the career ladder, the benefits ledger,
   the apply-mode switch and the full-application disclosure. No new colour is introduced.
   ============================================================================================ */

/* ───────── 1. WHAT YOU ARE JOINING — copy beside a photo card ───────── */
.crjoin{display:grid;grid-template-columns:1.04fr .96fr;gap:clamp(32px,4.2vw,66px);
  align-items:center;margin-top:46px}
.crjoin .vals{display:flex;flex-wrap:wrap;gap:9px;margin-top:28px}
.crjoin .val{display:inline-flex;align-items:center;gap:9px;padding:9px 15px;
  border:1px solid var(--line-2);border-radius:999px;background:var(--surface);
  font-size:14px;font-weight:500;color:var(--ink)}
.crjoin .val::before{content:"";width:6px;height:6px;border-radius:50%;background:var(--gold);flex:none}
.crjoin-media{position:relative}
.crjoin-media .frame{border-radius:20px;overflow:hidden;aspect-ratio:4/3.2;
  border:1px solid var(--line);box-shadow:0 28px 56px rgba(20,56,131,.13)}
.crjoin-media .frame img{width:100%;height:100%;object-fit:cover;object-position:50% 32%}
/* the caption is a real card overlapping the frame, the same device as .own-cred, so the photo
   carries a stated fact rather than being decoration */
.crjoin-media .cap{position:absolute;left:-26px;bottom:-24px;max-width:290px;background:var(--surface);
  border:1px solid var(--line);border-radius:14px;padding:17px 19px;box-shadow:var(--shadow)}
.crjoin-media .cap b{display:block;font-family:var(--disp);font-weight:700;font-size:14.5px;color:var(--navy)}
.crjoin-media .cap span{display:block;font-size:12.8px;color:var(--muted);margin-top:5px;line-height:1.55}

/* ───────── 2. WHY TECHNICIANS CHOOSE US — six cards and one wide card ─────────
   Seven reasons in a three-column grid leaves an orphan in the last row. The seventh is promoted
   to a full-width card that also carries the apply CTA, so the row that would have been a gap is
   the row that asks for the application. */
.crgrid{display:grid;grid-template-columns:repeat(3,1fr);gap:18px;margin-top:46px}
.crcard{background:var(--canvas);border:1px solid var(--line);border-radius:var(--r);padding:26px 24px}
.crcard .ic{width:38px;height:38px;border-radius:11px;background:var(--gold-soft);display:grid;place-items:center}
.crcard .ic svg{width:19px;height:19px;color:var(--gold)}
.crcard h3{font-family:var(--disp);font-weight:700;font-size:17px;color:var(--navy);
  letter-spacing:-.01em;margin:16px 0 0}
.crcard p{font-size:14.6px;color:var(--muted);margin:10px 0 0;line-height:1.66}
.crcard.wide{grid-column:1/-1;display:grid;grid-template-columns:38px 1fr auto;gap:22px;
  align-items:center;background:linear-gradient(118deg,var(--gold-soft) 0%,var(--surface) 58%);
  border-color:rgba(225,165,12,.42)}
.crcard.wide h3{margin:0}
.crcard.wide p{margin:6px 0 0;max-width:64ch}
.crcard.wide .ic{align-self:start}

/* ───────── 3. OPEN ROLES — cards on the dark band ───────── */
.roles{display:grid;grid-template-columns:repeat(3,1fr);gap:16px;margin-top:46px}
.role{display:flex;flex-direction:column;padding:26px 24px 22px;border-radius:16px;
  background:rgba(255,255,255,.055);border:1px solid rgba(255,255,255,.15);
  transition:transform .18s ease,border-color .18s ease,background .18s ease}
.role:hover{transform:translateY(-2px);border-color:rgba(252,201,82,.5);background:rgba(255,255,255,.085)}
.role .lvl{font-family:var(--disp);font-weight:700;font-size:10.5px;letter-spacing:.16em;
  text-transform:uppercase;color:var(--gold-2)}
.role h3{font-family:var(--disp);font-weight:700;font-size:19px;color:#fff;letter-spacing:-.014em;margin:11px 0 0}
.role .rtags{display:flex;flex-wrap:wrap;gap:7px;margin-top:15px}
.role .rtags span{font-size:11.6px;padding:4px 11px;border-radius:999px;
  border:1px solid rgba(255,255,255,.22);color:#c5d2e8;white-space:nowrap}
.role p{font-size:14.5px;color:#b6c4de;margin:16px 0 0;line-height:1.66}
.role .go{margin-top:auto;padding-top:20px;display:inline-flex;align-items:center;gap:9px;
  font-family:var(--disp);font-weight:700;font-size:14.4px;color:var(--gold-2)}
.role .go svg{width:16px;height:16px;transition:transform .18s ease}
.role:hover .go svg{transform:translateX(3px)}
/* the "something else" card. The client asked for it in words: qualified people should write in
   even when their exact role is not listed. Dashed, so it never reads as a sixth vacancy. */
.role.other{background:none;border-style:dashed;border-color:rgba(255,255,255,.26)}
.role.other:hover{transform:none;background:rgba(255,255,255,.04)}

/* ───────── 4. CAREER LADDER — OPTION A, THE RAIL ─────────
   Owner picked "Option A / the rail" off `_concepts/ladder-variations.html` on 2026-08-18, replacing
   the ascending stair that shipped in v1 through v3.

   ONE gold rail, every card on the SAME left edge, and that is the whole point of the change. The
   stair indented each rung 34px further than the last, which drew a diagonal, left a widening empty
   triangle down the left of the band, and by rung eight had pushed the card 238px off the column the
   rest of the page is set to. Seniority is carried by the rail and the numbers instead.

   The five-of-eight fact is now told three times over without a word being read: an open rung gets a
   FILLED node and a gold-edged card, a promote-into rung gets a HOLLOW node and a quiet one, and the
   rail's own gradient turns from gold to hairline at the 62% mark, which is where the open rungs stop.
   The v3 stair told it once, in the chips.
   WARNING: `--gold-ink` is defined in ie-v16.css and nowhere else, so any page using this component
   has to load that layer. The careers page already does. */
.ldr{position:relative;margin-top:46px;padding-left:52px}
.ldr::before{content:"";position:absolute;left:19px;top:12px;bottom:12px;width:2px;border-radius:2px;
  background:linear-gradient(180deg,var(--gold) 0%,var(--gold) 62%,var(--line-2) 62%,var(--line-2) 100%)}
.ldr .rung{position:relative;display:grid;grid-template-columns:1fr auto;gap:18px;align-items:center;
  background:var(--surface);border:1px solid var(--line);border-radius:14px;padding:16px 20px;
  box-shadow:0 6px 18px rgba(20,56,131,.05);transition:transform .18s ease,box-shadow .18s ease}
.ldr .rung + .rung{margin-top:10px}
.ldr .rung:hover{transform:translateX(3px);box-shadow:0 12px 26px rgba(20,56,131,.09)}
/* the node that sits on the rail, and the tick that joins the card to it */
.ldr .rung::before{content:"";position:absolute;left:-41px;top:50%;transform:translateY(-50%);
  width:16px;height:16px;border-radius:50%;background:var(--canvas);border:2px solid var(--line-2)}
.ldr .rung.hiring::before{background:var(--gold);border-color:var(--gold);
  box-shadow:0 0 0 4px rgba(225,165,12,.18)}
.ldr .rung::after{content:"";position:absolute;left:-25px;top:50%;width:16px;height:1.5px;background:var(--line-2)}
.ldr .rung.hiring::after{background:rgba(225,165,12,.55)}
.ldr .ttl{display:flex;align-items:baseline;gap:12px;min-width:0}
.ldr .n{font-family:var(--disp);font-weight:700;font-size:12.5px;color:var(--muted);
  letter-spacing:.08em;flex:none}
.ldr .rung.hiring .n{color:var(--gold-ink)}
.ldr b{font-family:var(--disp);font-weight:600;font-size:16.5px;color:var(--ink);letter-spacing:-.012em}
.ldr .st{font-family:var(--disp);font-weight:700;font-size:10.5px;letter-spacing:.13em;
  text-transform:uppercase;color:var(--muted);border:1px solid var(--line-2);border-radius:999px;
  padding:5px 12px;white-space:nowrap;flex:none}
.ldr .rung.hiring{border-color:rgba(225,165,12,.45)}
.ldr .rung.hiring .st{color:var(--gold-ink);border-color:rgba(225,165,12,.5);background:rgba(252,201,82,.2)}
.ldrnote{margin-top:26px;font-size:14.2px;color:var(--muted);display:inline-flex;align-items:center;gap:10px}
.ldrnote::before{content:"";width:7px;height:7px;border-radius:50%;background:var(--gold);flex:none}

/* ───────── 5. BENEFITS LEDGER — on the dark band ─────────
   Deliberately NOT another `.signs` grid. The nine things we look for already use that hairline
   checklist two sections earlier, and repeating the device would make the two bands read as the
   same list twice. These are bordered rows with a gold rule, and the qualifier pill exists because
   the client wrote "(Qualified Positions)" against two of the ten. */
.benl{display:grid;grid-template-columns:1fr 1fr;gap:12px;margin-top:46px}
.ben{display:flex;align-items:center;justify-content:space-between;gap:14px;
  padding:16px 20px;border-radius:12px;background:rgba(255,255,255,.05);
  border:1px solid rgba(255,255,255,.14);border-left:3px solid rgba(252,201,82,.75)}
.ben b{font-family:var(--disp);font-weight:600;font-size:15.4px;color:#fff;letter-spacing:-.008em}
.ben .q{font-size:11px;letter-spacing:.08em;text-transform:uppercase;color:var(--gold-2);
  border:1px solid rgba(252,201,82,.42);border-radius:999px;padding:4px 10px;white-space:nowrap;flex:none}
.benfoot{margin-top:26px;font-size:14.2px;color:#b6c4de;display:inline-flex;align-items:center;gap:10px}
.benfoot::before{content:"";width:7px;height:7px;border-radius:50%;background:var(--gold-2);flex:none}

/* ───────── 6. THE OWNER'S MESSAGE — a letter inside the shared .ownr band ───────── */
.ownltr{margin-top:30px;max-width:60ch}
.ownltr p{font-size:16px;line-height:1.75;color:#c3cfe6;margin:0 0 16px}
.ownltr p:last-of-type{margin-bottom:0}
.ownsign{margin-top:30px;padding-top:24px;border-top:1px solid rgba(255,255,255,.18);
  display:flex;align-items:center;gap:16px}
.ownsign .nm{font-family:var(--disp);font-weight:700;font-size:17px;color:#fff;letter-spacing:-.012em}
.ownsign .rl{display:block;font-family:var(--body);font-weight:400;font-size:13px;
  color:#9fb0d0;margin-top:4px;letter-spacing:.02em}
.ownsign .mk{width:44px;height:44px;border-radius:50%;border:1.4px solid rgba(252,201,82,.55);
  background:rgba(252,201,82,.1);display:grid;place-items:center;flex:none;
  font-family:var(--disp);font-weight:700;font-size:14px;color:var(--gold-2)}

/* ───────── 7. THE APPLY FORM ─────────
   One form, two modes. The client's own words are "no pressure, no obligation, just a conversation",
   so the conversation mode has to be a real state of the form rather than a paragraph promising one.
   The switch sets data-mode on the form and the role-only fields leave the DOM flow. */
.fmode{display:grid;grid-template-columns:1fr 1fr;gap:6px;margin:0 0 24px;padding:5px;
  background:var(--canvas-2);border-radius:12px}
.fmode input{position:absolute;opacity:0;width:0;height:0}
.fmode label{display:block;padding:11px 14px;border-radius:9px;cursor:pointer;text-align:center;
  font-family:var(--disp);font-weight:600;font-size:14px;color:var(--muted);
  letter-spacing:0;text-transform:none;transition:.16s ease}
.fmode label small{display:block;font-family:var(--body);font-weight:400;font-size:11.6px;
  color:var(--muted);margin-top:3px}
.fmode input:checked + label{background:var(--surface);color:var(--navy);box-shadow:0 4px 12px rgba(20,56,131,.1)}
.fmode input:focus-visible + label{outline:2px solid var(--gold);outline-offset:2px}
.qform[data-mode="talk"] .roleonly{display:none}
/* the file input is the one control browsers style badly enough to look broken next to the rest */
.qform input[type=file]{padding:10px 12px;font-size:14px;font-family:var(--body);cursor:pointer}
.qform input[type=file]::file-selector-button{font-family:var(--disp);font-weight:600;font-size:13px;
  padding:8px 14px;margin-right:12px;border:0;border-radius:8px;background:var(--navy);color:#fff;cursor:pointer}
.qform input[type=file]:hover::file-selector-button{background:var(--navy-2)}

/* the full application, disclosed rather than dumped. Every field inside is a field the client
   already collects on the live /careers/ form, so opening this loses nothing they have today. */
.fullapp{margin-top:22px;border:1px dashed var(--line-2);border-radius:12px;background:var(--canvas)}
.fullapp > summary{list-style:none;cursor:pointer;display:flex;align-items:flex-start;
  justify-content:space-between;gap:14px;padding:15px 18px;
  font-family:var(--disp);font-weight:600;font-size:14.8px;color:var(--navy)}
.fullapp > summary::-webkit-details-marker{display:none}
.fullapp > summary small{display:block;font-family:var(--body);font-weight:400;font-size:12.4px;
  color:var(--muted);margin-top:4px;line-height:1.55}
.fullapp > summary .ic{width:24px;height:24px;flex:none;border-radius:50%;border:1px solid var(--line-2);
  display:grid;place-items:center;position:relative;margin-top:2px}
.fullapp > summary .ic::before,.fullapp > summary .ic::after{content:"";position:absolute;
  background:var(--navy);border-radius:2px;transition:.2s}
.fullapp > summary .ic::before{width:10px;height:1.6px}
.fullapp > summary .ic::after{width:1.6px;height:10px}
.fullapp[open] > summary{border-bottom:1px solid var(--line)}
.fullapp[open] > summary .ic{background:var(--gold);border-color:var(--gold)}
.fullapp[open] > summary .ic::after{opacity:0}
.fullapp .fbody{padding:22px 18px 24px}
.fset{border:0;padding:0;margin:0 0 24px;min-width:0}
.fset:last-child{margin-bottom:0}
.fset legend{font-family:var(--disp);font-weight:700;font-size:11px;letter-spacing:.15em;
  text-transform:uppercase;color:var(--gold);padding:0;margin-bottom:14px}
.row3{display:grid;grid-template-columns:1fr 1fr 1fr;gap:14px}
/* a yes/no pair reuses the chip look from the booking form so the page has one control language */
.fyn{display:flex;gap:8px;flex-wrap:wrap;margin-top:2px}
.emp{border:1px solid var(--line);border-radius:12px;padding:18px 18px 6px;background:var(--surface);margin-bottom:14px}
.emp:last-child{margin-bottom:0}
.emp .eh{font-family:var(--disp);font-weight:700;font-size:12.5px;letter-spacing:.05em;
  color:var(--navy);margin:0 0 14px}

/* ───────── 8. RESPONSIVE ───────── */
@media(max-width:1080px){
  .crjoin{grid-template-columns:1fr;gap:44px}
  .crjoin-media .cap{left:auto;right:16px;bottom:-20px}
  .crgrid{grid-template-columns:1fr 1fr}
  .roles{grid-template-columns:1fr 1fr}
}
@media(max-width:860px){
  .benl{grid-template-columns:1fr}
  .crcard.wide{grid-template-columns:38px 1fr;gap:18px}
  .crcard.wide .btn{grid-column:2}
  .row3{grid-template-columns:1fr 1fr}
}
@media(max-width:640px){
  .crgrid,.roles{grid-template-columns:1fr}
  /* the rail pulls in and the status chip drops under the title. At 390px a chip on the same row
     squeezes "Lead service technician" to two words and a hyphen. */
  .ldr{padding-left:38px}
  .ldr::before{left:13px}
  .ldr .rung{grid-template-columns:1fr;gap:9px;padding:14px 16px}
  .ldr .rung::before{left:-33px}
  .ldr .rung::after{left:-19px;width:12px}
  .ldr .st{justify-self:start}
  .row3{grid-template-columns:1fr}
  .fmode{grid-template-columns:1fr}
  .ben{align-items:flex-start;flex-direction:column;gap:9px}
  .crjoin-media .cap{position:static;max-width:none;margin-top:16px;box-shadow:none}
}

/* ───────── 9. CAREERS v2 — the fixes the screenshots produced ─────────
   Four of these came out of reading the rendered page rather than the markup, which is the only
   way any of them would have been found. */

/* 🔴 `.row2` DOES NOTHING OUTSIDE `.rch-form`. ie.css defines it as `.rch-form .row2`, so every
   two-up field pair inside a plain `.qform` renders as two stacked full-width rows. On the careers
   form that put first name, last name, phone and email on four separate lines and made an already
   long application look endless. Scoped to this form rather than fixed globally: /contact-us/ and
   /schedule/ carry the same latent bug and they are approved, shipped pages, so widening the
   selector would silently restyle two signed-off forms.
   ⚠ FLAG, NOT FIXED HERE: `.row2` is inert on /contact-us/ and /schedule/ too. */
#apply-form .row2{display:grid;grid-template-columns:1fr 1fr;gap:0 14px}
@media(max-width:560px){ #apply-form .row2{grid-template-columns:1fr} }

/* WARNING: THE v2 `.rung{max-width:660px}` CAP IS GONE ON PURPOSE. It existed because the stair
   drifted right as it descended, so a full-width rung left a large empty gap beside the deepest ones.
   Option A puts every card on the same left edge, so re-adding a cap would only produce a ragged
   right margin. */

/* NINE traits in a two-column grid orphans the ninth in a half-empty final row. Nine is 3x3, and
   the shared `.signs` border rules are keyed to `nth-child(2n)`, so a three-up grid needs its
   dividers re-keyed to 3n. Scoped to this section: `.signs` is a shared component and every other
   page that uses it has an even count. */
#traits .signs{grid-template-columns:repeat(3,1fr)}
#traits .sign{padding:26px 26px 26px 26px}
#traits .sign:not(:nth-child(2n)){border-right:0}
#traits .sign:not(:nth-child(3n)){border-right:1px solid var(--line)}
#traits .sign:nth-child(3n+1){padding-left:0}
/* ⚠ NO `+ .sign` RULE HERE, and that is the point. The shared layer has
   `.sign:not(:nth-child(2n)) + .sign{padding-left:30px}`, which in a THREE-column grid lands on
   cells 2, 4, 6 and 8, so cell 4 is the first cell of row two and it was indented 26px past the
   cell above it. The whole middle row sat visibly off the column. `#traits .sign` carries an id, so
   it outranks the shared sibling rule for every cell, and the `3n+1` rule above zeroes the first
   column. Adding a sibling rule back here re-breaks the alignment. */
@media(max-width:1080px){
  /* two-up, with the dividers keyed back to 2n */
  #traits .signs{grid-template-columns:1fr 1fr}
  #traits .sign:not(:nth-child(3n)){border-right:0}
  #traits .sign:not(:nth-child(2n)){border-right:1px solid var(--line)}
  #traits .sign:nth-child(2n+1){padding-left:0}
}
@media(max-width:640px){
  #traits .signs{grid-template-columns:1fr}
  #traits .sign,#traits .sign:not(:nth-child(2n)){border-right:0;padding:22px 0}
}

/* The owner band's portrait crop put the SECOND technician back-to-camera across the right third
   of the frame, which is the exact shot class the owner has rejected four times. Anderson is
   camera-forward and smiling at roughly 30% across in AND10, so the crop is pulled left onto him
   and the other technician falls mostly outside the frame. */
.ownr .own-media .frame img{object-position:27% 32%}

/* The application is taller than the column beside it, so "what to have ready" scrolled away and
   left a long empty gutter. Sticky keeps the answer beside the question for the whole form. */
#apply .gtside{position:sticky;top:104px}
@media(max-width:1080px){ #apply .gtside{position:static} }

/* `.crjoin` carries a 46px top margin for the case where a section head sits above it. On the
   careers page the head is INSIDE it, so that margin was stacking on the section's own padding. */
.sec > .wrap > .crjoin:first-child{margin-top:0}

/* ============================================================================================
   v3 — LAYERED HERO (2026-08-18). Owner picked this direction after rejecting v1 and v2.

   THE THREE THINGS THE OWNER NAMED, and what each one changes here:

   1. "IMAGERY IS WEAK."  v1 and v2 used .hero-photo: a photograph behind a 90%-opacity navy
      grade. That is a TEXTURE, not a photograph. You could not read Anderson's face, the van, or
      anything the picture was there to prove. v3 stops scrimming photography altogether. The hero
      ground is a clean navy gradient, and the photograph becomes a CRISP FRAMED PLANE at full
      saturation with a cream border, plus a circular van badge. The pictures are now legible,
      which is the only reason to have them.

   2. "COMPOSITION LACKS DEPTH."  Everything sat in flat rows inside one container. The hero right
      column is now a four-plane stack that reads front to back: a dotted navy plane at the back,
      the photograph over it, the reach console over that, and a circular van badge breaking the
      console's right edge. Planes deliberately cross the column gutter.

   3. "TOO PLAIN / TEMPLATED."  Left-copy / right-card is the most common layout on the web. The
      stack breaks the grid instead of filling it: the photo hangs into the gutter, the badge
      overhangs the card, and the dotted plane runs past the container edge.

   ⚠ Built from devices this site ALREADY OWNS, not new inventions. The dotted navy plane is
     .axm-deco and the circular photo badge is .axm-van, both from the AC hub map band the owner
     signed off on 2026-08-17. Same language, applied to the hero.
   ⚠ STILL NO SHAPE DIVIDERS. Sections meet on a flat edge. That decision stands.
   ============================================================================================ */

/* 🔴 overflow:HIDDEN, and it was visible for one sweep before being corrected.
   The reasoning for visible was that a layered hero needs planes to hang past its edges. It does
   not: everything here hangs into the COLUMN GUTTER, which is inside the hero, and only the dotted
   plane reaches past the container on the right. With overflow visible that plane spilled 30px
   past the VIEWPORT at 1200px and below, where the centred wrap has only 28px of side margin left
   to hang into. sweep.mjs caught it at seven widths. Clipping at the hero edge also renders the
   plane exactly as intended, running off the side of the section.
   ⚠ The glows still live in .glow rather than on ::before/::after, which is harmless and keeps the
   two concerns separate if this ever needs to open up again. */
.hero-layer{overflow:hidden;background:linear-gradient(158deg,#0a1c3f 0%,#143883 55%,#0f2a5e 100%)}
.hero-layer::before,.hero-layer::after{display:none}
.hero-layer .glow{position:absolute;inset:0;overflow:hidden;pointer-events:none;z-index:0}
.hero-layer .glow::before{content:"";position:absolute;top:-170px;right:-150px;width:520px;height:520px;
  border-radius:50%;background:radial-gradient(circle,rgba(252,201,82,.16),transparent 68%)}
.hero-layer .glow::after{content:"";position:absolute;left:-130px;bottom:-210px;width:520px;height:520px;
  border-radius:50%;background:radial-gradient(circle,rgba(255,255,255,.07),transparent 66%)}
.hero-layer .wrap{position:relative;z-index:1;align-items:center}
.hero-layer .hleft{position:relative;z-index:2}

/* ───────── THE STACK ─────────
   Four planes. The console is the only one in normal flow, so the stack's height is the console's
   height plus the top padding the photo needs. Everything else is absolute against it. */
.hstack{position:relative;padding-top:210px}

/* back plane — the dotted navy panel, .axm-deco's treatment. Runs past the container on the right. */
.hstack .plane{position:absolute;z-index:0;top:0;right:-58px;width:66%;height:250px;border-radius:20px;
  background-color:#0f2a5e;background-image:radial-gradient(rgba(252,201,82,.30) 1.4px,transparent 1.5px);
  background-size:13px 13px;pointer-events:none}

/* the photograph. FULL SATURATION, no scrim, cream border so it reads as a print on the navy.
   Hangs 56px into the column gutter, which is 60px wide, so it never touches the copy. */
.hstack .shot{position:absolute;z-index:2;top:22px;left:-56px;width:60%;aspect-ratio:4/3;
  border-radius:18px;overflow:hidden;border:4px solid var(--canvas);
  box-shadow:0 30px 60px rgba(0,0,0,.42)}
.hstack .shot img{width:100%;height:100%;object-fit:cover;display:block}
/* Caption chip. ⚠ TOP-RIGHT, and both other corners were tried and failed. As a bottom gradient
   band the console sliced it in half and the fold read "Ander" and stopped. Moved to top-left, the
   van badge then covered its first two words. Top-right is the one corner of this photo that no
   other plane reaches. General rule for the stack: planes may overlap planes, never type. */
.hstack .shot .cap{position:absolute;right:12px;top:12px;padding:7px 12px;border-radius:999px;
  background:rgba(6,18,44,.78);backdrop-filter:blur(4px);
  font-family:var(--disp);font-weight:600;font-size:11px;letter-spacing:.05em;color:#fff}

/* the console sits in flow and lands over the photo's bottom edge */
.hstack .rconsole{position:relative;z-index:3}

/* circular van badge, .axm-van's treatment, breaking the console's right edge */
/* ⚠ THE BADGE MUST STAY INSIDE THE COLUMN GUTTER. Two positions were wrong before this one.
   At right:-30px it landed on the console's header row and covered the opening hours. At
   left:-88px it cleared the console but reached 28px INTO the copy column and sat on the H1,
   because the grid gutter is only 60px wide. -58px is the widest leftward hang the gutter allows.
   THREE vertical positions were wrong before this one, and every failure was the same failure:
   the badge landed on TEXT. On the console header it covered the opening hours, then it covered
   the "How booking works" label, and further up it sat on the H1. It now overhangs the PHOTO's
   top-left corner, where the only things behind it are the navy ground and the photo itself.
   ⚠ Rule for this component: the badge may overlap planes, never type. If the hero grid gap
   changes, the -58px has to change with it, because that number is the gutter width minus 2. */
.hstack .vbadge{position:absolute;z-index:4;left:-58px;top:-26px;
  width:104px;height:104px;border-radius:50%;overflow:hidden;border:4px solid var(--canvas);
  box-shadow:0 16px 34px rgba(6,18,44,.42);pointer-events:none}
.hstack .vbadge img{width:100%;height:100%;object-fit:cover;display:block}

/* a small gold credential chip pinned to the plane, top right */
.hstack .chip{position:absolute;z-index:3;right:-18px;top:-16px;
  display:inline-flex;align-items:center;gap:8px;padding:9px 15px;border-radius:999px;
  background:var(--gold);color:#1c1403;font-family:var(--disp);font-weight:700;font-size:11.5px;
  letter-spacing:.09em;text-transform:uppercase;box-shadow:0 12px 26px rgba(6,18,44,.34)}

/* the console loses its own drop shadow inside the stack: four stacked shadows reads as mush.
   The photo and the badge carry the depth, the console carries the hairline. */
.hstack .rconsole{box-shadow:0 22px 46px rgba(6,18,44,.34)}

/* ───────── LAYERED FORM SECTION ─────────
   Same complaint, same fix, one section down: the form card was a rectangle in a two-column grid.
   It now sits over a dotted plane that runs out past its top-left corner. */
.gtouch .formcard{position:relative;z-index:1}
.gtwrap{position:relative}
.gtwrap .plane{position:absolute;z-index:0;top:-26px;left:-30px;width:210px;height:170px;border-radius:18px;
  background-color:#0f2a5e;background-image:radial-gradient(rgba(252,201,82,.30) 1.4px,transparent 1.5px);
  background-size:13px 13px;pointer-events:none}

/* ───────── LEAD PRICE CARD LIFTS OUT OF THE ROW ─────────
   Three identical rectangles is the flat-row problem again. The lead card breaks the line. */
.pricegrid{align-items:center}
.pricecard2.lead{transform:translateY(-14px);padding-top:38px;padding-bottom:38px;
  box-shadow:0 26px 52px rgba(20,56,131,.13)}

/* ───────── RESPONSIVE (v3) ─────────
   ⚠ The stack UNSTACKS rather than shrinking. Absolute planes that overlap beautifully at 1440
   become a pile at 900. Below the breakpoint the photo becomes a normal block above the console,
   the dotted plane and the badge come off, and the section is a plain two-row layout again. */
@media(max-width:1080px){
  .hstack{padding-top:0}
  .hstack .plane,.hstack .vbadge,.hstack .chip{display:none}
  .hstack .shot{position:relative;top:auto;left:auto;width:100%;aspect-ratio:16/9;margin-bottom:-46px}
  .hstack .rconsole{margin-top:0}
  .gtwrap .plane{display:none}
  .pricecard2.lead{transform:none}
}
@media(max-width:640px){
  .hstack .shot{aspect-ratio:4/3;margin-bottom:-34px;border-width:3px}
}

/* ============================================================================================
   v4 — PRECISION-DENSITY CONTACT (2026-08-18)

   Owner rejected v1, v2, v3 and all six concept directions, then named the bar directly:
   MATCH OR BEAT precisionairhc.com/contact/, and make it MUCH RICHER than anything shown so far.

   Every one of my six concepts was on the restrained end, which is why they all missed: the owner
   had already said "too plain / templated" and I answered with more minimalism. This layer goes
   the other way on purpose.

   PRECISION'S DEVICE INVENTORY, read off the live page rather than remembered:
     · pill badge above the H1 (location + family-owned-since)
     · H1 with a brand-colour accent word
     · one large CTA, then a row of three check-chips
     · a Google rating cluster
     · a dedicated dark TRUST BAR, four items, icons and dividers
     · a section eyebrow set on a rule
     · an H2 with a second accent word
     · an elevated form card with real labels, a required-fields note and a consent line
     · a "reach us directly" card, five rows, each an alternating colour icon tile
     · a map card
     · curved section edges throughout
   All of it is rebuilt here in IE's navy / gold / warm-canvas language, not copied in Precision's
   orange and blue.

   🔴 ONE DEVICE DELIBERATELY NOT COPIED: the curved section edges. Precision uses them everywhere,
   and they are a big part of why that page feels finished. This owner ruled AGAINST shape dividers
   on the AC repair page after three passes, and the note says not to re-add one without an explicit
   ask. Choosing Precision as the reference is close to that ask but is not literally it, so the
   richness here comes from everything else and the sections still meet on a flat edge.
   ⚠ If the owner wants them, they are one rule away and this comment is the place to start.
   ============================================================================================ */

/* ───────── RICH HERO — full-bleed photograph, centred, Precision's arrangement ─────────
   ⚠ The grade is LIGHTER than the .hero-photo grade this build used before. That one ran to ~90%
   and turned every photograph into navy mush, which is exactly what the owner called weak imagery.
   This one is a vertical pair: dark enough at top and bottom to hold type, near clear through the
   middle band where the subjects are. Contrast still has to pass bgcontrast.mjs. */
.rhero{position:relative;overflow:hidden;background:#0a1c3f;text-align:center}
.rhero .bg{position:absolute;inset:0;z-index:0}
/* ⚠ 14%, NOT 38%. The hero is ~2.2:1 and the source is 3:2, so cover crops ~316px of height.
   At 38% that took 120px off the TOP and cut the technician's head off — a decapitated subject is
   worse than no photograph. 14% takes ~44px and keeps both faces whole. Re-check this number if
   the hero's height ever changes, because it is derived from the crop, not chosen by eye. */
.rhero .bg img{width:100%;height:100%;object-fit:cover;object-position:50% 14%}
/* 🔴 TWO AXES, NOT ONE — and the measurement is why.
   A single vertical grade at ~55% through the middle band measured 1.20:1 to 2.85:1 on the hero
   type, because the photograph's bright areas (a coral shirt, sunlit grass) sat at luminance 233
   directly behind white text. Every one of the four hero elements FAILED. A heavier flat grade
   fixes contrast and brings back exactly the murk the owner called weak imagery.
   So: dark down the CENTRE COLUMN where the centred type lives, near-clear at the left and right
   thirds where the subjects are. The photograph stays legible where it matters and the type sits
   on ~0.91 combined alpha. Re-measure with the contrast probe if either stop moves. */
.rhero .bg::after{content:"";position:absolute;inset:0;background:
  linear-gradient(180deg,rgba(6,18,44,.86) 0%,rgba(6,18,44,.42) 26%,rgba(6,18,44,.45) 70%,rgba(6,18,44,.90) 100%),
  linear-gradient(90deg,rgba(6,18,44,.20) 0%,rgba(6,18,44,.80) 27%,rgba(6,18,44,.84) 73%,rgba(6,18,44,.20) 100%)}
.rhero .wrap{position:relative;z-index:1;padding:clamp(46px,5vw,86px) 28px clamp(40px,4.4vw,70px);
  display:flex;flex-direction:column;align-items:center}

/* pill badge above the headline */
.rh-pill{display:inline-flex;align-items:center;gap:10px;padding:9px 18px;border-radius:999px;
  background:rgba(250,248,243,.12);border:1px solid rgba(252,201,82,.42);backdrop-filter:blur(6px);
  font-family:var(--disp);font-weight:600;font-size:12.5px;letter-spacing:.05em;color:#fff}
.rh-pill::before{content:"";width:7px;height:7px;border-radius:50%;background:var(--gold-2);flex:none;
  box-shadow:0 0 0 4px rgba(252,201,82,.22)}

.rhero h1{font-family:var(--disp);font-weight:700;color:#fff;letter-spacing:-.032em;
  font-size:clamp(34px,4.6vw,64px);line-height:1.03;margin:24px 0 0;max-width:19ch}
.rhero h1 em{font-style:normal;color:var(--gold-2)}
.rhero .sub{color:#d8e2f2;font-size:clamp(16px,1.4vw,18.5px);line-height:1.62;margin:20px 0 0;max-width:58ch}
.rhero .act{display:flex;gap:14px;flex-wrap:wrap;justify-content:center;margin-top:30px}
.rhero .act .btn{padding:16px 30px;font-size:16px}

/* three check chips under the CTA */
.rh-chips{display:flex;gap:10px 26px;flex-wrap:wrap;justify-content:center;margin-top:26px}
.rh-chips span{display:inline-flex;align-items:center;gap:9px;font-size:14px;font-weight:500;color:#e3eaf7}
.rh-chips svg{width:19px;height:19px;flex:none;color:#1c1403;background:var(--gold-2);border-radius:50%;padding:3.5px}

/* rating cluster. ⚠ NO INVENTED REVIEWER AVATARS. Precision shows faces; we have no reviewer
   photographs and no permission, and crew faces standing in for reviewers would be a fabrication.
   Stars and the count only, which are the two facts we actually hold. */
.rh-score{display:inline-flex;align-items:center;gap:14px;margin-top:30px;padding:11px 22px 11px 16px;
  border-radius:999px;background:rgba(250,248,243,.96);box-shadow:0 16px 34px rgba(0,0,0,.34)}
.rh-score .n{font-family:var(--disp);font-weight:700;font-size:25px;color:var(--navy);line-height:1}
.rh-score .st{color:var(--gold);font-size:14px;letter-spacing:2px;line-height:1;display:block}
.rh-score .sm{display:block;font-size:12.5px;color:var(--muted);margin-top:4px;text-align:left}

/* ───────── TRUST BAR — dark, four credentials, icon tiles and dividers ───────── */
.tbar{background:#0f2a5e;border-top:1px solid rgba(255,255,255,.1)}
.tbar .wrap{display:grid;grid-template-columns:repeat(4,1fr);gap:0;padding:0 28px}
.tbar .ti{display:flex;align-items:center;gap:14px;padding:24px 26px;border-right:1px solid rgba(255,255,255,.13)}
.tbar .ti:first-child{padding-left:0}
.tbar .ti:last-child{border-right:0;padding-right:0}
.tbar .ic{width:40px;height:40px;flex:none;border-radius:11px;background:rgba(252,201,82,.14);
  border:1px solid rgba(252,201,82,.3);display:grid;place-items:center}
.tbar .ic svg{width:19px;height:19px;color:var(--gold-2)}
.tbar b{display:block;font-family:var(--disp);font-weight:700;font-size:14.5px;color:#fff;line-height:1.25}
.tbar span{display:block;font-size:12.2px;color:#9dafd1;margin-top:3px}

/* ───────── SECTION EYEBROW SET ON A RULE ───────── */
.eyerule{display:flex;align-items:center;justify-content:center;gap:16px;margin-bottom:16px}
.eyerule::before,.eyerule::after{content:"";height:1px;width:44px;background:var(--line-2)}
.eyerule span{font-family:var(--disp);font-weight:700;font-size:11.5px;letter-spacing:.2em;
  text-transform:uppercase;color:var(--gold)}
.sec-dark .eyerule::before,.sec-dark .eyerule::after{background:rgba(255,255,255,.28)}
.sec-dark .eyerule span{color:var(--gold-2)}
.h2accent em{font-style:normal;color:var(--navy)}
.sec-dark .h2accent em{color:var(--gold-2)}

/* ───────── ELEVATED FORM CARD ───────── */
.gtcard{background:#fff;border:1px solid var(--line);border-radius:22px;
  padding:clamp(28px,2.9vw,42px);box-shadow:0 30px 64px rgba(20,56,131,.11)}
.gtcard h3{font-family:var(--disp);font-weight:700;font-size:23px;color:var(--ink);margin:0;letter-spacing:-.018em}
.gtcard .qs{font-size:14.8px;color:var(--muted);margin:10px 0 0;line-height:1.6}
.gtcard .req{display:block;font-size:12px;color:var(--gold);margin:16px 0 20px;font-weight:500}
.gtcard .qform{background:none;border:0;padding:0;box-shadow:none;border-radius:0}
.gtcard .qform label .rq{color:var(--gold);margin-left:3px}
.gtcard .foot{margin-top:16px;text-align:center;font-size:13.4px;color:var(--muted)}
.gtcard .foot a{font-family:var(--disp);font-weight:700;color:var(--navy)}

/* ───────── REACH US DIRECTLY — five rows, alternating icon tiles ───────── */
.rdcard{background:#fff;border:1px solid var(--line);border-radius:22px;padding:clamp(24px,2.4vw,32px);
  box-shadow:0 20px 44px rgba(20,56,131,.07)}
.rdcard h3{font-family:var(--disp);font-weight:700;font-size:20px;color:var(--ink);margin:0 0 6px;letter-spacing:-.016em}
.rdrow{display:grid;grid-template-columns:46px 1fr;gap:16px;align-items:start;
  padding:19px 0;border-bottom:1px solid var(--line)}
.rdrow:last-child{border-bottom:0;padding-bottom:4px}
.rdrow .ic{width:44px;height:44px;border-radius:12px;display:grid;place-items:center;flex:none}
.rdrow .ic svg{width:19px;height:19px}
/* alternating tiles, navy then gold, straight down the card. Precision alternates blue and orange. */
.rdrow:nth-child(odd) .ic{background:rgba(20,56,131,.10)}
.rdrow:nth-child(odd) .ic svg{color:var(--navy)}
.rdrow:nth-child(even) .ic{background:var(--gold-soft)}
.rdrow:nth-child(even) .ic svg{color:var(--gold)}
.rdrow .k{font-family:var(--disp);font-weight:700;font-size:14.5px;color:var(--ink);display:block}
.rdrow .v{display:block;font-family:var(--disp);font-weight:700;font-size:16px;color:var(--navy);
  margin-top:4px;letter-spacing:-.012em;overflow-wrap:anywhere}
.rdrow .v.long{font-size:14.4px}
.rdrow p{font-size:13.2px;color:var(--muted);margin:6px 0 0;line-height:1.55}

/* ───────── SMALL MAP CARD, under the reach card ───────── */
.mapmini{margin-top:22px;background:#fff;border:1px solid var(--line);border-radius:22px;overflow:hidden;
  box-shadow:0 20px 44px rgba(20,56,131,.07)}
.mapmini .frame{position:relative;height:230px;background:var(--canvas-2)}
.mapmini iframe{position:absolute;inset:0;width:100%;height:100%;border:0}
.mapmini .bar{display:flex;align-items:center;gap:14px;padding:16px 20px;border-top:1px solid var(--line)}
.mapmini .bar b{font-family:var(--disp);font-weight:700;font-size:14px;color:var(--ink);display:block}
.mapmini .bar span{display:block;font-size:12.6px;color:var(--muted);margin-top:2px}
.mapmini .bar .btn{margin-left:auto;flex:none}

/* ───────── STEP RAIL — four numbered medallions on a connecting line ─────────
   The "what happens next" steps were a plain vertical list in v2 and v3. As a horizontal rail with
   a rule running through the medallions they read as a process rather than as four paragraphs. */
.steprail{position:relative;display:grid;grid-template-columns:repeat(4,1fr);gap:26px;margin-top:52px}
.steprail::before{content:"";position:absolute;left:8%;right:8%;top:31px;height:2px;
  background:repeating-linear-gradient(90deg,var(--line-2) 0 7px,transparent 7px 14px)}
.sec-dark .steprail::before{background:repeating-linear-gradient(90deg,rgba(255,255,255,.3) 0 7px,transparent 7px 14px)}
.steprail .st{position:relative;text-align:center;padding:0 8px}
.steprail .md{width:62px;height:62px;margin:0 auto;border-radius:50%;display:grid;place-items:center;
  background:var(--canvas);border:2px solid var(--gold);font-family:var(--disp);font-weight:700;
  font-size:19px;color:var(--navy);position:relative;z-index:1}
.sec-dark .steprail .md{background:#0f2a5e;border-color:var(--gold-2);color:#fff}
/* h3, not h4: these follow the section h2 directly, and h2 -> h4 is a skipped level. */
.steprail h3{font-family:var(--disp);font-weight:700;font-size:16.5px;color:var(--ink);margin:18px 0 0}
.sec-dark /* h3, not h4: these follow the section h2 directly, and h2 -> h4 is a skipped level. */
.steprail h3{color:#fff}
.steprail p{font-size:13.8px;color:var(--muted);margin:9px 0 0;line-height:1.6}
.sec-dark .steprail p{color:#b3c1dc}

/* ───────── SCORE BAND — REMOVED 2026-08-18 ─────────
   A bespoke rating band sat before the FAQ on /contact-us/. The owner asked for the SHARED
   reviews section instead, after the FAQ, so the band and its ~30 rules are gone rather than
   left behind as dead CSS. revcheck.mjs is the reason this matters: one page carrying its own
   reviews treatment is a site-wide drift failure, not a local choice. */

/* ───────── RESPONSIVE (v4) ───────── */
@media(max-width:1080px){
  .tbar .wrap{grid-template-columns:1fr 1fr}
  .tbar .ti{padding:20px 22px;border-bottom:1px solid rgba(255,255,255,.13)}
  .tbar .ti:nth-child(2){border-right:0;padding-right:0}
  .tbar .ti:nth-child(3){padding-left:0}
  .tbar .ti:nth-child(3),.tbar .ti:nth-child(4){border-bottom:0}
  .steprail{grid-template-columns:1fr 1fr;gap:34px 26px}
  .steprail::before{display:none}
}
@media(max-width:640px){
  .tbar .wrap{grid-template-columns:1fr}
  .tbar .ti{padding:18px 0;border-right:0}
  .tbar .ti:nth-child(3){border-bottom:1px solid rgba(255,255,255,.13)}
  .steprail{grid-template-columns:1fr}
  .rh-chips{gap:9px 18px}
  .rh-score{gap:11px;padding:10px 17px 10px 13px}
  .mapmini .bar{flex-wrap:wrap}
  .mapmini .bar .btn{margin-left:0;width:100%;justify-content:center}
}

/* ============================================================================================
   CAREERS v3 — FORM VARIETY PASS (2026-08-18, on owner feedback "design needs to be better")
   ============================================================================================
   THE DIAGNOSIS, measured off the rendered page rather than felt. Sections 3 to 8 ran as six
   grid-shaped objects back to back: card grid, card grid, stair, icon grid, pill list, price cards.
   Copy quality could not rescue that, because the complaint is about FORM, not words. Two of the six
   were also weak on their own terms:
     · benefits was ten identical bordered pills in two columns, no grouping and no hierarchy, and
       the backdrop photograph was doing no work at all;
     · the referral band was three EQUAL cards where the third is the SUM of the first two, so a
       sequence was drawn as a price table and the reader had to read it to understand the order.
   v3 replaces four objects with four DIFFERENT shapes, so the middle of the page alternates
   asymmetric > sheet > grouped columns > rail instead of repeating one rhythm:
     1. `.rsn`     reasons: one large photo panel plus a numbered hairline list (asymmetric)
     2. `.std`     what we look for: ONE signed standard sheet, which also removes the page's
                   second icon grid, the thing that made two sections blur together
     3. `.bgrp`    benefits: four titled groups, so ten flat items gain hierarchy
     4. `.reftl`   referral: a timeline rail with the milestones ON it
   The hero also goes back to the site's full 62px H1. v2 had scaled it down to fit a longer
   approved headline, which quietly made this page's fold weaker than every other page on the site.
   No new colour. Every object is built from the locked tokens.
   ============================================================================================ */

/* ───────── 1. REASONS: asymmetric photo panel + numbered list ───────── */
.rsn{display:grid;grid-template-columns:.9fr 1.1fr;gap:clamp(28px,3.6vw,58px);margin-top:46px;align-items:stretch}
.rsn-lead{position:relative;overflow:hidden;border-radius:20px;min-height:440px;
  display:flex;flex-direction:column;justify-content:flex-end;box-shadow:0 26px 54px rgba(20,56,131,.16)}
.rsn-lead img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;object-position:62% 34%}
.rsn-lead .scr{position:absolute;inset:0;
  background:linear-gradient(to top,rgba(10,26,58,.95) 0%,rgba(10,26,58,.72) 42%,rgba(10,26,58,.14) 100%)}
.rsn-lead .bd{position:relative;padding:clamp(24px,2.6vw,34px)}
.rsn-lead .lb{display:inline-flex;align-items:center;gap:9px;font-family:var(--disp);font-weight:700;
  font-size:10.5px;letter-spacing:.16em;text-transform:uppercase;color:var(--gold-2)}
.rsn-lead .lb::before{content:"";width:18px;height:1.5px;background:var(--gold-2)}
.rsn-lead h3{font-family:var(--disp);font-weight:700;font-size:clamp(21px,2.3vw,27px);color:#fff;
  letter-spacing:-.018em;margin:14px 0 0}
.rsn-lead p{font-size:15.2px;line-height:1.68;color:#c6d2e8;margin:12px 0 0;max-width:34ch}
.rsn-lead .go{margin-top:20px;display:inline-flex;align-items:center;gap:9px;font-family:var(--disp);
  font-weight:700;font-size:14.4px;color:var(--gold-2)}
.rsn-lead .go svg{width:16px;height:16px;transition:transform .18s ease}
.rsn-lead:hover .go svg{transform:translateX(3px)}
/* the list. Big hairline numerals rather than icon chips, which is what stops this reading as
   another card grid. */
.rsn-list{align-self:center}
.rsn-row{display:grid;grid-template-columns:56px 1fr;gap:18px;padding:21px 0;
  border-bottom:1px solid var(--line);align-items:start}
.rsn-row:first-child{border-top:1px solid var(--line)}
.rsn-row .n{font-family:var(--disp);font-weight:700;font-size:27px;line-height:.9;
  color:var(--line-2);letter-spacing:-.04em;transition:color .18s ease}
.rsn-row:hover .n{color:var(--gold)}
.rsn-row h3{font-family:var(--disp);font-weight:700;font-size:16.6px;color:var(--navy);
  letter-spacing:-.01em;margin:0}
.rsn-row p{font-size:14.6px;line-height:1.66;color:var(--muted);margin:7px 0 0}

/* ───────── 2. THE STANDARD SHEET: one object, signed ─────────
   Nine ticks in a shared `.signs` grid was the page's SECOND icon grid and the two blurred together.
   As one sheet it becomes a thing rather than a list, and the owner's mark at the foot is the point:
   this is the standard he holds the crew to, so his name belongs on it. */
.std{margin-top:46px;background:var(--canvas);border:1px solid var(--line);border-radius:20px;
  padding:clamp(24px,2.9vw,40px);box-shadow:0 20px 44px rgba(20,56,131,.07)}
.std-hd{display:flex;align-items:baseline;justify-content:space-between;gap:20px;flex-wrap:wrap;
  padding-bottom:18px;border-bottom:2px solid var(--navy)}
.std-hd b{font-family:var(--disp);font-weight:700;font-size:12px;letter-spacing:.18em;
  text-transform:uppercase;color:var(--navy)}
.std-hd span{font-size:12.8px;color:var(--muted)}
.std-grid{display:grid;grid-template-columns:repeat(3,1fr);gap:0 clamp(22px,3vw,46px)}
.std-item{display:grid;grid-template-columns:22px 1fr;gap:12px;padding:17px 0;align-items:start;
  border-bottom:1px dashed var(--line-2)}
/* the last row of each column loses its dash, so the sheet closes on a clean edge */
.std-item:nth-last-child(-n+3){border-bottom:0}
.std-item .tk{width:22px;height:22px;border-radius:50%;background:var(--gold-soft);
  border:1px solid rgba(225,165,12,.4);display:grid;place-items:center;margin-top:1px}
.std-item .tk svg{width:12px;height:12px;color:var(--gold)}
.std-item b{display:block;font-family:var(--disp);font-weight:600;font-size:15.2px;color:var(--ink);
  letter-spacing:-.006em;line-height:1.34}
.std-item p{font-size:13.8px;line-height:1.6;color:var(--muted);margin:5px 0 0}
.std-foot{margin-top:22px;padding-top:20px;border-top:1px solid var(--line);
  display:flex;align-items:center;justify-content:space-between;gap:20px;flex-wrap:wrap}
.std-foot .who{display:flex;align-items:center;gap:14px}
.std-foot .mk{width:40px;height:40px;border-radius:50%;flex:none;display:grid;place-items:center;
  background:var(--gold-soft);border:1.4px solid rgba(225,165,12,.45);
  font-family:var(--disp);font-weight:700;font-size:13px;color:var(--gold)}
.std-foot .nm{display:block;font-family:var(--disp);font-weight:700;font-size:15px;color:var(--navy)}
.std-foot .rl{display:block;font-size:12.6px;color:var(--muted);margin-top:2px}
.std-foot .note{font-size:13.4px;color:var(--muted);max-width:44ch}

/* ───────── 3. BENEFITS AS FOUR TITLED GROUPS ─────────
   Ten items with no grouping is a list. Four groups is a structure, and it also puts the two
   "(Qualified Positions)" items in the one column where that qualifier makes sense. */
.bgrp{display:grid;grid-template-columns:repeat(4,1fr);gap:clamp(16px,2vw,24px);margin-top:46px}
.bcol{background:rgba(255,255,255,.055);border:1px solid rgba(255,255,255,.15);border-radius:16px;
  padding:24px 22px 22px}
.bcol .hd{display:flex;align-items:center;gap:12px;padding-bottom:15px;
  border-bottom:1px solid rgba(255,255,255,.17)}
.bcol .hd .ic{width:36px;height:36px;flex:none;border-radius:10px;background:rgba(252,201,82,.13);
  display:grid;place-items:center}
.bcol .hd .ic svg{width:18px;height:18px;color:var(--gold-2)}
.bcol .hd b{font-family:var(--disp);font-weight:700;font-size:15.5px;color:#fff;letter-spacing:-.01em}
.bcol ul{list-style:none;margin:15px 0 0;padding:0;display:grid;gap:12px}
.bcol li{display:grid;grid-template-columns:16px 1fr;gap:11px;font-size:14.8px;line-height:1.5;
  color:#cbd7ec;align-items:start}
.bcol li svg{width:16px;height:16px;color:var(--gold-2);margin-top:3px}
.bcol li .q{display:block;font-size:10.5px;letter-spacing:.09em;text-transform:uppercase;
  color:var(--gold-2);margin-top:4px}

/* ───────── 4. REFERRAL AS A TIMELINE RAIL ─────────
   The two payments are a SEQUENCE and the total is their sum, so the shape has to carry the order.
   The rail is drawn on the container and the milestones sit on it. */
.reftl{margin-top:56px;position:relative;display:grid;grid-template-columns:repeat(4,1fr)}
.reftl::before{content:"";position:absolute;left:12.5%;right:12.5%;top:26px;height:2px;
  background:linear-gradient(90deg,var(--line-2) 0%,var(--gold) 26%,var(--gold) 74%,var(--gold-2) 100%)}
.rtl{position:relative;text-align:center;padding:0 clamp(8px,1.4vw,20px)}
.rtl .dot{display:block;position:relative;z-index:2;width:20px;height:20px;border-radius:50%;
  margin:17px auto 0;background:var(--canvas);border:3px solid var(--line-2)}
.rtl.on .dot{background:var(--gold);border-color:var(--gold);
  box-shadow:0 0 0 6px rgba(225,165,12,.14)}
.rtl .lb{display:block;font-family:var(--disp);font-weight:700;font-size:10.5px;letter-spacing:.16em;
  text-transform:uppercase;color:var(--muted);margin-top:18px}
.rtl .amt{display:flex;align-items:flex-end;justify-content:center;min-height:clamp(30px,3.4vw,44px);
  font-family:var(--disp);font-weight:700;letter-spacing:-.032em;line-height:1;
  font-size:clamp(26px,3.1vw,40px);color:var(--navy);margin-top:9px}
.rtl p{font-size:13.8px;line-height:1.6;color:var(--muted);margin:11px auto 0;max-width:26ch}
/* step one is a instruction, not an amount, so it takes the same slot at a readable size */
.rtl .amt.txt{font-size:clamp(19px,2vw,25px);letter-spacing:-.016em;color:var(--ink)}
/* the total is the payoff, so it is the one milestone that gets a plate behind it */
.rtl.total{padding-bottom:24px}
.rtl.total::after{content:"";position:absolute;left:4px;right:4px;top:48px;bottom:4px;border-radius:16px;
  background:linear-gradient(180deg,var(--gold-soft) 0%,rgba(251,241,214,0) 80%);z-index:0}
.rtl.total .lb,.rtl.total .amt,.rtl.total p{position:relative;z-index:1}
.rtl.total .amt{color:var(--gold)}
.rtl.total .dot{box-shadow:0 0 0 7px rgba(225,165,12,.18)}
.reftl-foot{margin-top:30px;text-align:center;font-size:13.4px;color:var(--muted)}

/* ───────── RESPONSIVE (v3) ───────── */
@media(max-width:1080px){
  .rsn{grid-template-columns:1fr;gap:34px}
  .rsn-lead{min-height:360px}
  .bgrp{grid-template-columns:1fr 1fr}
  .std-grid{grid-template-columns:1fr 1fr}
  .std-item:nth-last-child(-n+3){border-bottom:1px dashed var(--line-2)}
  .std-item:nth-last-child(-n+2){border-bottom:0}
}
@media(max-width:720px){
  /* the rail turns vertical. It stays ONE rail, so the sequence is still legible. */
  .reftl{grid-template-columns:1fr;gap:0}
  .reftl::before{left:26px;right:auto;top:26px;bottom:34px;width:2px;height:auto;
    background:linear-gradient(180deg,var(--line-2) 0%,var(--gold) 26%,var(--gold) 74%,var(--gold-2) 100%)}
  .rtl{text-align:left;padding:0 0 26px 62px}
  .rtl .dot{position:absolute;left:17px;top:20px;margin:0}
  .rtl .lb{margin-top:14px}
  .rtl p{margin-left:0;max-width:none}
  .rtl.total{padding:0 0 22px 62px}
  .rtl.total::after{left:44px;right:0;top:8px}
  .rtl .amt{justify-content:flex-start}
}
@media(max-width:640px){
  .bgrp{grid-template-columns:1fr}
  .std-grid{grid-template-columns:1fr}
  .std-item,.std-item:nth-last-child(-n+3),.std-item:nth-last-child(-n+2){border-bottom:1px dashed var(--line-2)}
  .std-item:last-child{border-bottom:0}
  .rsn-row{grid-template-columns:42px 1fr;gap:14px}
  .rsn-row .n{font-size:22px}
}

/* ═══════════════════════════════════════════════════════════════════════════
   ABOUT US — .credx  ·  CREDENTIALS ON DARK, EACH WITH ITS "WHY IT PROTECTS YOU"
   Added 2026-08-18 for /about-us/. See ABOUT-PAGE.md.

   WHY A NEW COMPONENT RATHER THAN AN EXISTING ONE. Two candidates were tried first and both
   are wrong here for the same structural reason:
     · `.crcard`/`.crgrid` (defined ~line 40 of this file, used on NO page) is the closest fit
       in shape, but it is LIGHT-NATIVE: `background:var(--canvas)`, `color:var(--navy)` headings.
       Dropping it into a `.sec-dark` hits the documented "light cards inside dark sections"
       cascade trap that once produced white-on-white text and an invisible button.
     · `.cxcard` is `background:#fff`, same problem, and it is already this page's device for the
       six promises two sections above. One device, one job.
   The section HAS to be dark: `.ownr` above it and the FAQ below it are both dark on every page
   in the build, and the page alternates tone with no two same-tone sections touching. Credentials
   is the slot between them, so it is the dark one. rhythm.mjs measures this.

   The pairing is the point. Each credential carries a plain statement of what it IS and then a
   separately-marked line for what it PROTECTS, because a credential with no consequence attached
   is the "licensed and insured" filler the client's own draft calls out. `.why` is a distinct
   block, not italic emphasis inside the paragraph, so it survives a screen reader and a
   text-only render.
   ═══════════════════════════════════════════════════════════════════════════ */
.credx{display:grid;grid-template-columns:repeat(3,1fr);gap:18px;margin-top:46px}
.credx .cx{display:flex;flex-direction:column;padding:28px 26px 26px;border-radius:16px;
  background:rgba(255,255,255,.055);border:1px solid rgba(255,255,255,.15);
  transition:border-color .18s ease,background .18s ease}
.credx .cx:hover{border-color:rgba(252,201,82,.5);background:rgba(255,255,255,.085)}
.credx .ic{width:42px;height:42px;flex:none;border-radius:12px;background:rgba(252,201,82,.14);
  border:1px solid rgba(252,201,82,.32);display:grid;place-items:center}
.credx .ic svg{width:20px;height:20px;color:var(--gold-2)}
.credx .lb{display:block;font-family:var(--disp);font-weight:700;font-size:10.5px;
  letter-spacing:.16em;text-transform:uppercase;color:var(--gold-2);margin-top:18px}
.credx h3{font-family:var(--disp);font-weight:700;font-size:18.5px;color:#fff;
  letter-spacing:-.014em;margin:9px 0 0;line-height:1.22}
.credx p{font-size:14.6px;color:#b6c4de;margin:14px 0 0;line-height:1.66}
/* the consequence line. Gold hairline on the left so it reads as the answer to the claim above it
   rather than as a second paragraph of the same claim. */
.credx .why{margin-top:auto;padding:15px 0 0 15px;border-left:2px solid rgba(252,201,82,.55);
  margin-left:1px}
.credx .why b{display:block;font-family:var(--disp);font-weight:700;font-size:11.5px;
  letter-spacing:.13em;text-transform:uppercase;color:var(--gold-2)}
.credx .why span{display:block;font-size:14.2px;color:#cdd8ec;margin-top:7px;line-height:1.62}
/* the verify line under the grid: one sentence, not a fourth card, because it is an instruction
   rather than a credential. */
.credx-foot{margin-top:26px;display:flex;align-items:center;gap:12px;font-size:14.4px;color:#b6c4de}
.credx-foot svg{width:17px;height:17px;flex:none;color:var(--gold-2)}
.credx-foot a{color:var(--gold-2);text-decoration:underline;text-underline-offset:3px}

@media(max-width:1080px){
  .credx{grid-template-columns:1fr 1fr}
  /* the third card would sit alone on its row at half width, so it spans and its .why
     stops being a tall thin column. */
  .credx .cx:last-child{grid-column:1/-1}
  .credx .cx:last-child .why{margin-top:16px}
}
@media(max-width:720px){
  .credx{grid-template-columns:1fr;gap:14px}
  .credx .cx:last-child{grid-column:auto}
  .credx-foot{align-items:flex-start}
}

/* the two buttons that close the "what you get" grid. A .head.center with inline styles was the
   first attempt and it inherited .head's 820px max-width plus its h2/lede spacing, which pushed
   the pair off centre at 1440px. Its own tiny rule instead. */
.cxfoot{display:flex;flex-wrap:wrap;justify-content:center;gap:12px;margin-top:42px}

/* ============================================================================================
   FINANCING  —  /financing/  (2026-08-19)
   Page-scoped components for the financing page. Everything here is prefixed .fnx so it cannot
   collide with the money-page vocabulary, and nothing here is used by another page.

   WHY NEW COMPONENTS AT ALL. Six of the eleven sections map cleanly onto existing devices
   (.hero.hero-photo + #book, .tstrip, .cxgrid/.cxcard, .faq.faq-2col, the shared reviews band and
   .close). The rest have no equivalent anywhere in the build:
     · a four-step path            .steps is a THREE-column grid with a connector line drawn at
                                   8%-92%; forcing a fourth column into it breaks the connector
                                   and orphans a step on mobile.
     · a payment estimator         nothing in this build takes numeric input at all.
     · lender program cards        .cxcard is a fixed icon+title+paragraph card with no room for a
                                   terms line, a "best for" line and a featured state.
     · a slim conversion band      TWO existing candidates were checked and both are DARK.
                                   `.ctaband` (the money pages' mid-page band) is navy-ink with a
                                   photo backdrop and a two-column editorial layout, and `.close`
                                   is the hero-scale ending. The band on this page sits BETWEEN TWO
                                   DARK SECTIONS, so either one would have made the only adjacent
                                   same-tone pair on the page, and the Notion template asks for a
                                   *slim* recatch rather than a second ending. Gold, and slim.
   ============================================================================================ */

/* ---------- 1. WHAT YOU CAN FINANCE, the 2x3 grid beside the "why" copy ----------
   Every tile is a LINK to the page that does that work, and this is the only place on the page
   where the financeable-job list appears (the "what qualifies happens once" rule in the Notion
   template). Tiles are links rather than static cards because a reader who has decided they are
   financing a heat pump should be able to leave for the heat pump page from here. */
.fnxwhy{display:grid;grid-template-columns:1.02fr .98fr;gap:clamp(30px,4vw,62px);align-items:start;margin-top:8px}
.fnxwhy .copy p{font-size:16.4px;color:var(--muted);max-width:52ch}
.fnxwhy .copy p b{color:var(--ink);font-weight:600}
.fnxgrid{display:grid;grid-template-columns:1fr 1fr;gap:12px;grid-auto-rows:1fr}
/* grid-auto-rows:1fr, not auto. "Full system replacement" is the only two-line label of the six, so
   with auto rows its row grew and the 2x3 block came out ragged down the middle. */
.fnxtile{display:flex;align-items:center;gap:13px;background:var(--surface);border:1px solid var(--line);
  border-radius:13px;padding:16px 17px;transition:.18s ease}
.fnxtile:hover{border-color:var(--line-2);transform:translateY(-2px);box-shadow:var(--shadow)}
.fnxtile .ic{width:38px;height:38px;flex:none;border-radius:10px;background:var(--gold-soft);display:grid;place-items:center}
.fnxtile .ic svg{width:18px;height:18px;color:var(--gold)}
.fnxtile b{font-family:var(--disp);font-weight:600;font-size:14.6px;color:var(--ink);line-height:1.25}
.fnxtile span{display:block;font-size:12.6px;color:var(--muted);margin-top:2px}

/* ---------- 2. FOUR-STEP PATH, on the dark band ----------
   A four-column rail. The connector is a single 1px line behind the numbers rather than a border
   per card, so the row reads as one path instead of four boxes. It is drawn from the middle of the
   first number to the middle of the last (left/right 12.5% = half a column), which is what .steps
   gets wrong the moment you add a fourth column to it. */
.fnxpath{display:grid;grid-template-columns:repeat(4,1fr);gap:26px;margin-top:46px;position:relative}
.fnxpath::before{content:"";position:absolute;top:21px;left:12.5%;right:12.5%;height:1px;
  background:rgba(255,255,255,.22);z-index:0}
.fnxstep{position:relative;z-index:1}
.fnxstep .n{width:42px;height:42px;border-radius:50%;background:var(--navy-ink);border:1px solid rgba(255,255,255,.3);
  display:grid;place-items:center;font-family:var(--disp);font-weight:700;font-size:15px;color:#fff;margin-bottom:18px}
.fnxstep:first-child .n{background:var(--gold);border-color:var(--gold);color:#1c1403}
.fnxstep h3{font-size:17.4px;color:#fff}
.fnxstep p{font-size:14.6px;color:#c3cfe6;margin:9px 0 0;max-width:34ch}
/* the one line on this band that has to be read, so it gets a rule and the gold, not italics */
.fnxpath-note{margin:38px 0 0;padding-top:20px;border-top:1px solid rgba(255,255,255,.16);
  display:flex;align-items:flex-start;gap:11px;font-size:14.4px;color:#c3cfe6;max-width:78ch}
.fnxpath-note svg{width:17px;height:17px;flex:none;color:var(--gold-2);margin-top:3px}
.fnxpath-note b{color:#fff;font-weight:600}

/* ---------- 3. PAYMENT ESTIMATOR ----------
   READ THIS BEFORE "FIXING" THE DEAD READOUT. The payment number is deliberately NOT computed.
   Service Finance's APR and its available terms are both unconfirmed for this client (the three
   lender documents are the outstanding input in NON-NEGOTIABLES.md, and the approved Notion draft
   marks every rate and every term [VERIFY] in red). This build does not invent a number, so the
   estimator ships as a REQUEST BUILDER: the slider and the term chips are live, they compose a
   real sentence about the reader's own project, and that sentence is what the CTA carries into the
   form. Nothing on screen claims a rate.
   ONE ATTRIBUTE TURNS IT INTO A CALCULATOR. Put the confirmed rate in data-apr on .fnxest and the
   page script computes and prints the amortised payment in place of the placeholder. Empty or
   missing data-apr = locked state. Do not hardcode a rate anywhere else. */
.fnxest{display:grid;grid-template-columns:1.05fr .95fr;gap:clamp(24px,3vw,44px);margin-top:44px;
  background:rgba(255,255,255,.06);border:1px solid rgba(255,255,255,.16);border-radius:22px;
  padding:clamp(24px,3vw,38px)}
.fnxest .k{display:block;font-family:var(--disp);font-weight:600;font-size:11.5px;letter-spacing:.14em;
  text-transform:uppercase;color:var(--gold-2)}
.fnxamt{display:flex;align-items:baseline;justify-content:space-between;gap:16px}
.fnxamt b{font-family:var(--disp);font-weight:700;font-size:clamp(28px,3vw,38px);color:#fff;letter-spacing:-.02em}
/* the native range, restyled. Track and thumb have to be declared per engine, there is no shorthand. */
.fnxrange{-webkit-appearance:none;appearance:none;width:100%;height:6px;border-radius:99px;margin:18px 0 8px;
  background:linear-gradient(90deg,var(--gold) 0%,var(--gold) var(--fill,44%),rgba(255,255,255,.2) var(--fill,44%));
  outline:none;cursor:pointer}
.fnxrange::-webkit-slider-thumb{-webkit-appearance:none;appearance:none;width:26px;height:26px;border-radius:50%;
  background:#fff;border:5px solid var(--gold);cursor:grab;box-shadow:0 4px 14px rgba(0,0,0,.35)}
.fnxrange::-moz-range-thumb{width:26px;height:26px;border-radius:50%;background:#fff;border:5px solid var(--gold);
  cursor:grab;box-shadow:0 4px 14px rgba(0,0,0,.35)}
.fnxrange:focus-visible{box-shadow:0 0 0 3px rgba(252,201,82,.45)}
.fnxscale{display:flex;justify-content:space-between;font-size:12.4px;color:#a9b8d4}
.fnxterms{display:flex;flex-wrap:wrap;gap:9px;margin-top:12px}
.fnxterm{font-family:var(--disp);font-weight:600;font-size:14px;color:#dbe4f3;background:transparent;
  border:1px solid rgba(255,255,255,.28);border-radius:10px;padding:10px 16px;cursor:pointer;transition:.16s}
.fnxterm:hover{border-color:#fff;color:#fff}
.fnxterm[aria-pressed="true"]{background:var(--gold);border-color:var(--gold);color:#1c1403}
.fnxterm:focus-visible{outline:2px solid var(--gold-2);outline-offset:2px}
/* the output half. Its own panel, so the readout does not read as another control. */
.fnxout{background:var(--navy-ink);border:1px solid rgba(255,255,255,.14);border-radius:18px;
  padding:clamp(22px,2.4vw,30px);display:flex;flex-direction:column}
.fnxout .pay{font-family:var(--disp);font-weight:700;font-size:clamp(38px,4.6vw,60px);line-height:1;
  color:#fff;letter-spacing:-.03em;margin:14px 0 0}
.fnxout .pay small{font-size:.36em;font-weight:600;color:#a9b8d4;letter-spacing:0;margin-left:4px}
/* the locked state. The placeholder is a chip, the same object the reviews band uses for a blocked
   fact, so a reader of this page cannot mistake it for a styling accident. It sits INSIDE the
   sentence that explains what is missing rather than floating on its own, because a bare chip
   under a heading reads as a broken component and a chip at the end of an explanation reads as a
   note. */
.fnxout .ns{display:inline-block;font-family:var(--disp);font-weight:600;font-size:12px;letter-spacing:.04em;
  color:#f4d79a;background:rgba(225,165,12,.14);border:1px solid rgba(252,201,82,.4);border-radius:7px;
  padding:3px 9px;margin-top:6px}
/* the reader's own sentence is the LARGEST thing in the panel, because in the locked state it is
   the only thing in the panel that is true. When data-apr lands, .pay is inserted above it and
   takes the size back. */
.fnxout .said{font-family:var(--disp);font-weight:700;font-size:clamp(23px,2.4vw,30px);line-height:1.2;
  color:#fff;letter-spacing:-.02em;margin:12px 0 14px}
.fnxout .said b{color:var(--gold-2);font-weight:700}
.fnxout .pend{font-size:13.6px;color:#a9b8d4;margin:0 0 18px}
.fnxest[data-apr]:not([data-apr=""]) .said{font-family:var(--body);font-weight:400;font-size:15px;
  letter-spacing:0;color:#dbe4f3;margin:14px 0 16px}
.fnxout .btn{margin-top:auto;width:100%;justify-content:center}
.fnxout .fine{font-size:12.6px;color:#a9b8d4;margin:13px 0 0;text-align:center}
.fnxest-note{grid-column:1/-1;margin:4px 0 0;font-size:13.4px;color:#a9b8d4;display:flex;align-items:flex-start;gap:10px}
.fnxest-note svg{width:16px;height:16px;flex:none;color:var(--gold-2);margin-top:3px}

/* ---------- 4. LENDER PROGRAM CARDS ----------
   The Notion template is explicit that these are the CHARACTERISTICS of Service Finance's
   promotional programs, not tiers a homeowner picks between like pricing packages. So the card has
   no price, no button and no "choose" affordance. It has a name, the terms and who it suits. */
.fnxprog{display:grid;grid-template-columns:repeat(3,1fr);gap:18px;margin-top:44px;align-items:stretch}
.fnxcard{background:var(--surface);border:1px solid var(--line);border-radius:var(--r);padding:26px 24px;
  display:flex;flex-direction:column;position:relative;transition:.18s ease}
.fnxcard:hover{border-color:var(--line-2);transform:translateY(-2px);box-shadow:var(--shadow)}
.fnxcard.feat{border-color:var(--gold);box-shadow:0 18px 40px rgba(225,165,12,.16)}
.fnxcard .pop{position:absolute;top:-11px;left:24px;font-family:var(--disp);font-weight:700;font-size:11px;
  letter-spacing:.13em;text-transform:uppercase;color:#1c1403;background:var(--gold);border-radius:6px;padding:4px 10px}
.fnxcard h3{font-size:18.6px;color:var(--navy);margin:0}
.fnxcard .terms{margin:16px 0 0;padding:14px 16px;background:var(--canvas-2);border-radius:11px;
  font-size:14.6px;color:var(--ink);line-height:1.5}
.fnxcard .terms .ns{display:inline-block;font-family:var(--disp);font-weight:600;font-size:12.5px;letter-spacing:.05em;
  color:#a3785f;background:#fdf5ee;border:1px solid #f0e2d4;border-radius:6px;padding:3px 8px}
.fnxcard .terms .ns + span{display:block;margin-top:8px;font-size:13.6px;color:var(--muted)}
/* .tbd is the SAME SLOT as .ns, for a value the lender has not confirmed yet but which the page
   should not advertise as missing. The {{NEEDS_SOURCE}} chip is correct while a build is internal;
   on a client-visible URL it reads as broken markup, so /financing/ uses this instead (owner call,
   2026-08-28). It is deliberately NOT a chip: no pill, no border, no placeholder colour — it reads
   as the card's answer, because "you find out at application" IS the answer until the three Service
   Finance documents arrive. Drop the confirmed terms straight into this span when they do. */
.fnxcard .terms .tbd{display:block;font-family:var(--disp);font-weight:600;font-size:14.8px;color:var(--navy)}
.fnxcard .terms .tbd + span{display:block;margin-top:7px;font-size:13.6px;color:var(--muted)}
.fnxcard .best{margin:16px 0 0;font-size:14.4px;color:var(--muted)}
.fnxcard .best b{display:block;font-family:var(--disp);font-weight:600;font-size:11.5px;letter-spacing:.12em;
  text-transform:uppercase;color:var(--gold);margin-bottom:6px}

/* the lender disclosure. Legally required wherever a rate or a promotional period appears, so it
   sits with the programs rather than being exiled to the footer. */
.fnxdisc{margin-top:34px;border:1px solid var(--line);border-left:3px solid var(--navy);border-radius:12px;
  background:var(--surface);padding:20px 22px}
.fnxdisc p{font-size:13.4px;color:var(--muted);margin:0}
.fnxdisc p + p{margin-top:9px}
.fnxdisc b{color:var(--ink);font-weight:600}


/* ---------- 4b. THREE TIPS, on the dark band ----------
   ⚠ THIS IS NOT .fnxpath AND MUST NOT BE. The first build reused the four-step path here and it
   was wrong twice over: the connector line asserts a SEQUENCE (these three are independent, you
   might do all of them or none) and .fnxstep:first-child paints its number gold, which on a
   non-sequence marks the first tip as special for no reason. It is the homepage's .pgrid hairline
   treatment translated onto the dark band instead: a rule, a label that says WHEN the tip applies,
   and the copy. No icons, which this owner has twice called out as reading AI-generated. */
.fnxtips{display:grid;grid-template-columns:repeat(3,1fr);gap:0;margin-top:48px;
  border-top:1px solid rgba(255,255,255,.22)}
.fnxtip{padding:30px 30px 4px 0}
.fnxtip:not(:last-child){border-right:1px solid rgba(255,255,255,.14)}
.fnxtip + .fnxtip{padding-left:30px}
.fnxtip .k{display:block;font-family:var(--disp);font-weight:700;font-size:11.5px;letter-spacing:.14em;
  text-transform:uppercase;color:var(--gold-2);margin-bottom:12px}
.fnxtip h3{font-size:18px;color:#fff;line-height:1.28}
.fnxtip p{font-size:14.6px;color:#c3cfe6;margin:11px 0 0}


/* ---------- 4c. A PLACEHOLDER INSIDE A DARK FAQ ANSWER ----------
   /financing/ FAQ 1 is the first answer in the build to carry a {{NEEDS_SOURCE}} inline. Unstyled
   it rendered as raw braces mid-sentence and read as a template bug rather than a marked gap, which
   is the opposite of what the placeholder is for. Same chip as the reviews band, on its own line so
   it sits after the answer instead of inside it. */
.faq .ans .ns{display:block;width:fit-content;font-family:var(--disp);font-weight:600;font-size:12px;
  letter-spacing:.04em;color:#f4d79a;background:rgba(225,165,12,.14);border:1px solid rgba(252,201,82,.4);
  border-radius:7px;padding:4px 10px;margin-top:12px}

/* ---------- 5. SLIM MID-PAGE CONVERSION BAND ----------
   Exists to recatch the reader who has scrolled past the hero form and is not yet at the close.
   Gold, because both bands it sits between are dark and a third dark band would read as the page
   ending twice. */
.fnxband{background:linear-gradient(120deg,var(--gold-soft) 0%,#fdf3dc 55%,var(--gold-soft) 100%);
  border-top:1px solid #f0e2c2;border-bottom:1px solid #f0e2c2;padding:clamp(26px,3.4vw,40px) 0}
.fnxband .wrap{display:flex;align-items:center;justify-content:space-between;gap:26px;flex-wrap:wrap}
.fnxband h2{font-size:clamp(21px,2.2vw,28px);color:var(--navy-ink);margin:0}
.fnxband p{font-size:15px;color:#6a5a33;margin:8px 0 0;max-width:52ch}
.fnxband .act{display:flex;align-items:center;gap:14px;flex-wrap:wrap}
.fnxband .tel{font-family:var(--disp);font-weight:700;font-size:16.4px;color:var(--navy);
  display:inline-flex;align-items:center;gap:9px}
.fnxband .tel svg{width:17px;height:17px}

/* ---------- 6. RESPONSIVE ----------
   Both breakpoints are where a component actually breaks rather than at a round number: the
   estimator's two panels stop fitting side by side under ~980px, and the four-step rail's
   connector stops meaning anything the moment the steps stack. */
@media(max-width:1080px){
  .fnxwhy{grid-template-columns:1fr}
  .fnxpath{grid-template-columns:1fr 1fr;gap:30px 26px}
  .fnxpath::before{display:none}
  .fnxprog{grid-template-columns:1fr}
  .fnxcard.feat{order:-1}
  .fnxtips{grid-template-columns:1fr}
  .fnxtip{padding:26px 0 4px}
  .fnxtip:not(:last-child){border-right:0;border-bottom:1px solid rgba(255,255,255,.14)}
  .fnxtip + .fnxtip{padding-left:0}
}
@media(max-width:980px){
  .fnxest{grid-template-columns:1fr}
}
@media(max-width:720px){
  .fnxgrid{grid-template-columns:1fr}
  .fnxpath{grid-template-columns:1fr;gap:26px}
  .fnxband .wrap{flex-direction:column;align-items:flex-start}
  .fnxest{padding:22px}
  .fnxterms .fnxterm{flex:1 1 calc(50% - 5px);text-align:center}
}


/* .plist — the "check us somewhere we do not control" rail on /reviews/.
   A modifier on .nsteps rather than a restyle of it, because .nsteps is shared and the base
   component is used for process steps where the heading is NOT a link.
   🔴 WHY IT EXISTS: on dark, .nstep h3 renders white and an <a> inside it inherits that, so four
   outbound profile links looked like four plain headings. On the one section whose entire purpose
   is "go and read these yourself", nothing signalled that they were clickable. Arrow plus the bare
   domain, so the destination is legible before the click and on a printout. */
.plist .nstep h3 a{display:inline-flex;align-items:baseline;gap:8px}
.plist .nstep h3 a .lx{width:13px;height:13px;flex:none;color:var(--gold-2);transition:transform .2s ease}
.plist .nstep h3 a:hover{color:var(--gold-2)}
.plist .nstep h3 a:hover .lx{transform:translate(2px,-2px)}
/* the domain sits inside the h3 for reading order, so it inherits Montserrat 700 and rendered
   as a second bold line. Reset to the body font and a normal weight explicitly. */
.plist .dom{display:block;font-family:var(--body);font-weight:400;font-size:12.4px;
  color:#8d9dbd;margin-top:5px;letter-spacing:.02em}

/* the attribution under a .credx pull quote. Without it the reviewer's name runs straight on from
   the closing quote mark and reads as part of the sentence. Scoped to cite so /about-us/, whose
   .why blocks carry no attribution, is untouched. */
.credx .why cite{display:block;margin-top:9px;font-style:normal;font-family:var(--disp);
  font-weight:600;font-size:11.6px;letter-spacing:.1em;text-transform:uppercase;color:var(--gold-2)}

/* ═════════════════════════════════════════════════════════════════════════════════════════════
   .gvr — GOOGLE REVIEW CARDS.  Added 2026-08-19 for /reviews/, the page the shared
   "Read the reviews" band has pointed at from 52 pages while returning a 404.

   🔑 WHY A NEW COMPONENT AND NOT .qcard. The shared reviews band's .qcard is a THREE-UP
   TEASER built for a ~28-word pull quote at font-size:14.4px. The five reviews Google's API
   returns for this profile run 45 to 155 words and two of them are MULTI-PARAGRAPH. Dropped
   into a 3-column .qcards grid a 155-word review becomes a ~40-character-wide column roughly
   1,100px tall, which is unreadable and would push the section past 4,000px on its own.
   .qcard is also the device the teaser band uses on every other page, and restyling it here
   would report as a site-wide drift failure in revcheck.mjs. One device, one job.

   Three deliberate differences from .qcard, each of which is why this exists:
     · a WIDE modifier, so a long review spans both columns instead of being squeezed. The grid
       is plain CSS grid rather than masonry on purpose: masonry would reorder visually away from
       the newest-first order the page states in prose, and the order is a factual claim here.
     · a FOOTER carrying the review's own permalink on Google. Every card is checkable, which is
       the entire argument of the page, so the link is structural rather than decorative.
     · INITIALS avatars, never the reviewer's Google photo. Hotlinking lh3.googleusercontent.com
       is banned fleet-wide (see the Alamo GBP feed rule: localise to /uploads or fall back to
       initials). At deploy the painter may swap in localised avatars; initials are the honest
       local state, not a placeholder, so they carry no {{NEEDS_SOURCE}}.
   ═════════════════════════════════════════════════════════════════════════════════════════ */
/* No visually-hidden utility existed in this design system before /reviews/. The star row is
   decorative markup (five glyphs regardless of the score), so a screen reader needs the real
   rating in text beside it. Named .sr-only rather than .sr because ie-v16.css already uses .sr*
   prefixes for the reach form and a two-character class is too easy to collide with. */
.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;
  clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap;border:0}
.gvr{margin-top:42px;border-top:1px solid var(--line)}
/* ONE COLUMN, and the card splits INSIDE. A two-column grid was tried first and broke on the
   real data: the five reviews are 62 to 152 words, so a 2-col grid needs a .wide modifier for
   the long ones, and a wide card in DOM order Michael/Lamar/Saul/Charles/Brian leaves a hole in
   row 1 because the two short reviews are not adjacent. Reordering to close the hole would break
   the newest-first order the prose states, and the order is a factual claim on this page.
   Full-width cards fix the hole but put a 120ch line in front of the reader, so the split moved
   inside: a fixed meta rail on the left, the quote capped at 72ch on the right. Any review length
   now lays out correctly and the stated order survives. */
.gvr .gv{display:grid;grid-template-columns:252px 1fr;gap:clamp(26px,3.4vw,54px);
  padding:32px 0;border-bottom:1px solid var(--line);align-items:start}
.gvr .gv-hd{display:flex;align-items:flex-start;gap:13px}
.gvr .av{width:44px;height:44px;flex:0 0 44px;border-radius:50%;display:grid;place-items:center;
  background:linear-gradient(145deg,var(--navy),var(--navy-2));color:#fff;
  font-family:var(--disp);font-weight:700;font-size:14.5px;letter-spacing:.01em}
.gvr .nm{font-family:var(--disp);font-weight:700;font-size:16.2px;color:var(--ink);
  letter-spacing:-.01em;line-height:1.24;display:block}
.gvr .st{display:block;color:var(--gold);letter-spacing:1.8px;font-size:13px;margin-top:5px}
.gvr .dt{display:block;font-size:12.6px;color:var(--muted);margin-top:4px}
/* 57px = the 44px avatar plus the 13px gap in .gv-hd. Without it the source line and the
   permalink start at the rail's left edge while the reviewer's name starts one avatar in, and
   the rail reads as two things that missed each other. Caught in an element screenshot, not by
   any gate: overlap.mjs passed at all nine widths because nothing intersected. */
.gvr .gv-meta{margin:18px 0 0 57px;padding-top:16px;border-top:1px solid var(--line)}
.gvr .gsrc{display:flex;align-items:center;gap:8px;font-size:12.4px;color:var(--muted)}
.gvr .gsrc svg{width:15px;height:15px;flex:none}
.gvr .glink{margin-top:9px;font-family:var(--disp);font-weight:600;font-size:12.8px;
  color:var(--navy);display:inline-flex;align-items:center;gap:6px}
.gvr .glink svg{width:12px;height:12px;transition:transform .2s ease}
.gvr .glink:hover{color:var(--gold)}
.gvr .glink:hover svg{transform:translate(2px,-2px)}
/* 72ch, measured in the body font, so the longest review still reads as a paragraph */
.gvr blockquote{margin:0;font-size:15.6px;line-height:1.74;color:#3d4757;max-width:72ch}
.gvr blockquote p{margin:0}
.gvr blockquote p + p{margin-top:.85rem}
.gvr .job{display:inline-flex;align-items:center;gap:8px;margin-top:16px;padding:6px 13px;
  border:1px solid var(--line);border-radius:999px;background:var(--canvas);
  font-family:var(--disp);font-weight:600;font-size:12.4px;color:var(--navy)}
.gvr .job svg{width:13px;height:13px;color:var(--gold);flex:none}
.gvr .job:hover{border-color:var(--gold)}
/* the strip above the list: says where the cards came from and when, in one line */
.gvsrc{display:flex;align-items:center;gap:12px;flex-wrap:wrap;margin-top:30px;
  padding:13px 18px;background:var(--canvas-2);border:1px solid var(--line);
  border-left:3px solid var(--gold);border-radius:12px;font-size:13.2px;color:#3d4757}
.gvsrc svg{width:16px;height:16px;flex:none}
.gvsrc b{font-family:var(--disp);font-weight:700;color:var(--ink)}
/* the SECOND provenance strip: the three reviews the client publishes on its own site. Same shape
   as .gvsrc, deliberately COOLER — navy hairline instead of gold — because these carry no permalink
   and the page says outright that they are worth less than the five above. A visually identical
   strip would flatten a distinction the copy is making. */
.gvsrc-own{background:var(--surface);border-left-color:var(--navy)}
.gvsrc-own svg{color:var(--navy)}
/* no Google mark on these, so the source line is text only and needs the muted treatment the
   .gsrc svg + gap was providing */
.gvr .gv-meta .gsrc:only-child{font-family:var(--disp);font-weight:600;font-size:11.6px;
  letter-spacing:.08em;text-transform:uppercase;color:#8a94a3}
/* the closing row under the list, so the page never implies five is all there is */
.gvall{display:flex;align-items:center;justify-content:center;gap:18px;flex-wrap:wrap;margin-top:34px}
@media(max-width:900px){
  .gvr .gv{grid-template-columns:1fr;gap:20px;padding:26px 0}
  /* stacked, the rail is full width and the avatar indent is meaningless, so drop it */
  .gvr .gv-meta{margin:14px 0 0;padding-top:13px;display:flex;align-items:center;gap:18px;flex-wrap:wrap}
  .gvr .glink{margin-top:0}
  .gvr blockquote{font-size:15px;max-width:none}
}
@media(max-width:640px){
  .gvsrc{padding:13px 15px}
  .gvall{flex-direction:column;align-items:stretch}
  .gvall .btn{justify-content:center}
}

/* ═══════════════════════════════════════════════════════════════════════════════════════════
   .bcard — THE BRAND CARD.  Added 2026-08-19 for /brands/, and it is the component the five
   W2 product pages inherit. Read BRANDS-PAGE.md before changing it.

   WHY IT EXISTS, since .cxcard was tried first and rejected on sight:
   a brands page cannot show a logo wall on this build. Trane's marks are a client-blocked input
   (attribution and web-publishing scope never arrived) and NON-NEGOTIABLES bans competitor marks
   outright. .cxcard sets its h3 at body scale, which is right for a sentence-shaped heading like
   "No quotas, no upsell" and wrong for a one-word brand name: "Trane" rendered at 15px and the
   section read as a generic three-up with no subject. .bcard makes the NAME the graphic, which is
   the only lever left once logos are off the table.

   LIGHT SECTIONS ONLY. This is a light-native card and it will hit the documented "light cards
   inside dark sections" cascade trap. If a dark section needs brand cards, use .credx.
   ═══════════════════════════════════════════════════════════════════════════════════════════ */
.bgrid{display:grid;grid-template-columns:repeat(3,1fr);gap:22px;margin-top:46px;align-items:stretch}
.bcard{display:flex;flex-direction:column;background:var(--surface);border:1px solid var(--line);
  border-radius:20px;padding:30px 28px 26px;position:relative;overflow:hidden;
  transition:border-color .25s ease,box-shadow .25s ease,transform .25s ease}
/* the hairline of gold across the top is the only decoration, and it is what stops three white
   boxes reading as a table. It grows on hover rather than appearing, so nothing shifts. */
.bcard::before{content:"";position:absolute;left:0;top:0;height:3px;width:64px;
  background:linear-gradient(90deg,var(--gold),var(--gold-2));transition:width .3s ease}
.bcard:hover{border-color:var(--line-2);box-shadow:var(--shadow);transform:translateY(-3px)}
.bcard:hover::before{width:100%}
.bcard .role{font-family:var(--disp);font-weight:700;font-size:11px;letter-spacing:.15em;
  text-transform:uppercase;color:var(--gold);display:block}
.bcard .bnm{font-family:var(--disp);font-weight:700;font-size:clamp(27px,2.5vw,36px);
  line-height:1.08;letter-spacing:-.022em;color:var(--navy);margin:10px 0 0}
.bcard .bnm small{display:block;font-size:.44em;font-weight:600;letter-spacing:0;
  color:var(--muted);margin-top:7px}
.bcard .brule{display:block;width:46px;height:3px;border-radius:2px;background:var(--gold-2);
  margin:17px 0 16px}
.bcard p{font-size:14.6px;line-height:1.64;color:var(--muted);margin:0}
/* margin-top:auto pins the fit list to the bottom, so three cards with unequal paragraphs still
   line their lists up. Without it the rules sat at three different heights and looked broken. */
.bcard .bfit{list-style:none;margin:22px 0 0;padding:16px 0 0;border-top:1px dashed var(--line-2);
  display:grid;gap:9px;margin-top:auto}
.bcard .bfit li{display:flex;align-items:flex-start;gap:9px;font-size:13.6px;color:var(--ink);
  font-weight:500}
.bcard .bfit li::before{content:"";width:6px;height:6px;border-radius:50%;background:var(--gold);
  flex:none;margin-top:7px}
.bcard .blink{display:inline-flex;align-items:center;gap:7px;margin-top:20px;
  font-family:var(--disp);font-weight:700;font-size:13.4px;color:var(--navy);text-decoration:none}
.bcard .blink svg{width:15px;height:15px;transition:transform .25s ease}
.bcard .blink:hover{color:var(--gold)}
.bcard .blink:hover svg{transform:translateX(4px)}
@media(max-width:960px){
  .bgrid{grid-template-columns:1fr;gap:16px;margin-top:36px}
  .bcard{padding:26px 22px 24px}
  .bcard .bfit{margin-top:20px}
}

/* ═════════ FINANCING — apply-card heading level (2026-08-25) ═════════
   /financing/'s apply card titles itself with an <h2>, not an <h3>, so the page outline does not
   skip h1 > h3. `ie.css` sizes `.qform h3` at 21px and says nothing about `.qform h2`, so without
   this the card's title renders at full section-heading size.
   ⚠ THIS IS A PORT, NOT A NEW RULE. `ie-loc.css` line 172 already carries the identical
     declaration for the location-page heroes, which solved this exact skip first. /financing/
     loads ie.css + ie-v16.css + ie-util.css and NOT ie-loc.css, which is the only reason it could
     not simply inherit it. Keep the two in step: change one and change the other. */
.qform h2{font-size:21px;letter-spacing:-.018em}

/* ═════════ FINANCING — ESTIMATOR, LIGHT VARIANT (2026-08-25) ═════════
   The content agent's 13-section spine puts COST in a LIGHT slot (slot 5 on the canonical
   AC-repair page). The estimator is financing's cost chapter, and `.fnxest` was built for a dark
   band unconditionally: `rgba(255,255,255,.06)` panels, `color:#fff` numerals, a translucent-white
   range track and `#a9b8d4` muted text. Dropped onto a light section it renders as a white panel
   on white with invisible numbers, so the tone change is a component variant rather than a class
   swap.

   ⚠ ADD `on-light` TO `.fnxest`, do not delete the dark rules. The dark version is still the
     correct one if this section ever moves back to a dark slot, and `_qa/bgcontrast.mjs` checks
     the rendered pair either way.
   ⚠ THE GOLD STAYS GOLD. `--gold` on the range fill, the pressed term chip and the CTA is the
     page's action colour on both tones. Only the neutrals flip.
   ⚠ WHAT THIS COSTS, recorded because it was a deliberate trade and not an improvement: the
     estimator loses the `B02_unit_dark_studio` backdrop, which was chosen as "the only near-black
     frame in the set, so the numbers do not have to fight a daylight photo". On a light band the
     numbers now sit on cream. That is the price of spine conformance at this slot. */
.fnxest.on-light{background:var(--surface);border-color:var(--line)}
.fnxest.on-light .k{color:#8a6a1f}
.fnxest.on-light .fnxamt b{color:var(--navy)}
.fnxest.on-light .fnxrange{background:linear-gradient(90deg,var(--gold) 0%,var(--gold) var(--fill,44%),
  rgba(20,32,58,.16) var(--fill,44%))}
.fnxest.on-light .fnxrange::-webkit-slider-thumb{background:#fff;border-color:var(--gold);
  box-shadow:0 3px 10px rgba(20,32,58,.22)}
.fnxest.on-light .fnxrange::-moz-range-thumb{background:#fff;border-color:var(--gold);
  box-shadow:0 3px 10px rgba(20,32,58,.22)}
.fnxest.on-light .fnxscale{color:var(--muted)}
.fnxest.on-light .fnxterm{color:var(--ink);border-color:var(--line-2)}
.fnxest.on-light .fnxterm:hover{border-color:var(--navy);color:var(--navy)}
.fnxest.on-light .fnxterm[aria-pressed="true"]{background:var(--gold);border-color:var(--gold);color:#1c1403}
/* the output half keeps its own panel so the readout still does not read as another control, but
   on a light band it inverts: the panel is the dark object now, which also keeps the reader's own
   sentence the most prominent thing in the composition. */
.fnxest.on-light .fnxout{background:var(--navy-ink);border-color:rgba(255,255,255,.14)}
.fnxest.on-light .fnxest-note{color:var(--muted)}
.fnxest.on-light .fnxest-note svg{color:#8a6a1f}

/* ─────────────────────────────────────────────────────────────────────────────
   THE HERO HEADING PAIR INSIDE `.rhero` — added 2026-08-25 with the /about-us/
   rebuild onto the 13-section content-agent spine.

   Brief rule 3 splits the hero heading: the <h1> carries the eyebrow and the fixed
   service-area line, and the page's own tagline is an <h2> that renders BETWEEN
   them. The LAYOUT half of that device is generic and already lives in ie-v16.css
   (.hhead grid, .h3l{display:contents}, the three order values, .h1a type).

   What is NOT generic is the type SIZE of the tagline and the gold underline. Both
   are scoped to `.hero` / `.hero-photo` in ie.css, and this page uses `.rhero`,
   a different hero component with its own centred layout. Without the rules below
   the tagline renders at body size and the `.u` span has no underline at all.

   ⚠ `.h3l{display:contents}` removes the h1's own box, so `.rhero h1`'s font-size,
     margin and max-width stop applying. The h1t below restates the same clamp.
   ⚠ THE MEASURE IS 30ch, NOT the 19ch `.rhero h1` used, and that is measured rather
     than preferred. `.u` is white-space:nowrap, so "sized for your house" can no longer
     break. At 19ch the tagline set as three lines with "system" alone on the middle one.
     30ch fits "Honest answers, and a system" on line one and drops the underlined phrase
     to line two, which is the two-line rag the other heroes have.
   ⚠ SCOPED TO `.rhero .hhead`. contact-us, reviews and schedule also use `.rhero`
     and none of them carries `.hhead`, so none of them is touched. Checked by grep
     before shipping, not assumed.
   ⚠ `.rhero` is text-align:center, so the grid must centre its items or the three
     lines left-align inside a centred hero. ie-v16.css sets justify-items:start.
   ───────────────────────────────────────────────────────────────────────────── */
.rhero .hhead{justify-items:center;text-align:center;gap:.24em;margin-top:24px}
.rhero .hhead .h1t{font-family:var(--disp);font-weight:700;color:#fff;
  letter-spacing:-.032em;font-size:clamp(34px,4.6vw,64px);line-height:1.03;
  margin:0;max-width:30ch;padding-bottom:.1em}
.rhero .hhead .h1a{color:#cdd9ec}
/* z-index:0 on the span with -1 on its ::after is the pairing that keeps the gold bar
   BEHIND the glyphs rather than painted over them. Same fix as ie.css for `.hero h1 .u`,
   which is recorded there as a real render defect, not a precaution. */
.rhero .hhead .h1t .u{position:relative;z-index:0;white-space:nowrap;color:#fff}
.rhero .hhead .h1t .u::after{content:"";position:absolute;left:0;right:0;bottom:.06em;
  height:.14em;background:var(--gold-2);border-radius:3px;z-index:-1;opacity:.92}
/* nowrap protects the underline from breaking across two lines; below 640 the phrase is
   wider than the viewport, so it has to be allowed to wrap. */
@media(max-width:640px){.rhero .hhead .h1t .u{white-space:normal}}

/* ─────────────────────────────────────────────────────────────────────────────
   `.reachsec.no-panel` — the REACH band WITHOUT the booking panel. Added 2026-08-25
   for /about-us/, which declares IE-NOFORM.

   ie.css sets `.reachsec .wrap{grid-template-columns:1fr 460px}` above 980px, and the
   460px track exists for one child: `.rch-form`. Every page that has shipped this band
   so far carries that form, so nobody had ever rendered the band without it. On
   /about-us/ the track was still reserved and the right half of the section rendered
   as an empty void the full height of the band. Caught on the render, not by a gate:
   an empty grid track overflows nothing and contrasts fine, so overlap, sweep, qa and
   bgcontrast all passed it.

   ⚠ Only the >=981px layout needs this. Below 980px ie.css already collapses the wrap
     to a single column, so the modifier deliberately does nothing there.
   ⚠ The connector rule between the two items is suppressed. `.rch-item:not(:last-child)
     ::before` draws a vertical line from item one down to item two, which is correct
     when they are stacked and is a line pointing at nothing when they sit side by side.
   ───────────────────────────────────────────────────────────────────────────── */
@media(min-width:981px){
  .reachsec.no-panel .wrap{grid-template-columns:1fr}
  .reachsec.no-panel .rch-lower{grid-column:1 / -1;padding-left:0}
  .reachsec.no-panel .rch-items.rch-steps{display:grid;grid-template-columns:1fr 1fr;
    column-gap:clamp(34px,4.4vw,64px)}
  .reachsec.no-panel .rch-item{padding-bottom:0}
  .reachsec.no-panel .rch-item:not(:last-child)::before{display:none}
}

/* ══ DOC-NATIVE DEVICES (Notion Parity, promoted 2026-08-27) ══════════════════════════════════
   Shared home for the devices the doc-native assembler and the AC-repair design canonical use.
   statx v2 + tmx match the canonical page's own block verbatim (kept there too, harmless);
   cmpx had NO home after the canonical replaced the per-page css - this is now the one source. */
.statx-sec .statx{display:grid;grid-template-columns:repeat(4,1fr);gap:0;background:#FAF8F3;border:1px solid rgba(10,28,63,.12);border-radius:20px;box-shadow:0 30px 60px rgba(10,28,63,.10),0 4px 14px rgba(10,28,63,.05);overflow:hidden}
.statx .s{padding:38px 32px 32px;text-align:left;border-left:1px solid rgba(10,28,63,.10);position:relative}
.statx .s:first-child{border-left:0}
.statx .s::before{content:"";position:absolute;left:32px;top:0;width:46px;height:4px;background:#E1A50C;border-radius:0 0 3px 3px}
.statx .s > b{display:flex;align-items:flex-end;height:clamp(36px,3.5vw,52px);font-family:Montserrat,sans-serif;font-weight:800;font-size:clamp(34px,3.4vw,50px);line-height:.94;color:#0a1c3f;letter-spacing:-.02em}
.statx .s > i{display:block;font-style:normal;font-family:Montserrat,sans-serif;font-weight:700;font-size:12.5px;letter-spacing:.08em;text-transform:uppercase;color:#0a1c3f;margin-top:12px}
.statx .s > i::before{content:"";display:inline-block;width:16px;height:2px;background:#E1A50C;vertical-align:middle;margin-right:8px}
@media(min-width:861px){.statx .s > i{min-height:36px}}
.statx .s > span{display:block;margin-top:8px;font-size:14px;line-height:1.6;color:rgba(10,28,63,.64)}
@media(max-width:860px){.statx-sec .statx{grid-template-columns:1fr 1fr}.statx .s{padding:30px 24px 26px}.statx .s::before{left:24px}.statx .s:nth-child(3){border-left:0}.statx .s:nth-child(n+3){border-top:1px solid rgba(10,28,63,.1)}}
@media(max-width:480px){.statx-sec .statx{grid-template-columns:1fr}.statx .s{border-left:0}.statx .s:nth-child(n+2){border-top:1px solid rgba(10,28,63,.1)}}
.statx .s > b.yr{font-size:clamp(24px,2.4vw,34px);letter-spacing:-.01em}
.tmx{display:grid;grid-template-columns:1fr 1fr;gap:34px 46px;max-width:960px;margin:40px auto 0}
.tmx .pl-note + .pl-note{margin-top:0;padding-top:0;border-top:0}
.tmx .pl-note + .pl-note .n{top:2px}
@media(max-width:760px){.tmx{grid-template-columns:1fr;gap:26px}}
.cmpx{max-width:920px;margin:34px auto 0;border:1px solid rgba(10,28,63,.14);border-radius:16px;overflow:hidden;background:#fff;box-shadow:0 22px 48px rgba(10,28,63,.08)}
.cmpx-h{display:grid;grid-template-columns:1fr 1fr;font-family:Montserrat,sans-serif;font-weight:700;font-size:15px}
.cmpx-h span{padding:16px 22px;background:rgba(10,28,63,.05);color:rgba(10,28,63,.75)}
.cmpx-h .us{background:#0a1c3f;color:#fff}
.cmpx-r{display:grid;grid-template-columns:1fr 1fr;border-top:1px solid rgba(10,28,63,.1)}
.cmpx-r > div{display:flex;gap:10px;align-items:flex-start;padding:15px 22px;font-size:15px;line-height:1.6;color:rgba(10,28,63,.85)}
.cmpx-r > div svg{width:16px;height:16px;flex:0 0 16px;margin-top:4px;color:rgba(10,28,63,.4)}
.cmpx-r .us{background:rgba(225,165,12,.07)}
.cmpx-r .us svg{color:#E1A50C}
@media(max-width:720px){.cmpx-h,.cmpx-r{grid-template-columns:1fr}.cmpx-h span:first-child{display:none}}
.dnlist{list-style:none;margin:18px 0 0;padding:0;display:grid;gap:14px}
.dnlist li{display:flex;gap:12px;align-items:flex-start;font-size:15.5px;line-height:1.65;color:rgba(10,28,63,.85)}
.dnlist li svg{width:18px;height:18px;flex:0 0 18px;margin-top:4px;color:#E1A50C}
.dnlist.routelist{max-width:760px;margin:26px auto 0}
.sec-dark .dnlist li{color:rgba(255,255,255,.88)}
.sec-dark .dnlist li b{color:#fff}
a.cxcard{display:block;text-decoration:none;color:inherit}


/* ═══════════════════════════════════════════════════════════════════════════════════════════
   DOC-NATIVE CANONICAL v2 DEVICES (2026-08-27) — promoted from the hand-tuned canonical
   /air-conditioning-repair-atlanta-ga/ after the user finalized it. Emitted by
   _shared/build-docnative.cjs on every doc-native service page. The canonical page carries its
   own inline copies of these; keep the two in step.
   ═══════════════════════════════════════════════════════════════════════════════════════════ */
/* stats folded into the intro's text column (replaces the statx band) */
.statin{display:grid;grid-template-columns:1fr 1fr;gap:22px 30px;margin-top:32px;padding-top:28px;border-top:1px solid rgba(10,28,63,.12)}
.statin .s{position:relative;padding-left:16px}
.statin .s::before{content:"";position:absolute;left:0;top:4px;bottom:4px;width:3px;border-radius:2px;background:#E1A50C}
.statin .s > b{display:block;font-family:Montserrat,sans-serif;font-weight:800;font-size:24px;line-height:1.05;color:#0a1c3f;letter-spacing:-.015em}
.statin .s > i{display:block;font-style:normal;font-family:Montserrat,sans-serif;font-weight:700;font-size:11px;letter-spacing:.07em;text-transform:uppercase;color:#0a1c3f;margin-top:6px}
.statin .s > span{display:block;margin-top:5px;font-size:12.8px;line-height:1.55;color:rgba(10,28,63,.62)}
@media(max-width:480px){.statin{grid-template-columns:1fr;gap:18px}}
/* cost: left text + the cost-rail element */
.costs{display:grid;grid-template-columns:1.15fr .85fr;gap:clamp(34px,4.5vw,60px);align-items:center}
.costp .chap{justify-content:flex-start}
.costp p{font-size:16.5px;line-height:1.85;color:rgba(10,28,63,.78)}
.costviz{background:#fff;border:1px solid rgba(10,28,63,.14);border-radius:18px;padding:30px 28px 26px;box-shadow:0 24px 48px rgba(10,28,63,.08);max-width:420px;justify-self:center;width:100%}
.cv-lb{display:block;font-family:Montserrat,sans-serif;font-weight:700;font-size:11.5px;letter-spacing:.12em;text-transform:uppercase;color:#B07C00}
.cv-rail{position:relative;height:6px;border-radius:3px;margin:26px 6px 18px;background:linear-gradient(90deg,#E1A50C,#143883)}
.cv-rail .dot{position:absolute;top:50%;transform:translate(-50%,-50%);width:16px;height:16px;border-radius:50%;background:#fff;border:4px solid #E1A50C;box-shadow:0 2px 8px rgba(10,28,63,.25)}
.cv-rail .dot.l{left:0}
.cv-rail .dot.r{left:100%;border-color:#143883}
.cv-ends{display:grid;grid-template-columns:1fr 1fr;gap:18px}
.cv-ends .e b{display:block;font-family:Montserrat,sans-serif;font-weight:700;font-size:13.5px;color:#0a1c3f}
.cv-ends .e span{display:block;margin-top:4px;font-size:12.8px;line-height:1.5;color:rgba(10,28,63,.62)}
.cv-ends .e.r{text-align:right}
.cv-foot{margin-top:22px;padding-top:18px;border-top:1px solid rgba(10,28,63,.10);font-size:13.5px;line-height:1.6;color:rgba(10,28,63,.72)}
.cv-foot b{font-family:Montserrat,sans-serif;font-weight:800;color:#143883}
.costp-solo{max-width:820px}
@media(max-width:860px){.costs{grid-template-columns:1fr;gap:30px}.costp p{font-size:15.5px}.costviz{justify-self:start}}
/* compare: the proper table (replaces cmpx) */
.cmpt-wrap{max-width:920px;margin:0 auto;overflow-x:auto}
.cmpt{width:100%;border-collapse:separate;border-spacing:0;border:1px solid rgba(10,28,63,.14);border-radius:16px;overflow:hidden;background:#fff}
.cmpt th{background:#0a1c3f;color:#fff;font-family:Montserrat,sans-serif;font-weight:700;font-size:15.5px;text-align:left;padding:17px 24px;width:50%}
.cmpt th+th{border-left:1px solid rgba(255,255,255,.16)}
.cmpt td{padding:16px 24px;font-size:15px;line-height:1.6;color:rgba(10,28,63,.85);border-top:1px solid rgba(10,28,63,.10);vertical-align:top}
.cmpt td+td{border-left:1px solid rgba(10,28,63,.10)}
.cmpt tbody tr:nth-child(even) td{background:rgba(10,28,63,.028)}
@media(max-width:640px){.cmpt th{font-size:13.5px;padding:13px 14px}.cmpt td{font-size:13.5px;padding:12px 14px}}
/* matrix tables (label column + 2+ data columns): the 50% th width is a 2-col assumption */
.cmpt-multi th{width:auto}
.cmpt-multi th:first-child{width:22%}
/* A FOUR-column matrix at 390px. Restoring this page's two dropped columns took the table to
   373px inside a 350px content box; .cmpt-wrap's overflow-x:auto absorbed it, so no page-overflow
   gate saw anything, but the fourth column shipped SLICED MID-WORD with no scroll affordance --
   which reads as a broken render, not a scroller (owner report 2026-08-27, humidifiers, the only
   4-column table in the fleet). Tightening the cells recovers ~40px so it FITS instead; the wrap
   keeps overflow-x:auto as the backstop below 390px. Scoped with :has() to the 4+-column case, so
   the six 3-column .cmpt-multi tables are untouched. Re-measure with _qa/_cmpt-scroll.mjs. */
@media(max-width:640px){
  .cmpt-multi:has(thead th:nth-child(4)) th{font-size:12.5px;padding:12px 9px;line-height:1.34}
  .cmpt-multi:has(thead th:nth-child(4)) td{font-size:12.5px;padding:11px 9px}
  .cmpt-multi:has(thead th:nth-child(4)) th:first-child{width:20%}
}
/* ...and then a THREE-column matrix did the same thing (owner report 2026-08-28,
   air-conditioning-maintenance). _cmpt-scroll.mjs measured its table at 364px inside the same
   350px box: the third column shipped sliced mid-word ("With regular maintenance" cut, "runs
   closer to", "they cascade"), again with overflow-x:auto absorbing it so every page-overflow gate
   passed. It was the ONLY 3-column table in the fleet that did not fit -- the other six sit a few
   px under, so this is a margin problem, not a design problem. Same remedy as the 4-column case
   above, horizontal padding only: 3 columns x 2 sides x 4px recovers ~24px, which is more than the
   14px it was over. Scoped to the 3-column case with :not(:has()) so humidifiers' 4-column table
   keeps its own tighter rule and nothing outside .cmpt-multi is touched. The six that already fit
   gain ~24px of text room and lose no styling. Re-measure ALL SEVEN with _qa/_cmpt-scroll.mjs. */
@media(max-width:640px){
  .cmpt-multi:not(:has(thead th:nth-child(4))) th{padding-left:10px;padding-right:10px}
  .cmpt-multi:not(:has(thead th:nth-child(4))) td{padding-left:10px;padding-right:10px}
}
.cmpt-note{max-width:920px;margin:14px auto 0;font-size:13.5px;line-height:1.6;color:rgba(10,28,63,.62)}
/* why: dark three-card band, doc content only (replaces the ownr photo band) */
.whysec{background:linear-gradient(160deg,#0a1c3f 0%,#122a56 55%,#0a1c3f 100%)}
.wsx{display:grid;grid-template-columns:repeat(3,1fr);gap:22px;margin-top:26px}
.ws{position:relative;background:rgba(255,255,255,.045);border:1px solid rgba(255,255,255,.12);border-radius:18px;padding:34px 28px 30px}
.ws::before{content:"";position:absolute;left:28px;top:0;width:44px;height:4px;background:#E1A50C;border-radius:0 0 3px 3px}
.ws h3{font-size:19px;color:#fff;letter-spacing:-.012em;margin:0}
.ws p{font-size:14.8px;line-height:1.68;color:#b6c4de;margin:11px 0 0}
@media(max-width:960px){.wsx{grid-template-columns:1fr;gap:16px;max-width:640px;margin-left:auto;margin-right:auto}}
/* timing: dark split band, photo left / doc copy right (replaces the light tmx pair) */
.tmsplit{display:grid;grid-template-columns:.92fr 1.08fr;gap:clamp(34px,4.5vw,64px);align-items:center}
.tmdark{background:linear-gradient(160deg,#0a1c3f 0%,#122a56 55%,#0a1c3f 100%)}
.tm-pic .pic{border-radius:22px;overflow:hidden;border:1px solid rgba(10,28,63,.14);box-shadow:0 30px 60px rgba(10,28,63,.14)}
.tm-pic img{width:100%;height:100%;aspect-ratio:4/4.4;object-fit:cover;display:block}
.tmdark .tm-pic .pic{border-color:rgba(255,255,255,.16);box-shadow:0 34px 66px rgba(6,18,44,.42)}
.tm-pt+.tm-pt{margin-top:22px;padding-top:22px;border-top:1px solid rgba(10,28,63,.10)}
.tm-pt h3{font-size:19.5px;color:var(--navy,#143883);letter-spacing:-.012em;margin:0}
.tm-pt p{font-size:15.2px;line-height:1.7;color:rgba(10,28,63,.68);margin:10px 0 0}
.tmdark .tm-pt h3{color:#fff}
.tmdark .tm-pt p{color:#b6c4de}
.tmdark .tm-pt p a{color:#FCC952}
.tmdark .tm-pt+.tm-pt{border-top-color:rgba(255,255,255,.12)}
.tm-cta{display:flex;gap:14px;flex-wrap:wrap;margin-top:30px}
@media(max-width:900px){.tmsplit{grid-template-columns:1fr}.tm-pic{max-width:560px}.tm-pic img{aspect-ratio:16/10}}
/* blog grid: every .bgrid on the build is a BLOG grid (brand pages deleted 08-26); restore the
   homepage blog-card render that this sheet's brand .bcard rules were overriding */
.bgrid{grid-template-columns:repeat(3,1fr);gap:26px;margin-top:42px}
.bgrid .bcard{padding:0;border-radius:16px}
.bgrid .bcard::before{content:none}
@media(max-width:960px){.bgrid{grid-template-columns:1fr 1fr;gap:20px}}
@media(max-width:640px){.bgrid{grid-template-columns:1fr}}

/* hub services: DARK icon cards (user 2026-08-27) */
.svcx{display:grid;grid-template-columns:repeat(3,1fr);gap:22px;margin-top:30px}
.svcx .sc{position:relative;display:flex;flex-direction:column;background:linear-gradient(160deg,#0e2247 0%,#16305d 100%);border:1px solid rgba(255,255,255,.12);border-radius:18px;padding:34px 28px 26px;text-decoration:none;box-shadow:0 18px 40px rgba(10,28,63,.18);transition:box-shadow .25s ease,transform .25s ease,border-color .25s ease}
.svcx .sc::before{content:"";position:absolute;left:28px;top:0;width:44px;height:4px;background:#E1A50C;border-radius:0 0 3px 3px}
.svcx .sc:hover{transform:translateY(-3px);box-shadow:0 28px 56px rgba(10,28,63,.30);border-color:rgba(252,201,82,.45)}
.svcx .sc .ic{display:grid;place-items:center;width:48px;height:48px;border-radius:13px;border:1.4px solid rgba(252,201,82,.5);background:rgba(252,201,82,.08);color:#FCC952;margin-bottom:18px}
.svcx .sc .ic svg{width:24px;height:24px}
.svcx .sc h3{font-size:19px;color:#fff;letter-spacing:-.012em;margin:0}
.svcx .sc p{font-size:14.8px;line-height:1.66;color:#b6c4de;margin:11px 0 18px;flex:1}
.svcx .sc .go{display:inline-flex;align-items:center;gap:7px;font-family:Montserrat,sans-serif;font-weight:700;font-size:12.5px;letter-spacing:.06em;text-transform:uppercase;color:#FCC952;margin-top:auto}
.svcx .sc .go svg{width:15px;height:15px;transition:transform .25s ease}
.svcx .sc:hover .go svg{transform:translateX(4px)}
@media(max-width:960px){.svcx{grid-template-columns:1fr 1fr;gap:16px}}
@media(max-width:640px){.svcx{grid-template-columns:1fr}}

/* the compact CTA card that completes the hub service grid (user 2026-08-27): same dark vibe
   as its siblings, gold border accent, the draft's short question + the two buttons */
.svcx .ctac{border-color:rgba(252,201,82,.42);justify-content:center}
.svcx .ctac h3{margin:0 0 20px}
.svcx .ctac .cta-btns{display:flex;gap:12px;flex-wrap:wrap;margin-top:auto}

/* the prose that closes the hub service grid: centered, internally linked service names */
/* .svcnote: NOT .svcfoot — ie.css owns that name as the homepage flex foot */
.svcnote{max-width:840px;margin:36px auto 0;font-size:15.4px;line-height:1.85;color:rgba(10,28,63,.72);text-align:center}
.svcnote b{color:#0a1c3f;display:inline;font-size:inherit}
.svcnote a,.svcnote b a{color:var(--navy,#143883);font-weight:700;text-decoration:underline;text-underline-offset:3px;text-decoration-thickness:2px;text-decoration-color:rgba(225,165,12,.55)}
.svcnote a:hover{text-decoration-color:#E1A50C}

/* costviz fact variant (pages whose drafts state a fixed number but no cheap/expensive pair) */
.cv-fact{margin:20px 0 0;font-family:Montserrat,sans-serif;font-weight:700;font-size:17px;line-height:1.5;color:#0a1c3f}
.cv-fact b{color:#143883;font-weight:800}

/* the draft's 💡 callout on a light prose section: a quiet aside, never body copy (the dark
   signs band renders the same callout as .sgx-links) */
.pnote{max-width:820px;margin:28px auto 0;padding:18px 22px;border-left:3px solid #E1A50C;background:rgba(10,28,63,.035);border-radius:0 12px 12px 0;font-size:15.2px;line-height:1.8;color:rgba(10,28,63,.78)}
.pnote a{color:var(--navy,#143883);font-weight:700;text-decoration:underline;text-underline-offset:3px;text-decoration-thickness:2px;text-decoration-color:rgba(225,165,12,.55)}
.pnote a:hover{text-decoration-color:#E1A50C}

/* generic inline button pair (a prose section's "**CTAs:**" spec line); .svcx .ctac keeps its
   own scoped margin variant */
.cta-btns{display:flex;gap:12px;flex-wrap:wrap}

/* statin PLAIN cell (2026-08-27): a stats line that is a statement, not a figure. statCell()
   used to force every line into the figure/label/note shape, which set the first word at 24px
   and the rest of the sentence in 11px uppercase. Same grid, same gold rule, sentence readable. */
.statin .s.plain > span{margin-top:0;font-size:14.5px;line-height:1.6;color:rgba(10,28,63,.82)}
.statin .s.plain > span b{font-weight:700;color:#0a1c3f}

/* ============================================================================================
   ROUTE DEVICE (.rtx*) — the "How fast we reach you" band on the 8 location pages.
   Added 2026-08-28 (user: the band "was an interactive feature", reference supplied).

   WHAT IT REPLACES. The draft's route table is a SLOT SPEC, not prose: its rows are keyed
   `A` / `B` / `Badge`, which the old `.dnlist.routelist` printed literally as three checkmark
   bullets reading "A Indoor Experts...", "B Your Buckhead home...", "Badge ~25 min...". The
   slot NAMES were on the page and Notion's escaped tilde shipped with them.

   THE ORIGIN MARKER IS THE BRAND MARK, not a generic map pin. It is the same doubled broken
   ring as `--ie-arc` (outer gold r9.2 sw2.6 dash 22.80/6.10, inner navy r4.4 sw2.4 dash
   10.90/2.92, group rotated -25deg) in its on-dark colours, drawn inline so it can animate.
   That is the whole idea of the device: the route starts AT the company's own mark.
   Geometry must stay in step with ie-v16.css :root --ie-arc. Change one, change both.

   NO DISTANCE, NO MAP TILES, NO DRAWN BOUNDARY. The travel time, the traffic note and the
   route name are the DRAFT's own three strings and nothing here computes or rounds them. The
   "Check the drive" link hands the number to Google to confirm rather than asserting it harder,
   and its origin/destination are built only from strings already in the table (the office
   address, and the first ZIP of the destination row).
   ============================================================================================ */
.rtx{--rtx-chev:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 8'%3E%3Cpath d='M2 1l4 3-4 3' fill='none' stroke='%23fff' stroke-width='1.6' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  display:grid;grid-template-columns:minmax(0,1.06fr) minmax(0,.94fr);gap:22px;
  align-items:stretch;margin-top:34px}

/* the card */
.rtx-card{position:relative;border-radius:20px;padding:26px 26px 24px;
  background:linear-gradient(158deg,rgba(255,255,255,.14),rgba(255,255,255,.06));
  border:1px solid rgba(255,255,255,.21);
  box-shadow:0 24px 54px rgba(4,14,38,.34);backdrop-filter:blur(3px)}

/* the rail: ghost path, drawn path, brand-mark origin, van */
.rtx-rail{display:block;width:100%;height:auto;overflow:visible}
.rtx-ghost{fill:none;stroke:rgba(255,255,255,.16);stroke-width:2;stroke-linecap:round;
  stroke-dasharray:1 7}
.rtx-line{fill:none;stroke:url(#rtxg);stroke-width:3.2;stroke-linecap:round}
.rtx-ring-o{fill:none;stroke:#FCC952;stroke-width:2.6;stroke-dasharray:22.80 6.10}
.rtx-ring-i{fill:none;stroke:#7f9bdd;stroke-width:2.4;stroke-dasharray:10.90 2.92}
.rtx-van path,.rtx-van circle{fill:none;stroke:#fff;stroke-width:2;stroke-linecap:round;
  stroke-linejoin:round}
.rtx-van .glass{fill:rgba(252,201,82,.22);stroke:none}

/* A / B rows. The pin letters are the draft's own row keys, kept as the visual index they were
   always meant to be instead of being read out as body text. */
.rtx-pts{list-style:none;margin:20px 0 0;padding:18px 0 0;display:grid;gap:15px;
  border-top:1px solid rgba(255,255,255,.13)}
.rtx-pts li{display:grid;grid-template-columns:30px 1fr;gap:13px;align-items:start}
.rtx-pin{width:30px;height:30px;border-radius:50%;display:grid;place-items:center;
  font-family:var(--disp,'Montserrat',sans-serif);font-weight:700;font-size:12.5px;
  letter-spacing:.02em;margin-top:1px}
.rtx-pin.a{color:#FCC952;border:1.6px solid rgba(252,201,82,.62);background:rgba(252,201,82,.12)}
.rtx-pin.b{color:#a9c0ee;border:1.6px solid rgba(127,155,221,.6);background:rgba(127,155,221,.14)}
.rtx-pts b{display:block;font-family:var(--disp,'Montserrat',sans-serif);font-weight:700;
  font-size:15.6px;line-height:1.35;color:#fff}
/* ⚠ :not(.rtx-pin) is load-bearing, not defensive. The A/B pin is itself a <span> inside
   `.rtx-pts li`, so a bare `.rtx-pts span` also matched it — and at (0,1,1) it outranked
   `.rtx-pin` (0,1,0). The pin therefore computed display:block, font-size:14.4px,
   line-height:23px, margin-top:3px and text-align:start, which made `place-items:center` inert
   and dropped the letter to the TOP-LEFT of its 30px circle instead of the middle (owner report
   2026-08-28). Address lines live inside the row's <div>; the pin never does. */
.rtx-pts span:not(.rtx-pin){display:block;margin-top:3px;font-size:14.4px;line-height:1.6;
  color:rgba(255,255,255,.7)}

/* the badge chip: the draft's time / traffic / via line */
.rtx-badge{display:flex;align-items:center;gap:16px;flex-wrap:wrap;margin-top:20px;
  padding:15px 18px;border-radius:14px;background:rgba(252,201,82,.11);
  border:1px solid rgba(252,201,82,.3)}
.rtx-badge .t{font-family:var(--disp,'Montserrat',sans-serif);font-weight:800;
  font-size:clamp(21px,2.1vw,26px);line-height:1;color:#FCC952;white-space:nowrap}
.rtx-badge .d{flex:1 1 190px;font-size:14.2px;line-height:1.55;color:rgba(255,255,255,.8)}
.rtx-badge .v{flex:0 0 auto;display:inline-flex;align-items:center;gap:7px;
  padding:9px 15px;border-radius:999px;font-family:var(--disp,'Montserrat',sans-serif);
  font-weight:700;font-size:12.6px;letter-spacing:.03em;text-transform:uppercase;
  color:#0b1f45;background:#FCC952;transition:background .2s ease,transform .2s ease}
.rtx-badge .v svg{width:14px;height:14px;stroke:currentColor;stroke-width:2.4;fill:none}
.rtx-badge .v:hover{background:#fff;transform:translateY(-1px)}
.rtx-badge .v:focus-visible{outline:2px solid #fff;outline-offset:3px}

/* the four fact cards, 2x2 beside the card.
   These were `.cxgrid.three` + `.cxcard`, i.e. WHITE cards on the dark photo band, and four
   cards in a three-column grid left a single orphan on row two. Both fixed here. */
.rtx-facts{display:grid;grid-template-columns:1fr;grid-template-rows:repeat(4,auto);
  align-content:space-between;gap:14px}
.rtx-f{position:relative;padding:20px 20px 18px;border-radius:15px;
  background:rgba(255,255,255,.06);border:1px solid rgba(255,255,255,.14);
  transition:background .22s ease,border-color .22s ease,transform .22s ease}
.rtx-f::before{content:"";position:absolute;left:20px;right:20px;top:0;height:2px;
  border-radius:0 0 2px 2px;background:#E1A50C;transform:scaleX(0);transform-origin:left;
  transition:transform .28s cubic-bezier(.2,.7,.3,1)}
.rtx-f:hover{background:rgba(255,255,255,.09);border-color:rgba(255,255,255,.24);
  transform:translateY(-2px)}
.rtx-f:hover::before{transform:scaleX(1)}
.rtx-f h3{margin:0;font-family:var(--disp,'Montserrat',sans-serif);font-weight:700;
  font-size:15.2px;line-height:1.35;color:#FCC952}
.rtx-f p{margin:8px 0 0;font-size:14.3px;line-height:1.62;color:rgba(255,255,255,.78)}

/* motion, keyed to the shared .rv-in reveal (no new JS). The path draws, the van runs it, the
   brand ring settles. Everything animates transform / opacity / stroke-dashoffset only. */
.js [data-rv] .rtx-line{stroke-dasharray:var(--rtx-len,480);stroke-dashoffset:var(--rtx-len,480)}
.js [data-rv] .rtx-van{opacity:0}
.js [data-rv] .rtx-origin{opacity:0;transform:scale(.6);transform-origin:0 0}
.js [data-rv].rv-in .rtx-line{animation:rtxdraw 1.15s cubic-bezier(.3,.7,.3,1) .12s forwards}
.js [data-rv].rv-in .rtx-van{animation:rtxdrive 1.15s cubic-bezier(.3,.7,.3,1) .12s forwards}
.js [data-rv].rv-in .rtx-origin{animation:rtxpop .55s cubic-bezier(.2,1.5,.4,1) .05s forwards}
@keyframes rtxdraw{to{stroke-dashoffset:0}}
@keyframes rtxpop{to{opacity:1;transform:scale(1)}}
@keyframes rtxdrive{
  0%{opacity:0;transform:translate(-448px,82px)}
  12%{opacity:1}
  100%{opacity:1;transform:translate(0,0)}
}
.rtx-card:hover .rtx-van{transform:translate(6px,-2px);transition:transform .3s ease}

/* Shape-2 drafts key the drive separately ("About 20 minutes", "About five minutes"), which is
   far longer than shape 1's "~25 min" and blew the nowrap chip off a 390px screen. */
.rtx-badge .t.long{font-size:clamp(17px,1.7vw,20px);white-space:normal}

/* ARROW CHAIN — the route strip for a draft that writes its route as
   "390 Stovall St SE -> I-75/85 Connector north -> GA-400 north -> Glenridge Drive" and specs no
   Point A / Point B pair (Sandy Springs). Numbered list, but the numbers are never shown: the
   chevrons carry the order. Owner ruling on /service-area/ was "remove numbers", so none appear. */
.rtx-chain{list-style:none;margin:20px 0 0;padding:18px 0 0;display:flex;flex-wrap:wrap;
  align-items:center;gap:8px 0;border-top:1px solid rgba(255,255,255,.13)}
.rtx-chain li{display:inline-flex;align-items:center;font-size:14.6px;line-height:1.4;
  color:rgba(255,255,255,.9)}
.rtx-chain li + li::before{content:"";width:16px;height:8px;margin:0 9px;flex:0 0 16px;
  background:currentColor;opacity:.42;
  -webkit-mask:var(--rtx-chev) center/contain no-repeat;mask:var(--rtx-chev) center/contain no-repeat}
.rtx-chain li:first-child{font-family:var(--disp,'Montserrat',sans-serif);font-weight:700;color:#fff}
.rtx-chain li:last-child{font-family:var(--disp,'Montserrat',sans-serif);font-weight:700;color:#FCC952}

/* a chain-shaped draft carries no time string, so it gets no chip: the maps affordance moves to
   the card foot rather than being lost. Same link, quieter treatment. */
.rtx-foot{margin:20px 0 0;padding-top:16px;border-top:1px solid rgba(255,255,255,.13)}
.rtx-foot a{display:inline-flex;align-items:center;gap:7px;font-family:var(--disp,'Montserrat',sans-serif);
  font-weight:700;font-size:12.6px;letter-spacing:.03em;text-transform:uppercase;color:#FCC952;
  text-decoration:underline;text-underline-offset:4px;text-decoration-thickness:2px;
  text-decoration-color:rgba(252,201,82,.4)}
.rtx-foot a svg{width:14px;height:14px;stroke:currentColor;stroke-width:2.4;fill:none}
.rtx-foot a:hover{color:#fff;text-decoration-color:#fff}

/* a band with no fact cards gives the card the full width */
.rtx.solo{grid-template-columns:1fr}

/* The route band owns a graphic now, so its photo goes back to being texture. .bgq already
   grades to .94; the livery text on B01_van_atlanta_skyline still read through it. */
.secbg.bgq.rtxsec > .bgw img{opacity:.3}

/* responsive */
@media(max-width:1080px){
  .rtx{grid-template-columns:1fr;gap:18px}
  /* stacked, a single column of four would be a very tall rail: go 2x2 */
  .rtx-facts{grid-template-columns:1fr 1fr;grid-template-rows:auto auto;align-content:start}
}
@media(max-width:640px){
  .rtx-card{padding:20px 18px 18px;border-radius:16px}
  .rtx-facts{grid-template-columns:1fr}
  .rtx-badge{gap:12px;padding:14px 15px}
  .rtx-badge .d{flex-basis:100%;order:3}
  .rtx-pts b{font-size:15px}
}
/* the drawn path and the drive are decoration; a reader who asked for less motion gets the
   finished state, not a blank rail */
@media(prefers-reduced-motion:reduce){
  .js [data-rv] .rtx-line{stroke-dasharray:none;stroke-dashoffset:0}
  .js [data-rv] .rtx-van,.js [data-rv] .rtx-origin{opacity:1;transform:none}
    .js [data-rv].rv-in .rtx-line,.js [data-rv].rv-in .rtx-van,
  .js [data-rv].rv-in .rtx-origin{animation:none}
  .rtx-card:hover .rtx-van{transform:none}
}

/* ============ SERVICES · svcard (2026-08-28) =====================================================
   Owner picked concept B1 from _concepts/services-blue-2026-08-28.html: solid navy cards, one
   colour, laid out two-by-two.

   Replaces the `.cxgrid.three` + `.cxcard` treatment on doc-native services sections. Two reasons
   it changed, not one:
   (a) FOUR groups in a THREE-column grid left "Air Quality" orphaned alone on a second row. The
       location drafts all carry exactly four groups, so `.svgrid` is 2x2 by design.
   (b) The owner asked for the cards in blue. Navy fill, white heading, muted-blue blurb, and the
       services as outlined pills that go gold on hover.

   Every pill is a link now (owner: "everything needs to be internal links") — the `span` rule below
   is kept only as the fallback skin for a label with no page, so a future draft naming a service we
   have no page for degrades to plain text instead of a dead anchor. */
.svgrid{display:grid;grid-template-columns:1fr 1fr;gap:20px;margin-top:40px}
.svcard{background:linear-gradient(150deg,var(--navy-ink) 0%,var(--navy) 100%);
  border:1px solid rgba(255,255,255,.10);border-radius:var(--r);padding:26px 28px;
  box-shadow:0 10px 26px rgba(11,31,69,.16)}
.svcard h3{font-family:var(--disp);font-weight:700;font-size:20px;color:#fff;margin:0 0 6px}
.svcard .svbl{font-size:14.5px;color:#a9b8d4;margin:0 0 18px;line-height:1.55}
.svchips{display:flex;flex-wrap:wrap;gap:9px}
.svchips a,.svchips span{font-family:var(--disp);font-weight:600;font-size:13.5px;
  padding:7px 13px;border-radius:999px;text-decoration:none;display:inline-block;transition:.18s}
.svchips a{color:#fff;border:1px solid rgba(255,255,255,.34);background:rgba(255,255,255,.05)}
.svchips a:hover{border-color:var(--gold-2);color:var(--gold-2);background:rgba(252,201,82,.08)}
.svchips span{color:#8fa0bf;border:1px dashed rgba(255,255,255,.20);background:transparent}
/* ⚠ The band behind these cards stays WHITE. Do not also darken the section: the signs band
   directly above is already `sec-dark`, and a dark band here would read as one continuous navy
   block from the signs section through to the services list. */
@media(max-width:820px){.svgrid{grid-template-columns:1fr}}

/* ============ .ownc — CREDENTIALS STRIP (2026-08-28) ============================================
   Owner ruling: port the old `.ownr` band's `own-cred` grid forward rather than lose it to a
   regeneration. It read "Who is coming to the house" and carried GA CN211042 · Trane Comfort
   Specialist · Since 2014 / Locally owned · 4.8 from 100+ reviews, and it was live on brookhaven,
   buckhead, decatur and old-fourth-ward.
   The canonical v2 ruling had stripped credentials from the `why` device — correctly, for SERVICE
   pages, where the same claims already sit in the trust strip. On a LOCATION page this grid is the
   local-trust payload, so it is restored there and ONLY there: the builder gates it on an
   `hvac-contractor-` slug and renders it inside the existing why (or, where a page has no why
   band, timing) section. Never its own section — that would breach the no-extras rule. */
.ownc{margin-top:30px;padding-top:22px;border-top:1px solid rgba(255,255,255,.14)}
.ownc .lb{display:block;font-family:var(--disp,'Montserrat',sans-serif);font-weight:600;
  font-size:11.5px;letter-spacing:.15em;text-transform:uppercase;color:#8fa0bf;margin-bottom:14px}
.ownc .g{display:grid;grid-template-columns:repeat(4,1fr);gap:14px}
.ownc .g > span{display:block;padding-left:14px;border-left:2px solid rgba(252,201,82,.55)}
.ownc .g b{display:block;font-family:var(--disp,'Montserrat',sans-serif);font-weight:700;
  font-size:16px;color:#fff;line-height:1.25}
.ownc .g > span > span{display:block;margin-top:2px;font-size:13px;color:#a9b8d4;line-height:1.4}
@media(max-width:820px){.ownc .g{grid-template-columns:1fr 1fr;gap:16px 14px}}
@media(max-width:420px){.ownc .g{grid-template-columns:1fr}}
