/* =========================================================
   ABC Chimney Solutions
   Design system: Thrive-style structure & type scale,
   remapped to the ABC brand (navy + red).
   ========================================================= */

/* ---- Outfit (self-hosted variable font) — everything except the nav ---- */
@font-face{
  font-family:'Outfit';
  src:url('../fonts/Outfit-var.woff2') format('woff2');
  font-weight:100 900; font-style:normal; font-display:swap;
}

/* ---- Proxima Nova, self-hosted (client-supplied license).
        Kit ships Regular / Bold / Black only — there is no ExtraBold
        cut, so Black (900) is the heavy display weight. ---- */
@font-face{
  font-family:'Proxima Nova';
  src:url('../fonts/ProximaNova-Regular.woff2') format('woff2');
  font-weight:400; font-style:normal; font-display:swap;
}
@font-face{
  font-family:'Proxima Nova';
  src:url('../fonts/ProximaNova-Bold.woff2') format('woff2');
  font-weight:700; font-style:normal; font-display:swap;
}
@font-face{
  font-family:'Proxima Nova';
  src:url('../fonts/ProximaNova-Black.woff2') format('woff2');
  font-weight:900; font-style:normal; font-display:swap;
}
/* Header cut, exposed as its own family at weight 400 — mirrors how
   Thrive ships "proximanova-extrabld / 400 / 18px".
   NOTE: the supplied kit has no ExtraBold (800) cut, only Bold (700)
   and Black (900). Black is the stand-in. Drop
   ProximaNova-Extrabld.woff2 into assets/fonts/ and point this src at
   it for an exact match. */
@font-face{
  font-family:'Proxima Nova Nav';
  src:url('../fonts/ProximaNova-Bold.woff2') format('woff2');
  font-weight:400; font-style:normal; font-display:swap;
}

:root{
  /* Brand — sampled from the logo */
  --navy:        #0E1E63;
  --navy-deep:   #0A1748;
  --navy-soft:   #2B3C8C;
  --red:         #ED1C24;
  --red-dark:    #C4141B;

  /* Neutrals (navy-tinted, so they sit with the brand) */
  --ink:         #16204A;
  --ink-body:    #4A5170;
  --ink-muted:   #7A81A0;
  --line:        #E2E7F3;
  --tint:        #EEF2FD;
  /* the live-status green — every "we are available" dot on the site */
  --live:        #2BD97C;
  --live-ring:   rgba(43,217,124,.7);
  --tint-deep:   #DCE4F8;
  --tint-red:    #ED1C24;   /* nav hover pill — full brand red */
  --tint-red-sm: #FCE4E5;   /* phone icon disc */
  --white:       #fff;

  --nav-x: 16px;            /* hover-pill side padding */

  /* Outfit everywhere; Proxima Nova is kept for the nav only */
  --font-head:'Outfit',system-ui,-apple-system,'Segoe UI',Arial,sans-serif;
  --font-body:'Outfit',system-ui,-apple-system,'Segoe UI',Arial,sans-serif;
  --font-nav:'Proxima Nova Nav','Outfit',system-ui,-apple-system,'Segoe UI',Arial,sans-serif;
  /* real Proxima family (400/700/900) for the odd element specced off Thrive */
  --font-proxima:'Proxima Nova','Outfit',system-ui,-apple-system,'Segoe UI',Arial,sans-serif;

  --shell: 1680px;
  --pad: 32px;
  /* distance from the shell's edge to the viewport edge — lets an element
     break out of the container and run to the screen edge */
  --gutter: calc(max((100vw - var(--shell)) / 2, 0px) + var(--pad));
  --header-h: 106px;  /* logo height (86) + 10px breathing room each side */

  --shadow-sm: 0 2px 10px rgba(14,30,99,.06);
  --shadow-md: 0 14px 40px rgba(14,30,99,.10);
  --shadow-lg: 0 28px 70px rgba(14,30,99,.16);
}

/* ---------------- base ---------------- */
*,*::before,*::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%}
body{
  margin:0;
  font-family:var(--font-body);
  font-size:17px;
  line-height:1.62;
  font-weight:400;
  color:var(--ink-body);
  background:var(--white);
  -webkit-font-smoothing:antialiased;
}
img{max-width:100%;height:auto;display:block}
h1,h2,h3,h4{font-family:var(--font-head);font-weight:700;color:var(--ink);margin:0;line-height:1.12}
a{color:inherit;text-decoration:none}
button{font:inherit;color:inherit;background:none;border:0;cursor:pointer}
/* ol as well as ul — an <ol> keeps a 40px padding-inline-start otherwise, which
   silently inset the How It Works cards from the grid they sit in */
ul,ol{margin:0;padding:0;list-style:none}
/* figure ships with margin-inline:40px and blockquote with 40px too — both are
   used as cards here, and a stray UA margin silently trebled the gutter */
figure,blockquote{margin:0}

