/* Purify v2 — mock redesign. Mobile-first, self-hosted open-source type, rationed motion. */

/* ---------- v3.3 typography: "Neighborly" — OWNER'S PICK (2026-07-29) ----------
   Owner chose trial B from the v3.1 font trials; Franklin/Caslon and the other candidates
   are deleted. Self-hosted WOFF2 (open-source, no font service): Plus Jakarta Sans
   variable carries headlines, body, and UI; Bitter variable carries the certificate,
   serif leads, pull quotes, and the 4.9 numeral. latin + latin-ext covers Spanish. */
@font-face{font-family:"Plus Jakarta Sans";font-style:normal;font-weight:200 800;font-display:swap;src:url("../fonts/jakarta-var-latin-ext.woff2") format("woff2");unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}
@font-face{font-family:"Plus Jakarta Sans";font-style:normal;font-weight:200 800;font-display:swap;src:url("../fonts/jakarta-var-latin.woff2") format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}
@font-face{font-family:"Bitter";font-style:normal;font-weight:100 900;font-display:swap;src:url("../fonts/bitter-var-latin-ext.woff2") format("woff2");unicode-range:U+0100-02BA,U+02BD-02C5,U+02C7-02CC,U+02CE-02D7,U+02DD-02FF,U+0304,U+0308,U+0329,U+1D00-1DBF,U+1E00-1E9F,U+1EF2-1EFF,U+2020,U+20A0-20AB,U+20AD-20C0,U+2113,U+2C60-2C7F,U+A720-A7FF}
@font-face{font-family:"Bitter";font-style:normal;font-weight:100 900;font-display:swap;src:url("../fonts/bitter-var-latin.woff2") format("woff2");unicode-range:U+0000-00FF,U+0131,U+0152-0153,U+02BB-02BC,U+02C6,U+02DA,U+02DC,U+0304,U+0308,U+0329,U+2000-206F,U+20AC,U+2122,U+2191,U+2193,U+2212,U+2215,U+FEFF,U+FFFD}

:root{
  --navy:#12181D;
  --navy-deep:#07090B;
  --navy-card:#1B242B;
  --blue:#2E9FF2;
  --blue-deep:#1877C9;
  --gold:#C8A24B;
  --gold-light:#E4C983;
  --white:#FFFFFF;
  --mist:#F5F8FB;
  --slate:#2A3540;
  /* v3.13 (Ruling #11 audit): the designer MEASURED muted text failing AA on the blue
     ground below ~57% of page height (4.36:1 at the packages note, 3.80:1 at the reviews
     meta, 3.68:1 at the trust sublines). Darkened to clear 4.5:1 against the deepest
     ground tone (#6FC0F6) — the owner's blue stays, the text becomes legal. */
  --muted:#3B4650;
  /* --border was LIGHTER than the mid-page ground, so every hairline vanished (the whole
     v3 "hairlines not boxes" system went invisible). Now reads on paper AND on blue. */
  --border:#B9D3E8;
  --cta:#1877C9; /* AA: white text passes 4.5:1 across the whole gradient */
  --cta-deep:#1569BB;
  --shadow:0 10px 22px -14px rgba(9,14,18,.28);
  --radius:10px;
  /* v2.8 motion grammar: one curve, one clock (~120ms press / ~250ms ease) sitewide */
  --ease:cubic-bezier(.2,.7,.3,1);
  --font:"Plus Jakarta Sans",system-ui,-apple-system,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;
  --display:var(--font);
  --serif:"Bitter",Georgia,"Times New Roman",Times,serif;
}
*{box-sizing:border-box}
/* [hidden] must always win — author display rules (.btn, .bf-fields…) were overriding it */
[hidden]{display:none !important}
html{-webkit-text-size-adjust:100%;overflow-x:hidden}
/* smooth anchor scrolling (killed under reduced motion) + room for the sticky header */
@media (prefers-reduced-motion:no-preference){html{scroll-behavior:smooth}}
[id]{scroll-margin-top:102px}
/* editorial masthead rule */
body::before{content:"";display:block;height:3px;background:linear-gradient(90deg,var(--blue),var(--blue-deep))}
/* v3 "one desk": ONE continuous paper tone page-wide — sections are objects on it,
   full-bleed dark is reserved for the final CTA and the footer alone */
body{
  margin:0;font-family:var(--font);color:var(--slate);
  line-height:1.65;background:var(--mist);
  -webkit-font-smoothing:antialiased;
  padding-bottom:calc(74px + env(safe-area-inset-bottom)); /* clears sticky mobile bar */
}
/* ---------- v3.7 LIVING GROUND — three LIVE candidates (owner decision pending) ------
   v3.6's engraved wave-hairline tile is DEAD (owner: "looks like paper lines") — the
   tile SVG and paper-swell drift are removed; do not reintroduce line textures. The
   v3.7b: THE OWNER PICKED C "THE DESCENT" — now LAW. Candidates A/B, the ?bg=
   switcher, and the Bg chip are deleted. The ambient ripple rings carry the
   water-texture duty at raised presence (see .amb-ripples).
   Laws: framed panels and white sheets are solid fills and sit clean on the ground;
   the glass buttons' documented worst-case math assumes PURE BLACK backdrops, far
   inside their floors; static paint, zero runtime cost; fail-visible (plain CSS on
   body); hairline strokes that pass behind type (ambient rings, the whoosh's flow
   lines) fall under the v3.5 "rings behind type" engraving precedent.

   C (default) — "THE DESCENT": one continuous vertical fade, certificate mist at the
   top deepening through azure-tinted paper toward the dark final CTA — the page
   descends into water and the ink band is the plunge. Static paint, zero runtime cost.
   AA: deepest tone (page bottom) #DAECFA = rgb(218,236,250), L .818 — muted #5D6B77
   4.53:1 (the documented floor), slate 10.3:1, ink 14.8:1. The hero lives in the top
   ~10% where the ground is still mist-grade, so the whoosh compound math (.hw-curl)
   holds against it.

   */
/* v3.9c owner: the ground matches the LOGO DROP hex — every stop is a white tint of
   #2E9FF2 (same hue), landing on the exact logo blue at the page bottom. AA re-derivation
   deferred to the audit (most reading text sits inside white sheets/panels). */
/* v3.9e owner: a tad lighter — same logo-blue hue, the deep end pulled back from the
   full-saturation hex to a softer tint */
body{
  background-image:linear-gradient(180deg,#DFF1FD 0%,#BCE0FB 35%,#93CDF8 70%,#6FC0F6 100%);
}

/* v3.10 mobile burger + glass dropdown — phones only, shown by JS when the header tucks */
.mnav-burger{
  position:fixed;top:12px;right:14px;z-index:55;width:46px;height:46px;border-radius:14px;
  display:flex;align-items:center;justify-content:center;cursor:pointer;color:var(--navy);
  border:1.5px solid rgba(46,159,242,.7);background:rgba(255,255,255,.7);
  -webkit-backdrop-filter:blur(14px) saturate(1.8);backdrop-filter:blur(14px) saturate(1.8);
  box-shadow:inset 0 1.5px 0 rgba(255,255,255,.9),0 0 10px rgba(46,159,242,.3),0 8px 20px -10px rgba(9,14,18,.3);
}
.mnav-burger svg{width:22px;height:22px}
.mnav-burger:active{transform:scale(.94)}
.mnav-burger:focus-visible{outline:3px solid var(--blue);outline-offset:2px}
@media (min-width:760px){.mnav-burger,.mnav-drop{display:none !important}}
.mnav-drop{
  position:fixed;top:66px;right:14px;z-index:55;min-width:210px;padding:10px;border-radius:16px;
  border:1.5px solid rgba(255,255,255,.8);background:rgba(255,255,255,.85);
  -webkit-backdrop-filter:blur(18px) saturate(1.8);backdrop-filter:blur(18px) saturate(1.8);
  box-shadow:inset 0 1.5px 0 rgba(255,255,255,.95),0 0 12px rgba(46,159,242,.3),0 14px 30px -12px rgba(9,14,18,.35);
}
.mnav-drop a{display:block;padding:12px 14px;color:var(--navy);font-weight:700;border-radius:10px}
.mnav-drop a:active{background:var(--mist)}
.mnav-drop .mnav-book{color:var(--blue-deep)}
@supports not ((backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px))){
  .mnav-burger{background:rgba(255,255,255,.95)}
  .mnav-drop{background:rgba(255,255,255,.97)}
}
.amb-ripples{position:fixed;inset:0;z-index:-1;pointer-events:none;overflow:hidden}
.amb-ripples span{position:absolute;transform:translate(-50%,-50%)}
/* v3.7: ring presence raised (owner kept these when the line texture died — they carry
   the texture duty now; size/frequency/cap raised in JS alongside) */
/* v3.8b owner: "very light and hard to notice" — thicker strokes, hotter azure, higher
   peak opacity, slightly longer visible life */
.amb-ripples span::before,.amb-ripples span::after{
  content:"";position:absolute;inset:0;border-radius:50%;
  border:2px solid rgba(46,159,242,.8);
  opacity:0;transform:scale(.12);will-change:transform,opacity;
}
.amb-ripples span::before{animation:amb-ring 2.8s var(--ease) forwards}
.amb-ripples span::after{border-color:rgba(46,159,242,.55);animation:amb-ring 3.1s var(--ease) .3s forwards}
@keyframes amb-ring{
  0%{transform:scale(.12);opacity:0}
  12%{opacity:1}
  55%{opacity:.55}
  100%{transform:scale(1);opacity:0}
}
img{max-width:100%;display:block}
a{color:var(--blue-deep);text-decoration:none;-webkit-tap-highlight-color:transparent}
.btn,button,summary{-webkit-tap-highlight-color:transparent}
h1,h2,h3,h4{font-family:var(--display);color:var(--navy);line-height:1.15;margin:0 0 .4em;font-weight:800;letter-spacing:-.02em;text-wrap:balance}
/* deliberate section-heading scale (was browser default) — Swiss discipline, felt hierarchy */
h2{font-size:clamp(1.6rem,1.15rem+1.7vw,2.2rem)}
p{margin:0 0 1em}
.wrap{width:100%;max-width:1140px;margin:0 auto;padding:0 max(20px,env(safe-area-inset-right)) 0 max(20px,env(safe-area-inset-left))}
.section{padding:64px 0}
/* desktop breathing room — whitespace reads as confidence (band-specific paddings live with their rules) */
/* v3.14c owner: "compact the entire site on browser" — desktop section rhythm
   tightened 92 -> 64 (guarantee/stance follow at 56). Mobile spacing untouched. */
