/* ==========================================================================
   1st Class Protection - design system
   --------------------------------------------------------------------------
   Derived from the existing brand mark: lime green on charcoal, angular
   geometry, white technical lettering. The palette, radii and type scale
   below are the single source of truth for the whole site.
   ========================================================================== */

/* ---------- 1. Tokens ---------------------------------------------------- */

:root{
  /* Brand. The lime is carried over from the existing logo unchanged. */
  --brand:#8DC63F;
  --brand-bright:#A8E052;
  --brand-deep:#6C9C2E;
  --brand-ink:#0A1204;            /* text that sits on brand fills */
  --brand-wash:rgba(141,198,63,.12);
  --brand-line:rgba(141,198,63,.34);
  /* the lime is bright enough to read on dark, but only 1.9:1 on white, so
     light mode gets a darkened version for anything that is *text* */
  --brand-txt:#4A7317;            /* lime is 1.9:1 on light, so text uses this */

  /* SHOWROOM CONTRAST.
     The page ground is light and dark is a BAND, not a global theme. Every
     token below is redeclared inside .on-dark, so a component dropped in
     either surface inherits the right values with no variant classes. */

  /* light surface (default) */
  --ink-950:#EFF1EA;
  --ink-900:#FBFBF8;              /* page */
  --ink-850:#F5F6F0;
  --ink-800:#EFF1EA;              /* surface */
  --ink-700:#E6E9DE;              /* surface raised */
  --ink-600:#D9DDCF;

  --fg:#14170F;
  --fg-muted:#545C4B;
  --fg-dim:#6B7360;

  --line:rgba(20,23,15,.13);
  --line-2:rgba(20,23,15,.22);

  /* Semantic, kept separate from the brand accent */
  --ok:#7FC97F;
  --warn:#E0B84A;
  --err:#E2685F;

  /* Radius. Structural surfaces are square to echo the angular mark;
     only interactive chips and inputs get a hairline radius. */
  --r-0:0px;
  --r-1:2px;
  --r-2:4px;

  /* Spacing scale */
  --s-1:.25rem; --s-2:.5rem;  --s-3:.75rem; --s-4:1rem;
  --s-5:1.5rem; --s-6:2rem;   --s-7:3rem;   --s-8:4rem;
  --s-9:6rem;   --s-10:8rem;

  /* Section rhythm */
  --sec:clamp(3.25rem,6.4vw,6rem);
  --nav-h:76px;
  --pad:clamp(1.15rem,4.5vw,3.5rem);
  --maxw:1440px;
  --measure:64ch;

  /* Shadows, tinted with the page hue rather than pure black */
  --sh-1:0 1px 2px rgba(20,23,15,.08);
  --sh-2:0 8px 24px -8px rgba(20,23,15,.16);
  --sh-3:0 24px 60px -16px rgba(20,23,15,.22);

  /* Type */
  /* One superfamily, three widths. Saira has squared, engineered terminals
     that sit naturally next to the angular shield in the logo, and its width
     axis gives real hierarchy without dragging in unrelated typefaces.
       Condensed      -> headlines
       Semi Condensed -> small uppercase labels
       Regular width  -> body copy and figures */
  --display:"Jost","Archivo Black","Archivo",Helvetica,Arial,sans-serif;
  --label:"Archivo",Helvetica,Arial,sans-serif;
  --sans:"Archivo",-apple-system,BlinkMacSystemFont,"Segoe UI",Helvetica,Arial,sans-serif;
  --mono:var(--label);
  --num:"Archivo",Helvetica,Arial,sans-serif;

  --t-xs:.75rem; --t-sm:.875rem; --t-base:1rem;   --t-md:1.0625rem;
  --t-lg:1.25rem; --t-xl:1.5rem;
  --d-1:clamp(2rem,3.6vw,2.9rem);
  --d-2:clamp(2.4rem,5.2vw,4.2rem);
  --d-3:clamp(2.9rem,6.8vw,5.6rem);
  --d-4:clamp(2.5rem,8.4vw,7.2rem);

  /* Motion */
  --e:cubic-bezier(.16,1,.3,1);
  --e-enter:cubic-bezier(.22,1,.36,1);   /* entrances, transform hover */
  --e-move:cubic-bezier(.25,1,.5,1);     /* slides, drawers, panels */
  --t-press:120ms; --t-fast:150ms; --t-hover:200ms;
  --t-mid:280ms; --t-slow:520ms;         /* exits run ~65% of enter */
  --t-exit:180ms;

  /* Layers */
  --z-base:1; --z-sticky:20; --z-nav:40; --z-modal:80; --z-grain:90;
}


/* ---------- 1b. Dark bands --------------------------------------------------
   Any section carrying .on-dark flips the whole token set. Components inside
   need no variant classes: they read the same names and get dark values.
   -------------------------------------------------------------------------- */

.on-dark{
  --ink-950:#08090A;
  --ink-900:#0C0F0A;
  --ink-850:#11150E;
  --ink-800:#161B12;
  --ink-700:#1D2317;
  --ink-600:#262D1F;

  --fg:#FBFBF8;
  --fg-muted:rgba(251,251,248,.66);
  --fg-dim:rgba(251,251,248,.45);

  --line:rgba(251,251,248,.12);
  --line-2:rgba(251,251,248,.22);

  --brand-txt:#8DC63F;            /* full lime reads fine on dark */
  --brand-wash:rgba(141,198,63,.12);
  --brand-line:rgba(141,198,63,.34);

  --ok:#7FC97F; --warn:#E0B84A; --err:#E2685F;

  --sh-1:0 1px 2px rgba(6,10,5,.5);
  --sh-2:0 8px 24px -8px rgba(6,10,5,.7);
  --sh-3:0 24px 60px -16px rgba(6,10,5,.85);

  background:var(--ink-900);
  color:var(--fg);
}

/* an explicit light band, for flipping back inside a dark parent */
/* light bands swap the wordmark to dark ink */
.on-light .logo-swap{content:none}
.on-light{
  --ink-950:#EFF1EA; --ink-900:#FBFBF8; --ink-850:#F5F6F0;
  --ink-800:#EFF1EA; --ink-700:#E6E9DE; --ink-600:#D9DDCF;
  --fg:#14170F; --fg-muted:#545C4B; --fg-dim:#6B7360;
  --line:rgba(20,23,15,.13); --line-2:rgba(20,23,15,.22);
  --brand-txt:#4A7317;
  --brand-wash:rgba(141,198,63,.16);
  --brand-line:rgba(106,150,45,.42);
  background:var(--ink-900);
  color:var(--fg);
}

/* ---------- 2. Reset ----------------------------------------------------- */

*,*::before,*::after{box-sizing:border-box}

/* The canvas takes its colour from html when html has one, otherwise it
   propagates from body - and body's ground is light in Direction A, which is
   what made navigation flash white. Mirrors the inline critical style. */