.shell{width:100%;max-width:var(--shell);margin:0 auto;padding:0 var(--pad)}
.sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);white-space:nowrap;border:0}
.skip-link{position:absolute;left:-9999px;top:0;z-index:200;background:var(--navy);color:#fff;padding:12px 20px;border-radius:0 0 8px 0}
.skip-link:focus{left:0}
:focus-visible{outline:3px solid var(--red);outline-offset:3px;border-radius:4px}

/* ---------------- buttons ----------------
   Flat fill, one radius, darken on hover — the same make-up as the service
   card buttons, so every button on the site reads the same way. No gradient,
   no inset highlights, no glow. */
.btn{
  display:inline-flex;align-items:center;justify-content:center;
  font-family:var(--font-head);
  font-size:17px;font-weight:700;letter-spacing:.06em;text-transform:uppercase;
  padding:19px 34px;border-radius:11px;
  white-space:nowrap;
  transition:background .2s ease,color .2s ease,filter .28s ease;
}

.btn--red{background:var(--red);color:#fff}
.btn--red:hover{filter:brightness(.88)}

.btn--white{background:#fff;color:var(--navy)}
.btn--white:hover{background:var(--navy);color:#fff}

/* ring rather than a border, so it can't sit 3px taller than the solid variants */
.btn--ghost{
  background:transparent;color:#fff;
  box-shadow:inset 0 0 0 1.5px rgba(255,255,255,.5);
}
.btn--ghost:hover{background:#fff;color:var(--red)}

.btn--pill{border-radius:50px}

/* =========================================================
   HEADER
   ========================================================= */
/* Sticky, always — including while a mega panel is open. The panel is absolutely
   positioned inside the header, so it stays pinned to the top of the window with
   it and the page scrolls underneath. */
.site-header{
  position:sticky;top:0;z-index:100;
  background:#fff;
  border-bottom:1px solid var(--line);
  transition:box-shadow .2s ease;
}
.site-header.is-stuck{box-shadow:var(--shadow-sm)}

.header-inner{
  height:var(--header-h);
  display:flex;align-items:center;gap:0;
}

/* Nav starts just after the logo (not centred) and the items breathe —
   both distances are fluid so they hold their proportion like Thrive's. */
.brand{flex:none}
.brand img{height:86px;width:auto}

/* --nav-x is the hover-pill's side padding. It is subtracted back out of
   the nav offset and the item gap so the *text* still sits exactly where
   Thrive's does (≈62px after the logo, ≈98px apart at 1900px). */
.nav{flex:1 1 auto;min-width:0;margin-left:calc(clamp(42px,3.3vw,64px) - var(--nav-x))}
/* The list fills all the room between the logo and the phone block and
   spreads the items across it, so CONTACT always lands flush against the
   right-hand group no matter the screen width. The gap is only a floor. */
.nav-list{display:flex;align-items:center;width:100%;justify-content:space-between;gap:24px}
/* pull the last item's pill padding back so its TEXT sits on the edge */
.nav-list > li:last-child{margin-right:calc(-1 * var(--nav-x))}

.nav-link{
  display:inline-flex;align-items:center;gap:9px;
  font-family:var(--font-nav);
  font-size:18px;font-weight:400;line-height:34px;letter-spacing:normal;text-transform:uppercase;
  color:var(--ink);
  /* kit has no ExtraBold cut — a hairline stroke nudges Bold up toward it */
  -webkit-text-stroke:.34px currentColor;
  padding:11px var(--nav-x);border-radius:8px;position:relative;
  transition:background .16s ease,color .16s ease;
}
.nav-link:hover,
.has-drop[data-open="true"] > .nav-link{background:var(--tint-red);color:#fff}
/* caret has its own color, so flip it to white on the red pill too */
.nav-link:hover .caret,
.has-drop[data-open="true"] > .nav-link .caret{border-color:#fff}

.caret{
  width:10px;height:10px;
  border-right:2px solid var(--ink-muted);border-bottom:2px solid var(--ink-muted);
  transform:rotate(45deg) translate(-3px,-3px);transition:transform .22s ease;
}
.has-drop[data-open="true"] .caret{transform:rotate(-135deg) translate(-3px,-3px)}

/* dropdown */
.has-drop{position:relative}
.drop{
  position:absolute;top:calc(100% + 22px);left:-24px;
  min-width:620px;
  background:#fff;border:1px solid var(--line);border-radius:16px;
  box-shadow:var(--shadow-lg);
  padding:14px;
  opacity:0;visibility:hidden;transform:translateY(10px);
  transition:opacity .2s ease,transform .2s ease,visibility .2s;
}
.drop--sm{min-width:460px}
.has-drop[data-open="true"] .drop{opacity:1;visibility:visible;transform:translateY(0)}
.drop::before{content:"";position:absolute;top:-22px;left:0;right:0;height:22px}
.drop-inner{display:grid;grid-template-columns:1fr 1fr;gap:4px}
.drop-inner--cols{grid-template-columns:1fr 1fr}
.drop-inner a{
  display:block;padding:13px 16px;border-radius:10px;
  transition:background .15s ease;
}
.drop-inner a:hover{background:var(--tint)}
.drop-inner strong{
  display:block;font-family:var(--font-head);font-weight:700;
  font-size:15.5px;color:var(--ink);letter-spacing:-.005em;
}
.drop-inner span{display:block;font-size:13.5px;color:var(--ink-muted);margin-top:2px;line-height:1.4}

/* ---- mega menu ----
   The <li> goes position:static so the sticky header becomes the containing
   block, letting the panel span the full window instead of the nav item. */
.has-drop--mega{position:static}
.drop--mega{
  left:0;right:0;top:calc(100% + 1px);
  min-width:0;max-width:none;
  border-radius:0 0 20px 20px;border-top:0;
  padding:0;
  /* No max-height and no overflow. Both together are what made the panel a scroll
     container, so the wheel moved the panel instead of the page. With neither, the
     wheel goes straight to the document and the menu just stays open while you
     scroll — which is what it should do. */
  overflow:visible;
}
.drop--mega::-webkit-scrollbar{width:0;height:0;display:none}
/* The panel must open inside the viewport without becoming a scroll container —
   giving it a max-height and overflow is what made the wheel move the menu instead
   of the page. So the height is controlled by what goes in it: four link rows per
   group, three lines of promo copy, and this trimmed padding. */
.mega{
  display:grid;grid-template-columns:300px 1fr;
  gap:32px;align-items:start;
  padding:15px var(--pad) 13px;
}

/* promo card */
.mega-promo{
  align-self:stretch;
  padding:24px 22px;border-radius:16px;
  background:linear-gradient(165deg,var(--navy) 0%,#0A1748 100%);
  color:#fff;
}
.mega-promo h3{
  font-family:var(--font-head);font-weight:900;
  font-size:23px;line-height:1.2;color:#fff;
}
.mega-promo p{margin:10px 0 17px;font-size:14.5px;line-height:1.6;color:rgba(255,255,255,.8)}
/* The two ways out of the promo card, stacked and full width. */
.mega-act{display:flex;flex-direction:column;gap:11px}
/* Two classes deep on purpose. .scard-btn sets width:fit-content and is defined
   further down the file, so a single-class rule here lost on source order and
   the button came out 211px against the 256px one below it. */
.mega-act .mega-call{
  /* .scard-btn colors its disc and glyph from --card-ico / --card-ico-bg, which
     the service cards set per card. Outside a .scard those were undefined, so
     the fill fell back to black — that is why the handset came out dark on a
     pale disc. Declared here, the existing machinery does the rest. */
  --card-ink:var(--navy);
  --card-ico-bg:var(--tint-red-sm);
  --card-ico:var(--red);
  --card-glow:rgba(237,28,36,.45);

  width:100%;margin:0;height:58px;
  align-self:stretch;justify-self:stretch;
  box-shadow:inset 0 0 0 1px rgba(255,255,255,.12);
}
.mega-call .scb-txt em{color:rgba(255,255,255,.78)}
.mega-cta{width:100%;justify-content:center}

/* phone capture inside the promo card — same gate as the hero */
.mega-form{display:flex;flex-direction:column;gap:10px}
.mega-form .field{flex:none;width:100%}
.mega-form .field input{height:50px;font-size:15px;padding:0 18px 0 46px;border-color:transparent}
.mega-form .field-ico{left:17px}
.mega-form .btn{width:100%;font-size:14.5px;padding:15px 18px}
.mega-form .field-msg{margin:0;font-size:12.5px;color:rgba(255,255,255,.72)}
.mega-form .field-msg.is-good{color:#8FE3B2}
.mega-form .field-msg.is-bad{color:#FFB4B8}
.mega-promo-points{margin:0 0 18px;display:flex;flex-direction:column;gap:10px}
.mega-promo-points li{
  position:relative;padding-left:24px;
  font-size:13.5px;line-height:1.45;color:rgba(255,255,255,.82);
}
.mega-promo-points li::before{
  content:"";position:absolute;left:0;top:6px;
  width:13px;height:7px;
  border-left:2px solid var(--red);border-bottom:2px solid var(--red);
  transform:rotate(-45deg);
}


/* A multi-column flow, not a fixed grid.

   The groups used to be pinned into four columns of two by the shape of
   $megaCols, and that pairing was badly out of balance — one column carried
   twenty rows and another thirteen, and the tallest one decided the height of
   the entire panel. Multi-column layout is the tool for this: the browser
   evens the columns out itself, and re-evens them at every width, so the panel
   is only ever as tall as it has to be.

   column-rule replaces the hand-drawn hairlines, which were positioned by
   nth-child and could not survive the groups moving between columns. */
/* Four columns of two, filled top-then-next-column, with the pairing chosen in
   inc/header.php so the columns come out even.

   Multi-column layout was tried here and rejected: the browser balances by
   height, but with break-inside:avoid on eight groups of very different sizes
   it still left one column ending 200px short of the others, which read as a
   hole in the menu. An explicit grid with a chosen pairing is both tidier and
   predictable.

   The second row is `1fr` and its groups sit at the top of it, so a column with
   less in it spreads the slack between its two groups instead of collecting it
   all at the foot. Every column now ends at the same line. */
.mega-cols{
  display:grid;
  grid-template-columns:repeat(4,1fr);
  gap:0 30px;
  align-items:start;
}
/* each column is its own stack — see the note in inc/header.php for why the
   two shared grid rows had to go */
.mega-col{display:flex;flex-direction:column;gap:20px}
.mega-group{position:relative}
/* one hairline per column, drawn on the column itself and faded at both ends.
   It used to be drawn on individual groups, which only worked while the groups
   were pinned to fixed grid positions. */
.mega-col{position:relative}
.mega-col:not(:first-child)::before{
  content:"";position:absolute;left:-15px;top:2px;bottom:2px;width:1px;
  background:linear-gradient(180deg,transparent,var(--line) 12%,var(--line) 88%,transparent);
}

.mega-head{
  display:flex;align-items:center;gap:11px;
  min-height:28px;          /* keeps one- and two-line headings on one baseline */
  font-family:var(--font-head);font-weight:800;
  font-size:15px;line-height:1.25;color:var(--ink);
  transition:color .15s ease;
}
.mega-head:hover{color:var(--red)}
.mega-ico{
  flex:none;width:32px;height:32px;border-radius:10px;
  display:grid;place-items:center;
  background:#fff;color:var(--navy);
  box-shadow:inset 0 0 0 1px rgba(14,30,99,.12);
  transition:background .2s ease,color .2s ease,box-shadow .2s ease;
}
.mega-ico svg{width:16px;height:16px}
.mega-head:hover .mega-ico{background:var(--red);color:#fff;box-shadow:inset 0 0 0 1px var(--red)}

/* rule under each heading with a red leader that extends on group hover */
.mega-links{
  position:relative;
  display:flex;flex-direction:column;gap:0;
  margin-top:6px;padding-top:7px;
  border-top:1px solid var(--line);
}
.mega-links::before{
  content:"";position:absolute;top:-1px;left:0;
  width:28px;height:2px;background:var(--red);
  transition:width .38s cubic-bezier(.22,1,.36,1);
}
.mega-group:hover .mega-links::before{width:72px}

.mega-links a{
  position:relative;display:block;
  padding:4px 0;
  font-size:13.8px;line-height:1.36;color:var(--ink-body);
  transition:color .18s ease,padding-left .24s cubic-bezier(.22,1,.36,1);
}
/* marker morphs from a dot into a short red dash on hover — same treatment on
   every item, so all eight groups read as one system */
.mega-links a::before{
  /* a rule that grows out of nothing on hover — no bullet sitting there
     permanently, so the list reads as type rather than as a bulleted menu */
  content:"";position:absolute;left:0;top:50%;
  width:0;height:1.5px;margin-top:-.75px;border-radius:2px;
  background:var(--red);
  transition:width .24s cubic-bezier(.22,1,.36,1);
}
.mega-links a:hover{color:var(--red)}
.mega-links a:hover{padding-left:16px}
.mega-links a:hover::before{width:10px}

/* ---- full-width bar closing the areas panel ----
   Sits outside .mega so it spans the promo card as well as the columns, and
   carries the panel's own bottom radius. The eight county groups only name ten
   towns each; this is the way through to the rest. */
.mega-foot{
  display:flex;align-items:center;justify-content:center;gap:16px;
  padding:14px var(--pad);
  border-top:1px solid var(--line);
  border-radius:0 0 20px 20px;
  background:var(--tint);
  transition:background .2s ease,color .2s ease;
}
.mega-foot-txt{display:flex;align-items:baseline;gap:12px;min-width:0}
.mega-foot b{
  font-family:var(--font-head);font-weight:800;
  font-size:15.5px;letter-spacing:-.01em;color:var(--navy);
  transition:color .2s ease;
}
.mega-foot em{font-style:normal;font-size:13.5px;color:var(--ink-muted);transition:color .2s ease}
/* the arrow rides its own disc so it reads as a destination, not a decoration */
.mega-foot-go{
  flex:none;width:30px;height:30px;border-radius:50%;
  display:grid;place-items:center;
  background:var(--red);color:#fff;
  transition:transform .28s cubic-bezier(.22,1,.36,1);
}
.mega-foot:hover{background:var(--navy)}
.mega-foot:hover b{color:#fff}
.mega-foot:hover em{color:rgba(255,255,255,.72)}
.mega-foot:hover .mega-foot-go{transform:translateX(5px)}



.header-aside{flex:none;margin-left:auto;padding-left:34px;display:flex;align-items:center;gap:18px}

.phone{display:inline-flex;align-items:center;gap:11px}
.phone-ico{
  position:relative;
  width:38px;height:38px;border-radius:50%;
  display:grid;place-items:center;
  background:var(--tint-red-sm);color:var(--red);
  transition:background .18s ease,color .18s ease;
}
.phone:hover .phone-ico{background:var(--red);color:#fff}

/* Same ring-and-rock as the service card buttons — same 2.2s cycle, same
   keyframes — so the two read as one behavior rather than two animations that
   happen to be on phone icons. The ring takes the disc's own tint here rather
   than the card variable, because this disc sits on white. */
.phone .phone-ico::before,
.phone .phone-ico::after{
  content:"";position:absolute;inset:0;border-radius:50%;
  border:2.5px solid var(--tint-red-sm);
  pointer-events:none;
  animation:ico-ring 2.2s cubic-bezier(.3,0,.5,1) infinite;
}
.phone .phone-ico::after{animation-delay:1.1s}
/* the rings are the tint at rest and would vanish into a red disc on hover */
.phone:hover .phone-ico::before,
.phone:hover .phone-ico::after{border-color:rgba(237,28,36,.35)}

.phone .phone-ico svg{animation:ico-rock 2.2s ease-in-out infinite}
.phone-num{
  font-family:var(--font-head);font-weight:700;font-size:21px;
  color:var(--red);letter-spacing:-.01em;white-space:nowrap;
}

/* The search key.
   A flat navy pill read as a placeholder next to the phone disc, so it is built
   the way the rest of the chrome is: a lit face rather than a fill. Three layers,
   all of them cheap to animate —
     the pill itself   a navy gradient with a hairline of light along its top edge
                       and a soft cast shadow, so it sits above the header
     ::before          the red face, cross-faded in on hover; opacity only, so
                       nothing repaints
     ::after           a sheen that crosses the face once every 7s. Long enough
                       apart to register as a material catching the light rather
                       than as an animation running.
   The magnifier is a stroked glyph now, same weight and round caps as the mega
   menu and card icons, so it belongs to the same family instead of being the one
   solid icon in the header. */
.icon-btn{
  position:relative;overflow:hidden;isolation:isolate;
  width:62px;height:40px;border-radius:20px;
  display:grid;place-items:center;
  background:linear-gradient(163deg,#1D3192 0%,var(--navy) 58%,#091641 100%);
  color:#fff;
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.20),
    inset 0 0 0 1px rgba(255,255,255,.07),
    0 8px 18px -11px rgba(14,30,99,.9);
  transition:box-shadow .3s ease, transform .3s cubic-bezier(.22,1,.36,1);
}
.icon-btn::before{
  content:"";position:absolute;inset:0;z-index:-1;
  background:linear-gradient(163deg,#FF3C44 0%,var(--red) 58%,#BE1219 100%);
  opacity:0;transition:opacity .3s ease;
}
.icon-btn::after{
  content:"";position:absolute;top:-70%;left:0;z-index:-1;
  width:26%;height:240%;
  background:linear-gradient(90deg,transparent,rgba(255,255,255,.42),transparent);
  transform:rotate(18deg) translateX(-90px);
  animation:btn-sheen 7s cubic-bezier(.4,0,.2,1) infinite;
}
@keyframes btn-sheen{
  0%,78%  {transform:rotate(18deg) translateX(-90px)}
  92%,100%{transform:rotate(18deg) translateX(150px)}
}
.icon-btn svg{position:relative;transition:transform .34s cubic-bezier(.22,1,.36,1)}

.icon-btn:hover{
  transform:translateY(-1.5px);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.28),
    inset 0 0 0 1px rgba(255,255,255,.10),
    0 12px 24px -12px rgba(237,28,36,.95);
}
.icon-btn:hover::before{opacity:1}
/* the lens tips as if being brought up to look through */
.icon-btn:hover svg{transform:scale(1.1) rotate(-10deg)}
.icon-btn:active{transform:translateY(0) scale(.97)}
/* the button is the only focusable thing in the header without a visible ring */
.icon-btn:focus-visible{outline:2px solid var(--red);outline-offset:3px}

@media (prefers-reduced-motion:reduce){
  .icon-btn::after{animation:none;opacity:0}
  .icon-btn,.icon-btn svg{transition:none}
}

/* =========================================================
   HEADER SEARCH
   ========================================================= */
.search{position:fixed;inset:0;z-index:200;display:grid;place-items:start center}
/* A class rule beats the UA's [hidden]{display:none}, so without this the panel
   was never actually hidden — just transparent, and still a full-screen layer at
   z-index 200 swallowing every click on the page, the search button included.
   Same guard the modal and the form success panels already carry. */
.search[hidden]{display:none}
.search-veil{
  position:absolute;inset:0;
  background:rgba(8,16,48,.55);
  backdrop-filter:blur(3px);
  opacity:0;transition:opacity .22s ease;
}
.search-card{
  position:relative;
  width:min(680px,calc(100vw - 32px));
  margin-top:min(14vh,120px);
  background:#fff;border-radius:20px;
  box-shadow:0 40px 90px -30px rgba(8,16,48,.55);
  overflow:hidden;
  opacity:0;transform:translateY(-14px) scale(.985);
  transition:opacity .22s ease, transform .28s cubic-bezier(.22,1,.36,1);
}
.search.is-open .search-veil{opacity:1}
.search.is-open .search-card{opacity:1;transform:none}

.search-bar{display:flex;align-items:center;gap:14px;padding:0 16px 0 22px;height:70px}
.search-ico{flex:none;display:grid;place-items:center;color:var(--red)}
.search-bar input{
  flex:1 1 auto;min-width:0;height:100%;border:0;background:none;
  font-family:var(--font-head);font-weight:600;
  font-size:19px;letter-spacing:-.01em;color:var(--ink);
}
.search-bar input::placeholder{color:var(--ink-muted);font-weight:500}
.search-bar input:focus{outline:none}
.search-x{
  flex:none;width:34px;height:34px;border-radius:50%;
  display:grid;place-items:center;
  background:var(--tint);color:var(--ink-muted);
  transition:background .18s ease,color .18s ease;
}
.search-x:hover{background:var(--red);color:#fff}

/* The results area only exists once there is something to show, so an untouched
   search box is a single bar rather than a tall empty white sheet. */
.search-body{max-height:min(52vh,420px);overflow-y:auto;overscroll-behavior:contain}
.search:not(.has-results) .search-body{display:none}
.search-results{padding:8px}
.search-results a{
  display:flex;align-items:center;gap:14px;
  padding:12px 14px;border-radius:12px;
  transition:background .14s ease;
}
.search-results a.is-on{background:var(--tint)}
.sr-t{
  flex:1 1 auto;min-width:0;
  font-family:var(--font-head);font-weight:600;
  font-size:15.5px;letter-spacing:-.005em;color:var(--ink);
  white-space:nowrap;overflow:hidden;text-overflow:ellipsis;
}
/* the matched run, so it is obvious why the row is in the list */
.sr-t b{font-weight:800;color:var(--red)}
.sr-k{
  flex:none;
  padding:4px 10px;border-radius:999px;
  background:var(--tint-red-sm);
  font-family:var(--font-head);font-weight:700;
  font-size:11px;letter-spacing:.04em;text-transform:uppercase;color:var(--red);
}
.sr-go{
  flex:none;color:var(--ink-muted);
  opacity:0;transform:translateX(-4px);
  transition:opacity .2s ease,transform .25s cubic-bezier(.22,1,.36,1);
}
.search-results a.is-on .sr-go{opacity:1;transform:none;color:var(--red)}

.search-empty{padding:26px 24px 30px;text-align:center}
.search-empty b{
  display:block;font-family:var(--font-head);font-weight:800;
  font-size:17px;color:var(--ink);margin-bottom:6px;
}
.search-empty p{font-size:14.5px;line-height:1.6;color:var(--ink-muted)}
.search-empty em{font-style:normal;font-weight:700;color:var(--ink)}
.search-empty a{color:var(--red);font-weight:700}

.search-foot{
  display:flex;align-items:center;gap:20px;
  padding:12px 22px;
  border-top:1px solid var(--line);background:#FBFCFE;
}
.search-keys{display:inline-flex;align-items:center;gap:7px;font-size:12px;color:var(--ink-muted)}
.search-keys kbd{
  display:inline-grid;place-items:center;
  min-width:20px;height:20px;padding:0 5px;border-radius:5px;
  background:#fff;box-shadow:inset 0 0 0 1px var(--line),0 1px 0 var(--line);
  font-family:var(--font-head);font-size:11px;font-weight:700;color:var(--ink);
}

@media (max-width:620px){
  .search-card{margin-top:12px;border-radius:16px}
  .search-bar{height:62px;padding:0 12px 0 18px;gap:11px}
  .search-bar input{font-size:17px}
  .search-body{max-height:60vh}
  /* the badge goes first: the title is what people are reading */
  .sr-k{display:none}
  .search-foot{display:none}
}

@media (prefers-reduced-motion:reduce){
  .search-veil,.search-card{transition:none}
  .search-card{transform:none}
}
.icon-btn:hover{background:var(--red)}

/* Chimney burger.
   The three bars are graduated instead of identical: the top one is wider and
   overhangs the two below it, which is exactly how a chimney crown sits on its
   stack. Centred, so it overhangs both sides. It still reads instantly as a menu
   — the silhouette is the only thing that changed — and a wisp of brand red
   drifts off the crown to finish the idea.
   The tile is the same frosted glass as the hero eyebrow, so the two pieces of
   chrome on this screen belong to each other. */
.burger{
  display:none;position:relative;
  width:46px;height:46px;border-radius:14px;
  flex-direction:column;align-items:center;justify-content:center;gap:5px;
  background:rgba(255,255,255,.55);
  -webkit-backdrop-filter:blur(14px) saturate(1.4);
          backdrop-filter:blur(14px) saturate(1.4);
  border:1px solid rgba(14,30,99,.1);
  box-shadow:inset 0 1px 0 rgba(255,255,255,.9),
             0 6px 16px rgba(9,16,48,.12);
  transition:background .22s ease,box-shadow .22s ease;
}
.burger span{
  display:block;height:2.6px;border-radius:2px;background:var(--navy);
  transition:width .32s cubic-bezier(.22,1,.36,1),
             transform .3s ease,opacity .2s ease;
}
.burger span:nth-child(1){width:26px}   /* crown */
.burger span:nth-child(2){width:19px}   /* stack */
.burger span:nth-child(3){width:19px}

/* smoke off the crown */
.burger::before{
  content:"";position:absolute;left:50%;top:9px;
  width:4.5px;height:4.5px;border-radius:50%;
  background:var(--red);pointer-events:none;
  animation:burger-smoke 2.6s ease-out infinite;
}
@keyframes burger-smoke{
  0%  {opacity:0;   transform:translate(8px,4px)   scale(.5)}
  22% {opacity:.85}
  100%{opacity:0;   transform:translate(13px,-9px) scale(1.6)}
}

/* Open state equalises the three widths first — an X built from a 26px bar and a
   19px bar is visibly lopsided. Smoke stops, because the chimney has become a
   close button. */
.burger[aria-expanded="true"] span{width:24px}
.burger[aria-expanded="true"] span:nth-child(1){transform:translateY(7.6px) rotate(45deg)}
.burger[aria-expanded="true"] span:nth-child(2){opacity:0}
.burger[aria-expanded="true"] span:nth-child(3){transform:translateY(-7.6px) rotate(-45deg)}
.burger[aria-expanded="true"]::before{animation:none;opacity:0}
.burger[aria-expanded="true"]{background:rgba(255,255,255,.8)}

@supports not ((backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px))){
  .burger{background:#fff}
}
@media (prefers-reduced-motion:reduce){
  .burger::before{animation:none;opacity:.85}
}

/* =========================================================
   HERO
   ========================================================= */
/* Fills exactly the space left under the header so the whole hero sits in
   one viewport. No bottom padding — the visual rests on the section's
   bottom edge and the copy column carries its own spacing instead.
   min-height (not height) so it still grows rather than clipping on short
   screens or when text wraps unexpectedly. */
/* Height follows the content (no forced height = no dead space), but is hard
   capped at the leftover viewport so header + hero can never exceed one
   screen. The image cap further down keeps content inside that ceiling. */
.hero{
  position:relative;
  padding:18px 0 0;
  overflow:hidden;   /* contains the image's right-edge bleed */
  /* Fills the viewport below the header, so the red ticker underneath can never
     show through at the bottom of the banner.
     min-height rather than height, and the centring on this element rather than
     on .hero-grid: forcing a height onto the grid stretched its columns, floated
     the copy and cut the testimonial card off. The banner is shorter than a tall
     screen, so the slack is split evenly above and below instead of collecting
     at one end. */
  min-height:calc(100vh - var(--header-h));
  min-height:calc(100dvh - var(--header-h));
  /* end, not center. The technician is a cut-out standing on the bottom edge of
     the banner, so centring left him hovering with a band of white underneath.
     All the slack goes above instead, where it lands on the sky in the rooftop
     photo and reads as part of the picture. */
  display:grid;align-content:end;
}
/* Photo layer, left side only. The horizontal mask is the whole trick: the
   layer is cut off with a gradient rather than a hard edge, so it thins out and
   is gone by 94% of its width — well before the testimonial photo starts. A
   plain width with no mask would leave a visible vertical seam. */
.hero-bg{
  position:absolute;z-index:0;pointer-events:none;
  top:0;bottom:0;left:0;
  /* narrower than before so the layer still ends short of the testimonial */
  width:min(58%,980px);
  /* holds solid to 74% and only then falls away, instead of thinning from 40%.
     Every one of these shots frames its chimney hard right, so a fade that
     starts early puts the subject in the washed-out part — the exact problem. */
  -webkit-mask-image:linear-gradient(90deg,#000 0%,#000 74%,rgba(0,0,0,.55) 88%,transparent 99%);
          mask-image:linear-gradient(90deg,#000 0%,#000 74%,rgba(0,0,0,.55) 88%,transparent 99%);
}
/* feathers the top and bottom into the white page. Sits above the slides but
   inside .hero-bg, and .hero-bg carries no opacity of its own — the fade lives
   on the slides, so this veil stays at full strength and actually works. */
.hero-bg::after{
  content:"";position:absolute;inset:0;z-index:1;
  background:linear-gradient(180deg,
    #fff 0%, rgba(255,255,255,0) 24%,
    rgba(255,255,255,0) 66%, #fff 100%);
}
.hero-bg-slide{
  position:absolute;inset:0;display:block;
  opacity:0;
  animation:hero-bg-cycle 28s cubic-bezier(.45,0,.55,1) infinite;
}
.hero-bg-slide img{width:100%;height:100%;object-fit:cover;display:block}
/* same 1.68s shift as the inner-page hero, so this one doesn't open white either */
.hero-bg-slide:nth-child(1){animation-delay:-1.68s}
.hero-bg-slide:nth-child(2){animation-delay:5.32s}
.hero-bg-slide:nth-child(3){animation-delay:12.32s}
.hero-bg-slide:nth-child(4){animation-delay:19.32s}
/* The hold has to run to 25% and the fade-out finish at 31%, because the slides
   are staggered 7s apart on a 28s loop and 7s IS 25%. So the outgoing still only
   begins leaving at the exact moment the next one begins arriving, and the two
   cross over during 25-31%. Finishing the fade earlier (the old 28%) left a gap
   where neither was up and the white page showed through — that was the flash.
   Each frame also drifts 1.07 -> 1 while visible, so it's never sitting dead.
   The scale reset happens at opacity 0, so it never snaps on screen. */
@keyframes hero-bg-cycle{
  0%      {opacity:0;  transform:scale(1.07)}
  6%,25%  {opacity:.6}
  31%     {opacity:0;  transform:scale(1)}
  100%    {opacity:0;  transform:scale(1)}
}
@media (prefers-reduced-motion:reduce){
  .hero-bg-slide{animation:none}
  .hero-bg-slide:nth-child(1){opacity:.6}
}

.hero-grid{
  position:relative;z-index:1;
  display:grid;grid-template-columns:1.02fr .98fr;
  gap:56px;align-items:end;
}
/* without this a long unbreakable headline stretches its own column */
.hero-grid > *{min-width:0}
/* this drives the hero's height — the copy column is the taller of the two,
   so trimming it shortens the whole banner and closes the gap above the image.
   The top padding pushes the eyebrow off the header without touching the
   right column: the image is bottom-anchored, so it stays put. */
.hero-copy{padding-top:26px;padding-bottom:40px}

/* Thrive ships this as ProximaNova-Extrabld / 900 / 29px / lh 36px */
.eyebrow{
  font-family:var(--font-proxima);
  font-size:29px;line-height:36px;font-weight:700;
  letter-spacing:normal;
  text-transform:uppercase;color:var(--ink);
  margin-bottom:10px;
}
/* Thrive ships this as ProximaNova-Extrabld / 81px / lh 85px */
.hero-title{
  font-family:var(--font-proxima);
  font-size:80px;line-height:85px;
  /* Two lines of the large size are reserved whatever the slide is showing.
     Slide one runs a full sentence at a smaller size over three lines, the rest
     are two big words over two — so without this the banner changed height every
     seven seconds and shunted the page under it. */
  min-height:176px;font-weight:900;
  letter-spacing:normal;
  color:var(--red);
  text-transform:uppercase;
}
/* One slide carries the client's full headline rather than two words, and 80px
   on a fifty-character line runs to four lines and out of the column. JS adds
   this when the line it is about to show is long, so it tracks the copy instead
   of being pinned to a slide number. One clamp rather than a set of breakpoint
   overrides, so it holds at every width without a specificity fight. */
.hero-title.is-long{
  font-size:clamp(26px,2.9vw,44px);
  line-height:1.16;
}
/* The two-word slides are built as "word one / & / word two" over two lines.
   A full sentence does not want that break — it stranded the ampersand alone on
   its own line — so the long variant drops it and the headline simply flows. */
.hero-title.is-long br{display:none}
.hero-title.is-long .amp{margin-left:.12em}

/* one nowrap box per word, so a line can only break at a real space */
.ht-word{display:inline-block;white-space:nowrap}

/* the ampersand is the one glyph here in Outfit — it had no rule of its own and
   was inheriting Proxima from the heading */
.amp{font-family:var(--font-head);font-weight:900}
/* Per-letter reveal. The word is split into one span per character and each
   carries its own transition-delay, so the headline resolves letter by letter
   rather than moving as one block. That sequencing is what separates a crafted
   headline from a faded one — a whole word sliding is a transition, letters
   arriving in order is a performance.
   Delays are written inline by JS, since they depend on each letter's index. */
.ht-mask{display:inline-block;vertical-align:bottom}
.ht-c{
  display:inline-block;
  transition:opacity .5s ease,
             transform .62s cubic-bezier(.19,1,.22,1);
}
/* Leaving is fast and unstaggered; only arriving is staggered. Sharing the
   per-letter delays with the out phase meant the line took ~1s to clear AND ~1s
   to come back, so the hero sat empty in between. The !important is doing real
   work here: the delays are inline styles written by JS, and only !important
   overrides an inline declaration. */
.hero-copy.is-out .ht-c,
.hero-copy.is-out .amp{
  transition-delay:0s !important;
  transition-duration:.22s !important;
  opacity:0;transform:translateY(-16px);
}
.hero-copy.is-pre .ht-c{opacity:0;transform:translateY(26px);transition:none}

/* the ampersand travels with the letters. Its delay is written by JS rather than
   fixed here, because it has to land between the two words and the first word's
   length changes with every line. */
.amp{
  display:inline-block;
  transition:opacity .5s ease,
             transform .62s cubic-bezier(.19,1,.22,1);
}
.hero-copy.is-pre .amp{opacity:0;transform:translateY(26px);transition:none}

/* the eyebrow moves as one line — per-letter on a full sentence reads as a
   gimmick, and it would compete with the headline doing the same thing */
#heroEyebrow{
  display:inline-block;
  transition:opacity .5s ease,transform .5s cubic-bezier(.22,1,.36,1);
}
.hero-copy.is-out #heroEyebrow{opacity:0;transform:translateY(-12px);transition-duration:.22s}
.hero-copy.is-pre #heroEyebrow{opacity:0;transform:translateY(12px);transition:none}

@media (prefers-reduced-motion:reduce){
  .ht-c,.amp,#heroEyebrow{transition:none}
  .hero-copy.is-out .amp,
  .hero-copy.is-pre .amp,
  .hero-copy.is-out .ht-c,
  .hero-copy.is-pre .ht-c,
  .hero-copy.is-out #heroEyebrow,
  .hero-copy.is-pre #heroEyebrow{opacity:1;transform:none}
}


.hero-title .amp{color:var(--navy)}

/* form */
.hero-form{display:flex;gap:16px;margin-top:38px;max-width:820px}
.field{
  position:relative;flex:1 1 210px;min-width:0;
}
.field-ico{
  position:absolute;left:20px;top:50%;transform:translateY(-50%);
  color:var(--ink-muted);pointer-events:none;display:grid;place-items:center;
}
.field input{
  width:100%;height:64px;
  padding:0 22px 0 50px;
  font-family:var(--font-body);font-size:17px;color:var(--ink);
  background:#fff;border:1.5px solid var(--line);border-radius:10px;
  transition:border-color .18s ease,box-shadow .18s ease;
}
.field input::placeholder{color:var(--ink-muted)}

/* Animated placeholder. The native ::placeholder can't carry a caret, so JS
   blanks it and types into this overlay instead. It sits behind the input's
   pointer events, and hides the moment the field is focused or has a value. */
.field-ghost{
  position:absolute;left:50px;top:50%;transform:translateY(-50%);
  pointer-events:none;
  font-family:var(--font-body);font-size:17px;line-height:1;
  color:var(--ink-muted);white-space:nowrap;
  opacity:1;transition:opacity .18s ease;
}
.field-ghost::after{
  content:"";display:inline-block;
  width:2px;height:1.05em;margin-left:3px;vertical-align:-2px;
  background:var(--red);
  animation:ghost-caret 1.05s steps(1) infinite;
}
/* visibility as well as opacity: opacity alone left the overlay in the paint
   tree mid-transition, so the placeholder text sat on top of the number the
   visitor had just typed. */
.field-ghost.is-off{opacity:0;visibility:hidden}
@keyframes ghost-caret{50%{opacity:0}}

.field input:focus{outline:none;border-color:var(--navy);box-shadow:0 0 0 4px rgba(14,30,99,.10)}
.hero-form .btn{height:64px;padding:0 36px}
.hero-form{flex-wrap:wrap}
.field input.is-bad{border-color:var(--red);box-shadow:0 0 0 4px rgba(237,28,36,.12)}
.field input.is-good{border-color:#1E9E5A;box-shadow:0 0 0 4px rgba(30,158,90,.12)}

/* validation message sits on its own line under the row */
.field-msg{
  flex:0 0 100%;margin:0;min-height:0;
  font-size:14px;line-height:1.4;color:var(--ink-muted);
}
.field-msg.is-bad{color:var(--red);font-weight:600}
.field-msg.is-good{color:#137F45;font-weight:600}

/* ---- autocomplete dropdown (shared by the ZIP and Town fields) ---- */
.ac-list{
  position:absolute;z-index:40;top:calc(100% + 10px);left:0;right:0;
  max-height:286px;overflow-y:auto;overscroll-behavior:contain;
  background:#fff;border:1px solid var(--line);border-radius:14px;
  box-shadow:var(--shadow-lg);
  padding:7px;
}
.ac-list li{
  display:flex;align-items:center;gap:13px;
  padding:11px 13px;border-radius:9px;cursor:pointer;
  transition:background .13s ease;
}
.ac-list li[aria-selected="true"],
.ac-list li:hover{background:var(--tint)}
.ac-list .zl-pin{
  flex:none;width:32px;height:32px;border-radius:9px;
  display:grid;place-items:center;
  background:var(--tint);color:var(--navy);
}
.ac-list li[aria-selected="true"] .zl-pin,
.ac-list li:hover .zl-pin{background:var(--navy);color:#fff}
.zl-code{
  font-family:var(--font-proxima);font-weight:700;
  font-size:16px;color:var(--ink);letter-spacing:.01em;
}
.zl-code mark{background:none;color:var(--red);font:inherit}
.zl-town{font-size:13.5px;color:var(--ink-muted);margin-left:auto;padding-left:14px}
.ac-list .zl-empty{
  padding:16px 13px;color:var(--ink-muted);font-size:14px;cursor:default;
}
.ac-list .zl-empty:hover{background:none}

/* =========================================================
   SERVICE TICKER
   ========================================================= */
.ticker{
  background:var(--red);
  /* The band's height came from the text's own line box, and an uppercase
     Proxima line box carries more space under the baseline than over it — so
     20px top and bottom rendered visibly off-center. The items are given a
     fixed line height and centred inside it instead. */
  padding:0;
  overflow:hidden;
}
/* two identical sets; slides exactly one set's width then snaps back, so the
   reset lands on a pixel-identical frame and the loop never seams */
.ticker-track{
  display:flex;width:max-content;
  animation:ticker-scroll 34s linear infinite;
}
.ticker:hover .ticker-track{animation-play-state:paused}

.ticker-set{display:flex;align-items:stretch;flex:none}
.ticker-set li{flex:none;display:flex;align-items:center}
/* the layout moves onto the anchor so the whole item is the hit area, not just
   the words */
.ticker-set a{
  position:relative;
  display:inline-flex;align-items:center;gap:16px;
  height:clamp(58px,5.4vw,84px);
  padding:0 26px;
  color:inherit;
  transition:opacity .18s ease;
}
/* the underline grows from the middle out under whichever item is hovered,
   fading at both ends so it reads as a highlight rather than a border */
.ticker-label{position:relative;display:inline-block}
.ticker-label::after{
  content:"";position:absolute;left:50%;right:50%;bottom:-.18em;height:3px;
  border-radius:3px;
  background:linear-gradient(90deg,rgba(255,255,255,0),#fff 50%,rgba(255,255,255,0));
  transition:left .34s cubic-bezier(.22,1,.36,1),right .34s cubic-bezier(.22,1,.36,1);
}
.ticker-set a:hover .ticker-label::after{left:0;right:0}
.ticker-set a:hover{opacity:1}
.ticker-set li{
  font-family:var(--font-proxima);font-weight:700;
  font-size:clamp(19px,1.85vw,30px);line-height:1.2;
  letter-spacing:-.015em;text-transform:uppercase;
  color:#fff;white-space:nowrap;
}
/* the separator turns continuously — slowly enough to be a texture rather than
   something competing with the band's own movement */
.ticker-star{flex:none;display:grid;place-items:center;color:#fff}
.ticker-star svg{
  width:.82em;height:.82em;display:block;opacity:.9;
  animation:ticker-spin 9s linear infinite;
}
@keyframes ticker-spin{from{transform:rotate(0)}to{transform:rotate(360deg)}}

@keyframes ticker-scroll{
  from{transform:translate3d(0,0,0)}
  to{transform:translate3d(-50%,0,0)}
}
@media (prefers-reduced-motion:reduce){
  .ticker-track{animation:none}
  .ticker-star svg{animation:none}
  .ticker{overflow-x:auto}
}

/* =========================================================
   BOOK / INQUIRY
   =========================================================
   Photo field with a heavy white wash over it, so the section still reads as a
   light part of the page while the rooftop shot gives it depth. The form sits in
   a white card on the left, the pitch on the right. */
.book{
  position:relative;overflow:hidden;
  padding:78px 0 84px;
  background:#EEF1F8;
}
.book::before{
  content:"";position:absolute;inset:0;z-index:0;
  background:url("../img/hero/hero-bg-2.jpg") center/cover no-repeat;
  opacity:.5;
}
/* the wash is a separate layer so the photo's own opacity doesn't dilute it */
.book::after{
  content:"";position:absolute;inset:0;z-index:0;
  background:linear-gradient(180deg,rgba(244,245,248,.82),rgba(244,245,248,.9));
}
.book-grid{
  position:relative;z-index:1;
  display:grid;grid-template-columns:1.04fr .96fr;
  gap:clamp(34px,4vw,64px);align-items:center;
}
.book-grid > *{min-width:0}

/* ---- the card ---- */
.book-card{
  background:#fff;border-radius:22px;
  padding:34px 34px 32px;
  box-shadow:0 26px 60px rgba(9,16,48,.16);
}
.book-card > h2{
  margin-bottom:22px;text-align:center;
  font-family:var(--font-proxima);font-weight:700;
  font-size:clamp(25px,2.3vw,32px);line-height:1.2;
  color:var(--ink);letter-spacing:-.02em;
}
/* the emphasis word carries the accent — same trick as the hero's two-tone line */
.book-card > h2 em{font-style:normal;color:var(--red)}

.book-form{display:flex;flex-direction:column;gap:14px}
/* required marks read as part of the label, not as errors */
.book-form label i{font-style:normal;color:var(--red);margin-left:1px}
.book-form textarea{
  width:100%;padding:13px 16px;resize:vertical;min-height:104px;
  font-family:var(--font-body);font-size:16px;line-height:1.55;color:var(--ink);
  background:#fff;border:1.5px solid var(--line);border-radius:10px;
  transition:border-color .18s ease,box-shadow .18s ease;
}
.book-form textarea::placeholder{color:#AEB4CB}
.book-form textarea:focus{outline:none;border-color:var(--navy);box-shadow:0 0 0 4px rgba(14,30,99,.1)}

/* native select is fine on white — it only needed theming on the dark CTA */
.mf-sel{position:relative}
.mf-sel select{
  appearance:none;-webkit-appearance:none;
  width:100%;height:50px;padding:0 38px 0 16px;cursor:pointer;
  font-family:var(--font-body);font-size:16px;color:var(--ink);
  background:#fff;border:1.5px solid var(--line);border-radius:10px;
  transition:border-color .18s ease,box-shadow .18s ease;
}
.mf-sel select:focus{outline:none;border-color:var(--navy);box-shadow:0 0 0 4px rgba(14,30,99,.1)}
.mf-sel select.is-bad{border-color:var(--red);box-shadow:0 0 0 4px rgba(237,28,36,.12)}
.mf-sel svg{position:absolute;right:14px;top:17px;color:var(--ink-muted);pointer-events:none}

/* hugs its label and sits left — .book-form is a flex column, so align-self is
   what controls the cross axis here */
.book-send{
  width:auto;align-self:flex-start;
  height:56px;gap:9px;margin-top:4px;
}
/* On a phone the label plus .btn's 34px side padding came to 305px of a 346px
   measure — technically left-aligned, but it read as full-bleed. Trimming both
   makes the alignment legible. */
@media (max-width:600px){
  .book-send{height:52px;padding:0 22px;font-size:15px}
}

.book-done{text-align:center;padding:26px 0 10px}
.book-done[hidden]{display:none}
.book-done h3{font-family:var(--font-proxima);font-weight:700;font-size:25px;color:var(--ink)}
.book-done p{margin:9px 0 0;font-size:15.5px;line-height:1.6;color:var(--ink-body)}

/* ---- the pitch ---- */
.book-badge{
  display:inline-flex;align-items:center;gap:10px;
  padding:9px 16px 9px 13px;border-radius:50px;
  background:#fff;box-shadow:0 6px 18px rgba(9,16,48,.1);
  font-family:var(--font-head);font-weight:700;
  font-size:13.5px;color:var(--ink);
}
.book-badge img,.book-g{display:block;flex:none}
.book-copy h2{
  margin:20px 0 0;
  font-family:var(--font-proxima);font-weight:700;
  font-size:clamp(32px,3.7vw,50px);line-height:1.08;
  color:var(--ink);letter-spacing:-.028em;
}
.book-copy h2 em{font-style:normal;color:var(--red)}
.book-copy > p{
  margin:16px 0 0;max-width:46ch;
  font-size:16.5px;line-height:1.7;color:var(--ink-body);
}

/* Same build as the service card buttons — carries .scard-btn so the disc, the
   ringing icon, the rings and the hover all come from one place. Scaled up,
   since this one is the section's primary action rather than a card footer.
   Two classes so the responsive .scard-btn block later in the file (one class)
   can't shrink it back to card height. */
.scard-btn.book-call{
  --card-ink:var(--red);
  --card-ico-bg:var(--tint-red-sm);
  --card-ico:var(--red);
  --card-glow:rgba(237,28,36,.5);

  margin:30px 0 0;
  height:74px;padding:0 32px 0 13px;gap:16px;
  border-radius:14px;
}
.scard-btn.book-call .phone-ico{width:48px;height:48px}
.scard-btn.book-call .scb-txt em{font-size:11px}
.scard-btn.book-call b{font-size:25px}

@media (max-width:560px){
  .scard-btn.book-call{height:66px;padding:0 24px 0 10px;gap:13px;margin-top:24px}
  .scard-btn.book-call .phone-ico{width:42px;height:42px}
  .scard-btn.book-call b{font-size:21px}
}

@media (max-width:980px){
  .book{padding:56px 0 62px}
  .book-grid{grid-template-columns:1fr;gap:32px}
  /* pitch above the form on narrow screens — the heading has to introduce the
     card, not follow it */
  .book-copy{order:-1}
  .book-card{padding:26px 22px 24px}
  .book-copy h2{margin-top:16px}
}
@media (max-width:560px){
  .book-form .mf-row{grid-template-columns:1fr}
}

/* =========================================================
   VIDEO TESTIMONIALS
   ========================================================= */
.results{padding:74px 0 84px}
.results-head{
  font-family:var(--font-head);font-weight:700;
  font-size:clamp(26px,2.6vw,36px);line-height:1.2;
  text-align:center;color:var(--ink);
  margin-bottom:38px;
}
.results-grid{display:grid;grid-template-columns:1fr 1fr;gap:32px}

.rcard{
  display:flex;flex-direction:column;
  background:#fff;border:1px solid var(--line);border-radius:18px;
  overflow:hidden;
  box-shadow:var(--shadow-sm);
  transition:box-shadow .3s ease,transform .3s ease;
}
.rcard:hover{box-shadow:var(--shadow-md);transform:translateY(-3px)}

/* self-hosted clip — no third-party player, so play is instant */
.rcard-media{
  position:relative;width:100%;
  aspect-ratio:16/9;overflow:hidden;
  background:var(--navy);
}
.rcard-video{
  position:absolute;inset:0;
  width:100%;height:100%;display:block;
  object-fit:cover;background:var(--navy);
}

/* full-bleed hit area; fades away once the clip is running */
.rcard-btn{
  position:absolute;inset:0;z-index:2;
  width:100%;height:100%;padding:0;
  cursor:pointer;
  opacity:1;transition:opacity .3s ease;
}
.rcard-media.is-playing .rcard-btn{opacity:0;pointer-events:none}
/* scrim keeps the button readable on any poster */
.rcard-btn::after{
  content:"";position:absolute;inset:0;
  background:linear-gradient(180deg,rgba(9,16,48,.12),rgba(9,16,48,.4));
  transition:background .35s ease;
}
.rcard-btn:hover::after{background:linear-gradient(180deg,rgba(9,16,48,.04),rgba(9,16,48,.28))}

/* transparent frosted disc — picks up the colors of the frame behind it */
.rcard-play{
  position:absolute;z-index:2;left:50%;top:50%;
  transform:translate(-50%,-50%);
  width:76px;height:76px;border-radius:50%;
  display:grid;place-items:center;
  color:#fff;
  background:rgba(255,255,255,.13);
  border:1.5px solid rgba(255,255,255,.72);
  backdrop-filter:blur(10px) saturate(150%);
  -webkit-backdrop-filter:blur(10px) saturate(150%);
  box-shadow:0 12px 36px rgba(9,16,48,.28);
  transition:transform .35s cubic-bezier(.22,1,.36,1),
             background .3s ease,border-color .3s ease;
}
/* hairline ring that breathes outward on hover */
.rcard-play::before{
  content:"";position:absolute;inset:-12px;border-radius:50%;
  border:1px solid rgba(255,255,255,.32);
  transition:inset .45s cubic-bezier(.22,1,.36,1),opacity .45s ease;
}
.rcard-btn:hover .rcard-play{
  transform:translate(-50%,-50%) scale(1.06);
  background:rgba(255,255,255,.24);
  border-color:#fff;
}
.rcard-btn:hover .rcard-play::before{inset:-21px;opacity:0}

.rcard-quote{margin:0;padding:22px 26px;background:var(--red)}
.rcard-quote p{
  margin:0;
  font-family:var(--font-head);font-weight:700;
  font-size:17.5px;line-height:1.45;color:#fff;
}
.rcard-quote cite{
  display:block;margin-top:10px;font-style:normal;
  font-family:var(--font-head);font-weight:700;
  font-size:13px;letter-spacing:.05em;text-transform:uppercase;
  color:rgba(255,255,255,.82);
}

.rcard-body{display:flex;flex-direction:column;flex:1 1 auto;padding:24px 26px 26px}

.rcard-stats{display:grid;grid-template-columns:1fr 1fr;margin-bottom:20px}
.rcard-stats > div{text-align:center;padding:0 10px}
.rcard-stats > div + div{border-left:1px solid var(--line)}
.rcard-stats b{
  display:block;
  font-family:var(--font-proxima);font-weight:700;
  font-size:clamp(26px,2.2vw,34px);line-height:1.1;color:var(--navy);
}
.rcard-stats span{
  display:block;margin-top:5px;
  font-size:13px;line-height:1.35;color:var(--ink-muted);
}

.rcard-copy{margin:0;font-size:15px;line-height:1.62;color:var(--ink-body)}

.results-cta{display:flex;justify-content:center;margin-top:40px}

/* =========================================================
   ABOUT
   ========================================================= */
.about{padding:44px 0 90px}
.about-grid{
  display:grid;grid-template-columns:1fr 1fr;
  gap:64px;align-items:center;
}
.about-grid > *{min-width:0}

.kicker{
  display:inline-block;margin-bottom:14px;
  font-family:var(--font-head);font-weight:800;
  font-size:12.5px;letter-spacing:.14em;text-transform:uppercase;
  color:var(--red);
}
/* pill variant — the right padding is trimmed because .14em tracking leaves a
   trailing space after the last letter that would otherwise read off-center */
.about-copy .kicker,
.why-copy .kicker{
  padding:7px 13px 7px 16px;
  border-radius:999px;
  background:var(--tint-red-sm);
}
.about-copy h2{
  font-family:var(--font-head);font-weight:700;
  font-size:clamp(27px,2.5vw,38px);line-height:1.22;
  color:var(--ink);letter-spacing:-.01em;
}
.about-copy p{margin:18px 0 0;font-size:16px;line-height:1.68;color:var(--ink-body)}

.about-points{
  display:grid;grid-template-columns:1fr 1fr;gap:12px 22px;
  margin:26px 0 30px;
}
.about-points li{
  position:relative;padding-left:28px;
  font-size:15px;line-height:1.45;color:var(--ink);font-weight:500;
}
.about-points li::before{
  content:"";position:absolute;left:0;top:3px;
  width:18px;height:18px;border-radius:50%;
  background:var(--tint-red-sm);
}
.about-points li::after{
  content:"";position:absolute;left:5px;top:8px;
  width:8px;height:4.5px;
  border-left:2px solid var(--red);border-bottom:2px solid var(--red);
  transform:rotate(-45deg);
}

.about-cta{display:flex;align-items:center;gap:26px;flex-wrap:wrap}
.about-call{display:inline-flex;align-items:center;gap:14px}
.about-call-ico{
  width:50px;height:50px;border-radius:50%;
  display:grid;place-items:center;
  background:var(--tint-red-sm);color:var(--red);
  transition:background .18s ease,color .18s ease;
}
.about-call:hover .about-call-ico{background:var(--red);color:#fff}
.about-call em{
  display:block;font-style:normal;
  font-size:13.5px;color:var(--ink-muted);line-height:1.3;
}
.about-call b{
  display:block;
  font-family:var(--font-head);font-weight:800;font-size:24px;
  color:var(--red);letter-spacing:-.015em;
}

/* image + overlapping stat badge */
.about-visual{position:relative}
.about-visual img{
  width:100%;height:clamp(400px,42vw,560px);object-fit:cover;
  border-radius:20px;
  box-shadow:var(--shadow-lg);
}
.about-badge{
  position:absolute;left:-26px;bottom:-26px;
  display:flex;align-items:center;gap:15px;
  padding:20px 26px;border-radius:16px;
  background:var(--navy);color:#fff;
  box-shadow:0 22px 46px rgba(9,16,48,.28);
}
.about-badge b{
  font-family:var(--font-proxima);font-weight:700;
  font-size:44px;line-height:1;letter-spacing:-.02em;
}
.about-badge i{
  font-style:normal;color:var(--red);
  font-size:.5em;vertical-align:super;margin-left:1px;
}
.about-badge span{font-size:13px;line-height:1.4;color:rgba(255,255,255,.82)}

/* =========================================================
   WHY CHOOSE ABC
   ========================================================= */
.why{padding:26px 0 92px}
.why-grid{
  display:grid;grid-template-columns:1fr 1fr;
  gap:64px;align-items:center;
}
.why-grid > *{min-width:0}

/* image + review badge */
.why-visual{position:relative}
.why-visual img{
  width:100%;height:clamp(420px,44vw,580px);object-fit:cover;
  border-radius:20px;
  box-shadow:var(--shadow-lg);
}
/* The home page runs a wide photograph here instead of the portrait crew shot.
   The default frame is 1.118 at desktop, so a 16:10 image loses 30% off its
   sides — on the skyline that cuts the first and last letters off the word.
   This frame matches the picture instead, so nothing is cropped. */
.why-visual--wide img{height:auto;aspect-ratio:16/10}

/* compact horizontal lockup — the Google mark does the credibility work, so
   the rating can sit small beside it rather than filling a tall card */
.why-badge{
  position:absolute;right:-24px;bottom:-24px;
  display:flex;align-items:center;gap:15px;
  padding:14px 20px;border-radius:14px;
  background:#fff;border:1px solid var(--line);
  box-shadow:0 18px 40px rgba(9,16,48,.16);
}
.why-badge img{height:30px;width:auto;flex:none}
.why-badge-sep{width:1px;align-self:stretch;background:var(--line);flex:none}
.why-badge-rate{display:flex;flex-direction:column;gap:3px}
.why-stars{display:block;color:#F5A623;font-size:12px;letter-spacing:2.5px;line-height:1}
.why-badge-rate p{margin:0;display:flex;align-items:baseline;gap:6px;white-space:nowrap}
.why-badge-rate b{
  font-family:var(--font-proxima);font-weight:700;
  font-size:18px;line-height:1;color:var(--ink);
}
.why-badge-rate small{font-size:12px;color:var(--ink-muted)}

.why-copy h2{
  font-family:var(--font-head);font-weight:700;
  font-size:clamp(27px,2.5vw,38px);line-height:1.22;
  color:var(--ink);letter-spacing:-.01em;
}
.why-lead{margin:16px 0 0;font-size:16px;line-height:1.68;color:var(--ink-body)}

/* 2x2 grid of cards. The numeral is a direct child of the card so it anchors
   to the card's own top-right corner, not to the text block. */
.why-list{display:grid;grid-template-columns:1fr 1fr;gap:18px;margin-top:32px}
/* tinted in a diagonal: blue top-left + bottom-right, red top-right +
   bottom-left. Each card sets its own accent vars so the icon, numeral and
   hover all follow its tint without repeating selectors. */
.why-list li{
  --card-bg:var(--tint);
  --card-ink:var(--navy);
  --card-ghost:#D7DFF7;
  --card-shadow:rgba(14,30,99,.28);
  position:relative;overflow:hidden;
  display:flex;flex-direction:column;
  padding:24px 22px 26px;
  background:var(--card-bg);border:0;border-radius:18px;
  transition:transform .32s cubic-bezier(.22,1,.36,1),box-shadow .32s ease;
}
.why-list li:nth-child(2),
.why-list li:nth-child(3){
  --card-bg:var(--tint-red-sm);
  --card-ink:var(--red);
  --card-ghost:#F6C9CC;
  --card-shadow:rgba(237,28,36,.26);
}
.why-list li:hover{
  transform:translateY(-5px);
  box-shadow:0 22px 46px rgba(14,30,99,.15);
}
.why-num{
  position:absolute;top:14px;right:18px;
  font-family:var(--font-proxima);font-weight:700;
  font-size:40px;line-height:1;
  color:var(--card-ghost);
  font-variant-numeric:tabular-nums;
  transition:color .32s ease,transform .32s ease;
  pointer-events:none;
}
.why-list li:hover .why-num{transform:scale(1.06)}

.why-node{
  flex:none;width:52px;height:52px;border-radius:16px;
  display:grid;place-items:center;
  margin-bottom:16px;
  background:var(--card-ink);color:#fff;
  box-shadow:0 8px 20px var(--card-shadow);
  transition:background .3s ease,color .3s ease,transform .3s cubic-bezier(.22,1,.36,1);
}
.why-node svg{width:32px;height:32px;overflow:visible}
.why-list li:hover .why-node{transform:translateY(-3px) scale(1.05)}

/* ---- icon animations ----
   Every card's icon acts out its own claim. Each runs on its own clock so the
   four never fall into step, which is what makes icon sets look mechanical. */
.why-node svg [class^="ic-"]{transform-box:fill-box}

/* 01 · SAFETY — protection rings outward; the fire keeps burning, contained */
.ic-pulse{
  transform-origin:center;opacity:0;
  animation:ic-pulse 3.2s cubic-bezier(.22,1,.36,1) infinite;
}
@keyframes ic-pulse{
  0%  {transform:scale(.55);opacity:0}
  25% {opacity:.5}
  70%,100%{transform:scale(1.16);opacity:0}
}
.ic-flame{transform-origin:50% 100%;animation:ic-flicker 1.9s ease-in-out infinite}
@keyframes ic-flicker{
  0%,100%{transform:scale(1,1)      translateX(0)}
  18%    {transform:scale(.86,1.22) translateX(-.35px)}
  38%    {transform:scale(1.12,.88) translateX(.3px)}
  58%    {transform:scale(.92,1.14) translateX(-.2px)}
  80%    {transform:scale(1.05,.95) translateX(.15px)}
}
/* inner spark runs faster than the flame around it — real fire never moves as one */
.ic-spark{transform-origin:50% 100%;animation:ic-spark 1.15s ease-in-out infinite}
@keyframes ic-spark{
  0%,100%{transform:scale(1,1);opacity:.9}
  40%    {transform:scale(.8,1.3);opacity:.45}
  70%    {transform:scale(1.15,.85);opacity:1}
}

/* 02 · INSPECTION — scan sweeps the flue, aperture stops down on what it finds */
.ic-scan{
  stroke-dasharray:14.8;
  animation:ic-scan 3.6s cubic-bezier(.5,0,.5,1) infinite;
}
@keyframes ic-scan{
  0%      {transform:translateY(-5.6px);opacity:0}
  12%     {opacity:.95}
  50%     {transform:translateY(5.6px); opacity:.95}
  62%,100%{transform:translateY(5.6px); opacity:0}
}
.ic-lens{transform-origin:center;animation:ic-focus 3.6s ease-in-out infinite}
@keyframes ic-focus{
  0%,42%{transform:scale(1)}
  55%   {transform:scale(.8)}
  68%   {transform:scale(1.06)}
  82%,100%{transform:scale(1)}
}
/* the aperture stops right down at the moment the scan lands */
.ic-iris{transform-origin:center;animation:ic-iris 3.6s ease-in-out infinite}
@keyframes ic-iris{
  0%,42%{transform:scale(1)}
  55%   {transform:scale(.28)}
  70%   {transform:scale(1.5)}
  85%,100%{transform:scale(1)}
}
.ic-rec{animation:ic-blink 1.2s steps(1,end) infinite}
@keyframes ic-blink{0%,52%{opacity:1}53%,100%{opacity:.1}}

/* 03 · ONE CREW — the hat works away while the bar under it runs start to finish */
.ic-hat{transform-origin:50% 92%;animation:ic-work 1.6s ease-in-out infinite}
@keyframes ic-work{
  0%,100%{transform:translateY(0)    rotate(0deg)}
  30%    {transform:translateY(-1.4px) rotate(-5deg)}
  62%    {transform:translateY(-.3px)  rotate(4deg)}
}
.ic-track{opacity:.28}
.ic-fill{
  stroke:var(--red);
  stroke-dasharray:15.2;stroke-dashoffset:15.2;
  animation:ic-progress 3.8s cubic-bezier(.65,0,.35,1) infinite;
}
@keyframes ic-progress{
  0%      {stroke-dashoffset:15.2}
  55%,78% {stroke-dashoffset:0}
  92%,100%{stroke-dashoffset:-15.2}   /* runs off the end rather than snapping back */
}

/* 04 · IN WRITING — three lines written in sequence, then the seal presses down */
.ic-l1,.ic-l2,.ic-l3{stroke-dashoffset:7}
.ic-l1{stroke-dasharray:7;  animation:ic-write 5s ease-out infinite}
.ic-l2{stroke-dasharray:7;  animation:ic-write 5s ease-out infinite .42s}
.ic-l3{stroke-dasharray:3.6;stroke-dashoffset:3.6;animation:ic-write3 5s ease-out infinite .84s}
@keyframes ic-write { 0%{stroke-dashoffset:7}  22%,86%{stroke-dashoffset:0}  100%{stroke-dashoffset:7} }
@keyframes ic-write3{ 0%{stroke-dashoffset:3.6}22%,86%{stroke-dashoffset:0}  100%{stroke-dashoffset:3.6} }

.ic-seal{transform-origin:50% 55%;animation:ic-stamp 5s cubic-bezier(.34,1.56,.64,1) infinite}
@keyframes ic-stamp{
  0%,44%  {transform:scale(1) translateY(-2.2px);opacity:0}
  50%     {transform:scale(1.3) translateY(0);   opacity:1}
  57%     {transform:scale(.93) translateY(0);   opacity:1}
  64%,88% {transform:scale(1) translateY(0);     opacity:1}
  100%    {transform:scale(1) translateY(-2.2px);opacity:0}
}
/* impact ring thrown off as the seal lands */
.ic-ring{
  transform-origin:center;opacity:0;
  animation:ic-impact 5s ease-out infinite;
}
@keyframes ic-impact{
  0%,50%  {transform:scale(1);opacity:0}
  56%     {opacity:.55}
  74%,100%{transform:scale(1.85);opacity:0}
}

@media (prefers-reduced-motion:reduce){
  .why-node svg [class^="ic-"]{animation:none !important}
  .ic-l1,.ic-l2,.ic-l3,.ic-fill{stroke-dashoffset:0}
  .ic-pulse,.ic-ring,.ic-scan{opacity:0}
  .ic-seal{opacity:1;transform:none}
}

.why-text{position:relative;z-index:1}
.why-list h3{
  font-family:var(--font-head);font-weight:800;
  font-size:17px;line-height:1.3;color:var(--ink);letter-spacing:-.005em;
}
.why-list p{margin:8px 0 0;font-size:14.5px;line-height:1.6;color:var(--ink-body)}

/* =========================================================
   CTA
   ========================================================= */
.cta{
  position:relative;overflow:hidden;
  padding:68px 0 72px;
  background:#080D26;
}
/* deep red owns the right, deep blue the left; the blur softens the edges
   without washing the color out */

.cta-grid{
  position:relative;z-index:1;
  display:grid;grid-template-columns:.92fr 1.08fr;
  gap:clamp(48px,7vw,110px);align-items:start;
}
.cta-grid > *{min-width:0}

.cta .kicker{color:#FF9096}
.cta-copy h2{
  font-family:var(--font-head);font-weight:700;
  font-size:clamp(34px,4.1vw,58px);line-height:1.04;
  color:#fff;letter-spacing:-.028em;margin-top:2px;
}
.cta-copy > p{
  margin:22px 0 0;max-width:44ch;
  font-size:16.5px;line-height:1.7;color:rgba(255,255,255,.74);
}

/* the number gets the weight of a headline, because it converts like one */
.cta-phone{
  display:inline-block;margin-top:34px;
  padding-left:20px;border-left:3px solid var(--red);
}
.cta-phone em{
  display:block;font-style:normal;
  font-size:12.5px;letter-spacing:.14em;text-transform:uppercase;
  color:rgba(255,255,255,.58);margin-bottom:5px;
}
.cta-phone b{
  display:block;
  font-family:var(--font-proxima);font-weight:700;
  font-size:clamp(26px,2.4vw,34px);line-height:1;
  color:#fff;letter-spacing:-.02em;transition:color .2s ease;
}
.cta-phone:hover b{color:#FF9096}

.cta-points{margin-top:38px;display:flex;flex-direction:column;gap:0}
.cta-points li{
  position:relative;padding:13px 0 13px 30px;
  border-top:1px solid rgba(255,255,255,.15);
  font-size:14.5px;line-height:1.45;color:rgba(255,255,255,.9);
}
.cta-points li:last-child{border-bottom:1px solid rgba(255,255,255,.15)}
.cta-points li::before{
  content:"";position:absolute;left:2px;top:19px;
  width:9px;height:5px;
  border-left:2px solid #FF5A62;border-bottom:2px solid #FF5A62;
  transform:rotate(-45deg);
}

/* ---- custom listbox ---- */
.cf-label{
  font-family:var(--font-head);font-weight:700;
  font-size:11.5px;letter-spacing:.14em;text-transform:uppercase;
  color:rgba(255,255,255,.6);margin-bottom:9px;
}
.csel{position:relative}
.csel-btn{
  width:100%;display:flex;align-items:center;justify-content:space-between;gap:12px;
  padding:0 0 12px;text-align:left;cursor:pointer;
  background:transparent;border:0;border-bottom:1.5px solid rgba(255,255,255,.24);
  font-family:var(--font-body);font-size:16.5px;color:#fff;
  transition:border-color .22s ease;
}
.csel-btn svg{flex:none;color:rgba(255,255,255,.6);transition:transform .24s ease}
.csel-btn[aria-expanded="true"]{border-bottom-color:#fff}
.csel-btn[aria-expanded="true"] svg{transform:rotate(180deg)}
.csel.is-bad .csel-btn{border-bottom-color:#FF5A62}
.csel-val.is-placeholder{color:rgba(255,255,255,.38)}
.csel-list{
  position:absolute;z-index:40;left:0;right:0;top:calc(100% + 10px);
  max-height:268px;overflow-y:auto;overscroll-behavior:contain;padding:7px;
  background:#0C1330;border:1px solid rgba(255,255,255,.15);border-radius:13px;
  box-shadow:0 26px 56px rgba(0,0,0,.55);
}
.csel-list li{
  padding:11px 14px;border-radius:9px;cursor:pointer;
  font-size:15px;line-height:1.35;color:rgba(255,255,255,.84);
  transition:background .14s ease,color .14s ease;
}
.csel-list li:hover,
.csel-list li[aria-selected="true"]{background:rgba(255,255,255,.1);color:#fff}
.csel-list li.is-chosen{color:#FF9096}
.csel-list::-webkit-scrollbar{width:6px}
.csel-list::-webkit-scrollbar-thumb{background:rgba(255,255,255,.2);border-radius:6px}

/* ---- form: rule-only fields ---- */
.cform{display:flex;flex-direction:column;gap:26px}
.cform-row{display:grid;grid-template-columns:1fr 1fr;gap:26px}
.cf{display:flex;flex-direction:column;gap:0;min-width:0}
.cf label{
  font-family:var(--font-head);font-weight:700;
  font-size:11.5px;letter-spacing:.14em;text-transform:uppercase;
  color:rgba(255,255,255,.6);margin-bottom:9px;
}
.cf-opt{text-transform:none;letter-spacing:.02em;font-weight:500;color:rgba(255,255,255,.4);margin-left:4px}
.cf input,.cf textarea{
  width:100%;font-family:var(--font-body);font-size:16.5px;color:#fff;
  background:transparent;border:0;border-bottom:1.5px solid rgba(255,255,255,.24);
  border-radius:0;padding:0 0 12px;transition:border-color .22s ease;
}
.cf textarea{resize:vertical;min-height:52px;line-height:1.6}
.cf input::placeholder,.cf textarea::placeholder{color:rgba(255,255,255,.38)}
.cf input:focus,.cf textarea:focus{outline:none;border-bottom-color:#fff}
.cf input.is-bad,.cf textarea.is-bad{border-bottom-color:#FF5A62}
.cf-err{font-size:12.5px;color:#FF9096;font-weight:600;display:none;margin-top:8px}
.cf-err.show{display:block}

.cform-send{width:100%;height:62px;margin-top:6px}
.cform-note{margin:0;text-align:center;font-size:12.5px;color:rgba(255,255,255,.55)}
.cform-done{text-align:center;padding:40px 0}
.cform-done[hidden]{display:none}
.cform-done h3{font-family:var(--font-proxima);font-weight:700;font-size:27px;color:#fff}
.cform-done p{margin:10px 0 0;font-size:15.5px;line-height:1.6;color:rgba(255,255,255,.75)}

/* =========================================================
   SERVICES
   ========================================================= */
.services{background:#F4F5F8;padding:82px 0 90px}
.services-head{max-width:660px;margin:0 auto 44px;text-align:center}

/* =========================================================
   SERVICE AREAS — the county blocks and their town lists
   ========================================================= */
.counties{padding:82px 0 90px}
/* Two blocks per row for the eight-county index. A town page renders one block
   and takes --one, because a lone card in a two-column grid sits at half width
   with a dead column beside it. */
.county-list{
  display:grid;grid-template-columns:repeat(2,1fr);
  gap:26px;align-items:start;
}
.county-list--one{grid-template-columns:1fr}

.county-block{
  overflow:hidden;
  background:#fff;border:1px solid var(--line);border-radius:20px;
  box-shadow:0 1px 2px rgba(14,30,99,.04), 0 14px 32px -20px rgba(14,30,99,.30);
  transition:box-shadow .35s ease;
}
.county-block:hover{box-shadow:0 1px 2px rgba(14,30,99,.05), 0 30px 54px -28px rgba(14,30,99,.42)}

/* navy bar rather than a hairline: it gives the county its own header the way
   the mega menu's promo card has one, and the list below reads as its contents */
.county-head{
  position:relative;
  display:flex;align-items:center;gap:14px;
  padding:17px 24px;
  background:linear-gradient(165deg,var(--navy) 0%,#0A1748 100%);
}
/* the same red leader that runs under the mega menu headings, extending the
   full width of the bar on hover */
.county-head::after{
  content:"";position:absolute;left:0;bottom:0;height:3px;width:74px;
  background:var(--red);
  transition:width .5s cubic-bezier(.22,1,.36,1);
}
.county-block:hover .county-head::after{width:100%}

.county-name{
  display:flex;align-items:center;gap:13px;
  font-family:var(--font-head);font-weight:800;
  font-size:18.5px;letter-spacing:-.01em;color:#fff;
}
.county-head .mega-ico{
  background:rgba(255,255,255,.08);color:#fff;
  box-shadow:inset 0 0 0 1px rgba(255,255,255,.18);
}
.county-name:hover .mega-ico{background:var(--red);color:#fff;box-shadow:inset 0 0 0 1px var(--red)}

.county-count{
  margin-left:auto;flex:none;
  padding:5px 12px;border-radius:999px;
  background:rgba(255,255,255,.09);
  box-shadow:inset 0 0 0 1px rgba(255,255,255,.16);
  font-family:var(--font-head);font-weight:700;
  font-size:11.5px;letter-spacing:.06em;text-transform:uppercase;
  color:rgba(255,255,255,.78);
}

/* Chips, not a text list. A column grid leaves ragged gaps when a county has 13
   towns and its neighbor has 29 — chips wrap to fill whatever width they get,
   and each town becomes a target you can see rather than a line of body copy. */
.town-grid{
  display:flex;flex-wrap:wrap;gap:9px;
  padding:22px 24px 24px;
}
.town-grid a{
  display:block;padding:9px 16px;border-radius:999px;
  background:var(--tint);
  font-family:var(--font-head);font-weight:600;
  font-size:14px;letter-spacing:-.005em;color:var(--ink);
  white-space:nowrap;
  transition:background .2s ease, color .2s ease,
             transform .3s cubic-bezier(.22,1,.36,1), box-shadow .25s ease;
}
.town-grid a:hover{
  background:var(--red);color:#fff;
  transform:translateY(-2px);
  box-shadow:0 10px 20px -9px rgba(237,28,36,.75);
}

.county-all{margin-top:40px;text-align:center}

@media (max-width:900px){
  .counties{padding:56px 0 60px}
  .county-list{grid-template-columns:1fr;gap:20px}
}
@media (max-width:560px){
  .county-head{padding:15px 18px;gap:11px}
  .county-name{font-size:16.5px;gap:11px}
  .county-count{padding:4px 10px;font-size:11px}
  .town-grid{padding:18px 18px 20px;gap:8px}
  .town-grid a{padding:8px 14px;font-size:13.5px}
}
/* "WHAT WE DO" — Proxima Nova / 700 / 17px */
/* right padding is trimmed to offset the .10em trailing track */
.services-head .kicker{
  font-family:var(--font-head);font-weight:700;
  font-size:13px;letter-spacing:.10em;
  padding:7px 13px 7px 15px;
  border-radius:999px;
  background:var(--tint-red-sm);
}
.services-head h2{
  font-family:var(--font-head);font-weight:700;
  font-size:clamp(27px,2.5vw,38px);line-height:1.22;
  color:var(--ink);letter-spacing:-.01em;
}
.services-head p{margin:14px 0 0;font-size:16px;line-height:1.65;color:var(--ink-body)}

.services-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:20px}

/* The tinted body runs straight off the bottom of the photo — connected, not
   overlapping. Each card sets its own accent vars so the kicker, ticks and
   footer all follow its tint. Laid out as a checkerboard across the grid. */
.scard{
  --card-bg:var(--tint);
  --card-ink:var(--navy);
  --card-line:rgba(14,30,99,.13);
  --card-soft:rgba(14,30,99,.10);
  --card-ico-bg:var(--tint);        /* light blue disc  */
  --card-ico:var(--navy);           /* dark blue glyph  */
  --card-glow:rgba(14,30,99,.5);    /* button ring       */
  display:flex;flex-direction:column;
  background:var(--card-bg);
  border-radius:18px;overflow:hidden;
  transition:transform .38s cubic-bezier(.22,1,.36,1),box-shadow .38s ease;
}
.scard:nth-child(2),.scard:nth-child(4),
.scard:nth-child(5),.scard:nth-child(7){
  --card-bg:var(--tint-red-sm);
  --card-ink:var(--red);
  --card-line:rgba(237,28,36,.18);
  --card-soft:rgba(237,28,36,.13);
  --card-ico-bg:var(--tint-red-sm); /* light red disc   */
  --card-ico:var(--red);            /* dark red glyph   */
  --card-glow:rgba(237,28,36,.55);  /* button ring       */
}
.scard:hover{transform:translateY(-7px);box-shadow:0 28px 56px rgba(14,30,99,.16)}

.scard-media{display:block;aspect-ratio:16/10;overflow:hidden}
.scard-media img{
  width:100%;height:100%;object-fit:cover;display:block;
  transition:transform .75s cubic-bezier(.22,1,.36,1);
}
.scard:hover .scard-media img{transform:scale(1.06)}

.scard-body{display:flex;flex-direction:column;flex:1 1 auto;padding:24px 24px 0}

/* white pill lifts the tag off the card's tint — hugs its own text in both
   the flex fallback and the subgrid layout, hence the two self-alignments */
.scard-kicker{
  display:inline-flex;align-items:center;width:fit-content;
  align-self:flex-start;justify-self:start;
  margin-bottom:12px;padding:6px 12px;
  border-radius:999px;background:#fff;
  box-shadow:0 1px 2px rgba(14,30,99,.07);
  font-family:var(--font-head);font-weight:800;
  font-size:11px;letter-spacing:.15em;text-transform:uppercase;
  color:var(--card-ink);
}
.scard h3{
  font-family:var(--font-head);font-weight:700;
  font-size:25px;line-height:1.18;color:var(--ink);letter-spacing:-.022em;
}
.scard h3 a{transition:color .18s ease}
.scard h3 a:hover{color:var(--card-ink)}
.scard-body > p{
  margin:11px 0 18px;
  font-size:14.2px;line-height:1.62;color:var(--ink-body);
}

/* Spec list. The tick is a real SVG with round caps sitting in its own tile —
   a CSS border-corner tick always reads mechanical at this size. The tiles
   fill in sequence on hover so the list resolves rather than flicking. */
.scard-ticks{display:flex;flex-direction:column;margin-bottom:24px}
.scard-ticks li{
  display:flex;align-items:center;gap:12px;
  padding:10px 0;
  border-top:1px solid var(--card-line);
  font-size:13.6px;line-height:1.4;color:var(--ink);
}
.scard-ticks li:first-child{border-top:0;padding-top:2px}

/* A hairline ring with a fine mark inside. Weight is what made the earlier
   passes read cheap — a 2.6 stroke at 17px shouts, and a pale filled tile
   washes out. Restraint instead: 1.15 ring at 26% and a 1.85 mark at full
   card ink, so the row reads as a spec line rather than an icon. */
.tick{flex:none;width:20px;height:20px;display:block;color:var(--card-ink)}
.tick svg{width:100%;height:100%;display:block;overflow:visible}
.tick circle{
  fill:none;stroke:currentColor;stroke-width:1.15;opacity:.26;
  transition:opacity .34s ease;
}
.tick path{
  fill:none;stroke:currentColor;stroke-width:1.85;
  stroke-linecap:round;stroke-linejoin:round;
}
.scard:hover .tick circle{opacity:.5}

/* pathLength:1 normalises the dash to the stroke, so each mark redraws
   itself in sequence when the card is hovered */
.tick path{stroke-dasharray:1;stroke-dashoffset:0}
@keyframes tick-draw{from{stroke-dashoffset:1}to{stroke-dashoffset:0}}
.scard:hover .tick path{animation:tick-draw .5s cubic-bezier(.22,1,.36,1) both}
.scard-ticks li:nth-child(2) .tick path{animation-delay:.08s}
.scard-ticks li:nth-child(3) .tick path{animation-delay:.16s}
@media (prefers-reduced-motion:reduce){
  .scard:hover .tick path{animation:none}
}

/* Call button, same make-up as the CTA bar's call half: light red disc, dark
   red glyph, number in Proxima. Keeps each card's own ink as the ground so the
   navy/red checkerboard across the grid still holds. */
.scard-btn{
  margin:auto 0 24px;
  /* hugs its content and sits left — align-self covers the flex fallback,
     justify-self the subgrid layout */
  width:fit-content;align-self:flex-start;justify-self:start;
  position:relative;
  display:inline-flex;align-items:center;gap:12px;
  height:62px;padding:0 22px 0 10px;
  border-radius:11px;border:0;
  background:var(--card-ink);
  cursor:pointer;
  transition:filter .28s ease,gap .28s cubic-bezier(.22,1,.36,1);
}
/* disc follows the card's accent — blue cards get a blue icon, red cards red.
   The fill is set on the path in CSS because the markup carries fill="#ED1C24"
   as an attribute, and a CSS fill is what overrides a presentation attribute. */
.scard-btn .phone-ico{
  position:relative;
  flex:none;width:34px;height:34px;
  background:var(--card-ico-bg);
}
.scard-btn .phone-ico svg path{fill:var(--card-ico)}

/* Two rings leaving the disc, the second half a cycle behind the first, so the
   signal reads as continuous rather than a repeated pop. Scale stops at 1.5
   (34px -> 51px) to stay inside the 58px button instead of spilling past its
   edges. Ring takes the light tint so it shows against the navy or red fill. */
.scard-btn .phone-ico::before,
.scard-btn .phone-ico::after{
  content:"";position:absolute;inset:0;border-radius:50%;
  border:2.5px solid var(--card-ico-bg);
  pointer-events:none;
  animation:ico-ring 2.2s cubic-bezier(.3,0,.5,1) infinite;
  animation-delay:var(--ico-delay,0s);
}
.scard-btn .phone-ico::after{animation-delay:calc(var(--ico-delay,0s) + 1.1s)}
@keyframes ico-ring{
  0%      {transform:scale(1);opacity:1}
  75%,100%{transform:scale(1.62);opacity:0}
}

/* handset rocks only in the last third of the cycle, so it reads as a phone
   actually ringing rather than a permanent wobble */
.scard-btn .phone-ico svg{
  animation:ico-rock 2.2s ease-in-out infinite;
  animation-delay:var(--ico-delay,0s);
}
@keyframes ico-rock{
  0%,50%,100%{transform:rotate(0) scale(1)}
  56%{transform:rotate(-15deg) scale(1.12)}
  63%{transform:rotate(13deg) scale(1.12)}
  70%{transform:rotate(-10deg) scale(1.08)}
  77%{transform:rotate(7deg) scale(1.05)}
  85%{transform:rotate(0) scale(1)}
}

/* Offset every card so the eight discs never pulse in lockstep — in unison it
   reads mechanical; staggered it reads alive. */
.scard:nth-child(1){--ico-delay:0s}
.scard:nth-child(2){--ico-delay:.14s}
.scard:nth-child(3){--ico-delay:.28s}
.scard:nth-child(4){--ico-delay:.42s}
.scard:nth-child(5){--ico-delay:.56s}
.scard:nth-child(6){--ico-delay:.70s}
.scard:nth-child(7){--ico-delay:.84s}
.scard:nth-child(8){--ico-delay:.98s}

@media (prefers-reduced-motion:reduce){
  .scard-btn::before,
  .scard-btn .phone-ico::before,
  .scard-btn .phone-ico::after,
  .scard-btn .phone-ico svg,
  .phone .phone-ico::before,
  .phone .phone-ico::after,
  .phone .phone-ico svg{animation:none}
  .scard-btn::before,
  .scard-btn::after,
  .scard-btn .phone-ico::before,
  .scard-btn .phone-ico::after,
  .phone .phone-ico::before,
  .phone .phone-ico::after{display:none}
}
/* Two lines, same idea as the CTA bar: what it gets you, then the number. The
   label is deliberately small — these buttons sit inside cards and the number
   has to stay the thing you read first. */
.scb-txt{
  display:flex;flex-direction:column;align-items:flex-start;
  text-align:left;line-height:1.12;
}
.scb-txt em{
  font-style:normal;
  font-family:var(--font-head);font-weight:800;
  font-size:9.5px;letter-spacing:.1em;text-transform:uppercase;
  color:#fff;margin-bottom:1px;
}
.scard-btn b{
  font-family:var(--font-proxima);font-weight:700;
  font-size:19px;letter-spacing:-.015em;color:#fff;
}
.scard-btn:hover{filter:brightness(.88);gap:15px}

/* Two crisp rings expanding off the button edge, launched half a cycle apart so
   one is always leaving as the other fades. Spread grows the ring outward while
   holding the 11px corner radius true — scaling a rounded rect would stretch its
   corners out of shape. */
.scard-btn::before,
.scard-btn::after{
  content:"";position:absolute;inset:0;
  border-radius:inherit;pointer-events:none;
  animation:btn-ring 3s cubic-bezier(.16,.7,.3,1) infinite;
  animation-delay:var(--ico-delay,0s);
}
.scard-btn::after{animation-delay:calc(var(--ico-delay,0s) + 1.5s)}
@keyframes btn-ring{
  0%      {box-shadow:0 0 0 0     var(--card-glow)}
  8%      {box-shadow:0 0 0 1.5px var(--card-glow)}
  72%,100%{box-shadow:0 0 0 16px  rgba(0,0,0,0)}
}

/* Every card shares the section grid's rows, so the photo, title, description,
   tick list and button each line up across a row by measurement. A row is only
   as tall as its own longest card, so a one-line title reserves nothing —
   which is what a min-height fallback could never do, since how many lines a
   title takes depends on the column width. */
@supports (grid-template-rows: subgrid){
  .scard{
    grid-row:span 6;
    display:grid;grid-template-rows:subgrid;row-gap:0;
  }
  .scard-body{
    grid-row:span 5;
    display:grid;grid-template-rows:subgrid;row-gap:0;
  }
  .scard-btn{margin:0 0 24px}
}

/* =========================================================
   CTA BAND
   =========================================================
   Flat brand red, nothing layered over it. All the richness is
   carried by the two controls, so the field stays clean. */
/* Both dark bands share one field definition rather than each carrying its own
   copy of four radial gradients — change the mix once and both follow. */
.ctab,.final{
  position:relative;overflow:hidden;
  background:#080D26;
}
.ctab{padding:62px 0 66px}
/* deep red right, deep blue left */
.cta::before,.ctab::before,.final::before{
  content:"";position:absolute;inset:-18%;z-index:0;
  background:
    radial-gradient(78% 96% at 86% 38%, rgba(152, 10, 22,.98), transparent 72%),
    radial-gradient(62% 78% at 70% 92%, rgba(124,  8, 18,.92), transparent 74%),
    radial-gradient(70% 92% at 10% 44%, rgba( 22, 44,158,.95), transparent 72%),
    radial-gradient(52% 66% at 26% 96%, rgba( 16, 32,120,.85), transparent 74%);
  filter:blur(64px);
  pointer-events:none;
}
.ctab-inner{
  position:relative;z-index:1;
  max-width:820px;margin:0 auto;text-align:center;
}

.ctab-pill{
  display:inline-flex;align-items:center;gap:9px;
  padding:8px 18px 8px 14px;border-radius:999px;
  background:rgba(255,255,255,.15);
  border:1px solid rgba(255,255,255,.3);
  font-family:var(--font-head);font-weight:800;
  font-size:11.5px;letter-spacing:.15em;text-transform:uppercase;color:#fff;
}
.ctab-dot{
  flex:none;width:8px;height:8px;border-radius:50%;background:var(--live);
  animation:ctab-ping 2.4s ease-out infinite;
}
@keyframes ctab-ping{
  0%  {box-shadow:0 0 0 0 var(--live-ring)}
  70% {box-shadow:0 0 0 9px rgba(43,217,124,0)}
  100%{box-shadow:0 0 0 0 rgba(43,217,124,0)}
}

.ctab h2{
  margin-top:24px;
  font-family:var(--font-proxima);font-weight:700;
  font-size:clamp(32px,4vw,56px);line-height:1.06;
  letter-spacing:-.028em;color:#fff;
}
.ctab-inner > p{
  margin:18px auto 0;max-width:52ch;
  font-size:16.5px;line-height:1.7;color:rgba(255,255,255,.87);
}

.ctab-actions{display:flex;justify-content:center;margin-top:38px}

/* One object, not two. Two filled boxes of different widths sitting next to
   each other never resolve — whatever you do to them they read as a pair that
   didn't fit. A single white bar split by a hairline reads as one considered
   control, and each half lights up in its own color on hover. */
.ctab-bar{
  display:inline-flex;align-items:stretch;
  border-radius:16px;
  overflow:hidden;                       /* clips both fills to the corners */
  box-shadow:0 20px 46px rgba(0,0,0,.3), 0 2px 6px rgba(0,0,0,.16);
}
.ctab-bar > *{
  display:inline-flex;align-items:center;gap:13px;
  height:74px;padding:0 32px;
  border:0;cursor:pointer;color:#fff;
  font-family:var(--font-head);font-weight:800;
  font-size:15px;letter-spacing:.09em;text-transform:uppercase;
  transition:background .26s ease,color .26s ease;
}
/* Both halves carry the same two-line label: a small caps line saying what the
   button gets you, and the thing you actually read underneath. */
.ctab-txt{
  display:flex;flex-direction:column;align-items:flex-start;gap:1px;
  text-align:left;
}
.ctab-txt em{
  font-style:normal;
  font-family:var(--font-head);font-weight:800;
  font-size:11.5px;letter-spacing:.1em;text-transform:uppercase;
  color:#fff;
}
.ctab-txt b{
  font-family:var(--font-proxima);font-weight:700;
  font-size:23px;letter-spacing:-.015em;text-transform:none;color:#fff;
  white-space:nowrap;
}

/* The whole mark moves as one: the sheet lifts and settles while the tick draws
   across it, both on the same 2.8s beat so they read as a single gesture. */
.ctab-book .ctab-ico svg{animation:ctab-doc 2.8s ease-in-out infinite}
@keyframes ctab-doc{
  0%,6%    {transform:translateY(0) rotate(0deg) scale(1)}
  20%      {transform:translateY(-2.5px) rotate(-4deg) scale(1.04)}
  38%,66%  {transform:translateY(0) rotate(0deg) scale(1)}
  80%      {transform:translateY(-1.5px) rotate(3deg) scale(1.02)}
  100%     {transform:translateY(0) rotate(0deg) scale(1)}
}

/* the tick draws across the sheet, holds, and clears — a job being signed off */
.ctab-tick{
  stroke-dasharray:1;stroke-dashoffset:1;
  animation:ctab-tick 2.8s ease-in-out infinite;
}
@keyframes ctab-tick{
  0%,8%    {stroke-dashoffset:1}
  32%,70%  {stroke-dashoffset:0}
  86%,100% {stroke-dashoffset:1}
}

/* ---- red half ---- */
.ctab-call{background:var(--red);padding-left:24px}
/* Header disc, stated outright rather than inherited. The glyph is drawn with
   fill="currentColor", and a CSS fill beats that presentation attribute, so it
   is set here too — leaving it to inherit through the red zone was rendering
   the phone white. */
.ctab-call .phone-ico{
  position:relative;
  flex:none;
  background:var(--tint-red-sm);
  color:var(--red);
}
.ctab-call .phone-ico svg{fill:var(--red)}
/* Same ring-and-rock as the header disc and the service card buttons — the same
   keyframes, not a lookalike. The ring is white here because the disc sits on a
   solid red half, where a red ring would be invisible. */
.ctab-call .phone-ico::before,
.ctab-call .phone-ico::after{
  content:"";position:absolute;inset:0;border-radius:50%;
  border:2.5px solid rgba(255,255,255,.62);
  pointer-events:none;
  animation:ico-ring 2.2s cubic-bezier(.3,0,.5,1) infinite;
}
.ctab-call .phone-ico::after{animation-delay:1.1s}
.ctab-call .phone-ico svg{position:relative;animation:ico-rock 2.2s ease-in-out infinite}
@media (prefers-reduced-motion:reduce){
  .ctab-call .phone-ico::before,.ctab-call .phone-ico::after{display:none}
  .ctab-call .phone-ico svg{animation:none}
}
.ctab-call:hover{background:#C9151C}

/* ---- navy half ---- */
/* no divider needed: the color change is the seam */
.ctab-book{background:var(--navy);padding-left:13px}
/* mirrors the call side's disc — a light tint of its own half's color, so the
   two icons read as a matched pair rather than one being an afterthought */
.ctab-ico{
  flex:none;display:grid;place-items:center;
  width:42px;height:42px;border-radius:50%;
  background:var(--tint);color:var(--navy);
}
.ctab-ico svg{width:22px;height:22px}
/* Direct child only. `.ctab-book svg` also matched the calendar nested inside
   .ctab-ico, so hovering slid the icon out of its disc along with the arrow. */
.ctab-book > svg{transition:transform .3s cubic-bezier(.22,1,.36,1)}
.ctab-book:hover{background:#0A164C}
.ctab-book:hover > svg{transform:translateX(4px)}

@media (prefers-reduced-motion:reduce){
  .ctab-dot,.eyebrow::before{animation:none}
  .ctab-tick{animation:none;stroke-dashoffset:0}
  .ctab-book .ctab-ico svg{animation:none}
}

@media (max-width:760px){
  /* stacked layout has no right-hand photo to avoid, so fade downward instead */
  .hero-bg{
    width:100%;
    -webkit-mask-image:linear-gradient(180deg,#000 0%,#000 48%,transparent 86%);
            mask-image:linear-gradient(180deg,#000 0%,#000 48%,transparent 86%);
  }
  .hero-bg::after{background:linear-gradient(180deg,#fff 0%,rgba(255,255,255,0) 30%)}
  .ctab{padding:46px 0 50px}
  .ctab h2{margin-top:20px}
  .ctab-actions{margin-top:30px}
  /* stacks into one column but stays a single object */
  .ctab-bar{flex-direction:column;width:100%;max-width:340px;border-radius:14px}
  .ctab-bar > *{height:64px;padding:0 22px;justify-content:center}
  .ctab-call{gap:11px;padding-left:16px}
  .ctab-book{padding-left:11px}
  .ctab-ico{width:34px;height:34px}
  .ctab-call b,
  .ctab-book > span{font-size:20px}
  .ctab-bar > *{font-size:13.5px}
}

/* =========================================================
   FLOATING CALL
   =========================================================
   Reuses .scard-btn for everything visual. The card variants get their accent
   vars from .scard, which this isn't inside, so the four are declared here —
   without them var(--card-ink) resolves to nothing and the fill disappears. */
.scard-btn.fab-call{
  --card-ink:var(--red);
  --card-ico-bg:var(--tint-red-sm);
  --card-ico:var(--red);
  --card-glow:rgba(237,28,36,.5);

  position:fixed;z-index:150;
  right:24px;bottom:24px;
  margin:0;                     /* .scard-btn's auto margin is for card layout */
  /* bigger than the card buttons it borrows from — this one is competing with a
     whole page rather than sitting in a 300px card */
  height:70px;padding:0 28px 0 12px;gap:14px;border-radius:13px;
  box-shadow:0 18px 42px rgba(14,30,99,.3);
}
.scard-btn.fab-call .phone-ico{width:44px;height:44px}
.scard-btn.fab-call b{font-size:22px}
/* drops out of the way when the mobile drawer is open, which sits under it */
body.nav-open .fab-call{opacity:0;pointer-events:none}
/* the footer has the same number and an estimate button of its own, so the
   floating pair gets out of the way rather than sitting on top of the credit */
body.at-footer .fab-call,
body.at-footer .fab-bar{opacity:0;pointer-events:none;transition:opacity .3s ease}
.scard-btn.fab-call{transition:opacity .25s ease,filter .28s ease,gap .28s cubic-bezier(.22,1,.36,1)}

@media (max-width:760px){
  /* two classes so the responsive .scard-btn block later in the file, which is
     only one class, can't reintroduce a bottom margin and lift it off the edge */
  .scard-btn.fab-call{
    right:14px;bottom:14px;
    height:54px;padding:0 18px 0 8px;
    margin:0;
  }
  .scard-btn.fab-call b{font-size:17.5px}
  /* icon keeps pulsing; the button's own corner rings come off */
  .fab-call::before,
  .fab-call::after{display:none}
}

/* ---------------- mobile action bar ----------------
   Ported from the Infinity Rug Care dock at the client's request, rebuilt in
   ABC's navy and red.

   The tray is deep navy glass rather than the flat white panel it was: two
   coloured segments on white read as two loose buttons, whereas a dark dock
   with lit tiles inside it reads as one control that belongs to the phone.

   Structure, outside in: blurred tray, gradient tile, diagonal glass sheen,
   inner hairline, squircle icon orb, caption over value. */
.fab-bar{
  display:none;
  position:fixed;z-index:150;
  left:14px;right:14px;bottom:14px;
  padding:7px;gap:8px;
  border-radius:22px;
  background:linear-gradient(135deg,
    rgba(9,17,52,.88)  0%,
    rgba(16,30,84,.88) 50%,
    rgba(6,12,40,.92)  100%);
  backdrop-filter:blur(24px) saturate(180%);
  -webkit-backdrop-filter:blur(24px) saturate(180%);
  box-shadow:
    0 1px 0 rgba(255,255,255,.10) inset,
    0 -1px 0 rgba(0,0,0,.25) inset,
    0 0 0 1px rgba(255,255,255,.04),
    0 22px 44px -14px rgba(0,0,0,.55),
    0 12px 28px -10px rgba(14,30,99,.45);
  /* clear of the iPhone home indicator */
  margin-bottom:env(safe-area-inset-bottom);
}

.fab-seg{
  flex:1 1 0;min-width:0;position:relative;
  display:flex;align-items:center;gap:9px;
  padding:10px 11px;min-height:58px;
  border:0;border-radius:16px;cursor:pointer;
  text-align:left;color:#fff;
  transition:transform .28s cubic-bezier(.2,.7,.3,1.35),filter .2s ease;
  will-change:transform;
}
/* the number needs more room than the two-word booking label */
.fab-seg--call{
  flex:1 1 56%;
  background:linear-gradient(135deg,#F2353D 0%,#ED1C24 55%,#B8121A 100%);
  box-shadow:
    0 1px 0 rgba(255,255,255,.20) inset,
    0 -1px 0 rgba(0,0,0,.22) inset,
    0 6px 14px -6px rgba(237,28,36,.55);
}
/* WhatsApp green, the brand's own, so the tile is recognised before it is
   read. Deliberately not navy: against the dark tray a navy tile sinks into
   the glass, and this is the one control on the dock that is not a phone call. */
.fab-seg--wa{
  flex:1 1 44%;
  background:linear-gradient(135deg,#2CDB78 0%,#22C668 55%,#1AAA5A 100%);
  box-shadow:
    0 1px 0 rgba(255,255,255,.22) inset,
    0 -1px 0 rgba(0,0,0,.18) inset,
    0 6px 14px -6px rgba(37,211,102,.55);
}
.fab-seg--wa:hover{
  box-shadow:
    inset 0 0 0 1px rgba(255,255,255,.34),
    0 2px 4px rgba(14,30,99,.07),
    0 26px 48px -22px rgba(37,211,102,.45);
}
/* the live "we are here" dot, the one detail that makes it read as a chat
   channel rather than another button */
.fab-seg--wa .fab-ico::after{
  content:"";position:absolute;top:-2px;right:-2px;
  width:10px;height:10px;border-radius:50%;
  background:radial-gradient(circle at 35% 30%,#9EF79C,#22C55E 70%);
  border:2px solid #1AAA5A;
  animation:fab-wa-pulse 2s ease-out infinite;
}
@keyframes fab-wa-pulse{
  0%  {box-shadow:0 0 0 0 rgba(155,247,156,.7)}
  70% {box-shadow:0 0 0 8px rgba(155,247,156,0)}
  100%{box-shadow:0 0 0 0 rgba(155,247,156,0)}
}
@media (prefers-reduced-motion:reduce){
  .fab-seg--wa .fab-ico::after{animation:none}
}

/* diagonal sheen across each tile, and a hairline inside its own radius */
.fab-seg::before{
  content:"";position:absolute;inset:0;border-radius:inherit;z-index:0;
  background:linear-gradient(135deg,
    rgba(255,255,255,.20) 0%,
    rgba(255,255,255,.06) 32%,
    transparent 55%);
  pointer-events:none;
}
.fab-seg::after{
  content:"";position:absolute;inset:0;border-radius:inherit;z-index:1;
  border:1px solid rgba(255,255,255,.10);pointer-events:none;
}
.fab-seg:active{transform:scale(.955);filter:brightness(.94)}

/* the icon orb: a squircle, lit from the top left.

   It was a circle carrying two expanding rings. The rings are gone with it —
   they were written for a circle, and an earlier rounded-square version of
   this made them expand as a square outline round the icon, which is the
   thing that looked broken. The reference has no ring here either. */
.fab-ico{
  position:relative;z-index:2;flex:none;
  width:34px;height:34px;border-radius:12px;
  display:grid;place-items:center;
  background:linear-gradient(150deg,
    rgba(255,255,255,.32) 0%,
    rgba(255,255,255,.10) 60%,
    rgba(255,255,255,.04) 100%);
  box-shadow:
    0 1px 0 rgba(255,255,255,.5) inset,
    0 -1px 0 rgba(0,0,0,.18) inset,
    0 4px 10px -3px rgba(0,0,0,.35),
    0 0 0 .5px rgba(255,255,255,.08);
}
.fab-ico svg{width:18px;height:18px;display:block;
  filter:drop-shadow(0 1px 0 rgba(0,0,0,.3))}

.fab-txt{position:relative;z-index:2;
  display:flex;flex-direction:column;line-height:1.05;min-width:0}
.fab-txt em{
  font-style:normal;
  font-family:var(--font-head);font-weight:800;
  font-size:10px;letter-spacing:.11em;text-transform:uppercase;
  color:rgba(255,255,255,.78);
  margin:0 0 2px;white-space:nowrap;
}
.fab-txt b{
  font-family:var(--font-proxima);font-weight:800;
  font-size:clamp(13px,3.5vw,16px);line-height:1.15;letter-spacing:-.015em;
  color:#fff;white-space:nowrap;
  text-shadow:0 1px 0 rgba(0,0,0,.22);
}

@media (prefers-reduced-motion:reduce){
  .fab-seg{transition:none}
}

@media (max-width:820px){
  .fab-bar{display:flex}
  .scard-btn.fab-call{display:none}   /* the pill gives way to the bar */
  /* No bottom padding. It was here so the fixed bar could not cover the last
     content, but the bar fades out once the footer scrolls in (body.at-footer),
     so the only thing the padding ever did was leave a blank strip under the
     credit line. */
  body.nav-open .fab-bar{opacity:0;pointer-events:none;transition:opacity .25s ease}
}
/* Small phones scale the dock down rather than dropping the caption. The
   caption was hidden here before, which left two unlabelled numbers; the
   reference keeps it and shrinks it, and it still fits at 360px. */
@media (max-width:380px){
  .fab-bar{left:8px;right:8px;bottom:8px;padding:5px;gap:5px;border-radius:18px}
  .fab-seg{padding:9px;gap:7px;border-radius:13px;min-height:52px}
  .fab-ico{width:30px;height:30px;border-radius:10px}
  .fab-ico svg{width:16px;height:16px}
  .fab-txt em{font-size:8.5px;letter-spacing:.085em;margin-bottom:1px}
}

/* =========================================================
   HOW IT WORKS
   =========================================================
   Kicker, heading, lead, four cards, one action. The cards borrow the service
   card system — the same alternating navy/red tints and the same --card-* vars —
   so this reads as part of the page rather than a new component.
   Light, because the CTA band directly above is the dark gradient. */
.how{background:#fff;padding:80px 0 88px}

.how-grid{display:grid;grid-template-columns:repeat(4,1fr);gap:20px}
.how-card{
  --card-bg:var(--tint);
  --card-ink:var(--navy);
  display:flex;flex-direction:column;
  padding:26px 24px 28px;
  background:var(--card-bg);border-radius:18px;
  transition:transform .38s cubic-bezier(.22,1,.36,1),box-shadow .38s ease;
}
.how-card:nth-child(even){
  --card-bg:var(--tint-red-sm);
  --card-ink:var(--red);
}
.how-card:hover{transform:translateY(-6px);box-shadow:0 26px 52px rgba(14,30,99,.16)}

.how-ico{
  width:52px;height:52px;border-radius:15px;margin-bottom:16px;
  display:grid;place-items:center;
  background:var(--card-ink);color:#fff;
  transition:transform .34s cubic-bezier(.22,1,.36,1);
}
.how-ico svg{width:26px;height:26px;display:block;overflow:visible}
.how-card:hover .how-ico{transform:translateY(-2px) scale(1.05)}

/* Each icon animates what its step does. Durations differ on purpose — four
   identical loops firing together reads mechanical. */

/* 01 — a date gets marked */
.hi-drop{animation:hi-drop 3s cubic-bezier(.34,1.56,.64,1) infinite}
@keyframes hi-drop{
  0%,8%   {transform:translateY(-7px);opacity:0}
  26%,64% {transform:translateY(0);opacity:1}
  84%,100%{transform:translateY(0);opacity:0}
}

/* 02 — the camera travels down between the flue walls */
.hi-scope{animation:hi-scope 3.2s cubic-bezier(.45,0,.55,1) infinite}
@keyframes hi-scope{
  0%      {transform:translateY(-1px);opacity:0}
  14%,78% {opacity:1}
  100%    {transform:translateY(9px);opacity:0}
}

/* 03 — the quote writes itself, line after line. pathLength:1 normalises the
   dash to each line's own length, so all three draw at the same rate. */
.hi-line{stroke-dasharray:1;stroke-dashoffset:1;animation:hi-write 3.4s ease-in-out infinite}
@keyframes hi-write{
  0%,6%   {stroke-dashoffset:1}
  34%,74% {stroke-dashoffset:0}
  94%,100%{stroke-dashoffset:1}
}

/* 04 — the certificate is signed off, then the seal rings out */
.hi-tick{stroke-dasharray:1;stroke-dashoffset:1;animation:hi-tick 3s ease-in-out infinite}
@keyframes hi-tick{
  0%,14%  {stroke-dashoffset:1}
  46%,78% {stroke-dashoffset:0}
  95%,100%{stroke-dashoffset:1}
}
.hi-ring{transform-origin:12px 12px;opacity:0;animation:hi-seal 3s ease-out infinite}
@keyframes hi-seal{
  0%,42%  {transform:scale(.62);opacity:0}
  56%     {transform:scale(1);opacity:.75}
  86%,100%{transform:scale(1.25);opacity:0}
}

@media (prefers-reduced-motion:reduce){
  .hi-drop,.hi-scope,.hi-line,.hi-tick,.hi-ring{animation:none}
  .hi-drop,.hi-scope{opacity:1;transform:none}
  .hi-line,.hi-tick{stroke-dashoffset:0}
  .hi-ring{opacity:0}
}

.how-card h3{
  font-family:var(--font-head);font-weight:700;
  font-size:20px;line-height:1.22;
  color:var(--ink);letter-spacing:-.02em;
}
.how-card p{
  margin:9px 0 0;
  font-size:14.2px;line-height:1.62;color:var(--ink-body);
}

.how-cta{display:flex;justify-content:center;margin-top:36px}

@media (max-width:1040px){
  .how-grid{grid-template-columns:repeat(2,1fr)}
}
@media (max-width:600px){
  .how{padding:56px 0 62px}
  .how-grid{grid-template-columns:1fr;gap:14px}
  .how-card{padding:22px 20px 24px}
  .how-ico{width:46px;height:46px;border-radius:13px;margin-bottom:13px}
  .how-ico svg{width:23px;height:23px}
  .how-cta{margin-top:28px}
  .how-cta .btn{width:100%}
}

/* =========================================================
   TESTIMONIALS
   =========================================================
   Two rows travelling in opposite directions. The counter-motion is the point:
   one row alone reads as a ticker, two against each other read as a wall of
   people, and the eye can rest on either without the section feeling static. */
.says{background:#F4F5F8;padding:80px 0 90px;overflow:hidden}

.says-row{
  overflow:hidden;
  /* overflow:hidden clips on BOTH axes, so the hover lift and its shadow were
     being sliced off at the row's edge. The padding gives them somewhere to go;
     the negative margin below pulls the rows back to the spacing they'd have
     had without it. */
  padding:26px 0;
  /* cards dissolve at both edges instead of being chopped by the viewport */
  -webkit-mask-image:linear-gradient(90deg,transparent,#000 7%,#000 93%,transparent);
          mask-image:linear-gradient(90deg,transparent,#000 7%,#000 93%,transparent);
}
.says-row + .says-row{margin-top:-30px}
/* the section's own padding absorbs the rows' new top/bottom padding */
.says{padding-top:56px;padding-bottom:66px}

.says-track{
  display:flex;width:max-content;
  animation:says-left 54s linear infinite;
}
.says-track--rev{animation:says-right 54s linear infinite}
.says-row:hover .says-track{animation-play-state:paused}

/* The gap lives in the card's own margin, not in a flex `gap`. With `gap` the
   track is 16 cards + 15 gutters, so shifting 50% lands half a gutter out and
   the loop visibly jumps. Margins make each unit card+gutter, and half of
   sixteen units is exactly eight — a seamless reset. */
@keyframes says-left{
  from{transform:translate3d(0,0,0)}
  to  {transform:translate3d(-50%,0,0)}
}
@keyframes says-right{
  from{transform:translate3d(-50%,0,0)}
  to  {transform:translate3d(0,0,0)}
}

.says-card{
  position:relative;                /* anchors the watermark */
  flex:none;margin:0 16px 0 0;
  width:clamp(304px,26vw,392px);
  display:flex;flex-direction:column;
  padding:26px 26px 24px;
  background:#fff;border-radius:0;
  /* Brand gradient border, red into navy on the diagonal. border-image is only
     usable here because the cards are square now — it ignores border-radius, so
     on a rounded card the gradient would square the corners off. The border must
     be `transparent` first: border-image paints over the color, and a colored
     fallback would show through in anything that doesn't support it.
     A tight shadow only — the wide 40px ambient one had to go, because sixteen
     of them in a row overlapped into a haze that read as a band behind the row. */
  border:1.5px solid transparent;
  border-image:linear-gradient(135deg,var(--red) 0%,#8E1230 52%,var(--navy) 100%) 1;
  box-shadow:0 1px 3px rgba(14,30,99,.05);
  transition:transform .4s cubic-bezier(.22,1,.36,1),box-shadow .4s ease;
}
/* only the hovered card gets a real shadow, so there's never more than one */
.says-card:hover{
  transform:translateY(-5px);
  box-shadow:0 14px 32px rgba(14,30,99,.13);
}

/* logo watermark, top-right — the stars occupy top-left, so the two never meet.
   Kept in brand color rather than greyscaled: at 12% the navy and red still
   read as the mark, where grey would just look like a smudge. */
.says-mark{
  position:absolute;top:16px;right:18px;
  width:54px;height:auto;
  opacity:.12;pointer-events:none;user-select:none;
}
.says-stars{display:flex;gap:3px;color:var(--red);margin-bottom:15px}
.says-stars svg{display:block}

.says-card blockquote{
  margin:0 0 20px;
  font-size:15.4px;line-height:1.68;color:var(--ink);
}

.says-by{
  display:flex;align-items:center;gap:13px;
  margin-top:auto;padding-top:4px;
}
/* initials rather than stock portraits — a fake face undermines a real quote */
.says-mono{
  flex:none;display:grid;place-items:center;
  width:44px;height:44px;border-radius:50%;
  background:var(--tint);color:var(--navy);
  font-family:var(--font-head);font-weight:800;
  font-size:14.5px;letter-spacing:.02em;
}
.says-card:nth-child(even) .says-mono{background:var(--tint-red-sm);color:var(--red)}
.says-who{display:flex;flex-direction:column;gap:2px;min-width:0}
.says-who b{
  font-family:var(--font-head);font-weight:700;
  font-size:15.5px;color:var(--ink);letter-spacing:-.01em;
}
.says-who em{
  font-style:normal;font-size:13px;line-height:1.35;color:var(--ink-muted);
}

@media (prefers-reduced-motion:reduce){
  .says-track,.says-track--rev{animation:none}
  .says-row{overflow-x:auto}
}

@media (max-width:600px){
  .says{padding:56px 0 62px}
  .says-card{width:clamp(262px,84vw,310px);padding:22px 22px 20px;margin:0 12px 0 0}
  .says-row{padding:18px 0}
  .says-row + .says-row{margin-top:-22px}
  .says-card blockquote{font-size:14.6px;margin-bottom:17px}
  .says-mono{width:40px;height:40px;font-size:13.5px}
}

/* =========================================================
   FINAL CTA
   =========================================================
   Flat navy, not the blurred gradient. The page already has two gradient bands;
   a third would blur into them at the point where the closing argument needs to
   land hardest. Solid navy reads as the end of the page. */
.final{padding:82px 0 86px;text-align:center}
.final-inner{position:relative;z-index:1;max-width:780px;margin:0 auto}

.final-pill{
  display:inline-flex;align-items:center;gap:9px;
  padding:8px 18px 8px 14px;border-radius:999px;
  background:rgba(255,255,255,.12);border:1px solid rgba(255,255,255,.26);
  font-family:var(--font-head);font-weight:800;
  font-size:11.5px;letter-spacing:.14em;text-transform:uppercase;color:#fff;
}
.final h2{
  margin-top:24px;
  font-family:var(--font-head);font-weight:700;
  font-size:clamp(30px,3.9vw,54px);line-height:1.07;
  letter-spacing:-.03em;color:#fff;
}
.final-inner > p{
  margin:18px auto 0;max-width:56ch;
  font-size:16.5px;line-height:1.7;color:rgba(255,255,255,.8);
}

.final-actions{display:flex;justify-content:center;margin-top:36px}

/* The three proof points read as part of the button block, not as a separate
   line under it. They were centred flex items of 169, 179 and 116px inside a
   716px row, which left about 96px of slack at each end and no rhythm between
   them; three equal columns give them even spacing at any width. The gap was
   34px, which is why the client saw them as detached. */
.final-trust{
  display:grid;grid-template-columns:repeat(3,1fr);
  justify-items:center;align-items:start;
  gap:10px 16px;
  max-width:716px;margin:18px auto 0;
}
.final-trust li{
  position:relative;padding-left:20px;
  font-size:14px;color:rgba(255,255,255,.76);
}
.final-trust li::before{
  content:"";position:absolute;left:0;top:6px;
  width:8px;height:5px;
  border-left:2px solid #FF6E74;border-bottom:2px solid #FF6E74;
  transform:rotate(-45deg);
}

/* =========================================================
   FOOTER
   =========================================================
   White, so every color in here had to be re-derived: the navy-on-dark set was
   built for a dark ground and would be unreadable. Headings take brand red, body
   copy the standard ink, and the logo no longer needs a plate to sit on. */
.site-footer{background:#fff;color:var(--ink);padding:66px 0 0;border-top:1px solid var(--line)}
.foot-grid{
  display:grid;grid-template-columns:1.5fr 1fr 1fr 1.25fr;
  gap:clamp(28px,3.4vw,54px);
}
.foot-grid > *{min-width:0}

/* no plate, no background — on a white footer the artwork stands on its own */
.foot-logo{display:inline-block;background:none;padding:0;border-radius:0}
.foot-logo img{display:block;height:112px;width:auto}
.foot-brand p{
  margin:18px 0 0;max-width:38ch;
  font-size:14.6px;line-height:1.72;color:var(--ink-body);
}
.foot-phone{
  display:inline-block;margin-top:16px;
  font-family:var(--font-proxima);font-weight:700;
  font-size:24px;letter-spacing:-.02em;color:var(--navy);
  transition:color .2s ease;
}
.foot-phone:hover{color:var(--red)}

.foot-col h2{
  margin-bottom:16px;
  font-family:var(--font-head);font-weight:800;
  font-size:12px;letter-spacing:.15em;text-transform:uppercase;
  color:var(--red);
}
.foot-col ul{display:flex;flex-direction:column;gap:11px}
.foot-col li{font-size:14.4px;line-height:1.45;color:var(--ink-body)}
.foot-col a{color:var(--ink-body);transition:color .18s ease}
.foot-col a:hover{color:var(--red)}
/* hugs its label instead of filling the column — .btn is inline-flex, so width
   auto is enough here; no self-alignment needed */
.foot-cta{margin-top:22px;width:auto;height:52px;font-size:14.5px}

.foot-base{
  display:flex;flex-wrap:wrap;justify-content:space-between;gap:10px 24px;
  margin-top:8px;
  /* padding-block only: `padding:22px 0 26px` here reset the left/right values
     that .shell sets, so the row lost its gutters and sat flush to the viewport */
  padding-top:2px;padding-bottom:3px;
  border-top:1px solid var(--line);
}
/* margin:0 — <p> keeps its UA 1em top and bottom margin (the reset covers ul, ol,
   figure and blockquote but not p). In a flex container those margins do not
   collapse, so the two lines were sitting 13px + gap + 13px apart and the row was
   114px tall for 45px of text. */
.foot-base p{margin:0;font-size:13.2px;color:var(--ink-muted)}
.foot-credit a{
  font-family:var(--font-head);font-weight:900;
  font-size:14.5px;letter-spacing:-.005em;
  color:var(--red);transition:color .18s ease;
}
.foot-credit a:hover{color:var(--navy)}
/* Double beat then a rest, rather than one even pulse — that rhythm is what
   reads as a heartbeat instead of a throbbing icon. */
.foot-heart{
  display:inline-block;vertical-align:-.16em;margin:0 1px;
  color:var(--red);transform-origin:center;
  animation:heart-beat 1.7s ease-in-out infinite;
}
.foot-heart svg{display:block;width:14px;height:14px}
@keyframes heart-beat{
  0%,100%{transform:scale(1)}
  12%    {transform:scale(1.26)}
  24%    {transform:scale(1)}
  36%    {transform:scale(1.16)}
  50%    {transform:scale(1)}
}
@media (prefers-reduced-motion:reduce){
  .foot-heart{animation:none}
}

@media (max-width:1040px){
  .foot-grid{grid-template-columns:1fr 1fr}
  .foot-brand{grid-column:1 / -1}
}
@media (max-width:640px){
  .final{padding:58px 0 62px}
  .final-actions{margin-top:28px}
  /* Was wrapping one item onto the first line and two onto the second, which
     looks like a layout error rather than a list. One per line, each centred as a
     unit so the ticks stay with their text. */
  .final-trust{
    grid-template-columns:1fr;justify-items:start;
    width:max-content;margin-inline:auto;
    flex-direction:column;align-items:center;
    gap:11px;margin-top:26px;
  }
  .final-trust li{font-size:14.5px}
  .site-footer{padding-top:48px}
  .foot-grid{grid-template-columns:1fr;gap:30px}
  /* space-between is for the desktop row, where it pushes the copyright and the
     credit to opposite ends. Stacked, it has a vertical axis to act on instead —
     so any spare height in the container lands between the two lines, which is
     where the 36px gap came from. flex-start keeps them together; nowrap stops
     column-wrap inflating the container to begin with. */
  .foot-base{
    margin-top:10px;padding-top:4px;padding-bottom:6px;
    flex-direction:column;flex-wrap:nowrap;
    /* stacked, so align-items is the horizontal axis — center goes there, not on
       justify-content, which now controls the vertical stack */
    justify-content:flex-start;align-items:center;
    gap:5px;text-align:center;
  }
}

/* =========================================================
   PAGE HERO  (inner pages)
   =========================================================
   Centred title, sub, and a single inline action, over two soft brand shapes.
   The shapes are pure CSS ellipses rather than images — they scale with the
   viewport, cost nothing to load, and can't go out of date with the brand. */
.phero{
  position:relative;overflow:hidden;
  background:#fff;text-align:left;
  /* Matches the home hero's height. That hero is content-driven and its height
     tracks the viewport, because the technician image scales with it — so this
     uses a vw-based clamp rather than a fixed px, which would agree at one width
     and drift at every other. 38vw lands on the home hero at 1280 (484px). */
  display:flex;align-items:center;
  /* same rule as the home hero: at least the viewport less the header, so the
     next section never shows under it */
  min-height:calc(100vh - var(--header-h));
  min-height:calc(100dvh - var(--header-h));
  padding:40px 0;
}

/* photos behind, content in front */
.phero-bg{position:absolute;inset:0;z-index:0;pointer-events:none}
.phero-inner{position:relative;z-index:2;width:100%}

/* White veil over the stills — inside .phero-bg but above the slides, so their
   own opacity fade can't dilute it. Keeps the navy heading and red subtitle
   readable over the bright skies in shots 2 and 4 without dropping the photo's
   own strength any further. */
.phero-bg::after{
  /* z-index 3, not 1. A slide animates at z-index 2 while it fades in and
     drops to 1 the moment it lands, so at 1 this veil was BELOW the incoming
     image and above the settled one — the new photo arrived unveiled and then
     instantly gained the white wash a frame later. That was the white glow on
     every transition. 3 keeps the veil above both states, so it applies evenly
     and nothing changes at the handover.

     .phero-bg is itself positioned with z-index 0, so this is scoped to that
     stacking context and still sits under .phero-inner. */
  content:"";position:absolute;inset:0;z-index:3;
  /* Thin at the top where there is only sky, heavier lower down where the
     heading, subtitle and form sit — so the photo stays open in the areas with
     nothing over it, rather than being dimmed evenly to protect the middle. */
  background:linear-gradient(180deg,
    rgba(255,255,255,.14) 0%,
    rgba(255,255,255,.30) 42%,
    rgba(255,255,255,.46) 100%);
}

/* All four stills are cut to 2.60:1 — the hero's own ratio — so cover fills it
   with effectively no crop. object-position only matters above ~1630px, where the
   height cap stretches the hero past 2.6:1 and some sky starts to go. */
.phero-slide{position:absolute;inset:0;display:block;opacity:0;z-index:1}
.phero-slide img{width:100%;height:100%;object-fit:cover;object-position:50% 34%}

/* Four slides staggered 7s on a 28s loop, and 7s IS 25% of it — so the hold has
   to run to exactly 25% and the fade-out finish at 31%. Any earlier and there's a
   moment where neither slide is up and the page shows through; that gap was the
   white flash on the home hero. */
/* Every slide starts at opacity 0 and takes 6% of the cycle (1.68s) to reach full,
   so on load the hero sat white while the first one ramped up. Shifting the whole
   sequence back by exactly that 1.68s means slide 1 begins at its fully-visible
   keyframe. All four move by the same amount, so the 7s spacing — and the precise
   25%/31% crossover that stops a gap opening mid-loop — is preserved. */
.phero-slide{animation:phero-cycle 28s linear infinite}
.phero-slide:nth-child(1){animation-delay:-1.68s}
.phero-slide:nth-child(2){animation-delay:5.32s}
.phero-slide:nth-child(3){animation-delay:12.32s}
.phero-slide:nth-child(4){animation-delay:19.32s}
/* A crossfade of two stacked layers does NOT hold full coverage. Both ramp
   linearly, so halfway through they are at .5 each and the composite is
   .5 + .5x.5 = .75 — a quarter of whatever sits behind shows through. Behind
   here is .phero's white background, under a white veil, which is exactly the
   white flash on the hero.

   So only the incoming slide fades. The outgoing one holds at full opacity
   underneath until the incoming has completely covered it, then cuts to zero
   while hidden. z-index is animated alongside so the arriving slide is on top —
   DOM order handles 1→2→3→4, but not 4→1 when the loop wraps. */
@keyframes phero-cycle{
  0%           {opacity:0; z-index:2}
  6%           {opacity:1; z-index:2}
  6.001%       {opacity:1; z-index:1}
  31%          {opacity:1; z-index:1}
  31.001%,100% {opacity:0; z-index:1}
}
@media (prefers-reduced-motion:reduce){
  .phero-slide{animation:none}
  .phero-slide:nth-child(1){opacity:1}
}

.phero h1{
  font-family:var(--font-proxima);font-weight:900;
  font-size:clamp(34px,5vw,66px);line-height:1.05;
  letter-spacing:-.03em;color:var(--ink);
}
/* The title arrives a word at a time rather than as one block, and the words
   alternate navy and red so the line carries the brand instead of being a wall
   of one color. Split and wrapped by JS; without it the plain h1 still reads,
   which is what a crawler and a no-JS visitor get. */
.phero h1 .pw{
  display:inline-block;
  opacity:0;transform:translateY(26px);
  animation:pw-rise .72s cubic-bezier(.19,1,.22,1) forwards;
  animation-delay:calc(var(--w) * 90ms);
}
.phero h1 .pw--red{color:var(--red)}
@keyframes pw-rise{to{opacity:1;transform:none}}
/* the accent underline grows out from under the heading once the words land */
.phero h1::after{
  content:"";display:block;
  width:0;height:5px;border-radius:3px;margin-top:18px;
  background:linear-gradient(90deg,var(--red),#FF6A70);
  animation:pw-rule .9s cubic-bezier(.22,1,.36,1) .5s forwards;
}
@keyframes pw-rule{to{width:132px}}
@media (prefers-reduced-motion:reduce){
  .phero h1 .pw{animation:none;opacity:1;transform:none}
  .phero h1::after{animation:none;width:132px}
}

.phero-sub{
  margin:20px 0 0;max-width:56ch;
  font-family:var(--font-head);font-weight:600;
  /* a size up from the old 16-20px, and navy rather than red — at this length
     a full paragraph of brand red shouted over the heading above it */
  font-size:clamp(18px,1.85vw,24px);line-height:1.5;color:var(--navy);
}

/* No panel — the field and button sit straight on the background, exactly as they
   do in the home hero. */
.phero-form{
  position:relative;
  display:flex;flex-wrap:wrap;justify-content:flex-start;align-items:center;gap:12px;
  max-width:660px;margin:32px 0 0;
}
.phero-form .field{flex:1 1 300px;min-width:0}
.phero-form .field input{background:#fff}
.phero-form .btn{flex:none;height:62px}
.phero-form .field-msg{
  flex:1 1 100%;margin:0;text-align:left;padding-left:4px;
}
/* Collapse it while there's nothing to say. As a flex item with basis 100% it
   claimed a whole second row even when empty — that row plus the 12px gap is
   what made the bottom padding look thicker than the top. */
.phero-form .field-msg:empty{display:none}

/* ---- breadcrumbs ----
   Sits inside the hero above the title now, so it carries no band of its own:
   no background, no border, left-aligned with the rest of the content. */
/* ---- breadcrumbs ----
   No container. The pill went through glass, gradient rims and a nested chip, and
   every version drew more attention than a breadcrumb should — it is orientation,
   not a control. The hero copy is navy on a veiled photo and reads perfectly
   without a panel, so this is the same treatment: small caps, a hairline chevron,
   and the current page in red. */
.crumbs{margin-bottom:18px}
.crumbs ol{display:flex;flex-wrap:wrap;align-items:center;gap:10px}

.crumbs li{
  display:flex;align-items:center;gap:10px;
  font-family:var(--font-head);font-weight:700;
  font-size:12.5px;letter-spacing:.1em;text-transform:uppercase;
  color:var(--ink-body);
}
/* chevron hangs off the item before the divide, so it can never land inside the
   current page's own box */
.crumbs li:not(:last-child)::after{
  content:"";flex:none;
  width:5px;height:5px;
  border-top:1.6px solid rgba(14,30,99,.3);
  border-right:1.6px solid rgba(14,30,99,.3);
  transform:rotate(45deg);
}
.crumbs a{
  display:inline-flex;align-items:center;gap:8px;
  color:var(--navy);transition:color .18s ease;
}
.crumbs a svg{opacity:.8;transition:opacity .18s ease}
.crumbs a:hover{color:var(--red)}
.crumbs a:hover svg{opacity:1}
.crumbs li[aria-current]{color:var(--red)}

@media (max-width:640px){
  /* stacked layout sizes to its own content, as the home hero does on mobile */
  /* stacked layout sizes to its own content, as the home hero does on mobile */
  .phero{min-height:0;padding:44px 0 40px}
  .phero-form{margin-top:24px;padding:12px;gap:10px}
  .phero-form .field{flex:1 1 100%}
  .phero-form .btn{width:100%;height:58px}
}

/* ---- service page: the About layout's right column ----
   Photo over a "signs you need it" card. Sticky, so the estimate button stays
   reachable through a long read; static once the grid stacks. */
.svc-side{
  display:flex;flex-direction:column;gap:16px;
  position:sticky;top:calc(var(--header-h) + 20px);
}
.svc-shot{border-radius:18px;overflow:hidden;box-shadow:0 18px 44px rgba(9,16,48,.16)}
.svc-shot picture{display:contents}
.svc-shot img{display:block;width:100%;aspect-ratio:16/10;object-fit:cover}

.svc-card{padding:24px 24px 26px;border-radius:18px;background:var(--tint-red-sm)}
.svc-card h3{
  margin-bottom:14px;
  font-family:var(--font-head);font-weight:800;
  font-size:12px;letter-spacing:.14em;text-transform:uppercase;color:var(--red);
}
.svc-signs{display:flex;flex-direction:column}
.svc-signs li{
  position:relative;padding:9px 0 9px 21px;
  font-size:14.6px;line-height:1.45;color:var(--ink);
  border-top:1px solid rgba(237,28,36,.16);
}
.svc-signs li:first-child{border-top:0}
/* corner tick from two borders — lighter than an svg at this size */
.svc-signs li::before{
  content:"";position:absolute;left:1px;top:15px;
  width:8px;height:5px;
  border-left:2px solid var(--red);border-bottom:2px solid var(--red);
  transform:rotate(-45deg);
}

@media (max-width:960px){
  .svc-side{position:static}
}

/* =========================================================
   SERVICE PAGE — sub-service cards
   =========================================================
   The home-page .scard, minus the description and tick rows there is no data for.
   Those two rows are why the subgrid exists (it spans six), so this variant opts
   out of it and falls back to flex — otherwise the card reserves two empty rows
   and opens up a tall gap above the button. */
.services-grid--sub{grid-template-columns:repeat(3,1fr)}
.services-grid--sub .scard{
  grid-row:auto;
  display:flex;flex-direction:column;
}
.services-grid--sub .scard-body{
  grid-row:auto;
  display:flex;flex-direction:column;flex:1 1 auto;
}
.services-grid--sub .scard-btn{margin-top:auto}

/* The .scard checkerboard is hard-coded to 2,4,5,7 — the right sequence for the
   home page's FOUR columns. This grid is three wide, where that sequence puts
   cards 4 and 5 side by side in red. Alternation has to follow the column count,
   so each breakpoint sets its own:
     3 cols -> every other card
     2 cols -> pairs, so the diagonal still alternates
     1 col  -> every other card again
   Three classes plus a pseudo-class, so these outrank the base rule. */
.services-grid--sub .scard:nth-child(odd){
  --card-bg:var(--tint);
  --card-ink:var(--navy);
  --card-line:rgba(14,30,99,.13);
  --card-ico-bg:var(--tint);
  --card-ico:var(--navy);
  --card-glow:rgba(14,30,99,.5);
}
.services-grid--sub .scard:nth-child(even){
  --card-bg:var(--tint-red-sm);
  --card-ink:var(--red);
  --card-line:rgba(237,28,36,.18);
  --card-ico-bg:var(--tint-red-sm);
  --card-ico:var(--red);
  --card-glow:rgba(237,28,36,.55);
}

/* Icon tile inside the card body, How It Works shape. Takes the card's own ink so
   the row alternates navy and red. */
.scard-ico{
  display:grid;place-items:center;
  width:54px;height:54px;border-radius:16px;
  margin-bottom:16px;
  background:var(--card-ink);color:#fff;
  transition:transform .34s cubic-bezier(.22,1,.36,1);
}
.scard-ico svg{width:27px;height:27px;display:block;overflow:visible}
.scard:hover .scard-ico{transform:translateY(-3px) scale(1.05)}

.services-grid--sub .scard-body{padding:26px 24px 0}
.services-grid--sub .scard h3{font-size:19px;line-height:1.24}
.services-grid--sub .scard h3 a{color:inherit;transition:color .18s ease}
.services-grid--sub .scard:hover h3 a{color:var(--card-ink)}
.services-grid--sub .scard-body > p{
  margin:9px 0 20px;
  font-size:14.2px;line-height:1.62;color:var(--ink-body);
}

/* ---------------------------------------------------------------------------
   Icon motion library.
   Each behavior animates only the element marked class="m" in the glyph, never
   the whole icon — the point is that the moving part IS the thing described, so
   a camera travels down a flue and a certificate signs itself.
   Durations are deliberately uneven so a grid of them never ticks in lockstep.
   --------------------------------------------------------------------------- */
.scard-ico .m{transform-origin:12px 12px}

/* strokes writing themselves — inspections, repointing, certificates */
.ico--draw .m{
  stroke-dasharray:1;stroke-dashoffset:0;
  animation:m-draw 3.2s ease-in-out infinite;
}
@keyframes m-draw{
  0%,10%  {stroke-dashoffset:1}
  40%,74% {stroke-dashoffset:0}
  94%,100%{stroke-dashoffset:1}
}

/* something landing in place — a date marked, pellets fed, a tile set */
.ico--drop .m{animation:m-drop 3s cubic-bezier(.34,1.56,.64,1) infinite}
@keyframes m-drop{
  0%,8%   {transform:translateY(-6px);opacity:0}
  28%,66% {transform:translateY(0);opacity:1}
  86%,100%{transform:translateY(0);opacity:0}
}

/* travelling down the flue — camera, liner, insert */
.ico--travel .m{animation:m-travel 3.4s cubic-bezier(.45,0,.55,1) infinite}
@keyframes m-travel{
  0%      {transform:translateY(-2px);opacity:0}
  16%,74% {opacity:1}
  100%    {transform:translateY(8px);opacity:0}
}

/* a flame, never quite steady */
.ico--flicker .m{animation:m-flicker 2.4s ease-in-out infinite;transform-origin:12px 18px}
@keyframes m-flicker{
  0%,100%{transform:scaleY(1) scaleX(1)}
  30%    {transform:scaleY(1.12) scaleX(.94)}
  55%    {transform:scaleY(.96) scaleX(1.05)}
  78%    {transform:scaleY(1.07) scaleX(.97)}
}

/* a brush or airflow crossing — sweeping, draft */
.ico--sweep .m{animation:m-sweep 2.8s cubic-bezier(.45,0,.55,1) infinite}
@keyframes m-sweep{
  0%,100%{transform:translateX(-2.5px)}
  50%    {transform:translateX(2.5px)}
}

/* a sensor reading the room */
.ico--pulse .m{animation:m-pulse 2.6s ease-out infinite}
@keyframes m-pulse{
  0%      {transform:scale(.86);opacity:.55}
  55%     {transform:scale(1.04);opacity:1}
  100%    {transform:scale(1.14);opacity:0}
}

/* draft and smoke going up */
.ico--rise .m{animation:m-rise 3s ease-in-out infinite}
@keyframes m-rise{
  0%      {transform:translateY(4px);opacity:0}
  30%,70% {transform:translateY(0);opacity:1}
  100%    {transform:translateY(-4px);opacity:0}
}

/* a component seating onto the stack — crown, cap, cover, stove */
.ico--settle .m{animation:m-settle 3.2s cubic-bezier(.34,1.4,.64,1) infinite}
@keyframes m-settle{
  0%,6%   {transform:translateY(-4px);opacity:0}
  30%,72% {transform:translateY(0);opacity:1}
  92%,100%{transform:translateY(-4px);opacity:0}
}

/* a damper plate turning */
.ico--spin .m{animation:m-spin 4s cubic-bezier(.5,0,.5,1) infinite}
@keyframes m-spin{
  0%,20% {transform:rotate(0)}
  50%,70%{transform:rotate(-32deg)}
  100%   {transform:rotate(0)}
}

/* cement going in from the top */
.ico--pour .m{animation:m-pour 2.6s cubic-bezier(.45,0,.55,1) infinite}
@keyframes m-pour{
  0%     {transform:translateY(-3px);opacity:0}
  25%,60%{transform:translateY(0);opacity:1}
  100%   {transform:translateY(6px);opacity:0}
}

/* a magnifier hunting across the subject */
.ico--seek .m{animation:m-seek 3.6s ease-in-out infinite}
@keyframes m-seek{
  0%,100%{transform:translate(0,0)}
  35%    {transform:translate(-3px,-2px)}
  70%    {transform:translate(2px,1.5px)}
}

@media (prefers-reduced-motion:reduce){
  .scard-ico .m{animation:none!important;opacity:1;transform:none;stroke-dashoffset:0}
}

@media (max-width:600px){
  .scard-ico{width:48px;height:48px;border-radius:14px;margin-bottom:13px}
  .scard-ico svg{width:24px;height:24px}
}

@media (max-width:1000px){
  .services-grid--sub{grid-template-columns:repeat(2,1fr)}
  /* 1b 2r / 3r 4b / 5b 6r — pairs, so no two of a color ever touch */
  .services-grid--sub .scard:nth-child(4n+1),
  .services-grid--sub .scard:nth-child(4n+4){
    --card-bg:var(--tint);--card-ink:var(--navy);
    --card-line:rgba(14,30,99,.13);
    --card-ico-bg:var(--tint);--card-ico:var(--navy);
    --card-glow:rgba(14,30,99,.5);
  }
  .services-grid--sub .scard:nth-child(4n+2),
  .services-grid--sub .scard:nth-child(4n+3){
    --card-bg:var(--tint-red-sm);--card-ink:var(--red);
    --card-line:rgba(237,28,36,.18);
    --card-ico-bg:var(--tint-red-sm);--card-ico:var(--red);
    --card-glow:rgba(237,28,36,.55);
  }
}
@media (max-width:760px){
  /* the service name is the h1 directly beneath, so the tag alone carries enough */
  .kicker-svc{display:none}

  /* Desktop has empty space to the right of the copy for the photo to show
     through. On a phone the copy spans the full width, so it sits directly on the
     brickwork — the red subtitle especially. The veil goes much heavier here: the
     photo stays present as texture, but the type wins. */
  .phero-bg::after{
    background:linear-gradient(180deg,
      rgba(255,255,255,.62) 0%,
      rgba(255,255,255,.72) 55%,
      rgba(255,255,255,.8) 100%);
  }
  /* and a touch less contrast in the photo itself, so busy brick stops competing
     with the letterforms sitting on it */
  .phero-slide img{filter:saturate(.9) contrast(.94)}

  /* Current page comes off the trail — it is the h1 immediately below. Its
     chevron has to go too, or SERVICES is left with a dangling arrow pointing at
     nothing. */
  .crumbs li[aria-current]{display:none}
  .crumbs li:nth-last-child(2)::after{display:none}
}

@media (max-width:600px){
  .services-grid--sub{grid-template-columns:1fr}
  /* The 2-column pair pattern above still matches at this width, which produced
     blue, red, red, blue, blue, red down the page. One column needs plain
     alternation, so it is restated here rather than inherited. */
  .services-grid--sub .scard:nth-child(odd){
    --card-bg:var(--tint);--card-ink:var(--navy);
    --card-line:rgba(14,30,99,.13);
    --card-ico-bg:var(--tint);--card-ico:var(--navy);
    --card-glow:rgba(14,30,99,.5);
  }
  .services-grid--sub .scard:nth-child(even){
    --card-bg:var(--tint-red-sm);--card-ink:var(--red);
    --card-line:rgba(237,28,36,.18);
    --card-ico-bg:var(--tint-red-sm);--card-ico:var(--red);
    --card-glow:rgba(237,28,36,.55);
  }
}

/* =========================================================
   ESTIMATE MODAL
   ========================================================= */
.modal{position:fixed;inset:0;z-index:200;display:grid;place-items:center;padding:16px}
.modal[hidden]{display:none}
.modal-veil{
  position:absolute;inset:0;
  background:rgba(9,16,48,.62);
  backdrop-filter:blur(7px);-webkit-backdrop-filter:blur(7px);
  opacity:0;transition:opacity .3s ease;
}
/* Two panels: why bother on the left, the form on the right. The card no longer
   scrolls as a whole — only the form column does — so the reasons and the phone
   number stay on screen while someone works through the fields. */
.modal-card{
  position:relative;width:100%;max-width:920px;
  display:grid;grid-template-columns:0.78fr 1fr;
  max-height:calc(100vh - 40px);
  max-height:calc(100dvh - 40px);
  background:#fff;border-radius:22px;overflow:hidden;
  box-shadow:0 50px 110px rgba(9,16,48,.42);
  opacity:0;transform:translateY(20px) scale(.97);
  transition:opacity .38s ease,transform .45s cubic-bezier(.22,1,.36,1);
}

/* ---- left panel ---- */
.modal-aside{
  display:flex;flex-direction:column;
  min-height:0;overflow-y:auto;overscroll-behavior:contain;
  padding:30px 30px 26px;
  background:linear-gradient(158deg,#16296F 0%,var(--navy) 46%,#070F35 100%);
  color:#fff;
}
/* The real logo, not a white silhouette of it. It is a navy-and-red mark drawn
   for a white ground, so it gets its own white plate rather than being flattened
   with a filter — which threw away both brand colors and left a grey smudge. */
.modal-logo{
  /* content-box, so the height is the logo itself rather than the logo minus the
     plate padding — border-box was shrinking the mark to 34px */
  box-sizing:content-box;
  width:auto;height:46px;margin-bottom:18px;align-self:flex-start;
  padding:9px 14px;border-radius:12px;
  background:#fff;
  box-shadow:0 6px 18px -8px rgba(0,0,0,.5);
}
.modal-aside-h{
  font-family:var(--font-head);font-weight:900;
  font-size:clamp(24px,2.1vw,30px);line-height:1.14;letter-spacing:-.03em;color:#fff;
}
/* the one italic word, the way the reference does it — in brand red rather than
   another weight, so it reads as emphasis and not as a different typeface */
.modal-aside-h em{font-style:italic;color:var(--red)}
.modal-aside > p{
  margin-top:11px;
  font-size:13.5px;line-height:1.6;color:rgba(255,255,255,.72);
}

.modal-perks{display:flex;flex-direction:column;gap:11px;margin:20px 0 26px}
.modal-perks li{
  display:flex;align-items:flex-start;gap:12px;
  font-family:var(--font-head);font-weight:700;
  font-size:13.5px;line-height:1.38;color:#fff;
}
.modal-perks li > span{
  flex:none;display:grid;place-items:center;
  width:24px;height:24px;border-radius:7px;
  background:rgba(255,255,255,.09);
  box-shadow:inset 0 0 0 1px rgba(255,255,255,.14);
  color:var(--red);
}
.modal-perks svg{width:14px;height:14px}

/* pushed to the foot of the panel, above a hairline, so it reads as the
   alternative to the form rather than as another bullet */
.modal-call{
  display:flex;align-items:center;gap:14px;
  /* margin-top:auto only pushes this down when there is slack to push into —
     on a short panel the rule ended up sitting right under the last perk. The
     margin on the list guarantees a gap either way. */
  margin-top:auto;padding-top:22px;
  border-top:1px solid rgba(255,255,255,.14);
}
/* Solid brand red at rest, and running the same ring-and-rock the header phone
   and the service card buttons use — same keyframes, not a second animation that
   happens to look similar. */
.modal-call-ico{
  position:relative;
  flex:none;display:grid;place-items:center;
  width:40px;height:40px;border-radius:50%;
  background:var(--red);color:#fff;
  box-shadow:inset 0 0 0 1px rgba(255,255,255,.14);
}
.modal-call-ico::before,
.modal-call-ico::after{
  content:"";position:absolute;inset:0;border-radius:50%;
  border:2.5px solid rgba(237,28,36,.7);
  pointer-events:none;
  animation:ico-ring 2.2s cubic-bezier(.3,0,.5,1) infinite;
}
.modal-call-ico::after{animation-delay:1.1s}
.modal-call-ico svg{position:relative;animation:ico-rock 2.2s ease-in-out infinite}
.modal-call:hover .modal-call-ico{background:#C9161D}
@media (prefers-reduced-motion:reduce){
  .modal-call-ico::before,.modal-call-ico::after{display:none}
  .modal-call-ico svg{animation:none}
}
.modal-call em{
  display:block;font-style:normal;
  font-size:11.5px;font-weight:700;letter-spacing:.08em;text-transform:uppercase;
  color:rgba(255,255,255,.55);margin-bottom:3px;
}
.modal-call b{
  display:block;
  font-family:var(--font-head);font-weight:800;font-size:18px;
  letter-spacing:-.015em;color:#fff;
}

/* ---- right panel ---- */
.modal-main{
  position:relative;min-height:0;
  padding:30px 32px 26px;
  overflow-y:auto;overscroll-behavior:contain;
  display:flex;flex-direction:column;
}

/* ---- the step meter ---- */
.msteps{display:flex;align-items:center;gap:0;margin-top:16px;margin-bottom:20px}
.mstep{
  display:flex;align-items:center;gap:10px;flex:none;
  font-family:var(--font-head);font-weight:700;font-size:13.5px;
  color:var(--ink-muted);
}
.mstep b{
  display:grid;place-items:center;
  width:30px;height:30px;border-radius:50%;
  background:var(--tint);color:var(--ink-muted);
  font-size:14px;font-weight:800;
  transition:background .25s ease,color .25s ease,box-shadow .25s ease;
}
.mstep.is-on{color:var(--ink)}
.mstep.is-on b{background:var(--red);color:#fff;box-shadow:0 0 0 4px rgba(237,28,36,.16)}
.mstep.is-done b{background:var(--navy);color:#fff}
/* the rule between the two markers grows out of the first one */
.mstep:first-child::after{
  content:"";flex:1 1 auto;height:2px;min-width:26px;
  margin:0 14px;border-radius:2px;background:var(--line);
}
.msteps{justify-content:space-between}
.mstep:first-child{flex:1 1 auto}

/* ---- panes ---- */
/* The form is the flex column, but the panes sit inside it — so its gap fell
   between the panes, not between the rows within one. The rows and the button
   were left stacked with nothing between them. */
.mpane{display:none}
.mpane.is-on{
  display:flex;flex-direction:column;gap:17px;
  animation:mpane-in .32s cubic-bezier(.22,1,.36,1) both;
}
/* a little more air before the action than between two field rows */
.mpane .modal-send,
.mpane .modal-actions{margin-top:5px}
@keyframes mpane-in{from{opacity:0;transform:translateX(14px)}to{opacity:1;transform:none}}
@media (prefers-reduced-motion:reduce){.mpane.is-on{animation:none}}

.mf label i,.mf-label i{font-style:normal;color:var(--red)}
.mf-opt{
  font-weight:600;font-size:11.5px;letter-spacing:.04em;text-transform:uppercase;
  color:var(--ink-muted);margin-left:6px;
}

.modal-actions{display:flex;align-items:center;gap:14px;margin-top:4px}
.modal-actions .modal-send{flex:1 1 auto}
.modal-back{
  display:inline-flex;align-items:center;gap:7px;flex:none;
  padding:15px 18px;border-radius:12px;
  font-family:var(--font-head);font-weight:700;font-size:15px;
  color:var(--ink-muted);
  transition:color .2s ease,background .2s ease;
}
.modal-back:hover{color:var(--red);background:var(--tint)}

/* the send button carries a chevron on step one, so it needs to lay out as a row */
.modal-send{
  display:inline-flex;align-items:center;justify-content:center;gap:10px;
  width:100%;
}

.modal-note{
  display:flex;align-items:center;justify-content:center;gap:8px;
  margin-top:16px;
  /* one line, whatever the width — it wrapped to two on a phone and the second
     line hung under the shield looking like a stray sentence */
  white-space:nowrap;
  font-size:clamp(10.5px,2.9vw,13px);color:var(--ink-muted);
}
.modal-note svg{flex:none;color:var(--live)}

/* the success panel takes the whole right column */
.modal.is-done .modal-main{justify-content:center}
.modal.is-open .modal-veil{opacity:1}
.modal.is-open .modal-card{opacity:1;transform:none}



.modal-x{
  /* .modal-main is position:relative and comes after this in the DOM, so it
     painted over the button — the click was landing on .modal-head instead and
     nothing happened. Positioned siblings need an explicit order. */
  position:absolute;top:18px;right:18px;z-index:6;
  width:38px;height:38px;border-radius:50%;
  display:grid;place-items:center;
  color:var(--ink-muted);background:var(--tint);
  transition:background .18s ease,color .18s ease;
}
.modal-x:hover{background:var(--red);color:#fff}

.modal-head{margin-bottom:18px}
.modal-chip{
  display:inline-flex;align-items:center;gap:8px;
  padding:6px 13px;border-radius:50px;margin-bottom:11px;
  background:var(--tint);color:var(--navy);
  font-family:var(--font-head);font-weight:700;font-size:12.5px;letter-spacing:.02em;
}
.modal-head h2{
  font-family:var(--font-head);font-weight:900;
  font-size:27px;line-height:1.16;color:var(--ink);letter-spacing:-.015em;
}
.modal-head p{margin:7px 0 0;font-size:14.5px;line-height:1.5;color:var(--ink-body)}

.modal-form{display:flex;flex-direction:column;gap:13px}
.mf-row{display:grid;grid-template-columns:1fr 1fr;gap:14px}
.mf{display:flex;flex-direction:column;gap:6px;min-width:0}
.mf--ac{position:relative}
.ac-list{top:calc(100% - 18px);max-height:212px}
.mf label{
  font-family:var(--font-head);font-weight:700;
  font-size:12px;letter-spacing:.03em;text-transform:uppercase;color:var(--ink);
}
.mf input{
  width:100%;height:50px;padding:0 16px;
  font-family:var(--font-body);font-size:16px;color:var(--ink);
  background:#fff;border:1.5px solid var(--line);border-radius:10px;
  transition:border-color .18s ease,box-shadow .18s ease;
}
.mf input::placeholder{color:#AEB4CB}
.mf input:focus{outline:none;border-color:var(--navy);box-shadow:0 0 0 4px rgba(14,30,99,.10)}
.mf input.is-bad{border-color:var(--red);box-shadow:0 0 0 4px rgba(237,28,36,.12)}
.mf-err{font-size:12.5px;color:var(--red);font-weight:600;display:none}
.mf-err.show{display:block}

.modal-send{width:100%;height:54px}
/* the sizing lives with the two-panel rule above; this only zeroes the margin */
.modal-note{margin-top:16px;margin-bottom:0}

/* honeypot */
.hp{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}

/* success state */
.modal-done{text-align:center;padding:14px 0 6px}
.modal-done[hidden]{display:none}
.done-mark{
  display:grid;place-items:center;
  width:74px;height:74px;border-radius:50%;margin:0 auto 20px;
  background:#E8F7EE;color:#1E9E5A;
}
.modal-done h3{
  font-family:var(--font-head);font-weight:900;
  font-size:26px;color:var(--ink);
}
.modal-done p{margin:10px 0 24px;font-size:15.5px;line-height:1.55;color:var(--ink-body)}

/* Short viewports (laptops at scale, landscape phones): shed the description
   and tighten the rest so the dialog still fits without a scroller. The
   overflow-y:auto above stays as a last resort — clipping the submit button
   off-screen would be worse than a scrollbar. */
@media (max-height:720px){
  .modal-head p{display:none}
  .modal-chip{margin-bottom:9px}
  .modal-form{gap:11px}
  .mf input{height:46px}
  .modal-send{height:50px}
}

body.modal-open{overflow:hidden}

/* animated stat counters — Thrive's partner-badge row equivalent */
.counters{display:flex;align-items:flex-start;margin-top:38px;flex-wrap:wrap}
.counters li{padding-right:46px;margin-right:46px;border-right:1px solid var(--line)}
.counters li:last-child{padding-right:0;margin-right:0;border-right:0}

.counter-num{
  display:block;
  /* kit has no 750/800 cut (only 400/700/900), and CSS resolves anything
     over 700 straight to Black — so this is Bold nudged up with a hairline
     stroke to sit between the two. */
  font-family:var(--font-proxima);font-weight:700;
  -webkit-text-stroke:.4px currentColor;
  font-size:46px;line-height:1;letter-spacing:-.02em;
  color:var(--navy);
  font-variant-numeric:tabular-nums;   /* stops digits jittering while counting */
}
/* suffix set small and raised toward the cap height, so it reads as a mark
   on the figure rather than another full-size character */
.counter-num i{
  font-style:normal;color:var(--red);
  font-size:.54em;font-weight:800;
  display:inline-block;               /* transform without disturbing layout */
  transform:translateY(-.72em);
  margin-left:.06em;letter-spacing:0;
}
.counter-label{
  display:block;margin-top:9px;
  font-size:14px;line-height:1.3;color:var(--ink-body);
}

/* ---------------- hero visual ---------------- */
/* Single pre-composed transparent PNG (testimonial card + technician).
   Breaks out of the shell by --gutter so the subject runs to the screen edge,
   and stretches to the full row height so there's no dead gap above it. */
.hero-visual{
  position:relative;align-self:stretch;
  margin-right:calc(-1 * var(--gutter));
}
/* Slides are stacked in the same box and cross-faded. .hero-visual is
   align-self:stretch so it has a definite height for them to fill. */
.hero-slide{
  position:absolute;inset:0;
  opacity:0;transform:scale(1.025);
  transition:opacity .9s ease,transform 1.1s cubic-bezier(.22,1,.36,1);
  will-change:opacity,transform;
}
.hero-slide.is-active{opacity:1;transform:none}
.hero-img{
  display:block;
  width:100%;height:100%;
  object-fit:contain;
  object-position:right bottom;
}

/* =========================================================
   RESPONSIVE
   ========================================================= */
@media (max-width:1560px){
  :root{--header-h:98px}
  .brand img{height:78px}
}
@media (max-width:1380px){
  :root{--header-h:90px}
  .nav-link{font-size:16.5px}
  .phone-num{font-size:19px}
  .brand img{height:70px}
  .header-aside{padding-left:24px}
}
/* Squeeze the desktop nav rather than dropping to the drawer. A 1280 screen at
   110% browser zoom reports ~1164 CSS px, and at 125% ~1024 — both used to land
   under the old 1180 drawer breakpoint and flip the whole site to mobile. */
@media (max-width:1180px){
  :root{--header-h:84px;--nav-x:11px}
  .nav-link{font-size:15.5px}
  .nav{margin-left:calc(28px - var(--nav-x))}
  .phone-num{font-size:17.5px}
  .phone-ico{width:34px;height:34px}
  .brand img{height:62px}
  .header-aside{padding-left:16px;gap:10px}
  .icon-btn{display:none}
}

/* "INSTALLATIONS" is one unbreakable word — ramp the hero type down smoothly
   so it never outgrows the copy column at any width. */
@media (max-width:1560px){
  .hero-title{font-size:clamp(52px,5.1vw,80px);line-height:1.06;min-height:calc(clamp(52px,5.1vw,80px) * 2.2)}
  .eyebrow{font-size:clamp(21px,1.85vw,29px);line-height:1.24}
  .counter-num{font-size:clamp(34px,2.9vw,46px)}
  .counter-label{font-size:13px}
}

@media (max-width:1040px){
  .services-grid{grid-template-columns:repeat(2,1fr)}
  :root{--header-h:80px;--nav-x:16px}
  .burger{display:flex}
  .icon-btn{display:none}
  /* search stays — it is the fastest route to a town page on a phone, where the
     drawer means a lot of scrolling. Narrowed to sit beside the burger. */
  #searchBtn{display:grid;width:44px;height:36px;border-radius:18px}
  .brand img{height:62px}

  .brand{flex:none}
  .header-aside{flex:none}
  .nav{
    flex:none;display:block;
    position:fixed;top:var(--header-h);left:0;right:0;bottom:0;
    background:#fff;margin:0;padding:22px var(--pad) 40px;
    overflow-y:auto;
    /* No transition by default. The moment this query activates the browser
       would otherwise animate from no-transform to -100%, so the whole white
       drawer visibly slides off to the left on resize, zoom or first paint.
       JS opts the animation in on the first burger press. */
    transform:translateX(-100%);transition:none;
  }
  .nav-anim .nav{transition:transform .3s ease}
  .nav.is-open{transform:translateX(0)}
  .nav-list{flex-direction:column;align-items:stretch;justify-content:flex-start;gap:0}
  .nav-list > li:last-child{margin-right:0;border-bottom:0}
  .nav-list > li{border-bottom:1px solid var(--line)}
  /* rows get real padding and corners — at 2px the label sat hard against the
     edge, and the open row read as a raw red band rather than a control */
  .nav-link{
    width:100%;justify-content:space-between;
    padding:15px 14px;font-size:16px;border-radius:10px;
  }
  .has-drop[data-open="true"] > .nav-link{border-radius:10px 10px 0 0}

  .drop{
    position:static;min-width:0;opacity:1;visibility:visible;transform:none;
    box-shadow:none;border:0;border-radius:0;padding:0 0 12px;
    display:none;
  }
  .has-drop[data-open="true"] .drop{display:block}
  .drop-inner{grid-template-columns:1fr;gap:0}
  .drop-inner a{padding:11px 14px}

  /* mega menu collapses into the drawer as a plain stacked list */
  .has-drop--mega{position:relative}
  .drop--mega{left:auto;right:auto;top:auto;border-radius:0}
  .mega{display:block;padding:0;max-width:none}
  .mega-promo{display:none}
  /* The desktop rule is a four-column flow. In the drawer everything stacks, so
     the columns collapse to one and the rule between them goes with them. */
  .mega-cols{grid-template-columns:1fr;gap:0}
  /* the wrappers dissolve so the eight groups stack as one list */
  .mega-col{display:contents}
  .mega-col::before{display:none}
  /* indent the whole collapsed panel so groups line up under the row label
     instead of starting at the drawer edge */
  .drop--mega{padding:4px 0 10px}
  .mega-group{padding:10px 14px}
  .mega-head{font-size:15px;min-height:0;gap:10px}
  .mega-ico{width:28px;height:28px;border-radius:8px}
  .mega-ico svg{width:15px;height:15px}
  .mega-links{margin-top:9px;padding-top:10px;gap:0}
  .mega-links a{padding:8px 0 8px 17px;font-size:14.5px}
  .mega-links a::before{top:1.05em}

  /* in the drawer it is just the last row of the list, not a footer bar */
  .mega-foot{
    margin:6px 14px 0;padding:13px 15px;
    border:0;border-radius:12px;
    justify-content:space-between;gap:12px;
    background:var(--navy);
  }
  .mega-foot-txt{flex-direction:column;align-items:flex-start;gap:2px}
  .mega-foot b{color:#fff;font-size:15px}
  .mega-foot em{color:rgba(255,255,255,.72);font-size:12.5px}

  /* stacked layout can't fit one screen — let it flow naturally */
  .hero-grid{grid-template-columns:1fr;gap:40px;align-items:stretch}
  .hero-copy{padding-bottom:0}
  .hero-visual{margin-right:0;align-self:auto}
  /* no stretched height here, so the first slide sits in flow to give the
     box its height and the rest overlay it (both images are identical size) */
  .hero-slide:first-child{position:relative;inset:auto}
  .hero-slide:first-child .hero-img{height:auto}
  .hero-img{width:100%;height:100%}
  .eyebrow{font-size:25px;line-height:31px}
  .hero-title{font-size:64px;line-height:68px;min-height:141px}

}

@media (max-width:820px){
  :root{--pad:20px;--header-h:70px}
  .brand img{height:54px}
  /* the floating call button covers this on mobile, so the header keeps just
     the logo and the burger */
  .phone{display:none}

  .hero{padding:12px 0 0}
  /* fluid so a long word can never outgrow a narrow phone — the vw terms are
     tuned so "INSTALLATIONS" still clears the gutters at 360px */
  .hero-copy{text-align:center}
  /* sized off the viewport so the whole line always clears the gutters, with
     room for the pill's own padding — nowrap then guarantees one line */
  /* Frosted glass rather than a flat tint. There are photographs behind this
     now, so a solid pill just covers them — a translucent panel that blurs and
     lifts what's underneath belongs to the image instead of hiding it. The
     hairline border and the 1px inset highlight are what stop it reading as
     plain transparency: together they give the panel a lit top edge, the way
     real glass catches light.
     A live red dot leads the line, so it reads as a status rather than a label. */
  .eyebrow{
    position:relative;
    display:inline-flex;align-items:center;gap:10px;
    font-size:clamp(11px,4vw,22px);line-height:1.25;white-space:nowrap;
    padding:10px 22px 10px 18px;border-radius:50px;
    margin-bottom:14px;
    background:rgba(255,255,255,.5);
    backdrop-filter:blur(16px) saturate(1.5);
    -webkit-backdrop-filter:blur(16px) saturate(1.5);
    border:1px solid rgba(255,255,255,.72);
    box-shadow:inset 0 1px 0 rgba(255,255,255,.95),
               0 10px 26px rgba(9,16,48,.13);
  }
  .eyebrow::before{
    content:"";flex:none;
    width:8px;height:8px;border-radius:50%;
    background:var(--live);
    box-shadow:0 0 0 0 var(--live-ring);
    animation:brow-dot 2.4s ease-out infinite;
  }
  @keyframes brow-dot{
    0%  {box-shadow:0 0 0 0 var(--live-ring)}
    70% {box-shadow:0 0 0 9px rgba(43,217,124,0)}
    100%{box-shadow:0 0 0 0 rgba(43,217,124,0)}
  }
  /* no glass where it isn't supported — fall back to the flat tint rather than
     leaving text on a half-transparent white smear */
  @supports not ((backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px))){
    .eyebrow{background:var(--tint-red-sm);border-color:rgba(237,28,36,.14)}
  }
  .hero-title{font-size:clamp(34px,10.4vw,56px);line-height:1.06;min-height:calc(clamp(34px,10.4vw,56px) * 2.2)}

  .hero-form{flex-direction:column;gap:12px}
  /* the column flips the flex axis, so the 210px basis became a HEIGHT and
     left a huge gap between field and button */
  .field{flex:0 0 auto;width:100%}
  .hero-form .btn{width:100%;padding:0 20px}

  /* three even cells beats a wrapping flex row with orphan dividers.
     Centred to sit under the centred headline above. */
  .counters{display:grid;grid-template-columns:repeat(3,1fr);gap:18px 8px;margin-top:34px;text-align:center}
  .counters li{padding:0;margin:0;border:0}
  .counter-num{font-size:clamp(29px,8.2vw,42px)}
  .counter-label{font-size:12.5px;line-height:1.35;margin-top:7px}

  .ticker{padding:18px 0}
  .ticker-set li{gap:9px;padding:0 18px}
  /* the two-panel dialog sets its own padding, heading and row layout in the
     900px/600px blocks above — these were the old single-panel values and,
     being later in the file, were overriding them */
  .modal-card{border-radius:18px}
  .results{padding:48px 0 54px}
  .results-head{margin-bottom:26px}
  .results-grid{grid-template-columns:1fr;gap:22px}
  .rcard-quote{padding:18px 20px;font-size:16px}
  .rcard-body{padding:20px}
  .results-cta{margin-top:28px}
  .results-cta .btn{width:100%}

  .about{padding:26px 0 56px}
  .about-grid{grid-template-columns:1fr;gap:34px}
  .about-visual{order:-1}
  .about-visual img{height:280px;border-radius:14px}
  .about-badge{left:auto;right:14px;bottom:-20px;padding:14px 18px;gap:11px}
  .about-badge b{font-size:34px}
  .about-badge span{font-size:11.5px}
  .about-points{grid-template-columns:1fr;gap:10px;margin:22px 0 26px}
  .about-cta{gap:18px}
  .about-cta .btn{width:100%}

  .why{padding:10px 0 60px}
  .why-grid{grid-template-columns:1fr;gap:36px}
  .why-visual img{height:280px;border-radius:14px}
  /* the wide variant keeps its own ratio here too — a fixed 280px height
     put the skyline back into a 1.25 frame and cropped 22% off its sides */
  .why-visual--wide img{height:auto;aspect-ratio:16/10}
  .why-badge{right:12px;bottom:-20px;padding:11px 15px;gap:12px}
  .why-badge img{height:26px}
  .cta{padding:44px 0 48px}
  .cta-grid{grid-template-columns:1fr;gap:38px}
  .cta-phone{margin-top:26px}
  .cta-points{margin-top:26px}
  .cform{gap:22px}
  .cform-row{grid-template-columns:1fr;gap:22px}

  .services{padding:52px 0 58px}
  .services-head{margin-bottom:28px}
  .services-grid{grid-template-columns:1fr;gap:14px}
  .scard-body{padding:20px 20px 0}
  .scard-btn{margin:0 0 20px;height:50px}

  .why-list{grid-template-columns:1fr;gap:14px;margin-top:26px}
  .why-list li{padding:20px 18px 22px}
  .why-node{width:46px;height:46px;border-radius:14px;margin-bottom:13px}
  .why-node svg{width:28px;height:28px}
  .why-num{font-size:32px;top:12px;right:15px}
  .why-list h3{font-size:16.5px}
}

@media (prefers-reduced-motion:reduce){
  *{animation-duration:.001ms !important;transition-duration:.001ms !important}
}

/* ===========================================================================
   ESTIMATE DIALOG — RESPONSIVE
   Kept at the end of the file on purpose. These were originally written next to
   the dialog's own rules, which put them ABOVE the base .modal-head, .modal-form
   and .mf declarations — so every one of them lost on source order and the
   mobile sizing silently did nothing.
   =========================================================================== */
@media (max-width:900px){
  /* The navy panel goes entirely. Stacked it was a second screenful before the
     first field; collapsed to a bar it was still a strip of chrome above a form
     that already says who this is. On a phone the form is the whole point. */
  .modal{padding:12px}
  .modal-card{
    grid-template-columns:1fr;
    max-width:520px;
    max-height:calc(100vh - 24px);
    max-height:calc(100dvh - 24px);
  }
  .modal-aside{display:none}

  .modal-x{top:12px;right:12px;width:34px;height:34px}
  .modal-main{padding:22px 18px 20px}
  /* the chip would otherwise run under the close button */
  .modal-head{margin-bottom:0;padding-right:40px}
}

@media (max-width:600px){
  /* One field per row — two 130px-wide inputs side by side is not a form. That
     turns four fields into four rows though, so everything else tightens to pay
     for it: the whole step has to land inside the viewport without scrolling. */
  .modal-form .mf-row{grid-template-columns:1fr;gap:12px}
  .mpane.is-on{gap:12px}
  .mf{gap:5px}
  .mf input{height:46px}
  .mf label{font-size:11.5px}
  .mf-err{font-size:11.5px}

  .modal-main{padding:18px 16px 16px}
  .modal-chip{margin-bottom:9px;padding:5px 11px;font-size:11.5px}
  .modal-head h2{font-size:21px}
  .msteps{margin-top:12px;margin-bottom:14px}
  .mstep b{width:27px;height:27px;font-size:13px}
  .modal-send{height:50px}
  .modal-note{margin-top:12px}

  .modal-actions{flex-direction:column-reverse;align-items:stretch;gap:9px}
  .modal-actions .modal-back{justify-content:center;padding:12px 16px}
}

/* A short window as well as a narrow one — a 600px-tall browser is common on a
   laptop with the bookmarks bar and a taskbar, and the form still has to fit. */
@media (max-width:900px) and (max-height:720px){
  .modal{padding:8px}
  .modal-card{max-height:calc(100vh - 16px);max-height:calc(100dvh - 16px)}
  .modal-main{padding:14px 16px 13px}
  .modal-head h2{font-size:19px;line-height:1.14}
  .modal-chip{margin-bottom:7px}
  .msteps{margin-top:9px;margin-bottom:11px}
  .mstep b{width:25px;height:25px;font-size:12.5px}
  .mpane.is-on{gap:10px}
  .modal-form .mf-row{gap:10px}
  .mf{gap:4px}
  .mf input{height:43px;font-size:15px}
  .modal-send{height:46px}
  .modal-note{margin-top:9px}
  .modal-x{top:9px;right:9px;width:30px;height:30px}
}

@media (max-width:420px){
  .modal-call b{font-size:14.5px}
  .modal-call{margin-right:42px}
  .mstep span{display:none}
  .mstep:first-child::after{margin:0 10px}
  .modal-note{font-size:11.5px;gap:6px}
}

/* ---- verified-fact badges -------------------------------------------------
   The star rating and the Google mark that used to sit in these two spots were
   never verified against a real review profile. What replaces them is a fact
   the business can stand behind, styled to occupy the same footprint so the
   layout around them is unchanged. */
.why-badge--price .why-badge-num{
  font-family:var(--font-head);font-weight:900;
  font-size:30px;letter-spacing:-.03em;color:var(--red);
  line-height:1;flex:none;
}
.why-badge--price .why-badge-rate b{font-size:15px;letter-spacing:-.015em}
.book-badge .book-g{color:var(--red)}
@media (max-width:600px){
  .why-badge--price .why-badge-num{font-size:25px}
}

/* a mega-menu cross-link: a real page, but one that lives under a different
   group, so it is set apart from the group's own children rather than reading
   as one of them */
.mega-links .mega-x a{color:var(--ink-muted);font-style:italic}
.mega-links .mega-x a:hover{color:var(--red);font-style:italic}

/* the $59 counter doubles as the inspection CTA. It is a link inside the
   existing counter, so it costs the hero no height — the row it would have
   needed wrapped to three lines on a narrow window and pushed the hero past
   the viewport, which is the one thing this hero must not do. */
.counter-link{display:block}
.counter-link:hover .counter-num{color:var(--red)}
.counter-num{transition:color .2s ease}
.counter-link:hover .counter-label{color:#fff}

/* ---- mega menu: the panel under a thin group ------------------------------
   Chimney Inspections and Draft & Safety each hold one page, which is what the
   content master asks for — the inspection levels are merged into one service
   rather than split into tiers. That left a hole under both headings. Rather
   than invent pages to fill it, the space carries the thing those two groups
   most need to say. It stretches to the foot of its column, so the column ends
   flush whatever the group above it does. */
.mega-note{
  /* Natural height, sitting straight under the links.

     Two things were tried and both looked worse than the problem: pushing it
     to the foot of the column (which moved the hole above the card) and
     stretching it to fill (which made a 175px tinted box with two lines
     floating in it). The leftover space is a balance problem, so it is fixed
     by the pairing in inc/header.php, not by inflating a card. */
  display:block;
  margin-top:12px;padding:10px 12px;
  border-radius:12px;background:var(--tint);
  border:1px solid transparent;
  transition:border-color .2s ease,background .2s ease,transform .25s cubic-bezier(.22,1,.36,1);
}
.mega-note:hover{background:#fff;border-color:var(--red);transform:translateY(-1px)}
.mega-note b{
  display:flex;align-items:center;gap:6px;
  font-family:var(--font-head);font-weight:800;
  font-size:12.5px;letter-spacing:-.01em;color:var(--red);
}
.mega-note b svg{flex:none;transition:transform .25s cubic-bezier(.22,1,.36,1)}
.mega-note:hover b svg{transform:translateX(3px)}
.mega-note span{
  display:block;margin-top:4px;
  font-size:12px;line-height:1.45;color:var(--ink-body);
}
/* the group becomes a column so the note can take the slack */
.mega-group:has(.mega-note){display:flex;flex-direction:column}
@media (max-width:1024px){
  .mega-note{display:none}
}


/* ---- photograph credits page ------------------------------------------- */
.pc-list{padding:10px 0 78px}
.pc-table{width:100%;border-collapse:collapse;font-size:15px}
.pc-table th,.pc-table td{padding:11px 14px;text-align:left;border-bottom:1px solid rgba(14,30,99,.10)}
.pc-table th{
  font-family:var(--font-head);font-weight:800;font-size:11px;
  letter-spacing:.09em;text-transform:uppercase;color:var(--ink-muted);
}
.pc-table td a{color:var(--navy);font-weight:600}
.pc-note{margin-top:20px;font-size:13.5px;line-height:1.7;color:var(--ink-muted);max-width:70ch}
/* the table must scroll inside itself rather than widening the page */
@media (max-width:640px){
  .pc-list .shell{overflow-x:auto}
  .pc-table{min-width:520px}
}

/* ---- thank-you page ----------------------------------------------------- */
.ty{position:relative;overflow:hidden;padding:78px 0 96px;background:var(--tint)}
/* the shared hero slideshow, sitting behind the content */
.ty-bg{z-index:0}
.ty-inner{position:relative;z-index:2;max-width:720px;margin-inline:auto;text-align:center}

/* The red call pill. It used to borrow .scard-btn, which is built for a tinted
   card — on this light section its label rendered white-on-white and the
   number could not be read at all. */
.ty-call{
  display:inline-flex;align-items:center;gap:13px;
  padding:11px 24px 11px 11px;border-radius:14px;
  background:linear-gradient(135deg,#F2353D 0%,#ED1C24 55%,#B8121A 100%);
  color:#fff;text-decoration:none;text-align:left;
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.22),
    0 2px 4px rgba(14,30,99,.10),
    0 16px 30px -14px rgba(237,28,36,.62);
  transition:transform .28s cubic-bezier(.22,1,.36,1),box-shadow .28s ease;
}
.ty-call:hover{
  transform:translateY(-2px);
  box-shadow:
    inset 0 1px 0 rgba(255,255,255,.26),
    0 4px 8px rgba(14,30,99,.12),
    0 24px 44px -18px rgba(237,28,36,.68);
}
.ty-call:active{transform:translateY(0)}
.ty-call-ico{
  position:relative;flex:none;display:grid;place-items:center;
  width:44px;height:44px;border-radius:50%;background:#fff;
  box-shadow:0 3px 8px -3px rgba(0,0,0,.35);
}
/* The same ringing this button has everywhere else on the site: two rings
   expanding out of the disc on a 2.2s cycle, offset by half, and the handset
   rocking with them. Rebuilding this button as its own pill dropped both, so
   it sat still while the floating one kept ringing. White rather than the red
   tint used elsewhere — these sit on a red pill, not a light card. */
.ty-call-ico::before,
.ty-call-ico::after{
  content:"";position:absolute;inset:0;border-radius:50%;
  border:2.5px solid rgba(255,255,255,.55);
  pointer-events:none;
  animation:ico-ring 2.2s cubic-bezier(.3,0,.5,1) infinite;
}
.ty-call-ico::after{animation-delay:1.1s}
.ty-call-ico svg{animation:ico-rock 2.2s ease-in-out infinite}
@media (prefers-reduced-motion:reduce){
  .ty-call-ico::before,
  .ty-call-ico::after,
  .ty-call-ico svg{animation:none}
}
.ty-call-txt{display:flex;flex-direction:column;line-height:1.15}
.ty-call-txt em{
  font-style:normal;font-family:var(--font-head);font-weight:800;
  font-size:10.5px;letter-spacing:.1em;text-transform:uppercase;
  color:rgba(255,255,255,.86);margin-bottom:3px;
}
.ty-call-txt b{
  font-family:var(--font-proxima);font-weight:800;
  font-size:20px;letter-spacing:-.02em;color:#fff;white-space:nowrap;
}
.ty-mark{
  display:grid;place-items:center;width:74px;height:74px;margin:0 auto 26px;
  border-radius:50%;color:#fff;background:linear-gradient(135deg,#2A44A8,#0E1E63);
  box-shadow:0 14px 30px -12px rgba(14,30,99,.6);
}
.ty-mark svg{width:34px;height:34px}
.ty h1{
  font-family:var(--font-head);font-weight:800;
  font-size:clamp(30px,4.4vw,46px);line-height:1.1;letter-spacing:-.02em;
  color:var(--navy);margin:10px 0 16px;
}
.ty-lead{font-size:17px;line-height:1.7;color:var(--ink-body);max-width:56ch;margin:0 auto}
.ty-actions{display:flex;flex-wrap:wrap;gap:14px;justify-content:center;margin:32px 0 8px}
.ty-next{
  display:grid;grid-template-columns:repeat(3,1fr);gap:18px;
  margin:38px 0 0;text-align:left;
}
.ty-next li{
  background:#fff;border-radius:16px;padding:18px 20px;
  font-size:14.5px;line-height:1.6;color:var(--ink-body);
  box-shadow:inset 0 0 0 1px rgba(14,30,99,.09),0 10px 22px -16px rgba(14,30,99,.4);
}
.ty-next b{display:block;font-family:var(--font-head);font-weight:800;color:var(--navy);margin-bottom:4px}
.ty-more{margin-top:30px;font-size:15px;color:var(--ink-muted)}
.ty-more a{color:var(--navy);font-weight:600}
@media (max-width:820px){
  .ty{padding:52px 0 64px}
  .ty-next{grid-template-columns:1fr}
}

/* Shown in place when a submission genuinely fails, so the visitor's typing
   stays on screen instead of the form pretending it was sent. */
.form-error{
  margin:12px 0 0;padding:11px 14px;border-radius:12px;
  background:var(--tint-red-sm);color:var(--red);
  font-size:14px;line-height:1.5;font-weight:600;
}

/* ---- custom select and textarea inside the estimate modal ----------------
   .csel-btn is styled for the dark hero: white text, a faint white underline
   and a near-black dropdown panel. The modal's right side is white, so the
   field rendered white-on-white — present, focusable, and completely
   invisible, which is why step 2 looked like it had a blank gap where the
   service picker should be.

   These give it the same shape as .mf input beside it: 50px, bordered, rounded,
   dark text on white. The list is inverted to match. */
.modal .csel-btn{
  height:50px;padding:0 16px;
  background:#fff;border:1.5px solid var(--line);border-radius:10px;
  font-size:16px;color:var(--ink);
}
.modal .csel-btn svg{color:var(--ink-muted)}
.modal .csel-btn[aria-expanded="true"]{
  border-color:var(--navy);box-shadow:0 0 0 4px rgba(14,30,99,.10);
}
.modal .csel.is-bad .csel-btn{
  border-color:var(--red);box-shadow:0 0 0 4px rgba(237,28,36,.12);
}
.modal .csel-val.is-placeholder{color:#AEB4CB}
.modal .csel-list{
  background:#fff;border:1.5px solid var(--line);
  box-shadow:0 22px 48px -18px rgba(14,30,99,.34);
}
.modal .csel-list li{color:var(--ink)}
.modal .csel-list li:hover,
.modal .csel-list li[aria-selected="true"]{background:var(--tint);color:var(--navy)}

/* A textarea with no font-family of its own falls back to the browser default,
   which is monospace — so the one multi-line field on the site was typeset in
   Courier while everything around it was Outfit. */
.mf textarea,
textarea{
  font-family:var(--font-body);
  font-size:16px;line-height:1.55;color:var(--ink);
}
.mf textarea{
  width:100%;min-height:104px;padding:12px 16px;resize:vertical;
  background:#fff;border:1.5px solid var(--line);border-radius:10px;
  transition:border-color .18s ease,box-shadow .18s ease;
}
.mf textarea::placeholder{color:#AEB4CB}
.mf textarea:focus{outline:none;border-color:var(--navy);box-shadow:0 0 0 4px rgba(14,30,99,.10)}
@media (max-width:640px){
  .modal .csel-btn{height:46px}
}