@media (min-width:760px){.section{padding:64px 0}}
/* v3.11c owner: reviews ride closer to the trust band above (dead space there read empty) */
#reviews{padding-top:26px}
@media (min-width:760px){#reviews{padding-top:36px}}
.eyebrow{
  text-transform:uppercase;letter-spacing:.14em;font-size:.72rem;font-weight:700;
  color:var(--blue-deep);margin:0 0 .6em;
}
/* editorial rule marks around eyebrows */
.eyebrow::before{content:"";display:inline-block;width:26px;height:1px;background:currentColor;vertical-align:middle;margin-right:10px;opacity:.55}
.eyebrow.center::after{content:"";display:inline-block;width:26px;height:1px;background:currentColor;vertical-align:middle;margin-left:10px;opacity:.55}
.center{text-align:center}
.lead{font-family:var(--serif);font-size:1.13rem;color:var(--muted);line-height:1.7}
/* v3.11c owner: key lead paragraphs sit in a WHITE GLASS tab instead of floating on blue */
.lead-glass{
  background:linear-gradient(180deg,rgba(255,255,255,.72),rgba(255,255,255,.52));
  border:1.5px solid rgba(255,255,255,.85);border-radius:16px;padding:16px 20px;
  box-shadow:inset 0 1.5px 0 rgba(255,255,255,.95),0 0 12px rgba(46,159,242,.28),0 10px 24px -14px rgba(9,14,18,.25);
  color:var(--slate);
}
/* v3 audit fix (e): numbered, left-aligned section heads (How, Packages, Our Work) —
   a big serif marginal numeral beside the heading block; cadence varies section to section */
.sec-head{display:grid;grid-template-columns:auto 1fr;gap:0 16px;align-items:start;margin-bottom:30px}
@media (min-width:760px){.sec-head{gap:0 22px;margin-bottom:38px}}
.sec-num{font-family:var(--serif);font-weight:400;font-size:clamp(1.7rem,1.3rem+1.5vw,2.3rem);line-height:1;color:var(--blue);padding-top:2px}
.sec-head .eyebrow::before{display:none}
.sec-head h2{margin-bottom:.25em}
/* v3.11c owner: Our Work's head sits CENTERED above the installs, inside a hairline
   frame, instead of the left-numbered cadence */
.work .sec-head{
  display:block;text-align:center;width:fit-content;margin:0 auto 26px;
  border:1px solid rgba(46,159,242,.5);border-radius:14px;padding:14px 26px;
  background:rgba(255,255,255,.4);
}
.work .sec-num{display:none}
.work .sec-head h2{margin-bottom:0}

/* ---------- Buttons ---------- */
/* v3.2 EDGE-LIT GLASS (owner reference 2026-07-29 — SUPERSEDES the v3.1 frost-with-
   under-glow fills; the frost/spatial bones stay). The reference: a rounded glass tile
   on deep blue whose GLOW LIVES IN THE RIM — lit azure tubing tracing the edge, bloom
   radiating BOTH outward and inward, translucent body, soft top sheen, crisp label.
   Anatomy of every control (all glow in the #2E9FF2 azure family):
     rim   = 1.5px border, the sharp lit line
     bloom = outer glow (drop shadows) + inner glow (negative-spread inset shadows that
             hug the rim and die ~12px in — labels start ≥26px in, on clean body)
     body  = translucent fill, the ground reads through (frost blur kept; ONLY the
             url(#lg-dist) refraction pass stays banned on buttons — it smears the glow
             into mottling, see design-system v3.1)
     sheen = the ::after top-left specular sweep, z-index:-1, ALWAYS under the label
   Literal dark cut on dark grounds (final CTA, mobile bar); daylight cut on the paper.
   No gradient fills, no text-shadow. */
.btn{
  position:relative;overflow:hidden;
  display:inline-flex;align-items:center;justify-content:center;gap:.5em;
  font-family:var(--font);font-weight:700;font-size:1.02rem;line-height:1;
  padding:16px 26px;border-radius:14px;border:1.5px solid transparent;cursor:pointer;
  text-align:center;transition:filter .15s var(--ease),transform .15s var(--ease),box-shadow .15s var(--ease),background-color .15s var(--ease),border-color .15s var(--ease);
  will-change:transform;
}
/* NOTE (v3.1): a per-button refraction pseudo (backdrop-filter:url displacement) was
   built and REMOVED — it displaces the button's own under-glow shadow into visible
   mottling on the CTA fill. The liquid pass lives on the structural planes (header,
   mobile bar) only; buttons carry frost + specular + glow. Do not re-add without testing. */
/* specular sweep — curved glass catching light from the upper left.
   z-index:-1 keeps it above the button fill but UNDER the label (.btn's will-change
   makes a stacking context) — painting it over the text broke AA contrast. */
.btn::after{content:"";position:absolute;inset:0;border-radius:inherit;pointer-events:none;z-index:-1;
  background:linear-gradient(160deg,rgba(255,255,255,.3),rgba(255,255,255,.05) 38%,transparent 55%)}
/* DAYLIGHT primary (v3.2 edge-lit; body fill carried over from v3.1b — its math is
   proven): thin luminous azure glass, INK label, azure rim lit both ways.
   Contrast math (label = ink #12181D, luminance .0087; worst backdrop = pure black,
   e.g. floating over a dark panel): fill rgba(156,207,247,.66) blends to
   rgb(103,137,163), luminance .2342 = 4.84:1 AA. Over white it blends to
   rgb(189,223,250) = 12.7:1. Every real backdrop lands between those bounds.
   The inner azure bloom (inset, -8px spread, 18px blur) dies ~12px from the rim;
   the label starts 26px in, so it never sits on bloom. */
/* v3.13 (Ruling #11 audit): the .66 azure glass composited to rgb(156,208,248) over a
   mid-page ground of rgb(156,209,249) — a luminance ratio of 1.009, meaning the button had
   NO shape, only a rim and a glow. The fill is now opaque enough to be an object on any
   ground while keeping the edge-lit identity (rim, blooms, sheen all unchanged). Label
   flips to white: on this fill white reads ~5.6:1, ink would read ~3.6:1. */
.btn-primary{
  /* SOLID (designer's prescription): translucent glass could not hold a shape on the blue
     ground, and a .92 fill still left the white label at 4.35:1. Solid --cta puts white at
     4.65:1 and makes the primary ask unmistakable on every ground. The edge-lit identity
     lives in the rim, blooms and sheen below — no backdrop blur, since nothing shows
     through an opaque fill (also one less GPU pass on phones). */
  background:var(--cta);color:#fff;border-color:var(--blue);
  box-shadow:
    0 0 9px rgba(46,159,242,.55),0 0 26px -4px rgba(46,159,242,.5),
    0 12px 28px -16px rgba(24,119,201,.55),
    inset 0 0 8px rgba(255,255,255,.65),inset 0 0 18px -8px rgba(46,159,242,.75),
    inset 0 1px 0 rgba(255,255,255,.9);
}
.btn-primary:hover{
  border-color:#5CB6F5;transform:translateY(-1px);
  box-shadow:
    0 0 13px rgba(46,159,242,.7),0 0 32px -4px rgba(46,159,242,.6),
    0 14px 32px -16px rgba(24,119,201,.6),
    inset 0 0 10px rgba(255,255,255,.75),inset 0 0 20px -8px rgba(46,159,242,.85),
    inset 0 1px 0 rgba(255,255,255,.95);
}
/* DARK literal cut (final CTA band) — the owner's reference verbatim: deep translucent
   body showing the band through it, WHITE label, rim glowing hot.
   AA math: worst (lightest) composited backdrop = the band's radial high #16344A under
   body rgba(46,159,242,.12) -> rgb(25,65,94), luminance .0479 = 10.7:1 vs white; with
   the sheen's residual ~6% white at the label line -> rgb(39,76,104), .0660 = 9.0:1. */
.btn-ghost{
  background:rgba(46,159,242,.12);color:#fff;border-color:rgba(111,189,246,.9);
  -webkit-backdrop-filter:blur(12px) saturate(1.5);backdrop-filter:blur(12px) saturate(1.5);
  box-shadow:
    0 0 12px rgba(46,159,242,.6),0 0 34px -4px rgba(46,159,242,.55),
    inset 0 0 9px rgba(124,196,248,.45),inset 0 0 22px -8px rgba(46,159,242,.6),
    inset 0 1px 0 rgba(255,255,255,.5);
}
.btn-ghost:hover{
  border-color:#B7DDFB;background:rgba(46,159,242,.2);
  box-shadow:
    0 0 16px rgba(46,159,242,.75),0 0 40px -4px rgba(46,159,242,.65),
    inset 0 0 11px rgba(124,196,248,.55),inset 0 0 24px -8px rgba(46,159,242,.7),
    inset 0 1px 0 rgba(255,255,255,.6);
}
/* DAYLIGHT ghost — clear glass on the paper, INK label, rim still reads lit (dimmer
   bloom than the primary so the hierarchy holds). AA math: this variant only ever sits
   on light grounds (hero paper, the white EWG card): body rgba(255,255,255,.4) over the
   darkest of them (mist #F5F8FB) -> rgb(249,251,253), luminance .962 = 17.2:1 vs ink. */
.btn-ghost-dark{
  background:rgba(255,255,255,.4);color:var(--navy);border-color:rgba(46,159,242,.7);
  -webkit-backdrop-filter:blur(12px) saturate(1.6);backdrop-filter:blur(12px) saturate(1.6);
  box-shadow:
    0 0 8px rgba(46,159,242,.32),0 0 20px -6px rgba(46,159,242,.32),
    0 8px 20px -14px rgba(9,14,18,.28),
    inset 0 0 8px rgba(255,255,255,.6),inset 0 0 16px -8px rgba(46,159,242,.5),
    inset 0 1px 0 rgba(255,255,255,.9);
}
.btn-ghost-dark:hover{
  border-color:var(--blue);background:rgba(255,255,255,.58);
  box-shadow:
    0 0 11px rgba(46,159,242,.45),0 0 24px -6px rgba(46,159,242,.42),
    0 10px 24px -14px rgba(9,14,18,.32),
    inset 0 0 9px rgba(255,255,255,.7),inset 0 0 18px -8px rgba(46,159,242,.6),
    inset 0 1px 0 rgba(255,255,255,.95);
}
/* no backdrop-filter engine -> near-solid fills, same contrast guarantees:
   #BFE0FA vs ink = 13:1; the ghost's .16 azure over the band's #16344A high -> white 10:1.
   (The mobile bar's buttons keep their translucent fills — they composite over the bar's
   own solid fallback, which is darker than the blurred case, so contrast only climbs.) */
@supports not ((backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px))){
  /* v3.13: primary is solid now, so the no-blur fallback no longer needs a lighter fill —
     keeping it identical avoids a two-tone primary across engines */
  .btn-primary{background:var(--cta)}
  .btn-ghost{background:rgba(46,159,242,.16)}
  .btn-ghost-dark{background:#fff}
}
.btn-block{width:100%}
/* tap states are first-class on mobile — every press answers immediately, no hover needed */
.btn:active{transform:scale(.97)}
.btn-primary:active{filter:brightness(1.08)}
.btn-ghost-dark:active{border-color:var(--blue);background:rgba(255,255,255,.8)}
.btn-ghost:active{border-color:#D6ECFD;background:rgba(46,159,242,.26)}
.btn:focus-visible{outline:3px solid var(--blue);outline-offset:2px}
/* click-flash press state (JS toggles .is-flash) */
@keyframes btnflash{0%{filter:brightness(1.9);transform:scale(.94)}100%{filter:brightness(1);transform:scale(1)}}
.btn.is-flash{animation:btnflash .18s ease-out}

/* ---------- Header (light — v2.5 de-clone · v2.6 liquid glass) ---------- */
/* Liquid glass: saturated blur + refraction (Chromium takes the url() displacement pass,
   everyone else keeps the plain blur; no backdrop-filter at all -> solid white fallback). */
.site-header{
  position:sticky;top:0;z-index:40;
  /* v3.1b structural glass plane, retuned truer (owner re-order): thinner fill, deeper
     blur/saturation, crisp lit edges. AA floor: the fill never drops below .52 white, so
     even over a passing dark panel the backdrop blends to ≥ rgb(133,133,133) and the INK
     nav text holds ≥ 4.7:1 (slate failed this math — hence ink links below). */
  /* v3.9d owner: TRUE WINDOW — much thinner fill so content clearly shows through the
     pane, deeper blur+saturation, crisp lit edges top and bottom like real glass.
     (AA re-check at audit; nav links are already ink.) */
  /* v3.13 (Ruling #11 audit): restored to the fill's OWN documented .52 floor. The v3.9d
     "true window" thinning to .34/.22 put the ink nav at 2.0-3.1:1 over the five dark
     panels that pass beneath the header — a measured accessibility failure, and the pane
     had stopped reading as glass at all. Still far more transparent than the .84 original,
     so the window character survives. Never thin below .52 without redoing this math. */
  background:linear-gradient(180deg,rgba(255,255,255,.60),rgba(255,255,255,.52));
  -webkit-backdrop-filter:blur(34px) saturate(2.7);
  backdrop-filter:blur(34px) saturate(2.7);
  border-bottom:1px solid rgba(255,255,255,.55);
  box-shadow:inset 0 1.5px 0 rgba(255,255,255,.95),inset 0 -1.5px 0 rgba(255,255,255,.5),0 1px 20px -8px rgba(9,14,18,.28);
}
/* brand hairline: a thin azure line surfaces along the bottom edge once the header lands */
.site-header::after{
  content:"";position:absolute;left:0;right:0;bottom:-1px;height:2px;pointer-events:none;
  background:linear-gradient(90deg,var(--blue),var(--blue-deep));
  opacity:0;transition:opacity .25s var(--ease);
}
.hdr-scrolled::after{opacity:1}
/* refraction pass — Chromium-only enhancement; a silent no-op elsewhere */
.site-header::before{
  content:"";position:absolute;inset:0;z-index:-1;pointer-events:none;
  backdrop-filter:url(#lg-dist);
}
@supports not ((backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px))){
  .site-header{background:rgba(255,255,255,.97)}
}
/* Full-bleed header row (owner spec 2026-07-29): the logo hugs the site's left corner
   and the CTA the right — no 1140px cage; the nav floats centered between them. */
.header-row{
  display:flex;align-items:center;gap:18px;padding:12px max(18px,env(safe-area-inset-right)) 12px max(18px,env(safe-area-inset-left));
  max-width:none;
}
@media (min-width:980px){.header-row{padding-left:max(28px,env(safe-area-inset-left));padding-right:max(28px,env(safe-area-inset-right))}}
.brand{display:flex;align-items:center;flex:0 0 auto} /* never let flex crush the logo */
/* owner order 2026-07-29: larger logo — 56px on phones, 64px on desktop */
.brand-img{height:56px;width:auto;display:block}
@media (min-width:980px){.brand-img{height:64px}}
.brand-img-dark{height:56px;width:auto;display:block}
/* Editorial tabs: uppercase, letter-spaced, underline grows in from the left on hover */
/* v3.12c: five items now (Commercial joined) — nav tightened so the row still fits */
.nav{display:none;margin-left:auto;gap:22px}
/* ink (not slate) so the links hold AA through the thinner glass — see header math above */
.nav a{position:relative;color:var(--navy);font-weight:700;font-size:.77rem;letter-spacing:.09em;text-transform:uppercase;padding:8px 2px;white-space:nowrap}
.nav a::after{content:"";position:absolute;left:2px;right:100%;bottom:2px;height:2px;background:var(--blue);transition:right .25s var(--ease)}
.nav a:hover{color:var(--navy)}
.nav a:hover::after{right:2px}
/* v2.8 #9 — the underline answers on tap too, not just hover */
.nav a:active{color:var(--navy)}
.nav a:active::after{right:2px}
.header-cta{margin-left:auto;display:flex;align-items:center;gap:16px}
/* ink label (azure-deep fails AA through the thin glass over dark panels); azure border keeps the accent */
.se-habla{display:inline-block;color:var(--navy);font-weight:700;font-size:.8rem;border:1px solid rgba(24,119,201,.55);border-radius:6px;padding:6px 12px;white-space:nowrap}
/* v2.8 #9 — the lang pill presses like every other button */
.se-habla{transition:transform .12s var(--ease),background-color .15s var(--ease),border-color .15s var(--ease)}
.se-habla:active{transform:scale(.97)}
.header-phone{display:none;color:var(--navy);font-weight:700;font-size:1rem;align-items:center;gap:7px;white-space:nowrap;transition:color .15s var(--ease),opacity .12s var(--ease)}
.header-phone:active{opacity:.65}
.header-phone svg{width:16px;height:16px}
.header-phone:hover{color:var(--blue-deep)}
/* 44px+ target with the 1.5px rim. Shown only ≥1080px: between 760 and ~1050 the full
   header row (logo + nav + pill + phone + button) is wider than the viewport and the
   button was clipping/wrapping — the hero's identical CTA sits one glance below. */
.header-book{display:none;padding:13px 18px;font-size:.92rem;white-space:nowrap}
/* v3.4 compact Book square (760-1139px ONLY): the mobile bar leaves at 760 and the full
   .header-book joins at 1140 — this square keeps a persistent Book ask in between.
   Same daylight edge-lit material as .btn-primary (rim + blooms + sheen under content +
   @supports fallback all inherited); the icon is the logo's canonical drop (favicon.svg
   path) in INK. Contrast math (icon = ink #12181D, luminance .0087): worst theoretical
   backdrop is pure black under the .66 azure body -> rgb(103,137,163), luminance .2342
   = 4.84:1 (same proven floor as .btn-primary's label; ≥3:1 non-text AND ≥4.5:1 text
   both pass). Real case — header glass floor (.52 white over ink = rgb(141,144,147))
   under the body -> rgb(151,186,213) ≈ 8.6:1. Over white: 12.7:1. A white icon fails
   (1.4:1 over white-blended body), hence ink. 46px ≥44 target. */
.header-book-sq{display:none;width:46px;height:46px;padding:0;flex:0 0 auto}
.header-book-sq svg{width:19px;height:26px;display:block}
@media (min-width:760px) and (max-width:1139px){.header-book-sq{display:inline-flex}}
/* v2.8 #10 — the glass "lands": hairline + shadow deepen once scrolled (JS toggles .hdr-scrolled) */
.site-header{transition:opacity .25s var(--ease),box-shadow .25s var(--ease),border-color .25s var(--ease),transform .3s var(--ease)}
/* v3.9d owner: the header TUCKS AWAY on scroll down and returns on scroll up (JS toggles
   .hdr-hide; never hidden near the top of the page) */
.hdr-hide{transform:translateY(-104%)}
.hdr-scrolled{border-bottom-color:rgba(18,24,29,.18);box-shadow:inset 0 1.5px 0 rgba(255,255,255,.95),inset 0 -1px 0 rgba(255,255,255,.35),0 14px 32px -16px rgba(9,14,18,.45)}
/* v2.8 #1 — language dissolve: the page dims, text swaps, page returns. User toggles only
   (JS-driven; never fires on the initial saved-language apply). The mobile bar never dims. */
main,.site-footer{transition:opacity .25s var(--ease)}
body.lang-swap main,body.lang-swap .site-header,body.lang-swap .site-footer{opacity:.55;transition-duration:.15s}

/* ---------- Hero (v3 "Engraved waterline": FLAT paper, no photo background) ----------
   The water photo + white wash and the hero drift are gone (v3). The page's paper tone
   runs straight through; the only ornament is the engraved ripple SVG behind the framed
   owner portraits — the hero's single photo moment. */
.hero{position:relative;color:var(--slate);overflow:hidden}
.hero .wrap{position:relative;z-index:1}

/* v3.11 signature moment — THE LIGHT STREAK (owner reference: a neon light ribbon).
   Replaces the v3.7 wave curl. One glowing streak enters at the hero's TOP LEFT,
   does a LOOP-THE-LOOP mid-band, and exits BOTTOM RIGHT: three strokes on one path
   (wide azure glow, hot azure mid, near-white core — the edge-lit material as a
   moving line). The travel is a dash segment running the path (pathLength 1000,
   240-long comet). One run on load; still wakes the engraved waterline as it passes.
   z0 behind all hero content, pointer-events:none, JS-armed (.go), [hidden] without
   JS, dead under reduced motion, node removed after. Hairline-family strokes crossing
   type ride the established engraving precedent; the streak is transient (~2.4s). */
.hero-whoosh{position:absolute;inset:0;pointer-events:none;z-index:0;overflow:hidden}
.hw-streak{position:absolute;inset:-4% -2%;width:104%;height:108%}
.hw-streak svg{width:100%;height:100%;display:block}
.hw-glow{filter:blur(7px)}
.hw-streak path{
  fill:none;stroke-linecap:round;
  stroke-dasharray:240 1000;stroke-dashoffset:240;
}
.hero-whoosh.go .hw-streak path{animation:streak-run 2.4s cubic-bezier(.32,.08,.28,1) .05s both}
@keyframes streak-run{
  from{stroke-dashoffset:240}
  to{stroke-dashoffset:-1000}
}
/* v3.11b: the streak's WAKE — splash rings bloom along its path as it passes (JS-spawned,
   brighter and quicker than the ambient rings; the water reacts to the light) */
.hw-wake{position:absolute;inset:0;pointer-events:none;z-index:0;overflow:hidden}
.hw-wake span{position:absolute;width:130px;height:130px;transform:translate(-50%,-50%)}
.hw-wake span::before,.hw-wake span::after{
  content:"";position:absolute;inset:0;border-radius:50%;
  border:2px solid rgba(46,159,242,.9);
  opacity:0;transform:scale(.1);will-change:transform,opacity;
}
.hw-wake span::before{animation:amb-ring 1.15s var(--ease) forwards}
.hw-wake span::after{border-color:rgba(124,196,248,.7);animation:amb-ring 1.4s var(--ease) .12s forwards}
.hero .wrap{display:grid;grid-template-columns:1fr;gap:30px;padding-top:44px;padding-bottom:56px;align-items:center}
@media (min-width:760px){.hero .wrap{padding-top:56px;padding-bottom:64px;gap:34px}}
.hero-copy{min-width:0}
.hero h1{color:var(--navy);font-size:clamp(1.9rem,5.6vw,3.05rem);margin-bottom:.4em}
.hero h1 .accent{color:var(--blue-deep)}
.hero-sub{font-size:1.12rem;color:var(--slate);max-width:46ch;margin-bottom:1.4em}
.hero-sub b{color:var(--navy)}
.hero-cta{display:flex;flex-wrap:wrap;gap:12px;align-items:center}
/* mobile: both asks go full-width in the thumb zone */
@media (max-width:559px){.hero-cta .btn{width:100%}}
.hero-es{margin:.9em 0 0;color:var(--muted)}
.hero-trust{display:flex;flex-wrap:wrap;gap:10px 14px;align-items:center;margin-top:24px;padding-top:20px;border-top:1px solid var(--border)}
.hero-trust span{color:var(--muted);font-size:.9rem}
/* v3 audit fix (c): the score is a serif numeral + the Google mark — no unicode stars */
.ht-score{display:inline-flex;align-items:center;gap:8px}
.ht-score .score{font-family:var(--serif);font-weight:700;font-size:1.5rem;line-height:1;color:var(--navy)}
.ht-score .gmark{width:16px;height:16px;flex:0 0 auto}
.ht-txt{color:var(--muted);font-size:.9rem}
/* v2.6: certification marks read as small glass chips over the water photo */
.mini-badge{
  display:inline-flex;align-items:center;gap:6px;color:var(--slate);font-size:.82rem;font-weight:600;
  padding:7px 12px;border-radius:8px;border:1px solid rgba(18,24,29,.1);
  background:rgba(255,255,255,.55);
  -webkit-backdrop-filter:blur(10px) saturate(1.6);
  backdrop-filter:blur(10px) saturate(1.6);
  /* v3.1: same glass system as the buttons — lit edge + a whisper of float */
  box-shadow:inset 0 1px 0 rgba(255,255,255,.85),0 4px 10px -6px rgba(9,14,18,.14);
}
.mini-badge svg{width:15px;height:15px;color:var(--blue-deep)}

/* Owner photo frames (photo-print style) */
.hero-owners{position:relative;justify-self:center;width:100%;max-width:460px;min-width:0}
/* v3 engraved waterline — fine concentric ripple hairlines behind the frame.
   Decorative, low opacity; the .hero overflow clip fades the outer rings at the edges. */
.hero-ripples{
  position:absolute;left:50%;top:46%;width:158%;max-width:none;height:auto;
  transform:translate(-50%,-50%);pointer-events:none;z-index:0;
}
/* v3.5 OWNER ORDER — the engraved waterline LIVES. Sequential ring emphasis: a slow
   pulse travels outward through the concentric hairlines — each ring in turn swells
   ~40% brighter and +5% in scale, then settles, like water breathing after a drop.
   Applies to the hero engraving AND its phone strip echo (.hs-ripples).
   Engraving idiom intact: hairlines only, no fills, no gradient mesh. Transform +
   opacity only (multiplies the per-ring stroke-opacity grading, so the graded depth
   is preserved). .rip-live is JS-armed via IntersectionObserver ONLY while the
   ornament is on screen; without JS the engraving is simply static; dead under
   reduced motion (gated here AND never armed by JS). */
.hero-ripples circle,.hs-ripples circle{transform-box:view-box;transform-origin:50% 50%}
/* v3.8 owner: the big ripple moves CONSTANTLY — cycle halved, stagger tightened, so a
   pulse is always visibly traveling outward */
@media (prefers-reduced-motion:no-preference){
  .rip-live circle{animation:ring-breathe 3.2s var(--ease) infinite;animation-delay:calc(var(--ri,0)*.26s)}
}
.hero-ripples circle:nth-child(2),.hs-ripples circle:nth-child(2){--ri:1}
.hero-ripples circle:nth-child(3),.hs-ripples circle:nth-child(3){--ri:2}
.hero-ripples circle:nth-child(4),.hs-ripples circle:nth-child(4){--ri:3}
.hero-ripples circle:nth-child(5),.hs-ripples circle:nth-child(5){--ri:4}
.hero-ripples circle:nth-child(6),.hs-ripples circle:nth-child(6){--ri:5}
.hero-ripples circle:nth-child(7){--ri:6}
.hero-ripples circle:nth-child(8){--ri:7}
.hero-ripples circle:nth-child(9){--ri:8}
.hero-ripples circle:nth-child(10){--ri:9}
.hero-ripples circle:nth-child(11){--ri:10}
.hero-ripples circle:nth-child(12){--ri:11}
@keyframes ring-breathe{
  0%,42%,100%{opacity:.7;transform:scale(1)}
  12%{opacity:1;transform:scale(1.07)}
}
/* v3.6: the water whoosh WAKES the waterline as its crest passes — one brighter
   outward pulse (JS adds .rip-wake for ~1.5s, then removes it and the ambient
   breathe resumes). Sits AFTER the .rip-live rule on purpose: while both classes are
   present the wake's animation wins the cascade. Dead under reduced motion (media
   gate here AND the kill block's circle rule AND JS never runs the whoosh). */
@media (prefers-reduced-motion:no-preference){
  .rip-wake circle{animation:ring-wake 1s var(--ease) both;animation-delay:calc(var(--ri,0)*.06s)}
}
@keyframes ring-wake{
  0%{opacity:.72;transform:scale(1)}
  30%{opacity:1;transform:scale(1.07)}
  100%{opacity:.72;transform:scale(1)}
}
.owners-photo{position:relative;z-index:1;border-radius:4px;overflow:hidden;background:#fff;border:10px solid #fff;outline:1px solid var(--border);box-shadow:var(--shadow)}
.owners-duo{display:grid;grid-template-columns:1fr 1fr;gap:2px;aspect-ratio:16/10.5}
.owners-duo img{width:100%;height:100%;object-fit:cover;object-position:50% 22%;display:block}
.owners-pair{display:grid;grid-template-columns:1fr 1fr;gap:18px;max-width:520px;justify-self:center;width:100%}
.owners-pair figure{margin:0}
.owners-pair img{width:100%;aspect-ratio:4/5;object-fit:cover;object-position:50% 22%;border:8px solid #fff;outline:1px solid var(--border);border-radius:4px;box-shadow:var(--shadow);display:block}
.owners-pair figcaption{text-align:center;margin-top:9px;font-weight:700;color:var(--navy);font-size:.95rem}
.owners-caption{position:relative;z-index:1;display:flex;flex-direction:column;text-align:center;margin-top:14px;line-height:1.4}
.owners-caption b{font-family:var(--serif);color:var(--navy);font-size:1.15rem}
.owners-caption span{color:var(--muted);font-size:.88rem}

/* ---------- v3.4 phone hero recomposition (<560 ONLY; 560+ untouched) ----------
   Owner: the phone hero was copy-only — the portraits (the hero's visual anchor) sat
   below the first screen. On phones the big framed duo hides and a SIGNATURE STRIP
   (mini photo-print duo + caption, engraved ripples behind) lands directly under the
   CTAs, inside the 375x667 fold, right above the glass mobile bar. The copy block is
   tightened (padding/type) so BOTH CTAs stay above the fold. #owners still carries the
   full 4:5 portraits mid-page — phones lose zero content. */
.hero-sig{display:none}
@media (max-width:559px){
  .hero .wrap{padding-top:16px;gap:0}
  .hero h1{font-size:1.8rem}
  .hero-sub{font-size:1.05rem;margin-bottom:.9em}
  .hero-trust{margin-top:20px}
  /* the fold budget: both CTAs AND the strip inside 375x667 minus the mobile bar —
     hero buttons ease to 14px pads (~47px, still ≥44) to buy the strip its clearance */
  .hero-cta{gap:10px}
  .hero-cta .btn{padding-top:14px;padding-bottom:14px}
  .hero-owners{display:none} /* hands off to the strip; ripples echo in .hs-ripples */
  .hero-sig{position:relative;display:flex;align-items:center;gap:14px;margin-top:12px}
  .hs-ripples{
    position:absolute;left:56px;top:50%;width:340px;height:340px;
    transform:translate(-50%,-50%);pointer-events:none;z-index:0;
  }
  /* v3.4b (owner): the tiny duo read as thumbnails — ONE portrait at a time, big,
     crossfading every 4s (JS-driven), tap advances. Same photo-print frame idiom. */
  .hs-slider{
    position:relative;z-index:1;flex:0 0 auto;width:92px;aspect-ratio:4/5;
    background:#fff;border:4px solid #fff;outline:1px solid var(--border);border-radius:3px;
    box-shadow:var(--shadow);overflow:hidden;padding:0;cursor:pointer;
  }
  .hs-slider img{
    position:absolute;inset:0;width:100%;height:100%;object-fit:cover;object-position:50% 18%;
    opacity:0;transition:opacity .6s var(--ease);
  }
  .hs-slider img.on{opacity:1}
  /* v3.10d: the cursive name floats UNDER the picture box, syncing with the portrait */
  .hs-col{position:relative;z-index:1;flex:0 0 auto;display:flex;flex-direction:column;align-items:center;gap:2px}
  .hs-name{
    font-family:"Segoe Script","Brush Script MT",cursive;font-size:.74rem;line-height:1.1;
    color:var(--navy);text-align:center;
  }
  .hs-slider:focus-visible{outline:3px solid var(--blue);outline-offset:2px}
  .hs-cap{position:relative;z-index:1;display:flex;flex-direction:column;line-height:1.35;min-width:0}
  .hs-cap b{font-family:var(--serif);color:var(--navy);font-size:1.02rem}
  .hs-cap span{color:var(--muted);font-size:.78rem}
  /* (v3.6: the falling drops and their per-breakpoint aim sets are gone — the water
     whoosh needs no aiming; it sweeps the whole band behind the content layer) */
}

/* ---------- Guarantee certificate (v3: a FRAMED DARK PANEL on the paper desk) ----------
   The full-bleed ink band and its smoothing gradients are gone. The dark ink is now a
   contained, hairline-framed panel holding the cream certificate — a framed document. */
.guarantee{padding:56px 0}
@media (min-width:760px){.guarantee{padding:56px 0}}
.panel-dark{
  position:relative;background:var(--navy);color:#fff;border-radius:12px;
  border:1px solid rgba(9,14,18,.4);
  box-shadow:0 28px 56px -34px rgba(9,14,18,.55);
}
/* inner hairline frame — same document idiom as the certificate's inset rule */
.panel-dark::after{content:"";position:absolute;inset:10px;border:1px solid rgba(255,255,255,.13);border-radius:6px;pointer-events:none}
.panel-guarantee{max-width:880px;margin:0 auto;padding:34px 20px 38px}
@media (min-width:560px){.panel-guarantee{padding:52px 48px 56px}}
.cert{
  position:relative;max-width:660px;margin:0 auto;text-align:center;
  background:#FBF9F4;color:var(--slate);border-radius:8px;padding:32px 22px 20px;
  border:1px solid #E8E2D4;border-top:4px solid var(--blue-deep);
  box-shadow:0 24px 50px -24px rgba(0,0,0,.6);
}
@media (min-width:560px){.cert{padding:38px 36px 22px}}
/* inner hairline frame — reads as a printed document, not a web card */
.cert::after{content:"";position:absolute;inset:9px;border:1px solid #E6DFCC;border-radius:4px;pointer-events:none}
.cert-head{text-transform:uppercase;letter-spacing:.28em;font-size:.68rem;font-weight:700;color:var(--blue-deep);margin-bottom:16px}
.seal{width:54px;height:54px;margin:0 auto 12px}
.cert h2{color:var(--navy);font-family:var(--serif);font-weight:700;font-size:clamp(1.35rem,3.4vw,1.8rem);letter-spacing:-.01em;margin-bottom:.5em}
.cert p{font-size:1.02rem;color:var(--slate);max-width:50ch;margin:0 auto .3em}
.cert .es{color:var(--muted);margin-top:6px;font-size:.92rem}
.cert-signs{display:flex;justify-content:center;gap:32px;margin:22px auto 4px;max-width:420px}
@media (min-width:560px){.cert-signs{gap:52px}}
.sig{display:flex;flex-direction:column;align-items:center;min-width:118px}
.sig-name{font-family:"Segoe Script","Brush Script MT",cursive;font-size:1.4rem;color:var(--navy);line-height:1.1;transform:rotate(-2deg)}
.sig .sig-role{border-top:1px solid #C9C2B2;margin-top:5px;padding-top:5px;font-size:.68rem;letter-spacing:.14em;text-transform:uppercase;color:var(--muted);width:100%}
.cert-meta{margin-top:12px;padding-top:10px;border-top:1px solid #E8E2D4;font-size:.72rem !important;letter-spacing:.08em;color:var(--muted) !important}
/* v2.8 #4 — the certificate executes itself: seal ring + check draw in, dashed ring and
   banner surface, then the signatures land a beat later. One-time. JS arms .cert-anim
   (skipped without JS, under reduced motion, or if the cert starts in view) and .cert-go fires it. */
.cert-anim .seal-ring{stroke-dasharray:164;stroke-dashoffset:164}
.cert-anim .seal-check{stroke-dasharray:30;stroke-dashoffset:30}
.cert-anim .seal-dash,.cert-anim .seal-banner{opacity:0}
.cert-anim .sig{opacity:0;transform:translateY(6px);transition:opacity .45s var(--ease),transform .45s var(--ease)}
/* owner tune 2026-07-29: slowed to read as a ceremony — ring 1.4s, check after, sigs last */
.cert-go .seal-ring{animation:seal-draw 1.4s var(--ease) forwards}
.cert-go .seal-check{animation:seal-draw .7s var(--ease) 1.15s forwards}
.cert-go .seal-dash,.cert-go .seal-banner{opacity:1;transition:opacity .5s var(--ease) 1.6s}
.cert-go .sig{opacity:1;transform:none}
.cert-go .sig:nth-child(1){transition-delay:1.9s}
.cert-go .sig:nth-child(2){transition-delay:2.15s}
@keyframes seal-draw{to{stroke-dashoffset:0}}

/* ---------- Where we stand (typographic — deliberately no boxes, on the open paper) ---------- */
.stance{padding:56px 0}
@media (min-width:760px){.stance{padding:56px 0}}
.stance .eyebrow{margin-bottom:1.6em}
.stance-grid{display:grid;grid-template-columns:1fr;gap:30px;max-width:1020px;margin:0 auto}
.stance h3{font-family:var(--serif);font-weight:700;font-size:1.42rem;letter-spacing:-.01em;margin-bottom:.35em}
.stance p{color:var(--muted);margin:0;font-size:.98rem}

/* ---------- Independent data (EWG card on the open paper) ---------- */
.proof-grid{display:grid;grid-template-columns:1fr;gap:28px;align-items:center}
.retest-visual{background:#fff;border:1px solid var(--border);border-radius:var(--radius);padding:26px 24px 14px;box-shadow:var(--shadow)}
.rt-title{font-family:var(--serif);font-weight:700;color:var(--navy);font-size:1.05rem;margin-bottom:18px}
.rt-note{font-size:.78rem;color:var(--muted);font-style:italic;margin:10px 0 6px}
/* EWG summary + verify-it-yourself card */
.ewg-cta{padding:28px 28px 16px}
.ewg-hero{display:flex;align-items:center;gap:20px;margin:16px 0 18px}
.ewg-big{font-family:var(--serif);font-size:4.6rem;font-weight:700;color:var(--navy);line-height:1}
.ewg-big-side{display:flex;flex-direction:column;align-items:flex-start;gap:8px}
.ewg-caption{color:var(--slate);font-weight:600;font-size:1rem;max-width:24ch;line-height:1.4}
.ewg-stamp{display:inline-block;border:2px solid #B4622D;color:#B4622D;padding:4px 12px;border-radius:4px;font-weight:800;letter-spacing:.08em;text-transform:uppercase;font-size:.76rem;transform:rotate(-2deg)}
/* v2.8 #5 — stamp-in: ink hits paper once revealed (JS arms .stamp-anim on .ewg-cta, .stamp-go fires) */
/* owner tune 2026-07-29: bigger drop + slower hit so the stamp actually registers */
.stamp-anim .ewg-stamp{opacity:0;transform:rotate(-2deg) scale(1.45)}
.stamp-go .ewg-stamp{opacity:1;transform:rotate(-2deg) scale(1);transition:opacity .25s var(--ease) .2s,transform .6s cubic-bezier(.2,.9,.3,1.2) .2s}
.ewg-list{list-style:none;padding:0;margin:0 0 20px;display:grid;gap:8px;text-align:left}
.ewg-list li{position:relative;padding-left:18px;font-size:.95rem;color:var(--slate)}
.ewg-list li::before{content:"";position:absolute;left:0;top:.48em;width:8px;height:8px;border-radius:50%;background:#B4622D}
.ewg-link{width:100%;margin-bottom:6px}
.proof-copy h2{margin-bottom:.3em}

/* ---------- How it works ---------- */
/* de-boxed (v2.5): plain numbered columns with editorial top rules, on the open paper */
.steps{display:grid;grid-template-columns:1fr;gap:34px;margin-top:8px}
.step{position:relative;padding:18px 4px 0;border-top:2px solid var(--border)}
/* azure tick on each column's rule — implies sequence without arrows or cards */
.step::before{content:"";position:absolute;top:-2px;left:0;width:38px;height:2px;background:var(--blue-deep)}
.step .num{width:40px;height:40px;border-radius:50%;border:2px solid var(--navy);color:var(--navy);font-weight:800;display:flex;align-items:center;justify-content:center;font-size:1.05rem;margin-bottom:14px;font-family:var(--serif);background:#fff}
.step h3{font-size:1.2rem}
.step p{margin:0;color:var(--muted)}
/* (v3.1: the science accordion was removed by owner order — the x-ray carries the story) */

/* ---------- Value stack (v3: FRAMED DARK PANEL on the paper desk) ---------- */
.valuestack h2{color:#fff}
.valuestack .eyebrow{color:var(--blue)}
.panel-value{max-width:980px;margin:0 auto;padding:34px 22px 26px;text-align:left}
@media (min-width:760px){.panel-value{padding:48px 52px 38px}}
/* de-boxed (v2.5): a plain two-column checklist, no card bubbles — hairline rows for rhythm.
   v3 audit fix (d): the marker is a typographic azure rule tick, not the check SVG. */
.vs-grid{display:grid;grid-template-columns:1fr;gap:0 56px;margin:26px auto 0;max-width:860px}
.vs-item{display:flex;gap:13px;align-items:flex-start;padding:15px 0;border-top:1px solid rgba(255,255,255,.09)}
.vs-item::before{content:"";flex:0 0 18px;height:2px;background:var(--blue);margin-top:.72em}
.vs-item b{color:#fff;display:block}
.vs-item span{color:#B9C6D2;font-size:.92rem}

/* ---------- Packages (v3 audit fix (b): typographic comparison sheet) ----------
   One document object on the desk: white sheet, azure top rule (the certificate's mark),
   three tier columns divided by hairlines. No elevated center card, no gold ribbon,
   no per-card buttons — ONE dominant CTA under the sheet. NO prices, ever. */
.pkg-sheet{
  background:#fff;border:1px solid var(--border);border-top:4px solid var(--blue-deep);
  border-radius:8px;box-shadow:var(--shadow);margin-top:8px;
}
.pkg-grid{display:grid;grid-template-columns:1fr}
.pkg{position:relative;padding:26px 22px;display:flex;flex-direction:column;border-top:1px solid var(--border)}
.pkg:first-child{border-top:0}
@media (min-width:560px){.pkg{padding:30px 30px}}
.pkg-helper{color:var(--muted);margin:0;font-size:.98rem}
.pkg .tier{font-family:var(--serif);font-size:1.45rem;color:var(--navy);font-weight:700;margin-bottom:2px}
.pkg .tier-desc{color:var(--muted);font-size:.92rem;margin-bottom:14px}
@media (min-width:760px){.pkg .tier-desc{min-height:2.6em}}
.pkg .nodep{color:var(--blue-deep);font-weight:700;font-size:.85rem;margin-bottom:14px}
/* v3 audit fix (d): package features carry serif middot markers, not the check SVG */
.pkg ul{list-style:none;padding:0;margin:0 0 16px;display:grid;gap:8px}
.pkg li{position:relative;padding-left:16px;font-size:.95rem;color:var(--slate)}
.pkg li::before{content:"·";position:absolute;left:1px;top:-1px;color:var(--blue-deep);font-family:var(--serif);font-weight:700;font-size:1.25em;line-height:1.35}
/* care line: typographic, hairline-topped — no bubble */
.pkg .care{margin-top:auto;padding-top:12px;border-top:1px solid var(--border);font-size:.86rem;color:var(--muted)}
.pkg .care b{color:var(--navy)}

/* Signature: typographic emphasis only — azure small-caps flag, no ribbon, no elevation */
.pkg-flag{
  display:inline-block;align-self:flex-start;color:var(--blue-deep);
  font-weight:800;font-size:.68rem;letter-spacing:.16em;text-transform:uppercase;
  border:1px solid rgba(24,119,201,.45);border-radius:4px;padding:3px 9px;margin-bottom:10px;
}

/* Elite (gold accent — the only gold on the site) */
.pkg-elite .tier{color:#8a6d1f}
.pkg-elite li::before{color:var(--gold)}
.pkg-elite .nodep{color:#8a6d1f}
.pkg-cta-row{display:flex;justify-content:center;margin-top:26px}
.pkg-cta{min-width:min(100%,340px)}
.pkg-note{text-align:center;color:var(--muted);font-size:.9rem;margin-top:18px}

/* ---------- Reviews ---------- */
/* v3 audit fix (c): the Caslon numeral carries the badge — no unicode star row */
.reviews-badge{display:flex;flex-direction:column;align-items:center;text-align:center;gap:2px;margin-bottom:34px}
.rb-score{font-family:var(--serif);font-size:3.6rem;font-weight:700;color:var(--navy);line-height:1}
.rb-meta{color:var(--muted);font-weight:600;margin-top:6px}
.rb-google{display:inline-flex;align-items:center;gap:7px;margin-top:6px;color:var(--slate);font-weight:700;font-size:.9rem}
.rb-google svg{width:18px;height:18px}
.rev-sub{text-align:center;color:var(--muted);font-size:.95rem;margin:-8px 0 24px}
.rev-grid{display:grid;grid-template-columns:1fr;gap:18px}
.rev{position:relative;background:#fff;border:1px solid var(--border);border-radius:var(--radius);padding:22px}
.rev .rev-stars{color:#FFC542;letter-spacing:1px;margin-bottom:8px}
.rev .quote{font-family:var(--serif);color:var(--slate);font-style:italic;margin-bottom:14px}
.rev .quote::before{content:"\201C";display:block;font-family:var(--serif);font-size:2rem;line-height:.6;color:var(--blue);margin-bottom:6px}
.rev .who{display:flex;align-items:center;gap:10px}
.rev .avatar{width:34px;height:34px;border-radius:50%;background:var(--navy-card);color:#fff;display:flex;align-items:center;justify-content:center;font-weight:800;font-size:.9rem}
.rev .who b{color:var(--navy);font-size:.92rem;display:block;line-height:1.2}
.rev .who span{color:var(--muted);font-size:.8rem}
.rev-lang{position:absolute;top:20px;right:20px;font-size:.7rem;font-weight:700;letter-spacing:.06em;text-transform:uppercase;color:var(--blue-deep);border:1px solid var(--border);border-radius:6px;padding:2px 7px;background:#fff}

/* ---------- Meet the owners ---------- */
.owners-grid{display:grid;grid-template-columns:1fr;gap:30px;align-items:center}
.owners-photo-wide{aspect-ratio:16/11;width:100%;max-width:560px;justify-self:center}
.owners .lead{max-width:52ch}

/* ---------- Trust badges ---------- */
.trust-row{display:flex;flex-wrap:wrap;justify-content:center;align-items:center;gap:16px 44px}
/* de-boxed (v2.5): plain inline marks, no pill boxes */
.trust-badge{display:flex;align-items:center;gap:12px;padding:4px 0}
.trust-badge svg{width:30px;height:30px;flex:0 0 auto}
.trust-badge b{color:var(--navy);font-size:.92rem;display:block;line-height:1.2}
.trust-badge span{color:var(--muted);font-size:.78rem}

/* ---------- Final CTA (v3: the FIRST of exactly two full-bleed dark moments) ----------
   The light entry-ramp gradient is gone with the band system — the ask lands as a clean
   full-bleed cut from the paper page. */
.finalcta{position:relative;overflow:hidden;background:
  radial-gradient(900px 500px at 50% 0%,#16344A,transparent 60%),
  linear-gradient(180deg,#1A2530 0,var(--navy) 240px);
  color:#fff;text-align:center}
.finalcta .wrap{position:relative;z-index:1}
/* v2.6 living water — deep-ink-to-azure drift, barely perceptible. Static without JS
   (.flow-on is JS-armed and only set while the band is on screen); dead under reduced motion. */
.finalcta::before{
  content:"";position:absolute;inset:-45% -25%;pointer-events:none;
  background:
    radial-gradient(44% 34% at 30% 30%,rgba(46,159,242,.17),transparent 70%),
    radial-gradient(38% 30% at 72% 60%,rgba(24,119,201,.15),transparent 70%),
    radial-gradient(52% 44% at 56% 20%,rgba(22,52,74,.6),transparent 72%);
  will-change:transform;
}
@media (prefers-reduced-motion:no-preference){
  .finalcta.flow-on::before{animation:water-drift 36s ease-in-out infinite alternate}
}
@keyframes water-drift{
  0%{transform:translate3d(-2.5%,-1.5%,0) rotate(0deg) scale(1)}
  50%{transform:translate3d(2%,1.5%,0) rotate(2.2deg) scale(1.05)}
  100%{transform:translate3d(-1.2%,2.4%,0) rotate(-1.8deg) scale(1.02)}
}
.finalcta .eyebrow{color:var(--blue)}
.finalcta h2{color:#fff;font-size:clamp(1.7rem,4.4vw,2.4rem)}
.finalcta p{color:#D4E1EA;max-width:44ch;margin:0 auto 1.4em}
.finalcta .cta-row{display:flex;flex-wrap:wrap;gap:12px;justify-content:center;align-items:center}
.finalcta .speed{margin-top:16px;color:#9FB3C2;font-weight:600;font-size:.92rem;display:inline-flex;align-items:center;gap:8px}
.finalcta .speed svg{width:16px;height:16px}
.finalcta .es{color:#9FB3C2;margin-top:10px}
.finalcta .cta-alt{margin-top:16px}

/* Booking form (the converter — wired to GHL at launch) */
/* the converter carries the certificate's mark: same 4px azure top rule as the signed guarantee */
.book-form{max-width:560px;margin:10px auto 0;background:#fff;border-radius:12px;border-top:4px solid var(--blue-deep);padding:22px 18px;box-shadow:0 24px 50px -24px rgba(0,0,0,.6);text-align:left}
@media (min-width:560px){.book-form{padding:24px 22px}}
.bf-fields{display:grid;grid-template-columns:1fr;gap:14px;margin-bottom:16px}
.book-form label{display:flex;flex-direction:column;gap:6px;font-weight:700;font-size:.82rem;color:var(--navy);transition:color .15s var(--ease)}
/* inputs: 16px font (no iOS zoom), ≥48px touch height */
.book-form input[type=text],.book-form input[type=tel]{
  border:1px solid var(--border);border-radius:10px;padding:13px 15px;width:100%;min-height:48px;
  font-size:1rem;font-family:var(--font);color:var(--slate);background:var(--mist);
  transition:background-color .15s var(--ease),border-color .15s var(--ease); /* v2.8 #8 */
}
.book-form input:focus{outline:2px solid var(--blue);outline-offset:1px;background:#fff;border-color:var(--blue)}
/* v2.8 #8 — the field's label ticks azure while its input is focused */
.bf-fields label:focus-within{color:var(--blue-deep)}
/* v3.13 (Ruling #11): the segment + ownership fieldsets share the language fieldset's
   styling exactly — one form idiom, no new pattern */
.bf-lang,.bf-seg,.bf-own{border:0;padding:0;margin:0 0 14px}
.bf-lang legend,.bf-seg legend,.bf-own legend{font-size:.82rem;font-weight:700;color:var(--navy);padding:0;margin-bottom:2px}
.bf-lang label,.bf-seg label,.bf-own label{display:inline-flex;flex-direction:row;align-items:center;gap:9px;font-weight:600;color:var(--slate);font-size:1rem;margin-right:22px;padding:12px 0;min-height:44px}
.bf-lang input,.bf-seg input,.bf-own input{accent-color:var(--blue-deep);width:19px;height:19px;margin:0}
.bf-biz{margin:0 0 14px}
/* consent line: small, quiet, but present — the form takes a mobile number */
.bf-consent{font-size:.74rem;line-height:1.5;color:var(--muted);margin:12px 0 0}
.bf-consent a{color:var(--blue-deep);text-decoration:underline}
/* failed-send fallback: must out-shout the consent line, never lose a lead silently
   (.finalcta p would out-rank a bare class — match its specificity, same as .bf-success) */
.finalcta .bf-error,.bf-error{font-size:.9rem;line-height:1.5;color:#ffd7d2;background:rgba(178,58,44,.28);
  border:1px solid rgba(255,150,135,.5);border-radius:10px;padding:10px 14px;margin:12px 0 0}
.finalcta .bf-error a,.bf-error a{color:#fff;text-decoration:underline;font-weight:600}
.book-form button[type=submit]{min-height:54px}
/* success state: a real confirmation card, focusable for screen readers
   (.finalcta p would out-rank a bare class — match its specificity) */
.finalcta .bf-success,.bf-success{
  color:#14683F;font-weight:700;margin:4px 0 0;text-align:center;
  background:#EFF8F2;border:1px solid #BFE3D0;border-radius:10px;padding:18px 16px;
}
.bf-success:focus{outline:2px solid #1a7f4e;outline-offset:2px}
/* v2.8 #3 — the conversion moment: fields fade out (JS adds .bf-hide, then hides them),
   the confirmation card rises in, and the check draws itself — echoing the guarantee seal.
   Without JS or under reduced motion the check renders complete (no dash applied). */
.bf-fields,.bf-lang,.bf-seg,.bf-own,.bf-biz,.bf-consent,.book-form button[type=submit]{transition:opacity .15s var(--ease)}
.bf-hide .bf-fields,.bf-hide .bf-lang,.bf-hide .bf-seg,.bf-hide .bf-own,.bf-hide .bf-biz,.bf-hide .bf-consent,.bf-hide button[type=submit]{opacity:0}
.bf-check{width:20px;height:20px;vertical-align:-4px;margin-right:4px;display:inline-block}
.bf-success.bf-in{animation:bf-rise .25s var(--ease)}
.bf-success.bf-in .bf-check path{stroke-dasharray:24;stroke-dashoffset:24;animation:bf-draw .45s var(--ease) .2s forwards}
@keyframes bf-rise{from{opacity:0;transform:translateY(10px)}to{opacity:1;transform:none}}
@keyframes bf-draw{to{stroke-dashoffset:0}}

/* ---------- Footer ---------- */
.site-footer{background:var(--navy-deep);color:#9DAEBB;padding:52px 0 96px}
@media (min-width:760px){.site-footer{padding-top:64px}}
.footer-top{display:grid;grid-template-columns:1fr;gap:36px;align-items:start}
@media (min-width:760px){.footer-top{grid-template-columns:1.25fr .7fr .85fr;gap:40px}}
.footer-brand{display:flex;flex-direction:column;align-items:flex-start;gap:18px;color:#fff;font-weight:800;font-size:1.15rem}
.footer-brand .mark{width:30px;height:30px}
.footer-desc{margin:12px 0 0;max-width:34ch}
.footer-heading{color:#fff;font-weight:700;font-size:.74rem;letter-spacing:.14em;text-transform:uppercase;margin:0 0 12px}
.footer-nav{display:grid;gap:4px;justify-items:start}
.footer-nav a{color:#9DAEBB;font-weight:600;font-size:.95rem;padding:9px 0}
.footer-nav a:hover,.footer-nav a:active{color:#fff}
/* v2.8 #9 — footer links + contact answer the press */
.footer-nav a,.footer-contact a{transition:color .15s var(--ease),opacity .12s var(--ease)}
.footer-nav a:active,.footer-contact a:active{opacity:.65}
.footer-contact b{color:#fff}
.footer-contact a{color:#fff;font-weight:700}
.footer-contact .se-habla{display:inline-block;margin-top:10px;color:#9FB3C2;border:1px solid rgba(46,159,242,.5)}
.footer-note{margin-top:34px;padding-top:18px;border-top:1px solid rgba(255,255,255,.1);font-size:.8rem;color:#778894}

/* ---------- Sticky mobile bar (v2.6 liquid glass, dark) ---------- */
.mobile-bar{
  position:fixed;left:0;right:0;bottom:0;z-index:50;display:flex;gap:10px;
  padding:6px max(14px,env(safe-area-inset-left)) calc(6px + env(safe-area-inset-bottom)) max(14px,env(safe-area-inset-right));
  background:linear-gradient(180deg,rgba(13,18,23,.8),rgba(13,18,23,.72));
  -webkit-backdrop-filter:blur(22px) saturate(2);
  backdrop-filter:blur(22px) saturate(2);
  border-top:1px solid rgba(255,255,255,.18);
  box-shadow:inset 0 1.5px 0 rgba(255,255,255,.14),0 -14px 34px -22px rgba(0,0,0,.7);
}
/* refraction pass — Chromium-only enhancement; a silent no-op elsewhere */
.mobile-bar::before{
  content:"";position:absolute;inset:0;z-index:-1;pointer-events:none;
  backdrop-filter:url(#lg-dist);
}
@supports not ((backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px))){
  .mobile-bar{background:rgba(13,18,23,.97)}
}
/* v3.10d owner: smaller still — 38px buttons, tighter type. (Below the 44px target
   guideline by owner order; flag at audit.) */
.mobile-bar .btn{flex:1;min-height:38px;padding:8px 8px;font-size:.84rem}
/* v3.2 edge-lit, literal dark cut on the bar (owner reference ground = dark).
   AA math, WHITE labels: worst bar composite (white page behind the .8 bar) =
   rgb(61,65,69). Book: body rgba(46,159,242,.3) over it -> rgb(57,93,121),
   luminance .1008 = 7.0:1. Call: body .14 -> rgb(59,78,93), .0717 = 8.6:1.
   The no-blur fallback bar is near-solid rgb(19,24,28), so both climb past 10:1. */
.mobile-bar .btn-primary{
  background:rgba(46,159,242,.3);color:#fff;border-color:rgba(111,189,246,.95);
  box-shadow:
    0 0 10px rgba(46,159,242,.6),0 0 26px -4px rgba(46,159,242,.5),
    inset 0 0 9px rgba(124,196,248,.4),inset 0 0 20px -8px rgba(46,159,242,.55),
    inset 0 1px 0 rgba(255,255,255,.45);
}
.mobile-bar .btn-primary:active{background:rgba(46,159,242,.42)}
.mobile-bar .btn-call{
  background:rgba(46,159,242,.14);color:#fff;border-color:rgba(111,189,246,.65);
  box-shadow:
    0 0 8px rgba(46,159,242,.45),0 0 20px -6px rgba(46,159,242,.4),
    inset 0 0 8px rgba(124,196,248,.35),inset 0 0 16px -8px rgba(46,159,242,.45),
    inset 0 1px 0 rgba(255,255,255,.4);
}
.mobile-bar .btn-call:active{background:rgba(46,159,242,.26)}

/* ---------- Responsive ---------- */
@media (min-width:560px){
  .steps{grid-template-columns:repeat(2,1fr)}
  .rev-grid{grid-template-columns:repeat(2,1fr)}
  .trust-row{gap:22px}
  .bf-fields{grid-template-columns:1.3fr 1fr .7fr}
}
@media (min-width:900px){
  .steps{grid-template-columns:repeat(4,1fr)}
}
@media (min-width:760px){
  .mobile-bar{display:none}
  body{padding-bottom:0 !important}
  .nav{display:flex}
  .brand small{display:block}
  .hero .wrap{grid-template-columns:1.15fr .85fr}
  /* editorial column rules between the three statements — hairlines, not boxes */
  .stance-grid{grid-template-columns:repeat(3,1fr);gap:0}
  .stance-grid>div{padding:0 36px;border-left:1px solid var(--border)}
  .stance-grid>div:first-child{border-left:0;padding-left:0}
  .stance-grid>div:last-child{padding-right:0}
  .owners-grid{grid-template-columns:.95fr 1.05fr}
  .proof-grid{grid-template-columns:1.15fr .85fr}
  .vs-grid{grid-template-columns:1fr 1fr}
  /* the sheet's three tier columns divide with vertical hairlines (stacked rows on phones);
     the Signature flag floats in reserved headroom so all three tier names share a baseline */
  .pkg-grid{grid-template-columns:repeat(3,1fr)}
  .pkg{border-top:0;border-left:1px solid var(--border);padding-top:58px}
  .pkg:first-child{border-left:0}
  .pkg-flag{position:absolute;top:22px;left:30px;margin:0}
  .rev-grid{grid-template-columns:repeat(3,1fr)}
}

/* Header progressive disclosure (fixes a pre-existing 760-1050 clip: the full row is
   wider than the viewport there, and overflow-x:hidden was silently cutting the CTA).
   <760 mobile bar carries Call/Book · ≥900 the phone joins · ≥1140 the Book button joins. */
/* v3.12c: the 5th nav item ate the phone's room — phone now joins at 1240 (it lives in
   the hero, footer, and mobile bar regardless) */
@media (min-width:1240px){
  .header-phone{display:inline-flex}
}
@media (min-width:1140px){
  .header-book{display:inline-flex}
}
/* 760-1139: the row still runs tight — ease the nav gap. v3.4: the compact Book square
   adds ~62px, and at exactly 900 (the phone's entrance) the row clipped — tracking and
   gaps ease across the band so logo + nav + pill + phone + square all clear 900. */
@media (min-width:760px) and (max-width:1139px){
  .nav{gap:18px}
  .nav a{letter-spacing:.1em}
  .header-row{gap:14px}
  .header-cta{gap:12px}
}

/* ---------- Our Work (hotspot install photo + marquee, on the open paper) ---------- */
.wk-hint{color:var(--muted);font-size:.95rem;margin:0}
/* v2.9: photo + stage list. One column on phones (stages under the photo), side-by-side ≥900px */
.wk-grid{display:grid;grid-template-columns:1fr;gap:28px;justify-items:center}
@media (min-width:900px){
  .wk-grid{grid-template-columns:minmax(0,520px) minmax(260px,340px);justify-content:center;align-items:center;gap:44px}
}
/* v3.11 owner: the Solution figure sits in a GLASS TAB like the install slides —
   lit rim, azure bloom, translucent body; the photo (now cropped to just the shed)
   and all x-ray layers live in .spot-inner so zone percentages track the image box */
.spotfig{
  position:relative;margin:0;max-width:520px;width:100%;
  padding:10px;border-radius:18px;
  background:linear-gradient(180deg,rgba(255,255,255,.62),rgba(255,255,255,.4));
  border:1.5px solid rgba(255,255,255,.8);
  box-shadow:inset 0 1.5px 0 rgba(255,255,255,.95),0 0 12px rgba(46,159,242,.35),0 10px 24px -12px rgba(9,14,18,.3);
}
.spot-inner{position:relative;border-radius:11px;overflow:hidden}
.spot-inner>img{width:100%;height:auto;display:block}
.spotfig figcaption{text-align:center;color:var(--muted);font-size:.85rem;font-style:italic;margin-top:10px}

/* ---------- v3.1 X-RAY EVERYWHERE (owner order — the droplet hotspots are REMOVED) ----------
   Every equipment piece x-rays: main tank + brine tank carry locally-baked azure film
   crops of the branded cutaway; the valve (no cutaway art exists) gets a schematic line
   drawing in the same glow language. Hover/tap a piece: the photo dims, its film lights,
   ITS stage rows fade in beside the photo, and a pointer line connects part to copy.
   GPU budget: transform/opacity only. */
.xray-veil{
  /* covers the PHOTO only (3:4), not the caption below it — figure is taller than the img */
  position:absolute;left:0;top:0;width:100%;aspect-ratio:3/4;z-index:4;pointer-events:none;
  border-radius:var(--radius);
  background:radial-gradient(130% 95% at 64% 58%,rgba(9,14,18,.3),rgba(9,14,18,.62));
  opacity:0;transition:opacity .35s var(--ease);
}
.xray-veil.on{opacity:1}
.xray{
  position:absolute;z-index:5;pointer-events:none;overflow:hidden;
  background:#0A2338;border:1px solid rgba(46,159,242,.6);
  box-shadow:0 0 0 1px rgba(46,159,242,.18),0 0 30px rgba(46,159,242,.4),inset 0 0 22px rgba(46,159,242,.28);
  opacity:0;transition:opacity .3s var(--ease);
}
/* v3.11c: zones re-aimed to the TIGHTER shed crop (768x940, crop 705:863:55:40 of the
   original — newX=(oldXpx-55)/705, newY=(oldYpx-40)/863) */
.xray-main{left:52.3%;top:34.5%;width:24%;height:64%;border-radius:34% 34% 7% 7% / 8% 8% 3% 3%}
.xray-brine{left:28.3%;top:59.4%;width:22.9%;height:40.3%;border-radius:12% 12% 5% 5% / 7% 7% 3% 3%}
.xray-valve{left:52.9%;top:25.6%;width:19.5%;height:11.9%;border-radius:12px}
.xray-valve svg{width:100%;height:100%;display:block}
.xray-uv{left:35.7%;top:42.8%;width:13.2%;height:22.5%;border-radius:14px}
.xray-uv svg{width:100%;height:100%;display:block}
.xray.on{opacity:1}
/* the wipe: wrapper slides up-and-out, film slides down-into-place — pure transform reveal */
.xray-wipe{position:absolute;inset:0;overflow:hidden;transform:translateY(-101%);transition:transform .95s linear}
.xray-img{width:100%;height:100%;object-fit:cover;display:block;transform:translateY(101%);transition:transform .95s linear}
.xray.on .xray-wipe,.xray.on .xray-img{transform:none}
.xray-scan{
  position:absolute;left:4%;right:4%;top:0;height:3.5%;z-index:2;border-radius:999px;opacity:0;
  background:linear-gradient(180deg,rgba(120,200,255,0),rgba(170,224,255,.95),rgba(120,200,255,0));
  box-shadow:0 0 14px 3px rgba(46,159,242,.8);
}
@media (prefers-reduced-motion:no-preference){
  .xray.on .xray-scan{animation:xscan .95s linear both}
}
/* height 3.5% × 27.6 ≈ full frame travel; the bar dies just before the base */
@keyframes xscan{0%{opacity:0;transform:none}6%{opacity:1}86%{opacity:1}100%{opacity:0;transform:translateY(2760%)}}
/* valve schematic draws itself in — same one-shot draw idiom as the guarantee seal */
.xray-valve .xv-d,.xray-uv .xv-d{stroke-dasharray:100;stroke-dashoffset:100}
.xray-valve.on .xv-d,.xray-uv.on .xv-d{animation:xv-draw .6s var(--ease) .12s forwards}
.xray-valve.on .xv-d:nth-child(n+4),.xray-uv.on .xv-d:nth-child(n+4){animation-delay:.3s}
@keyframes xv-draw{to{stroke-dashoffset:0}}

/* hit zones — one per equipment piece */
.xray-hit{position:absolute;z-index:6;background:transparent;border:0;cursor:pointer;padding:0}
.xh-tank{left:50.6%;top:35.1%;width:27.5%;height:63.5%}
.xh-brine{left:26.5%;top:57.7%;width:25.8%;height:41.5%}
.xh-valve{left:51.1%;top:23.8%;width:22.9%;height:13.6%}
.xh-uv{left:32.8%;top:40.5%;width:17.7%;height:27.3%}
.xray-hit:focus-visible{outline:3px solid var(--blue);outline-offset:2px;border-radius:18px}
/* v3.10b owner: the magnifier chips sit centered ON their equipment piece */
.xray-chip{
  position:absolute;left:50%;top:50%;transform:translate(-50%,-50%);
  display:inline-flex;align-items:center;gap:6px;white-space:nowrap;
  color:#fff;font-weight:700;font-size:.78rem;padding:7px 11px;border-radius:9px;
  background:rgba(9,14,18,.55);border:1px solid rgba(46,159,242,.55);
  -webkit-backdrop-filter:blur(8px) saturate(1.5);backdrop-filter:blur(8px) saturate(1.5);
  box-shadow:0 0 0 4px rgba(46,159,242,.18);
  transition:opacity .25s var(--ease);
}
.xray-chip svg{width:13px;height:13px;color:var(--blue)}
.xray-chip-mini{padding:7px;border-radius:50%}
.xray-chip-mini svg{width:12px;height:12px}
/* the chips breathe — same pulse idiom, same clock */
@media (prefers-reduced-motion:no-preference){.xray-chip{animation:chip-pulse 2.6s ease-in-out infinite}}
@keyframes chip-pulse{0%,100%{box-shadow:0 0 0 4px rgba(46,159,242,.18)}50%{box-shadow:0 0 0 9px rgba(46,159,242,.1)}}
/* while any piece is lit, all chips get out of the way */
.spotfig.x-live .xray-chip{opacity:0}

/* Stage list — grouped per equipment piece. Fail-visible: the FULL grouped list renders
   without JS; JS arms .stg-armed so a group appears only while its piece is x-rayed. */
.wk-stages{width:100%;max-width:520px}
.wk-stages-head{font-family:var(--serif);font-weight:700;color:var(--navy);font-size:1.15rem;margin:0 0 6px}
.wk-idle{color:var(--muted);font-style:italic;font-size:.92rem;margin:0 0 10px}
.stg-title{font-family:var(--serif);font-weight:700;color:var(--blue-deep);font-size:.98rem;margin:16px 0 2px}
.stg-group:first-of-type .stg-title{margin-top:4px}
.stg{display:flex;gap:14px;align-items:flex-start;padding:13px 0;border-top:1px solid var(--border)}
.stg-num{
  flex:0 0 auto;width:30px;height:30px;border-radius:50%;border:2px solid var(--muted);color:var(--muted);
  font-family:var(--serif);font-weight:800;font-size:.9rem;display:flex;align-items:center;justify-content:center;
  background:#fff;
}
.stg-txt b{display:block;color:var(--navy);font-size:.95rem;line-height:1.3;margin-bottom:2px}
.stg-txt span{display:block;color:var(--muted);font-size:.88rem;line-height:1.5}
/* armed (JS, not under reduced motion): groups hide until their piece is lit, then the
   rows cascade in and their numerals ignite azure */
.stg-armed .stg-group{display:none}
.stg-armed .stg-group.g-on{display:block}
.stg-armed .stg-group.g-on .stg-title{margin-top:4px}
.stg-armed .stg-group.g-on .stg{animation:stg-in .5s var(--ease) both}
.stg-armed .stg-group.g-on .stg:nth-child(3){animation-delay:.15s}
.stg-armed .stg-group.g-on .stg:nth-child(4){animation-delay:.33s}
.stg-armed .stg-group.g-on .stg:nth-child(5){animation-delay:.51s}
.stg-armed .stg-group.g-on .stg .stg-num{color:var(--blue-deep);border-color:var(--blue-deep)}
@keyframes stg-in{from{opacity:0;transform:translateY(8px)}to{opacity:1;transform:none}}

/* pointer line: part → description (JS sets endpoints + --len; dash draws in) */
.wk-grid{position:relative}
.wk-lines{position:absolute;inset:0;width:100%;height:100%;pointer-events:none;z-index:7;overflow:visible}
.wk-lines line{
  stroke:var(--blue-deep);stroke-width:1.5;opacity:.8;
  stroke-dasharray:var(--len,0);stroke-dashoffset:var(--len,0);
  transition:stroke-dashoffset .45s var(--ease);
}
.wk-lines.on line{stroke-dashoffset:0}

.wk-sub{font-family:var(--serif);font-weight:700;color:var(--navy);font-size:1.35rem;margin:46px 0 18px}
/* Continuous install marquee (Illuminate-style). Base = plain swipeable strip
   (the no-JS / reduced-motion fallback); .is-marquee = JS doubled the set and the
   track slides forever, translateX(-50%) looping with no visible seam. */
/* v3.11 owner: the installs band sits between two editorial rails — a hairline above
   and below — so the glass slides aren't floating loose on the page */
.workcar-wrap{
  position:relative;overflow:hidden;
  border-top:1px solid rgba(46,159,242,.45);border-bottom:1px solid rgba(46,159,242,.45);
  padding:18px 0;
}
.workcar{
  display:flex;overflow-x:auto;-webkit-overflow-scrolling:touch;scrollbar-width:none;padding:4px;
}
.workcar::-webkit-scrollbar{display:none}
/* v3.10 owner: each install photo sits inside a GLASS rectangle with smooth angles —
   edge-lit frame (lit rim + azure bloom), translucent body, rounded photo inside.
   No backdrop-filter here: 14 slides in constant motion would be blur-over-motion cost;
   the translucent fill over the blue ground reads as glass at zero cost. */
.car-slide{
  flex:0 0 auto;width:min(240px,70vw);margin:0 16px 0 0;position:relative;
  padding:9px;border-radius:18px;overflow:hidden;
  background:linear-gradient(180deg,rgba(255,255,255,.62),rgba(255,255,255,.4));
  border:1.5px solid rgba(255,255,255,.8);
  box-shadow:inset 0 1.5px 0 rgba(255,255,255,.95),0 0 12px rgba(46,159,242,.35),0 10px 24px -12px rgba(9,14,18,.3);
}
@media (min-width:900px){.car-slide{width:280px}}
.car-slide img{width:100%;aspect-ratio:4/5;object-fit:cover;display:block;border-radius:11px}
.car-slide figcaption{position:absolute;left:0;right:0;bottom:0;padding:22px 12px 10px;color:#fff;font-size:.82rem;font-weight:700;background:linear-gradient(180deg,transparent,rgba(9,14,18,.78))}
@keyframes workcar-slide{
  from{transform:translateX(0)}
  to{transform:translateX(-50%)}
}
.workcar.is-marquee{
  overflow:visible;width:max-content;
  padding-left:0;padding-right:0; /* half-width loop must equal exactly one image set */
  animation:workcar-slide linear infinite;
  animation-duration:var(--cardur,40s);
}

/* ---------- Language droplet (every visit — v3.5: FROSTED + moved to bottom-left) ----------
   The bubble IS the drop: the logo's own drop path scaled up, with the wording and both
   buttons living inside the round belly. Two v3.5 owner orders:
   (a) FROSTED — the owner saw the hero headline ghosting through the glass body. A real
       frost layer (.lang-frost: white + backdrop-blur, clipped to the drop shape by
       #dropclip) now sits under the rim, so copy behind smears into light, never words.
       The edge-lit rim identity (sharp azure line + bloom + sheen) is unchanged.
   (b) MOVED LOWER — the drop docks bottom-left: above the mobile bar on phones, in the
       bottom corner on desktop. It no longer touches the headline or subhead. On the
       packed 375x667 fold the belly still overlaps the LEFT HALF of the secondary Call
       button + the signature strip until dismissed — deliberate: headline, subhead, and
       the PRIMARY Book CTA stay fully clear, and Call is duplicated in the never-covered
       mobile bar. The root is pointer-events:none (only the belly content accepts taps),
       so even the grazed zone stays clickable through the glass.
   AA (ink wording; worst backdrop = solid ink rgb(18,24,29), e.g. over a dark panel):
   frost .55 white -> rgb(148,151,154); the SVG body's .62 white over that ->
   rgb(214,215,217), luminance ~.68 = 12.4:1 vs ink. Espanol button body
   rgba(156,207,247,.6) over it -> rgb(179,210,235) ~ 11:1; English rgba(255,255,255,.42)
   -> ~13:1. Over clean paper everything sits higher. NOTE: the entrance drop-shadow
   lives on the SVG, NOT this root — a filter here would make .lang-pop a backdrop root
   and the frost's backdrop-blur would see nothing behind it. */
/* v3.5b owner revert: back to the TOP-LEFT corner under the header (the v3.5 frost and
   phone sizing stay — only the docking position returned) */
.lang-pop{
  position:fixed;left:12px;top:calc(100px + env(safe-area-inset-top));z-index:60;
  width:min(150px,42vw);aspect-ratio:18/25.5;
  pointer-events:none;
  animation:langdrip .45s cubic-bezier(.2,.9,.3,1.2) both;
}
@media (min-width:760px){.lang-pop{left:16px;width:min(190px,52vw)}}
.lang-frost{
  position:absolute;inset:0;
  -webkit-clip-path:url(#dropclip);clip-path:url(#dropclip);
  background:rgba(255,255,255,.55);
  -webkit-backdrop-filter:blur(18px) saturate(1.6);backdrop-filter:blur(18px) saturate(1.6);
}
/* no-blur engines: heavier white keeps the wording from reading through */
@supports not ((backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px))){
  .lang-frost{background:rgba(255,255,255,.82)}
}
@keyframes langdrip{
  from{opacity:0;transform:translateY(-14px) scale(.9)}
  to{opacity:1;transform:none}
}
/* v2.8 #11 — reverse drip on dismiss (JS adds .lang-out, sets hidden after it plays) */
.lang-pop.lang-out{animation:langout .25s var(--ease) both}
@keyframes langout{to{opacity:0;transform:translateY(-14px) scale(.9)}}
/* overflow:visible lets the rim's bloom breathe past the tight drop viewBox;
   the float shadow lives here (see the backdrop-root note above) */
.lang-drop-bg{position:absolute;inset:0;width:100%;height:100%;display:block;overflow:visible;
  filter:drop-shadow(0 16px 28px rgba(24,119,201,.32))}
.lang-pop-body{
  position:absolute;left:14.5%;right:14.5%;top:37%;bottom:11%;
  pointer-events:auto; /* the root is pointer-events:none — only the belly takes taps */
  display:flex;flex-direction:column;align-items:center;justify-content:center;gap:6px;text-align:center;
}
/* wording stays INK for AA — the droplet only ever floats over the light hero paper */
.lang-pop p{font-family:var(--serif);font-weight:700;color:var(--navy);font-size:1.1rem;margin:0;white-space:nowrap}
.lang-pop-btns{display:flex;flex-direction:column;gap:7px;width:100%}
.lang-pop-btns .btn{min-height:44px;padding:8px 6px;font-size:.84rem;border-radius:12px}
/* v3.2 edge-lit minis, INK labels (blue-deep fell to 4.47:1 on the v3.1 drop —
   reviewer 2026-07-29; ink stays). AA math on the ACTUAL composited backdrop: on
   phones the drop floats over hero TEXT, so worst case is solid ink rgb(18,24,29)
   behind the drop's .52 white body -> rgb(141,144,147). Español body
   rgba(156,207,247,.6) over that -> rgb(150,182,207) = 8.4:1 vs ink; English body
   rgba(255,255,255,.42) -> rgb(189,191,192) = 9.7:1. Over clean paper both sit
   at 13:1 to 17:1. AA holds everywhere. */
#langSi.btn{background:rgba(156,207,247,.6);color:var(--navy);font-weight:800;border:1.5px solid var(--blue);
  box-shadow:0 0 7px rgba(46,159,242,.5),inset 0 0 6px rgba(255,255,255,.6),
    inset 0 0 12px -6px rgba(46,159,242,.6),inset 0 1px 0 rgba(255,255,255,.85)}
#langNo.btn{background:rgba(255,255,255,.42);color:var(--navy);font-weight:700;border:1.5px solid rgba(46,159,242,.55);
  box-shadow:0 0 6px rgba(46,159,242,.3),inset 0 0 10px -6px rgba(46,159,242,.4)}
/* v3.5 phone cut: the drop is smaller so it clears the Book CTA above it — the belly
   tightens to keep both ≥44px buttons and the wording inside the glass */
@media (max-width:759px){
  .lang-pop-body{left:16%;right:16%;top:35%;bottom:9.5%;gap:4px}
  .lang-pop p{font-size:.88rem;line-height:1.25}
  .lang-pop-btns{gap:5px}
  .lang-pop-btns .btn{font-size:.78rem;padding:8px 4px;border-radius:10px}
}
.lang-toggle{cursor:pointer;background:transparent;font-family:var(--font)}
.lang-toggle:hover{border-color:var(--blue-deep);background:var(--mist)}
.footer-contact .lang-toggle:hover{background:rgba(255,255,255,.08)}
.fl{display:block}

/* Scroll reveal (JS-armed; fail-visible without JS, dead under reduced motion) */
.rv{opacity:0;transform:translateY(14px);transition:opacity .55s var(--ease),transform .55s var(--ease)}
.rv-in{opacity:1;transform:none}
/* v2.8 #6 — key grids cascade child-by-child, 60ms apart (JS-armed, one-time; JS removes
   the classes after the run so stylesheet transforms — Signature elevation, hover lifts —
   take back over). .rv-flat (packages) fades only: no transform fight with the elevated card. */
/* owner tune 2026-07-29: deeper rise + wider steps so the ripple actually reads */
.rv-kids>*{opacity:0;transition:opacity .7s var(--ease),transform .7s var(--ease)}
.rv-kids:not(.rv-flat)>*{transform:translateY(22px)}
.rv-kids.rv-in>*{opacity:1}
.rv-kids.rv-in:not(.rv-flat)>*{transform:none}
.rv-kids.rv-in>*:nth-child(2){transition-delay:.12s}
.rv-kids.rv-in>*:nth-child(3){transition-delay:.24s}
.rv-kids.rv-in>*:nth-child(4){transition-delay:.36s}
.rv-kids.rv-in>*:nth-child(5){transition-delay:.48s}
.rv-kids.rv-in>*:nth-child(6){transition-delay:.6s}
.rv-kids.rv-in>*:nth-child(n+7){transition-delay:.6s}

/* ---------- v3.12 BEFORE/AFTER WIPE (below the EWG proof) ----------
   The original Clarity Wipe (v2.5, recovered from git history) reborn as a HAND-DRIVEN
   comparison: the visitor drags the boundary between murky and clear. Control = a
   full-surface transparent range input (native drag/tap/arrow keys — keyboard access
   for free, whole surface far past 44px); the drawn handle (hairline + 44px glass
   knob) just follows --pos, pointer-events:none. USER-DRIVEN ONLY: no transitions, no
   idle motion — outside the motion ration by construction, nothing for reduced motion
   to kill. Fail-visible: without JS the input/handle/hint stay [hidden] and the split
   sits at the static 50% default, both halves + labels showing. The range is clamped
   6-94 so both labeled regions always exist (a corner tag never floats over the wrong
   half). AA (tags, white .72rem bold text on dark glass rgba(9,14,18,.6)): worst
   backdrop = the clear azure mid #4BB5E6 -> blended rgb(35,81,103), L .072 = 8.6:1 vs
   white; over the murky mid rgb(49,46,35) = 13:1. */
.ba-sec{padding-top:0}
.ba-box{max-width:640px;margin:0 auto}
.ba-title{font-family:var(--serif);font-weight:700;color:var(--navy);font-size:1.15rem;text-align:center;margin:0 0 4px}
.ba-hint{text-align:center;color:var(--muted);font-size:.88rem;margin:0 0 4px}
/* v3.14: real b-roll of the in-home test replaced the illustrated wipe (owner order).
   Vertical phone footage in the same glass frame the wipe used — max width keeps a
   9:16 video from towering on desktop. Slider styles below are retired with it. */
.ba-video{
  margin:8px auto 0;padding:10px;border-radius:18px;max-width:340px;
  background:linear-gradient(180deg,rgba(255,255,255,.62),rgba(255,255,255,.4));
  border:1.5px solid rgba(255,255,255,.8);
  box-shadow:inset 0 1.5px 0 rgba(255,255,255,.95),0 0 12px rgba(46,159,242,.35),0 10px 24px -12px rgba(9,14,18,.3);
}
.ba-vid{display:block;width:100%;aspect-ratio:9/16;object-fit:cover;border-radius:11px;background:#0d1418}

/* v3.14b: proof chips flanking the footage on desktop; 2x2 row under it on phones.
   Chips reuse the glass-card material; icons ride the azure accent. */
.ba-duo{display:flex;flex-direction:column;align-items:center;gap:14px}
.ba-side{list-style:none;display:grid;grid-template-columns:repeat(2,minmax(0,1fr));gap:10px;margin:0;padding:0;width:100%;max-width:640px}
.ba-fact{
  display:flex;align-items:center;gap:10px;padding:12px 14px;border-radius:14px;
  background:linear-gradient(180deg,rgba(255,255,255,.6),rgba(255,255,255,.38));
  border:1.5px solid rgba(255,255,255,.8);
  box-shadow:inset 0 1.5px 0 rgba(255,255,255,.95),0 8px 18px -12px rgba(9,14,18,.25);
  color:var(--navy);font-weight:600;font-size:.88rem;line-height:1.35;min-width:0;
}
@media (max-width:420px){.ba-fact{font-size:.8rem;padding:10px 11px;gap:8px}}
.ba-fact svg{flex:0 0 auto;width:21px;height:21px;color:var(--blue-deep)}
@media (min-width:900px){
  .ba-sec .ba-box{max-width:1100px}
  .ba-duo{display:grid;grid-template-columns:1fr 340px 1fr;align-items:center;gap:26px}
  .ba-side{grid-template-columns:1fr;width:230px;gap:16px}
  .ba-side-l{justify-self:end}
  .ba-side-r{justify-self:start}
  .ba-side-l .ba-fact{justify-content:flex-end;text-align:right;flex-direction:row-reverse}
  .ba-fact{font-size:.92rem;padding:14px 16px}
  .ba-video{margin-top:8px}
}

.ba-frame{
  margin-top:8px;padding:10px;border-radius:18px;
  background:linear-gradient(180deg,rgba(255,255,255,.62),rgba(255,255,255,.4));
  border:1.5px solid rgba(255,255,255,.8);
  box-shadow:inset 0 1.5px 0 rgba(255,255,255,.95),0 0 12px rgba(46,159,242,.35),0 10px 24px -12px rgba(9,14,18,.3);
}
/* v3.13 (Ruling #11 audit): the "before" half was mud-brown, which (a) introduced the only
   warm colour in the palette and (b) implied VISIBLY DIRTY tap water — a claim the EWG copy
   directly above it carefully declines to make. Hard water is scale and cloudiness, not
   sewage. Repainted as cool chalky limescale: honest to what a softener actually fixes, and
   inside the azure/ink palette. */
.ba-wipe{--pos:50%;position:relative;aspect-ratio:16/9;border-radius:11px;overflow:hidden;background:#9DA8AD}
.ba-half{position:absolute;inset:0}
/* untreated half — cloudy, chalky, scaled (illustration; labelled as such) */
.ba-before{background:linear-gradient(115deg,#C3CBCC,#A6B0B4 48%,#8C979C)}
.ba-before::after{content:"";position:absolute;inset:-12px;filter:blur(9px);background:
  radial-gradient(120px 80px at 26% 38%,rgba(255,255,255,.55),transparent 70%),
  radial-gradient(160px 100px at 70% 66%,rgba(120,132,138,.5),transparent 70%),
  radial-gradient(90px 60px at 55% 18%,rgba(235,240,241,.6),transparent 70%)}
/* clear half on top, clipped to the right of the boundary (original cw-clear family) */
.ba-after{background:linear-gradient(115deg,#8FD4F2,#4BB5E6 45%,#1F8FC9);clip-path:inset(0 0 0 var(--pos))}
.ba-after::after{content:"";position:absolute;inset:0;background:
  radial-gradient(120px 80px at 30% 30%,rgba(255,255,255,.5),transparent 60%),
  radial-gradient(160px 100px at 75% 70%,rgba(255,255,255,.28),transparent 60%)}
.ba-tag{
  position:absolute;top:12px;z-index:2;font-size:.72rem;font-weight:800;letter-spacing:.08em;
  text-transform:uppercase;color:#fff;background:rgba(9,14,18,.6);
  padding:5px 11px;border-radius:8px;border:1px solid rgba(255,255,255,.3);
}
.ba-tag-b{left:12px}
.ba-tag-a{right:12px;border-color:rgba(46,159,242,.85)}
.ba-handle{position:absolute;top:0;bottom:0;left:var(--pos);z-index:3;width:0;pointer-events:none}
.ba-handle::before{content:"";position:absolute;top:0;bottom:0;left:-1px;width:2px;background:rgba(255,255,255,.95);box-shadow:0 0 9px rgba(46,159,242,.85)}
/* the knob is edge-lit glass (white rim, azure bloom) — the button material as a grip */
.ba-knob{
  position:absolute;top:50%;left:0;transform:translate(-50%,-50%);
  width:44px;height:44px;border-radius:50%;display:flex;align-items:center;justify-content:center;
  color:#fff;background:rgba(9,14,18,.45);border:1.5px solid rgba(255,255,255,.9);
  -webkit-backdrop-filter:blur(8px) saturate(1.5);backdrop-filter:blur(8px) saturate(1.5);
  box-shadow:0 0 10px rgba(46,159,242,.65),0 0 24px -6px rgba(46,159,242,.5),inset 0 1px 0 rgba(255,255,255,.55);
}
.ba-knob svg{width:20px;height:20px}
.ba-range{
  position:absolute;inset:0;z-index:4;width:100%;height:100%;margin:0;padding:0;
  opacity:0;cursor:ew-resize;-webkit-appearance:none;appearance:none;background:transparent;
}
/* visible keyboard focus: the knob lights while the (invisible) slider is focused */
.ba-range:focus-visible ~ .ba-handle .ba-knob{outline:3px solid var(--blue);outline-offset:2px}
@supports not ((backdrop-filter:blur(1px)) or (-webkit-backdrop-filter:blur(1px))){
  .ba-knob{background:rgba(9,14,18,.75)}
}
.ba-note{text-align:center;margin-top:10px}

/* ---------- v3.12 COMMERCIAL (framed dark panel after Our Work) ----------
   Third ink document on the desk (guarantee -> value stack -> commercial): the dark
   rhythm deepens toward the final-CTA plunge. Panel-head cadence like the value stack
   (eyebrow + h2 inside the panel, no marginal numeral — 01-04 stay untouched).
   Points ride the value stack's hairline-row idiom (azure rule tick, no boxes).
   Text #B9C6D2 on ink #12181D ≈ 10:1; the CTA is the literal dark cut (.btn-ghost,
   white label — its documented worst-case math assumed a LIGHTER backdrop, so contrast
   only climbs on the flat ink panel). */
.panel-comm{max-width:880px;margin:0 auto;padding:34px 22px 32px}
@media (min-width:760px){.panel-comm{padding:48px 52px 44px}}
.panel-comm h2{color:#fff}
.panel-comm .eyebrow{color:var(--blue)}
.cm-lead{font-family:var(--serif);color:#B9C6D2;font-size:1.1rem;line-height:1.6;max-width:56ch;margin:0}
.cm-points{margin:20px 0 26px;max-width:640px}
.cm-point{display:flex;gap:13px;align-items:flex-start;padding:15px 0;border-top:1px solid rgba(255,255,255,.09)}
.cm-point::before{content:"";flex:0 0 18px;height:2px;background:var(--blue);margin-top:.72em}
.cm-point b{color:#fff;display:block}
.cm-point span{display:block;color:#B9C6D2;font-size:.92rem}
.cm-cta-row{display:flex}

@media (prefers-reduced-motion:reduce){
  .btn,.btn:active,.btn.is-flash{animation:none !important;transition:none !important;transform:none !important}
  .hs-slider img{transition:none !important} /* tap still switches, instantly; JS skips auto */
  .finalcta::before{animation:none !important}
  .xray-chip{animation:none !important}
  /* v3.7 water whoosh (curl + streams + roll) — dead under reduced motion (JS never
     arms .go either) */
  .hw-streak path{animation:none !important;opacity:0 !important}
  /* v3.7 living ground — candidate drifts stop (the static faint field stays; the
     default descent is static paint anyway), ambient ripples never render (JS never
     spawns them either) */
  .amb-ripples span::before,.amb-ripples span::after{animation:none !important;opacity:0 !important}
  /* v3.5 living waterline (+ the v3.6 .rip-wake pulse — same circles) — engraving goes
     fully static (JS never arms .rip-live either) */
  .hero-ripples circle,.hs-ripples circle{animation:none !important;opacity:1 !important;transform:none !important}
  .wk-lines line{transition:none !important}
  .stg-armed .stg-group.g-on .stg{animation:none !important}
  .xray-valve .xv-d,.xray-uv .xv-d{animation:none !important;stroke-dasharray:none !important;stroke-dashoffset:0 !important}
  .workcar.is-marquee{animation:none !important}
  .lang-pop{animation:none !important}
  .nav a::after{transition:none !important}
  .rv{opacity:1 !important;transform:none !important;transition:none !important}
  /* v2.8 additions — every new motion dies here (JS also skips arming under reduced motion) */
  main,.site-header,.site-footer,.se-habla,.header-phone,.footer-nav a,.footer-contact a,
  .nav a,.book-form input,.book-form label,.sig,
  .bf-fields,.bf-lang,.book-form button[type=submit],.rv-kids>*{transition:none !important}
  body.lang-swap main,body.lang-swap .site-header,body.lang-swap .site-footer{opacity:1 !important}
  .se-habla:active{transform:none !important}
  .rv-kids>*{opacity:1 !important;transform:none !important}
  .cert-anim .seal-ring,.cert-anim .seal-check{stroke-dasharray:none !important;stroke-dashoffset:0 !important;animation:none !important}
  .cert-anim .seal-dash,.cert-anim .seal-banner,.cert-anim .sig{opacity:1 !important;transform:none !important}
  .stamp-anim .ewg-stamp{opacity:1 !important;transform:rotate(-2deg) !important}
  .bf-success.bf-in{animation:none !important}
  .bf-success.bf-in .bf-check path{stroke-dasharray:none !important;stroke-dashoffset:0 !important;animation:none !important}
  .site-header::after{transition:none !important}
  .lang-pop.lang-out{animation:none !important}
  /* v2.9 x-ray — toggle still works, but instantly: no wipe, no scanline, no chip pulse,
     stages stay fully readable (JS never arms .stg-armed under reduced motion) */
  .xray,.xray-veil,.xray-wipe,.xray-img,.xray-chip,.stg,.stg-num{transition:none !important}
  .xray-wipe,.xray-img{transform:none !important}
  .xray-scan{animation:none !important;opacity:0 !important}
  .xray-chip{animation:none !important}
  .stg-armed .stg{opacity:1 !important;transform:none !important}
}

/* ============ FAQ (v3.15, owner-ordered 2026-08-05) ============
   Hairlines, not boxes — the same rule the rest of v3 follows (rounded bubble cards
   read as AI made, per the owner). Native <details> carries the open/close state, so
   there is no JS and no ARIA to keep in sync. */
.faq-wrap{max-width:820px}
.faq-list{margin-top:26px;border-top:1px solid var(--border)}
.faq-item{border-bottom:1px solid var(--border)}
.faq-item summary{
  list-style:none;cursor:pointer;position:relative;
  padding:18px 46px 18px 0;
  font-weight:700;font-size:1.02rem;line-height:1.4;color:var(--navy);
}
.faq-item summary::-webkit-details-marker{display:none}
/* chevron: rotates to point up when open */
.faq-item summary::after{
  content:"";position:absolute;right:16px;top:50%;width:10px;height:10px;
  border-right:2px solid var(--blue-deep);border-bottom:2px solid var(--blue-deep);
  transform:translateY(-70%) rotate(45deg);
  transition:transform .25s var(--ease);
}
.faq-item[open] summary::after{transform:translateY(-25%) rotate(-135deg)}
.faq-item summary:focus-visible{outline:2px solid var(--blue-deep);outline-offset:3px;border-radius:4px}
.faq-item summary:hover{color:var(--blue-deep)}
.faq-item p{margin:0;padding:0 46px 20px 0;color:var(--muted);max-width:68ch;line-height:1.65}
@media (max-width:640px){
  .faq-item summary{padding-right:38px;font-size:.98rem}
  .faq-item p{padding-right:8px}
}
@media (prefers-reduced-motion:reduce){.faq-item summary::after{transition:none}}


/* Honeypot field — off screen rather than display:none, because some bots skip inputs
   that are display:none. Never focusable, never announced. */
.bf-hp{position:absolute;left:-9999px;width:1px;height:1px;overflow:hidden}