html{-webkit-text-size-adjust:100%;background:#0A0D08}
@media (prefers-reduced-motion:no-preference){ html{scroll-behavior:smooth} }

body{
  margin:0;
  background:var(--ink-900);
  color:var(--fg);
  font-family:var(--sans);
  font-size:var(--t-md);
  line-height:1.6;
  -webkit-font-smoothing:antialiased;
  overflow-x:hidden;
}

img,svg,video{display:block;max-width:100%}
img{height:auto}

/* Jost is geometric and needs far less negative tracking than Archivo Black
   did, and weight 700 rather than 400 (Archivo Black's only face WAS the
   black; Jost 400 is a regular). */
h1,h2,h3,h4{margin:0;font-family:var(--display);font-weight:700;line-height:1.02;letter-spacing:-.012em;text-transform:uppercase;text-wrap:balance}

/* Uppercase at small sizes needs POSITIVE tracking - tight caps close up and
   turn into a block. The negative tracking belongs on the big display lines
   only. */
h3,h4{letter-spacing:.015em}
p{margin:0;text-wrap:pretty}
ul,ol{margin:0;padding:0;list-style:none}

a{color:inherit;text-decoration:none}
button,input,select,textarea{font:inherit;color:inherit}

:focus-visible{outline:2px solid var(--brand);outline-offset:3px;border-radius:var(--r-1)}

::selection{background:var(--brand);color:var(--brand-ink)}

.skip-link{
  position:absolute;left:-9999px;top:0;z-index:200;
  background:var(--brand);color:var(--brand-ink);
  padding:var(--s-3) var(--s-5);font-weight:600;
}
.skip-link:focus{left:0}

.vh{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}

/* ---------- 3. Layout primitives ---------------------------------------- */

.wrap{width:100%;max-width:var(--maxw);margin-inline:auto;padding-inline:var(--pad)}
.wrap-tight{max-width:1120px}

.section{padding-block:var(--sec)}
.section--line{border-top:1px solid var(--line)}

.stack{display:flex;flex-direction:column}
.stack-3{gap:var(--s-3)} .stack-4{gap:var(--s-4)}
.stack-5{gap:var(--s-5)} .stack-6{gap:var(--s-6)}

.measure{max-width:var(--measure)}

.grain{
  position:fixed;inset:0;z-index:var(--z-grain);pointer-events:none;
  opacity:.03;mix-blend-mode:overlay;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='160' height='160'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='.8' numOctaves='3'/%3E%3C/filter%3E%3Crect width='160' height='160' filter='url(%23n)'/%3E%3C/svg%3E");
}

/* ---------- 4. Type helpers --------------------------------------------- */

.eyebrow{
  font-family:var(--label);font-size:.8125rem;font-weight:700;
  letter-spacing:.22em;text-transform:uppercase;color:var(--brand-txt);
}
.lede{color:var(--fg-muted);font-size:var(--t-lg);max-width:var(--measure)}
.muted{color:var(--fg-muted)}
.dim{color:var(--fg-dim)}
.mono{font-family:var(--label);letter-spacing:.12em;text-transform:uppercase}
.num{font-family:var(--num);font-variant-numeric:tabular-nums;font-weight:600}

.d1,.d2,.d3,.d4{font-family:var(--display)}
.d1{font-size:var(--d-1)} .d2{font-size:var(--d-2)}
.d3{font-size:var(--d-3)} .d4{font-size:var(--d-4)}

.sec-head--flush{margin-bottom:0}
/* max-width used to sit on the container, where `ch` resolves against the
   BODY font - so 64ch was about 576px and a 100px display heading got crammed
   into a third of the page and wrapped to four lines. The measure belongs on
   the prose; the heading gets its own, which `ch` resolves at the heading's
   own size and is therefore much wider. */
.sec-head{display:flex;flex-direction:column;gap:var(--s-4);margin-bottom:clamp(2rem,4.5vw,3.5rem)}
.sec-head > h1,.sec-head > h2,.sec-head > h3{max-width:22ch}
.sec-head > p,.sec-head > .lede,.sec-head > .muted{max-width:var(--measure)}

/* ---------- 5. Buttons --------------------------------------------------- */

.btn{
  font-family:var(--sans);font-weight:600;
  display:inline-flex;align-items:center;justify-content:center;gap:var(--s-2);
  padding:.9rem 1.7rem;border:1px solid transparent;border-radius:var(--r-0);
  font-size:1rem;font-weight:600;letter-spacing:.03em;text-transform:uppercase;
  white-space:nowrap;cursor:pointer;text-align:center;
  transition:background var(--t-fast) var(--e),border-color var(--t-fast) var(--e),
             color var(--t-fast) var(--e),transform 90ms ease;
}
.btn:active{transform:translateY(1px)}

.btn--primary{background:var(--brand);color:var(--brand-ink);border-color:var(--brand-txt)}
.btn--primary:hover{background:var(--brand-bright);border-color:var(--brand-txt)}

.btn--ghost{border-color:var(--line-2);color:var(--fg)}
.btn--ghost:hover{border-color:var(--brand-txt);color:var(--brand-txt)}

.btn--quiet{display:inline-flex;align-items:center;min-height:44px;padding:.75rem 0;color:var(--brand-txt);font-family:var(--mono);
  font-size:.75rem;font-weight:700;letter-spacing:.14em;text-transform:uppercase}
.btn--quiet:hover{color:var(--brand-txt)}

.btn--block{width:100%}
.btn--lg{padding:1.05rem 2.1rem;font-size:1.125rem}

.btn[disabled],.btn[aria-disabled="true"]{opacity:.45;cursor:not-allowed}
.btn[disabled]:active{transform:none}

/* ---------- 6. Chips ----------------------------------------------------- */

.chip{
  display:inline-flex;align-items:center;gap:var(--s-2);
  padding:.55rem 1rem;border:1px solid var(--line);border-radius:var(--r-1);
  background:transparent;color:var(--fg-muted);font-size:var(--t-sm);cursor:pointer;
  transition:border-color var(--t-fast) var(--e),color var(--t-fast) var(--e),
             background var(--t-fast) var(--e),transform 90ms ease;
  min-height:44px;   /* touch target floor - the padding alone left it at 42px */
}
.chip:hover{border-color:var(--line-2);color:var(--fg)}
.chip:active{transform:translateY(1px)}
/* a tinted wash over a light ground drops the label to 2.7:1, so the selected
   chip is a solid fill on both surfaces */
.chip[aria-pressed="true"],.chip[aria-selected="true"]{
  border-color:var(--brand);background:var(--brand);color:var(--brand-ink);font-weight:600;
}

/* ---------- 7. Navigation ------------------------------------------------ */

.nav{
  overflow-x:clip;
  /* Solid black masthead. The page ground is light in Direction A, so a
     translucent dark bar rendered as a grey slab over it - the fill is
     opaque on purpose, and the nav carries its own dark tokens so every
     child inside it behaves without needing an .on-dark wrapper. */
  --fg:#FBFBF8; --fg-muted:rgba(251,251,248,.62); --fg-dim:rgba(251,251,248,.48);
  --brand-txt:#8DC63F; --line:rgba(251,251,248,.13);
  position:sticky;top:0;z-index:var(--z-nav);
  background:#0A0D08;color:var(--fg);
  border-bottom:1px solid var(--line);
  transition:box-shadow var(--t-mid) var(--e);
}
.nav.is-stuck{box-shadow:0 10px 30px -18px rgba(0,0,0,.9)}

.nav__in{
  /* above the drawer (both are children of .nav) so the logo and the
     close X stay visible and clickable while the menu is open */
  position:relative;z-index:3;
  height:76px;display:flex;align-items:center;gap:var(--s-6);
  max-width:var(--maxw);margin-inline:auto;padding-inline:var(--pad);
}
.nav__logo{display:flex;align-items:center;gap:.65rem;flex:0 0 auto;min-height:44px}
.nav__mark{height:34px;width:auto;display:block;flex:0 0 auto}
.nav__wm{display:flex;flex-direction:column;justify-content:center;line-height:1}
.nav__wm1{
  font-family:var(--display);font-weight:700;text-transform:uppercase;
  font-size:1.06rem;letter-spacing:.02em;color:var(--fg);
}
.nav__wm2{
  font-family:var(--label);font-weight:700;text-transform:uppercase;
  font-size:.56rem;letter-spacing:.34em;color:var(--brand-txt);margin-top:.2rem;
}

/* the links take the free middle so the bar reads logo | nav | actions */
.nav__links{
  flex:1 1 auto;display:flex;align-items:center;justify-content:center;
  gap:clamp(1rem,2.4vw,2.1rem);font-size:var(--t-sm);white-space:nowrap;
}
.nav__links a{
  position:relative;display:inline-flex;align-items:center;min-height:44px;
  font-family:var(--label);font-size:.78rem;font-weight:700;
  letter-spacing:.1em;text-transform:uppercase;
  color:var(--fg-muted);transition:color var(--t-fast) var(--e);
}
.nav__links a::after{
  content:"";position:absolute;left:0;right:0;bottom:12px;height:1.5px;
  background:var(--brand-txt);transform:scaleX(0);transform-origin:left;
  transition:transform var(--t-mid) var(--e-enter);
}
.nav__links a:hover{color:var(--fg)}
@media (hover:hover) and (pointer:fine){
  .nav__links a:hover::after{transform:scaleX(1)}
}
.nav__links a[aria-current="page"]{color:var(--fg)}
.nav__links a[aria-current="page"]::after{transform:scaleX(1)}

.nav__right{flex:0 0 auto;display:flex;align-items:center;gap:var(--s-4)}
.nav__tel{
  display:inline-flex;align-items:center;min-height:44px;
  font-family:var(--num);font-size:var(--t-sm);font-weight:600;
  font-variant-numeric:tabular-nums;white-space:nowrap;color:var(--fg);
}
.nav__tel:hover{color:var(--brand-txt)}

/* bare icon, no box: the 44px target comes from the button's own size */
.nav__burger{
  display:none;width:44px;height:44px;margin-right:-10px;
  align-items:center;justify-content:center;
  background:transparent;border:0;border-radius:var(--r-1);cursor:pointer;
  -webkit-tap-highlight-color:transparent;
}
.nav__burger:focus-visible{outline:2px solid var(--brand-txt);outline-offset:2px}
.nav__burger span{
  display:block;width:22px;height:2px;background:var(--fg);border-radius:2px;
  position:relative;transition:background-color var(--t-fast) var(--e);
}
.nav__burger span::before,.nav__burger span::after{
  /* transform only: animating `top` would recalc layout every frame */
  content:"";position:absolute;left:0;width:22px;height:2px;border-radius:2px;
  background:var(--fg);
  transition:transform var(--t-mid) var(--e-enter),background-color var(--t-fast) var(--e);
}
.nav__burger span::before{transform:translateY(-7px)}
.nav__burger span::after{transform:translateY(7px)}
.nav__burger[aria-expanded="true"] span{background:transparent}
.nav__burger[aria-expanded="true"] span::before{transform:rotate(45deg)}
.nav__burger[aria-expanded="true"] span::after{transform:rotate(-45deg)}

.nav__drawer{
  /* Covers the whole viewport; the bar itself sits above it via .nav__in,
     so the drawer offset can never drift out of sync with the bar height. */
  --fg:#FBFBF8; --fg-muted:rgba(251,251,248,.62); --brand-txt:#8DC63F;
  --line:rgba(251,251,248,.13);
  position:fixed;inset:0;z-index:2;
  background:#0A0D08;color:var(--fg);
  padding:calc(64px + var(--s-5)) var(--pad) calc(var(--s-8) + env(safe-area-inset-bottom));
  display:flex;flex-direction:column;gap:0;
  overflow-y:auto;
  transform:translateY(-8px);opacity:0;visibility:hidden;pointer-events:none;
  transition:opacity var(--t-mid) var(--e),transform var(--t-mid) var(--e),visibility var(--t-mid);
}
.nav__drawer.is-open{opacity:1;transform:none;visibility:visible;pointer-events:auto}
.nav__drawer > a{
  display:flex;align-items:center;justify-content:space-between;
  padding:var(--s-4) 0;border-bottom:1px solid var(--line);
  font-family:var(--display);font-size:clamp(1.5rem,7vw,2rem);line-height:1.1;
  letter-spacing:0;text-transform:uppercase;color:var(--fg);
}
.nav__drawer > a[aria-current="page"]{color:var(--brand-txt)}
.nav__drawer .drawer-cta{display:flex;flex-direction:column;gap:var(--s-3);margin-top:var(--s-7)}

/* 1080-1400px: logo + five links + phone + CTA do not fit, and body clips the
   overflow, so on a 1366 laptop the "Get an estimate" button was cut off at
   the right edge. Drop the phone from the bar first (it is in the hero, every
   closer, the footer and the contact page) and pull the link spacing in. */
@media (max-width:1400px){
  .nav__tel{display:none}
  .nav__links{gap:clamp(.9rem,1.6vw,1.6rem)}
  .nav__links a{letter-spacing:.08em}
  .nav__in{gap:var(--s-5)}
}
@media (max-width:1080px){
  .nav__in{height:64px}
  :root{--nav-h:64px}
  .nav__mark{height:28px}
  .nav__wm1{font-size:.94rem}
  .nav__wm2{font-size:.56rem;letter-spacing:.26em}
  .nav__links{display:none}
  .nav__burger{display:inline-flex}
  .nav__right{margin-left:auto}
  .nav__right .btn{display:none}
}
@media (max-width:520px){ .nav__tel{display:none} }

body.is-locked{overflow:hidden}

/* ---------- 8. Hero ------------------------------------------------------ */

.hero{position:relative;min-height:min(88dvh,780px);display:flex;align-items:flex-end;overflow:hidden}
.hero--short{min-height:calc(100dvh - var(--nav-h))}

.hero__media{position:absolute;inset:0}
.hero__media img{width:100%;height:100%;object-fit:cover;object-position:center 42%}
.hero__media::after{
  content:"";position:absolute;inset:0;
  background:
    linear-gradient(to top,var(--ink-900) 2%,rgba(11,14,10,.72) 36%,rgba(11,14,10,.22) 72%,rgba(11,14,10,.40) 100%),
    linear-gradient(to right,rgba(11,14,10,.68),rgba(11,14,10,0) 62%);
}

@media (max-width:760px){
  /* single-column hero: drop the side scrim so the vehicle stays visible */
  .hero__media::after{
    background:linear-gradient(to top,var(--ink-900) 1%,rgba(11,14,10,.80) 38%,rgba(11,14,10,.18) 78%,rgba(11,14,10,.30) 100%);
  }
}

.hero__in{position:relative;z-index:var(--z-base);width:100%;padding-block:clamp(3rem,8vw,6.5rem)}
/* width lives on the single .hero__copy rule in section 26 */
.hero h1{font-size:var(--d-4);letter-spacing:-.015em}
.hero__sub{color:var(--fg-muted);font-size:var(--t-lg);max-width:38rem}
.hero__cta{display:flex;flex-wrap:wrap;gap:var(--s-3)}

/* service strip under the hero */
.hero__strip{
  position:relative;z-index:var(--z-base);
  border-top:1px solid var(--line);background:rgba(8,11,7,.6);
}
.hero__strip ul{
  display:grid;grid-template-columns:repeat(3,1fr);
  max-width:var(--maxw);margin-inline:auto;
}
.hero__strip li + li{border-left:1px solid var(--line)}
.hero__strip a{display:flex;flex-direction:column;gap:.3rem;padding:var(--s-5) var(--pad);transition:background var(--t-fast) var(--e)}
.hero__strip a:hover{background:var(--brand-wash)}
.hero__strip .k{font-family:var(--display);font-weight:700;font-size:1.35rem;text-transform:uppercase;letter-spacing:.015em}
.hero__strip a{min-height:44px}
.hero__strip .v{font-family:var(--label);font-size:.75rem;font-weight:700;letter-spacing:.14em;text-transform:uppercase;color:var(--fg-dim)}
@media (max-width:760px){
  .hero__strip ul{grid-template-columns:1fr}
  .hero__strip li + li{border-left:0;border-top:1px solid var(--line)}
  .hero__strip a{padding-block:var(--s-4)}
}

/* ---------- 9. Service panels (asymmetric, not three equal cards) -------- */

.panels{display:grid;grid-template-columns:1.4fr 1fr;gap:1px;background:var(--line);border:1px solid var(--line)}
.panel{position:relative;background:var(--ink-850);overflow:hidden;display:flex;flex-direction:column;justify-content:flex-end;min-height:22rem;padding:clamp(1.5rem,2.6vw,2.5rem)}
.panel--tall{grid-row:span 2;min-height:34rem}
.panel__img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;opacity:.46;transition:transform var(--t-slow) var(--e),opacity var(--t-slow) var(--e)}
.panel::after{content:"";position:absolute;inset:0;background:linear-gradient(to top,rgba(8,11,7,.96) 10%,rgba(8,11,7,.6) 52%,rgba(8,11,7,.25))}
/* the background image must stay absolute, so exclude it here */
.panel > :not(.panel__img){position:relative;z-index:var(--z-base)}
.panel:hover .panel__img{transform:scale(1.04);opacity:.58}
.panel h3{font-size:clamp(1.5rem,2.4vw,2.1rem);margin-bottom:var(--s-3)}
.panel--tall h3{font-size:clamp(1.9rem,3.2vw,2.8rem)}
.panel p{color:var(--fg-muted);font-size:var(--t-sm);max-width:38ch}
.panel__tag{font-family:var(--label);font-size:.75rem;font-weight:700;letter-spacing:.16em;text-transform:uppercase;color:var(--brand-txt);margin-bottom:var(--s-3)}
.panel__links{display:flex;gap:var(--s-5);align-items:center;margin-top:var(--s-5);padding-top:var(--s-4);border-top:1px solid var(--line)}
@media (max-width:900px){
  .panels{grid-template-columns:1fr}
  .panel--tall{grid-row:auto;min-height:24rem}
}

/* ---------- 10. Editorial band (full bleed image + copy) ----------------- */

.band{position:relative;min-height:min(80dvh,760px);display:flex;align-items:flex-end;overflow:hidden}
.band img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;object-position:center 40%}
.band::after{content:"";position:absolute;inset:0;background:linear-gradient(to top,var(--ink-900) 3%,rgba(11,14,10,.74) 42%,rgba(11,14,10,.3))}
.band__in{position:relative;z-index:var(--z-base);padding-block:clamp(3rem,7vw,6rem);display:flex;flex-direction:column;gap:var(--s-4);max-width:48rem}

/* ---------- 11. Threat list (numbered rows, grouped) --------------------- */

.threats{display:grid;grid-template-columns:repeat(3,1fr);gap:1px;background:var(--line);border-block:1px solid var(--line)}
.threat{background:var(--ink-900);padding:clamp(1.5rem,2.5vw,2.25rem);display:flex;flex-direction:column;gap:var(--s-3)}
.threat h3{font-size:var(--t-lg);letter-spacing:.015em}
.threat p{color:var(--fg-muted);font-size:var(--t-sm)}
.threats--4{grid-template-columns:repeat(4,1fr)}
@media (max-width:1000px){ .threats--4{grid-template-columns:repeat(2,1fr)} }
@media (max-width:900px){ .threats{grid-template-columns:repeat(2,1fr)} }
@media (max-width:560px){ .threats,.threats--4{grid-template-columns:1fr} }

/* ---------- 12. Coverage visualiser -------------------------------------- */

.cov{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1.05fr);gap:clamp(2rem,4vw,4rem);align-items:center}
/* Headings in the .cov column sit in roughly half the page width, so the full
   display size turned a 61-character line into five lines of type. One step
   down fits it in three without changing the hierarchy. */
.cov .d2{font-size:var(--d-1)}
@media (max-width:940px){ .cov{grid-template-columns:1fr} }

.cov__stage{
  background:
    radial-gradient(120% 90% at 50% 0%,rgba(141,198,63,.07),transparent 60%),
    var(--ink-850);
  border:1px solid var(--line);padding:clamp(1rem,2.5vw,2rem);
}
/* media shown in a .cov slot without the panel treatment */
.cov__media{align-self:center}
.cov__media img{width:100%}

.cov__stage svg{width:100%;height:auto;max-height:60vh;margin-inline:auto}

/* His coverage renders are artwork on white. Framing them on a light panel
   keeps them legible without inverting the page theme. */
