/* ============================================================================
   Smart Sprinkler Solutions — shared design system
   Written 2026-08-18 for the site rebuild (PRD-REBUILD-2026-08-18.md §5).

   ONE stylesheet for every page. Pages used to be self-contained with an inline
   <style>; five copies of a design system is five copies that drift, which is the
   same failure mode brand.json exists to prevent for facts. Link it as:

       <link rel="stylesheet" href="/assets/site.css">

   Hard rules this file is written against (PRD §5 AI-slop checklist):
     - No excessive letter-spacing. Nothing above 0.04em, and only on small caps.
     - No gradient washes on light backgrounds. Light sections are flat fills.
       The only gradient in the file is the legibility scrim over the hero photo,
       which is neutral near-black, not a colour.
     - Green has exactly ONE role: "go". Primary buttons, the mobile call bar, and
       affirmative check glyphs. It is not a heading colour, an icon colour, a
       border colour, or a background tint anywhere.
     - No gradient cards, and no strokes by default. Cards are separated by fill
       and shadow. Borders appear only where they are functional (focus rings).
     - prefers-reduced-motion turns every animation off, including the reveals.

   Motion is progressive enhancement. `.reveal` only hides content when the
   <html> element carries `js`, which an inline one-liner in <head> adds. With
   JavaScript blocked, nothing is hidden. And if the inline script runs but
   site.js itself never does (404, stalled network, parse error), the same
   inline script strips `js` again after 2.5s unless window.__sssReady — the
   first statement of site.js — is set; the site.js tag's onerror strips it
   immediately on a clean 404. Content cannot stay hidden for want of a file.
   ========================================================================== */

/* --- Tokens -------------------------------------------------------------- */
:root {
  --ink: #0D1526;
  --ink-2: #131E36;
  --ink-3: #08101F;
  --muted: #55607A;
  --muted-2: #6A7488;   /* was #7B8598 — darkened 2026-08-18 for WCAG AA on white */

  --blue: #093EAA;
  --blue-deep: #072F82;
  --blue-soft: rgba(9, 62, 170, 0.07);
  --blue-light: #8CAAF0;        /* blue that survives on an ink background */

  --green: #22C358;
  --green-dark: #16A34A;

  --line: #E5E9F0;
  --bg: #FFFFFF;
  --bg-alt: #F6F8FB;

  --on-dark: #F2F5FA;
  --on-dark-soft: #AEB9CD;

  --radius: 12px;
  --radius-lg: 20px;
  --pill: 999px;

  --shadow-1: 0 1px 2px rgba(13, 21, 38, 0.05);
  --shadow-2: 0 2px 4px rgba(13, 21, 38, 0.04), 0 14px 30px -16px rgba(13, 21, 38, 0.24);
  --shadow-3: 0 30px 70px -32px rgba(13, 21, 38, 0.45);

  --maxw: 1120px;
  --header-h: 76px;   /* real measured height of .site-header — see [id] scroll-margin */
  --gutter: clamp(20px, 4vw, 28px);
  --sec-y: clamp(60px, 8vw, 104px);
  --ease: cubic-bezier(0.22, 0.7, 0.3, 1);
}

/* --- Reset --------------------------------------------------------------- */
*, *::before, *::after { margin: 0; padding: 0; box-sizing: border-box; }
html { scroll-behavior: smooth; -webkit-text-size-adjust: 100%; }
body {
  font-family: 'Outfit', -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;
  color: var(--ink);
  background: var(--bg);
  line-height: 1.6;
  font-size: 16px;
  overflow-x: hidden;
}
img, svg { max-width: 100%; display: block; }
ul { list-style: none; }
a { color: var(--blue); }

/* --- Layout -------------------------------------------------------------- */
.wrap { max-width: var(--maxw); margin: 0 auto; padding: 0 var(--gutter); width: 100%; }
.wrap.narrow { max-width: 860px; }
section { padding: var(--sec-y) 0; }
section.alt { background: var(--bg-alt); }
/* Every nav link and every redirect in build/redirects.json lands on one of these
   ids. Without this the sticky header sits on top of the heading you just asked
   for, which reads as a broken link even though the scroll worked. Measured, not
   guessed: a flat 92px cleared the 70px desktop header and hid the heading behind
   the 95px mobile one. --header-h is kept in step with the real bar below. */
