/* ═══════════════════════════════════════════════════════════════════════════
   ⛔ HAND-EDITED ON PURPOSE — 23 Sep 2026. THIS FILE HAS DIVERGED FROM ITS
   SOURCE, AND THE DIVERGENCE IS THE POINT.

   public/demo/<name> is normally GENERATED from ~/Desktop/demo-<name>/dist by
   tools/sync-demo.mjs, and the generated headers say never to hand-edit it.
   The hero, type and offer-strip pass below was written HERE, directly, with
   the owner's decision, because:

   - the sources live OUTSIDE this repo, are untracked and are unbacked; and
   - for at least one demo the source provably does NOT reproduce the published
     copy — a rebuild loses photo bands, self-hosted fonts and the town.

   public/demo IS committed to git, so this work is recoverable and reviewable
   and the source is neither.

   ⛔ THEREFORE: do NOT run tools/sync-demo.mjs or any build.py against this
   folder. A sync would silently revert everything below and every page would
   still render, which is exactly the failure mode that costs days here.
   Reconcile the source to THIS file first, or delete the source.
   ═══════════════════════════════════════════════════════════════════════════ */

/* ============================================================
   COPPERFIELD PLUMBING & AIR — "GAUGE CLUSTER"
   Instrument panel. Deep navy ground, panel-gray surfaces raised
   by a hairline (never a shadow). Two signal colors only:
   cyan  = a reading inside its range
   amber = a reading outside its range
   Copper is a spot accent and is never a signal.
   Mono carries every number and label. Sans carries prose.
   ⛔ System fonts only. This file must make zero network requests.
   ============================================================ */

:root{
  --ink:#0A1016;          /* instrument ground */
  --ink2:#070C11;         /* deeper, for the footer well */
  --panel:#111C25;        /* raised panel surface */
  --panel2:#16232E;       /* panel, one step lighter */
  --panel3:#1B2A36;
  --hair:#26343F;         /* the hairline that does all the raising */
  --hair2:#334755;
  --txt:#DCE6ED;
  --dim:#8FA6B4;
  --dimmer:#66808F;
  --cyan:#43D3E0;         /* IN RANGE */
  --cyan-d:#0E3A42;
  --amber:#F2A63A;        /* OUT OF RANGE */
  --amber-d:#42300F;
  --copper:#C9814F;       /* spot accent, never a signal */
  --copper-d:#3A2416;
  --mono:ui-monospace,SFMono-Regular,"SF Mono",Menlo,Consolas,"DejaVu Sans Mono","Liberation Mono",monospace;
  --sans:system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue",Arial,"Noto Sans",sans-serif;
  --rule:8px;             /* the baseline the whole panel is ruled to */
}

*,*::before,*::after{box-sizing:border-box}
/* .chatbox and #bookmsg are toggled with the hidden attribute; several
   rules below set display, which would otherwise beat the UA hidden rule. */