.cov__plate{background:#F2F4EF;border:1px solid var(--line);padding:clamp(.75rem,2vw,1.5rem);position:relative}
.cov__plate img{width:100%;height:auto;display:block;color:transparent} /* no alt spill while a retry is pending */
.cov__plate figcaption{position:absolute;left:0;bottom:0;padding:.5rem .85rem;
  font-family:var(--mono);font-size:10px;letter-spacing:.14em;text-transform:uppercase;color:#4A5442}
.cov__key{display:flex;gap:var(--s-5);flex-wrap:wrap;margin-top:var(--s-4);
  font-family:var(--mono);font-size:var(--t-xs);letter-spacing:.1em;text-transform:uppercase;color:var(--fg-dim)}
.cov__key i{display:inline-block;width:12px;height:12px;margin-right:.5rem;vertical-align:-1px}
.cov__key .sw-on{background:#5BBF3B}
.cov__key .sw-off{background:#2C4A78}

.car-zone{fill:var(--ink-600);stroke:rgba(236,241,230,.13);stroke-width:1.2;
  transition:fill var(--t-mid) var(--e),stroke var(--t-mid) var(--e)}
.car-zone.is-on{fill:var(--brand);stroke:var(--brand-bright)}
.car-glass{fill:#0E1A22;stroke:rgba(236,241,230,.13);stroke-width:1.2;
  transition:fill var(--t-mid) var(--e),stroke var(--t-mid) var(--e)}
.car-glass.is-on{fill:#2A4A5C;stroke:var(--brand)}
.car-trim{fill:none;stroke:rgba(236,241,230,.18);stroke-width:1.2}
@media (prefers-reduced-motion:reduce){ .car-zone,.car-glass{transition:none} }

.cov__legend{display:flex;gap:var(--s-5);flex-wrap:wrap;margin-top:var(--s-4);
  font-family:var(--mono);font-size:var(--t-xs);letter-spacing:.1em;text-transform:uppercase;color:var(--fg-dim)}
.cov__legend i{display:inline-block;width:12px;height:12px;margin-right:.5rem;vertical-align:-1px}
.cov__legend .sw-on{background:var(--brand)}
.cov__legend .sw-off{background:var(--ink-600);border:1px solid var(--line-2)}

.pk-list{display:flex;flex-direction:column;gap:1px;background:var(--line);border:1px solid var(--line)}
.pk{
  background:var(--ink-850);padding:clamp(1.15rem,2vw,1.6rem) clamp(1.15rem,2vw,1.75rem);
  display:grid;grid-template-columns:auto 1fr auto;gap:var(--s-4);align-items:start;
  cursor:pointer;text-align:left;border:0;width:100%;
  transition:background var(--t-fast) var(--e);
}
.pk:hover{background:var(--ink-800)}
.pk[aria-pressed="true"]{background:var(--ink-800);box-shadow:inset 3px 0 0 var(--brand)}
.on-dark .pk[aria-pressed="true"]{background:var(--brand-wash)}
.pk__dot{width:14px;height:14px;margin-top:.45rem;border:1px solid var(--line-2);border-radius:50%;
  transition:border-color var(--t-fast) var(--e),background-color var(--t-fast) var(--e),box-shadow var(--t-fast) var(--e)}
.pk[aria-pressed="true"] .pk__dot{border-color:var(--brand-txt);background:var(--brand);box-shadow:inset 0 0 0 3px var(--ink-850)}
.pk__name{font-family:var(--display);font-weight:700;font-size:1.25rem;letter-spacing:.015em;text-transform:uppercase;display:block}
.pk__cov{color:var(--fg-muted);font-size:var(--t-sm);display:block;margin-top:.15rem}
a.pk__cov{display:inline-flex;align-items:center;min-height:44px}
.pk__flag{white-space:nowrap;font-family:var(--label);font-size:.7rem;font-weight:600;letter-spacing:.14em;text-transform:uppercase;
  color:var(--brand-ink);background:var(--brand);padding:.28rem .55rem}
@media (max-width:560px){
  .pk{grid-template-columns:auto 1fr;gap:var(--s-3)}
  .pk__flag{grid-column:2;justify-self:start;margin-top:var(--s-2)}
}


/* ---------- 13. Add-on grid ---------------------------------------------- */

.addons{display:grid;grid-template-columns:repeat(auto-fit,minmax(15rem,1fr));gap:1px;background:var(--line);border:1px solid var(--line)}
.addon{background:var(--ink-850);padding:clamp(1.25rem,2.2vw,1.9rem);display:flex;flex-direction:column;gap:var(--s-2)}
.addon h3{font-size:var(--t-lg)}
.addon .cvg{font-family:var(--mono);font-size:var(--t-xs);letter-spacing:.1em;text-transform:uppercase;color:var(--brand-txt)}
.addon p{color:var(--fg-muted);font-size:var(--t-sm);max-width:52ch}

/* ---------- 14. Estimator ------------------------------------------------ */

.est{border:1px solid var(--line);background:var(--ink-850)}
.est__bar{display:flex;gap:0;border-bottom:1px solid var(--line);overflow-x:auto;scrollbar-width:none}
.est__bar::-webkit-scrollbar{display:none}
.est__step{
  flex:1 0 auto;min-width:8.5rem;padding:var(--s-4) var(--s-4);
  display:flex;align-items:center;gap:var(--s-3);
  font-family:var(--mono);font-size:var(--t-xs);letter-spacing:.1em;text-transform:uppercase;
  color:var(--fg-dim);background:transparent;border:0;border-bottom:2px solid transparent;
  cursor:pointer;white-space:nowrap;transition:color var(--t-fast),border-color var(--t-fast)
}
.est__step:hover:not([disabled]){color:var(--fg-muted)}
.est__step[aria-current="step"]{color:var(--brand-txt);border-bottom-color:var(--brand-txt)}
.est__step[data-done="true"]{color:var(--fg-muted)}
.est__step[disabled]{cursor:not-allowed;opacity:.4}
.est__num{font-variant-numeric:tabular-nums}

.est__body{padding:clamp(1.5rem,3vw,2.75rem)}
.est__pane{display:none;flex-direction:column;gap:var(--s-6)}
.est__pane.is-active{display:flex}
@media (prefers-reduced-motion:no-preference){
  .est__pane.is-active{animation:paneIn var(--t-mid) var(--e) both}
  /* Steps run left to right in the bar above, so the panes should travel that
     way too: forward enters from the right, back from the left. The outgoing
     pane is display:none and cannot animate, so the incoming one carries the
     movement on its own. */
  [data-estimator][data-dir="fwd"]  .est__pane.is-active{animation:paneNext 260ms cubic-bezier(.25,1,.5,1) both}
  [data-estimator][data-dir="back"] .est__pane.is-active{animation:panePrev 260ms cubic-bezier(.25,1,.5,1) both}
}
@keyframes paneIn{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}}
@keyframes paneNext{from{opacity:0;transform:translate3d(26px,0,0)}to{opacity:1;transform:none}}
@keyframes panePrev{from{opacity:0;transform:translate3d(-26px,0,0)}to{opacity:1;transform:none}}

.est__foot{display:flex;justify-content:space-between;gap:var(--s-4);
  padding:var(--s-5) clamp(1.5rem,3vw,2.75rem);border-top:1px solid var(--line);flex-wrap:wrap}

.field{display:flex;flex-direction:column;gap:var(--s-2)}
.field > label,.field > .lab{font-family:var(--mono);font-size:var(--t-xs);letter-spacing:.14em;
  text-transform:uppercase;color:var(--fg-muted)}
.field .help{font-size:var(--t-sm);color:var(--fg-dim)}
.field .err{font-size:var(--t-sm);color:var(--err);display:none}
.field.is-invalid .err{display:block}

.input,select.input,textarea.input{
  width:100%;padding:.85rem 1rem;background:var(--ink-900);
  border:1px solid var(--line-2);border-radius:var(--r-1);color:var(--fg);
  transition:border-color var(--t-fast) var(--e),background var(--t-fast) var(--e);
}
.input::placeholder{color:var(--fg-dim)}
.input:hover{border-color:rgba(236,241,230,.26)}
.input:focus{border-color:var(--brand-txt);background:var(--ink-850)}
/* keyboard focus keeps a real ring; pointer focus gets the quieter border
   treatment above, which is what the outline:none here used to remove for
   everyone. */
.input:focus-visible{outline:2px solid var(--brand);outline-offset:2px}
.field.is-invalid .input{border-color:var(--err)}
textarea.input{min-height:7rem;resize:vertical}
select.input{appearance:none;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='8' fill='none' stroke='%239AA491' stroke-width='1.5'%3E%3Cpath d='M1 1l5 5 5-5'/%3E%3C/svg%3E");
  background-repeat:no-repeat;background-position:right 1rem center;padding-right:2.5rem}

.grid-2{display:grid;grid-template-columns:repeat(2,1fr);gap:var(--s-4)}
.grid-3{display:grid;grid-template-columns:repeat(3,1fr);gap:var(--s-4)}
@media (max-width:640px){ .grid-2,.grid-3{grid-template-columns:1fr} }

.opt-row{display:flex;flex-wrap:wrap;gap:var(--s-3)}

.svc-pick{display:grid;grid-template-columns:repeat(3,1fr);gap:var(--s-3)}
@media (max-width:720px){ .svc-pick{grid-template-columns:1fr} }
.svc-opt{
  display:flex;flex-direction:column;gap:var(--s-2);text-align:left;
  padding:var(--s-5);background:var(--ink-900);border:1px solid var(--line-2);
  border-radius:var(--r-1);cursor:pointer;
  transition:border-color var(--t-fast) var(--e),background-color var(--t-fast) var(--e),transform 120ms var(--e-enter);
}
.svc-opt:hover{border-color:rgba(236,241,230,.3)}
.svc-opt[aria-pressed="true"]{border-color:var(--brand-txt);background:var(--brand-wash)}
.svc-opt .n{font-weight:600}
.svc-opt .d{font-size:var(--t-sm);color:var(--fg-muted)}
.svc-opt .tick{font-family:var(--mono);font-size:var(--t-xs);color:var(--brand-txt);opacity:0;transition:opacity var(--t-fast)}
.svc-opt[aria-pressed="true"] .tick{opacity:1}

.summary{display:flex;flex-direction:column;gap:1px;background:var(--line);border:1px solid var(--line)}
.summary__row{background:var(--ink-900);padding:var(--s-4) var(--s-5);display:flex;justify-content:space-between;gap:var(--s-4);flex-wrap:wrap}
.summary__row .k{color:var(--fg-muted);font-size:var(--t-sm)}
.summary__row .v{font-weight:600;text-align:right}
.summary__empty{background:var(--ink-900);padding:var(--s-5);color:var(--fg-dim);font-size:var(--t-sm)}

.quote-note{border-left:2px solid var(--brand);padding:var(--s-4) var(--s-5);background:var(--brand-wash)}
.quote-note .h{font-weight:600;margin-bottom:var(--s-2)}
.quote-note p{font-size:var(--t-sm);color:var(--fg-muted)}

.disclaimer{font-size:var(--t-xs);color:var(--fg-dim);max-width:70ch;line-height:1.55}

.form-status{padding:var(--s-4) var(--s-5);border:1px solid var(--line-2);border-radius:var(--r-1);display:none}
.form-status.is-ok{display:block;border-color:var(--ok);background:rgba(127,201,127,.1)}
.form-status.is-err{display:block;border-color:var(--err);background:rgba(226,104,95,.1)}

/* ---------- 15. Gallery -------------------------------------------------- */

.gal-filters{display:flex;gap:var(--s-3);flex-wrap:wrap;margin-bottom:var(--s-6)}

/* A real grid, not CSS columns. Columns gave every tile the photograph's own
   height, so the wall was a jumble. Uniform cells with `object-fit:contain`
   means one size everywhere and nothing cropped: the matte around a picture is
   the mount, not a mistake. Landscape shots get a double-wide cell so the
   widest one is not left as a strip. */
.gal{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:var(--s-4)}
.gal__item{
  position:relative;aspect-ratio:4/5;
  background:var(--ink-850);border:1px solid var(--line);overflow:hidden;
  width:100%;padding:0;cursor:zoom-in;display:block;text-align:left;
}


/* After the base rules, not before: same specificity means source order
   decides, and the narrow-screen span was being cancelled by the desktop one. */
@media (max-width:960px){ .gal{grid-template-columns:repeat(2,minmax(0,1fr))} }
@media (max-width:560px){
  .gal{grid-template-columns:minmax(0,1fr);gap:var(--s-3)}
}
.gal__item img{
  width:100%;height:100%;object-fit:cover;display:block;
  object-position:50% 50%;               /* per-photo focal point overrides inline */
  transition:transform var(--t-slow) var(--e-enter),opacity var(--t-slow) var(--e);
}
.gal__item:hover img{transform:scale(1.04)}
.gal__cap{position:absolute;left:0;right:0;bottom:0;padding:var(--s-5) var(--s-4) var(--s-4);
  background:linear-gradient(to top,rgba(8,11,7,.94),rgba(8,11,7,0));
  opacity:0;transform:translateY(6px);transition:opacity var(--t-mid) var(--e),transform var(--t-mid) var(--e)}
.gal__item:hover .gal__cap,.gal__item:focus-visible .gal__cap{opacity:1;transform:none}
.gal__cap .t{font-weight:600;font-size:var(--t-sm)}
.gal__cap .n{color:var(--fg-muted);font-size:var(--t-xs)}
.gal__item.is-hidden{display:none}
@media (prefers-reduced-motion:reduce){
  .gal__item img{transition:none} .gal__item:hover img{transform:none}
  .gal__cap{opacity:1;transform:none}
}

/* rail variant used on the homepage */
.rail{display:grid;grid-auto-flow:column;grid-auto-columns:minmax(16rem,22rem);
  gap:1px;background:var(--line);border-block:1px solid var(--line);
  overflow-x:auto;scroll-snap-type:x mandatory;overscroll-behavior-x:contain}
.rail figure{position:relative;scroll-snap-align:start;background:var(--ink-850);margin:0}
.rail img{width:100%;aspect-ratio:3/4;object-fit:cover}
.rail figcaption{position:absolute;inset:auto 0 0 0;padding:var(--s-6) var(--s-4) var(--s-4);
  background:linear-gradient(to top,rgba(8,11,7,.95),transparent);font-size:var(--t-sm);font-weight:600}

/* lightbox */
.lb{position:fixed;inset:0;z-index:var(--z-modal);background:rgba(6,9,5,.96);
  display:none;align-items:center;justify-content:center;padding:var(--s-5)}
.lb[open],.lb.is-open{display:flex}
.lb__img{max-width:min(94vw,1100px);max-height:84dvh;object-fit:contain}
.lb__cap{position:absolute;left:0;right:0;bottom:var(--s-5);text-align:center;color:var(--fg-muted);font-size:var(--t-sm)}
.lb__btn{position:absolute;background:transparent;border:1px solid var(--line-2);border-radius:var(--r-1);
  width:48px;height:48px;display:grid;place-items:center;cursor:pointer;color:var(--fg);
  transition:border-color var(--t-fast),color var(--t-fast)}
.lb__btn:hover{border-color:var(--brand-txt);color:var(--brand-txt)}
.lb__close{top:var(--s-5);right:var(--s-5)}
.lb__prev{left:var(--s-5);top:50%;transform:translateY(-50%)}
.lb__next{right:var(--s-5);top:50%;transform:translateY(-50%)}
@media (max-width:640px){
  .lb__prev{left:var(--s-3)} .lb__next{right:var(--s-3)}
  .lb__btn{width:42px;height:42px}
}

/* ---------- 16. Process -------------------------------------------------- */

.steps{display:grid;grid-template-columns:repeat(5,1fr);gap:1px;background:var(--line);border:1px solid var(--line)}
.step{background:var(--ink-850);padding:clamp(1.25rem,2.2vw,1.9rem);display:flex;flex-direction:column;gap:var(--s-3)}
.step .n{font-family:var(--mono);font-size:var(--t-xs);color:var(--brand-txt);letter-spacing:.14em}
.step h3{font-size:var(--t-base);letter-spacing:.02em}
.step p{color:var(--fg-muted);font-size:var(--t-sm)}
.steps--4{grid-template-columns:repeat(4,1fr)}
@media (max-width:1000px){ .steps,.steps--4{grid-template-columns:repeat(2,1fr)} }
@media (max-width:560px){ .steps,.steps--4{grid-template-columns:1fr} }

/* ---------- 17. Trust ---------------------------------------------------- */

.trust{display:grid;grid-template-columns:repeat(auto-fit,minmax(12.5rem,1fr));gap:var(--s-6);margin-top:var(--s-7)}
.trust > div{display:flex;flex-direction:column;gap:var(--s-2);padding-top:var(--s-4);border-top:1px solid var(--brand-line)}
.trust h3{font-size:var(--t-base)}
.trust p{color:var(--fg-muted);font-size:var(--t-sm)}
@media (max-width:900px){ .trust{grid-template-columns:repeat(2,1fr)} }
@media (max-width:520px){ .trust{grid-template-columns:1fr} }

/* ---------- 18. FAQ ------------------------------------------------------ */

.faq{border-top:1px solid var(--line)}
.faq details{border-bottom:1px solid var(--line)}
.faq summary{
  display:flex;justify-content:space-between;align-items:center;gap:var(--s-4);
  padding:var(--s-5) 0;cursor:pointer;font-family:var(--display);font-weight:700;font-size:1.5rem;
  letter-spacing:.01em;text-transform:uppercase;list-style:none;
}
.faq summary::-webkit-details-marker{display:none}
.faq summary::after{content:"";width:12px;height:12px;flex:0 0 auto;
  border-right:1.5px solid var(--brand);border-bottom:1.5px solid var(--brand);
  transform:rotate(45deg) translateY(-3px);transition:transform var(--t-mid) var(--e)}
.faq details[open] summary::after{transform:rotate(-135deg) translateY(-3px)}
.faq summary:hover{color:var(--brand-txt)}
.faq .a{padding:0 0 var(--s-5);color:var(--fg-muted);max-width:var(--measure)}

/* ---------- 19. Final CTA ------------------------------------------------ */

.cta{position:relative;overflow:hidden;border-top:1px solid var(--line)}
.cta img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;object-position:center 42%}
.cta::after{content:"";position:absolute;inset:0;background:linear-gradient(to right,rgba(8,11,7,.95) 12%,rgba(8,11,7,.72) 58%,rgba(8,11,7,.5))}
.cta__in{position:relative;z-index:var(--z-base);padding-block:clamp(3.25rem,6.6vw,5.75rem);
  display:flex;flex-direction:column;gap:var(--s-5);max-width:44rem}

/* ---------- 20. Footer --------------------------------------------------- */

.footer{border-top:1px solid var(--line);background:var(--ink-950)}
.footer__grid{display:grid;grid-template-columns:1.4fr 1fr 1fr 1.2fr;gap:var(--s-6);
  padding-block:clamp(3rem,6vw,5rem)}
.footer h2,.footer h3{font-family:var(--mono);font-size:var(--t-xs);letter-spacing:.16em;
  text-transform:uppercase;color:var(--brand-txt);font-weight:500;margin-bottom:var(--s-4)}
.footer li + li{margin-top:var(--s-2)}
/* padding keeps the tap target at or above the WCAG 2.2 minimum of 24px */
.footer a{display:inline-flex;align-items:center;min-height:44px;padding-block:.3rem;color:var(--fg-muted);font-size:var(--t-sm);transition:color var(--t-fast)}
.footer a:hover{color:var(--brand-txt)}
.footer p{color:var(--fg-muted);font-size:var(--t-sm)}
/* width:auto is load-bearing: logoFor() emits width="140" height="87" for CLS,
   and setting only CSS height leaves that width attribute in force, which
   stretched the badge to 140x44 against its natural 1.609 ratio. */
.footer__logo img{height:44px;width:auto;margin-bottom:var(--s-4)}
.footer__bar{border-top:1px solid var(--line);padding-block:var(--s-5);
  display:flex;justify-content:space-between;gap:var(--s-4);flex-wrap:wrap;
  font-size:var(--t-xs);color:var(--fg-dim)}
@media (max-width:900px){ .footer__grid{grid-template-columns:repeat(2,1fr)} }
@media (max-width:540px){ .footer__grid{grid-template-columns:1fr} }

/* ---------- 21. Mobile sticky action bar --------------------------------- */

.sticky-bar{
  /* Two different actions sat 1px apart: one dials the shop, the other opens
     the estimator. On a phone that is a real mis-tap, and the wrong tap places
     a phone call. They are now a tray of two separate buttons with a 10px gap,
     clear of the 8px touch-spacing minimum. */
  position:fixed;left:0;right:0;bottom:0;z-index:var(--z-sticky);display:none;
  /* auto 1fr, not 1fr 1fr: an even split gave "Call" 145px for four characters
     while the primary CTA wrapped to two lines and pushed both buttons to 81px
     tall on a 320px screen. */
  grid-template-columns:auto 1fr;gap:10px;background:var(--ink-900);
  border-top:1px solid var(--line-2);
  padding:8px 10px calc(8px + env(safe-area-inset-bottom));
  transform:translateY(110%);transition:transform var(--t-mid) var(--e);
}
.sticky-bar.is-up{transform:none}
.sticky-bar a{padding:.85rem 1rem;border-radius:var(--r-1);text-align:center;font-family:var(--display);font-size:1.05rem;font-weight:700;text-transform:uppercase;letter-spacing:.03em;background:var(--ink-850)}
.sticky-bar a.primary{background:var(--brand);color:var(--brand-ink)}
@media (max-width:820px){ .sticky-bar{display:grid} body{padding-bottom:0} }
/* Archivo Black is wide: at 320px the primary label still broke onto a second
   line inside its 207px column. Slightly tighter type and padding on the
   narrowest phones keeps it on one line. */
@media (max-width:360px){
  .sticky-bar a{padding:.85rem .55rem;font-size:.95rem;letter-spacing:.01em}
}
@media (prefers-reduced-motion:reduce){ .sticky-bar{transition:none} }

/* ---------- 22. Scroll reveal -------------------------------------------- */

@media (prefers-reduced-motion:no-preference){
  .rv{opacity:0;transform:translateY(16px);
      transition:opacity var(--t-slow) var(--e),transform var(--t-slow) var(--e-enter)}
  .rv.is-in{opacity:1;transform:none}
  /* gallery tiles stagger in individually */
  .rv-tile{opacity:0;transform:translateY(14px);
      transition:opacity var(--t-mid) var(--e-enter),transform var(--t-mid) var(--e-enter)}
  .rv-tile.is-in{opacity:1;transform:none}
  .rv-d1{transition-delay:70ms} .rv-d2{transition-delay:140ms} .rv-d3{transition-delay:210ms}
}

@media (prefers-reduced-motion:reduce){
  .rv,.rv-tile{opacity:1;transform:none;transition:none}
}

/* Hard-shown state. The fallback timer applies this instead of relying on a
   transition running, so content is visible even where transitions never
   execute (hidden tab, some webviews, reduced-power modes). */
.rv.is-shown,.rv-tile.is-shown{opacity:1 !important;transform:none !important;transition:none !important}

/* ---------- 23. 404 ------------------------------------------------------ */

.nf{min-height:70dvh;display:flex;flex-direction:column;justify-content:center;gap:var(--s-5)}

/* ---------- 24. Small utilities (replace one-off inline styles) ---------- */
.pb-sec{padding-bottom:var(--sec)}
.mt-4{margin-top:var(--s-4)}
.mt-5{margin-top:var(--s-5)}
.mt-6{margin-top:var(--s-6)}
.mt-7{margin-top:var(--s-7)}
.mb-4{margin-bottom:var(--s-4)}
.mb-5{margin-bottom:var(--s-5)}
.link-brand{color:var(--brand-txt)}
.link-brand:hover{color:var(--brand-txt)}
/* static info rows reuse the .pk shell without the button affordance */
.pk--static{cursor:default}
.pk--static:hover{background:var(--ink-850)}

/* ---------- 25. Motion layer ----------------------------------------------
   Transform and opacity only. Every hover enhancement is gated behind a real
   pointer so touch devices never latch a hover state after a tap.
   -------------------------------------------------------------------------- */

@media (hover:hover) and (pointer:fine){

  /* buttons lift very slightly, then press back in */
  .btn{transition:background-color var(--t-hover) ease,border-color var(--t-hover) ease,
                 color var(--t-hover) ease,transform var(--t-press) var(--e-enter)}
  .btn--primary:hover,.btn--ghost:hover{transform:translateY(-2px)}
  .btn:active{transform:translateY(0)}

  /* service panels: image pushes in, copy lifts, brand rule draws across */
  .panel{transition:transform var(--t-mid) var(--e-enter)}
  .panel__links{position:relative}
  .panel__links::before{
    content:"";position:absolute;top:-1px;left:0;right:0;height:1px;background:var(--brand);
    transform:scaleX(0);transform-origin:left center;
    transition:transform var(--t-slow) var(--e-enter);
  }
  .panel:hover .panel__links::before{transform:scaleX(1)}

  /* gallery tiles */
  .gal__item{transition:transform var(--t-mid) var(--e-enter),border-color var(--t-hover) ease}
  .gal__item:hover{transform:translateY(-4px);border-color:var(--brand)}

  /* rail cards */
  .rail figure{overflow:hidden}
  .rail img{transition:transform var(--t-slow) var(--e-enter)}
  .rail figure:hover img{transform:scale(1.04)}

  /* package rows slide a touch toward the pointer */
  .pk{transition:background-color var(--t-fast) var(--e),transform var(--t-fast) var(--e-enter)}
  .pk:hover{transform:translateX(3px)}
  .pk[aria-pressed="true"]:hover{transform:none}

  /* threat and step cells warm up */
  .threat,.step,.addon{transition:background-color var(--t-hover) ease}
  .threat:hover,.step:hover,.addon:hover{background:var(--ink-800)}

  /* footer links nudge */
  .footer a{transition:color var(--t-fast) ease,transform var(--t-fast) var(--e-enter)}
  .footer a:hover{transform:translateX(2px)}

  .chip:hover,.svc-opt:hover{transform:translateY(-1px)}
  .chip:active,.svc-opt:active{transform:translateY(0)}
}

/* the sticky bar and nav respond to scroll direction, not to hover */
.nav{transition:background-color var(--t-mid) var(--e),box-shadow var(--t-mid) var(--e)}
.nav.is-stuck{box-shadow:var(--sh-2)}



@media (prefers-reduced-motion:reduce){
}

/* ---------- 26. Mobile hero --------------------------------------------
   A 16:9 crop in a tall phone viewport over-zooms, and the shop wall behind
   the copy is busy. Shorter hero, a scrim anchored to the text block only,
   and the two CTAs share a row instead of stacking.
   ------------------------------------------------------------------------ */

@media (max-width:760px){
  .hero{min-height:min(76dvh,600px)}
  .hero--short{min-height:calc(100dvh - var(--nav-h))}

  .hero__in{padding-block:clamp(2rem,6vw,3rem)}
  .hero__copy{gap:var(--s-4)}

  .hero h1{font-size:clamp(2.4rem,10vw,3.4rem);letter-spacing:-.005em}
  .hero__sub{font-size:1.0625rem;max-width:30ch}
  .eyebrow{font-size:.6875rem;letter-spacing:.18em}

  /* full-bleed legibility scrim: weighted to the lower half where the copy
     sits, so the vehicle above stays visible and there is no vertical seam */
  .hero__media::after{
    background:linear-gradient(to top,
      var(--ink-900) 2%,
      rgba(11,14,10,.90) 30%,
      rgba(11,14,10,.45) 55%,
      rgba(11,14,10,.10) 80%,
      rgba(11,14,10,.28) 100%);
  }

  /* CTAs side by side; they fit at these labels */
  .hero__cta{flex-wrap:nowrap;gap:var(--s-3)}
  .hero__cta .btn{flex:1 1 0;min-width:0;padding-inline:.75rem;font-size:.9375rem}

  .section{padding-block:clamp(3rem,8vw,4.5rem)}
  .sec-head{margin-bottom:var(--s-6)}
  .lede{font-size:1.0625rem}
}

@media (max-width:380px){
  .hero h1{font-size:2.15rem}
  .hero__cta .btn{font-size:.875rem;padding-inline:.6rem}
}

/* ==========================================================================
   27. SIGNATURE COMPONENTS
   --------------------------------------------------------------------------
   Deliberately none of the moves used on the Unlimited Collision build:
   no marquee, no custom cursor, no intro wipe, no progress rail, no ghost
   numerals, no vertical-only parallax.
   ========================================================================== */

/* ---------- 27a. Editorial split hero with inline typographic images ------ */

.hero--full{
  position:relative;isolation:isolate;overflow:hidden;
  /* fills the viewport under the bar: an 820px cap left a strip of the
     light band showing before anyone had scrolled */
  min-height:calc(100dvh - var(--nav-h));display:flex;align-items:flex-end;
}
.hero__bg{position:absolute;inset:0;z-index:0}
/* The source is a bright daylight shot: blown sky at the top right, pale
   pavement bottom right, against a near-black grille. Pulling the highlights
   down and desaturating the warm cast lets it sit in a dark green/black
   palette instead of fighting it. */
.hero__bg img{
  width:100%;height:100%;object-fit:cover;object-position:center 46%;display:block;
  /* The colour grade is baked into the file. It used to be a CSS filter, but a
     filter on the element that is also being transform-animated pushes the
     animation off the compositor and onto the main thread, which is what made
     the drift step like a slideshow. */
  transform:scale(1.08);
}

/* Scrim sits on the section, above the artwork wrapper, so the sweep inside
   .hero__bg passes UNDER it and never glows over the copy. */
.hero--full::after{
  content:"";position:absolute;inset:0;z-index:1;pointer-events:none;
  background:
    /* A pool anchored under the copy, so the type has weight without the whole
       frame going flat. */
    radial-gradient(118% 125% at 3% 80%,
      rgba(11,14,10,.96) 0%,rgba(11,14,10,.88) 34%,rgba(11,14,10,.46) 62%,rgba(11,14,10,0) 84%),
    /* Vertical: knocks the blown sky down at the top and lands on solid ink at
       the bottom, so the hero resolves into the band edge with no seam. */
    linear-gradient(to bottom,
      rgba(11,14,10,.42) 0%,rgba(11,14,10,.14) 22%,rgba(11,14,10,.08) 46%,
      rgba(11,14,10,.58) 78%,var(--ink-900) 99%),
    /* Horizontal: heavy on the copy side, and a lift back up on the far right
       to take the pale pavement out of the corner. Softened 2026-09-03: the
       three scrims stacked took the photograph from mean luminance 94 down to
       30, so the car was a silhouette on the one page every visitor sees. The
       radial pool above still carries the type contrast. */
    linear-gradient(to right,
      rgba(11,14,10,.72) 0%,rgba(11,14,10,.28) 32%,rgba(11,14,10,0) 60%,rgba(11,14,10,.14) 100%);
}
.hero__in{position:relative;z-index:2;width:100%;padding-block:clamp(3rem,9vw,6rem)}
.hero__copy{display:flex;flex-direction:column;gap:var(--s-5);max-width:53rem}
/* Inner-page heroes carry longer headlines than the home page's three stacked
   words. At 53rem a 27-character line could not fit two words at display size
   and broke one word per line - four lines for a six-word headline. */
.hero--short .hero__copy{max-width:60rem}

/* the H1 is the page. Ultra-wide, 2 lines, never a text wall. */
.hero__line{
  font-family:var(--display);font-weight:700;text-transform:uppercase;
  font-size:clamp(2.6rem,6.4vw,6.4rem);line-height:.96;letter-spacing:-.012em;
  max-width:22ch;margin:0;
}

/* ---- hero motion -------------------------------------------------------
   Three separate jobs, all transform/opacity so they stay on the compositor:
   a slow drift that keeps the still frame alive, a staggered entrance for the
   copy, and the specular sweep across the paint. All three are gated on
   reduced-motion and on the hero actually being in view. */

/* 1. drift. Baseline is already scaled up so the edges can never gap. */
@media (prefers-reduced-motion:no-preference){
  .hero--full.is-live .hero__bg img{
    will-change:transform;
    animation:heroDrift 34s cubic-bezier(.45,0,.55,1) infinite alternate;
  }
}
/* The scale is CONSTANT and only the translation moves. A changing scale makes
   the browser either re-rasterise every frame or stretch one bitmap, and over
   30s the per-frame delta is small enough that either shows as stepping. A
   pure translation at a fixed scale is a straight compositor move. */
@keyframes heroDrift{
  from{transform:scale(1.08) translate3d(-1.6%,-0.9%,0)}
  to  {transform:scale(1.08) translate3d( 1.6%, 0.9%,0)}
}

/* 2. copy entrance. The initial state lives INSIDE the keyframe, never on the
   base rule - if the script never runs, the copy is simply visible. */
@media (prefers-reduced-motion:no-preference){
  .hero--full.is-ready .hero__q{
    animation:heroQ .58s cubic-bezier(.22,1,.36,1) both;
    animation-delay:calc(var(--qi) * 50ms);
  }
}
@keyframes heroQ{
  from{opacity:0;transform:translate3d(0,15px,0)}
  to  {opacity:1;transform:none}
}
/* forced resting state once the stagger has had its time - see heroMotion() */
.hero--full.is-settled .hero__q{animation:none;opacity:1;transform:none}

/* 3. the sweep. Ceramic and PPF change how light sits on a panel, so the hero
   shows exactly that rather than borrowing anyone else's badge. */
.hero__bg::after{
  content:"";position:absolute;z-index:1;pointer-events:none;
  top:-30%;height:160%;left:0;width:34%;
  background:linear-gradient(100deg,
    rgba(255,255,255,0)   0%,
    rgba(255,255,255,.05) 26%,
    rgba(255,255,255,.34) 50%,
    rgba(255,255,255,.05) 74%,
    rgba(255,255,255,0)   100%);
  mix-blend-mode:screen;
  filter:blur(14px);
  transform:translate3d(-200%,0,0) rotate(9deg);
  opacity:0;
}
@media (prefers-reduced-motion:no-preference){
  .hero--full.is-live .hero__bg::after{
    will-change:transform,opacity;
    animation:heroSheen 9s linear infinite;
  }
}
/* Real light travels at a constant speed, and CSS applies the timing function
   to EVERY keyframe interval - so `transform` is declared on all of them at a
   uniform rate. Declaring it only at the ends while adding opacity stops in
   between made the band lurch at each stop. */
/* Wider band, softer edge, and a travel that clears both sides of the hero so
   the light crosses the whole frame rather than clipping in and out. Constant
   velocity throughout: the percentages advance at a uniform rate, because CSS
   applies the timing function to every keyframe interval. */
@keyframes heroSheen{
  0%  {transform:translate3d(-160%,0,0) rotate(9deg);opacity:0}
  5%  {transform:translate3d(-125%,0,0) rotate(9deg);opacity:1}
  50% {transform:translate3d( 190%,0,0) rotate(9deg);opacity:1}
  55% {transform:translate3d( 225%,0,0) rotate(9deg);opacity:0}
  100%{transform:translate3d( 225%,0,0) rotate(9deg);opacity:0}
}

@media (max-width:900px){
  .hero--full{min-height:calc(100dvh - var(--nav-h))}
  .hero__bg img{object-position:center 42%}
  /* The mobile override replaced the whole stack and lost the pool, which put
     the eyebrow over the bright chrome grille at 3.42:1. The pool comes back,
     re-anchored for the taller crop. */
  .hero--full::after{
    background:
      radial-gradient(155% 72% at 50% 84%,
        rgba(11,14,10,.95) 0%,rgba(11,14,10,.82) 34%,rgba(11,14,10,.32) 64%,rgba(11,14,10,0) 88%),
      linear-gradient(to bottom,
        rgba(11,14,10,.74) 0%,rgba(11,14,10,.26) 26%,rgba(11,14,10,.55) 70%,var(--ink-900) 99%);
  }
  .hero__copy{max-width:none}
  .hero__line{max-width:none;font-size:clamp(2.3rem,10.5vw,3.6rem)}
}

/* ---------- 27b. Horizontal accordion (PPF coverage) --------------------- */



/* ---------- 27c. Card stacking (the threats) ----------------------------- */

.stack-deck{position:relative}
.stack-card{
  position:sticky;top:calc(72px + var(--s-5));
  background:var(--ink-850);border:1px solid var(--line);
  padding:clamp(1.6rem,3.4vw,3rem);
  display:grid;grid-template-columns:auto 1fr;gap:clamp(1rem,3vw,2.5rem);align-items:start;
  box-shadow:0 -18px 40px -24px rgba(6,10,5,.9);
}
.stack-card + .stack-card{margin-top:var(--s-5)}
.stack-card h3{font-size:clamp(1.5rem,3vw,2.4rem)}
.stack-card p{color:var(--fg-muted);max-width:52ch;margin-top:var(--s-3)}
.stack-card .mark{
  width:clamp(2.4rem,4vw,3.4rem);height:clamp(2.4rem,4vw,3.4rem);
  border:1px solid var(--brand-line);display:grid;place-items:center;flex:0 0 auto;
}
.stack-card .mark svg{width:55%;height:55%;stroke:var(--brand);fill:none;stroke-width:1.6}
@media (max-width:640px){
  .stack-card{grid-template-columns:1fr;gap:var(--s-4)}
  .stack-card{position:static}
}
@media (prefers-reduced-motion:reduce){ .stack-card{position:static} }

/* ---------- 27d. Pinned split (title holds, content scrolls) ------------- */

.pinned{display:grid;grid-template-columns:.9fr 1.1fr;gap:clamp(2rem,5vw,5rem);align-items:start}
.pinned__hold{position:sticky;top:calc(72px + var(--s-6));display:flex;flex-direction:column;gap:var(--s-4)}
.pinned__flow{display:flex;flex-direction:column;gap:1px;background:var(--line);border:1px solid var(--line)}
.pinned__row{background:var(--ink-850);padding:clamp(1.4rem,2.6vw,2.4rem);display:flex;flex-direction:column;gap:var(--s-3)}
.pinned__row h3{font-size:clamp(1.3rem,2.2vw,1.9rem)}
.pinned__row p{color:var(--fg-muted);font-size:var(--t-sm);max-width:46ch}
@media (max-width:900px){
  .pinned{grid-template-columns:1fr}
  .pinned__hold{position:static}
}

/* ---------- 27e. Gapless bento ------------------------------------------ */

.bento{
  display:grid;grid-auto-flow:dense;
  grid-template-columns:repeat(6,1fr);
  grid-auto-rows:minmax(11rem,auto);
  gap:1px;background:var(--line);border:1px solid var(--line);
}
.bento > *{background:var(--ink-850);position:relative;overflow:hidden;
  padding:clamp(1.3rem,2.4vw,2.2rem);display:flex;flex-direction:column;justify-content:flex-end;gap:var(--s-2)}
.b-4x2{grid-column:span 4;grid-row:span 2}
.b-2x1{grid-column:span 2;grid-row:span 1}
.b-2x2{grid-column:span 2;grid-row:span 2}
.b-3x1{grid-column:span 3;grid-row:span 1}
.b-6x1{grid-column:span 6;grid-row:span 1}
.bento__img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;opacity:.42}
.bento__scrim{position:absolute;inset:0;
  background:linear-gradient(to top,rgba(8,11,7,.95) 10%,rgba(8,11,7,.55) 56%,rgba(8,11,7,.22))}
.bento > * > *{position:relative;z-index:1}
.bento h3{font-size:clamp(1.4rem,2.4vw,2.1rem)}
.bento .b-4x2 h3{font-size:clamp(1.9rem,3.4vw,3rem)}
.bento p{color:var(--fg-muted);font-size:var(--t-sm);max-width:40ch}
.bento .stat{font-family:var(--display);font-weight:700;font-size:clamp(2.4rem,5vw,4rem);
  line-height:.9;color:var(--brand-txt)}
@media (hover:hover) and (pointer:fine){
  .bento__img{transition:transform var(--t-slow) var(--e-enter),opacity var(--t-slow) var(--e-enter)}
  .bento > *:hover .bento__img{transform:scale(1.05);opacity:.55}
}
@media (max-width:980px){
  .bento{grid-template-columns:repeat(2,1fr)}
  .b-4x2,.b-6x1,.b-3x1{grid-column:span 2}
  .b-2x1,.b-2x2{grid-column:span 1;grid-row:span 1}
}
@media (max-width:560px){
  .bento{grid-template-columns:1fr}
  .b-4x2,.b-6x1,.b-3x1,.b-2x1,.b-2x2{grid-column:span 1;grid-row:span 1}
}

/* ---------- 28. Social ----------------------------------------------------
   Meta's brand guidelines allow the "f" mark in a single flat colour. It is
   rendered monochrome here so it sits inside the site's one-accent system
   instead of dropping a Facebook-blue block into it. Proportions untouched.
   -------------------------------------------------------------------------- */

.social{
  display:inline-flex;align-items:center;gap:var(--s-3);
  padding:.65rem 1.1rem;border:1px solid var(--line-2);border-radius:var(--r-1);
  color:var(--fg-muted);font-size:var(--t-sm);text-decoration:none;
  transition:border-color var(--t-fast) var(--e),color var(--t-fast) var(--e),
             background-color var(--t-fast) var(--e);
}
.social svg{width:17px;height:17px;flex:0 0 auto;fill:currentColor;display:block}
.social:hover{border-color:var(--brand-line);color:var(--brand-txt);background:var(--brand-wash)}

/* compact icon-only variant for the footer contact column */
.social--icon{padding:.55rem;width:44px;height:44px;justify-content:center}

.social-row{display:flex;align-items:center;gap:var(--s-3);flex-wrap:wrap;margin-top:var(--s-4)}
.social-row .lbl{font-family:var(--label);font-size:.75rem;font-weight:600;
  letter-spacing:.14em;text-transform:uppercase;color:var(--fg-muted)}

@media (hover:hover) and (pointer:fine){
  .social{transition:border-color var(--t-fast) var(--e),color var(--t-fast) var(--e),
                     background-color var(--t-fast) var(--e),transform var(--t-press) var(--e-enter)}
  .social:hover{transform:translateY(-1px)}
  .social:active{transform:translateY(0)}
}


/* ---------- 29. Showroom Contrast band rhythm ---------------------------- */

.band-pad{padding-block:var(--sec)}
.on-dark + .on-light,
.on-light + .on-dark{border-top:0}

/* section heads sit tighter in this direction */
.sec-head--row{
  display:flex;align-items:baseline;justify-content:space-between;gap:var(--s-6);
  max-width:none;margin-bottom:clamp(2rem,4vw,3rem);flex-wrap:wrap;
}
.sec-head--row h2{max-width:22ch}
.sec-head--row .aside{color:var(--fg-muted);font-size:var(--t-base)}

/* the three service cards on the light band */
.svc3{display:grid;grid-template-columns:repeat(3,minmax(0,1fr));gap:1px;background:var(--line);border:1px solid var(--line)}
.svc3 > article{background:var(--ink-900);padding:clamp(1.6rem,2.6vw,2.4rem);display:flex;flex-direction:column;gap:var(--s-3)}
.svc3 h3{font-size:clamp(1.35rem,2.1vw,1.75rem);letter-spacing:.015em}
.svc3 p{color:var(--fg-muted);font-size:var(--t-sm);flex:1}
.svc3 .tag{font-family:var(--label);font-size:.7rem;font-weight:600;letter-spacing:.18em;
  text-transform:uppercase;color:var(--brand-txt)}
.svc3 .more{margin-top:var(--s-3);padding-top:var(--s-4);border-top:1px solid var(--line)}
@media (max-width:900px){ .svc3{grid-template-columns:1fr} }

/* work grid on the dark band */
.workgrid{display:grid;grid-template-columns:1.6fr 1fr;gap:var(--s-3)}
.workgrid img{width:100%;height:clamp(15rem,26vw,20rem);object-fit:cover;display:block}
@media (max-width:820px){ .workgrid{grid-template-columns:1fr} }


/* ---------- 30. Photo-backed components -----------------------------------
   These carry their own dark scrim and light text, so they must NOT inherit a
   light band's tokens. Scoping the dark set onto them fixes the whole class of
   bug (the accordion read 2.77:1 sitting inside a light section).
   -------------------------------------------------------------------------- */

.rail,
.gal__item,
.panel,
.band,
.cta{
  --ink-950:#08090A;
  --ink-900:#0C0F0A;
  --ink-850:#11150E;
  --ink-800:#161B12;
  --ink-700:#1D2317;
  --ink-600:#262D1F;
  --fg:#FBFBF8;
  --fg-muted:rgba(251,251,248,.72);
  --fg-dim:rgba(251,251,248,.50);
  --line:rgba(251,251,248,.12);
  --line-2:rgba(251,251,248,.22);
  --brand-txt:#8DC63F;
  --brand-wash:rgba(141,198,63,.12);
  --brand-line:rgba(141,198,63,.34);
  color:var(--fg);
}

/* the coverage plate is deliberately a LIGHT card holding his renders, so it
   keeps light tokens even when the surrounding band is dark */
.cov__plate{color:#2A3122}
.cov__plate figcaption{color:#4A5442}


/* ---------- 31. Added motion --------------------------------------------
   Everything here rides the reveal observer that already exists, so nothing
   below needs new script. transform + opacity only; each block is gated on
   reduced-motion, and hovers stay behind a real pointer so a tap can never
   latch one. */

@media (prefers-reduced-motion:no-preference){

  /* The container itself stops animating once its children do, otherwise the
     block's 20px lift and each cell's 16px lift compound into a 36px lurch. */
  .svc3.rv,.threats.rv,.steps.rv{opacity:1;transform:none;transition:none}

  /* Grid children settle in sequence instead of the whole block appearing at
     once. 50ms per item, capped so the last cell is never left waiting. */
  .svc3.rv > article,
  .threats.rv > *,
  .steps.rv > *{
    opacity:0;transform:translate3d(0,16px,0);
    transition:opacity .5s var(--e),transform .5s var(--e-enter);
  }
  .svc3.rv.is-in > article,
  .threats.rv.is-in > *,
  .steps.rv.is-in > *{opacity:1;transform:none}
  .svc3.rv.is-in > article:nth-child(2),
  .threats.rv.is-in > :nth-child(2),
  .steps.rv.is-in > :nth-child(2){transition-delay:50ms}
  .svc3.rv.is-in > article:nth-child(3),
  .threats.rv.is-in > :nth-child(3),
  .steps.rv.is-in > :nth-child(3){transition-delay:100ms}
  .threats.rv.is-in > :nth-child(4),
  .steps.rv.is-in > :nth-child(4){transition-delay:150ms}
  .steps.rv.is-in > :nth-child(5){transition-delay:200ms}

  /* the safety net must clear these too, or a stalled observer hides them */
  .svc3.is-shown > article,
  .threats.is-shown > *,
  .steps.is-shown > *{opacity:1 !important;transform:none !important;transition:none !important}

  /* photographs settle out of a slight push-in as their tile reveals */
  .rail.rv img,.gal__item img{transition:transform .8s var(--e-enter)}
  .rail.rv:not(.is-in) img{transform:scale(1.05)}
}

@media (hover:hover) and (pointer:fine){
  /* service cells: lift, and a brand rule draws across the top edge */
  .svc3 > article{position:relative;transition:transform var(--t-mid) var(--e-enter),
                                              background-color var(--t-hover) ease}
  .svc3 > article::before{
    content:"";position:absolute;top:0;left:0;right:0;height:2px;background:var(--brand);
    transform:scaleX(0);transform-origin:left center;
    transition:transform var(--t-slow) var(--e-enter);
  }
  .svc3 > article:hover{transform:translateY(-3px)}
  .svc3 > article:hover::before{transform:scaleX(1)}
  .svc3 > article:hover .tag{color:var(--brand-txt)}
  .svc3 .tag{transition:color var(--t-hover) ease}
}

/* drawer links come in behind the panel rather than arriving with it.
   Enter 260ms, exit 150ms - a dismissal should feel instant. */
@media (prefers-reduced-motion:no-preference){
  .nav__drawer > a,.nav__drawer .drawer-cta{
    opacity:0;transform:translate3d(0,12px,0);
    transition:opacity 150ms var(--e),transform 150ms var(--e);
  }
  .nav__drawer.is-open > a,.nav__drawer.is-open .drawer-cta{
    opacity:1;transform:none;
    transition:opacity 260ms var(--e),transform 260ms var(--e-enter);
  }
  .nav__drawer.is-open > a:nth-child(1){transition-delay:40ms}
  .nav__drawer.is-open > a:nth-child(2){transition-delay:80ms}
  .nav__drawer.is-open > a:nth-child(3){transition-delay:120ms}
  .nav__drawer.is-open > a:nth-child(4){transition-delay:160ms}
  .nav__drawer.is-open > a:nth-child(5){transition-delay:200ms}
  .nav__drawer.is-open .drawer-cta{transition-delay:240ms}
}


/* ---------- 32. Page transitions ----------------------------------------
   A black veil carrying the mark covers the outgoing page, and the incoming
   page paints already covered and lifts it away. One system in every browser:
   the native `@view-transition` route only worked in Chrome and Safari, and
   running two different mechanisms side by side is what caused the hard cut in
   Firefox and the entrance/exit cascade fight.

   Nothing here can strand anyone: the veil never accepts pointer events, its
   resting opacity is 0 so a browser that runs no animation simply never shows
   it, and the navigation itself is on a timeout rather than an event. */

/* Forced idle by the script backstop. Written before the .is-out rules so
   those still win and an exit can raise the veil again. */
.veil.is-idle{opacity:0;animation:none}

/* Leaving: fade the veil up, then go. Quick - a click should feel answered. */
html.is-out .veil,
html.is-out .veil.is-idle{
  opacity:1;
  animation:none;                 /* the arrival animation must not fight this */
  transition:opacity 190ms cubic-bezier(.4,0,1,1);
}
html.is-out .veil__mark,
html.is-out .veil.is-idle .veil__mark{
  transform:scale(.97);
  transition:transform 190ms cubic-bezier(.4,0,1,1);
}

/* Arriving: the page paints under a veil that is already up, then it lifts.
   No fill mode on purpose - the resting state is opacity 0, so if animations
   never run the veil is simply invisible rather than stuck over the page. */
@media (prefers-reduced-motion:no-preference){
  .veil{animation:veilOut 380ms cubic-bezier(.22,1,.36,1)}
  .veil__mark{animation:veilMark 380ms cubic-bezier(.22,1,.36,1)}
}
@keyframes veilOut{
  0%{opacity:1} 42%{opacity:1} 100%{opacity:0}
}
@keyframes veilMark{
  0%{opacity:1;transform:scale(1)} 42%{opacity:1;transform:scale(1)}
  100%{opacity:0;transform:scale(1.05)}
}

/* ---------- 33. Borrowed vocabulary, rebuilt -----------------------------
   Two ideas adapted from the Unlimited Collision build at Tony's request.
   Deliberately NOT taken: that site's intro curtain and custom cursor ring -
   those are its signature and lifting them would read as a clone. The two
   below are re-implemented with different mechanisms so they read as this
   site's own: a clip wipe rather than a masked transform, and a native
   scroll-driven timeline rather than a JS-measured track. */

@media (prefers-reduced-motion:no-preference){

  /* Section headings wipe up from their own baseline as the block reveals.
     Unlimited slides a span inside an overflow mask; this clips the glyphs
     directly, which keeps the descenders honest and needs no extra element. */
  .rv .d2{
    clip-path:inset(0 0 105% 0);
    transition:clip-path .72s cubic-bezier(.22,1,.36,1);
  }
  .rv.is-in .d2{clip-path:inset(0 0 -15% 0)}
  /* the rescue path must clear the clip too, or a stalled observer hides it */
  .rv.is-shown .d2{clip-path:none !important;transition:none !important}

  /* The nav settles a touch once you leave the top. transform only - the bar
     height never changes, so nothing below it can shift. */
  .nav__logo{transition:transform var(--t-mid) var(--e-enter)}
  .nav.is-stuck .nav__logo{transform:scale(.94)}
}

/* A green rule draws across the process row as it passes through the
   viewport. Native scroll-driven timeline: no script, no scroll listener, and
   it runs on the compositor. Gated on @supports so browsers without it simply
   show the finished rule instead of running it on a clock. */
@supports (animation-timeline:view()){
  @media (prefers-reduced-motion:no-preference){
    .steps{position:relative}
    .steps::after{
      content:"";position:absolute;left:0;top:-1px;height:2px;width:100%;
      background:var(--brand);transform-origin:left center;transform:scaleX(0);
      animation:stepsFill linear both;
      animation-timeline:view();
      animation-range:entry 25% cover 55%;
      z-index:2;pointer-events:none;
    }
    @keyframes stepsFill{ to{transform:scaleX(1)} }
  }
}


/* ---------- 34. Spacing utilities, last on purpose ----------------------
   These have to outrank the mobile `.section{padding-block:...}` override,
   which re-declares the shorthand inside a media query and was silently
   cancelling both of them on phones. That put 128px of dead space between
   the gallery filters and the first tile, because the two sit in separate
   sections whose paddings then stacked. Keep this block at the end. */
.pt-0{padding-top:0}
.pb-0{padding-bottom:0}


/* ---------- 35. Splash ---------------------------------------------------
   A curtain is the one component that can ruin a site outright, so it is
   built to get out of the way three separate ways: the lift is a pure CSS
   animation that needs no script, `pointer-events` is never enabled so it can
   never swallow a tap even mid-animation, and main.js clears it on load as a
   backstop. It shows once per session (the guard runs in <head>, before first
   paint) because sitting through it on every page would be miserable.

   Its own vocabulary, not the curtain from the Unlimited build: the mark
   settles, the wordmark wipes up out of its own baseline, a brand rule draws
   across, and the whole sheet lifts away upward. */
.splash{
  position:fixed;inset:0;z-index:200;
  background:#0A0D08;
  display:grid;place-items:center;
  pointer-events:none;
  animation:splashLift 460ms cubic-bezier(.25,1,.5,1) 820ms both;
}
.splash__in{display:flex;flex-direction:column;align-items:center;gap:.85rem;padding:0 var(--pad)}

.splash__mark{
  width:clamp(140px,24vw,280px);height:auto;display:block;
  animation:splashMark 380ms cubic-bezier(.22,1,.36,1) 60ms both;
}
.splash__wm{display:flex;flex-direction:column;align-items:center;line-height:1;
  animation:splashWipe 400ms cubic-bezier(.22,1,.36,1) 220ms both}
.splash__wm1{
  font-family:var(--display);font-weight:700;text-transform:uppercase;
  font-size:clamp(1.5rem,3.7vw,2.8rem);letter-spacing:.02em;color:#FBFBF8;
}
.splash__wm2{
  font-family:var(--label);font-weight:700;text-transform:uppercase;
  font-size:clamp(.66rem,1.5vw,.95rem);letter-spacing:.42em;color:#8DC63F;margin-top:.5rem;
  /* the trailing letter-space pushes the word off-centre; pull it back */
  text-indent:.42em;
}
.splash__rule{
  display:block;width:clamp(140px,24vw,280px);height:2px;background:#8DC63F;
  transform-origin:center;
  animation:splashRule 420ms cubic-bezier(.22,1,.36,1) 380ms both;
}

@keyframes splashMark{ from{opacity:0;transform:scale(.94)} to{opacity:1;transform:none} }
@keyframes splashWipe{ from{opacity:0;clip-path:inset(0 0 105% 0)} to{opacity:1;clip-path:inset(0 0 -20% 0)} }
@keyframes splashRule{ from{transform:scaleX(0)} to{transform:scaleX(1)} }
/* No hold inside the keyframes: the 820ms animation-delay already provides
   the pause, and holding to 62% squeezed the actual slide into 175ms, which
   is far too abrupt for a full-viewport surface. The whole 460ms is now the
   lift itself. */
@keyframes splashLift{
  from{transform:translate3d(0,0,0)}
  to  {transform:translate3d(0,-101%,0);visibility:hidden}
}

/* Repeat views in the same session, and anyone who has asked for less motion,
   never see it at all. */
html[data-splash="skip"] .splash,
.splash.is-done{display:none}
@media (prefers-reduced-motion:reduce){ .splash{display:none} }


/* ---------- 36. Separators ----------------------------------------------
   A hairline that draws out from the centre with a chevron sitting on it,
   echoing the peak in his mark. One at the foot of every hero, one under the
   bar. transform and opacity only. */

.sep{
  position:absolute;left:0;right:0;bottom:0;height:1px;z-index:3;pointer-events:none;
}
.sep::before{
  content:"";position:absolute;inset:0;
  background:linear-gradient(90deg,
    rgba(141,198,63,0) 0%,rgba(141,198,63,.42) 16%,
    rgba(141,198,63,.95) 50%,
    rgba(141,198,63,.42) 84%,rgba(141,198,63,0) 100%);
  transform:scaleX(.12);transform-origin:center;
}
.sep::after{
  content:"";position:absolute;left:50%;bottom:-5px;width:26px;height:11px;
  margin-left:-13px;
  border-left:2px solid var(--brand);border-top:2px solid var(--brand);
  transform:rotate(45deg) scale(.6);transform-origin:center;
  opacity:0;
}
@media (prefers-reduced-motion:no-preference){
  .sep::before{animation:sepDraw 1s cubic-bezier(.22,1,.36,1) 260ms both}
  .sep::after {animation:sepMark .5s cubic-bezier(.22,1,.36,1) 900ms both}
}
@media (prefers-reduced-motion:reduce){
  .sep::before{transform:scaleX(1)} .sep::after{opacity:.9;transform:rotate(45deg)}
}
@keyframes sepDraw{ from{transform:scaleX(.12)} to{transform:scaleX(1)} }
@keyframes sepMark{ from{opacity:0;transform:rotate(45deg) scale(.6)} to{opacity:.9;transform:rotate(45deg) scale(1)} }

/* Under the bar: a slow highlight travelling along the rule. Low contrast and
   unhurried on purpose - it sits on screen permanently, and the rule is that
   anything you see constantly has to stay quiet. */


/* ---------- 37. Packages written out + who we are ------------------------
   Descriptions used to appear one at a time, only for the selected package,
   and the PPF levels lived entirely inside a hover accordion. The old site
   showed every package plainly. Now every row carries its own description,
   and the PPF page lists all five under the accordion. */
.pk__txt{display:block;color:var(--fg-muted);font-size:var(--t-sm);line-height:1.5;margin-top:.4rem;max-width:44ch}
.sec-head--tight{margin-top:var(--s-7);margin-bottom:var(--s-5)}
.h-sub{font-family:var(--display);font-weight:700;text-transform:uppercase;letter-spacing:.015em;font-size:var(--t-xl)}
.about{display:grid;grid-template-columns:1fr 1.15fr;gap:var(--s-7);align-items:start}
.about__copy{display:flex;flex-direction:column;gap:var(--s-4);max-width:60ch}
.about__copy p{color:var(--fg-muted);font-size:var(--t-md);line-height:1.6}
@media (max-width:900px){ .about{grid-template-columns:1fr;gap:var(--s-5)} }

@media (prefers-reduced-motion:no-preference){
  /* the five trust cells settle in sequence, same rhythm as the service cells */
  .trust.rv{opacity:1;transform:none;transition:none}
  .trust.rv > div{opacity:0;transform:translate3d(0,16px,0);
    transition:opacity .5s var(--e),transform .5s var(--e-enter)}
  .trust.rv.is-in > div{opacity:1;transform:none}
  .trust.rv.is-in > div:nth-child(2){transition-delay:50ms}
  .trust.rv.is-in > div:nth-child(3){transition-delay:100ms}
  .trust.rv.is-in > div:nth-child(4){transition-delay:150ms}
  .trust.rv.is-in > div:nth-child(5){transition-delay:200ms}
  .trust.is-shown > div{opacity:1 !important;transform:none !important;transition:none !important}
  /* package rows: the whole list rises as one, each row's text is already in place */
  .pk{transition:background var(--t-fast) var(--e),transform var(--t-hover) var(--e-enter)}
}
@media (hover:hover) and (pointer:fine){
  .pk:hover{transform:translateX(3px)}
}

/* ---------- 38. Coverage system: level walk + matrix + add-ons ---------
   Same component on every service page. Panels are position:sticky and later
   ones paint over earlier ones, so scrolling down reads as the green
   spreading across the car. Under 860px the panels are plain stacked cards:
   sticky needs a panel shorter than the viewport, which a phone cannot
   promise. Everything scroll-driven is transform/opacity, gated on
   @supports and on reduced-motion. */
.covsys{display:flex;flex-direction:column;gap:var(--s-6)}
.lvl-stack{position:relative;display:grid;grid-template-columns:2.75rem minmax(0,1fr);column-gap:var(--s-4);row-gap:var(--s-5);align-items:start}
.lvl{grid-column:2}
.lvl{
  /* each level parks 12px lower than the one before it, so the covered cards
     stay visible as a deck of top edges instead of vanishing */
  position:sticky;top:calc(var(--nav-h) + 1rem + var(--i,0) * 12px);scroll-margin-top:calc(var(--nav-h) + 1rem);
  color:var(--fg);--tint:#1E2A1B;
}
/* the card itself. Chrome and the deck transform live on the inner box so the
   sticky wrapper is never transformed: once revealed, .lvl gets transform:none
   !important from the reveal rules, which would cancel anything put there. */
.lvl__in{
  position:relative;
  display:grid;grid-template-columns:minmax(0,1.1fr) minmax(0,1fr);gap:clamp(1.5rem,3.5vw,3.5rem);align-items:center;
  padding:clamp(1.25rem,2.6vw,2.5rem);min-height:min(56vh,470px);
  background:var(--ink-850);border:1px solid var(--line);
  box-shadow:0 -1px 0 var(--line),0 18px 40px -22px rgba(0,0,0,.55);
  transform-origin:50% 0;
}
.lvl:nth-child(even) .cov__plate{order:2}
.lvl .cov__plate{background:#F2F4EF;margin:0}
.lvl__txt{display:flex;flex-direction:column;gap:var(--s-3);max-width:46ch}
.lvl__txt h3{font-family:var(--display);font-weight:700;text-transform:uppercase;letter-spacing:.015em;
  font-size:clamp(1.6rem,2.6vw,2.4rem);line-height:1.02}
.lvl__n{display:flex;align-items:baseline;gap:.4rem;color:var(--brand-txt)}
.lvl__n span{color:var(--fg-muted);letter-spacing:.1em}
.lvl__txt > p:not(.eyebrow):not(.pk__flag){color:var(--fg-muted);font-size:var(--t-md);line-height:1.55}
.lvl__txt .pk__flag{display:inline-block;width:auto;align-self:flex-start;color:var(--brand-ink);background:var(--brand);padding:.32rem .6rem;margin:-.2rem 0 .1rem}
/* coverage chips: one per item in his coverage string */
.chips{list-style:none;display:flex;flex-wrap:wrap;gap:.5rem;margin:.25rem 0 0;padding:0}
.chips li{font-family:var(--label);font-size:.72rem;font-weight:700;letter-spacing:.09em;text-transform:uppercase;
  padding:.45rem .7rem;border:1px solid var(--brand-line);color:var(--fg);background:rgba(191,242,47,.07)}
/* rail: level numbers beside the stack, lit as each level reaches the top */
.lvl-rail{grid-column:1;grid-row:1 / span 99;position:sticky;top:calc(var(--nav-h) + 1rem + 1.25rem);align-self:start;margin:0;padding:0;list-style:none;
  display:flex;flex-direction:column;gap:.55rem;z-index:2}
.lvl-rail li{font-family:var(--mono);font-size:var(--t-xs);letter-spacing:.08em;color:var(--fg-dim);
  display:flex;align-items:center;gap:.4rem;transition:color var(--t-mid) var(--e)}
.lvl-rail li::before{content:"";width:6px;height:6px;border:1px solid var(--line-2);border-radius:50%;transition:background var(--t-mid) var(--e),border-color var(--t-mid) var(--e)}
.lvl-rail li.is-on{color:var(--brand-txt)}
.lvl-rail li.is-on::before{background:var(--brand);border-color:var(--brand)}
/* matrix */
.mtx-wrap{overflow-x:auto;-webkit-overflow-scrolling:touch;border:1px solid var(--line)}
.mtx{width:100%;border-collapse:collapse;background:var(--ink-850);color:var(--fg);font-size:var(--t-sm)}
.mtx th,.mtx td{padding:.85rem 1rem;border-bottom:1px solid var(--line);text-align:center;vertical-align:middle}
.mtx thead th{font-family:var(--label);font-size:.72rem;font-weight:700;letter-spacing:.1em;text-transform:uppercase;
  color:var(--fg-muted);background:var(--ink-900);white-space:nowrap}
.mtx tbody th{text-align:left;font-weight:600;color:var(--fg);white-space:nowrap}
.mtx .is-hot{background:rgba(191,242,47,.06)}
.mtx thead .is-hot{box-shadow:inset 0 2px 0 var(--brand)}
.mtx thead .is-hot{color:var(--fg)}
.mtx__flag{display:block;font-size:.6rem;letter-spacing:.14em;color:var(--brand-txt);margin-top:.25rem}
.mtx .tick{width:18px;height:18px;color:var(--brand);vertical-align:middle}
.mtx__part{font-family:var(--label);font-size:.68rem;font-weight:700;letter-spacing:.1em;text-transform:uppercase;color:var(--brand-txt)}
.mtx__no{display:inline-block;width:14px;height:1px;background:var(--line-2);vertical-align:middle}
.mtx tbody tr:last-child th,.mtx tbody tr:last-child td{border-bottom:0}
.mtx-cards{display:none}
.sr{position:absolute;width:1px;height:1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap}
/* add-ons with their diagrams */
.addons--ill{grid-template-columns:repeat(auto-fit,minmax(18rem,1fr))}
.addons--ill .addon{padding:0;gap:0}
.addons--ill .cov__plate{border:0;border-bottom:1px solid var(--line);margin:0}
.addons--ill .cvg{padding:1.1rem 1.25rem 0}
.addons--ill h3{padding:0 1.25rem}
.addons--ill .addon > p:last-child{padding:0 1.25rem 1.25rem}
/* phones and narrow tablets: plain stack, cards instead of the table */
@media (max-width:860px){
  .lvl-stack{grid-template-columns:1fr}
  .lvl{position:static;grid-column:1}
  .lvl__in{grid-template-columns:1fr;gap:var(--s-4);min-height:0;padding:clamp(1rem,4vw,1.5rem);box-shadow:none;transform:none}
  .lvl__in::after{display:none}
  .lvl:nth-child(even) .cov__plate{order:0}
  .lvl__txt{max-width:none}
  .lvl-rail{display:none}
  .mtx-wrap{display:none}
  .mtx-cards{display:grid;grid-template-columns:1fr;gap:1px;background:var(--line);border:1px solid var(--line)}
  .mtx-card{background:var(--ink-850);padding:1.1rem 1.25rem}
  .mtx-card.is-hot{box-shadow:inset 3px 0 0 var(--brand)}
  .mtx-card h4{font-family:var(--display);font-weight:700;text-transform:uppercase;letter-spacing:.015em;font-size:var(--t-lg);margin-bottom:.5rem}
  .mtx-card ul{list-style:none;margin:0;padding:0;display:flex;flex-wrap:wrap;gap:.4rem}
  .mtx-card li{font-size:var(--t-sm);color:var(--fg);padding:.35rem .6rem;border:1px solid var(--brand-line);background:rgba(191,242,47,.07)}
  .mtx-card li em{font-style:normal;color:var(--brand-txt);font-size:.72rem;letter-spacing:.08em;text-transform:uppercase;margin-left:.35rem}
}
@media (max-width:560px){ .addons--ill{grid-template-columns:1fr} .chips li{font-size:.84rem} }
/* motion: the level being covered eases back and dims; chips settle in sequence */
@media (prefers-reduced-motion:no-preference){
  .covsys.rv{opacity:1;transform:none;transition:none}
  .covsys.rv .lvl,.covsys.rv .addon,.covsys.rv .mtx-wrap,.covsys.rv .mtx-cards{opacity:0;transform:translate3d(0,14px,0);
    transition:opacity .55s var(--e),transform .55s var(--e-enter)}
  .covsys.rv.is-in .lvl,.covsys.rv.is-in .addon,.covsys.rv.is-in .mtx-wrap,.covsys.rv.is-in .mtx-cards{opacity:1;transform:none}
  .covsys.rv.is-in .lvl:nth-child(3){transition-delay:60ms}
  .covsys.rv.is-in .lvl:nth-child(4){transition-delay:120ms}
  .covsys.is-shown .lvl,.covsys.is-shown .addon,.covsys.is-shown .mtx-wrap,.covsys.is-shown .mtx-cards{opacity:1 !important;transform:none !important;transition:none !important}
  .chips li{opacity:0;transform:translate3d(0,6px,0);transition:opacity .4s var(--e),transform .4s var(--e-enter);transition-delay:calc(var(--ci) * 35ms + 120ms)}
  .covsys.rv.is-in .chips li,.covsys.is-shown .chips li{opacity:1;transform:none}
  @media (min-width:861px){
    /* --p comes from script: how far the next level has slid over this one,
       0 to 1. A sticky card never leaves the viewport, so a view() timeline
       sits at 0 on it for the whole walk; measured overlap is the honest signal. */
    .lvl__in{transform:scale(calc(1 - .04 * var(--p,0)))}
    .lvl__in::after{content:"";position:absolute;inset:0;background:#0A0D08;opacity:calc(.28 * var(--p,0));pointer-events:none;z-index:3} /* fixed ink, not the surface token: the section is light */
  }
}
@media (hover:hover) and (pointer:fine){
  .lvl .cov__plate img,.addons--ill .cov__plate img{transition:transform .7s var(--e-enter)}
  .lvl:hover .cov__plate img,.addon:hover .cov__plate img{transform:scale(1.025)}
}


/* ---------- 39. Wholesale: PIN gate, trade notice, panel rates -----------
   Lives on /wholesale/ only. Everything here sits inside .on-light, so it
   reads the light-surface tokens and needs no colours of its own. */

/* the browser default for [hidden] is display:none, but several of the
   classes used inside the gated body set display themselves and would win */
[hidden]{display:none !important}

/* the gate IS the page until it opens. Dark surface so it reads as a door,
   not as a section of a page that is partly visible behind it. */
.gate-screen{display:grid;place-items:center;
  min-height:calc(100vh - var(--nav-h));
  min-height:calc(100svh - var(--nav-h));padding:var(--s-8) 0}
/* wide enough that the headline sits on two lines, with the form itself
   kept narrow so a four digit code never looks like a search box */
.gate__in{width:min(34rem,100%);display:flex;flex-direction:column;align-items:stretch;
  gap:var(--s-4);text-align:center}
.gate__form{max-width:22rem;width:100%;margin-inline:auto}
.gate__mark{width:132px;height:auto;align-self:center;flex:0 0 auto;margin-bottom:var(--s-2)}
.gate__in .eyebrow{margin:0}
/* a gate is a utility screen, not a hero: smaller than .d2 so the line
   breaks twice instead of three times and it stops shouting */
.gate__in h1{margin:0;font-size:clamp(1.85rem,4.4vw,2.55rem);line-height:1.04}
.gate__lede{color:var(--fg-muted);font-size:var(--t-md);line-height:1.5;text-wrap:pretty}
.gate__form{display:flex;flex-direction:column;gap:var(--s-4);margin-top:var(--s-2);text-align:left;
  max-width:22rem;width:100%;margin-inline:auto}
/* a four digit code in a full width box looks like a mistake */
.gate__form .input{text-align:center;font-family:var(--mono);font-size:var(--t-lg);
  letter-spacing:.35em;padding-left:.35em}
.gate__msg{min-height:1.1rem;font-size:var(--t-sm);color:var(--err)}
.gate__help{font-size:var(--t-sm);color:var(--fg-muted)}
.gate__help a{color:var(--brand-txt);text-decoration:underline;text-underline-offset:2px}
@media (prefers-reduced-motion:no-preference){
  .gate-screen.is-wrong .gate__in{animation:gateNo .4s var(--e)}
  @keyframes gateNo{
    0%,100%{transform:translate3d(0,0,0)}
    20%{transform:translate3d(-7px,0,0)}
    40%{transform:translate3d(6px,0,0)}
    60%{transform:translate3d(-4px,0,0)}
    80%{transform:translate3d(2px,0,0)}
  }
}
@media (max-width:900px){
  /* The sticky call bar floats over the bottom of the viewport. Centring the
     gate inside exactly one viewport put the help line underneath it, and
     padding alone cannot fix that once the content is taller than the box.
     Let it flow from the top instead and give the bar real clearance. */
  .gate-screen{min-height:0;place-items:start center;
    padding:var(--s-7) 0 calc(var(--s-7) + 5rem)}
}
@media (max-width:560px){
  .gate__mark{width:112px}
}

/* the disclaimer a shop reads before any number */
.notice{border-left:2px solid var(--brand);background:var(--brand-wash);
  padding:var(--s-4) var(--s-5);margin-bottom:var(--s-7)}
.notice__h{font-family:var(--display);font-weight:700;text-transform:uppercase;letter-spacing:.015em;
  font-size:var(--t-lg);margin-bottom:var(--s-2)}
.notice p:not(.notice__h){font-size:var(--t-sm);color:var(--fg-muted);line-height:1.55;max-width:62ch}

/* panel work, priced outside a package */
.rates{display:grid;grid-template-columns:repeat(auto-fit,minmax(16rem,1fr));gap:1px;
  background:var(--line);border:1px solid var(--line)}
.rate{background:var(--ink-850);padding:var(--s-5)}
.rate__n{font-family:var(--display);font-weight:700;font-size:clamp(2rem,4vw,2.75rem);line-height:1;
  color:var(--fg)}
.rate__k{font-family:var(--mono);font-size:var(--t-xs);letter-spacing:.14em;text-transform:uppercase;
  color:var(--brand-txt);margin:var(--s-3) 0 var(--s-2)}
.rate__d{font-size:var(--t-sm);color:var(--fg-muted);line-height:1.55}


/* ---------- 40. Estimator: coverage preview beside the choice ------------
   The diagram is what makes one level legible against the next, so it sits
   next to the packages rather than only on the service pages. One image per
   service group, swapped on selection, so nothing is repeated down the page. */

.pk-group{display:grid;grid-template-columns:minmax(0,1fr) minmax(0,1.15fr);
  grid-template-areas:"head head" "prev list";gap:var(--s-4) var(--s-5);align-items:start}
.pk-group + .pk-group{margin-top:var(--s-6)}
.pk-group__h{grid-area:head;margin:0}
.pk-group .pk-prev{grid-area:prev}
.pk-group .pk-list{grid-area:list}

/* the list can run long, so the diagram follows it down on a big screen */
.pk-prev{margin:0;position:sticky;top:calc(var(--nav-h) + 1rem);background:#F2F4EF}
.pk-prev img{width:100%;height:auto;display:block;color:transparent}

/* estimate step: a thumbnail, deliberately small. The full diagram already
   did its job one step earlier and a second large image buries the price. */
.summary__row.has-thumb{display:grid;grid-template-columns:76px 1fr auto;align-items:center}
.summary__thumb{width:76px;height:auto;display:block;border:1px solid var(--line);background:#F2F4EF;color:transparent}

@media (max-width:860px){
  /* stack: heading, then diagram, then the options it explains */
  .pk-group{grid-template-columns:1fr;grid-template-areas:"head" "prev" "list";gap:var(--s-4)}
  .pk-prev{position:static}
  .pk-prev img{max-height:34vh;object-fit:contain}
}
@media (max-width:560px){
  .summary__row.has-thumb{grid-template-columns:56px 1fr;row-gap:var(--s-2)}
  .summary__row.has-thumb .v{grid-column:2;text-align:left}
  .summary__thumb{width:56px}
}


/* ---------- 41. Estimator step bar: show there is more to the right ------
   .est__bar scrolls horizontally and its scrollbar is deliberately hidden, so
   on a narrow phone a visitor sees steps 1 and 2 with no sign that 3 to 6
   exist. A mask fades the right edge instead of a scrollbar: colour-agnostic,
   so it works on any surface the estimator sits on. */
@media (max-width:620px){
  .est__bar{
    -webkit-mask-image:linear-gradient(90deg,#000 0,#000 calc(100% - 26px),transparent 100%);
            mask-image:linear-gradient(90deg,#000 0,#000 calc(100% - 26px),transparent 100%);
  }
}

/* the quote-only state is now a call to action, so make the number tappable */
.quote-call{margin-top:.4rem}
.quote-call a{font-family:var(--display);font-weight:700;font-size:var(--t-lg);
  letter-spacing:.01em;color:var(--brand-txt);text-decoration:underline;text-underline-offset:3px}


/* ---------- 42. Cost calculator, single screen ---------------------------
   Rebuilt 2026-09-03 to match the calculator Eric already had: every choice
   visible at once, total updates on click, no steps and no Continue. */
.calc{display:flex;flex-direction:column;gap:var(--s-5);
  border:1px solid var(--line);background:var(--ink-850);padding:clamp(1.1rem,2.6vw,2rem)}
.cg{display:flex;flex-direction:column;gap:var(--s-3)}
.cg__h{font-family:var(--mono);font-size:var(--t-xs);letter-spacing:.14em;text-transform:uppercase;
  color:var(--brand-txt);margin:0}
/* choice buttons */
.opt{font-family:var(--label);font-size:var(--t-sm);font-weight:600;
  padding:.7rem 1.05rem;border:1px solid var(--line-2);background:var(--ink-900);color:var(--fg);
  cursor:pointer;min-height:44px;transition:background var(--t-fast),border-color var(--t-fast)}
.opt[aria-pressed="true"]{background:var(--brand);border-color:var(--brand);color:var(--brand-ink);font-weight:700}
.opt--chk[aria-pressed="true"]::before{content:"\2713 ";font-weight:700}
/* package rows: name, coverage, price */
.pklist{display:flex;flex-direction:column;gap:1px;background:var(--line);border:1px solid var(--line)}
.pkrow{display:grid;grid-template-columns:auto minmax(0,1fr) auto;gap:var(--s-3);align-items:center;
  text-align:left;background:var(--ink-900);border:0;cursor:pointer;padding:.85rem 1.1rem;
  min-height:44px;transition:background var(--t-fast)}
.pkrow__dot{width:14px;height:14px;border:1px solid var(--line-2);border-radius:50%;flex:none}
.pkrow[aria-checked="true"]{background:var(--brand-wash);box-shadow:inset 3px 0 0 var(--brand)}
.pkrow[aria-checked="true"] .pkrow__dot{border-color:var(--brand);background:var(--brand);
  box-shadow:inset 0 0 0 3px var(--ink-900)}
.pkrow__n{display:block;font-family:var(--display);font-weight:700;text-transform:uppercase;
  letter-spacing:.015em;font-size:var(--t-md);color:var(--fg)}
.pkrow__c{display:block;font-size:var(--t-sm);color:var(--fg-muted);margin-top:.1rem}
.pkrow__p{font-family:var(--display);font-weight:700;font-size:var(--t-lg);color:var(--fg);
  white-space:nowrap;font-variant-numeric:tabular-nums}
/* the number, which is the point of the whole thing */
.calc__out{border-top:1px solid var(--line);padding-top:var(--s-4)}
.calc__tot{display:flex;align-items:baseline;justify-content:space-between;gap:var(--s-4);flex-wrap:wrap}
.calc__tl{font-family:var(--mono);font-size:var(--t-xs);letter-spacing:.14em;text-transform:uppercase;
  color:var(--fg-muted)}
.calc__tv{font-family:var(--display);font-weight:700;letter-spacing:-.01em;
  font-size:clamp(2.2rem,6vw,3.2rem);line-height:1;color:var(--fg);font-variant-numeric:tabular-nums}
.calc__note{font-size:var(--t-xs);color:var(--fg-dim);line-height:1.45;margin-top:var(--s-3);max-width:62ch}
.calc__cta{margin-top:var(--s-4);display:inline-flex}
.calc__quote{border-left:2px solid var(--brand);background:var(--brand-wash);padding:var(--s-4) var(--s-5)}
.calc__qh{font-weight:700;margin-bottom:var(--s-2);color:var(--fg)}
.calc__quote p{font-size:var(--t-sm);color:var(--fg-muted);max-width:62ch}
@media (max-width:560px){
  .pkrow{grid-template-columns:auto minmax(0,1fr);row-gap:.2rem}
  .pkrow__p{grid-column:2;justify-self:start;font-size:var(--t-md)}
  .calc__cta{width:100%;justify-content:center}
}


/* body shop schedule: "Starting at" label above the figure, so nobody reads
   a minimum as a fixed price */
.rate__u{font-size:var(--t-sm);font-weight:700;color:var(--fg-muted);letter-spacing:.06em}
.rates__note{margin-top:var(--s-4);font-size:var(--t-sm);color:var(--fg-dim);
  line-height:1.5;max-width:66ch}
.rate__k{margin:0 0 var(--s-2)}
.rate__n{margin:0 0 var(--s-3)}


/* ---------- 43. Trade entry band -----------------------------------------
   The only public doorway to /wholesale/ besides the footer link. Quiet on
   purpose: a shop should find it, a retail customer should not be pulled in. */
.tradebar{border-top:1px solid var(--line);border-bottom:1px solid var(--line);
  background:var(--ink-850);padding:var(--s-6) 0}
.tradebar__in{display:flex;align-items:center;justify-content:space-between;
  gap:var(--s-5);flex-wrap:wrap}
.tradebar__copy{display:flex;flex-direction:column;gap:.15rem;min-width:0}
.tradebar__t{font-family:var(--display);font-weight:700;text-transform:uppercase;
  letter-spacing:.015em;font-size:var(--t-xl);color:var(--fg)}
.tradebar__d{font-size:var(--t-sm);color:var(--fg-muted);max-width:52ch}
@media (max-width:640px){
  .tradebar__in{flex-direction:column;align-items:flex-start}
  .tradebar__in .btn{width:100%;justify-content:center}
}

/* The footer legal line sat on --fg-dim at 12px, which measures 4.37:1 on
   the dark ground: under the 4.5 floor. --fg-muted clears it. */
.footer__bar--aa{color:var(--fg-muted)}
.footer__bar--aa span{color:var(--fg-muted)}

/* Anchor targets sit under a sticky bar, so scrolling to one used to put the
   heading behind the header. This offsets the landing point instead. */
.anchor{display:block;scroll-margin-top:calc(var(--nav-h) + var(--s-5))}

/* Mobile hero: the copy block sits higher in a shorter frame, which put the
   eyebrow just outside the copy pool and measured 4.41:1 against the
   photograph. Deepening the pool on small screens only keeps the desktop
   brightness gain while clearing AA everywhere. */
@media (max-width:820px){
  .hero--full::after{
    background:
      radial-gradient(150% 155% at 0% 78%,
        rgba(11,14,10,.96) 0%,rgba(11,14,10,.90) 38%,rgba(11,14,10,.52) 66%,rgba(11,14,10,0) 88%),
      linear-gradient(to bottom,
        rgba(11,14,10,.44) 0%,rgba(11,14,10,.16) 22%,rgba(11,14,10,.10) 46%,
        rgba(11,14,10,.60) 78%,var(--ink-900) 99%),
      linear-gradient(to right,
        rgba(11,14,10,.74) 0%,rgba(11,14,10,.32) 34%,rgba(11,14,10,.04) 62%,rgba(11,14,10,.16) 100%);
  }
}

/* Honeypot: taken out of the flow and off-screen instead of display:none,
   which a form-filling bot will skip. Never reaches a person. */
.hp{position:absolute!important;left:-9999px;top:auto;width:1px;height:1px;
  overflow:hidden;opacity:0;pointer-events:none}
/* Gate message: an error needs to read as one without relying on colour,
   which is why the copy itself always names the problem. */
.gate__msg.is-err{color:var(--err)}


/* ---- calculator: live coverage preview beside the controls -------------- */
/* One column on a phone with the diagram FIRST, so you can see the thing you
   are choosing before the choices. Two columns once there is room, and the
   diagram sticks while the options scroll.
   Colours use --fg* for text and --ink-* for surfaces: on this two-surface
   system --ink-900 is a SURFACE, not an ink, and using it for text is how you
   get near-white on near-white. */
.calc-wrap{display:grid;gap:var(--s-5)}
@media (min-width:900px){
  .calc-wrap{grid-template-columns:minmax(0,1fr) minmax(0,1.05fr);
    gap:var(--s-6);align-items:start}
  .calc-prev{position:sticky;top:calc(var(--nav-h) + var(--s-4))}
}
.calc-prev{margin:0;border:1px solid var(--line);border-radius:var(--r-2);
  overflow:hidden;background:var(--ink-900)}
.calc-prev img{display:block;width:100%;height:auto;aspect-ratio:1200/750;
  object-fit:cover;background:var(--ink-800)}
.calc-prev__cap{display:block;padding:var(--s-3) var(--s-4) var(--s-4)}
.calc-prev__n{display:block;font-family:var(--display);font-weight:700;
  text-transform:uppercase;letter-spacing:.015em;font-size:var(--t-md);color:var(--fg)}
.calc-prev__c{display:block;margin-top:.2rem;font-size:var(--t-sm);
  line-height:1.45;color:var(--fg-muted)}

/* ---- package list: ceramic + tint, no calculator ------------------------ */
.pkgrid{display:grid;gap:var(--s-4);grid-template-columns:1fr}
@media (min-width:640px){.pkgrid{grid-template-columns:repeat(2,minmax(0,1fr))}}
@media (min-width:1040px){.pkgrid{grid-template-columns:repeat(3,minmax(0,1fr))}}
.pkgc{display:flex;flex-direction:column;border:1px solid var(--line);
  border-radius:var(--r-2);overflow:hidden;background:var(--ink-900)}
.pkgc__img{display:block;width:100%;height:auto;aspect-ratio:1200/750;
  object-fit:cover;background:var(--ink-800)}
.pkgc__b{padding:var(--s-4);display:flex;flex-direction:column;gap:.35rem;flex:1 1 auto}
.pkgc__n{margin:0;font-family:var(--display);font-weight:700;text-transform:uppercase;
  letter-spacing:.015em;font-size:var(--t-md);color:var(--fg)}
.pkgc__c{margin:0;font-size:var(--t-sm);line-height:1.5;color:var(--fg-muted);flex:1 1 auto}
.pkgc__p{margin:.2rem 0 0;font-family:var(--display);font-weight:700;
  font-size:var(--t-lg);color:var(--fg);font-variant-numeric:tabular-nums}
.pkgc__from{font-family:var(--mono);font-weight:600;font-size:var(--t-xs);
  letter-spacing:.14em;text-transform:uppercase;color:var(--fg-dim)}
.pkgadd{margin-top:var(--s-6)}
.pkga-list{list-style:none;margin:var(--s-3) 0 0;padding:0;display:grid;
  grid-template-columns:1fr}
@media (min-width:640px){.pkga-list{grid-template-columns:repeat(2,minmax(0,1fr));
  column-gap:var(--s-6)}}
.pkga{display:flex;justify-content:space-between;align-items:baseline;
  gap:var(--s-3);padding:.62rem 0;border-bottom:1px solid var(--line)}
.pkga__n{color:var(--fg);font-size:var(--t-sm)}
.pkga__p{font-family:var(--display);font-weight:700;color:var(--fg);
  white-space:nowrap;font-variant-numeric:tabular-nums}
.pkgnote{margin-top:var(--s-4);font-size:var(--t-xs);line-height:1.45;
  color:var(--fg-dim);max-width:62ch}
.pkgcta,.covrow__cta .btn{max-width:100%;white-space:normal}
.pkgcta{margin-top:var(--s-5)}
/* .btn sets white-space:nowrap, and 'Call for a quote - (401) 537-7405'
   measures 397px inside a 338px column at 375. body{overflow-x:hidden}
   then clipped the phone number with no way to scroll to it. */
.pkgquote{margin-top:var(--s-6)}