[id] { scroll-margin-top: calc(var(--header-h) + 22px); }
.stack > * + * { margin-top: 16px; }

/* --- Type ---------------------------------------------------------------- */
h1, h2, h3, h4 { line-height: 1.1; letter-spacing: -0.022em; font-weight: 800; }
h1 { font-size: clamp(2.5rem, 6.2vw, 4.3rem); letter-spacing: -0.032em; }
h2 { font-size: clamp(1.7rem, 3.8vw, 2.6rem); margin-bottom: 0.5rem; }
h3 { font-size: 1.15rem; font-weight: 700; letter-spacing: -0.012em; }
p { color: var(--muted); }
.lead { font-size: clamp(1.05rem, 1.6vw, 1.2rem); max-width: 60ch; }
.answer { font-size: 1.08rem; color: var(--ink); max-width: 72ch; margin-top: 10px; }
.answer + p, .answer + .answer { margin-top: 14px; max-width: 72ch; }
.kicker {
  color: var(--blue);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.04em;
  font-size: 0.78rem;
  margin-bottom: 10px;
}
.fine { font-size: 0.88rem; color: var(--muted); }

/* Dark sections invert the palette rather than restating it per component. */
.on-dark { background: var(--ink); color: var(--on-dark); }
.on-dark h1, .on-dark h2, .on-dark h3, .on-dark h4, .on-dark strong { color: #fff; }
.on-dark p, .on-dark li { color: var(--on-dark-soft); }
.on-dark .kicker { color: var(--blue-light); }
.on-dark a { color: #fff; }

/* --- Buttons -------------------------------------------------------------
   Four variants, no borders on any of them. btn-outline is a tinted fill, not a
   stroke — the checklist bans default strokes and a tint reads cleaner anyway. */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 8px;
  font-family: inherit; font-weight: 700; font-size: 1rem;
  border-radius: var(--radius); padding: 15px 26px; min-height: 52px;
  text-decoration: none; cursor: pointer; border: none; text-align: center; white-space: nowrap;
  transition: transform 0.14s var(--ease), box-shadow 0.14s var(--ease), background 0.14s var(--ease);
}
.btn:hover { transform: translateY(-1px); }
.btn:active { transform: translateY(0); }
.btn:focus-visible { outline: 3px solid var(--blue-light); outline-offset: 3px; }
.btn small { font-weight: 500; font-size: 0.84rem; opacity: 0.92; }

.btn-green { background: var(--green); color: #fff; box-shadow: 0 8px 20px -8px rgba(34, 195, 88, 0.65); }
.btn-green:hover { background: var(--green-dark); box-shadow: 0 12px 26px -8px rgba(34, 195, 88, 0.6); }
.btn-outline { background: var(--blue-soft); color: var(--blue); }
.btn-outline:hover { background: rgba(9, 62, 170, 0.12); }
.btn-dark { background: var(--ink); color: #fff; }
.btn-dark:hover { background: var(--ink-2); }
.btn-ghost { background: rgba(255, 255, 255, 0.14); color: #fff; backdrop-filter: blur(6px); }
.btn-ghost:hover { background: rgba(255, 255, 255, 0.22); }
/* Full-width form submit. It overrides the nowrap above: a submit button owns its
   whole column, so a long label should wrap inside it rather than run past the
   fields it sits under. */
.btn-wide { width: 100%; white-space: normal; }

/* --- Header ---------------------------------------------------------------
   Dark, so it meets the dark hero without a seam and still reads as a bar over
   the light sections below. */
.site-header {
  position: sticky; top: 0; z-index: 60;
  background: rgba(8, 16, 31, 0.92);
  backdrop-filter: blur(10px);
}
/* The gutter is restated here, not left to .wrap. The header markup is
   `<div class="wrap nav">`, and a `padding: 12px 0` shorthand on the later rule
   silently zeroes .wrap's horizontal padding — which put the logo and the Instant
   Quote button hard against both screen edges at every width. Inherited from the
   old inline stylesheet, caught in the browser 2026-08-18. */
.nav { display: flex; align-items: center; gap: 18px; padding: 12px var(--gutter); }
.brand { display: flex; align-items: center; gap: 11px; text-decoration: none; color: #fff; margin-right: auto; }
.brand-mark {
  background: var(--blue); color: #fff; font-weight: 800; font-size: 0.9rem;
  border-radius: 11px; padding: 11px 12px; line-height: 1; letter-spacing: 0.02em;
}
.brand-name { font-weight: 800; font-size: 1.02rem; line-height: 1.15; color: #fff; }
.brand-tag {
  display: block; font-size: 0.62rem; font-weight: 700; color: var(--blue-light);
  text-transform: uppercase; letter-spacing: 0.04em; margin-top: 2px;
}
.nav-links { display: flex; gap: 2px; align-items: center; }
.nav-links a {
  text-decoration: none; color: var(--on-dark); font-weight: 600; font-size: 0.94rem;
  padding: 9px 13px; border-radius: 9px; white-space: nowrap;
  transition: background 0.14s var(--ease);
}
.nav-links a:hover, .nav-links a.active { background: rgba(255, 255, 255, 0.1); color: #fff; }
.nav-phone { font-weight: 700; color: #fff; text-decoration: none; white-space: nowrap; font-size: 0.98rem; }
.nav .btn { min-height: 44px; padding: 11px 20px; font-size: 0.95rem; }
/* 1100, not 1040: with the gutter restored the six links no longer fit at 1040 and
   "Service Area" wrapped onto a second line, which grew the sticky bar to 90px and
   ate the anchor clearance below. nowrap above turns that failure into an honest
   overflow; this breakpoint is where it stops happening. */
@media (max-width: 1100px) { .nav-links { display: none; } }
@media (max-width: 620px) {
  /* The tagline wraps the brand name onto a third line and pushes the bar to 95px,
     which then eats the heading every anchor link scrolls to. It also says the same
     thing as the hero badge two hundred pixels below it. */
  .nav-phone, .brand-tag { display: none; }
  .brand-name { font-size: 0.9rem; }
  .brand-mark { padding: 9px 10px; font-size: 0.82rem; }
  .nav { padding: 10px var(--gutter); gap: 10px; }
  .nav .btn { min-height: 42px; padding: 10px 14px; font-size: 0.9rem; }
  :root { --header-h: 66px; }
}

/* --- Hero ---------------------------------------------------------------- */
.hero {
  position: relative; isolation: isolate; overflow: hidden;
  background: var(--ink-3); color: var(--on-dark);
  padding: clamp(72px, 11vw, 132px) 0 clamp(56px, 8vw, 96px);
}
/* Stacking is explicit and non-negative: photo 0, scrim 1, copy 2. The obvious
   version — negative z-index on the photo so it slips behind the copy — renders
   as a black box, because a negative-z child of a stacking context paints under
   that element's own background, and .hero has one. Caught in the browser
   2026-08-18. Do not "simplify" this back to z-index:-1. */
.hero-media { position: absolute; inset: 0; z-index: 0; }
.hero-media img { width: 100%; height: 100%; object-fit: cover; opacity: 0.75; }
.hero::after {
  /* Legibility scrim. Neutral near-black, not a colour wash. Heavy on the left
     where the copy sits, light on the right so the photograph is actually seen. */
  content: ""; position: absolute; inset: 0; z-index: 1;
  background: linear-gradient(96deg, rgba(8, 16, 31, 0.9) 0%, rgba(8, 16, 31, 0.7) 48%, rgba(8, 16, 31, 0.22) 100%);
}
.hero > .wrap { position: relative; z-index: 2; }
@media (max-width: 860px) {
  /* No room for the copy to sit clear of the photo, so the scrim goes flat. */
  .hero::after { background: rgba(8, 16, 31, 0.86); }
}
.hero-inner { max-width: 760px; }
.hero h1 { color: #fff; }
.hero .lead { color: #D3DBE9; margin: 20px 0 26px; }
.hero .lead strong { color: #fff; }

.badge {
  display: inline-flex; align-items: center; gap: 8px;
  background: rgba(255, 255, 255, 0.1); color: #fff;
  font-weight: 700; font-size: 0.78rem; letter-spacing: 0.03em; text-transform: uppercase;
  border-radius: var(--pill); padding: 9px 18px; margin-bottom: 22px;
}
.offer-line {
  font-size: clamp(1.02rem, 1.7vw, 1.22rem); color: #E7ECF5; line-height: 1.5;
  background: rgba(255, 255, 255, 0.07); border-radius: var(--radius);
  padding: 16px 20px; max-width: 640px; margin-bottom: 24px;
}
.offer-line strong { color: #fff; font-weight: 800; }
.offer-sep { color: var(--on-dark-soft); padding: 0 4px; }
.hero-ctas { display: flex; flex-wrap: wrap; gap: 12px; margin-bottom: 18px; }
.offer-fine { font-size: 0.9rem; color: var(--on-dark-soft); max-width: 62ch; margin-bottom: 26px; }
.offer-fine a { color: #fff; text-underline-offset: 3px; }

.trust-strip {
  display: flex; flex-wrap: wrap; gap: 10px 22px;
  font-size: 0.8rem; font-weight: 700; letter-spacing: 0.03em; text-transform: uppercase;
}
.trust-strip li { color: #E7ECF5; }
.trust-strip li::before { content: "✓"; color: var(--green); font-weight: 800; margin-right: 7px; }

/* Slow zoom-out on the hero photo. Off under reduced motion (bottom of file). */
.hero-img { animation: kenburns 26s var(--ease) both; transform-origin: 60% 50%; }
@keyframes kenburns { from { transform: scale(1.07); } to { transform: scale(1); } }

/* The one water accent: a droplet falling down a hairline. Used once, in the
   hero, at low opacity. Anything more turns into decoration for its own sake. */
.drip { position: absolute; left: 50%; bottom: 0; z-index: 2; width: 1px; height: 64px; overflow: hidden; opacity: 0.4; }
.drip::before { content: ""; position: absolute; inset: 0; background: linear-gradient(rgba(255,255,255,0), rgba(255,255,255,0.35)); }
.drip::after {
  content: ""; position: absolute; left: -2px; width: 5px; height: 5px; border-radius: 50%;
  background: #fff; animation: fall 5.5s linear infinite;
}
@keyframes fall { 0% { top: -8px; opacity: 0; } 15% { opacity: 0.9; } 85% { opacity: 0.9; } 100% { top: 64px; opacity: 0; } }

/* --- Sub-hero (blowout waitlist) ----------------------------------------- */
.subhero { background: var(--ink-2); color: var(--on-dark); padding: clamp(48px, 6vw, 76px) 0; }
.subhero-grid { display: grid; grid-template-columns: 1.05fr 0.95fr; gap: clamp(28px, 5vw, 60px); align-items: start; }
@media (max-width: 860px) { .subhero-grid { grid-template-columns: 1fr; } }
.subhero h2 { font-size: clamp(1.5rem, 3vw, 2.1rem); }
.subhero-note { font-size: 0.92rem; margin-top: 14px; }
.subhero-note a { color: #fff; }

.waitlist { background: rgba(255, 255, 255, 0.06); border-radius: var(--radius-lg); padding: clamp(22px, 3vw, 30px); }
.waitlist h3 { color: #fff; margin-bottom: 4px; }
.waitlist .fine { color: var(--on-dark-soft); }
.field-row { display: grid; grid-template-columns: 1fr 1fr; gap: 12px; }
@media (max-width: 460px) { .field-row { grid-template-columns: 1fr; } }

/* --- Forms ---------------------------------------------------------------
   Filled inputs, no strokes. The focus ring is the only border in the file. */
label { display: block; font-weight: 600; font-size: 0.88rem; margin: 14px 0 6px; }
input, select, textarea {
  width: 100%; font-family: inherit; font-size: 1rem; color: var(--ink);
  padding: 13px 14px; border: none; border-radius: 10px; background: var(--bg-alt);
  transition: box-shadow 0.14s var(--ease), background 0.14s var(--ease);
}
input:focus, select:focus, textarea:focus { outline: none; box-shadow: 0 0 0 3px rgba(9, 62, 170, 0.35); background: #fff; }
.on-dark label, .subhero label { color: #E7ECF5; }
.on-dark input, .on-dark select, .subhero input, .subhero select {
  background: rgba(255, 255, 255, 0.1); color: #fff;
}
.on-dark input::placeholder, .subhero input::placeholder { color: rgba(255, 255, 255, 0.5); }
.on-dark input:focus, .subhero input:focus, .on-dark select:focus, .subhero select:focus {
  background: rgba(255, 255, 255, 0.18); box-shadow: 0 0 0 3px rgba(140, 170, 240, 0.5);
}
form .btn { margin-top: 20px; }
.consent { display: flex; gap: 10px; align-items: flex-start; margin-top: 16px; }
.consent input { width: auto; margin-top: 4px; flex-shrink: 0; }
.consent label { margin: 0; font-weight: 400; font-size: 0.8rem; color: var(--muted); line-height: 1.45; }
.subhero .consent label, .on-dark .consent label { color: var(--on-dark-soft); }

/* --- Stat band ----------------------------------------------------------- */
.stats { display: grid; grid-template-columns: repeat(auto-fit, minmax(230px, 1fr)); gap: clamp(24px, 4vw, 48px); }
.stat-num {
  font-size: clamp(2.5rem, 5.2vw, 3.6rem); font-weight: 800; color: var(--ink);
  letter-spacing: -0.04em; font-variant-numeric: tabular-nums; line-height: 1;
}
.stat-label { margin-top: 10px; font-size: 0.95rem; max-width: 34ch; }

/* --- Cards --------------------------------------------------------------- */
.grid { display: grid; gap: 20px; margin-top: 34px; }
.grid-2 { grid-template-columns: repeat(auto-fit, minmax(320px, 1fr)); }
.grid-3 { grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); }
.grid-4 { grid-template-columns: repeat(auto-fit, minmax(220px, 1fr)); }
.card { background: #fff; border-radius: var(--radius); padding: 26px; box-shadow: var(--shadow-2); }
.card h3 { margin-bottom: 8px; }
.card p { font-size: 0.96rem; }
.card .icon {
  width: 46px; height: 46px; border-radius: 12px; background: var(--bg-alt);
  display: flex; align-items: center; justify-content: center; margin-bottom: 15px; font-size: 1.3rem;
}
.card .price-note { display: inline-block; margin-top: 13px; font-weight: 700; color: var(--blue); font-size: 0.9rem; }

/* --- Offer panel ---------------------------------------------------------
   Dark card on the light section. The green stays on the button, where it means
   "press this", instead of becoming a 2px decorative frame. */
.offer-layout { display: grid; grid-template-columns: 1fr minmax(0, 520px); gap: clamp(28px, 5vw, 60px); align-items: center; }
@media (max-width: 940px) { .offer-layout { grid-template-columns: 1fr; align-items: start; } }
.offer-layout .offer-panel { margin-top: 0; }
.offer-panel {
  background: var(--ink); color: var(--on-dark); border-radius: var(--radius-lg);
  padding: clamp(28px, 4vw, 40px); max-width: 580px; margin-top: 34px; box-shadow: var(--shadow-3);
}
.offer-panel h3 { color: #fff; font-size: 1rem; text-transform: uppercase; letter-spacing: 0.04em; }
.offer-panel .price { font-size: clamp(2.8rem, 6vw, 3.6rem); font-weight: 800; color: #fff; margin: 8px 0 2px; letter-spacing: -0.04em; font-variant-numeric: tabular-nums; }
.offer-panel .price span { font-size: 1rem; font-weight: 600; color: var(--on-dark-soft); letter-spacing: 0; }
.offer-panel ul { margin: 20px 0 24px; }
.offer-panel li { padding: 7px 0 7px 28px; position: relative; color: #E7ECF5; font-size: 0.97rem; }
.offer-panel li::before { content: "✓"; position: absolute; left: 0; color: var(--green); font-weight: 800; }
.offer-panel .fine { color: var(--on-dark-soft); margin-top: 14px; }
.offer-actions { display: flex; flex-wrap: wrap; gap: 10px; }

/* --- Before / after slider -----------------------------------------------
   `--pos` is the divider position. It defaults to 50%, so with JavaScript off
   the block is a static half-and-half comparison — both images visible, both
   labelled. site.js only mirrors the range input's value into --pos. */
.ba { --pos: 50%; margin-top: 34px; }
.ba-frame {
  position: relative; aspect-ratio: 16 / 10; border-radius: var(--radius-lg);
  overflow: hidden; background: var(--ink-2); box-shadow: var(--shadow-2);
}
.ba-frame > img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.ba-after { clip-path: inset(0 0 0 var(--pos)); }
.ba-line { position: absolute; top: 0; bottom: 0; left: var(--pos); width: 2px; background: rgba(255, 255, 255, 0.9); pointer-events: none; }
.ba-knob {
  position: absolute; top: 50%; left: var(--pos); transform: translate(-50%, -50%);
  width: 46px; height: 46px; border-radius: 50%; background: #fff; color: var(--ink);
  display: grid; place-items: center; font-weight: 800; font-size: 0.95rem;
  box-shadow: 0 6px 18px rgba(8, 16, 31, 0.4); pointer-events: none;
}
.ba-range {
  position: absolute; inset: 0; width: 100%; height: 100%; margin: 0; padding: 0;
  opacity: 0; cursor: ew-resize; background: transparent; -webkit-appearance: none; appearance: none;
}
.ba-range::-webkit-slider-thumb { -webkit-appearance: none; width: 2px; height: 100%; }
.ba-range::-moz-range-thumb { width: 2px; height: 100%; border: none; }
.ba-frame:has(.ba-range:focus-visible) { outline: 3px solid var(--blue); outline-offset: 3px; }
.ba-tag {
  position: absolute; bottom: 14px; z-index: 2;
  background: rgba(8, 16, 31, 0.78); color: #fff; font-size: 0.7rem; font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.04em; padding: 7px 13px; border-radius: var(--pill);
  pointer-events: none;
}
.ba-tag-before { left: 14px; }
.ba-tag-after { right: 14px; }
.ba-caption { margin-top: 12px; font-size: 0.86rem; color: var(--muted); }

/* --- Media figures & work strip ------------------------------------------ */
.media-pair { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 22px; margin-top: 34px; }
.media-figure img {
  width: 100%; height: auto; aspect-ratio: 16 / 9; object-fit: cover;
  border-radius: var(--radius-lg); background: var(--bg-alt); box-shadow: var(--shadow-2);
}
.media-figure figcaption { margin-top: 11px; font-size: 0.92rem; color: var(--muted); }

.strip { display: grid; grid-template-columns: repeat(auto-fit, minmax(210px, 1fr)); gap: 16px; margin-top: 32px; }
.strip img { width: 100%; height: auto; aspect-ratio: 4 / 3; object-fit: cover; border-radius: var(--radius); background: var(--bg-alt); }
.strip figcaption { margin-top: 9px; font-size: 0.85rem; color: var(--muted); }

/* --- Guarantee panel ----------------------------------------------------- */
.guarantee {
  background: var(--ink); color: var(--on-dark); border-radius: var(--radius-lg);
  padding: clamp(32px, 5vw, 54px); display: grid; grid-template-columns: 1fr 1fr;
  gap: clamp(28px, 4vw, 44px); align-items: center; box-shadow: var(--shadow-3);
}
.guarantee h2, .guarantee h3 { color: #fff; }
.guarantee p { color: var(--on-dark-soft); }
.guarantee .btn-green { box-shadow: none; }
@media (max-width: 760px) { .guarantee { grid-template-columns: 1fr; } }

/* --- Service area -------------------------------------------------------- */
.city-list { display: flex; flex-wrap: wrap; gap: 9px; margin-top: 24px; }
.city-list a, .city-list span {
  display: inline-block; text-decoration: none; background: #fff; color: var(--ink);
  font-weight: 600; font-size: 0.92rem; border-radius: var(--pill); padding: 10px 18px;
  box-shadow: var(--shadow-1);
}
.city-list a { color: var(--blue); }
.city-list a:hover { background: var(--blue); color: #fff; }
/* Non-link cities: flat tinted fill, no shadow — only real links get the white
   raised pill, so only real links look clickable. */
.city-list span { color: var(--muted); background: var(--bg-alt); box-shadow: none; }

/* --- Reviews ------------------------------------------------------------- */
.proof { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 18px; margin-top: 30px; }
.proof-card { background: #fff; border-radius: var(--radius); padding: 24px 26px; box-shadow: var(--shadow-2); }
.proof-rate { font-size: 2.1rem; font-weight: 800; color: var(--ink); letter-spacing: -0.03em; line-height: 1; }
.proof-card p { font-size: 0.92rem; margin-top: 8px; }
.proof-card a { font-weight: 700; font-size: 0.92rem; display: inline-block; margin-top: 12px; text-underline-offset: 3px; }

.review-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); gap: 18px; margin-top: 22px; }
.review { background: #fff; border-radius: var(--radius); padding: 26px; box-shadow: var(--shadow-2); display: flex; flex-direction: column; }
.review blockquote p { color: var(--ink); font-size: 0.99rem; }
.review-meta { margin-top: auto; padding-top: 16px; font-size: 0.86rem; color: var(--muted); font-weight: 600; }
.review-plat {
  display: inline-block; background: var(--blue-soft); color: var(--blue);
  font-size: 0.72rem; font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em;
  padding: 4px 10px; border-radius: var(--pill); margin-right: 8px;
}
.review-job { display: block; margin-top: 6px; font-weight: 500; color: var(--muted-2); }
.review-note { margin-top: 20px; font-style: italic; color: var(--muted); font-size: 0.93rem; max-width: 66ch; }
.review-actions { display: flex; flex-wrap: wrap; gap: 10px; margin-top: 22px; }

/* --- FAQ ----------------------------------------------------------------- */
.faq { max-width: 860px; }
.faq details { background: #fff; border-radius: var(--radius); margin-top: 12px; box-shadow: var(--shadow-1); }
.faq summary {
  cursor: pointer; font-weight: 700; font-size: 1.04rem; padding: 20px 24px;
  list-style: none; display: flex; justify-content: space-between; gap: 14px; align-items: center;
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after { content: "+"; color: var(--blue); font-weight: 800; font-size: 1.4rem; line-height: 1; }
.faq details[open] summary::after { content: "–"; }
.faq summary:focus-visible { outline: 3px solid var(--blue); outline-offset: -3px; border-radius: var(--radius); }
.faq details p { padding: 0 24px 20px; max-width: none; }

/* --- Contact ------------------------------------------------------------- */
.contact-grid { display: grid; grid-template-columns: 1.1fr 0.9fr; gap: clamp(28px, 5vw, 52px); margin-top: 34px; align-items: start; }
@media (max-width: 820px) { .contact-grid { grid-template-columns: 1fr; } }
.contact-info h3 { margin: 20px 0 4px; }
.contact-info h3:first-child { margin-top: 0; }
.contact-info a { color: var(--blue); font-weight: 700; text-decoration: none; }
.contact-card { background: #fff; border-radius: var(--radius-lg); padding: clamp(24px, 3vw, 32px); box-shadow: var(--shadow-2); }

/* --- Footer -------------------------------------------------------------- */
.site-footer { background: var(--ink); color: var(--on-dark-soft); padding: 52px 0 96px; font-size: 0.92rem; }
/* Grid, not flex-wrap: with four columns of unequal text width, space-between
   dropped one of them onto a second row on its own and left a hole. */
.site-footer .wrap { display: grid; grid-template-columns: 1.7fr 1fr 1fr 1.3fr; gap: 32px; }
@media (max-width: 900px) { .site-footer .wrap { grid-template-columns: 1fr 1fr; } }
@media (max-width: 520px) { .site-footer .wrap { grid-template-columns: 1fr; } }
.site-footer strong { color: #fff; font-size: 1.04rem; display: block; margin-bottom: 6px; }
.site-footer a { color: var(--on-dark-soft); text-underline-offset: 3px; }
.site-footer a:hover { color: #fff; }
.legal { grid-column: 1 / -1; border-top: 1px solid rgba(255, 255, 255, 0.12); padding-top: 20px; margin-top: 8px; font-size: 0.84rem; }

/* --- Sticky mobile call bar ---------------------------------------------- */
.call-bar { position: fixed; bottom: 0; left: 0; right: 0; z-index: 70; display: none; background: var(--green); text-align: center; padding: 15px; }
.call-bar a { color: #fff; font-weight: 800; font-size: 1.08rem; text-decoration: none; }
@media (max-width: 760px) { .call-bar { display: block; } .site-footer { padding-bottom: 112px; } }

/* --- Scroll reveal -------------------------------------------------------
   Scoped to `.js` so a blocked script leaves every section visible. A FAILED
   script (404 after the inline head script already added `js`) is covered by
   the head script's 2.5s window.__sssReady fallback and the site.js tag's
   onerror, both of which strip `js` again. */
.js .reveal {
  opacity: 0; transform: translateY(16px);
  transition: opacity 0.65s var(--ease), transform 0.65s var(--ease);
  transition-delay: var(--rd, 0s);
}
.js .reveal.is-in { opacity: 1; transform: none; }

/* --- Reduced motion ------------------------------------------------------ */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { animation: none !important; transition: none !important; }
  .js .reveal { opacity: 1; transform: none; }
  .drip { display: none; }
}
