/* =========================================================================
   BIG EASY CUSTOM CARS &#8211; homepage mockup
   Design system for Big Easy Custom Cars:
   editorial serif + clean sans, .kw keyword highlight, .eyeb eyebrows,
   generous radius on all imagery, .rv reveal gated on .js with a full
   reduced-motion switch-off, btn-p / btn-s / btn-l / btn-o button set only.
   Palette retuned from pool navy to automotive ink + Big Easy orange.
   Outfit is already self-hosted on the live site, so it carries over.
   ========================================================================= */
:root{
  --ink:#0B0C0E;        /* body ground */
  --ink-2:#14161A;      /* raised panels */
  --ink-3:#1C1F24;      /* cards on dark */
  --paper:#F7F5F2;      /* light ground */
  --paper-2:#EFECE7;
  --line:#E4E0DA;
  --line-d:rgba(255,255,255,.13);
  --body:#55514C;       /* body copy on light */
  --body-d:#B6B1AA;     /* body copy on dark */
  /* Orange, retuned 2026-09-20: the live site's #FF5C1A glowed on dark and
     was tiring to read against. These are the same hue, desaturated and
     darkened, with a separate deeper value for orange text on LIGHT grounds
     so it clears WCAG AA instead of shimmering. */
  --amber:#E4783F;      /* accent on DARK grounds */
  --amber-2:#C25F2B;    /* hover, and deeper fills */
  --amber-ink:#A64E23;  /* orange TEXT on LIGHT grounds, AA-safe */
  --amber-tint:#FBF0E9;
  --steel:#8A8F98;
  --white:#fff;
  --serif:"Fraunces",Georgia,"Times New Roman",serif;
  --sans:"Outfit",-apple-system,"Segoe UI",Arial,sans-serif;
  --r:20px;
  --wrap:1440px;
  --ease:cubic-bezier(.22,.61,.36,1);
  /* One chevron for every menu that opens something: the top-level
     dropdowns, the town fly-outs and the mobile toggles all mask this
     same path and rotate it, so the caret is identical everywhere and
     picks up the link's own colour through currentColor. Replaces the
     text glyphs the mockup used, which rendered at a different weight
     and baseline in every font fallback. */
  --chev:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M5 9l7 7 7-7' fill='none' stroke='%23000' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
}
*{box-sizing:border-box;margin:0;padding:0}
html{scroll-behavior:smooth;
  /* The header is sticky, so without this every in-page jump (all the
     Free Estimate buttons, the footer links, the dropdown items) lands
     the section top UNDER the header and hides its heading.
     The value is the UNSHRUNK header, not the shrunk one. The header is in
     flow, so when it shrinks after the jump it pulls everything below it up.
     Re-measured 23 Sep: the logo is 86px and the bar's padding was cut to
     10px, which puts the header back at 107px unshrunk and 81px shrunk. */
  scroll-padding-top:108px}
@media(max-width:700px){html{scroll-padding-top:88px}}  /* 54px logo + 32 + 1 */
body{background:var(--paper);color:var(--body);font-family:var(--sans);
  font-size:17px;line-height:1.65;-webkit-font-smoothing:antialiased}
img{max-width:100%;display:block}
.wrap{max-width:var(--wrap);margin:0 auto;padding:0 clamp(16px,4vw,32px)}
h1,h2,h3,h4{font-family:var(--serif);color:var(--ink);font-weight:600;line-height:1.1}
h1{font-size:clamp(38px,6.2vw,72px);letter-spacing:-.02em}
h2{font-size:clamp(29px,3.9vw,46px);letter-spacing:-.015em}
h3{font-size:clamp(20px,2.2vw,25px)}
a{color:inherit}
/* Orange text switches value by ground so it never glows and never goes
   under WCAG AA: the deep tone on light, the lighter tone on dark. */
.kw{color:var(--amber-ink);font-style:italic}
.on-dark h1,.on-dark h2,.on-dark h3{color:var(--paper)}
.on-dark{color:var(--body-d)}
.on-dark .kw,.hero .kw{color:var(--amber)}
.eyeb{font-family:var(--sans);font-size:11.5px;font-weight:600;letter-spacing:.22em;
  text-transform:uppercase;color:var(--amber-ink);margin-bottom:14px}
.on-dark .eyeb,.hero .eyeb{color:var(--amber)}
.lead{max-width:56ch}
.lead p:not(.eyeb){margin-top:14px;font-size:clamp(15.5px,1.6vw,17.5px)}
/* Section rhythm. Two stacked sections each carrying 104px left about
   208px of dead space between a CTA and the next heading, which read as
   a gap rather than a break. */
section{padding:clamp(28px,2.4vw,44px) 0}

/* ---------- buttons: only these four exist ---------- */
.btn{display:inline-flex;align-items:center;justify-content:center;gap:9px;
  font-family:var(--sans);font-size:13px;font-weight:600;letter-spacing:.1em;
  text-transform:uppercase;text-decoration:none;padding:15px 28px;border-radius:999px;
  border:2px solid transparent;cursor:pointer;transition:all .3s var(--ease)}