[hidden]{display:none!important}
html{-webkit-text-size-adjust:100%;overflow-x:hidden}
body{
  margin:0;
  background-color:var(--ink);
  /* the ruled panel: a hairline every 8px, plus a faint column grid */
  background-image:
    repeating-linear-gradient(to bottom, rgba(160,200,230,.030) 0 1px, transparent 1px var(--rule)),
    repeating-linear-gradient(to right, rgba(160,200,230,.016) 0 1px, transparent 1px 48px);
  color:var(--txt);
  font-family:var(--sans);
  font-size:16px;
  line-height:1.62;
  overflow-x:hidden;
}
img,svg{max-width:100%}
a{color:var(--cyan);text-underline-offset:3px}
a:hover{color:#7FE4EE}
h1,h2,h3,h4{line-height:1.18;margin:0 0 .5em;font-weight:650;letter-spacing:-.015em}
h1{font-size:clamp(28px,5.4vw,46px)}
h2{font-size:clamp(21px,3.4vw,30px)}
h3{font-size:clamp(17px,2.3vw,20px)}
p{margin:0 0 1.05em}
ul,ol{margin:0 0 1.1em;padding-left:1.15em}
li{margin:0 0 .45em}
hr{border:0;border-top:1px solid var(--hair);margin:32px 0}
:focus-visible{outline:2px solid var(--cyan);outline-offset:2px}
.sr{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}

.wrap{width:min(1140px,calc(100% - 32px));margin-inline:auto}
.narrow{width:min(760px,100%)}
section{padding:44px 0}
section.tight{padding:28px 0}

/* ---------- the mono voice ---------- */
.mono{font-family:var(--mono)}
.lab{
  font-family:var(--mono);font-size:11px;letter-spacing:.16em;text-transform:uppercase;
  color:var(--dimmer);margin:0 0 10px;display:block;
}
.lab--cu{color:var(--copper)}
.lab--cy{color:var(--cyan)}
.lab--am{color:var(--amber)}

/* ============================================================
   DEMONSTRATION STRIP
   ⛔ Required, verbatim class name, first thing on every page.
   These files are reachable directly, outside the viewer that
   frames them. Standing alone the site reads as a real Tampa
   contractor with a phone number on it. So it says what it is,
   before anything else, on every single page.
   ============================================================ */
.demostrip{
  display:flex;gap:10px;align-items:flex-start;
  background:linear-gradient(180deg,#20140C,#1A1109);
  border-bottom:1px solid var(--copper-d);
  color:#E8CDB4;
  font-family:var(--mono);font-size:12.5px;line-height:1.5;
  padding:9px max(16px,calc((100% - 1140px)/2));
}
.demostrip b{color:#FFD9B4;font-weight:700}
.demostrip a{color:var(--copper);font-weight:700;white-space:nowrap}
.demostrip__dot{
  flex:0 0 auto;width:8px;height:8px;margin-top:6px;border-radius:50%;
  background:var(--copper);box-shadow:0 0 0 3px rgba(201,129,79,.18);
}
@media(prefers-reduced-motion:no-preference){
  .demostrip__dot{animation:pulse 2.6s ease-in-out infinite}
  @keyframes pulse{0%,100%{opacity:1}50%{opacity:.42}}
}

/* ---------- header ---------- */
.top{background:var(--panel);border-bottom:1px solid var(--hair)}
.top__in{display:flex;align-items:center;gap:14px;flex-wrap:wrap;padding:12px 0}
.brand{display:flex;align-items:center;gap:11px;text-decoration:none;color:inherit;margin-right:auto}
.brand__mk{flex:0 0 auto;width:38px;height:38px;border:1px solid var(--hair2);background:var(--ink);
  display:grid;place-items:center;border-radius:3px}
.brand__nm{display:block;font-weight:700;font-size:15.5px;letter-spacing:-.01em;line-height:1.2}
.brand__sub{display:block;font-family:var(--mono);font-size:10.5px;letter-spacing:.13em;
  text-transform:uppercase;color:var(--dimmer);line-height:1.6}
.top__act{display:flex;align-items:center;gap:10px}
.tel{
  font-family:var(--mono);font-size:14px;font-weight:700;letter-spacing:.02em;
  color:var(--txt);text-decoration:none;border:1px solid var(--hair2);
  padding:8px 12px;border-radius:3px;background:var(--panel2);white-space:nowrap;
}
.tel:hover{border-color:var(--copper);color:#FFF}
.burger{display:none;background:var(--panel2);border:1px solid var(--hair2);border-radius:3px;
  width:40px;height:38px;cursor:pointer;padding:0;color:var(--txt)}
.burger i,.burger i::before,.burger i::after{display:block;height:1.5px;width:18px;background:currentColor;
  margin-inline:auto;position:relative}
.burger i::before{content:"";position:absolute;top:-6px}
.burger i::after{content:"";position:absolute;top:6px}

.nav{width:100%;border-top:1px solid var(--hair);margin-top:2px}
.nav ul{list-style:none;margin:0;padding:0;display:flex;flex-wrap:wrap}
.nav a{
  display:block;text-decoration:none;color:var(--dim);
  font-family:var(--mono);font-size:11.5px;letter-spacing:.13em;text-transform:uppercase;
  padding:11px 13px 10px;border-bottom:2px solid transparent;
}
.nav a:hover{color:var(--txt);background:var(--panel2)}
.nav a[aria-current="page"]{color:var(--cyan);border-bottom-color:var(--cyan)}
@media(max-width:860px){
  .burger{display:block}
  .nav{display:none}
  .nav.open{display:block}
  .nav ul{flex-direction:column}
  .nav a{border-bottom:1px solid var(--hair);border-left:2px solid transparent;padding:12px 4px}
  .nav a[aria-current="page"]{border-bottom-color:var(--hair);border-left-color:var(--cyan)}
}

/* ============================================================
   THE READING TILE — the whole visual idea of this site.
   A bordered rectangle. Small mono label. A big number. A unit.
   A state. Nothing else. It should read like an instrument at a
   glance, from across a room.
   ============================================================ */
.cluster{display:grid;gap:10px;grid-template-columns:repeat(auto-fill,minmax(148px,1fr))}
.tile{
  position:relative;background:var(--panel);border:1px solid var(--hair);
  padding:13px 12px 12px;min-width:0;border-radius:2px;
}
.tile::after{ /* corner tick, top-right — the panel's rivet */
  content:"";position:absolute;top:6px;right:6px;width:5px;height:5px;
  border-top:1px solid var(--hair2);border-right:1px solid var(--hair2);
}
.tile__lab{font-family:var(--mono);font-size:10px;letter-spacing:.15em;text-transform:uppercase;
  color:var(--dimmer);display:block;margin-bottom:6px}
.tile__num{
  font-family:var(--mono);font-weight:700;font-size:48px;line-height:.94;letter-spacing:-.035em;
  display:block;word-break:break-word;
}
.tile__num--sm{font-size:30px;letter-spacing:-.02em;padding-block:9px}
.tile__unit{font-family:var(--mono);font-size:13px;font-weight:400;letter-spacing:0;
  color:var(--dim);margin-left:4px}
.tile__spec{font-family:var(--mono);font-size:10.5px;letter-spacing:.05em;color:var(--dimmer);
  display:block;margin-top:9px}
.tile__st{
  font-family:var(--mono);font-size:9.5px;letter-spacing:.16em;text-transform:uppercase;
  display:inline-block;margin-top:9px;padding:2px 6px;border:1px solid;border-radius:2px;
}
.tile--in{border-color:rgba(67,211,224,.34)}
.tile--in .tile__num{color:var(--cyan)}
.tile--in .tile__st{color:var(--cyan);border-color:rgba(67,211,224,.4);background:var(--cyan-d)}
.tile--out{border-color:rgba(242,166,58,.38)}
.tile--out .tile__num{color:var(--amber)}
.tile--out .tile__st{color:var(--amber);border-color:rgba(242,166,58,.42);background:var(--amber-d)}
.tile--flat .tile__num{color:var(--txt)}
.tile--flat .tile__st{color:var(--dim);border-color:var(--hair2)}

/* ---------- hero ---------- */
.hero{padding:38px 0 8px}
.hero__grid{display:grid;gap:26px;grid-template-columns:1fr}
@media(min-width:1000px){.hero__grid{grid-template-columns:1.02fr .98fr;gap:30px;align-items:start}}
.hero h1{margin-top:8px}
.hero__lede{font-size:clamp(16px,2vw,18.5px);color:var(--dim);max-width:60ch}
.hero__lede b{color:var(--txt);font-weight:600}

/* ---------- the drawn instrument ---------- */
.figure{background:var(--panel);border:1px solid var(--hair);border-radius:2px;padding:14px}
.figure svg{display:block;width:100%;height:auto}
.figure__cap{font-family:var(--mono);font-size:10.5px;letter-spacing:.08em;color:var(--dimmer);
  margin:10px 0 0;border-top:1px solid var(--hair);padding-top:9px}

/* ============================================================
   THE SERVICE REPORT — the document the customer keeps.
   The best line on it is the one where nothing was sold.
   ============================================================ */
.report{background:var(--panel);border:1px solid var(--hair2);border-radius:2px;overflow:hidden}
.report__hd{
  display:flex;flex-wrap:wrap;gap:6px 18px;align-items:baseline;
  padding:12px 16px;background:var(--panel2);border-bottom:1px solid var(--hair2);
  font-family:var(--mono);font-size:11px;letter-spacing:.12em;text-transform:uppercase;color:var(--dimmer);
}
.report__no{color:var(--copper);font-weight:700;letter-spacing:.1em}
.report__meta{padding:12px 16px;border-bottom:1px solid var(--hair);font-family:var(--mono);
  font-size:12px;color:var(--dim);line-height:1.85}
.report__meta span{color:var(--txt)}
.rows{width:100%;border-collapse:collapse;font-size:14px}
.rows th{
  text-align:left;font-family:var(--mono);font-size:10px;letter-spacing:.15em;text-transform:uppercase;
  color:var(--dimmer);font-weight:400;padding:10px 16px;border-bottom:1px solid var(--hair);
}
.rows th:last-child,.rows td:last-child{text-align:right;white-space:nowrap}
.rows td{padding:12px 16px;border-bottom:1px solid var(--hair);vertical-align:top}
.rows td:last-child{font-family:var(--mono);font-weight:700;font-size:14px}
.rows tr:last-child td{border-bottom:0}
.rows .desc b{color:#FFF;font-weight:650}
.rows .desc small{display:block;color:var(--dim);font-size:12.5px;line-height:1.55;margin-top:3px}
.row--zero{background:linear-gradient(90deg,rgba(242,166,58,.10),rgba(242,166,58,.02))}
.row--zero td{border-top:1px solid rgba(242,166,58,.35);border-bottom:1px solid rgba(242,166,58,.35)}
.row--zero td:last-child{color:var(--amber)}
.row--zero .desc b{color:var(--amber);font-family:var(--mono);letter-spacing:.02em;font-size:13.5px}
.rows .tot td{background:var(--panel2);font-weight:700}
.rows .tot td:last-child{color:var(--txt);font-size:16px}

.declined{
  border:1px solid rgba(242,166,58,.4);border-left:3px solid var(--amber);
  background:rgba(242,166,58,.055);padding:18px 18px 4px;border-radius:2px;margin:0 0 22px;
}
.declined__k{
  font-family:var(--mono);font-size:12px;letter-spacing:.14em;text-transform:uppercase;
  color:var(--amber);display:block;margin-bottom:9px;
}
.declined p:last-child{margin-bottom:1.05em}
.declined strong{color:#FFD9A6}

.asleft{
  font-family:var(--mono);font-size:11.5px;line-height:1.9;color:var(--dim);
  padding:12px 16px;background:var(--ink);border-top:1px solid var(--hair);
}
.asleft b{color:var(--cyan);font-weight:700}

/* ---------- callouts ---------- */
.note{border:1px solid var(--hair);border-left:3px solid var(--copper);background:var(--panel);
  padding:16px 18px 4px;border-radius:2px;margin:0 0 22px}
.note--cy{border-left-color:var(--cyan)}
.note--am{border-left-color:var(--amber)}
.note h3{margin-bottom:.35em;font-size:16.5px}
.note p:last-child{margin-bottom:1.05em}

/* ============================================================
   THE SWITCHBOARD — services are small labeled rectangles,
   a system or a symptom each, not marketing cards.
   ============================================================ */
.board{display:grid;gap:8px;grid-template-columns:repeat(auto-fill,minmax(158px,1fr))}
.cell{
  display:block;text-decoration:none;color:inherit;background:var(--panel);
  border:1px solid var(--hair);border-radius:2px;padding:12px 12px 13px;min-width:0;
}
.cell:hover{border-color:var(--hair2);background:var(--panel2)}
.cell__k{font-family:var(--mono);font-size:9.5px;letter-spacing:.16em;color:var(--copper);
  display:block;margin-bottom:7px}
.cell__n{display:block;font-weight:600;font-size:14.5px;line-height:1.3;letter-spacing:-.01em;color:var(--txt)}
.cell__d{display:block;font-size:12.5px;line-height:1.45;color:var(--dim);margin-top:5px}
.cell--sym .cell__k{color:var(--cyan)}

/* ---------- generic blocks ---------- */
.cols{display:grid;gap:22px;grid-template-columns:1fr}
@media(min-width:820px){.cols--2{grid-template-columns:1fr 1fr}.cols--3{grid-template-columns:repeat(3,1fr)}}
.panel{background:var(--panel);border:1px solid var(--hair);border-radius:2px;padding:20px 20px 6px}
.panel h3{color:#FFF}
.panel--well{background:var(--ink2)}

.steps{list-style:none;margin:0;padding:0;counter-reset:s}
.steps>li{
  counter-increment:s;position:relative;padding:0 0 26px 58px;margin:0;
  border-left:1px solid var(--hair);
}
.steps>li:last-child{border-left-color:transparent;padding-bottom:0}
.steps>li::before{
  content:"0" counter(s);position:absolute;left:-19px;top:0;width:38px;height:38px;
  display:grid;place-items:center;background:var(--panel2);border:1px solid var(--hair2);
  font-family:var(--mono);font-size:13px;font-weight:700;color:var(--copper);border-radius:2px;
}
.steps h3{margin-bottom:.35em}

.deflist{margin:0}
.deflist dt{font-family:var(--mono);font-size:11px;letter-spacing:.14em;text-transform:uppercase;
  color:var(--cyan);margin:18px 0 5px}
.deflist dt:first-child{margin-top:0}
.deflist dd{margin:0 0 0 0;color:var(--txt)}

.qa{border-top:1px solid var(--hair);padding:18px 0 2px}
.qa h3{font-size:17px;color:#FFF}

.tablewrap{overflow-x:auto;-webkit-overflow-scrolling:touch}
.spec{width:100%;border-collapse:collapse;font-family:var(--mono);font-size:12.5px;min-width:440px}
.spec th{text-align:left;padding:9px 12px;border-bottom:1px solid var(--hair2);color:var(--dimmer);
  font-weight:400;font-size:10px;letter-spacing:.15em;text-transform:uppercase}
.spec td{padding:9px 12px;border-bottom:1px solid var(--hair);color:var(--txt)}
.spec td.n{color:var(--cyan);font-weight:700;white-space:nowrap}
.spec td.w{color:var(--amber);font-weight:700;white-space:nowrap}

.btn{
  display:inline-block;text-decoration:none;font-family:var(--mono);font-size:12px;
  letter-spacing:.14em;text-transform:uppercase;font-weight:700;
  padding:13px 20px;border-radius:2px;border:1px solid var(--copper);
  background:var(--copper);color:#170D06;
}
.btn:hover{background:#DB925D;border-color:#DB925D;color:#170D06}
.btn--ghost{background:transparent;color:var(--txt);border-color:var(--hair2)}
.btn--ghost:hover{background:var(--panel2);color:#FFF;border-color:var(--cyan)}
.btnrow{display:flex;flex-wrap:wrap;gap:10px;margin:22px 0 6px}

.cta{border:1px solid var(--hair2);background:var(--panel);border-radius:2px;padding:26px 22px 22px;
  text-align:left}
.cta h2{margin-bottom:.35em}

/* ---------- form ---------- */
.form{display:grid;gap:14px;grid-template-columns:1fr}
@media(min-width:700px){.form .half{grid-column:span 1}.form{grid-template-columns:1fr 1fr}
  .form .full{grid-column:1 / -1}}
.field label{display:block;font-family:var(--mono);font-size:10.5px;letter-spacing:.14em;
  text-transform:uppercase;color:var(--dimmer);margin-bottom:6px}
.field input,.field select,.field textarea{
  width:100%;background:var(--ink);border:1px solid var(--hair2);color:var(--txt);
  font-family:var(--sans);font-size:15px;padding:11px 12px;border-radius:2px;
}
.field textarea{min-height:120px;resize:vertical}
.field input:focus,.field select:focus,.field textarea:focus{border-color:var(--cyan);outline:none}

/* ---------- reviews empty state ---------- */
.empty{
  border:1px dashed var(--hair2);background:var(--panel);border-radius:2px;
  padding:38px 22px;text-align:center;
}
.empty .lab{margin-bottom:14px}
.empty p{max-width:56ch;margin-inline:auto;color:var(--dim)}

/* ---------- footer ---------- */
.foot{background:var(--ink2);border-top:1px solid var(--hair);margin-top:40px;padding:36px 0 30px}
.foot__grid{display:grid;gap:26px;grid-template-columns:1fr}
@media(min-width:760px){.foot__grid{grid-template-columns:1.3fr 1fr 1fr}}
.foot h4{font-family:var(--mono);font-size:10.5px;letter-spacing:.16em;text-transform:uppercase;
  color:var(--dimmer);margin:0 0 12px;font-weight:400}
.foot ul{list-style:none;margin:0;padding:0}
.foot li{margin:0 0 7px}
.foot a{color:var(--dim);text-decoration:none;font-size:14px}
.foot a:hover{color:var(--cyan)}
.foot__addr{font-family:var(--mono);font-size:12.5px;line-height:1.85;color:var(--dim)}
.foot__addr b{color:var(--txt)}
.foot__fine{border-top:1px solid var(--hair);margin-top:28px;padding-top:18px;
  font-family:var(--mono);font-size:11px;line-height:1.75;color:var(--dimmer)}
.foot__fine a{font-size:11px;color:var(--copper)}

/* ============================================================
   CHAT LAUNCHER — pinned bottom-LEFT.
   ⛔ The page is displayed inside an iframe on another domain,
   whose own launcher sits bottom-right. Left, always.
   ============================================================ */
.launch{
  position:fixed;left:16px;bottom:16px;z-index:60;
  display:flex;align-items:center;gap:9px;cursor:pointer;
  background:var(--panel2);border:1px solid var(--hair2);border-radius:3px;
  color:var(--txt);font-family:var(--mono);font-size:11.5px;letter-spacing:.12em;
  text-transform:uppercase;font-weight:700;padding:11px 14px;
}
.launch:hover{border-color:var(--cyan);color:#FFF}
.launch__dot{width:7px;height:7px;border-radius:50%;background:var(--cyan);flex:0 0 auto}
.chatbox{
  position:fixed;left:16px;bottom:16px;z-index:61;
  width:min(344px,calc(100vw - 32px));
  max-height:min(520px,calc(100vh - 32px));
  display:flex;flex-direction:column;
  background:var(--panel);border:1px solid var(--hair2);border-radius:3px;
}
.chatbox__hd{display:flex;align-items:center;gap:9px;padding:11px 12px;background:var(--panel2);
  border-bottom:1px solid var(--hair2)}
.chatbox__t{font-family:var(--mono);font-size:11px;letter-spacing:.13em;text-transform:uppercase;
  color:var(--dim);margin-right:auto}
.chatbox__x{background:none;border:1px solid var(--hair2);color:var(--dim);cursor:pointer;
  width:26px;height:26px;border-radius:2px;font-size:15px;line-height:1;padding:0}
.chatbox__x:hover{color:#FFF;border-color:var(--cyan)}
.log{flex:1 1 auto;overflow-y:auto;padding:12px;display:flex;flex-direction:column;gap:9px;min-height:150px}
.msg{max-width:88%;padding:9px 11px;border-radius:3px;font-size:13.5px;line-height:1.5}
.msg--bot{background:var(--panel2);border:1px solid var(--hair);align-self:flex-start;color:var(--txt)}
.msg--me{background:var(--cyan-d);border:1px solid rgba(67,211,224,.35);align-self:flex-end;color:#CFF6FA}
.opts{display:flex;flex-wrap:wrap;gap:7px;padding:0 12px 12px}
.chip{
  background:var(--ink);border:1px solid var(--hair2);color:var(--txt);cursor:pointer;
  font-family:var(--sans);font-size:12.5px;padding:8px 11px;border-radius:2px;text-align:left;
}
.chip:hover{border-color:var(--cyan);color:#FFF}
.chatbox__fine{font-family:var(--mono);font-size:9.5px;letter-spacing:.08em;color:var(--dimmer);
  padding:8px 12px;border-top:1px solid var(--hair);line-height:1.5}

@media(max-width:420px){
  .tile__num{font-size:40px}
  .cluster{grid-template-columns:repeat(auto-fill,minmax(140px,1fr))}
}

/* ============================================================
   ENRICHMENT PASS — MATERIAL, LIGHT AND MOTION
   ------------------------------------------------------------
   Everything below deepens the gauge cluster. It does not
   change the idea: instrument navy, panel-gray surfaces raised
   by a hairline, mono on every number, cyan = in range,
   amber = out of range, copper as a spot and structural accent.
   ⛔ Still zero network requests. System fonts only.
   ⛔ Nothing here hides content and reveals it with script.
      Every rule animates TO the state the page already has.
   ============================================================ */

:root{
  --lip:rgba(196,228,248,.055);     /* the hairline highlight on a top edge */
  --sill:rgba(0,0,0,.46);           /* the darker line at the bottom edge */
  --raise:inset 0 1px 0 var(--lip), inset 0 -1px 0 var(--sill);
  --ease:cubic-bezier(.2,.7,.3,1);
  --t:180ms var(--ease);
}

/* ---------- the cluster sits in a pool of light ----------
   The navy deepens toward black at the page edges so the panel
   reads as a lit object rather than a flat fill. Fixed, so it
   never adds a scrollable pixel. */
body::before{
  content:"";position:fixed;inset:0;z-index:0;pointer-events:none;
  background:
    radial-gradient(120% 78% at 50% 12%, rgba(32,74,98,.30) 0%, rgba(10,16,22,0) 58%),
    radial-gradient(90% 60% at 50% 104%, rgba(0,0,0,.62) 0%, rgba(0,0,0,0) 62%),
    linear-gradient(90deg, rgba(0,0,0,.55) 0%, rgba(0,0,0,0) 16%, rgba(0,0,0,0) 84%, rgba(0,0,0,.55) 100%);
}
body>.demostrip,body>.top,body>section,body>.foot,body>footer{position:relative;z-index:1}

/* ---------- type: larger, tighter, more air ---------- */
section{padding:62px 0}
section.tight{padding:34px 0}
h1{font-size:clamp(31px,5.9vw,53px);letter-spacing:-.026em}
h2{font-size:clamp(22px,3.6vw,33px);letter-spacing:-.021em}
h3{font-size:clamp(17px,2.3vw,20.5px);letter-spacing:-.014em}
.hero__lede{font-size:clamp(16.5px,2vw,19.5px);line-height:1.6}

/* a copper tick leads every section label — one class, one hue,
   currentColor, so the cyan and amber variants carry their own. */
.lab{position:relative;padding-left:17px}
.lab::before{
  content:"";position:absolute;left:0;top:.63em;width:11px;height:1px;
  background:currentColor;opacity:.9;
}
.empty .lab{padding-left:0}
.empty .lab::before{display:none}

/* ============================================================
   MATERIAL — light falls across every panel surface.
   A gradient down the face, a hairline highlight on the top
   edge, a darker line at the bottom. No soft drop shadows:
   this panel is raised by its edges, the way a real one is.
   ============================================================ */
.tile,.cell,.panel,.figure,.report,.cta,.note,.empty,.shot{
  background-image:linear-gradient(176deg,rgba(206,234,252,.052) 0%,rgba(206,234,252,.012) 34%,rgba(0,0,0,.16) 100%);
  box-shadow:var(--raise);
}
.panel--well{
  background-image:linear-gradient(176deg,rgba(206,234,252,.036) 0%,rgba(0,0,0,.10) 40%,rgba(0,0,0,.30) 100%);
}
.report{box-shadow:var(--raise),0 1px 0 rgba(0,0,0,.4)}
.report__hd{
  background-image:linear-gradient(180deg,rgba(214,238,255,.06),rgba(0,0,0,.12));
  border-top:1px solid var(--copper-d);
  box-shadow:inset 0 1px 0 rgba(226,246,255,.05);
}

/* ---------- the lit display: a reading bleeds into its bezel ---------- */
.tile{
  transition:border-color var(--t),transform var(--t),box-shadow var(--t);
}
.tile::before{
  content:"";position:absolute;inset:0;border-radius:2px;pointer-events:none;
  background:radial-gradient(128% 86% at 16% 58%, var(--tglow,transparent) 0%, transparent 64%);
}
.tile>*{position:relative}
.tile--in{--tglow:rgba(67,211,224,.115)}
.tile--out{--tglow:rgba(242,166,58,.115)}
.tile--flat{--tglow:rgba(196,228,248,.05)}
.tile__num{font-size:clamp(40px,5.6vw,50px)}
.tile--in .tile__num{text-shadow:0 0 22px rgba(67,211,224,.34)}
.tile--out .tile__num{text-shadow:0 0 22px rgba(242,166,58,.30)}
.tile--in .tile__st,.tile--out .tile__st{box-shadow:inset 0 0 12px rgba(0,0,0,.35)}
.tile:hover{
  border-color:var(--hair2);transform:translateY(-2px);
  box-shadow:var(--raise),0 6px 18px rgba(0,0,0,.36);
}
.tile--in:hover{border-color:rgba(67,211,224,.62)}
.tile--out:hover{border-color:rgba(242,166,58,.66)}
.tile::after{transition:border-color var(--t)}
.tile:hover::after{border-color:var(--copper)}

/* ---------- the drawn instrument ---------- */
.figure{margin:0;transition:border-color var(--t)}
.ndl--lo{filter:drop-shadow(0 0 5px rgba(67,211,224,.55))}
.ndl--hi{filter:drop-shadow(0 0 5px rgba(242,166,58,.5))}
.figure:hover{border-color:var(--hair2)}
.figure--dia{padding:16px 14px 14px}
.dia{display:block;width:100%;height:auto}
.figure__cap{letter-spacing:.06em;line-height:1.65}

/* ============================================================
   THE SWITCHBOARD CELL — now carries a drawn icon for the
   thing it actually is. Copper on a system, cyan on a symptom,
   inherited through currentColor so one class carries one hue.
   ============================================================ */
.cell{
  transition:border-color var(--t),background-color var(--t),transform var(--t),box-shadow var(--t);
  padding:14px 13px 15px;
}
.cell__ic{
  display:grid;place-items:center;width:38px;height:38px;margin:0 0 12px;padding:5px;
  border:1px solid var(--hair2);border-radius:3px;background:var(--ink);color:var(--copper);
  background-image:linear-gradient(176deg,rgba(206,234,252,.05),rgba(0,0,0,.2));
  box-shadow:inset 0 1px 0 rgba(196,228,248,.05);
  transition:color var(--t),border-color var(--t),transform var(--t),box-shadow var(--t);
}
.cell__ic svg{display:block;width:100%;height:100%}
.cell--sym .cell__ic{color:var(--cyan)}
.cell:hover{
  border-color:var(--hair2);background-color:var(--panel2);transform:translateY(-2px);
  box-shadow:var(--raise),0 7px 20px rgba(0,0,0,.4);
}
.cell:hover .cell__ic{transform:translateY(-1px);border-color:var(--copper);
  box-shadow:inset 0 1px 0 rgba(196,228,248,.06),0 0 14px rgba(201,129,79,.22)}
.cell--sym:hover .cell__ic{border-color:var(--cyan);
  box-shadow:inset 0 1px 0 rgba(196,228,248,.06),0 0 14px rgba(67,211,224,.22)}
.cell:hover .cell__k{color:#E4A473}
.cell--sym:hover .cell__k{color:#8FE9F2}
.cell__k,.cell__n{transition:color var(--t)}
.cell:hover .cell__n{color:#FFF}

/* ============================================================
   DESIGNED IMAGE SLOTS
   A photograph belongs in each of these and none has been taken,
   because this company is invented. So the slot is drawn: the
   right aspect ratio, instrument line art in the panel palette,
   and a caption naming the photograph that goes here. It must
   never be mistaken for a photograph, and never read as broken.
   Class names are stable — a real photo drops straight in.
   ============================================================ */
.shot{
  position:relative;border:1px solid var(--hair2);border-radius:2px;overflow:hidden;
  background-color:var(--panel);margin:0;
}
.shot__frame{
  display:block;position:relative;width:100%;
  background:linear-gradient(163deg,#16242F 0%,#0E1A23 46%,#080D13 100%);
  border-bottom:1px solid var(--hair);
}
.shot__frame svg{display:block;width:100%;height:auto}
.shot__badge{
  position:absolute;top:9px;left:9px;z-index:2;
  font-family:var(--mono);font-size:8.5px;letter-spacing:.2em;text-transform:uppercase;
  color:var(--copper);background:rgba(8,13,19,.86);border:1px solid var(--copper-d);
  padding:3px 7px;border-radius:2px;
}
.shot__cap{
  font-family:var(--mono);font-size:10.5px;letter-spacing:.06em;line-height:1.65;
  color:var(--dimmer);margin:0;padding:10px 13px 11px;
}
.shot__cap b{color:var(--dim);font-weight:400}

/* ---------- notes, panels, callouts ---------- */
.note,.panel,.cta,.empty,.qa,.shot{transition:border-color var(--t),box-shadow var(--t)}
.note:hover,.panel:hover,.shot:hover{border-color:var(--hair2)}
.note{border-left-width:3px}
.note--cy{box-shadow:var(--raise),inset 3px 0 14px -6px rgba(67,211,224,.5)}
.note--am{box-shadow:var(--raise),inset 3px 0 14px -6px rgba(242,166,58,.5)}
.note:not(.note--cy):not(.note--am){box-shadow:var(--raise),inset 3px 0 14px -6px rgba(201,129,79,.5)}

/* the declined line: the best line on the report, lit from its own edge */
.declined{
  background-image:linear-gradient(174deg,rgba(242,166,58,.085) 0%,rgba(242,166,58,.02) 60%,rgba(0,0,0,.14) 100%);
  box-shadow:inset 3px 0 22px -8px rgba(242,166,58,.75),inset 0 1px 0 rgba(255,214,150,.09);
}
.row--zero td:first-child{box-shadow:inset 3px 0 0 rgba(242,166,58,.65)}

/* ---------- the report reads like a sheet lying on the panel ---------- */
.rows tr{transition:background-color var(--t)}
.rows tbody tr:not(.tot):not(.row--zero):hover{background:rgba(206,234,252,.028)}
.row--zero{background:linear-gradient(90deg,rgba(242,166,58,.13),rgba(242,166,58,.03))}
.asleft{background-image:linear-gradient(180deg,rgba(0,0,0,.3),rgba(206,234,252,.018))}
.rows .tot td{background-image:linear-gradient(180deg,rgba(214,238,255,.05),rgba(0,0,0,.16))}

/* ---------- switches, links and buttons ---------- */
a{transition:color var(--t)}
.btn{
  transition:background-color var(--t),border-color var(--t),color var(--t),
             transform var(--t),box-shadow var(--t);
  background-image:linear-gradient(180deg,rgba(255,236,214,.28),rgba(0,0,0,.14));
  box-shadow:inset 0 1px 0 rgba(255,240,220,.35),0 1px 0 rgba(0,0,0,.4);
}
.btn:hover{transform:translateY(-2px);box-shadow:inset 0 1px 0 rgba(255,240,220,.4),0 8px 20px rgba(201,129,79,.26)}
.btn:active{transform:translateY(0)}
.btn--ghost{background-image:linear-gradient(180deg,rgba(206,234,252,.05),rgba(0,0,0,.14));box-shadow:var(--raise)}
.btn--ghost:hover{box-shadow:var(--raise),0 8px 20px rgba(0,0,0,.42)}
.tel{transition:border-color var(--t),color var(--t),box-shadow var(--t);box-shadow:var(--raise)}
.tel:hover{box-shadow:var(--raise),0 0 0 1px rgba(201,129,79,.25)}
.nav a{transition:color var(--t),background-color var(--t),border-color var(--t)}
.foot a,.foot li a{transition:color var(--t),padding-left var(--t)}
.foot li a:hover{padding-left:4px}
.burger,.chip,.chatbox__x,.launch{transition:border-color var(--t),color var(--t),background-color var(--t),transform var(--t)}
.chip:hover{transform:translateY(-1px)}
.launch{box-shadow:var(--raise),0 6px 18px rgba(0,0,0,.45)}
.launch:hover{transform:translateY(-2px)}
.field input,.field select,.field textarea{transition:border-color var(--t),box-shadow var(--t)}
.field input:focus,.field select:focus,.field textarea:focus{box-shadow:0 0 0 3px rgba(67,211,224,.16)}
.qa:hover h3{color:var(--cyan)}
.spec tbody tr{transition:background-color var(--t)}
.spec tbody tr:hover{background:rgba(206,234,252,.03)}
.steps>li::before{box-shadow:var(--raise)}

/* copper does structural work: the header rail, the footer rail,
   and the bracket corners on the closing panel. */
.top{
  border-bottom-color:var(--hair2);
  box-shadow:0 1px 0 rgba(201,129,79,.22),0 6px 22px rgba(0,0,0,.4);
  background-image:linear-gradient(180deg,rgba(206,234,252,.045),rgba(0,0,0,.16));
}
.foot{border-top:1px solid var(--copper-d);box-shadow:inset 0 1px 0 rgba(201,129,79,.16)}
.cta{position:relative;overflow:hidden}
.cta::before,.cta::after{
  content:"";position:absolute;width:22px;height:22px;pointer-events:none;
  border-color:var(--copper);opacity:.7;
}
.cta::before{top:9px;left:9px;border-top:1px solid;border-left:1px solid}
.cta::after{bottom:9px;right:9px;border-bottom:1px solid;border-right:1px solid}

/* ============================================================
   MOTION
   Instruments move — a cluster sweeps at start-up, and an
   out-of-range lamp breathes. Everything below is an
   ENHANCEMENT of a page that is already complete and correct
   with scripting and animation both switched off:
     · the needles are drawn AT their printed psig values and
       animate FROM zero TO that same value;
     · .rv is unstyled until .is-in is added, so nothing is
       hidden waiting for a script that may never run.
   ============================================================ */
@media(prefers-reduced-motion:no-preference){

  /* start-up sweep. Each needle is already drawn on its reading;
     these keyframes wind it back to 0 psig and drive it home,
     overshooting slightly and settling, the way a real one does. */
  @keyframes sweepLo{
      0%{transform:rotate(-113.4deg);animation-timing-function:cubic-bezier(.22,.62,.24,1)}
     58%{transform:rotate(7.5deg);animation-timing-function:ease-in-out}
     76%{transform:rotate(-3.2deg);animation-timing-function:ease-in-out}
     90%{transform:rotate(1.3deg);animation-timing-function:ease-in-out}
    100%{transform:rotate(0)}
  }
  @keyframes sweepHi{
      0%{transform:rotate(-102.9deg);animation-timing-function:cubic-bezier(.22,.62,.24,1)}
     58%{transform:rotate(7deg);animation-timing-function:ease-in-out}
     76%{transform:rotate(-3deg);animation-timing-function:ease-in-out}
     90%{transform:rotate(1.2deg);animation-timing-function:ease-in-out}
    100%{transform:rotate(0)}
  }
  .ndl{transform-box:view-box}
  .ndl--lo{transform-origin:152px 118px;animation:sweepLo 1.9s .28s both}
  .ndl--hi{transform-origin:488px 118px;animation:sweepHi 1.9s .42s both}

  /* an out-of-range lamp breathes. Slow. Never a flash. */
  @keyframes ember{
    0%,100%{text-shadow:0 0 20px rgba(242,166,58,.24)}
    50%    {text-shadow:0 0 32px rgba(242,166,58,.56)}
  }
  .tile--out .tile__num{animation:ember 5.4s ease-in-out infinite}
  @keyframes emberEdge{
    0%,100%{box-shadow:inset 3px 0 22px -8px rgba(242,166,58,.6),inset 0 1px 0 rgba(255,214,150,.09)}
    50%    {box-shadow:inset 3px 0 26px -8px rgba(242,166,58,.95),inset 0 1px 0 rgba(255,214,150,.12)}
  }
  .declined{animation:emberEdge 6.2s ease-in-out infinite}

  /* section reveal. .rv on its own does nothing at all. */
  @keyframes rise{from{opacity:0;transform:translateY(18px)}to{opacity:1;transform:none}}
  .rv.is-in{animation:rise .58s var(--ease) both}
  @keyframes tilein{from{opacity:0;transform:translateY(12px) scale(.985)}to{opacity:1;transform:none}}
  .rvs.is-in>*{animation:tilein .5s var(--ease) both}
  .rvs.is-in>*:nth-child(1){animation-delay:.00s}
  .rvs.is-in>*:nth-child(2){animation-delay:.045s}
  .rvs.is-in>*:nth-child(3){animation-delay:.09s}
  .rvs.is-in>*:nth-child(4){animation-delay:.135s}
  .rvs.is-in>*:nth-child(5){animation-delay:.18s}
  .rvs.is-in>*:nth-child(6){animation-delay:.225s}
  .rvs.is-in>*:nth-child(7){animation-delay:.27s}
  .rvs.is-in>*:nth-child(8){animation-delay:.315s}
  .rvs.is-in>*:nth-child(n+9){animation-delay:.36s}
}

/* ---------- narrow screens: the cluster stays a cluster ---------- */
@media(max-width:420px){
  .tile__num{font-size:clamp(34px,10.2vw,40px)}
  .cell__ic{width:34px;height:34px;margin-bottom:10px;padding:4px}
  section{padding:46px 0}
  .cta::before,.cta::after{width:16px;height:16px}
}
@media(max-width:360px){
  .cluster{grid-template-columns:1fr}
}


/* ═══ 🔤 NAV TYPE PASS 9 Sep 2026 — size and tracking only.
   ⛔ Do not add colour, family, case or weight here: those are what keep these
   twelve sites from converging, and converging is the thing that was fixed
   once already. Measured before: 11–12.5px with tracking wide enough that
   the label read as separate letters rather than a word. */
nav[aria-label="Main"] a,
nav[aria-label="Primary"] a {
  font-size: 13px;
  letter-spacing: .1em;
}

/* ══════════════════════════════════════════════════════════════════════════
   ⭐ THE PROFESSIONAL PASS — plumbing & air, 11 Sep 2026.
   The five gaps the roofing demo had, answered in this site's own materials.
   ⚠️ THE ACCENT IS COPPER, AND IT IS NOT A SIGNAL. Cyan means IN RANGE and
   amber means OUT OF RANGE on this site; the brand colour must never be read
   as a third reading. So copper stays on brand furniture — the mark, one
   headline phrase, the offer strip, the primary button — and never on a
   number, a needle or a status pill.
   ⚠️ TWO COPPERS, ON PURPOSE. #C1682F is the FILL: it carries near-black type
   at ~4.8:1. As TEXT on the instrument ground it is only ~4.3:1, under the
   small-text floor, so accent type uses #D98A55 — same hue, ~6.3:1 on panel.
   ⛔ No photograph. The manifold is a drawing and stays one.
   ══════════════════════════════════════════════════════════════════════════ */
:root{
  --accent:#C1682F;      /* copper — FILL only */
  --accent-hi:#D97B3C;   /* copper, pressed/hover */
  --accent-tx:#D98A55;   /* copper as TYPE on the dark ground */
  --accent-dk:#8A4720;   /* the border under a copper fill */
}

/* ── the mark ─────────────────────────────────────────────────────────── */
/* The gauge was drawn with a hard-coded copper stroke, so it could not follow
   the brand anywhere. Re-inked in currentColor: bezel, scale arc, ticks,
   needle off the vertical, hub. */
.brand__ico{ display:block; width:24px; height:24px; color:var(--accent-tx);
  transition:transform var(--t), color var(--t); }
.brand__mk{ transition:border-color var(--t); }
.brand:hover .brand__ico{ transform:rotate(-8deg); color:var(--accent); }
.brand:hover .brand__mk{ border-color:var(--accent-dk); }

/* ── the headline carries the colour ──────────────────────────────────── */
h1 .hl{ font-style:normal; color:var(--accent-tx); }

/* ── the offer strip ──────────────────────────────────────────────────── */
/* ⭐ What the customer actually gets, in the site's own sentence. ⛔ Never a
   price, a rating or a count — this demo has published none of those. */
.offerbar{
  border-bottom:1px solid var(--hair);
  background-image:linear-gradient(180deg,var(--panel2),var(--panel));
  box-shadow:inset 0 1px 0 var(--lip);
}
.offerbar__in{
  display:flex;align-items:center;gap:14px;flex-wrap:wrap;
  padding-top:10px;padding-bottom:10px;
}
.offerbar__tag{
  font-family:var(--mono);font-size:10.5px;text-transform:uppercase;
  letter-spacing:.14em;color:var(--accent-tx);
  border:1px solid color-mix(in srgb, var(--accent) 45%, transparent);
  border-radius:2px;padding:3px 9px;flex:0 0 auto;
}
.offerbar__msg{
  margin:0;font-family:var(--sans);font-size:13.5px;line-height:1.45;
  color:var(--dim);flex:1 1 340px;min-width:0;
}
.offerbar__msg b{ color:var(--txt);font-weight:650; }
.offerbar__go{
  flex:0 0 auto;font-family:var(--mono);font-size:11.5px;text-transform:uppercase;
  letter-spacing:.09em;color:var(--txt);text-decoration:none;white-space:nowrap;
  border-bottom:1px solid color-mix(in srgb, var(--accent) 60%, transparent);
  padding-bottom:2px;transition:color var(--t),border-bottom-color var(--t);
}
.offerbar__go:hover{ color:var(--accent-tx);border-bottom-color:var(--accent); }
@media (max-width:640px){
  .offerbar__go{ display:none; }     /* the hero button is just below it */
  .offerbar__msg{ font-size:12.5px; }
}

/* ── the primary button is the accent ─────────────────────────────────── */
/* ⚠️ background-COLOR, not the `background` shorthand: the raised gradient is
   set ~290 lines above and the shorthand would silently erase it, flattening
   every button on the site. */
.btn{
  background-color:var(--accent);border-color:var(--accent-dk);color:#150A03;
  background-image:linear-gradient(180deg,rgba(255,236,214,.30),rgba(0,0,0,.16));
}
.btn:hover{
  background-color:var(--accent-hi);border-color:var(--accent-hi);color:#150A03;
  box-shadow:inset 0 1px 0 rgba(255,240,220,.4),0 8px 20px rgba(193,104,47,.30);
}

/* ── depth on the drawn instrument ────────────────────────────────────── */
.hero .figure{
  box-shadow:var(--raise), 0 34px 52px rgba(0,0,0,.55), 0 3px 10px rgba(0,0,0,.4);
}
.hero .figure svg{ filter:contrast(1.06) saturate(1.05); }

@media (prefers-reduced-motion:reduce){
  .brand:hover .brand__ico{ transform:none; }
}

/* 🔴 AND THE GHOST IS RESTATED AFTER IT. `.btn--ghost` is declared twice above
   — once at ~320 and again at ~610 — and this file is unlayered, so the `.btn`
   rule above (same specificity, later in the file) takes BOTH its colour and
   its gradient and the two buttons render as one. Two primaries is no primary.
   ⛔ Any future `.btn` rule appended below this point must restate it again. */
.btn--ghost{
  background-color:transparent;color:var(--txt);border-color:var(--hair2);
  background-image:linear-gradient(180deg,rgba(206,234,252,.05),rgba(0,0,0,.14));
  box-shadow:var(--raise);
}
.btn--ghost:hover{
  background-color:var(--panel2);color:#FFF;border-color:var(--cyan);
  box-shadow:var(--raise),0 8px 20px rgba(0,0,0,.42);
}

/* ── 🔴 RAGGED COLUMNS — 11 Sep 2026 ──────────────────────────────────────
   Owner: "columns dont line up", "no blank spaces".
   Measured on the live page: three side-by-side grids where one child ran far
   longer than the other, and `align-items:start` stranded the short one at the
   top with dead space under it. The worst was the service report beside the
   refrigerant note — 1,517px against 419px, leaving 1,098px of nothing.

   ⭐ THE SHORT COLUMN TRAVELS INSTEAD OF BEING STRETCHED. Stretching an empty
   card to 1,517px just makes a taller empty card. Sticky keeps the argument
   beside the document it is arguing about, which is what the section is for,
   and the dead space disappears because the eye is never asked to look at it.
   ⚠️ `align-self:start` is required with it — a stretched item has no free
   space to move within, so sticky silently does nothing. */
@media (min-width: 820px) {
  .cols--2 > * { align-self: start; }
  .cols--2 > *:last-child { position: sticky; top: 24px; }
}
/* ⛔ Sticky is motion-adjacent for anyone who finds movement uncomfortable, and
   it has no purpose at one column wide. */
@media (prefers-reduced-motion: reduce) {
  .cols--2 > *:last-child { position: static; }
}

/* ── ❄️ THE DAY, AS THE CUSTOMER HAS IT — 11 Sep 2026 ─────────────────────
   ⭐ The old headline led with the report, which is OUR fact. The thing the
   customer buys is the night they get back; the eleven readings are only how
   they know they got it. So the headline names the trade and the town and
   gives the accent to the night, and this block is job SR-4417 told from the
   householder's side, including the declined line.
   ⛔ The timestamps use --accent-tx (copper AS TYPE). --accent is a FILL only
   on this ground; do not swap them.
   ⛔ No motion of its own — the section carries .rv, which is the page's own
   reveal and is already gated on prefers-reduced-motion. */
.day{list-style:none;margin:22px 0 0;padding:0;display:grid;gap:0}
.day__i{
  display:grid;grid-template-columns:104px 1fr;gap:0 20px;
  padding:16px 0;border-top:1px solid var(--hair);align-items:start;
}
.day__i:first-child{border-top:0}
.day__t{
  font-family:var(--mono);font-size:11.5px;letter-spacing:.12em;text-transform:uppercase;
  color:var(--accent-tx);padding-top:3px;white-space:nowrap;font-variant-numeric:tabular-nums;
}
.day__i h3{margin:0 0 5px;font-size:clamp(16.5px,2.2vw,19px);line-height:1.24;color:var(--txt);max-width:62ch}
.day__i p{margin:0;font-size:14.5px;line-height:1.62;color:var(--dim);max-width:62ch}
/* ⭐ one beat is marked, and it is the one where the headline comes true. */
.day__i--live .day__t::after{
  content:"";display:inline-block;width:6px;height:6px;border-radius:50%;
  background:var(--accent-tx);margin-left:7px;vertical-align:middle;
}
/* 🔴 THE THREE-CHILD GRID BUG. `.day__i` holds THREE children — the timestamp,
   the h3 and the p — in a TWO-column grid, so auto-placement puts the
   paragraph back in column one, at the width of a timestamp. At 1280px that
   renders the beat's paragraph in a 100-odd-pixel gutter and makes the row
   four times as tall as it should be. Both text children are pinned to column
   two. ⛔ Reset this inside the single-column breakpoint, or the `2` invents an
   implicit second column on a phone. */
.day__i > h3,
.day__i > p{grid-column:2}
.day__foot{
  margin:22px 0 0;padding-top:16px;border-top:1px solid var(--hair);
  font-size:14.5px;line-height:1.65;color:var(--dim);max-width:66ch;
}
.day__foot b{color:var(--txt);font-weight:650}
@media (max-width:560px){
  .day__i{grid-template-columns:1fr;gap:4px}
  .day__t{padding-top:0}
  .day__i > h3,.day__i > p{grid-column:1}
}


/* ── 📷 PHOTOGRAPHS ───────────────────────────────────────────────────────
   🔴 11 Sep 2026. Owner: "need photos!!" and "no stick diagrams". This demo
   shipped with none, and a page of line drawings reads as a prototype rather
   than as a business's site.

   ⭐ PORTABLE ON PURPOSE. Thirteen demos, thirteen different token names —
   --soil/--panel/--hair here, --paper/--rule/--gr there, light and dark both.
   A component written against one demo's variables is a component that has to
   be rewritten twelve times and will be wrong in four of them. So this uses
   `currentColor` and plain rgba, and inherits the page's own ink.

   ⛔ Every CC BY / CC BY-SA frame carries its credit IN the frame. Attribution
   is a licence term, not a courtesy, and "we'll add the credits later" is
   exactly how a licence gets breached. */
.photo{position:relative;margin:0;line-height:0;border-radius:4px;overflow:hidden;
  border:1px solid rgba(128,128,128,.28)}
.photo img{width:100%;display:block;object-fit:cover;filter:saturate(1.03) contrast(1.02)}
.photo--hero img{height:clamp(260px,34vw,430px)}
.photo--band img{height:clamp(190px,26vw,320px)}
.photo--tall img{height:clamp(240px,30vw,380px)}
/* ⚠️ the badge carries its OWN scrim rather than the frame carrying a gradient.
   A gradient tuned for a dark ground turns a light photo muddy along the bottom,
   and half these demos are light. */
.photo__cr{position:absolute;right:8px;bottom:8px;z-index:2;
  font-size:9.5px;letter-spacing:.04em;line-height:1.45;font-weight:500;
  color:rgba(255,255,255,.88);background:rgba(0,0,0,.52);padding:3px 7px;border-radius:2px;
  text-shadow:0 1px 2px rgba(0,0,0,.5)}
.photo__cr a{color:inherit;text-decoration:underline;text-underline-offset:2px}
.photo__cap{line-height:1.55;font-size:12.5px;opacity:.72;padding-top:9px}

/* ── 🚪 THE WAY OUT STAYS ON SCREEN ───────────────────────────────────────
   🔴 11 Sep 2026, owner: "need to be able and x out of all the demo sites if
   you view on mobile dont let people get stuck somewher with out easy exit."

   This banner is the only route from a demo back to us, and it sat at the top
   of the document as a static block. On a phone, two swipes down a service page
   and it is gone — a visitor who arrived on a shared link has no way back and
   no reason to think one exists. ⚠️ The link was always there and was always
   unreachable, which is the same shape as the embed's close button being parked
   off-screen above the iframe.

   ⭐ Sticky on phones only. On a desktop the banner is in view at the top of a
   page people can see all of, and pinning it would just spend vertical room. */
@media (max-width: 640px) {
  .demostrip {
    position: sticky;
    top: 0;
    z-index: 90;
  }
  /* ⚠️ AND THE LINK HAS TO BE HITTABLE, NOT MERELY PRESENT. It is inline text
     inside a sentence, so on a 375px screen it wrapped into two fragments 15px
     tall — measured, both genuinely tappable, and both far under the 44px a
     thumb needs. ⭐ Make it a control: one line, real padding, no wrap. */
  .demostrip a {
    display: inline-block;
    margin-top: 4px;
    padding: 11px 12px;
    white-space: nowrap;
    font-weight: 700;
  }
}


/* 🔴 INSIDE OUR OWN FRAME THE BANNER IS DUPLICATE — 11 Sep 2026. Owner, looking
   at the embed on the home page: "take all of this off this is awfull they know
   that". He is right about that surface: our own chrome prints a disclosure
   directly under the frame, in our voice, so the demo's banner made two stacked
   notices — which reads as nervous rather than as honest.
   ⛔ A STANDALONE PAGE KEEPS IT. There the banner is the ONLY notice, and these
   pages carry a live telephone line: an invented business with a working number
   and nothing saying so is a trap, not a demo.
   ⚠️ Fails in the honest direction — with JavaScript off, nothing is hidden.
   ⛔ If the note under the frame is ever removed, delete this rule first. */
html[data-embedded] .demostrip { display: none !important; }


/* ── 🧭 THE UTILITY BAR — 15 Sep 2026 ─────────────────────────────────
   Written by tools/demo-utilbar.mjs. See that file for why the disclosure
   banner became a chip and why hours are absent on the demos that publish none.
   ⛔ Self-contained colour on purpose: every demo means something different by
   --ink, and borrowing it painted this a different thing on each site. */
.utilbar{background:#0f1b2a;color:rgba(255,255,255,.92);
  border-bottom:1px solid rgba(255,255,255,.14);font-size:.78rem;line-height:1.4;
  font-family:system-ui,-apple-system,"Segoe UI",sans-serif}
.utilbar__in{display:flex;align-items:center;justify-content:space-between;
  gap:.9rem;min-height:38px;padding:.3rem 20px;flex-wrap:wrap;
  max-width:1180px;margin:0 auto}
.utilbar__hours{margin:0;display:flex;align-items:center;gap:.45rem;min-width:0}
.utilbar__hours b{font-weight:600;color:#fff}
.utilbar__sep{opacity:.45}
.utilbar__hours>span:last-child{opacity:.72}
.utilbar__right{display:flex;align-items:center;gap:.9rem;flex-wrap:wrap;min-width:0}
.utilbar__lnk{color:rgba(255,255,255,.88);text-decoration:none;
  border-bottom:1px solid rgba(255,255,255,.26);padding-bottom:1px}
.utilbar__lnk:hover{color:#fff;border-bottom-color:#fff}
/* ⭐ colour is never the only carrier — the words say Open or Closed outright */
.utilbar__dot{width:8px;height:8px;border-radius:50%;flex:0 0 auto;background:#7fe0a8}
.utilbar__hours[data-state="open"] .utilbar__dot{background:#7fe0a8;animation:utilpulse 3s ease-out infinite}
.utilbar__hours[data-state="soon"] .utilbar__dot{background:#ffc861}
.utilbar__hours[data-state="shut"] .utilbar__dot{background:#9aa6b1}
@keyframes utilpulse{0%{box-shadow:0 0 0 0 rgba(127,224,168,.5)}
  70%{box-shadow:0 0 0 6px rgba(127,224,168,0)}100%{box-shadow:0 0 0 0 rgba(127,224,168,0)}}
@media (prefers-reduced-motion:reduce){.utilbar__dot{animation:none !important}}
.utilbar .demostrip{display:inline-flex;align-items:center;gap:.4rem;
  padding:.16rem .55rem;border-radius:999px;background:rgba(255,255,255,.10);
  border:1px solid rgba(255,255,255,.22);font-size:.72rem;color:#fff;
  text-decoration:none;cursor:pointer}
.utilbar .demostrip:hover{background:rgba(255,255,255,.18);border-color:rgba(255,255,255,.38)}
.utilbar .demostrip b{text-transform:uppercase;letter-spacing:.08em;font-size:.68rem;font-weight:700}
.utilbar .demostrip__dot{width:7px;height:7px;border-radius:50%;background:#ff6a55;display:block}
@media (max-width:860px){
  /* ⛔ the TAIL hides, never the notice — and the chip becomes the link to it */
  .utilbar__demotail{display:none}
  .utilbar__in{gap:.55rem}
  .utilbar__right{gap:.7rem}
  .utilbar .demostrip{min-height:30px}
}
@media (max-width:560px){
  .utilbar{font-size:.72rem}
  .utilbar__hours>span:last-child,.utilbar__sep{display:none}
  .utilbar .demostrip{min-height:34px;padding-inline:.7rem}
}
/* ⛔ Inside our own iframe the surrounding chrome carries the disclosure, so the
   chip is hidden there and ONLY there. A standalone page always keeps it. */
html[data-embedded] .utilbar .demostrip{display:none !important}

/* 🔴 NO STATUS LIGHT WITHOUT A STATUS — 15 Sep 2026. Six of these demos publish
   no hours at all, and one publishes "by appointment". The dot is a status
   light: green, beside a company name with nothing behind it, it silently says
   OPEN NOW about a business whose hours nobody ever wrote. It only appears once
   the script has decided a real state from real published hours.
   ⚠️ This shipped for one sync because the fix was written into a script that
   died on an assertion BEFORE the file was saved — the edit was reported and
   never landed. Verify the artefact, not the log line. */
.utilbar__hours:not([data-state]) .utilbar__dot{display:none}


/* ── 🖼️ THE PHOTOGRAPH IS THE HERO — 15 Sep 2026 ─────────────────────────
   Written by tools/demo-photo-hero.mjs; the reasoning lives there. */
.lanaihero{position:relative;isolation:isolate;display:flex;flex-direction:column;justify-content:center;
  min-height:clamp(330px,62vh,600px);overflow:hidden;background:#07182a}
.lanaihero>img{position:absolute;inset:0;z-index:0;width:100%;height:100%;
  object-fit:cover;object-position:center 58%}
/* 🔴 TWO GRADIENTS, BOTH LOAD-BEARING. The horizontal one carries the headline;
   the vertical one holds the eyebrow and the buttons, which sit where the
   horizontal scrim has already thinned out. */
.lanaihero__scrim{position:absolute;inset:0;z-index:1;
  background:
    linear-gradient(90deg, rgba(5,18,32,.93) 0%, rgba(5,18,32,.86) 38%,
                           rgba(5,18,32,.46) 70%, rgba(5,18,32,.24) 100%),
    linear-gradient(0deg,  rgba(5,18,32,.42) 0%, rgba(5,18,32,.30) 50%,
                           rgba(5,18,32,.14) 100%)}
/* ⛔ padding-block, never the shorthand — a `padding: X 0 Y` here wipes the
   horizontal gutter the wrap class contributes and every line goes flush to the
   edge of the screen. That shipped once. */
.lanaihero__in{position:relative;z-index:2;
  padding-block:clamp(2rem,5vw,3.4rem) clamp(1.9rem,4.5vw,3rem)}
.lanaihero h1{color:#fff;max-width:20ch;text-wrap:balance}
.lanaihero .h1__where{color:#fff}
.lanaihero .hl{color:rgba(255,255,255,.74)}
.lanaihero .eyebrow,.lanaihero .lbl,.lanaihero .kicker{color:rgba(255,255,255,.88)}
.lanaihero .btnrow,.lanaihero .hero__act{margin-top:1.4rem;display:flex;flex-wrap:wrap;gap:.7rem}
/* ⛔ A ghost/outline button is a hairline on paper; over a photograph it
   disappears. WCAG 2.2 asks 3:1 for the control's own boundary, not just its
   label. */
.lanaihero .btn--ghost,.lanaihero .btn--line,.lanaihero .btn--out{
  border-color:rgba(255,255,255,.62);color:#fff;background:rgba(7,22,38,.42);
  -webkit-backdrop-filter:blur(3px);backdrop-filter:blur(3px)}
.lanaihero .btn--ghost:hover,.lanaihero .btn--line:hover,.lanaihero .btn--out:hover{
  background:rgba(7,22,38,.66);border-color:#fff}
.lanaihero .photo__cr{position:absolute;right:10px;bottom:9px;z-index:3;
  font-size:10px;color:rgba(255,255,255,.8);background:rgba(0,0,0,.5);
  padding:3px 7px;border-radius:3px}
.lanaihero .photo__cr a{color:inherit}
@media (max-width:640px){
  /* ⚠️ At phone width the headline spans the full column, so a left-weighted
     gradient leaves its right-hand words over bright sky. Mostly vertical here. */
  .lanaihero{min-height:clamp(300px,52vh,420px)}
  .lanaihero__scrim{background:
    linear-gradient(0deg, rgba(5,18,32,.80) 0%, rgba(5,18,32,.72) 50%,
                          rgba(5,18,32,.55) 100%),
    linear-gradient(90deg, rgba(5,18,32,.55) 0%, rgba(5,18,32,.30) 100%)}
  .lanaihero h1{max-width:none}
}




/* 🔴 THE HERO BUTTONS — 15 Sep 2026. Owner: "make sure the buttons are spread
   out and even across heros", "not sqished into the tiltles".
   Measured at 1280 before touching anything: rv-powersports had its buttons
   touching the headline at a gap of ZERO, because its row is `.hero__cta` and
   the rule only named `.btnrow` and `.hero__act`. The rest sat at 22px with an
   11px gap between them and heights running 40 to 53.
   ⭐ One rule, all three row names, and a floor under the height so a row of
   buttons reads as a row rather than as two different controls. */
.lanaihero .btnrow,
.lanaihero .hero__act,
.lanaihero .hero__cta{
  margin-top:clamp(1.6rem,2.6vw,2.2rem);
  display:flex; flex-wrap:wrap; align-items:center;
  gap:.85rem;
}
.lanaihero .btn{
  min-height:48px;
  display:inline-flex; align-items:center; justify-content:center;
  padding-inline:1.25rem;
}
@media (max-width:560px){
  /* ⚠️ Full width and stacked on a phone — two half-width buttons side by side
     put both under the 48px the thumb needs in the direction that matters. */
  .lanaihero .btnrow,.lanaihero .hero__act,.lanaihero .hero__cta{gap:.65rem}
  .lanaihero .btn{width:100%}
}


/* ── 👥 THE SOCIAL MARKS — 15 Sep 2026. Owner: "put fake no link social on the
   headers", after twice being told there is nowhere honest to point them.
   ⛔ THEY ARE NOT LINKS, AND THAT IS THE POINT. These companies are invented,
   so a social icon could only lead to an invented profile, to somebody else's
   real account, or to nothing — and a control that goes nowhere is worse than
   no control. They are `<span>` marks, `aria-hidden`, not focusable and not
   clickable: an illustration of where a real client's profiles sit in the bar,
   on a page that already says it is a demonstration.
   ⛔ Do not turn these into <a> on a real build without real profiles behind
   them. Bots On Staff's own Facebook and Instagram have never published once. */
.utilbar__social{display:inline-flex;align-items:center;gap:.55rem;opacity:.62}
.utilbar__social svg{width:15px;height:15px;display:block}
@media (max-width:560px){ .utilbar__social{display:none} }


/* 🔴 THE GHOST BUTTON, RESTATED BELOW `.btn` — 15 Sep 2026.
   The polish gate refused four demos for this and it was right: adding a
   `.lanaihero .btn` block after the ghost rules puts the outline variant at the
   mercy of source order in unlayered CSS. It happens that the block above sets
   no background, so nothing rendered wrong — but "it happens to be fine" is not
   a property anyone can rely on while editing this file later.
   ⛔ Any new `.btn` rule goes ABOVE this, or this moves below it. */
.lanaihero .btn--ghost,
.lanaihero .btn--line,
.lanaihero .btn--out{
  border-color:rgba(255,255,255,.62);
  color:#fff;
  background:rgba(7,22,38,.42);
  -webkit-backdrop-filter:blur(3px); backdrop-filter:blur(3px);
}
.lanaihero .btn--ghost:hover,
.lanaihero .btn--line:hover,
.lanaihero .btn--out:hover{background:rgba(7,22,38,.66);border-color:#fff}

.lanaihero .btn--ghost{
  border-color:rgba(255,255,255,.62);
  color:#fff;
  background:rgba(7,22,38,.42);
}


/* ── 📣 THE OFFER BAND, ON THE PHOTOGRAPH — 15 Sep 2026 ──────────────────────
   Owner: "i dont think it needs the white section evry vist", then "figure it
   out in a great spot dont just throw it somewhere be creative".
   🔴 IT CANNOT SIMPLY GO. The polish gate requires an offer strip on every page
   and it is right to — it is the one line on a demonstration site that says what
   the shop actually promises. But as a white slab wedged between the header and
   the hero it interrupted the only picture on the page before anyone had seen it.
   ⭐ So it is pinned to the FOOT of the hero, over the photograph, on the same
   dark glass as the scrim. The promise now reads as part of the image instead of
   as an announcement above it, and the page opens header -> photograph -> story
   with nothing cutting across.
   ⛔ Its own backdrop is near-opaque on purpose: type over a photograph is the
   one thing on this estate that has been measured wrong twice, and a band that
   carries its own ground cannot drift when the picture changes. */
.lanaihero{padding-bottom:0}
.lanaihero .offerbar{
  position:absolute; left:0; right:0; bottom:0; z-index:3;
  background:rgba(6,19,34,.86);
  -webkit-backdrop-filter:blur(10px); backdrop-filter:blur(10px);
  border-top:1px solid rgba(255,255,255,.16);
  border-bottom:0;
}
.lanaihero .offerbar__in{
  display:flex; align-items:center; gap:1rem; flex-wrap:wrap;
  padding-block:.7rem;
}
.lanaihero .offerbar__tag{
  color:#fff; border-color:rgba(255,255,255,.45); background:rgba(255,255,255,.10);
}
.lanaihero .offerbar__msg{color:rgba(255,255,255,.92); margin:0}
.lanaihero .offerbar__msg b{color:#fff}
.lanaihero .offerbar__go{color:#fff; border-color:rgba(255,255,255,.5)}
/* ⚠️ the hero's own content must clear the band, or the buttons sit under it */
.lanaihero__in{padding-bottom:clamp(5.5rem,9vw,7rem)}
@media (max-width:860px){
  /* ⛔ On a phone the band would eat the picture. It goes back into the flow
     directly beneath the hero — still out from between the header and the photo,
     which is the thing that was wrong. */
  .lanaihero .offerbar{position:static;backdrop-filter:none;-webkit-backdrop-filter:none}
  .lanaihero__in{padding-bottom:clamp(1.9rem,4.5vw,3rem)}
}


/* ══ 🧭 THE HEADER, 2026 — 15 Sep 2026 ══════════════════════════════════════
   Owner: "the header need to be way better on each site look like proper 2026
   header trends", "make sure everyting looks as goos as outr customer sites".
   🔴 MEASURED FIRST, ALL TWELVE AT 1280: heights ran from 62px to 223px, only
   one was sticky, and eleven carried a telephone number that the new utility bar
   was already showing a few pixels above it.
   ⭐ This layer is keyed on the `header` ELEMENT, not on a class, because these
   demos call it .site, .top, .mast, .nav and .masthead — five names for one
   thing. Anything that needs a class name is done per demo.
   ⛔ It is deliberately visual-only: sticky, glass, a hairline that appears on
   scroll, and honest focus rings. It does not re-order anybody's markup. */
header{
  position:sticky; top:0; z-index:60;
  -webkit-backdrop-filter:saturate(1.3) blur(10px);
  backdrop-filter:saturate(1.3) blur(10px);
  transition:box-shadow .22s ease, border-color .22s ease;
}
/* ⭐ The rule under the header only appears once you have scrolled — a border
   that is always there is chrome, a border that arrives is depth. */
header::after{
  content:""; position:absolute; left:0; right:0; bottom:-1px; height:1px;
  background:currentColor; opacity:0; transition:opacity .22s ease;
  pointer-events:none;
}
html[data-scrolled] header::after{opacity:.16}
html[data-scrolled] header{box-shadow:0 10px 30px -22px rgba(0,0,0,.55)}

/* ⛔ 44px is not decoration. WCAG 2.2 §2.5.8, and on a phone this is the only
   navigation there is. */
@media (max-width:900px){
  header nav a{min-height:44px;display:flex;align-items:center}
}
/* a focus ring that is visible on both a light and a dark header */
header a:focus-visible, header button:focus-visible, header label:focus-visible{
  outline:2px solid currentColor; outline-offset:3px; border-radius:6px;
}


/* 🔴 STICKY WAS LOSING ON SPECIFICITY — 15 Sep 2026. `header{position:sticky}`
   is (0,0,1) and these demos set `.top{position:relative}` at (0,1,0), so five
   of twelve silently stayed put while the other seven pinned. Measured, not
   assumed: auto-detailing, drain-cleaning, mobile-repair, plumbing-hvac and
   rv-powersports all read `relative` after the layer went in.
   ⭐ `header[class]` is (0,1,1) and beats a single class without reaching for
   !important, which would then have to be fought later. */
header[class]{position:sticky;top:0;z-index:60}

/* 🔴 THE OFF-CANVAS MENU WAS WIDENING THE PAGE. Parked at translateX(102%) the
   panel still counted toward scrollWidth — 700px against a 371px viewport — so
   the whole site scrolled sideways on a phone with nothing visible to scroll to.
   ⛔ `overflow-x:hidden` would fix it and break `position:sticky` in the same
   stroke; `clip` does not create a scroll container, so the header still pins. */
html{overflow-x:clip}


/* 🔴 THE NAV WAS WRAPPING ONTO ITS OWN ROW — 15 Sep 2026, measured at 1280.
   These headers are flex rows that ran out of width, so the navigation dropped
   beneath the brand and the header doubled in height: 134, 138, 104, 223.
   A sticky header that tall eats a quarter of a laptop screen, and it is the
   clearest difference between these and the client sites.
   ⭐ One row, and the NAV is the part allowed to give — `min-width:0` lets it
   shrink, and if it still will not fit it scrolls sideways within itself rather
   than pushing the whole header down. ⛔ `scrollbar-width:none` hides the bar,
   not the ability to scroll; the items remain reachable by wheel, trackpad,
   touch and keyboard. */
@media (min-width:901px){
  header .top__in,
  header .masthead__row,
  header .brandline{flex-wrap:nowrap}
  header nav{min-width:0}
}
@media (min-width:901px){
  header nav ul{flex-wrap:nowrap;overflow-x:auto;scrollbar-width:none;-ms-overflow-style:none}
  header nav ul::-webkit-scrollbar{display:none}
  header nav a{white-space:nowrap}
}

@media (min-width:901px){
  header .brand{flex:0 1 auto;min-width:0}
  header nav.nav{flex:1 1 auto;min-width:0}
  header .top__act{flex:0 0 auto}
}



/* 🔴 ONE HERO WAS 83vh BECAUSE ITS HEADLINE WAS 104px — 15 Sep 2026.
   Owner: "make sure desktop hero are proper sixe". Measured at 1280: nine
   heroes sat at 62-66vh and auto-detailing at 83vh, and the cause was not the
   hero box at all — its <h1> renders at 104px over three lines, 306px of type.
   That size was tuned for a hero made ONLY of words; over a photograph it is
   shouting. ⭐ Capped to the size the rest already use, so the set reads as one
   family. ⛔ Still large text for contrast purposes (>=24px), so the 3:1
   threshold the probe applies is unchanged. */
.lanaihero h1{font-size:clamp(2rem,4.4vw,3.5rem);line-height:1.06}

/* ═══ 2026 HERO + TYPE PASS ═══ hand-edited, see the note at the top of this file.
   ⛔ APPENDED deliberately: this file redefines body and h1 twice (~40/447) and
   an unlayered stylesheet resolves that by source order. A correction that is
   not last does not apply. */

/* ── 1. TYPE IN rem, h1 >= 3x BODY AT EVERY WIDTH ──────────────────────────
   BEFORE: body 16px hard-pinned (WCAG 1.4.4 Resize Text fails outright — a
   reader at a larger browser base size got 16px anyway). Hero h1 resolved to
   32px at 320 and 375 = 2.00x body, against a bar of 3.0; 3.50x at 1280.
   ⭐ Both terms are rem now, so the ratio is >=3.0 by construction at every
   width and survives the reader scaling. */
body{font-size:1rem}
h1,
.lanaihero h1{
  font-size:clamp(3rem, 1.5rem + 4.6vw, 4rem);
  line-height:1.03;letter-spacing:-0.032em;font-weight:500;text-wrap:balance;
}

/* ── 2. THE HERO IS THE DOCUMENT ───────────────────────────────────────────
   The offer strip listed six readings in 31 words and then an uppercase pill.
   It is now the declined line off service report SR-4417 — seven words, the
   $0.00 a literal — and amber is exactly right here: this site's whole colour
   system says amber means OUT OF RANGE. */
.offerbar__tag,.offerbar__msg,.offerbar__go{display:none}
.herodoc{
  display:flex;align-items:baseline;flex-wrap:wrap;gap:.45rem 1.05rem;
  padding-top:.85rem;padding-bottom:.9rem;
}
.herodoc__no{
  flex:0 0 auto;font-family:var(--mono);font-size:.75rem;letter-spacing:.14em;
  color:var(--dimmer);
}
.herodoc__item{
  flex:1 1 15rem;min-width:0;color:var(--txt);
  font-size:clamp(.9375rem,1.5vw,1.0625rem);line-height:1.35;
}
.herodoc__item b{color:var(--amber);font-weight:600}
.herodoc__amt{
  flex:0 0 auto;font-family:var(--mono);font-weight:700;
  font-variant-numeric:tabular-nums;font-size:clamp(1rem,1.7vw,1.1875rem);
  color:var(--amber);letter-spacing:-.01em;
}

/* ── 3. ONE HERO, AND IT HOLDS THE FOLD ────────────────────────────────────
   index.html used to open a .lanaihero and then immediately a second
   <section class="hero"> — two heroes on one screen. The second is an ordinary
   evidence band now (.sec--evidence). ⛔ min-height, never height. */
.lanaihero{min-height:min(88vh,44rem);justify-content:flex-end}
/* ⛔ padding-TOP only. `.lanaihero .offerbar` is position:absolute, pinned to the
   bottom of the band, and the clearance that keeps the buttons out from under it
   is `.lanaihero__in{padding-bottom:clamp(5.5rem,9vw,7rem)}` further up this
   file — with a smaller value in the <=860px branch where the bar goes static.
   Setting padding-bottom here overrode BOTH and buried 35px of a 53px button row
   under the strip. Measured, not guessed: btnrow 726.8-779.7, strip top 744.4. */
.lanaihero__in{padding-top:3rem}
.lanaihero .btnrow{margin-top:1.15rem}
.lanaihero__in :is(h1,.btnrow){text-shadow:0 1px 2px rgba(0,0,0,.70),0 2px 20px rgba(0,0,0,.52)}
/* 🔴 `a.btn`, NOT `.btn`. THE TWO-PRIMARIES BUG: this stylesheet is unlayered,
   so a bare `.btn{` rule appended here would beat the `.btn--ghost{` rules above
   it at equal specificity and BOTH hero buttons would render solid — which is a
   defect that has actually shipped on this site. Qualifying the selector keeps
   the last `.btn{` above the last `.btn--ghost{`, which is what
   tools/check-demo-polish.mjs enforces. ⛔ Never append a bare `.btn{` below. */
.lanaihero a.btn{text-shadow:none}
.sec--evidence{padding:44px 0 8px}
.sec--evidence .hero__grid{display:grid;gap:26px;grid-template-columns:1fr}
@media (min-width:62rem){.sec--evidence .hero__grid{grid-template-columns:1.02fr .98fr;align-items:start}}

/* ── 4. THE 2018 TELLS ─────────────────────────────────────────────────────
   Measured on this file: 20 text-transform:uppercase, 37 non-none box-shadows
   including a three-layer 34px/52px stack, 27 `border:1px solid` boxes — on a
   file whose own header says surfaces are "raised by a hairline (never a
   shadow)". ⭐ The hairline stays; the shadows go. Uppercase survives only as a
   document convention — table heads, spec keys, the report header, the
   DECLINED key — because there it is the product, not decoration. */
.lab,.brand__sub,.nav a,.btn,.launch,.chatbox__t,.shot__badge,.navbtn{
  text-transform:none;letter-spacing:.005em;
}
.tile__lab,.tile__st{text-transform:none;letter-spacing:.02em}
.btn,.btn:hover,.launch,.launch:hover,.chatbox,
html[data-scrolled] header{box-shadow:none}
.btn:hover,.launch:hover{transform:none}
.report,.tablewrap,.figure,.tile,.cluster,.shot,.form,.card{box-shadow:inset 0 1px 0 var(--lip)}
.report,.tablewrap,.tile,.cluster,.shot,.form,.card,.note,.declined{border-color:var(--hair)}

/* 🔴 THE TWO-PRIMARIES BUG — see the identical note in roofing/styles.css.
   The `.lanaihero a.btn{…}` line above is now the last `.btn` rule in this
   unlayered file, so the ghost is restated here, last and unchanged. */
.btn--ghost{
  background-color:transparent;color:var(--txt);border-color:var(--hair2);
  background-image:linear-gradient(180deg,rgba(206,234,252,.05),rgba(0,0,0,.14));
  box-shadow:var(--raise);
}

/* ⚠️ the row number sat at 4.18-4.49:1 against a floor of 4.5 — marginal, and
   marginal on the one row the whole site is built to make somebody read. */
.lanaihero .herodoc__no{color:rgba(255,255,255,.82)}

/* 🔴 A POOL UNDER THE WORDS, NOT A LID ON THE PICTURE.
   MEASURED with the type hidden, before: band mean luma 37-45 against a floor
   of 60, picture side 58-79 against 80. At that level the photograph is paying
   for bandwidth and a licence obligation and contributing nothing anyone can
   see — and the owner's instruction is a full-picture hero, professionally
   done. Meanwhile the headline was sitting at 11-17:1 against a floor of 3.0.
   ⭐ So the margin gets SPENT ON THE PHOTOGRAPH, which is the right order: make
   the foreground carry itself, then take the darkness back.
   🔴 EVERY VERTICAL STOP IS IN px. A gradient percentage resolves against the
   ELEMENT, and this band is 704px tall against a 900px screen — the old
   `linear-gradient(0deg, …50%…)` was aiming its mid stop ~350px below where it
   looked like it was. Horizontal % is safe: the element is viewport-wide.
   ⭐ The last third stays at .06. That number IS the picture. If contrast ever
   fails here, fix the foreground or the near stops — never the far end. */
.lanaihero__scrim{
  background:
    linear-gradient(0deg,  rgba(5,18,32,.46) 0px, rgba(5,18,32,0) 240px),
    linear-gradient(92deg, rgba(5,18,32,.88) 0%,  rgba(5,18,32,.80) 40%,
                           rgba(5,18,32,.66) 58%, rgba(5,18,32,.20) 78%,
                           rgba(5,18,32,.06) 100%)}

/* the mark is a filled disc now; keep it square but let it breathe at 26 */
.brand__ico{width:26px;height:26px}

/* ── A PHOTOGRAPH WHERE A DRAWING WAS ────────────────────────────────────────
   ⛔ Not a picture in a rounded card with margin round it — the owner's words
   are "full picture … done professionally". Full-bleed to the gutter, one
   hairline caption under it, no shadow, no radius, no frame. */
.photoband{margin:0 0 2.25rem;padding:0}
.photoband img{display:block;width:100%;height:clamp(240px,34vw,460px);
  object-fit:cover;object-position:center 55%}
.photoband__cap{max-width:74ch;margin:.7rem auto 0;padding:0 clamp(14px,3vw,26px);
  font-size:.8125rem;line-height:1.5;opacity:.72}

/* ═══ GLASS — PLUMBING & AIR: A RULED SLAB ═══════════════════════════════════
   The instrument voice: a 3px radius, a bright hairline top lip and a darker
   base line, so the control reads like a panel switch rather than a pill. The
   fourth distinct material of the four.
   ⛔ Base declaration = the fallback, clearing 4.5:1 with no blur at all.
   ⭐ Copper carries the primary. This file's rule is that copper is a spot
   accent and NEVER a signal — cyan means in range, amber means out of range —
   so a copper button cannot be mistaken for a reading, which is exactly why it
   is the right colour for an action. */
.lanaihero .btn,.lanaihero .btn--ghost{
  border-radius:3px;
  box-shadow:inset 0 1px 0 rgba(255,255,255,.28),inset 0 -1px 0 rgba(0,0,0,.34);
  transition:background-color .2s var(--t),border-color .2s var(--t);
}
.lanaihero .btn{
  --glass-fb:rgba(201,129,79,.95);
  background:rgba(201,129,79,.95);color:#170c04;
  border:1px solid rgba(235,186,146,.62);
}
@supports ((backdrop-filter:blur(2px)) or (-webkit-backdrop-filter:blur(2px))){
  .lanaihero .btn{background:rgba(201,129,79,.88);
    -webkit-backdrop-filter:blur(15px) saturate(1.3);backdrop-filter:blur(15px) saturate(1.3)}
}
.lanaihero .btn:focus-visible,.lanaihero .btn--ghost:focus-visible{
  outline:2px solid var(--cyan);outline-offset:3px}
/* 🔴 restated last — see the note in roofing/styles.css */
.btn--ghost{
  --glass-fb:rgba(10,16,22,.88);
  background:rgba(10,16,22,.88);color:var(--txt);
  border:1px solid rgba(190,220,240,.34);border-radius:3px;
  box-shadow:inset 0 1px 0 rgba(255,255,255,.22);
}
@supports ((backdrop-filter:blur(2px)) or (-webkit-backdrop-filter:blur(2px))){
  .btn--ghost{background:rgba(10,16,22,.62);
    -webkit-backdrop-filter:blur(15px) saturate(1.15);backdrop-filter:blur(15px) saturate(1.15)}
}

/* 🔴 same specificity defect as roofing — both hero buttons rendered copper. */
.lanaihero .btn.btn--ghost{
  background:rgba(10,16,22,.88);color:var(--txt);
  border:1px solid rgba(190,220,240,.34);border-radius:3px;
  box-shadow:inset 0 1px 0 rgba(255,255,255,.22);
  --glass-fb:rgba(10,16,22,.88);
}
@supports ((backdrop-filter:blur(2px)) or (-webkit-backdrop-filter:blur(2px))){
  .lanaihero .btn.btn--ghost{background:rgba(10,16,22,.62);
    -webkit-backdrop-filter:blur(15px) saturate(1.15);backdrop-filter:blur(15px) saturate(1.15)}
}
.btn--ghost{background:rgba(10,16,22,.88);color:var(--txt);border-radius:3px}

/* ⚠️ MARGIN, MEASURED. The tinted primary carries a DARK label, so its worst
   case is the DARKEST backdrop it can sit on, not the brightest — the glass
   gets closer to the photograph and further from its own hue. Measured at
   a=0.80/0.82 the blurred state sat at 4.88 and 4.67 against a floor of 4.5,
   which is margin thin enough that one darker photograph would break it.
   Raising the tint alpha moves the composite back toward the pure brand colour
   (roofing's orange on its ink is 6.53:1 at full strength) and costs almost
   nothing visually: the blur and the saturation are what read as glass here,
   and the SECONDARY at .62 is what carries the visible translucency. */

/* ═══ THE SHEEN IS A SHAPE, NOT A SHEET ══════════════════════════════════════
   Owner, 23 Sep 2026: "i think the picture should be full hero then shene out
   where you want the text" · "evry hero needs to be perfecto".
   🔴 MEASURED BEFORE (tools/_sheen.mjs): sheen extent 100% of the frame on all
   four heroes — a global wash. The band, with the opaque offer strip excluded,
   sat at roughly HALF the photograph's own luminance across the whole picture,
   including the sky and the far side where no word is ever printed.

   ⭐ THE TECHNIQUE: a vertical intensity profile PAINTED, multiplied by a
   horizontal falloff MASKED. Two background layers would composite additively
   and still cover the whole box; a mask multiplies, so the result is a genuine
   two-dimensional shape that is soft on both axes and reaches true zero.
   ⛔ Soft stops only. A visible boundary where the sheen ends is worse than the
   flat wash it replaces.
   🔴 EVERY VERTICAL STOP IS IN px. A gradient percentage resolves against the
   ELEMENT, and this band is min(88vh,44rem) — its height moves with the window.
   Horizontal % is safe: the element is viewport-wide.
   ⭐ The horizontal stops are keyed to THIS site's measured type block, not to a
   shape that looked right — the widest run of ink ends at a different place on
   each of the four.
   ⚠️ FALLBACK: where mask-image is unsupported the vertical gradient paints
   alone — a bottom wash at full width. Dimmer than intended, never unreadable,
   which is the right direction for a graceful failure. */
.lanaihero__scrim{
  background:linear-gradient(0deg,
    rgba(5,14,22,.92) 0px,
    rgba(5,14,22,.88) 170px,
    rgba(5,14,22,.66) 330px,
    rgba(5,14,22,.30) 460px,
    rgba(5,14,22,0)   600px);
  -webkit-mask-image:linear-gradient(90deg,#000 0%,#000 48%,
    rgba(0,0,0,.58) 64%, rgba(0,0,0,.18) 78%, transparent 88%);
  mask-image:linear-gradient(90deg,#000 0%,#000 48%,
    rgba(0,0,0,.58) 64%, rgba(0,0,0,.18) 78%, transparent 88%);
}
/* ⛔ A PHONE IS NOT A NARROW DESKTOP. Below 741px the headline wraps to four or
   five lines and the type occupies almost the whole frame, so a horizontal
   falloff keyed to a desktop text block would leave the last words bare. The
   sheen goes nearly full width and taller; what still protects the photograph
   here is the VERTICAL profile, because the top half carries no type. */
@media (max-width:46.25rem){
  .lanaihero__scrim{
    background:linear-gradient(0deg,
      rgba(5,14,22,.93) 0px,
      rgba(5,14,22,.90) 220px,
      rgba(5,14,22,.70) 400px,
      rgba(5,14,22,.32) 530px,
      rgba(5,14,22,0)   660px);
    -webkit-mask-image:linear-gradient(90deg,#000 0%,#000 80%,rgba(0,0,0,.45) 92%,transparent 100%);
    mask-image:linear-gradient(90deg,#000 0%,#000 80%,rgba(0,0,0,.45) 92%,transparent 100%);
  }
}

/* 🔴 THE REFUSAL WAS OFF-SCREEN ON A PHONE. Diagnosed, not guessed: the glyph
   probe returned NO DIFF for the whole document row at 320 and 375, and a
   no-diff has three causes — invisible, unpainted, covered — of which only one
   is a contrast defect. tools/_heroluma.mjs now reports which; it said
   UNPAINTED, outside the captured viewport. The hero was min(88vh,44rem) = 704px
   tall, and 704 + the masthead put the strip 27px below an 812px fold.
   ⛔ That breaks the one rule this whole hero exists for: the refusal is read
   WITHOUT SCROLLING. A shorter band on a phone, so the row is on screen.
   ⛔ min-height, never height — the band still grows when a five-line headline
   needs it, which is the case a fixed height would clip. */
@media (max-width:46.25rem){
  .lanaihero{min-height:min(70vh,34rem)}
}

/* ⚠️ THE PHONE RAMP HAD TO SHRINK WITH THE PHONE BAND. Shortening the hero so
   the refusal clears the fold left the previous px stops (zero at 660px) taller
   than the band itself (~544px), so the sheen never reached zero and the whole
   phone hero went to band luma 53 against a floor of 60 — darker than the
   desktop version it was supposed to improve on.
   ⛔ This is the cost of px stops, and it is still the right trade: a % stop
   would drift with the viewport height instead, which is harder to see and
   harder to fix. When the band's height changes, the ramp is a number you own. */
@media (max-width:46.25rem){
  .lanaihero__scrim{
    background:linear-gradient(0deg,
      rgba(5,14,22,.93) 0px,
      rgba(5,14,22,.88) 140px,
      rgba(5,14,22,.62) 260px,
      rgba(5,14,22,.26) 350px,
      rgba(5,14,22,0)   430px);
  }
}

/* ⚖️ THE PHONE HERO IS A THREE-WAY TRADE AND THE FIRST TWO ATTEMPTS EACH LOST
   ONE LEG OF IT: a tall band put the refusal below the fold; a short band with
   a short ramp pushed the top of the headline to 1.89:1 against a floor of 3.
   ⛔ Contrast is not the leg that gives. So the TYPE BLOCK shrinks instead:
   the two hero buttons sit side by side rather than stacked full width, which
   returns a whole row (~55px) to the photograph, and the band grows back.
   ⭐ Then the ramp covers the type's real height and still reaches zero with
   clean photograph above it. Measured, not reasoned. */
@media (max-width:46.25rem){
  .lanaihero{min-height:min(72vh,36rem)}
  /* ⛔ comma-listed with the ghost on purpose: a bare `.btn{` rule here would
     become the last one in this unlayered file and strip the secondary. */
  .lanaihero .btn,.lanaihero .btn--ghost,
  .band--photo .btn,.band--photo .btn--out{width:auto;flex:0 1 auto}
  .lanaihero__scrim{
    background:linear-gradient(0deg,
      rgba(5,14,22,.93) 0px,
      rgba(5,14,22,.90) 200px,
      rgba(5,14,22,.74) 330px,
      rgba(5,14,22,.40) 440px,
      rgba(5,14,22,.12) 510px,
      rgba(5,14,22,0)   580px);
  }
}

/* 🔴 THE CHAT LAUNCHER WAS PAINTED ON TOP OF THE REFUSAL. Measured at 375px:
   the launcher is position:fixed at left:16px bottom:16px, box 16,748→107,796,
   and the document row sits at 0,723→375,777. document.elementFromPoint at the
   row's left end returned the launcher, not the row — so the first words of the
   one line this whole hero exists for were covered, at scroll 0, before the
   reader has done anything.
   ⚠️ This is the case ux-build calls unavoidable: a floating element is escapable
   by scrolling everywhere EXCEPT where the reader already is.
   ⭐ Raise it clear of the strip on phones rather than shrinking the hero again
   — the strip's own height is the offset, taken from the same tokens it uses. */
@media (max-width:46.25rem){
  .launch,.chatbox{bottom:calc(16px + 3.9rem + env(safe-area-inset-bottom,0px))}
}

/* ⚠️ AND THE SAME COLLISION AT 741px, WHICH THE PHONE BREAKPOINT MISSED.
   The probe found chat-btn painted over "Line 6" at 741 on tree-service: at that
   width the nav wraps, the masthead grows, and the strip is pushed far enough
   down the viewport to meet a launcher pinned 16px off the bottom. It does NOT
   collide at 1280 or 1440, where the header is short again — so this is a
   header-height effect, not a width effect, and the breakpoint has to be wide
   enough to cover every layout where the two can meet. Verified at 320, 375,
   741, 1280 and 1440. */
@media (max-width:64rem){
  .launch,.chatbox{bottom:calc(16px + 3.9rem + env(safe-area-inset-bottom,0px))}
}

/* 🔴 AND IT COLLIDES AT 1280 TOO — RAISED AT EVERY WIDTH.
   Measured directly on the page: the launcher covers 84% of the row's line
   number and document.elementFromPoint at its centre returns the launcher, not
   the row. My own glyph probe called 1280 CLEAN, because the uncovered 16% of
   the glyphs still produced a diff and so it returned a ratio instead of the
   no-diff that would have flagged it. ⛔ A contrast probe is not an overlap
   probe; do not let one stand in for the other.
   ⭐ The media query is gone. A launcher pinned 16px off the bottom will meet
   the strip at whatever width the header happens to be tall enough — 741 and
   1280 both did — so the offset is unconditional. It costs one row of empty
   space at the bottom of the screen and removes the whole class of collision. */
.launch,.chatbox{bottom:calc(16px + 3.9rem + env(safe-area-inset-bottom,0px))}

/* 🔴 MOVING THE LAUNCHER WAS THE WRONG FIX AND IT CAUSED WHAT IT CURED.
   Measured per width instead of reasoned: at 320 the strip ends 72px above the
   fold and at 741 it ends 88px above, and the launcher (42-48px plus its 16px
   inset) ALREADY FIT UNDERNEATH at both. Lifting it 78px moved it off the
   photograph and INTO the strip — two new collisions in exchange for one. And a
   single lift cannot be right everywhere: the room below the strip is 95px on
   roofing at 1280 and 8px on tree-service at the same width, because the two
   heroes are not the same height.
   ⭐ SO THE STRIP MOVES, NOT THE LAUNCHER. A fixed gutter at the foot of the
   band puts the document row clear of anything pinned to the bottom of the
   viewport, at every width, on every one of the four — and the launcher goes
   back where its own stylesheet put it.
   ⛔ Both declarations are needed: the strip is position:absolute in the wide
   layout and static below 860px, and only one of them answers to each. */
.launch,.chatbox{bottom:16px}
.lanaihero{padding-bottom:4.6rem}
.lanaihero .offerbar{bottom:4.6rem}

/* ⚠️ AT 320 THE ROW WRAPS TO THREE LINES and the strip grows from ~55px to
   ~108px, which ate the 4.6rem gutter and put it back under the launcher —
   plumbing-hvac's ran 671..779 in a 780px viewport, flush against the fold.
   The gutter has to clear the TALLEST the strip gets, not the shortest.
   ⭐ 320 is SC 1.4.10's own number and where a real iPhone SE at 400% zoom
   lands; it is the width where everything is worst and the one most likely to
   be skipped. Measured here, not extrapolated from 375. */
@media (max-width:22.5rem){
  .lanaihero{padding-bottom:7.6rem}
  .lanaihero .offerbar{bottom:7.6rem}
}

/* 🔴 AT 320 THE $0.00 WAS 97% COVERED BY THE CHAT LAUNCHER.
   The row is a flex line; at 320 it wraps to three stacked lines and the amount
   drops to the THIRD line, left-aligned — which is precisely where a launcher
   pinned to the bottom-left sits. document.elementFromPoint at the middle of
   "$0.00" returned the launcher. The single most important literal on the site,
   invisible, at the width the accessibility criterion names.
   ⭐ A two-column grid keeps the amount on the right edge where a document puts
   it, clear of anything docked bottom-left, and drops the strip from three
   lines to two — which also buys back the fold. */
@media (max-width:22.5rem){
  .herodoc{display:grid;grid-template-columns:minmax(0,1fr) auto;
    align-items:baseline;column-gap:.7rem;row-gap:.2rem}
  .herodoc__no{grid-column:1/-1}
  .herodoc__item{grid-column:1}
  .herodoc__amt{grid-column:2;justify-self:end}
}

/* ⚠️ AT 320 THE CONTENT ALREADY FILLS THE SCREEN, so a min-height only pushes
   the foot of the band past the fold. A six-line headline at the 3x-body floor
   plus two buttons plus the document row is taller than 320x780 leaves after
   the masthead — there is nothing for a minimum to add, and what it adds comes
   off the bottom, which is where the refusal lives.
   ⛔ Still min-height:auto rather than a fixed height: the band must be free to
   grow, it just must not be padded taller than its content. */
@media (max-width:22.5rem){
  .lanaihero{min-height:auto}
}

/* ⚠️ THE 320 GUTTER WAS BELOW THE FOLD AND SO BOUGHT NOTHING. Measured on
   plumbing-hvac: band 162..886 in a 780px viewport, strip 670..764, gutter
   121.6px sitting at 764..886 — entirely off-screen. The strip's position is
   set by the CONTENT ABOVE IT, not by padding underneath, so the only way to
   lift it is to take height out of what comes first.
   ⭐ ~56px recovered from the hero's top padding, the headline's leading and
   the button gap — none of it from the type SIZE, which is pinned at 3x body. */
@media (max-width:22.5rem){
  .lanaihero .lanaihero__in,.lanaihero>.wrap{padding-top:1rem}
  .lanaihero h1,.lanaihero .h1{line-height:.98}
  .lanaihero .btnrow{margin-top:.8rem}
  .lanaihero{padding-bottom:1.5rem}
}

/* ⚖️ THE 320 RAMP, AND THE TRADE I REFUSED TO MAKE.
   Letting content drive the band at 320 made it shorter again, so the previous
   ramp (zero at 580px) never reached zero inside it and the whole hero went to
   band luma 46 against a floor of 60. This ramp is scaled to the band that is
   actually there.
   ⛔ AND IT STILL COVERS THE TYPE FIRST. At 320 a headline pinned at 3x body is
   six lines, and with two buttons and the document row the type occupies almost
   the whole band — there is no width of clean photograph to be had without
   either shrinking the type below its floor or pushing the refusal past the
   fold. Both are worse than a darker picture on the narrowest phone, so the
   picture-side number is reported under floor rather than bought. */
@media (max-width:22.5rem){
  .lanaihero__scrim{
    background:linear-gradient(0deg,
      rgba(5,14,22,.93) 0px,
      rgba(5,14,22,.90) 180px,
      rgba(5,14,22,.76) 300px,
      rgba(5,14,22,.46) 400px,
      rgba(5,14,22,.16) 470px,
      rgba(5,14,22,0)   530px);
  }
}

/* ⚖️ 320 RAMP, TUNED TO THIS SITE'S OWN BAND. One shared set of stops could not
   serve four heroes whose headlines wrap to four, five and six lines: the same
   ramp left roofing's band at 48 luma with contrast to spare, and dropped
   plumbing-hvac's headline to 2.61 against a floor of 3. The type is covered
   first, everywhere; what varies is how much photograph is left over. */
@media (max-width:22.5rem){
  .lanaihero__scrim{
    background:linear-gradient(0deg,
      rgba(5,14,22,.93) 0px,
      rgba(5,14,22,.90) 220px,
      rgba(5,14,22,.74) 360px,
      rgba(5,14,22,.44) 470px,
      rgba(5,14,22,.15) 550px,
      rgba(5,14,22,0)   640px);
  }
}