.btn-p{background:var(--amber);color:#1A0600;border-color:var(--amber)}
.btn-p:hover{background:var(--amber-2);border-color:var(--amber-2);color:#fff;transform:translateY(-2px)}
.btn-s{background:transparent;color:var(--ink);border-color:var(--ink)}
.btn-s:hover{background:var(--ink);color:#fff;transform:translateY(-2px)}
.btn-l{background:#fff;color:var(--ink);border-color:#fff}
.btn-l:hover{background:var(--amber);border-color:var(--amber);color:#1A0600;transform:translateY(-2px)}
.btn-o{background:transparent;color:#fff;border-color:rgba(255,255,255,.55)}
.btn-o:hover{background:rgba(255,255,255,.12);border-color:#fff;transform:translateY(-2px)}
.btn-row{display:flex;flex-wrap:wrap;gap:12px;margin-top:30px}

/* ---------- reveal (gated on .js, killed by reduced motion) ---------- */
.rv{opacity:1;transform:none}
.js .rv{opacity:0;transform:translateY(22px);transition:opacity .7s var(--ease),transform .7s var(--ease)}
.js .rv.in{opacity:1;transform:none}
@media (prefers-reduced-motion:reduce){
  .js .rv{opacity:1!important;transform:none!important;transition:none}
  html{scroll-behavior:auto}
}

/* ---------- ribbon + header ---------- */
/* Ribbon was a full-width band of bright orange, which is the single most
   tiring element on a page this dark. It is now a quiet dark strip with the
   orange used only on the rating, the way Velocity Restorations does it. */
.ribbon{background:#06070A;color:var(--body-d);font-size:12.5px;font-weight:500;
  letter-spacing:.03em;padding:10px 16px;display:flex;justify-content:center;
  align-items:center;gap:22px;flex-wrap:wrap;border-bottom:1px solid var(--line-d)}
.ribbon b{color:var(--amber)}
.ribbon .rt{color:var(--amber);letter-spacing:1.5px}
.ribbon a{text-decoration:none;color:var(--paper);border-bottom:1px solid rgba(255,255,255,.28)}
.ribbon a:hover{border-bottom-color:var(--amber);color:var(--amber)}
.ribbon .sep{opacity:.28}
@media(max-width:860px){.ribbon .hide-sm{display:none}}
.head{position:sticky;top:0;z-index:60;background:rgba(11,12,14,.9);
  backdrop-filter:blur(14px);border-bottom:1px solid var(--line-d);
  transition:padding .35s var(--ease)}
/* padding-block, never the `padding` shorthand: this element is also a
   .wrap, and the shorthand wipes out the side gutter, leaving the logo hard
   against the left edge and the burger against the right at every width
   below --wrap. */
.head-in{display:flex;align-items:center;justify-content:space-between;gap:20px;
  padding-block:10px;transition:padding .35s var(--ease)}
.head.shrink .head-in{padding-block:6px}
/* Brand mark: the client's own logo file, used as-is. Do not substitute a
   typographic wordmark. The badge already contains the name, so no text
   is set beside it. */
.brand{display:block;text-decoration:none;flex:0 0 auto}
.brand img{height:86px;width:auto;transition:height .35s var(--ease)}
.head.shrink .brand img{height:68px}
@media(max-width:700px){.brand img{height:62px}.head.shrink .brand img{height:54px}}
.nav{display:flex;gap:26px;list-style:none;align-items:center}
.nav a{text-decoration:none;color:var(--body-d);font-size:16px;font-weight:500;
  padding:6px 0;border-bottom:2px solid transparent;transition:.25s}
.nav a:hover,.nav a.active{color:var(--paper);border-bottom-color:var(--amber)}
/* Menu mirrors the live site: Home, About, Services, Services Areas,
   Testimonials, Contact, with the same two dropdowns. "Services Areas"
   is the client's own spelling, carried over deliberately. */
.nav>li{position:relative}
.nav .has-sub>a::after{content:"";display:inline-block;vertical-align:-1px;
  margin-left:7px;opacity:.7;background-color:currentColor;-webkit-mask:var(--chev) center/contain no-repeat;mask:var(--chev) center/contain no-repeat;width:11px;height:11px;
  transition:transform .25s var(--ease),opacity .25s var(--ease)}
.nav .has-sub:hover>a::after,.nav .has-sub:focus-within>a::after{
  transform:rotate(180deg);opacity:1}
/* The menus are a white card on the dark bar. Orange here is --amber-ink,
   not --amber: the tokens block calls that out as the AA-safe orange for text
   on a light ground, and --amber is tuned for the dark one. */
.nav .sub{position:absolute;left:-10px;top:100%;min-width:246px;list-style:none;
  background:var(--white);border:1px solid var(--line);border-radius:14px;
  padding:8px;display:block;opacity:0;visibility:hidden;transform:translateY(8px);
  /* A closed panel must not be hit-testable. visibility:hidden alone is not
     enough here: the mega panel re-shows its nested town lists with
     visibility:visible, and a visible child inside a hidden parent IS
     rendered and IS hoverable. opacity:0 hides it, so the panel became an
     invisible 1376x391 hit area lying over the hero — moving the mouse
     anywhere across the banner opened the Service Areas menu. */
  pointer-events:none;
  box-shadow:0 18px 44px rgba(11,12,14,.26);z-index:80;
  transition:opacity .22s var(--ease),transform .22s var(--ease),visibility .22s}
.nav .has-sub:hover>.sub,.nav .has-sub:focus-within>.sub{
  opacity:1;visibility:visible;transform:none;pointer-events:auto}
.nav .sub li{margin:0}
.nav .sub a{display:block;padding:9px 12px;border-radius:9px;border-bottom:0;
  font-size:14.5px;font-weight:400;color:var(--body);white-space:nowrap}
.nav .sub a:hover,.nav .sub a:focus-visible{
  background:var(--amber-tint);color:var(--amber-ink);border-bottom:0}
/* Third level: each town opens its own twelve location+service pages. It
   flies out beside the town, and to the left where the window is too narrow
   for it to sit on the right. */
.nav .sub-areas .has-sub2{position:relative}
.nav .sub-areas .has-sub2>a::after{content:"";float:right;margin:4px 0 0 10px;
  width:10px;height:10px;opacity:.55;transform:rotate(-90deg);background-color:currentColor;-webkit-mask:var(--chev) center/contain no-repeat;mask:var(--chev) center/contain no-repeat;
  transition:transform .25s var(--ease),opacity .25s var(--ease)}
.nav .sub-areas .has-sub2:hover>a::after,
.nav .sub-areas .has-sub2:focus-within>a::after{opacity:1}
@media(max-width:1180px){
  /* the fly-out swaps to the left of the menu here, so the caret turns with it */
  .nav .sub-areas .has-sub2>a::after{transform:rotate(90deg)}
}
.nav .sub2{position:absolute;left:100%;top:-9px;min-width:212px;list-style:none;
  background:var(--white);border:1px solid var(--line);border-radius:14px;
  padding:8px;opacity:0;visibility:hidden;transform:translateX(6px);
  box-shadow:0 18px 44px rgba(11,12,14,.26);z-index:90;
  transition:opacity .2s var(--ease),transform .2s var(--ease),visibility .2s}
.nav .has-sub2:hover>.sub2,.nav .has-sub2:focus-within>.sub2{opacity:1;visibility:visible;transform:none}
@media(max-width:1180px){.nav .sub2{left:auto;right:100%;transform:translateX(-6px)}}
.head .btn{padding:12px 22px}
/* phone + Free Estimate + burger travel as one right-hand cluster, so the
   number stays beside the button instead of drifting into the gap that
   space-between opens up on a wide header */
.head-cta{display:flex;align-items:center;gap:18px;flex:0 0 auto}
@media(max-width:1180px){.head-cta{gap:14px}}
/* Phone in the sticky bar. The number is already in the proof ribbon, but
   that ribbon sits above the header and scrolls away; the header is what
   stays on screen, so the number has to live here too. It sits immediately
   left of Free Estimate. Below 980px the nav and that button collapse into
   the burger, so the digits drop and the handset stays on its own as a
   tap-to-call target beside the burger. */
.head-tel{display:inline-flex;align-items:center;gap:9px;flex:0 0 auto;
  text-decoration:none;color:var(--paper);font-family:var(--sans);
  font-weight:700;font-size:15px;letter-spacing:.04em;white-space:nowrap;
  padding:8px 2px;border-radius:8px;
  /* The proof ribbon above the header carries the same number and is still
     on screen at the top of the page, so showing both reads as a mistake.
     The ribbon scrolls away, the header does not, so this copy fades in only
     once the header has shrunk onto the top edge. visibility, not display:
     the slot stays reserved so nothing shifts when it appears. */
  opacity:0;visibility:hidden;pointer-events:none;transform:translateX(6px);
  transition:opacity .3s var(--ease),transform .3s var(--ease),
             visibility .3s,color .25s var(--ease)}
.head.shrink .head-tel{opacity:1;visibility:visible;pointer-events:auto;transform:none}
.head-tel svg{width:18px;height:18px;flex:0 0 auto;fill:var(--amber);
  transition:transform .25s var(--ease)}
.head-tel:hover{color:var(--amber)}
.head-tel:hover svg{transform:rotate(-12deg)}
.head-tel:focus-visible{outline:2px solid var(--amber);outline-offset:3px}
@media(max-width:1180px){.head-tel{font-size:14px;gap:7px}}
@media (prefers-reduced-motion:reduce){.head-tel svg{transition:none}}
.burger{display:none;background:none;border:0;cursor:pointer;padding:8px}
.burger i{display:block;width:22px;height:2px;background:var(--paper);margin:5px 0;transition:.3s}
/* 981-1180px: the bar has to carry the logo, six nav items, the phone and
   the estimate button. At the default 26px gap and 16px type that needs about
   1040px, so through this band the nav wrapped onto two and even three lines.
   Tightening the gaps and the type keeps it on one line all the way down to
   981, where the burger takes over. */
@media(min-width:981px) and (max-width:1180px){
  .head-in{gap:12px}
  .nav{gap:15px}
  .nav a{font-size:14.5px}
  .head-cta{gap:10px}
  .head .btn{padding:11px 16px;font-size:11px}
}
@media(max-width:980px){
  .nav,.head .btn{display:none}
  .burger{display:block}
  .head-tel{width:42px;height:42px;padding:0;justify-content:center;
    border:1px solid var(--line-d);border-radius:999px}
  .head-tel .head-tel-n{display:none}
}
/* the bars cross over while the drawer is open */
.burger.open i:nth-child(1){transform:translateY(7px) rotate(45deg)}
.burger.open i:nth-child(2){opacity:0}
.burger.open i:nth-child(3){transform:translateY(-7px) rotate(-45deg)}

/* ---------- Services Areas: mega panel ----------
   The towns used to fly out one at a time on hover, three levels deep. They
   now all sit in a single panel under the bar, each town a column heading
   with its own twelve services beneath it, so every location page is one
   move away instead of two.

   The structure is a plain nested menu -- exactly the shape wp_nav_menu()
   emits -- so a WordPress menu drops straight into these rules:

     li.mega        the Services Areas item.  In wp-admin, type "mega" into
                    that item's CSS Classes field (Screen Options -> CSS
                    Classes if the field is hidden).
     > ul           the panel itself            == ul.sub-menu   (depth 1)
     > li           one town                    == li.menu-item-has-children
     > ul           that town's services        == ul.sub-menu   (depth 2)

   This build calls those .sub-areas / .has-sub2 / .sub2; the selectors below
   accept WordPress's own class names alongside them, so nothing has to be
   renamed on either side. The only markup WordPress will not produce by
   itself is the mobile .sub-toggle button, which wants a short custom walker.

   Desktop only: below 981px the panel falls back to the stacked accordion in
   the mobile block further down, because 96 links opened at once is not a
   phone menu. */
@media(min-width:981px){
  /* the panel spans the content width, so it is measured from the header
     rather than from the one menu item it hangs off */
  .nav .mega{position:static}
  .nav .mega>.sub,
  .nav .mega>.sub-menu{
    left:clamp(16px,4vw,32px);right:clamp(16px,4vw,32px);
    max-width:var(--wrap);margin-inline:auto;min-width:0;
    display:grid;grid-template-columns:repeat(4,minmax(0,1fr));
    gap:16px 12px;padding:20px 18px;
    max-height:calc(100svh - 150px);overflow-y:auto;overscroll-behavior:contain}
  /* eight towns, eight columns, once there is room for them */
  @media(min-width:1240px){
    .nav .mega>.sub,
    .nav .mega>.sub-menu{grid-template-columns:repeat(8,minmax(0,1fr));gap:12px 8px}
  }
  /* The panel hangs below the WHOLE header, which leaves 47px of nothing
     between the menu item and the top of the panel. The mouse crosses that
     gap on its way down, the item stops being hovered, and the panel shuts
     before it can be reached. This is a corridor the width of the screen
     that exists ONLY while the item is hovered, so the closed panel stays
     untouchable and the banner underneath it is not a hover trap. */
  .nav .mega>a{position:relative}
  .nav .mega:hover>a::before,
  .nav .mega:focus-within>a::before{
    content:"";position:absolute;top:100%;left:50%;width:100vw;height:52px;
    transform:translateX(-50%)}

  /* a town is a column, not a fly-out trigger */
  .nav .mega .has-sub2,
  .nav .mega .menu-item-has-children{position:static;display:block}
  .nav .mega .has-sub2>a,
  .nav .mega .menu-item-has-children>a{
    display:block;padding:5px 8px;color:var(--ink);
    font-family:var(--sans);font-size:11.5px;font-weight:600;
    letter-spacing:.14em;text-transform:uppercase;white-space:nowrap;
    border-bottom:1px solid var(--line);border-radius:0;margin-bottom:5px}
  .nav .mega .has-sub2>a:hover,
  .nav .mega .has-sub2>a:focus-visible,
  .nav .mega .menu-item-has-children>a:hover,
  .nav .mega .menu-item-has-children>a:focus-visible{
    background:none;color:var(--amber-ink)}
  /* the caret pointed at a fly-out that no longer exists */
  .nav .mega .has-sub2>a::after,
  .nav .mega .menu-item-has-children>a::after{content:none}
  /* that town's services: a plain list in the column, always open */
  .nav .mega .sub2,
  .nav .mega .sub-menu .sub-menu{
    position:static;opacity:1;visibility:visible;transform:none;display:block;
    min-width:0;padding:0;margin:0;list-style:none;
    background:none;border:0;box-shadow:none;backdrop-filter:none}
  .nav .mega .sub2 a,
  .nav .mega .sub-menu .sub-menu a{
    padding:4px 8px;font-size:13.5px;white-space:normal;line-height:1.35}
}

/* ---------- touch targets ----------
   The footer link columns are 15px tall, well under the ~30px a thumb needs.
   The padding goes on the link rather than the li so the hit area grows
   without moving the text, and the li margin comes off so the rhythm stays
   roughly where it was. Links sitting inside a sentence are left alone —
   padding those breaks the line (WCAG 2.5.8 exempts them). */
@media(max-width:834px){
  .foot-grid>div>ul>li{margin-bottom:0}
  .foot-grid>div>ul>li>a{display:block;padding:8px 0}
  .foot-phone a{display:inline-block;padding:6px 0}
}

/* ---------- mobile: off-canvas drawer ----------
   Carried over from the SDBody build. The drawer is BUILT BY JS from
   <ul class="nav">, walked recursively, so it mirrors the desktop menu at any
   depth and no second copy of the navigation lives in the markup. That is
   also why this nav needs no custom WordPress walker: whatever wp_nav_menu()
   prints for the desktop menu is exactly what the drawer shows.

   White to match the dropdown and the mega panel, since this is those same
   menus on a phone. */
body.scroll-locked{overflow:hidden}
.mobile-backdrop{position:fixed;inset:0;z-index:110;background:rgba(6,7,10,.58);
  opacity:0;visibility:hidden;transition:opacity .4s var(--ease),visibility .4s}
.mobile-backdrop.open{opacity:1;visibility:visible}
.mobile-menu{position:fixed;top:0;right:0;bottom:0;z-index:120;
  width:min(360px,86vw);background:var(--white);color:var(--body);
  display:flex;flex-direction:column;transform:translateX(100%);visibility:hidden;
  transition:transform .45s var(--ease),visibility .45s;
  box-shadow:-24px 0 60px -24px rgba(6,7,10,.55);
  overflow-y:auto;overscroll-behavior:contain}
.mobile-menu.open{transform:none;visibility:visible}
.mobile-menu__head{display:flex;align-items:center;justify-content:space-between;
  gap:12px;padding:15px 16px;border-bottom:1px solid var(--line);
  position:sticky;top:0;background:var(--white);z-index:1}
.mobile-menu__brand{font-family:var(--sans);font-size:11.5px;font-weight:600;
  letter-spacing:.18em;text-transform:uppercase;color:var(--ink)}
.mobile-menu__close{display:grid;place-items:center;width:40px;height:40px;
  flex:0 0 auto;background:none;border:1px solid var(--line);border-radius:999px;
  color:var(--ink);cursor:pointer;transition:color .25s var(--ease),border-color .25s var(--ease)}
.mobile-menu__close svg{width:18px;height:18px}
.mobile-menu__close:hover{color:var(--amber-ink);border-color:var(--amber-ink)}
.mobile-nav{padding:8px 10px 4px}
.mobile-nav ul{list-style:none;margin:0;padding:0}
.mobile-nav a{display:block;padding:11px 10px;border-radius:9px;text-decoration:none;
  color:var(--body);font-size:15.5px;font-weight:500;line-height:1.3}
.mobile-nav a:hover,.mobile-nav a:focus-visible{background:var(--amber-tint);color:var(--amber-ink)}
.mnav-row{display:flex;align-items:center;gap:4px}
.mnav-row>a{flex:1 1 auto;min-width:0}
.mnav-toggle{flex:0 0 auto;width:40px;height:40px;display:grid;place-items:center;
  background:none;border:0;border-radius:9px;color:var(--body);cursor:pointer;
  transition:color .25s var(--ease),background .25s var(--ease)}
.mnav-toggle svg{width:18px;height:18px;transition:transform .3s var(--ease)}
.mnav-toggle:hover,.mnav-toggle:focus-visible{color:var(--amber-ink);background:var(--amber-tint)}
.mnav-has.open>.mnav-row>.mnav-toggle{color:var(--amber-ink)}
.mnav-has.open>.mnav-row>.mnav-toggle svg{transform:rotate(180deg)}
/* 0fr -> 1fr animates the real height, so no max-height has to be guessed
   for a branch whose length is not known until the menu is built */
.mnav-wrap{display:grid;grid-template-rows:0fr;
  transition:grid-template-rows .35s var(--ease)}
.mnav-has.open>.mnav-wrap{grid-template-rows:1fr}
.mnav-wrap>ul{overflow:hidden;min-height:0;padding-left:12px}
.mnav-sub a{font-size:14.5px;font-weight:400}
.mnav-sub .mnav-sub a{font-size:14px}
.mobile-menu__cta{margin-top:auto;display:grid;gap:8px;
  padding:14px 16px calc(16px + env(safe-area-inset-bottom,0px));
  border-top:1px solid var(--line)}
.mobile-menu__cta .btn{width:100%}
.mm-call{display:block;text-align:center;text-decoration:none;padding:9px;
  font-family:var(--sans);font-weight:700;font-size:15px;letter-spacing:.04em;
  color:var(--ink);transition:color .25s var(--ease)}
.mm-call:hover{color:var(--amber-ink)}
@media (prefers-reduced-motion:reduce){
  .mobile-menu,.mobile-backdrop,.mnav-wrap,.mnav-toggle svg,.mobile-menu__close{transition:none}
}

/* ---------- hero: THE VIDEO SLOT ---------- */
.hero{position:relative;min-height:clamp(560px,86svh,860px);display:flex;align-items:flex-end;overflow:hidden;background:var(--ink)}
.hero-media{position:absolute;inset:0}
.hero-media video,.hero-media img{width:100%;height:100%;object-fit:cover}
/* Placeholder stand-in until the client's hero video lands. Deliberately NOT a
   stock photograph of someone else's truck: that would imply a build the shop
   did not do. Swap the whole .ph block for the <video> when the file arrives. */
.ph{position:absolute;inset:0;background:linear-gradient(158deg,#191D22 0%,#0C0E11 54%,#07080A 100%)}
.ph::before{content:"";position:absolute;inset:-12%;
  background:radial-gradient(48% 38% at 24% 44%,rgba(228,120,63,.17),transparent 62%),
             radial-gradient(44% 50% at 78% 64%,rgba(70,130,215,.2),transparent 66%);
  animation:drift 21s var(--ease) infinite alternate}
.ph::after{content:"";position:absolute;top:-40%;bottom:-40%;left:-50%;width:40%;
  background:linear-gradient(100deg,transparent,rgba(255,255,255,.07) 46%,rgba(255,255,255,.12) 52%,transparent);
  transform:skewX(-14deg);animation:sweep 9s var(--ease) infinite}
@keyframes drift{from{transform:scale(1.03)}to{transform:scale(1.1) translate3d(-2%,-1.4%,0)}}
@keyframes sweep{0%{left:-50%}58%,100%{left:125%}}
@media (prefers-reduced-motion:reduce){.ph::before,.ph::after{animation:none}}
.hero-scrim{position:absolute;inset:0;
  background:linear-gradient(to top,rgba(5,6,7,.94) 0%,rgba(5,6,7,.74) 26%,rgba(5,6,7,.2) 60%,rgba(5,6,7,.52) 100%),
             radial-gradient(70% 86% at 14% 92%,rgba(0,0,0,.7),transparent 66%)}
.hero-in{position:relative;z-index:4;width:100%;padding-bottom:clamp(40px,6.5vh,78px);padding-top:120px}
.hero h1{color:var(--paper);max-width:15ch}
.hero-lede{color:#DFDAD3;max-width:46ch;margin-top:20px;font-size:clamp(15.5px,1.7vw,18px)}
.stars{display:flex;align-items:center;gap:10px;font-size:13.5px;color:#DFDAD3;margin-bottom:16px}
.stars b{color:var(--amber);letter-spacing:2px;font-size:15px}
.slot-note{position:absolute;top:104px;right:clamp(16px,4vw,32px);z-index:5;
  background:rgba(11,12,14,.86);border:1px dashed rgba(228,120,63,.65);border-radius:10px;
  padding:11px 14px;max-width:250px;font-size:11px;line-height:1.55;color:#CFC9C2}
.slot-note b{display:block;color:var(--amber);font-size:10px;letter-spacing:.18em;
  text-transform:uppercase;margin-bottom:6px}
@media(max-width:900px){.slot-note{display:none}}

/* ---------- centred hero (inner pages) ----------
   Same video stage as the homepage, but the copy is centred and the section
   is shorter, so an inner page does not open with a full-height hero. */
.hero-center{align-items:center;text-align:center;
  min-height:clamp(420px,62svh,600px)}
.hero-center .hero-in{padding-top:clamp(96px,12vh,132px);
  padding-bottom:clamp(34px,5vh,58px)}
.hero-center h1{max-width:19ch;margin-inline:auto}
/* Service pages keep the client's live H1 word for word (SEO), and some run
   past 80 characters. At the standard size those took 5-6 lines on a phone,
   about 250px of headline, and pushed the buttons below the fold. Headlines
   over 50 characters drop a size and get a wider measure. */
.hero-center h1.h1-long{font-size:clamp(28px,4.4vw,54px);max-width:30ch}
.hero-center .hero-lede{margin-inline:auto;max-width:58ch}
.hero-center .btn-row,.hero-center .stars{justify-content:center}
.hero-crumb{display:flex;align-items:center;justify-content:center;gap:8px;
  font-size:11.5px;font-weight:600;letter-spacing:.16em;text-transform:uppercase;
  color:var(--steel);margin-bottom:16px}
.hero-crumb a{color:var(--steel);text-decoration:none;transition:color .25s var(--ease)}
.hero-crumb a:hover{color:var(--amber)}
.hero-crumb i{font-style:normal;opacity:.5}

/* STANDING RULE (client, 2026-09-21): every section on every inner page must
   use a component that already exists on the homepage. The homepage is the
   basis for all section design. Do not invent new patterns per page. */

/* ---------- about story ----------
   Text left, one photograph right. The centred column left dead space down
   both sides; this fills the width and gives the copy something to sit
   against. The figure is sticky so it stays beside the text while you read. */
.story-split{display:grid;grid-template-columns:1.12fr .88fr;
  gap:clamp(26px,4vw,54px);align-items:start;margin-top:clamp(22px,3vw,34px)}
@media(max-width:900px){.story-split{grid-template-columns:1fr;gap:26px}}
.story-split .story{max-width:none;margin:0}
.story-figure{position:sticky;top:108px;border-radius:var(--r);overflow:hidden;
  border:1px solid var(--line-d);background:var(--ink-3);aspect-ratio:4/5}
.story-figure img{width:100%;height:100%;object-fit:cover;display:block}
.story-figure figcaption{position:absolute;left:0;right:0;bottom:0;
  padding:26px 20px 16px;font-size:12px;letter-spacing:.06em;color:var(--body-d);
  background:linear-gradient(to top,rgba(6,7,9,.92),transparent)}
/* relative, not static, on phones: an overlaid caption needs the figure as
   its containing block (static let one escape 7,400px up the page, measured
   at 390px on the Abita Springs page) */
@media(max-width:900px){.story-figure{position:relative;top:auto;aspect-ratio:16/10}}

/* ---------- about story (shared) ---------- */
.story{max-width:74ch;margin-inline:auto}
.story p{font-size:clamp(15.5px,1.65vw,17.5px);line-height:1.72;margin-bottom:18px}
.story p:last-child{margin-bottom:0}
/* the closing line reads as one sentence: balance the lines and never let
   the link inside it break across two of them */
.story .kicker{text-wrap:balance;font-family:var(--serif);font-size:clamp(20px,2.4vw,26px);
  font-weight:600;line-height:1.35}
.story .kicker a{white-space:nowrap}
/* A centred closing line is a sentence and then its call to action, so
   the link drops onto its own line. A newline in ::before rather than
   display:block, which would push the full stop after the link onto a
   third line of its own. */
.story-center .kicker a::before{content:"\A";white-space:pre}
.story a{color:var(--amber-ink);text-decoration:none;border-bottom:1px solid rgba(166,78,35,.4);
  transition:.25s var(--ease)}
.story a:hover{border-bottom-color:var(--amber-ink)}
.on-dark .story a{color:var(--amber);border-bottom-color:rgba(228,120,63,.45)}
.on-dark .story a:hover{border-bottom-color:var(--amber)}

/* ---------- city page: "All About" block ----------
   The about story split again (with .fit below: the photo follows the
   text's height; 16:10 on phones), then the town's lists in two balanced
   columns of plain text. NO caption under the photo (client, 2026-09-22):
   a photo credit its license requires goes in the footer's small print
   (.foot-credit). No cards below: the lists run to very different lengths,
   and equal-height cards would leave empty boxes, the "big space" the
   client flagged on the service boards. */
.area-shot img{object-position:58% 50%}
/* .fit (city pages): the photo takes the height of the text beside it, from
   320px up to 640px, so short copy never leaves a hole under the text
   (Covington's overview text ended 208px above its 4:5 photo). Long copy
   keeps a 640px photo that stays in view while you read. */
.story-split.fit{align-items:stretch}
.story-split.fit .story-figure{aspect-ratio:auto;align-self:stretch;min-height:320px;max-height:640px}
.story-split.fit .story-figure img{position:absolute;inset:0}
@media(max-width:900px){.story-split.fit .story-figure{aspect-ratio:16/10;min-height:0;max-height:none}}
/* The three lists flow through two BALANCED columns, newspaper style: a list
   may carry on at the top of the second column, headings stay with their
   first item, no item splits. Fixed columns could not balance every town
   (Covington's best split left 259px of empty column). */
.area-facts{column-count:2;column-gap:clamp(26px,4vw,54px);
  margin-top:clamp(30px,4vw,48px);padding-top:clamp(26px,3.4vw,40px);
  border-top:1px solid var(--line-d)}
.area-fact+.area-fact{margin-top:clamp(26px,3vw,38px)}
.area-fact h3{margin-bottom:12px;break-after:avoid}
.area-fact p{font-size:15.5px;line-height:1.66;margin-bottom:12px}
.area-fact p,.area-fact li{break-inside:avoid}
.area-fact p:last-child{margin-bottom:0}
/* a list never starts a new column away from its heading or lead-in line
   (Madisonville's "include:" line sat alone at the foot of column one).
   Short lists may split: keeping them whole left too few break points and
   Kenner's columns ended 259px apart. */
.area-fact .q-why{margin-top:14px;break-before:avoid}
.area-fact .q-why li:last-child{margin-bottom:0}
@media(max-width:900px){.area-facts{column-count:1}}

/* ---------- trust strip ----------
   Three figures that count up when the strip scrolls into view, then two
   OFFER tiles. The offers are styled and behave differently from the facts
   on purpose: they are the only things here a visitor can act on. */
.trust{background:var(--ink);padding:clamp(14px,1.8vw,22px) 0;
  border-top:1px solid var(--line-d);position:relative}
/* The band and the section under it are both dark, so the edge vanished.
   A hairline that warms to amber in the middle marks it without shouting. */
.trust::after{content:"";position:absolute;left:0;right:0;bottom:0;height:1px;
  background:linear-gradient(90deg,transparent,rgba(255,255,255,.14) 14%,
    rgba(228,120,63,.5) 50%,rgba(255,255,255,.14) 86%,transparent)}
/* This band is meant to run edge to edge. Leaving it inside the 1440px
   wrap left a dead strip of background either side, which read as the
   band being cut short. */
.trust > .wrap{max-width:none;padding:0 clamp(14px,1.8vw,24px)}
/* Flex, not grid. Grid leaves the odd tile on the last row sitting in one
   track with a hole beside it; flex lets that row grow to fill. Five tiles
   never divide evenly, so this matters at most widths. */
.trust ul{list-style:none;display:flex;flex-wrap:wrap;gap:clamp(8px,.9vw,12px);background:transparent}
.trust li{flex:1 1 178px;background:var(--ink-2);text-align:center;display:flex;
  align-items:center;justify-content:center;border:1px solid var(--line-d);
  border-radius:var(--r);overflow:hidden;position:relative;
  transition:background .3s var(--ease),border-color .3s var(--ease),transform .3s var(--ease)}
.trust li:hover{background:var(--ink-3);border-color:rgba(255,255,255,.22)}
.tf{display:block;padding:20px 18px;width:100%}
.tf b{display:block;font-family:var(--serif);font-size:clamp(26px,3vw,34px);color:var(--amber);
  font-weight:700;line-height:1;font-variant-numeric:tabular-nums}
.tf span{display:block;margin-top:6px;font-size:11.5px;font-weight:500;letter-spacing:.14em;
  text-transform:uppercase;color:var(--body-d)}
/* On a phone the three figures share one row and the two offers take a full
   row each, so the band stays three rows instead of five stacked cards. */
@media(max-width:620px){
  .trust li{flex:1 1 calc(33.333% - 8px)}
  .trust li.is-offer{flex:1 1 100%}
  .tf{padding:16px 8px}
  .tf span{font-size:10px;letter-spacing:.1em}
}
/* offer tiles */
.trust li.is-offer{background:linear-gradient(180deg,rgba(228,120,63,.13),rgba(228,120,63,.04))}
.trust li.is-offer:hover{background:linear-gradient(180deg,rgba(228,120,63,.24),rgba(228,120,63,.08));
  border-color:rgba(228,120,63,.55);transform:translateY(-3px)}
.to{display:block;padding:18px 16px;text-decoration:none;position:relative;overflow:hidden;width:100%}
.to i{display:grid;place-items:center;width:28px;height:28px;margin:0 auto 8px;border-radius:50%;
  background:var(--amber);color:#1A0600;font-style:normal;font-size:16px;font-weight:700;
  transition:transform .35s var(--ease)}
.to:hover i{transform:scale(1.12) rotate(-6deg)}
.to i svg{width:14px;height:14px;fill:currentColor;display:block}
.to b{display:block;font-family:var(--serif);font-size:clamp(17px,1.8vw,20px);color:var(--paper);
  font-weight:700;line-height:1.1}
.to em{display:block;font-style:normal;font-size:12px;color:var(--body-d);margin-top:5px;line-height:1.4}
.to u{display:inline-block;margin-top:9px;text-decoration:none;font-size:10.5px;font-weight:700;
  letter-spacing:.16em;text-transform:uppercase;color:var(--amber);transition:.3s var(--ease)}
.to:hover u{letter-spacing:.2em}

/* A slow shine crossing every tile, so the whole band reads as live.
   Staggered so they do not all flash together, and brighter on the two
   offer tiles since those are the ones a visitor can act on. */
.trust li::after{content:"";position:absolute;inset:0;pointer-events:none;
  background:linear-gradient(105deg,transparent 38%,rgba(255,255,255,.09) 48%,transparent 58%);
  transform:translateX(-100%);animation:toShine 5.5s var(--ease) infinite}
.trust li.is-offer::after{
  background:linear-gradient(105deg,transparent 38%,rgba(255,255,255,.14) 48%,transparent 58%)}
.trust li:nth-child(1)::after{animation-delay:0s}
.trust li:nth-child(2)::after{animation-delay:.45s}
.trust li:nth-child(3)::after{animation-delay:.9s}
.trust li:nth-child(4)::after{animation-delay:1.35s}
.trust li:nth-child(5)::after{animation-delay:1.8s}
@keyframes toShine{0%{transform:translateX(-100%)}55%,100%{transform:translateX(100%)}}
@media (prefers-reduced-motion:reduce){.trust li::after{animation:none;opacity:0}}

/* ---------- process: the build tacho ----------
   Five stages laid out as a rev counter sweeping from idle to redline. The
   needle points at the active stage, the stage list sits alongside, and the
   copy is the client's own split across five stages instead of three. */
.proc{background:var(--ink);color:var(--body-d)}
.tc-grid{display:grid;grid-template-columns:1fr 1.05fr;gap:clamp(24px,4vw,56px);
  align-items:center;margin-top:clamp(30px,4vw,50px)}
@media(max-width:900px){.tc-grid{grid-template-columns:1fr;gap:30px}}
.tc-dial{position:relative;max-width:520px;width:100%;margin-inline:auto}
.tc-svg{display:block;width:100%;height:auto;overflow:visible}
.tc-arc{fill:none;stroke-width:16;stroke-linecap:butt;opacity:.16;transition:opacity .45s var(--ease)}
.tc-arc.on{opacity:1;filter:drop-shadow(0 0 8px var(--g))}
.tc-tick{stroke:rgba(255,255,255,.28);stroke-width:2}
.tc-numl{fill:var(--steel);font:600 15px/1 var(--sans);letter-spacing:.06em;text-anchor:middle}
.tc-numl.on{fill:var(--paper);filter:drop-shadow(0 0 6px rgba(255,255,255,.5))}
.tc-needle{transform-origin:200px 200px;transition:transform .85s cubic-bezier(.34,1.3,.5,1)}
.tc-needle path{fill:var(--nc,#F7D14A);filter:drop-shadow(0 0 8px var(--nc,#F7D14A));transition:fill .4s var(--ease),filter .4s var(--ease)}
.tc-needle.revving{transition:transform .15s linear}
.tc-hub{fill:var(--ink-3);stroke:rgba(255,255,255,.22);stroke-width:2}
.tc-read{text-align:center;margin-top:2px}
.tc-read b{display:block;font-family:var(--serif);font-size:clamp(30px,4vw,46px);
  font-weight:700;color:var(--paper);line-height:1}
.tc-read span{display:block;font-size:10px;font-weight:600;letter-spacing:.3em;
  text-transform:uppercase;color:var(--steel);margin-top:6px}
.tc-redline{fill:#E85C33;font:700 11px/1 var(--sans);letter-spacing:.2em;text-anchor:middle}
/* stage list */
.tc-list{display:flex;flex-direction:column;gap:8px}
.tc-step{display:grid;grid-template-columns:auto 1fr;gap:15px;align-items:start;
  width:100%;text-align:left;cursor:pointer;background:transparent;
  border:1px solid transparent;border-radius:14px;padding:14px 16px;
  color:var(--body-d);font-family:var(--sans);transition:.35s var(--ease)}
.tc-step:hover{background:rgba(255,255,255,.035);border-color:var(--line-d)}
.tc-step.on{background:var(--ink-3);border-color:rgba(228,120,63,.4)}
.tc-step b{display:grid;place-items:center;width:34px;height:34px;border-radius:9px;
  background:rgba(255,255,255,.06);color:var(--steel);font-size:12.5px;font-weight:700;
  transition:.35s var(--ease)}
.tc-step.on b{background:var(--amber);color:#1A0600}
.tc-step h3{font-size:17.5px;color:var(--body-d);margin:0;transition:color .35s var(--ease);
  font-family:var(--serif);font-weight:600;line-height:1.25}
.tc-step.on h3{color:var(--paper)}
.tc-step p{margin:0;max-height:0;overflow:hidden;opacity:0;font-size:15px;line-height:1.6;
  transition:max-height .5s var(--ease),opacity .4s var(--ease),margin .4s var(--ease)}
.tc-step.on p{max-height:180px;opacity:1;margin-top:9px}
.tc-foot{display:flex;flex-wrap:wrap;gap:12px;align-items:center;margin-top:22px;padding-left:16px}
@media (prefers-reduced-motion:reduce){
  .tc-needle,.tc-arc,.tc-step,.tc-step p{transition:none}
}

/* ---------- services: the bay board ----------
   Not a card grid. A numbered job board on the left, a workshop bay on the
   right. Picking a job rolls the bay door up over the photograph, the way a
   shop door opens, and the spec underneath changes with it. The two
   columns always finish together (see .bay-panel). */
.bay{display:grid;grid-template-columns:.92fr 1.08fr;gap:clamp(20px,3vw,44px);
  align-items:stretch;margin-top:clamp(28px,4vw,46px)}
@media(max-width:900px){.bay{grid-template-columns:1fr;gap:18px}}

.bay-list{display:flex;flex-direction:column;border-top:1px solid var(--line)}
.bay-row{display:grid;grid-template-columns:auto 1fr auto;align-items:center;gap:14px;
  width:100%;text-align:left;background:none;cursor:pointer;
  border:0;border-bottom:1px solid var(--line);padding:15px 4px;
  font-family:var(--sans);color:var(--body);position:relative;
  transition:padding .35s var(--ease),color .35s var(--ease)}
/* the amber bar that grows in from the left on the active job */
.bay-row::before{content:"";position:absolute;left:-4px;top:0;bottom:0;width:3px;
  background:var(--amber-ink);transform:scaleY(0);transform-origin:center;
  transition:transform .4s var(--ease)}
.bay-row:hover{padding-left:12px;color:var(--ink)}
a.bay-row{text-decoration:none}
.bay-row.on{padding-left:14px}
.bay-row.on::before{transform:scaleY(1)}
.bay-no{font-family:var(--serif);font-size:13px;font-weight:700;color:var(--steel);
  min-width:26px;transition:color .35s var(--ease);font-variant-numeric:tabular-nums}
.bay-row.on .bay-no,.bay-row:hover .bay-no{color:var(--amber-ink)}
.bay-name{font-family:var(--serif);font-size:clamp(16px,1.7vw,19px);font-weight:600;
  color:var(--ink);line-height:1.2}
.bay-row.on .bay-name{color:var(--amber-ink)}
.bay-tick{font-size:15px;color:var(--steel);opacity:0;transform:translateX(-6px);
  transition:.35s var(--ease)}
.bay-row.on .bay-tick,.bay-row:hover .bay-tick{opacity:1;transform:none;color:var(--amber-ink)}
/* Group tag after a bay row's name. Service pages use it for the live H3 a row
   sits under (Audio / Lighting / Integration), which tells apart three rows
   that are all called some kind of "Integration". The bay script copies the
   row name into the panel title, tag and all, so the title carries it too. */
.bay-grp{font-style:normal;font-family:var(--sans);font-size:9.5px;font-weight:700;
  letter-spacing:.16em;text-transform:uppercase;color:var(--steel);margin-left:10px;
  vertical-align:middle;white-space:nowrap;transition:color .35s var(--ease)}
.bay-row.on .bay-grp,.bay-row:hover .bay-grp{color:var(--amber-ink)}
.bay-meta .bay-grp{font-size:10px;margin-left:12px}
.bay-row.is-new .bay-name::after{content:"NEW";margin-left:9px;font-family:var(--sans);
  font-size:9px;font-weight:700;letter-spacing:.14em;vertical-align:middle;
  color:var(--amber-2);border:1px solid var(--amber-2);border-radius:3px;padding:2px 5px}

/* Short bay variant. With only six jobs the list runs about half the height
   of the panel and leaves a large hole beneath it. Here the rows stretch to
   meet the panel and the stage is a little shallower, so the two columns
   finish together. The homepage keeps its twelve rows and its sticky panel
   untouched. */
.bay.bay-short{align-items:stretch}
.bay.bay-short .bay-panel{position:static}
.bay.bay-short .bay-stage{aspect-ratio:16/11}
.bay.bay-short .bay-list{justify-content:stretch}
.bay.bay-short .bay-row{flex:1 1 auto;min-height:62px}

/* Compact bay, for service pages with only four or five jobs. Stretching four
   rows to a 680px panel made each row 150px tall, so here the spec moves under
   the list and the photograph fills the other column instead. */
.bay.bay-compact .bay-col{display:flex;flex-direction:column}
.bay.bay-compact .bay-col>.bay-list{flex:0 0 auto}
.bay.bay-compact .bay-col>.bay-meta{padding:24px 2px 0}
.bay.bay-compact .bay-stage{aspect-ratio:auto;min-height:340px}
@media(max-width:900px){
  .bay.bay-compact .bay-col{display:contents}
  .bay.bay-compact .bay-list{order:1}
  .bay.bay-compact .bay-panel{order:2}
  .bay.bay-compact .bay-meta{order:3;padding-top:2px}
  .bay.bay-compact .bay-stage{aspect-ratio:4/3;min-height:0}
}

/* the bay itself */
/* both columns end together: the panel is a column whose photograph grows
   to fill any extra height, and the list rows share any extra height */
.bay-panel{display:flex;flex-direction:column}
.bay-list>.bay-row{flex:1 1 auto}
.bay-stage{position:relative;border-radius:var(--r);overflow:hidden;
  aspect-ratio:4/3;background:var(--ink-3);flex:1 0 auto}
.bay-img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover;
  opacity:0;clip-path:inset(100% 0 0 0);transform:scale(1.06);
  transition:opacity .55s var(--ease),clip-path .65s var(--ease),transform .9s var(--ease)}
.bay-img.on{opacity:1;clip-path:inset(0 0 0 0);transform:scale(1)}
/* the roll-up door: slats that lift away as the job changes */
.bay-door{position:absolute;inset:0;pointer-events:none;z-index:3;
  background:repeating-linear-gradient(to bottom,
    rgba(12,14,17,.96) 0 14px, rgba(24,27,32,.96) 14px 16px);
  transform:translateY(-101%);transition:transform .6s var(--ease)}
.bay-door.shut{transform:translateY(0)}
.bay-meta{padding:20px 2px 0}
.bay-meta h3{font-size:clamp(20px,2.3vw,26px);margin-bottom:9px;
  transition:opacity .4s var(--ease),transform .4s var(--ease)}
.bay-meta p{font-size:15.5px;line-height:1.62;max-width:52ch;
  transition:opacity .4s var(--ease),transform .4s var(--ease)}
.bay-meta.swap h3,.bay-meta.swap p{opacity:0;transform:translateY(8px)}
.bay-cta{margin-top:20px}
@media (prefers-reduced-motion:reduce){
  .bay-img,.bay-door,.bay-row,.bay-row::before,.bay-meta h3,.bay-meta p{transition:none}
  .bay-door{display:none}
}

/* ---------- builds: collection carousel ----------
   Pattern taken from the Gunther Werks collection: light ground, the active
   vehicle centred and full colour, its neighbours scaled back, desaturated
   and half off-frame, then the model name, spec pills, circular arrows and
   one outlined CTA underneath. */
.builds{background:var(--ink);overflow:hidden}
.bc-head{text-align:center;max-width:none;margin-inline:auto}
.bc-head .lead,.bc-head p{margin-inline:auto}
.bc-head h2{letter-spacing:.01em}
.bc-head .bc-lede{max-width:58ch;margin-inline:auto}
.bc-stage{position:relative;height:clamp(220px,33vw,430px);
  margin-top:clamp(26px,4vw,46px)}
.bc-slide{position:absolute;top:0;left:50%;height:100%;
  width:min(60%,740px);margin-left:calc(min(60%,740px) / -2);
  border-radius:var(--r);overflow:hidden;background:var(--ink-3);
  transition:transform .75s var(--ease),opacity .75s var(--ease),filter .75s var(--ease);
  will-change:transform,opacity}
.bc-slide img{width:100%;height:100%;object-fit:cover;display:block}
.bc-slide.is-active{transform:none;opacity:1;filter:none;z-index:3;
  box-shadow:0 26px 62px rgba(11,12,14,.2)}
.bc-slide.is-prev{transform:translateX(-84%) scale(.86);opacity:.5;filter:brightness(.62);z-index:2}
.bc-slide.is-next{transform:translateX(84%) scale(.86);opacity:.5;filter:brightness(.62);z-index:2}
.bc-slide.is-far{transform:scale(.72);opacity:0;z-index:1;pointer-events:none}
.bc-meta{text-align:center;margin-top:clamp(22px,3vw,34px)}
.bc-name{font-family:var(--serif);font-weight:600;color:var(--paper);line-height:1.05;
  font-size:clamp(26px,3.6vw,42px);letter-spacing:-.01em}
.bc-pills{display:flex;flex-wrap:wrap;gap:9px;justify-content:center;margin-top:15px}
.bc-pill{background:rgba(255,255,255,.06);border:1px solid var(--line-d);border-radius:999px;
  padding:7px 15px;font-size:10.5px;font-weight:600;letter-spacing:.15em;
  text-transform:uppercase;color:var(--body-d)}
.bc-nav{display:flex;gap:11px;justify-content:center;margin-top:clamp(18px,2.4vw,26px)}
.bc-arrow{width:46px;height:46px;border-radius:50%;display:grid;place-items:center;
  background:rgba(255,255,255,.06);border:1px solid var(--line-d);cursor:pointer;color:var(--paper);
  font:400 18px/1 var(--sans);transition:.3s var(--ease)}
.bc-arrow:hover{background:var(--amber);border-color:var(--amber);color:#1A0600;transform:translateY(-2px)}
.bc-arrow:focus-visible{outline:2px solid var(--amber-ink);outline-offset:3px}
.bc-explore{display:flex;justify-content:center;margin-top:clamp(18px,2.4vw,26px)}
.bc-dots{display:flex;gap:7px;justify-content:center;margin-top:18px}
.bc-dots button{width:7px;height:7px;padding:0;border-radius:50%;cursor:pointer;
  border:0;background:rgba(255,255,255,.22);transition:.3s var(--ease)}
.bc-dots button[aria-current="true"]{background:var(--amber);width:20px;border-radius:99px}
@media(max-width:760px){
  .bc-slide{width:82%;margin-left:-41%}
  .bc-slide.is-prev{transform:translateX(-96%) scale(.84)}
  .bc-slide.is-next{transform:translateX(96%) scale(.84)}
}
@media (prefers-reduced-motion:reduce){
  .bc-slide{transition:none}
}

/* ---------- reviews: the plate wall ----------
   Each customer gets a Louisiana plate: state name up top, stars where the
   registration goes, their parish town stamped across it, bolt holes and all.
   The card under it carries the quote and what we built. Regional, and it
   could not belong to any other kind of business. */
.revs{display:grid;grid-template-columns:repeat(auto-fit,minmax(min(300px,100%),1fr));
  gap:20px;margin-top:clamp(24px,3vw,38px)}
/* Four reviews read better as a balanced 2x2 than as 3 plus an orphan on a
   second row, so the dedicated testimonials page caps the grid at two
   columns. Same variant pattern as .bay.bay-short. */
@media(min-width:900px){.revs.revs-2{grid-template-columns:repeat(2,1fr)}}
.rev{background:var(--ink-3);border:1px solid var(--line-d);border-radius:var(--r);
  padding:clamp(18px,2vw,24px);display:flex;flex-direction:column;
  transition:transform .35s var(--ease),border-color .35s var(--ease),
             box-shadow .35s var(--ease)}
.rev:hover{transform:translateY(-5px);border-color:rgba(228,120,63,.4);
  box-shadow:0 20px 44px rgba(11,12,14,.45)}

/* the plate */
.plate{position:relative;border-radius:9px;padding:9px 14px 10px;
  background:linear-gradient(180deg,#FCFAF6 0%,#F1EDE4 60%,#E4DFD4 100%);
  border:2px solid #CFC7B8;
  box-shadow:inset 0 0 0 2px rgba(255,255,255,.75),0 3px 10px rgba(0,0,0,.45);
  text-align:center;overflow:hidden}
/* bolt holes */
.plate::before,.plate::after{content:"";position:absolute;top:7px;width:7px;height:7px;
  border-radius:50%;background:radial-gradient(circle at 35% 30%,#9A9285,#5E584E);
  box-shadow:inset 0 1px 1px rgba(0,0,0,.5)}
.plate::before{left:9px}
.plate::after{right:9px}
.plate-state{font-family:var(--sans);font-size:8.5px;font-weight:700;letter-spacing:.34em;
  text-transform:uppercase;color:#9A5A22;line-height:1}
.plate-num{font-family:var(--serif);font-weight:700;color:#1B242E;line-height:1;
  font-size:clamp(17px,2vw,21px);letter-spacing:.1em;margin-top:5px;
  display:flex;align-items:center;justify-content:center;gap:9px;
  text-shadow:0 1px 0 rgba(255,255,255,.9)}
.plate-num em{font-style:normal;color:#B4551E;letter-spacing:1px;font-size:.78em}
.plate-foot{font-family:var(--sans);font-size:7.5px;font-weight:700;letter-spacing:.24em;
  text-transform:uppercase;color:#7C7466;margin-top:5px}

.rev-quote{margin:18px 0 0;font-size:15.5px;line-height:1.68;color:var(--body-d);flex:1 1 auto}
.rev-who{margin-top:16px;padding-top:14px;border-top:1px solid var(--line-d);
  display:flex;flex-direction:column;gap:3px}
.rev-who b{font-family:var(--serif);font-size:16px;font-weight:600;color:var(--paper)}
.rev-who span{font-size:10.5px;font-weight:600;letter-spacing:.14em;text-transform:uppercase;
  color:var(--amber)}
@media (prefers-reduced-motion:reduce){.rev{transition:none}}

/* Blog post card. A variant of the review card above, not a new component:
   the same .rev shell (ink card, 20px radius, amber hover lift), an image
   frame on the .bay-stage pattern, and a .bc-pill category tag. Headings
   default to ink, which vanishes on an ink card, so the title colour is set
   here explicitly. Same variant approach as .revs-2 and .bay-short. */
.rev.rev-post{padding:0;overflow:hidden}
.rev-post .rp-img{aspect-ratio:16/10;overflow:hidden;background:var(--ink-2)}
.rev-post .rp-img img{width:100%;height:100%;object-fit:cover;display:block;
  transition:transform .9s var(--ease)}
.rev-post:hover .rp-img img{transform:scale(1.05)}
.rev-post .rp-body{padding:clamp(18px,2vw,24px);display:flex;flex-direction:column;
  align-items:flex-start;gap:12px;flex:1 1 auto}
.rev-post .bc-pill{padding:6px 13px;font-size:10px;color:var(--amber);
  border-color:rgba(228,120,63,.35);background:rgba(228,120,63,.08)}
.rev-post h3{color:var(--paper);font-size:clamp(19px,1.9vw,22px);line-height:1.22}
.rev-post p{font-size:15px;line-height:1.62;color:var(--body-d)}
/* Publish date: the review card's footer row (.rev-who) reused, a hairline
   divider with an amber micro-label under it. margin-top:auto pins it to the
   bottom of the card, so dates line up across the grid whatever the title
   length. */
.rev-post .rp-date{margin-top:auto;width:100%;padding-top:14px;
  border-top:1px solid var(--line-d);display:flex;align-items:center;gap:8px;
  font-size:10.5px;line-height:1.3;font-weight:600;letter-spacing:.14em;
  text-transform:uppercase;color:var(--amber)}
.rev-post .rp-date svg{width:14px;height:14px;flex:0 0 auto;fill:none;
  stroke:currentColor;stroke-width:2;stroke-linecap:round;stroke-linejoin:round}
/* A card whose post exists: the title link is stretched over the whole card,
   so the card is one click target and a screen reader still hears the title.
   The focus ring is drawn on the stretched layer so it traces the card. */
.rev-post{position:relative}
.rev-post h3 a{color:inherit;text-decoration:none}
.rev-post h3 a::after{content:"";position:absolute;inset:0;z-index:1;border-radius:var(--r)}
.rev-post h3 a:focus-visible{outline:none}
.rev-post h3 a:focus-visible::after{outline:2px solid var(--amber);outline-offset:-3px}
.rev-post .rp-read{margin-left:auto;color:var(--paper);transition:color .3s var(--ease)}
/* Service pages put the live page's bullet lists inside the cards. */
.rev-post .q-why{margin:0}
.rev-post .q-why li{font-size:14.5px;line-height:1.55;margin-bottom:9px;color:var(--body-d)}
.rev-post .q-why li:last-child{margin-bottom:0}
.rev-post .q-why b{color:var(--paper);font-weight:600}
.rev-post:hover .rp-read{color:var(--amber)}

/* ---------- blog post: the model every post follows ----------
   Built from homepage parts: the hero (a still instead of the video), the bay
   board's numbered rows as the table of contents, the About page's .story
   prose, .q-why check lists, the review-card shell for the rail call to
   action and the blog card for related posts. Long-form text needs a few
   rules the homepage never had (h2/h3 rhythm, a table); they use the same
   tokens throughout. */
.hero-post{min-height:clamp(460px,66svh,640px)}
/* A photograph is far brighter than the night-time hero video, and the
   standard scrim is weighted to the bottom-left. Post heroes get a heavier,
   centre-weighted scrim so the headline, and the amber keyword in particular,
   stays readable over any image (a red truck behind amber text was the case
   that caught this). */
.hero-post .hero-scrim{background:
  radial-gradient(75% 70% at 50% 52%,rgba(5,6,7,.8) 0%,rgba(5,6,7,.6) 70%,rgba(5,6,7,.66) 100%),
  linear-gradient(to top,rgba(5,6,7,.9) 0%,rgba(5,6,7,0) 45%)}
.post-meta{display:flex;flex-wrap:wrap;align-items:center;justify-content:center;
  gap:10px 14px;margin-top:18px;font-size:11.5px;font-weight:600;letter-spacing:.14em;
  text-transform:uppercase;color:#DFDAD3}
.post-meta .bc-pill{padding:6px 13px;font-size:10px;color:var(--amber);
  border-color:rgba(228,120,63,.45);background:rgba(228,120,63,.12)}
.post-meta i{font-style:normal;opacity:.45}

.art-grid{display:grid;grid-template-columns:minmax(0,280px) minmax(0,1fr);
  gap:clamp(28px,5vw,72px);align-items:start}
.art-rail{position:sticky;top:124px}
@media(max-width:960px){.art-grid{grid-template-columns:minmax(0,1fr)}.art-rail{position:static}}
.art-rail > .eyeb{margin-bottom:12px}
.toc a.bay-row{text-decoration:none;padding-top:12px;padding-bottom:12px}
.toc .bay-name{font-size:15.5px}
.rail-cta.rev{margin-top:24px;padding:22px}
.rail-cta h3{color:var(--paper);font-size:20px;margin-bottom:8px}
.rail-cta p{font-size:14.5px;line-height:1.6;color:var(--body-d);margin-bottom:16px}
.rail-cta .btn{width:100%;justify-content:center;text-align:center;
  /* the rail is 280px: at the standard 28px side padding the phone number
     needed 176px and got 175px, so it broke mid-number. 16px gives 201px. */
  padding-left:16px;padding-right:16px;white-space:nowrap}
.rail-cta .btn + .btn{margin-top:10px}

.story.art-body{max-width:72ch;margin:0}
.art-body h2{font-size:clamp(25px,2.8vw,34px);margin:clamp(34px,4vw,48px) 0 14px}
.art-body h3{font-size:clamp(19px,2vw,22px);margin:26px 0 10px}
.art-body .q-why{margin:4px 0 22px}
.art-body .q-why li{font-size:clamp(15.5px,1.65vw,17px);line-height:1.65}
.art-body .q-why li::before{border-color:var(--amber-ink)}
.art-body .q-why b,.art-body p b{color:var(--ink);font-weight:600}
/* quick answer: the offer tile's amber wash with the bay row's amber bar */
.art-quick{position:relative;margin:6px 0 30px;padding:20px 22px 20px 28px;
  border-radius:var(--r);border:1px solid rgba(166,78,35,.22);
  background:linear-gradient(180deg,rgba(228,120,63,.11),rgba(228,120,63,.04))}
.art-quick::before{content:"";position:absolute;left:0;top:18px;bottom:18px;width:3px;
  border-radius:3px;background:var(--amber-ink)}
.art-quick .eyeb{margin-bottom:8px}
.story .art-quick p{margin:0;color:var(--ink);font-size:clamp(15.5px,1.65vw,17px);line-height:1.66}
/* cost table */
.art-table-wrap{margin:10px 0 8px;border-radius:var(--r);border:1px solid var(--line);
  overflow-x:auto;background:rgba(255,255,255,.55)}
.art-table{width:100%;border-collapse:collapse;font-size:15px;line-height:1.5}
.art-table th{background:var(--ink);color:var(--paper);text-align:left;padding:13px 16px;
  font-size:10.5px;font-weight:600;letter-spacing:.14em;text-transform:uppercase}
.art-table td{padding:14px 16px;border-top:1px solid var(--line);vertical-align:top}
.art-table td:first-child{font-family:var(--serif);font-weight:600;color:var(--ink)}
.art-table td:last-child{font-weight:600;color:var(--amber-ink);white-space:nowrap}
.story p.art-note{font-size:13px;line-height:1.55;color:var(--steel);margin-bottom:24px}
/* Phones: at 390px the table measured 378px inside a 357px frame and scrolled
   sideways. Each row stacks instead: lift type and price on one line, what
   it raises underneath. The header row is hidden visually but kept for
   screen readers. */
@media(max-width:560px){
  .art-table thead{position:absolute;width:1px;height:1px;overflow:hidden;
    clip:rect(0 0 0 0);clip-path:inset(50%);white-space:nowrap}
  .art-table tr{display:grid;grid-template-columns:minmax(0,1fr) auto;gap:3px 12px;
    padding:14px 16px;border-top:1px solid var(--line)}
  .art-table tbody tr:first-child{border-top:0}
  .art-table td{padding:0;border-top:0}
  .art-table td:nth-child(2){grid-column:1 / -1;grid-row:2;font-size:14px}
}
/* in-article photograph, on the .story-figure pattern */
.art-figure{margin:30px 0;border-radius:var(--r);overflow:hidden;
  border:1px solid var(--line);background:var(--ink-3)}
.art-figure img{display:block;width:100%;aspect-ratio:16/9;object-fit:cover}
.art-figure figcaption{padding:12px 18px;font-size:13px;line-height:1.5;color:var(--body-d)}
@media (prefers-reduced-motion:reduce){.rev-post .rp-img img{transition:none}}

/* ---------- areas: coverage map ----------
   Layout lifted from the Big Easy Bathrooms homepage (head / map card /
   numbered side list). The CONTENT is rebuilt for a car shop: BEB ran water
   through a navy pipe with a drop travelling it. Here the routes are roads
   with amber lane dashes and a pickup driving them, shot at night, which
   suits the brand better than a cream daytime map. Lake Pontchartrain, the
   Mississippi and the parishes are real; pin positions are not to scale. */
.areas{background:var(--ink-2);color:var(--body-d)}
.am-grid{display:grid;grid-template-columns:1.6fr 1fr;gap:clamp(20px,2.6vw,34px);
  align-items:stretch;margin-top:0}
.am-head{grid-column:1/-1;margin-top:0}
.am-lede{max-width:60ch}
.am-card{background:var(--ink-3);border:1px solid var(--line-d);border-radius:var(--r);
  padding:clamp(14px,1.8vw,20px);overflow:hidden;display:flex;flex-direction:column}
.am-prompt{display:flex;align-items:baseline;justify-content:space-between;gap:14px;
  flex-wrap:wrap;margin-bottom:12px}
.am-prompt .eyeb{margin:0}
.am-prompt strong{font-size:12.5px;font-weight:500;color:var(--steel)}
.am-stage{position:relative;border-radius:14px;overflow:hidden;background:#0A0C0F;
  flex:1 1 auto;min-height:260px}
.am-map{display:block;width:100%;height:100%}
.am-land{fill:url(#bcTile)}
.am-water{fill:#101A24}
.am-waves path{fill:none;stroke:#1D2B39;stroke-width:2;animation:bcWave 9s linear infinite}
@keyframes bcWave{to{transform:translateX(60px)}}
.am-river{fill:none;stroke:#141F2B;stroke-width:9;stroke-linecap:round}
.am-wlabel{fill:#5C6672;font:500 15px/1 var(--sans);letter-spacing:.14em;text-transform:uppercase}
.am-small{font-size:12.5px}
.am-home{fill:var(--paper);font-size:16px;letter-spacing:.1em}
/* road: dark asphalt casing with an amber dashed centre line running along it */
.am-road{fill:none;stroke:#252A31;stroke-width:13;stroke-linecap:round;stroke-linejoin:round}
.am-lane{fill:none;stroke:var(--amber);stroke-width:2.4;stroke-linecap:round;stroke-linejoin:round;
  stroke-dasharray:14 20;opacity:.55;animation:bcLane 1.6s linear infinite}
@keyframes bcLane{to{stroke-dashoffset:-34}}
.am-dot .am-core{fill:var(--amber);stroke:#0A0C0F;stroke-width:3}
.am-dot .am-ring{fill:none;stroke:var(--amber);stroke-width:2}
.am-truck{filter:drop-shadow(0 3px 6px rgba(0,0,0,.6))}
@media (prefers-reduced-motion:reduce){
  .am-waves path,.am-lane{animation:none}
  .am-lane{opacity:.45}
  .am-map animate,.am-map animateMotion{display:none}
}
/* Pins sit over the svg in percentage space so they scale with it.
   They are numbered DOTS by default and only open their label on hover,
   focus or when their row is active. Eight labels on a map this size will
   always collide if they are all open at once; hand-tuning coordinates just
   moves the collision somewhere else. One label at a time cannot collide. */
.am-pin{position:absolute;left:var(--px);top:var(--py);
  transform:translate(-50%,-50%);display:flex;align-items:center;gap:0;
  text-decoration:none;white-space:nowrap;
  background:rgba(10,12,15,.9);border:1px solid var(--line-d);border-radius:999px;
  padding:4px;font-size:12px;font-weight:600;color:var(--paper);
  backdrop-filter:blur(6px);z-index:2;
  transition:transform .28s var(--ease),background .28s var(--ease),
             border-color .28s var(--ease),padding .28s var(--ease)}
.am-pin b{display:grid;place-items:center;width:19px;height:19px;border-radius:50%;
  background:var(--amber);color:#1A0600;font-size:10px;font-weight:700;flex:0 0 auto}
.am-pin span{max-width:0;opacity:0;overflow:hidden;
  transition:max-width .3s var(--ease),opacity .25s var(--ease),margin .3s var(--ease)}
.am-pin:hover,.am-pin:focus-visible,.am-pin.on{
  z-index:5;background:var(--amber);border-color:var(--amber);color:#1A0600;
  padding:4px 12px 4px 4px;transform:translate(-50%,-50%) scale(1.04)}
.am-pin:hover b,.am-pin:focus-visible b,.am-pin.on b{background:#1A0600;color:var(--amber)}
.am-pin:hover span,.am-pin:focus-visible span,.am-pin.on span{
  max-width:170px;opacity:1;margin-left:7px}
@media(max-width:700px){
  .am-pin{padding:3px}
  .am-pin b{width:17px;height:17px;font-size:9px}
  .am-pin:hover,.am-pin.on{padding:3px 10px 3px 3px}
}
/* Below about 340px the stage is small enough that even the dots crowd,
   so they shrink again. Checked at 280, 320, 390 and 1500. */
@media(max-width:340px){
  .am-pin{padding:2px}
  .am-pin b{width:14px;height:14px;font-size:8px}
}
.am-note{display:flex;align-items:center;gap:9px;margin-top:13px;font-size:13px;color:var(--steel)}
.am-note svg{flex:0 0 auto}
/* side list */
.am-side{display:flex;flex-direction:column;gap:16px}
.am-list{list-style:none;display:flex;flex-direction:column;gap:7px}
.am-row{display:flex;align-items:center;gap:13px;text-decoration:none;color:var(--body-d);
  background:var(--ink-3);border:1px solid var(--line-d);border-radius:13px;
  padding:12px 15px;transition:.28s var(--ease)}
.am-row b{display:grid;place-items:center;width:27px;height:27px;border-radius:8px;flex:0 0 auto;
  background:rgba(228,120,63,.14);color:var(--amber);font-size:11.5px;font-weight:700}
.am-txt{display:flex;flex-direction:column;line-height:1.25;flex:1 1 auto}
.am-city{font-size:15px;font-weight:600;color:var(--paper)}
.am-txt small{font-size:11.5px;color:var(--steel);letter-spacing:.06em}
.am-row i{font-style:normal;opacity:.4;transition:.28s}
.am-row:hover,.am-row.on{background:var(--amber);border-color:var(--amber);color:#1A0600}
.am-row:hover .am-city,.am-row.on .am-city{color:#1A0600}
.am-row:hover small,.am-row.on small{color:rgba(26,6,0,.72)}
.am-row:hover b,.am-row.on b{background:#1A0600;color:var(--amber)}
.am-row:hover i{opacity:1;transform:translateX(3px)}
.am-cta{display:flex;flex-wrap:wrap;gap:10px}
.am-cta .btn{flex:1 1 auto}
@media(max-width:940px){
  .am-grid{grid-template-columns:1fr}
}

/* ---------- faq: the dashboard ----------
   A cluster of warning lights over a driver display. Pick a light and it
   illuminates amber while the readout below prints the answer. Deliberately
   not another list-and-panel: the lights sit ABOVE the display, the way a
   real cluster does, so this section does not repeat the bay board or the
   coverage map. */
.fq{background:var(--ink-2)}
.dash{margin-top:clamp(22px,3vw,34px)}
.cluster{display:grid;grid-template-columns:repeat(8,1fr);gap:10px}
@media(max-width:1080px){.cluster{grid-template-columns:repeat(4,1fr)}}
@media(max-width:560px){.cluster{grid-template-columns:repeat(4,1fr);gap:7px}}
/* Service pages set --n (questions) and --n-md (half, rounded up) on the
   cluster, so 9 or 10 questions sit in one row on desktop and two even rows
   below 1080px, instead of leaving an orphan. The count used to arrive as an
   inline style and this rule keyed off [style*="--n"]; it now arrives as a
   .cluster-<n>-<n-md> class, so the hook moved to the class. */
/* minmax(0,1fr), not 1fr: a 1fr track refuses to go below its content,
   so the 10-question cluster forced the page 20px wider than a 360px
   phone. minmax(0,…) lets the tracks shrink and the labels wrap. */
.cluster[class*="cluster-"]{grid-template-columns:repeat(var(--n),minmax(0,1fr))}
@media(max-width:1080px){.cluster[class*="cluster-"]{grid-template-columns:repeat(var(--n-md),minmax(0,1fr))}}
.cluster>.tell{min-width:0}
.cluster>.tell b{overflow-wrap:anywhere;hyphens:auto}
.tell{position:relative;display:flex;flex-direction:column;align-items:center;gap:8px;
  padding:14px 8px 12px;cursor:pointer;font-family:var(--sans);
  background:linear-gradient(180deg,#1C2026,#14181D);
  border:1px solid var(--line-d);border-radius:14px;
  box-shadow:inset 0 1px 0 rgba(255,255,255,.05);
  transition:border-color .3s var(--ease),transform .3s var(--ease),
             background .3s var(--ease)}
.tell:hover{transform:translateY(-3px);border-color:rgba(255,255,255,.22)}
.tell svg{width:26px;height:26px;stroke:#5C646E;fill:none;stroke-width:1.7;
  stroke-linecap:round;stroke-linejoin:round;transition:stroke .35s var(--ease)}
.tell b{font-size:9.5px;font-weight:700;letter-spacing:.1em;text-transform:uppercase;
  color:var(--steel);text-align:center;line-height:1.25;transition:color .35s var(--ease)}
/* the lamp, lit */
.tell.on{border-color:rgba(228,120,63,.6);
  background:linear-gradient(180deg,rgba(228,120,63,.18),rgba(228,120,63,.05))}
.tell.on svg{stroke:var(--amber);filter:drop-shadow(0 0 7px rgba(228,120,63,.85))}
.tell.on b{color:var(--amber)}
.tell.on::after{content:"";position:absolute;top:7px;right:9px;width:6px;height:6px;
  border-radius:50%;background:var(--amber);box-shadow:0 0 8px var(--amber);
  animation:tellBlip 1.9s var(--ease) infinite}
@keyframes tellBlip{0%,100%{opacity:1}50%{opacity:.35}}

/* the driver display */
.readout{margin-top:14px;position:relative;overflow:hidden;
  background:linear-gradient(180deg,#0C1014,#080B0E);
  border:1px solid var(--line-d);border-radius:var(--r);
  padding:clamp(22px,3vw,34px) clamp(20px,3vw,36px);
  box-shadow:inset 0 0 44px rgba(0,0,0,.7)}
/* faint scanlines, like a cluster screen */
.readout::before{content:"";position:absolute;inset:0;pointer-events:none;opacity:.5;
  background:repeating-linear-gradient(180deg,transparent 0 3px,rgba(255,255,255,.022) 3px 4px)}
.readout-code{display:flex;align-items:center;gap:10px;font-size:10.5px;font-weight:700;
  letter-spacing:.22em;text-transform:uppercase;color:var(--amber);margin-bottom:12px}
.readout-code i{width:7px;height:7px;border-radius:50%;background:var(--amber);
  box-shadow:0 0 8px var(--amber);font-style:normal}
.readout h3{font-family:var(--serif);font-weight:600;color:var(--paper);
  font-size:clamp(19px,2.4vw,27px);line-height:1.25;margin-bottom:12px;position:relative}
.readout p{font-size:15.5px;line-height:1.65;color:var(--body-d);max-width:70ch;
  margin:0;position:relative}
/* the swap: text dims and lifts, like a cluster redrawing */
.readout h3,.readout p{transition:opacity .28s var(--ease),transform .28s var(--ease)}
.readout.swap h3,.readout.swap p{opacity:0;transform:translateY(7px)}
@media (prefers-reduced-motion:reduce){
  .tell,.tell svg,.tell b,.readout h3,.readout p{transition:none}
  .tell.on::after{animation:none}
}

/* ---------- quote band ---------- */
.quote{background:var(--ink);color:var(--body-d);position:relative;overflow:hidden}
/* Real footage behind the closing band. It reuses the hero file, so it is
   already in cache and costs no extra download. Heavily scrimmed, because
   this band has to stay readable, not show off. */
.q-bg{position:absolute;inset:0;z-index:0}
.q-bg video{width:100%;height:100%;object-fit:cover;filter:grayscale(.35) contrast(1.05)}
.quote::before{content:"";position:absolute;inset:0;z-index:1;
  background:linear-gradient(90deg,rgba(8,9,10,.95) 0%,rgba(8,9,10,.86) 48%,rgba(8,9,10,.7) 100%),
             radial-gradient(60% 70% at 78% 30%,rgba(228,120,63,.2),transparent 66%)}
.q-in{position:relative;z-index:2;display:grid;grid-template-columns:1.15fr 1fr;gap:clamp(30px,5vw,64px);align-items:center}
@media(max-width:900px){.q-in{grid-template-columns:1fr}}
.q-form{background:var(--ink-3);border:1px solid var(--line-d);border-radius:var(--r);padding:clamp(26px,3.4vw,38px)}
.q-form label{display:block;font-size:11.5px;font-weight:600;letter-spacing:.14em;
  text-transform:uppercase;color:var(--steel);margin:0 0 7px}
.q-form input,.q-form select{width:100%;background:rgba(255,255,255,.05);
  border:1px solid var(--line-d);border-radius:11px;padding:14px 15px;margin-bottom:17px;
  color:var(--paper);font-family:var(--sans);font-size:15.5px;transition:.25s}
.q-form input:focus,.q-form select:focus{outline:0;border-color:var(--amber);
  background:rgba(255,255,255,.08)}
.q-form select option{background:var(--ink-3);color:var(--paper)}
.q-form .btn{width:100%}
.q-fine{margin-top:14px;font-size:12.5px;color:var(--steel);text-align:center}
.q-why{list-style:none;margin-top:26px}
.q-why li{padding-left:28px;position:relative;margin-bottom:13px;font-size:15.5px}
.q-why li::before{content:"";position:absolute;left:0;top:9px;width:13px;height:7px;
  border-left:2px solid var(--amber);border-bottom:2px solid var(--amber);transform:rotate(-45deg)}

/* ---------- footer ---------- */
/* The CTA pill and the back-to-top are fixed to the bottom-right corner, so
   whatever ends the page sits underneath them unless it is padded clear. The
   pill's top edge is 66px off the bottom at every width and the arrow stacks
   above it to 124px, so the footer ends above the taller of the two. */
.foot{background:#06070A;color:var(--steel);padding:clamp(52px,7vw,80px) 0 140px;font-size:14.5px}
.foot-grid{display:grid;grid-template-columns:1.4fr 1fr 1fr 1fr;gap:clamp(26px,4vw,48px)}
@media(max-width:860px){.foot-grid{grid-template-columns:1fr 1fr}}
@media(max-width:520px){.foot-grid{grid-template-columns:1fr}}
.foot h4{color:var(--paper);font-family:var(--sans);font-size:11.5px;font-weight:600;
  letter-spacing:.2em;text-transform:uppercase;margin-bottom:17px}
.foot ul{list-style:none}
.foot li{margin-bottom:10px}
.foot a{text-decoration:none;transition:.25s}
.foot a:hover{color:var(--amber)}
.foot .brand b{color:var(--paper)}
/* Follow Us. Six brand marks, hairline-divided like the live footer. Inline
   SVG rather than the icon font the live site loads, so nothing extra is
   fetched and the marks stay crisp at any size. */
.foot-social{margin-top:26px}
.foot-social ul{display:flex;align-items:center;flex-wrap:wrap;list-style:none;gap:0}
.foot-social li{margin:0}
.foot-social li+li{border-left:1px solid rgba(255,255,255,.15)}
.foot-social a{display:flex;align-items:center;justify-content:center;
  width:44px;height:38px;border-radius:12px;color:var(--paper);opacity:.82;
  transition:color .25s,opacity .25s,background .25s,transform .25s}
.foot-social a:hover,.foot-social a:focus-visible{color:var(--amber);opacity:1;
  background:rgba(228,120,63,.13);transform:translateY(-2px)}
.foot-social svg{height:18px;width:auto;fill:currentColor;display:block}
@media(prefers-reduced-motion:reduce){.foot-social a:hover{transform:none}}

.foot-bot{margin-top:clamp(36px,5vw,56px);border-top:1px solid rgba(255,255,255,.1);
  padding:22px 0;display:flex;flex-wrap:wrap;gap:14px;justify-content:space-between;font-size:13px}
/* photo credits a license requires, on the pages that use such a photo:
   small print on a line of its own, never a caption on the photo */
.foot-credit{flex:1 1 100%;font-size:12px}
.foot-credit a{color:inherit;text-decoration:underline;text-underline-offset:2px}
.foot-credit a:hover{color:var(--amber)}

/* ---------- floating CTA bar ----------
   A pill that slides up once the
   visitor is past the hero, carrying the primary action and the phone number
   together. Replaces the old mobile-only Call Now button, and now shows at
   every width rather than only on phones. */
.fab-quote{position:fixed;right:16px;bottom:16px;z-index:180;
  display:flex;align-items:center;gap:2px;
  background:rgba(10,12,15,.92);backdrop-filter:blur(10px);
  border:1px solid rgba(228,120,63,.45);border-radius:999px;padding:4px;
  box-shadow:0 14px 36px rgba(0,0,0,.5);
  opacity:0;transform:translateY(16px);pointer-events:none;
  transition:opacity .45s var(--ease),transform .5s var(--ease)}
.fab-quote.on{opacity:1;transform:none;pointer-events:auto}
.fab-quote .btn{padding:9px 24px;font-size:11px;letter-spacing:.12em;white-space:nowrap}
.fab-tel{font-family:var(--sans);font-weight:700;font-size:12px;letter-spacing:.06em;
  color:var(--paper);text-decoration:none;padding:9px 18px;white-space:nowrap;
  transition:color .25s var(--ease)}
.fab-tel:hover{color:var(--amber)}
@media(max-width:560px){
  .fab-quote{left:12px;right:12px;bottom:12px;justify-content:center}
  .fab-quote .btn{padding:11px 14px;font-size:11px}
  .fab-tel{padding:10px 8px;font-size:12px}
}
@media (prefers-reduced-motion:reduce){.fab-quote{transition:none}}

/* ---------- mobile ---------- */
@media(max-width:700px){
  body{font-size:16px}
  .hero-in{padding-top:88px}
  .btn{width:100%;padding:15px 20px}
  .btn-row .btn{width:auto;flex:1 1 auto;min-width:0}
}


/* =========================================================================
   Rules lifted out of style="" attributes, 23 Sep 2026.
   The markup carried 2,663 inline declarations across the 130 pages; they
   are all reproduced here so the pages hold no inline CSS at all. Names
   follow the component they belong to rather than the value, so changing a
   value here changes it everywhere it was repeated.
   ========================================================================= */

/* sections that sit on the dark ground */
.sec-ink{background:var(--ink)}
.sec-flush{padding-bottom:0}

/* the footer's brand block: logo, blurb, phone */
.foot .brand img{height:84px}
.foot-blurb{margin-top:16px;max-width:34ch}
.foot-phone{margin-top:16px}
.foot-phone b{color:var(--amber);font-size:19px}

/* a run-in subheading inside the long-form town copy */
.h3-gap{margin-top:26px}

/* Staggered starts for the map lanes and the water lines. Negative delays,
   so each path begins part-way through the loop instead of all of them
   marching in step. */
path.d-06{animation-delay:-.6s}
path.d-1{animation-delay:-1s}
path.d-3{animation-delay:-3s}
path.d-6{animation-delay:-6s}

/* Map pins. Percentage coordinates in the svg's own space, so they scale
   with it. One class per pin, numbered in source order. */
.am-pin-1{--px:23.8000%;--py:0%}
.am-pin-2{--px:37.5000%;--py:0%}
.am-pin-3{--px:39.8000%;--py:0%}
.am-pin-4{--px:42.8000%;--py:17.1875%}
.am-pin-5{--px:51.2000%;--py:0%}
.am-pin-6{--px:54.2000%;--py:34.6875%}
.am-pin-7{--px:65.5000%;--py:18.7500%}
.am-pin-8{--px:86.0000%;--py:41.5625%}

/* Cluster grids: --n columns from the md breakpoint up, --n-md below it. */
.cluster-4-2{--n:4;--n-md:2}
.cluster-6-3{--n:6;--n-md:3}
.cluster-7-4{--n:7;--n-md:4}
.cluster-8-4{--n:8;--n-md:4}
.cluster-9-5{--n:9;--n-md:5}
.cluster-10-5{--n:10;--n-md:5}

/* Focal point for cropped photography. The vertical half is always 50%;
   only the horizontal changes, to keep the subject in frame. */
img.op-20{object-position:20% 50%}
img.op-40{object-position:40% 50%}
img.op-45{object-position:45% 50%}
img.op-50{object-position:50% 50%}
img.op-55{object-position:55% 50%}
img.op-58{object-position:58% 50%}
img.op-60{object-position:60% 50%}

/* the timeline arc gradient stops, warm to hot */
.tc-arc-1{--g:#FFE070}
.tc-arc-2{--g:#FFC757}
.tc-arc-3{--g:#FFA957}
.tc-arc-4{--g:#FF8C50}
.tc-arc-5{--g:#FF6A44}
.tc-numl-sm{font-size:10px;letter-spacing:.2em}

/* button rows and story blocks that differ from their default alignment */
.btn-row-center{justify-content:center;margin-top:clamp(24px,3vw,36px)}
.btn-row-center-sm{justify-content:center;margin-top:22px}
.story-gap{margin-top:clamp(18px,2.4vw,26px)}
.story-gap-sm{margin-top:clamp(14px,2vw,20px)}
.story-center{text-align:center}
.kicker-rule{border-left:3px solid var(--amber);padding-left:16px}

/* ---------- back to top ----------
   The floating CTA pill owns the bottom-right corner. It is 50px tall at
   16px from the bottom above 560px, and 54px tall at 12px below it, where it
   also goes full width -- so its top edge lands 66px off the bottom at EVERY
   width. This button sits 12px clear of that edge on the same right margin,
   and fades in on the same scroll threshold, so the two read as one stack
   and cannot overlap each other at any size.
   It is a <button>, not an anchor: a href="#top" would write a hash into the
   address bar on every click. */
.to-top{position:fixed;right:16px;bottom:78px;z-index:179;
  width:46px;height:46px;display:grid;place-items:center;
  background:rgba(10,12,15,.92);backdrop-filter:blur(10px);
  border:1px solid rgba(228,120,63,.45);border-radius:999px;
  box-shadow:0 14px 36px rgba(0,0,0,.5);cursor:pointer;
  opacity:0;transform:translateY(16px);pointer-events:none;
  transition:opacity .45s var(--ease),transform .5s var(--ease),
             border-color .25s var(--ease),background .25s var(--ease)}
.to-top.on{opacity:1;transform:none;pointer-events:auto}
.to-top svg{width:20px;height:20px;display:block;fill:none;stroke:var(--amber);
  stroke-width:2;stroke-linecap:round;stroke-linejoin:round}
.to-top:hover{border-color:var(--amber);background:rgba(20,22,26,.96)}
.to-top:focus-visible{outline:2px solid var(--amber);outline-offset:3px}
@media(max-width:560px){.to-top{right:12px;width:44px;height:44px}}
@media (prefers-reduced-motion:reduce){.to-top{transition:none}}

/* =========================================================================
   GoHighLevel forms and the estimate popup (WordPress build).
   The static mockup had no forms in it, so none of this could come from
   there — it matches how the live site embeds them.
   ========================================================================= */

/* The frame carries its own height attribute, set per form in Theme Settings,
   because GHL sizes the form itself and a CSS height would fight it. */
.begc-form{width:100%}
.begc-form iframe{display:block;width:100%;border:0;border-radius:12px;background:transparent}
/* A GoHighLevel form reports its own height and can run past 800px, which
   leaves the band around it enormous. With this on, the frame keeps its
   full height and the box around it scrolls, so the form occupies a
   sensible slot on the page. Which forms do this is a switch on each form
   in Theme Settings, never a style attribute in the markup. */
.begc-form--scroll{max-height:min(72vh,620px);overflow-y:auto;
  overscroll-behavior:contain;border-radius:12px}
/* in the popup the heading stays put and the form scrolls under it, so the
   visitor can always see what they are filling in and reach the close button */
.begc-popup__box .begc-form--scroll{flex:1 1 auto;min-height:0;max-height:none;
  overflow-y:auto;overscroll-behavior:contain}

/* ---------- estimate popup ----------
   Every Free Estimate button opens this. It is a real overlay rather than a
   jump to a form band, so the button behaves the same on every page and the
   URL never changes. */
.begc-popup{position:fixed;inset:0;z-index:200;display:grid;place-items:center;
  padding:clamp(12px,4vw,32px)}
.begc-popup[hidden]{display:none!important}
.begc-popup__scrim{position:absolute;inset:0;background:rgba(6,7,10,.68);
  animation:begcFade .25s var(--ease)}
.begc-popup__box{position:relative;width:min(560px,100%);max-height:calc(100svh - 48px);
  display:flex;flex-direction:column;overscroll-behavior:contain;background:var(--white);
  border-radius:16px;box-shadow:0 30px 80px -20px rgba(6,7,10,.6);
  padding:clamp(16px,3vw,24px);animation:begcRise .3s var(--ease)}
.begc-popup__head{flex:0 0 auto;display:flex;align-items:flex-start;
  justify-content:space-between;gap:14px;margin-bottom:10px}
.begc-popup__head h2{font-family:var(--serif);font-size:clamp(21px,3vw,27px);
  line-height:1.15;color:var(--ink);margin:0}
.begc-popup__close{flex:0 0 auto;display:grid;place-items:center;width:38px;height:38px;
  background:none;border:1px solid var(--line);border-radius:999px;color:var(--ink);
  cursor:pointer;transition:color .25s var(--ease),border-color .25s var(--ease)}
.begc-popup__close svg{width:18px;height:18px;fill:none}
.begc-popup__close:hover{color:var(--amber-ink);border-color:var(--amber-ink)}
.begc-popup__close:focus-visible{outline:2px solid var(--amber-ink);outline-offset:2px}
@keyframes begcFade{from{opacity:0}to{opacity:1}}
@keyframes begcRise{from{opacity:0;transform:translateY(14px)}to{opacity:1;transform:none}}
@media (prefers-reduced-motion:reduce){
  .begc-popup__scrim,.begc-popup__box{animation:none}
  .begc-popup__close{transition:none}
}

/* ---------- the offer shown on the way out ----------
   Built on the estimate popup, so it inherits the scrim, the box, the close
   button and the reduced-motion rules rather than repeating them. What it adds
   is a heading block that can carry a line of copy, and the quiet decline
   link under the form. Brand type and colour throughout: the panel on the old
   site was a different palette entirely and does not belong here. */
.begc-exit .begc-popup__box{width:min(520px,100%)}
.begc-exit .begc-popup__head{align-items:flex-start;gap:12px;margin-bottom:14px}
.begc-exit .begc-popup__head h2{font-size:clamp(20px,2.8vw,25px)}
.begc-exit__lead{margin:6px 0 0;font-size:14.5px;line-height:1.5;color:var(--steel)}
.begc-exit__no{display:block;width:100%;margin-top:10px;padding:10px 6px;
  background:none;border:0;cursor:pointer;font-family:var(--sans);font-size:13.5px;
  color:var(--steel);text-decoration:underline;text-underline-offset:3px;
  transition:color .25s var(--ease)}
.begc-exit__no:hover{color:var(--ink)}
.begc-exit__no:focus-visible{outline:2px solid var(--amber-ink);outline-offset:2px;border-radius:8px}

/* The heading above the build gallery is centred.
   The approved build does this with a bc-head class on the block, which is a
   stored field — and on a site that went live before that field existed, the
   value has nowhere to come from. Keyed on the band instead, so it is right
   whatever the field holds. Both the home page and the testimonials page use
   id="builds", so one rule covers both.
   No .in in the selector: that class is added by the reveal script on scroll,
   and the heading must be centred before it arrives. */
#builds .lead{text-align:center;max-width:none;margin-inline:auto}
#builds .lead p{margin-inline:auto}
#builds .lead p:not(.eyeb){max-width:58ch}

/* "Who We Build For" on the About page, centred. */
#who{text-align:center;margin:0 auto}
#who .lead,#who .story{margin-inline:auto}
