/* =====================================================================
   Pristine Bath Refinishing — landing page visual system
   Light and clean, because a bathroom is light and because this is a
   contractor a stranger has to trust enough to let into their house.
   White ground, navy voice, one warm CTA colour.

   Mobile first. Type sizes land on the Tailwind scale, spacing comes only
   from the approved tokens, radii follow inner = outer - gap, backgrounds
   are flat. The hero heading gradient is the single permitted gradient
   and it is on text.
   ===================================================================== */

:root {
  /* type scale */
  --text-xs: .75rem;   --lh-xs: 1rem;
  --text-sm: .875rem;  --lh-sm: 1.25rem;
  --text-base: 1rem;   --lh-base: 1.5rem;
  --text-lg: 1.125rem; --lh-lg: 1.75rem;
  --text-xl: 1.25rem;  --lh-xl: 1.75rem;
  --text-2xl: 1.5rem;  --lh-2xl: 2rem;
  --text-3xl: 1.875rem;--lh-3xl: 2.25rem;
  --text-4xl: 2.25rem; --lh-4xl: 2.5rem;
  --text-5xl: 3rem;    --lh-5xl: 1;
  --text-6xl: 3.75rem; --lh-6xl: 1;

  /* spacing — the only permitted values */
  --s-0:0; --s-25:2px; --s-50:4px; --s-75:8px; --s-100:12px; --s-200:16px;
  --s-300:24px; --s-400:32px; --s-500:40px; --s-600:48px; --s-700:64px;
  --s-800:80px; --s-900:96px;

  /* radius */
  --r-sm:2px; --r:4px; --r-md:6px; --r-lg:8px; --r-xl:12px;
  --r-2xl:16px; --r-3xl:24px; --r-4xl:32px; --r-full:9999px;

  /* palette
     Light, because a bathroom is light. The previous dark theme read as
     luxury tech, not as a local contractor you would let into your house,
     and every established company in this category is white with navy and
     a warm CTA. Being different here costs trust rather than buying it. */
  --bg:        #FFFFFF;
  --surface:   #F4F7F9;   /* cool porcelain */
  --surface-2: #E8EEF3;
  --line:      #CFDAE4;
  --line-2:    #C3CEd8;

  --ink:       #0B2033;   /* deep navy, not black: warmer and less harsh */
  --ink-2:     #33506A;
  --muted:     #566A7C;

  --brand:     #0E4C8A;   /* the trustworthy navy the category runs on */
  --brand-dark:#0A3A6B;
  --brand-soft:#E7F0F9;

  --chrome:    #0E4C8A;   /* links and focus follow the brand on light */
  --signal:    #C4470F;   /* CTA fill: white on this passes 4.5 */
  --signal-dark:#A33A0A;  /* CTA hover */
  --signal-ink:#8F3408;   /* the same warm as TEXT on a pale tint */
  --signal-dim:#FDF0E9;
  --ok:        #0F8A46;   /* dots, borders, icons (3:1 territory) */
  --ok-ink:    #0A6B36;   /* the same green as TEXT */
  --ok-dim:    #E8F5EE;

  /* One curve per job. ease-in is never used: it delays the first frame,
     which is exactly when the eye is watching. */
  --ease: cubic-bezier(.32,.72,0,1);          /* drawers, staged reveals */
  --ease-out: cubic-bezier(.23,1,.32,1);      /* enters, presses */
  --ease-io: cubic-bezier(.77,0,.175,1);      /* on-screen movement */

  /* Durations. High frequency stays under 150ms; nothing interactive
     goes over 300ms. */
  --t-press: 140ms;
  --t-hover: 150ms;
  --t-enter: 260ms;
  --t-stage: 400ms;
  --shell: 560px;
  --read: 680px;
}

/* ------------------------------------------------------------ reset */
*,*::before,*::after{box-sizing:border-box}
html{-webkit-text-size-adjust:100%;scroll-behavior:smooth;background:var(--bg)}
@media (prefers-reduced-motion:reduce){
  html{scroll-behavior:auto}
  *,*::before,*::after{animation-duration:.01ms!important;transition-duration:.01ms!important}
}
body{
  margin:0;background:var(--bg);color:var(--ink);
  font-family:Geist,ui-sans-serif,system-ui,-apple-system,"Segoe UI",sans-serif;
  font-size:var(--text-base);line-height:var(--lh-base);
  font-synthesis-weight:none;-webkit-font-smoothing:antialiased;
  overflow-x:hidden;
}
img,video{max-width:100%;display:block}
button,input,select,textarea{font:inherit;color:inherit}
h1,h2,h3,p{margin:0}
h1,h2,h3{font-weight:600;letter-spacing:-.025em;text-wrap:balance}
p{text-wrap:pretty}
a{color:inherit}
:focus-visible{outline:2px solid var(--chrome);outline-offset:3px;border-radius:var(--r)}

.skip{position:absolute;left:var(--s-100);top:-80px;z-index:100;background:var(--ink);
  color:#fff;padding:var(--s-75) var(--s-100);border-radius:var(--r-lg);
  font-weight:600;transition:top 300ms var(--ease)}
.skip:focus{top:var(--s-100)}
.sr{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;
  clip:rect(0 0 0 0);white-space:nowrap;border:0}

/* ----------------------------------------------------------- layout */
.wrap{width:100%;max-width:var(--shell);margin:0 auto;padding:0 var(--s-200)}
.wide{max-width:1040px}
/* Sections breathe. A landing page that runs its blocks together reads as
   one undifferentiated wall; the gap is what tells someone they have
   finished one idea and started the next. */
section{padding:var(--s-800) 0;position:relative}
@media (max-width:899px){ section{padding:var(--s-700) 0} }

/* ----------------------------------------------------------- header */
.hdr{position:sticky;top:0;z-index:40;background:rgba(255,255,255,.86);
  backdrop-filter:saturate(160%) blur(14px);border-bottom:1px solid var(--line)}
.hdr-in{max-width:1040px;margin:0 auto;padding:var(--s-100) var(--s-200);
  display:flex;align-items:center;justify-content:space-between;gap:var(--s-100)}
.logo{display:flex;align-items:center;gap:var(--s-75)}
.logo-mark{width:34px;height:34px;flex:none;display:grid;place-items:center;color:var(--brand)}
.logo-mark svg{width:30px;height:30px}
/* Wordmark: the name carries the weight, the category sits under it in
   small caps so the header states what the business actually does. */
.logo-word{display:flex;flex-direction:column;line-height:1.05}
.logo-word b{font-size:var(--text-base);font-weight:600;letter-spacing:-.02em;color:var(--ink)}
.logo-word em{font-style:normal;font-size:9px;font-weight:600;letter-spacing:.13em;
  text-transform:uppercase;color:var(--muted);margin-top:2px}
.call{display:inline-flex;align-items:center;gap:var(--s-50);font-size:var(--text-sm);
  font-weight:600;padding:var(--s-75) var(--s-100);border:1px solid var(--line-2);
  border-radius:var(--r-full);text-decoration:none;background:transparent;
  transition:background-color var(--t-hover) ease,border-color var(--t-hover) ease,color var(--t-hover) ease,transform var(--t-press) var(--ease-out)}

.call:active{transform:translateY(1px)}
.call svg{width:15px;height:15px}
.call[hidden]{display:none}

/* ------------------------------------------------------------- hero */
.hero{padding:var(--s-500) 0 var(--s-600);position:relative;isolation:isolate}

.hero h1{max-width:var(--read);font-size:var(--text-4xl);line-height:var(--lh-4xl);
  background:linear-gradient(90deg,#0B2033 0%,#4C6B85 100%);
  -webkit-background-clip:text;background-clip:text;color:transparent;
  margin-bottom:var(--s-100)}
@media (min-width:640px){.hero h1{font-size:var(--text-5xl);line-height:var(--lh-5xl)}}
.hero .sub{max-width:var(--read);font-size:var(--text-lg);line-height:var(--lh-lg);
  color:var(--muted);margin-bottom:var(--s-300)}

.rating{display:flex;align-items:center;gap:var(--s-75);margin-bottom:var(--s-200);flex-wrap:wrap}
.stars{display:inline-flex;gap:var(--s-25);color:#F5B841}
.stars svg{width:16px;height:16px}
.rating small{font-size:var(--text-sm);color:var(--muted)}

.chips{display:flex;flex-wrap:wrap;gap:var(--s-75);margin:0 0 var(--s-400);padding:0;list-style:none}
/* Staggered, because the sequence is what makes three claims read as
   three claims. The delay is set per chip at build time. `both` means a
   reduced-motion visitor still lands on the finished state. */
.chip{display:inline-flex;align-items:center;gap:var(--s-50);font-size:var(--text-sm);
  font-weight:500;padding:var(--s-50) var(--s-100);background:var(--surface);
  border:1px solid var(--line);border-radius:var(--r-full);color:var(--ink-2);
  animation:chipIn var(--t-enter) var(--ease-out) both}
@keyframes chipIn{from{opacity:0;transform:translateY(6px) scale(.96)}to{opacity:1;transform:none}}
.chip svg{width:14px;height:14px;color:var(--ok);flex:none}

/* ----------------------------------------------------------- funnel */
.funnel{border:1px solid var(--line-2);border-radius:var(--r-4xl);
  background:var(--surface);scroll-margin-top:var(--s-800);overflow:hidden;
  box-shadow:0 1px 2px rgba(11,32,51,.06),0 24px 48px -24px rgba(11,32,51,.24)}
/* 32px outer - 16px padding = 16px inner, which is what the inputs use */
.funnel-in{padding:var(--s-200)}
.funnel-head{display:flex;align-items:flex-start;gap:var(--s-100);margin-bottom:var(--s-200)}
.avatar{width:36px;height:36px;border-radius:var(--r-full);flex:none;display:grid;
  place-items:center;font-weight:600;font-size:var(--text-sm);
  background:var(--surface-2);color:var(--chrome);border:1px solid var(--line-2)}
.funnel-head p{font-size:var(--text-base);font-weight:500}
.funnel-head small{display:block;font-size:var(--text-sm);color:var(--muted)}

.thread{display:flex;flex-direction:column;gap:var(--s-100)}
.msg{max-width:88%;padding:var(--s-100) var(--s-200);font-size:var(--text-base);
  line-height:var(--lh-base);border-radius:var(--r-2xl);animation:rise var(--t-enter) var(--ease-out) both}
.msg.bot{align-self:flex-start;background:var(--surface-2);border-bottom-left-radius:var(--r);
  border:1px solid var(--line)}
.msg.me{align-self:flex-end;background:var(--brand);color:#fff;font-weight:500;
  border-bottom-right-radius:var(--r)}
/* Nothing in the world appears from nothing, so this starts from a
   position and a scale that already exist. */
@keyframes rise{from{opacity:0;transform:translateY(8px) scale(.98)}to{opacity:1;transform:none}}

.typing{display:inline-flex;gap:var(--s-50);align-items:center;padding:var(--s-100) var(--s-200)}
.typing i{width:6px;height:6px;border-radius:var(--r-full);background:var(--line-2);
  animation:blink 1.2s infinite}
.typing i:nth-child(2){animation-delay:.18s}
.typing i:nth-child(3){animation-delay:.36s}
@keyframes blink{0%,60%,100%{opacity:.35}30%{opacity:1}}

/* ----------------------------------------------------------- inputs */
.field{display:flex;gap:var(--s-75);margin-top:var(--s-200)}
.input{flex:1;min-width:0;padding:var(--s-200);font-size:var(--text-lg);font-weight:500;
  background:var(--bg);border:1px solid var(--line-2);border-radius:var(--r-2xl);
  color:var(--ink);transition:border-color var(--t-hover) ease,box-shadow var(--t-hover) ease}
.input::placeholder{color:#6A6F6D;font-weight:400}
.input:focus{outline:none;border-color:var(--chrome);box-shadow:0 0 0 3px rgba(159,216,255,.14)}
.input[inputmode="numeric"]{letter-spacing:.12em}
.input.bad{border-color:var(--signal);box-shadow:0 0 0 3px rgba(255,107,44,.16)}

.btn{display:inline-flex;align-items:center;justify-content:center;gap:var(--s-75);
  font-size:var(--text-base);font-weight:600;padding:var(--s-200) var(--s-300);
  min-height:52px;border:1px solid transparent;border-radius:var(--r-2xl);
  background:var(--signal);color:#fff;cursor:pointer;text-decoration:none;
  box-shadow:0 1px 2px rgba(11,32,51,.10),0 6px 16px -6px rgba(226,88,26,.44);
  transition:background-color var(--t-hover) ease,border-color var(--t-hover) ease,color var(--t-hover) ease,transform var(--t-press) var(--ease-out)}

.btn:active{transform:scale(.96)}
.btn[disabled]{opacity:.4;cursor:not-allowed;transform:none}
.btn svg{width:18px;height:18px}
.btn-full{width:100%}
.btn-ghost{background:transparent;color:var(--ink);border-color:var(--line-2)}

/* -------------------------------------------- call / text / quick form
   A direct path that does not run through the chat. Two full width
   buttons first, since a phone call or a text is the lowest-effort
   conversion there is, then the short form for anyone who wants a
   callback instead of talking right now. */
.quickform{background:var(--surface)}
.qf-wrap-max{max-width:560px}

/* The chat, docked to the side of the screen and closed by default. It is
   reachable from anywhere on the page and stands in front of nothing:
   the phone, the form and the calendar all sit in the page itself. */
.chatdock{position:fixed;right:var(--s-200);bottom:var(--s-200);z-index:60;
  width:min(370px,calc(100vw - var(--s-400)))}
.chatdock:not([open]){width:auto}
.chatdock .funnel{margin-top:var(--s-100);max-height:min(70svh,560px);
  display:flex;flex-direction:column;box-shadow:var(--shadow-lg,0 24px 60px -20px rgba(11,32,51,.45))}
.chatdock .funnel-in{overflow-y:auto;min-height:0}
/* Clears the sticky action bar on a phone. */
@media (max-width:899px){ .chatdock{bottom:calc(var(--s-800) + var(--s-100))} }

.chatwrap-open{display:flex;align-items:center;gap:var(--s-200);cursor:pointer;
  list-style:none;padding:var(--s-200);border:1px solid var(--line-2);
  border-radius:var(--r-3xl);background:var(--surface);
  box-shadow:var(--shadow,0 8px 24px -12px rgba(11,32,51,.4));
  transition:border-color var(--t-hover) ease}
/* Closed, it is just the bubble and the label. */
.chatdock:not([open]) .chatwrap-open small{display:none}
.chatdock:not([open]) .chatwrap-open b{font-size:var(--text-sm)}
/* On a phone the closed state shrinks to the bubble alone. A pill wide
   enough to read is a pill wide enough to sit on top of the phone
   number, and the number outranks the chat. */
@media (max-width:620px){
  .chatdock:not([open]) .chatwrap-open{width:52px;height:52px;padding:0;
    justify-content:center;border-radius:var(--r-full)}
  /* Hide the label, never the bubble or its presence dot. */
  .chatdock:not([open]) .chatwrap-open > span:not(.chatwrap-ico){position:absolute;
    width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0 0 0 0);
    white-space:nowrap;border:0}
}
.chatwrap-open::-webkit-details-marker{display:none}
.chatwrap-open:hover{border-color:var(--chrome)}
.chatwrap-open svg{width:22px;height:22px;color:var(--brand)}
/* Reads as a live channel, not a form: a presence dot on the bubble and a
   slow halo, both of which stop entirely under prefers-reduced-motion. */
.chatwrap-ico{position:relative;flex:none;display:grid;place-items:center;
  width:22px;height:22px}
.chatwrap-dot{position:absolute;top:-3px;right:-4px;width:10px;height:10px;
  border-radius:var(--r-full);background:var(--ok);border:2px solid var(--surface)}
.chatwrap-dot::after{content:"";position:absolute;inset:-3px;border-radius:var(--r-full);
  border:2px solid var(--ok);opacity:.65;animation:chatHalo 2s var(--ease) infinite}
@keyframes chatHalo{0%{transform:scale(.7);opacity:.7}70%,100%{transform:scale(1.7);opacity:0}}
.funnel-x{flex:none;margin-left:var(--s-75);width:34px;height:34px;padding:0;
  display:grid;place-items:center;cursor:pointer;
  background:transparent;border:1px solid var(--line-2);border-radius:var(--r-full);
  color:var(--muted);transition:background-color var(--t-hover) ease,color var(--t-hover) ease}
.funnel-x:hover{background:var(--surface-2);color:var(--ink)}
.funnel-x svg{width:16px;height:16px}
/* Only meaningful inside the dock; the funnel is not closable anywhere else. */
.funnel-x{display:none}
.chatdock .funnel-x{display:grid}

.chatwrap-live{color:var(--ok-ink);font-weight:600}
.chatwrap-live::before{content:"";display:inline-block;width:7px;height:7px;
  margin-right:5px;border-radius:var(--r-full);background:var(--ok);vertical-align:baseline}
@media (prefers-reduced-motion:reduce){.chatwrap-dot::after{animation:none;opacity:0}}
.chatwrap-open b{display:block;font-size:var(--text-base);font-weight:600}
.chatwrap-open small{display:block;margin-top:var(--s-25);
  font-size:var(--text-sm);color:var(--muted)}
.chatwrap[open] .chatwrap-open{margin-bottom:var(--s-200)}
.chatwrap .funnel{margin:0}

/* The arc of the job, stated on the footage. Three fixed labels, not a
   progress bar: the hero cycles several different clips and a bar that
   claimed "Before" over a finished-tub close-up would be a lie. */
.vstages{list-style:none;display:flex;align-items:center;gap:var(--s-50);
  margin:0 0 var(--s-200);padding:0;flex-wrap:wrap}
.vstages li{display:flex;align-items:center;gap:var(--s-50);
  font-size:var(--text-xs);line-height:var(--lh-xs);font-weight:600;
  letter-spacing:.08em;text-transform:uppercase;color:#fff;
  background:rgba(255,255,255,.16);border:1px solid rgba(255,255,255,.3);
  border-radius:var(--r-full);padding:var(--s-50) var(--s-100);
  backdrop-filter:blur(10px)}
.vstages li+li::before{content:"";width:0;height:0;margin-right:var(--s-25);
  border-top:4px solid transparent;border-bottom:4px solid transparent;
  border-left:5px solid rgba(255,255,255,.66)}
.vstages li:last-child{background:rgba(99,226,155,.22);border-color:rgba(99,226,155,.5)}

/* The lead card that shares the first screen with the footage: the phone
   number, then the four-field form, then text-a-photo. This is what used
   to be the ZIP-gated chat card. */
.herolead{background:var(--surface);border:1px solid var(--line-2);
  border-radius:var(--r-4xl);padding:var(--s-300);
  box-shadow:0 2px 4px rgba(11,32,51,.06),0 24px 60px -22px rgba(11,32,51,.42)}
.herolead .callnow{margin-top:0;max-width:none}
.herolead .qf-form{margin-top:var(--s-300);max-width:none}
.herolead-h{font-size:var(--text-lg);line-height:var(--lh-lg);font-weight:600;
  color:var(--ink)}
.herolead-h b{font-weight:600;color:var(--ok-ink)}
.herolead-sub{font-size:var(--text-sm);line-height:var(--lh-sm);color:var(--muted);
  margin-bottom:var(--s-100)}
.herolead .textphoto{margin-top:var(--s-200);max-width:none}
.textphoto--tight{padding:var(--s-200)}
.textphoto--tight .textphoto-ico{width:38px;height:38px}
.textphoto--tight .textphoto-ico svg{width:19px;height:19px}

/* The phone, at the size a 45+ visitor can read at arm's length without
   reaching for glasses. Tabular numerals so the digits do not jitter. */
.callnow{display:block;margin-top:var(--s-300);max-width:560px;
  padding:var(--s-300);border-radius:var(--r-3xl);text-decoration:none;
  background:var(--brand);color:#fff;
  box-shadow:0 1px 2px rgba(11,32,51,.10),0 10px 26px -10px rgba(14,76,138,.5);
  transition:background-color var(--t-hover) ease,transform var(--t-press) var(--ease-out)}
.callnow:active{transform:scale(.98)}
.callnow-k{display:flex;align-items:center;gap:var(--s-75);
  font-size:var(--text-xs);line-height:var(--lh-xs);font-weight:600;
  letter-spacing:.14em;text-transform:uppercase;color:rgba(255,255,255,.82)}
.callnow-k svg{width:16px;height:16px}
.callnow-n{display:block;margin:var(--s-50) 0;font-weight:600;
  font-size:clamp(2rem,8vw,2.75rem);line-height:1.06;letter-spacing:-.02em;
  font-variant-numeric:tabular-nums}
.callnow-s{display:block;font-size:var(--text-base);color:rgba(255,255,255,.9)}

.qf-form{margin-top:var(--s-200);max-width:560px}
.qf-form .f{margin-top:var(--s-100)}
/* Reassurance only. This line never rejects anyone: every valid ZIP that
   reaches this funnel is served. */
.qf-cover{display:flex;align-items:center;gap:var(--s-75);
  margin-top:var(--s-100);padding:var(--s-100) var(--s-200);
  border-radius:var(--r-2xl);background:var(--ok-dim);color:var(--ok-ink);
  font-size:var(--text-sm);line-height:var(--lh-sm);font-weight:500}
.qf-cover svg{width:16px;height:16px;flex:none;color:var(--ok)}

/* Text a photo. Warm, obvious, and the second largest block here. */
.textphoto{display:flex;align-items:center;gap:var(--s-200);flex-wrap:wrap;
  margin-top:var(--s-300);max-width:560px;padding:var(--s-300);
  border-radius:var(--r-3xl);text-decoration:none;color:var(--ink);
  background:var(--signal-dim,#FFF1E8);border:2px solid var(--signal);
  transition:background-color var(--t-hover) ease,transform var(--t-press) var(--ease-out)}
.textphoto:active{transform:scale(.98)}
.textphoto-ico{width:44px;height:44px;flex:none;border-radius:var(--r-full);
  background:var(--signal);color:#fff;display:grid;place-items:center}
.textphoto-ico svg{width:22px;height:22px}
.textphoto-txt{flex:1;min-width:0}
.textphoto-txt b{display:block;font-size:var(--text-base);line-height:var(--lh-base);
  font-weight:600;letter-spacing:.01em}
.textphoto-txt small{display:block;margin-top:var(--s-25);
  font-size:var(--text-sm);line-height:var(--lh-sm);color:var(--muted)}
.textphoto-save{flex:none;padding:var(--s-50) var(--s-100);border-radius:var(--r-full);
  background:var(--signal);color:#fff;font-size:var(--text-xs);font-weight:600;
  letter-spacing:.04em}

/* The four ways in, side by side. */
.qf-four{display:grid;gap:var(--s-75);grid-template-columns:repeat(2,1fr);
  margin-top:var(--s-300);max-width:560px}
@media (min-width:720px){.qf-four{grid-template-columns:repeat(4,1fr)}}
.qf-act{display:flex;flex-direction:column;align-items:center;justify-content:center;
  gap:var(--s-50);padding:var(--s-200) var(--s-75);min-height:76px;text-align:center;
  background:var(--bg);border:1px solid var(--line-2);border-radius:var(--r-2xl);
  color:var(--ink);text-decoration:none;font:inherit;cursor:pointer;
  transition:border-color var(--t-hover) ease,transform var(--t-press) var(--ease-out)}
.qf-act:active{transform:scale(.96)}
.qf-act svg{width:20px;height:20px;color:var(--brand)}
.qf-act b{font-size:var(--text-sm);line-height:var(--lh-sm);font-weight:600}

/* Trust, stated so the warranty and the lifespan can never be read as one
   number. */
.qf-trust{list-style:none;margin:var(--s-400) 0 0;padding:0;display:grid;
  gap:var(--s-100);max-width:640px}
.qf-trust li{display:flex;align-items:flex-start;gap:var(--s-75);
  font-size:var(--text-sm);line-height:var(--lh-sm);color:var(--muted)}
.qf-trust svg{width:17px;height:17px;flex:none;margin-top:2px;color:var(--ok)}
.qf-trust b{color:var(--ink);font-weight:600}
.qf-form select.input{appearance:none;-webkit-appearance:none;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='14' height='9' viewBox='0 0 14 9'%3E%3Cpath d='M1 1l6 6 6-6' stroke='%236A6F6D' stroke-width='2' fill='none' stroke-linecap='round'/%3E%3C/svg%3E");
  background-repeat:no-repeat;background-position:right var(--s-200) center;padding-right:var(--s-600)}
.qf-form .btn{margin-top:var(--s-200)}
.qf-note{margin-top:var(--s-100);text-align:center;font-size:var(--text-sm);
  font-weight:600;letter-spacing:.06em;color:var(--ok-ink)}
.qf-msg{margin-top:var(--s-100);font-size:var(--text-sm);font-weight:500;
  padding:var(--s-100);border-radius:var(--r-lg);background:var(--ok-dim);color:var(--ok-ink)}

.choices{display:grid;gap:var(--s-75);margin-top:var(--s-200)}
.choice{display:flex;align-items:center;gap:var(--s-100);width:100%;text-align:left;
  padding:var(--s-200);background:var(--bg);border:1px solid var(--line-2);
  border-radius:var(--r-2xl);cursor:pointer;color:var(--ink);
  transition:background-color var(--t-hover) ease,border-color var(--t-hover) ease,color var(--t-hover) ease,transform var(--t-press) var(--ease-out)}

.choice:active{transform:scale(.96)}
.choice-ico{font-size:var(--text-xl);line-height:1;flex:none}
.choice b{display:block;font-size:var(--text-base);font-weight:600}
.choice span{display:block;font-size:var(--text-sm);color:var(--muted)}

.banner{display:flex;align-items:flex-start;gap:var(--s-75);padding:var(--s-200);
  border-radius:var(--r-2xl);font-size:var(--text-base);font-weight:500;
  margin-top:var(--s-200);animation:rise var(--t-enter) var(--ease-out) both}
.banner.ok{background:var(--ok-dim);color:var(--ok-ink);border:1px solid rgba(52,211,153,.22)}
.banner svg{width:18px;height:18px;flex:none;margin-top:2px}

.offer{margin-top:var(--s-200);padding:var(--s-300);background:var(--signal-dim);
  border:1px solid rgba(255,107,44,.28);border-radius:var(--r-2xl)}
.offer b{display:block;font-size:var(--text-lg);color:var(--signal-ink);margin-bottom:var(--s-50)}
.offer p{font-size:var(--text-sm);color:var(--ink-2)}
.consent{margin-top:var(--s-100);font-size:var(--text-xs);line-height:var(--lh-xs);color:var(--muted)}
.consent a{color:var(--muted);text-decoration:underline}

.quote{margin-top:var(--s-200);padding:var(--s-300);border:1px solid var(--line);
  border-radius:var(--r-2xl);background:var(--bg)}
.quote-row{display:flex;align-items:baseline;justify-content:space-between;gap:var(--s-100)}
.quote-row+.quote-row{margin-top:var(--s-75)}
.quote-row span{font-size:var(--text-sm);color:var(--muted)}
.quote-row b{font-size:var(--text-base);font-weight:600}
.quote-total{border-top:1px solid var(--line);margin-top:var(--s-100);padding-top:var(--s-100)}
.quote-total b{font-size:var(--text-2xl);font-variant-numeric:tabular-nums}
.quote-total .off{color:var(--signal-ink)}
.was{text-decoration:line-through;color:var(--muted);font-weight:400;margin-right:var(--s-50)}

.slots{display:grid;gap:var(--s-75);margin-top:var(--s-200)}
.slot{display:flex;align-items:center;justify-content:space-between;gap:var(--s-100);
  padding:var(--s-200);text-align:left;border:1px solid var(--line-2);
  border-radius:var(--r-2xl);background:var(--bg);cursor:pointer;color:var(--ink);
  transition:background-color var(--t-hover) ease,border-color var(--t-hover) ease,color var(--t-hover) ease,transform var(--t-press) var(--ease-out)}

.slot:active{transform:scale(.96)}
.slot b{display:block;font-size:var(--text-base);font-weight:600}
.slot span{display:block;font-size:var(--text-sm);color:var(--muted)}
.slot em{font-style:normal;font-size:var(--text-sm);font-weight:600;color:var(--chrome);flex:none}

.proof-inline{margin-top:var(--s-200)}
.proof-inline p{font-size:var(--text-sm);color:var(--muted);margin-bottom:var(--s-75)}

.skel{border-radius:var(--r-2xl);background:var(--surface-2);animation:pulse 1.6s ease-in-out infinite}
.skel-slot{height:68px}
@keyframes pulse{0%,100%{opacity:1}50%{opacity:.5}}
.err{margin-top:var(--s-75);font-size:var(--text-sm);color:var(--signal-ink);font-weight:500}

/* -------------------------------------------------- before / after */
.ba{position:relative;border-radius:var(--r-2xl);overflow:hidden;
  outline:1px solid rgba(0,0,0,.1);outline-offset:-1px;
  background:var(--surface);aspect-ratio:4/3;touch-action:pan-y;cursor:ew-resize;
  user-select:none;-webkit-user-select:none}
.ba img{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}
.ba .after-img{clip-path:inset(0 0 0 var(--split,50%))}
.ba-handle{position:absolute;top:0;bottom:0;left:var(--split,50%);width:2px;
  background:#fff;box-shadow:0 0 12px rgba(0,0,0,.6);pointer-events:none}
.ba-handle::after{content:"";position:absolute;top:50%;left:50%;
  transform:translate(-50%,-50%);width:40px;height:40px;border-radius:var(--r-full);
  background:#fff;box-shadow:0 4px 16px rgba(0,0,0,.55)}
.ba-handle::before{content:"";position:absolute;top:50%;left:50%;
  transform:translate(-50%,-50%) rotate(45deg);width:11px;height:11px;z-index:1;
  border-right:2px solid #111;border-bottom:2px solid #111;margin-left:-4px}
.ba-tag{position:absolute;bottom:var(--s-75);font-size:var(--text-xs);font-weight:600;
  padding:var(--s-25) var(--s-75);border-radius:var(--r-full);letter-spacing:.06em;
  background:rgba(0,0,0,.72);color:#fff;backdrop-filter:blur(6px)}
.ba-tag.b{left:var(--s-75)} .ba-tag.a{right:var(--s-75)}

/* pair mode, for shots that were not photographed from the same spot */
.ba-pair{display:grid;grid-template-columns:1fr 1fr;gap:var(--s-75)}
.ba-pair figure{margin:0;position:relative}
.ba-pair img{width:100%;aspect-ratio:4/3;object-fit:cover;border-radius:var(--r-2xl);
  outline:1px solid rgba(0,0,0,.1);outline-offset:-1px}
.ba-pair figcaption{position:absolute;bottom:var(--s-75);left:var(--s-75);
  font-size:var(--text-xs);font-weight:600;padding:var(--s-25) var(--s-75);
  border-radius:var(--r-full);background:rgba(0,0,0,.72);color:#fff}

/* ------------------------------------------------------ video rail */
.rail{display:flex;gap:var(--s-200);overflow-x:auto;scroll-snap-type:x mandatory;
  padding-bottom:var(--s-100);margin:0 calc(var(--s-200) * -1);
  padding-left:var(--s-200);padding-right:var(--s-200);
  scrollbar-width:none}
.rail::-webkit-scrollbar{display:none}
.vid{position:relative;flex:0 0 72%;max-width:280px;scroll-snap-align:center;
  border-radius:var(--r-3xl);overflow:hidden;border:1px solid var(--line-2);
  background:var(--surface);aspect-ratio:9/16;cursor:pointer}
@media (min-width:720px){.vid{flex:0 0 30%}}
.vid video{width:100%;height:100%;object-fit:cover}
.vid-badge{position:absolute;top:var(--s-100);left:var(--s-100);font-size:var(--text-xs);
  font-weight:600;padding:var(--s-25) var(--s-75);border-radius:var(--r-full);
  background:rgba(0,0,0,.7);color:#fff;backdrop-filter:blur(6px);pointer-events:none}
.vid-sound{position:absolute;bottom:var(--s-100);right:var(--s-100);width:34px;height:34px;
  border-radius:var(--r-full);display:grid;place-items:center;background:rgba(0,0,0,.66);
  backdrop-filter:blur(6px);pointer-events:none}
.vid-sound svg{width:16px;height:16px;color:#fff}
.vid.is-unmuted .vid-sound{background:#fff}
.vid.is-unmuted .vid-sound svg{color:var(--ink)}

/* ------------------------------------------------- tagline reveal */
.reveal-line{max-width:var(--read);margin:0 auto;font-size:var(--text-3xl);
  line-height:1.2;font-weight:600;letter-spacing:-.025em}
@media (min-width:640px){.reveal-line{font-size:var(--text-4xl)}}
.reveal-line .w{color:rgba(11,32,51,.22);transition:color var(--t-stage) var(--ease-out)}
.reveal-line .w.on{color:var(--ink)}

/* --------------------------------------------------- steps / cards */
.h2{font-size:var(--text-2xl);line-height:var(--lh-2xl);margin-bottom:var(--s-300)}
.eyebrow{font-size:var(--text-xs);line-height:var(--lh-xs);letter-spacing:.16em;
  text-transform:uppercase;color:var(--chrome);margin-bottom:var(--s-75)}

.steps{display:grid;gap:var(--s-300);counter-reset:step}
.step{display:flex;gap:var(--s-200)}
.step-n{counter-increment:step;flex:none;width:32px;height:32px;border-radius:var(--r-full);
  display:grid;place-items:center;font-weight:600;font-size:var(--text-sm);
  background:var(--surface-2);color:var(--chrome);border:1px solid var(--line-2)}
.step-n::before{content:counter(step)}
.step b{display:block;font-size:var(--text-base);font-weight:600;margin-bottom:var(--s-50)}
.step p{font-size:var(--text-base);color:var(--muted)}

.cards{display:grid;gap:var(--s-200)}
@media (min-width:720px){.cards{grid-template-columns:repeat(2,1fr)}}
.card{padding:var(--s-300);border:1px solid var(--line);border-radius:var(--r-2xl);
  background:var(--surface)}
.card b{display:block;font-size:var(--text-base);font-weight:600;margin-bottom:var(--s-50)}
.card p{font-size:var(--text-sm);color:var(--muted);line-height:var(--lh-base)}

.prices{display:grid;gap:var(--s-100)}
.price{display:flex;align-items:center;justify-content:space-between;gap:var(--s-200);
  padding:var(--s-200) var(--s-300);border:1px solid var(--line);
  border-radius:var(--r-2xl);background:var(--surface)}
.price b{display:block;font-size:var(--text-base);font-weight:600}
.price small{display:block;font-size:var(--text-sm);color:var(--muted)}
.price em{font-style:normal;font-size:var(--text-xl);font-weight:600;white-space:nowrap;
  font-variant-numeric:tabular-nums;font-feature-settings:"tnum" 1}

.quotes{display:grid;gap:var(--s-200)}
.qcard{padding:var(--s-300);background:var(--surface);border-radius:var(--r-2xl);
  border:1px solid var(--line)}
.qcard p{font-size:var(--text-base);margin-bottom:var(--s-100)}
.qcard small{font-size:var(--text-sm);color:var(--muted)}

details.faq{border-bottom:1px solid var(--line);padding:var(--s-200) 0}
details.faq summary{display:flex;align-items:center;justify-content:space-between;
  gap:var(--s-200);cursor:pointer;list-style:none;font-size:var(--text-base);font-weight:600}
details.faq summary::-webkit-details-marker{display:none}
details.faq summary::after{content:"";flex:none;width:10px;height:10px;
  border-right:2px solid var(--muted);border-bottom:2px solid var(--muted);
  transform:rotate(45deg);transition:transform var(--t-stage) var(--ease-out)}
details.faq[open] summary::after{transform:rotate(-135deg)}
details.faq p{margin-top:var(--s-100);font-size:var(--text-base);color:var(--muted)}

/* ----------------------------------------------------------- footer */
.ftr{border-top:1px solid var(--line);padding:var(--s-500) 0 var(--s-900);background:var(--surface)}
.ftr strong{color:var(--ink)}
.ftr p,.ftr a{font-size:var(--text-sm);color:var(--muted)}
.ftr-links{display:flex;flex-wrap:wrap;gap:var(--s-200);margin-top:var(--s-100)}
.ftr-links a{text-decoration:underline}

/* ------------------------------------------------ sticky mobile CTA */
.sticky{position:fixed;left:0;right:0;bottom:0;z-index:50;
  padding:var(--s-100) var(--s-200) calc(var(--s-100) + env(safe-area-inset-bottom));
  /* Opaque. At .92 the page text scrolled visibly through the bar and
     collided with the button labels. */
  background:var(--bg,#fff);
  border-top:1px solid var(--line);display:flex;gap:var(--s-75);
  transform:translateY(110%);transition:transform var(--t-stage) var(--ease-out)}
.sticky.show{transform:none}
.sticky .btn{flex:1;min-height:50px;padding:var(--s-100) var(--s-75);font-size:var(--text-sm)}
@media (min-width:900px){.sticky{display:none}}
body.has-sticky{padding-bottom:var(--s-800)}

/* --------------------------------------------------- scroll reveals */
.rv{opacity:0;transform:translateY(16px);filter:blur(6px)}
.rv.in{opacity:1;transform:none;filter:blur(0);
  transition:opacity 600ms var(--ease-out),transform 600ms var(--ease-out),filter 600ms var(--ease-out)}

/* =====================================================================
   AD LAYER
   Video first, offer loud, chat unmistakably live, calendar to book.
   ===================================================================== */

/* ------------------------------------------------------ offer strip */
.offerbar{background:var(--signal);color:#fff;text-align:center;
  padding:var(--s-75) var(--s-200);font-size:var(--text-sm);font-weight:600}
.offerbar .rule{opacity:.72;font-weight:400}
/* Two wrapped lines of offer bar cost ~90px of the one screen that has to
   carry the video, the headline and the phone number. It stays, but on one
   compact line. */
@media (max-width:999px){
  .offerbar{padding:var(--s-50) var(--s-100);font-size:var(--text-xs);
    line-height:var(--lh-xs)}
}

/* ------------------------------------------------------- video hero */
/* Sized like a feed ad: edge to edge and tall enough that the footage is
   the page on a phone, not a banner sitting on top of one. The negative
   margin cancels the wrap padding so it goes truly full bleed. */
/* sizing lives in the AD SCALE block at the end of this file */
/* Holds the footage and everything that overlays it. Full bleed by
   default (desktop); on a phone the media query below turns it into a
   normal block so the copy can sit outside it. */
.vhero-media{position:absolute;inset:0}
.vhero video,.vhero-poster{position:absolute;inset:0;width:100%;height:100%;object-fit:cover}
/* Scrim, not a decorative background gradient: it exists so text over
   moving footage stays readable. */
/* Weighted to the bottom band only, where the copy actually sits. The top
   two thirds of the frame are left completely clean so the tub itself is
   what catches the eye — a scrim over the whole shot dims the one thing
   the page is selling. */
.vhero-scrim{position:absolute;inset:0;
  background:linear-gradient(to top,rgba(0,0,0,.88) 0%,rgba(0,0,0,.62) 22%,rgba(0,0,0,.18) 44%,rgba(0,0,0,0) 62%,rgba(0,0,0,0) 100%)}
/* Copy inside the video sits on footage, so it stays light regardless of
   the page being white. The gradient flips back to the dark-theme pair. */
.vhero-body{position:absolute;left:0;right:0;bottom:0;padding:var(--s-300)}
.vhero-body h1{background:linear-gradient(90deg,#FFFFFF 0%,#C7D3DD 100%);
  -webkit-background-clip:text;background-clip:text;color:transparent}
/* Scoped through #main on purpose: the page-wide `#main section p` rule
   carries an id and was beating the plain class here, which left the hero
   sub-copy dark slate on top of light footage — unreadable on exactly the
   screen the ad spend lands on. */
#main .vhero-body .sub{color:rgba(255,255,255,.9)}
#main .vhero-body .rating small{color:rgba(255,255,255,.82)}
.vhero-top{position:absolute;top:0;left:0;right:0;padding:var(--s-200);
  display:flex;align-items:flex-start;justify-content:space-between;gap:var(--s-100)}

.pricetag{display:inline-flex;align-items:baseline;gap:var(--s-75);
  background:#fff;color:var(--ink);padding:var(--s-75) var(--s-100);
  border-radius:var(--r-xl);font-weight:600;font-size:var(--text-lg);line-height:1}
.pricetag s{font-size:var(--text-sm);opacity:.5;font-weight:400}
.pricetag small{font-size:var(--text-xs);font-weight:500;opacity:.65}

.soundbtn{width:44px;height:44px;flex:none;border-radius:var(--r-full);
  border:1px solid rgba(255,255,255,.28);background:rgba(0,0,0,.5);
  backdrop-filter:blur(8px);color:#fff;display:grid;place-items:center;
  cursor:pointer;transition:background-color var(--t-hover) ease,border-color var(--t-hover) ease,color var(--t-hover) ease,transform var(--t-press) var(--ease-out)}

.soundbtn:active{transform:scale(.96)}
.soundbtn svg{width:20px;height:20px}
.soundbtn .on{display:none}
.is-unmuted .soundbtn .on{display:block}
.is-unmuted .soundbtn .off{display:none}
.is-unmuted .soundbtn{background:#fff;color:var(--ink);border-color:#fff}

/* A short nudge, because muted autoplay is the only kind a browser lets
   start on its own, so sound has to be asked for. */
.soundhint{position:absolute;top:var(--s-600);right:var(--s-200);
  font-size:var(--text-xs);font-weight:600;padding:var(--s-50) var(--s-75);
  border-radius:var(--r-full);background:rgba(0,0,0,.66);backdrop-filter:blur(8px);
  color:#fff;white-space:nowrap;animation:nudge 2.6s var(--ease) 1.2s 3 both}
.is-unmuted .soundhint{display:none}
@keyframes nudge{0%,100%{opacity:0;transform:translateX(6px)}18%,72%{opacity:1;transform:none}}

.vdots{position:absolute;bottom:var(--s-100);left:50%;transform:translateX(-50%);
  display:flex;gap:var(--s-50);z-index:2}
.vdots i{width:5px;height:5px;border-radius:var(--r-full);background:rgba(255,255,255,.34);
  transition:background-color var(--t-enter) ease,width var(--t-enter) var(--ease-out)}
.vdots i.on{background:#fff;width:16px}

/* --------------------------------------------------- live indicator */
.live{display:inline-flex;align-items:center;gap:var(--s-50);font-size:var(--text-xs);
  font-weight:600;color:var(--ok-ink)}
.live i{width:8px;height:8px;border-radius:var(--r-full);background:var(--ok);
  position:relative;flex:none}
.live i::after{content:"";position:absolute;inset:-4px;border-radius:var(--r-full);
  border:2px solid var(--ok);opacity:.55;animation:ping 1.9s var(--ease) infinite}
@keyframes ping{0%{transform:scale(.6);opacity:.7}70%,100%{transform:scale(1.5);opacity:0}}

/* The chat is the product here, so it gets the light. */
.funnel{border-color:rgba(15,138,70,.34);
  box-shadow:0 0 0 3px rgba(15,138,70,.08),
             0 1px 2px rgba(11,32,51,.06),
             0 24px 48px -24px rgba(11,32,51,.22)}
.funnel-head{align-items:center}
.avatar{position:relative;width:42px;height:42px;background:var(--ok-dim);
  color:var(--ok-ink);border-color:rgba(15,138,70,.30)}
.avatar::after{content:"";position:absolute;right:-1px;bottom:-1px;width:12px;height:12px;
  border-radius:var(--r-full);background:var(--ok);border:2px solid #fff}
.funnel-head p{font-weight:600}

/* --------------------------------------------------------- calendar */
/* 16px outer - 8px padding = 8px inner, matching .cal-day */
.cal{margin-top:var(--s-200);border:1px solid var(--line-2);border-radius:var(--r-2xl);
  background:var(--bg);padding:var(--s-75)}
.cal-head{display:flex;align-items:center;justify-content:space-between;margin-bottom:var(--s-100)}
.cal-head b{font-size:var(--text-base);font-weight:600}
.cal-nav{display:flex;gap:var(--s-50)}
.cal-nav button{width:32px;height:32px;border-radius:var(--r-lg);border:1px solid var(--line-2);
  background:transparent;color:var(--ink);cursor:pointer;display:grid;place-items:center;
  transition:background-color var(--t-hover) ease,border-color var(--t-hover) ease,color var(--t-hover) ease,transform var(--t-press) var(--ease-out)}

.cal-nav button[disabled]{opacity:.28;cursor:not-allowed}
.cal-nav svg{width:14px;height:14px}

.cal-dow{display:grid;grid-template-columns:repeat(7,1fr);gap:var(--s-25);margin-bottom:var(--s-50)}
.cal-dow span{text-align:center;font-size:var(--text-xs);color:var(--muted);padding:var(--s-25) 0}
.cal-grid{display:grid;grid-template-columns:repeat(7,1fr);gap:var(--s-25)}
.cal-day{aspect-ratio:1;border-radius:var(--r-lg);border:1px solid transparent;
  background:transparent;color:#A9B6C2;font-size:var(--text-sm);font-weight:500;
  display:grid;place-items:center;cursor:default;position:relative;
  transition:background-color var(--t-hover) ease,border-color var(--t-hover) ease,color var(--t-hover) ease}
.cal-day.open{color:var(--ink);border-color:var(--line-2);background:var(--surface-2);
  cursor:pointer;font-weight:600}

.cal-day.open::after{content:"";position:absolute;bottom:5px;left:50%;
  transform:translateX(-50%);width:4px;height:4px;border-radius:var(--r-full);background:var(--ok)}
.cal-day.sel{background:var(--brand);color:#fff;border-color:var(--brand)}
.cal-day.sel::after{background:#fff}
.cal-day.pad{visibility:hidden}

.wins{display:grid;gap:var(--s-75);margin-top:var(--s-200)}
.win{display:flex;align-items:center;justify-content:space-between;gap:var(--s-100);
  padding:var(--s-200);border:1px solid var(--line-2);border-radius:var(--r-2xl);
  background:var(--bg);color:var(--ink);cursor:pointer;text-align:left;
  transition:background-color var(--t-hover) ease,border-color var(--t-hover) ease,color var(--t-hover) ease,transform var(--t-press) var(--ease-out)}

.win:active{transform:scale(.96)}
.win b{display:block;font-size:var(--text-base);font-weight:600}
.win span{display:block;font-size:var(--text-sm);color:var(--muted)}
.win em{font-style:normal;font-size:var(--text-sm);font-weight:600;color:var(--ok-ink);flex:none}
.cal-empty{padding:var(--s-300);text-align:center;color:var(--muted);font-size:var(--text-sm)}

/* --------------------------------------------------- replace vs us
   The comparison the whole category sells on. Miracle Method leads with
   "replacement can cost $3,000 or more" and takes two to three days;
   this job is $299 and about two hours. Putting the two side by side is
   the single strongest argument on the page, so it gets its own block. */
.vs{display:grid;gap:var(--s-100)}
@media (min-width:640px){.vs{grid-template-columns:1fr 1fr;gap:var(--s-200)}}
.vs-col{border:1px solid var(--line);border-radius:var(--r-3xl);
  background:var(--surface);padding:var(--s-300)}
/* 24px outer - 8px gap = 16px inner */
.vs-col.win{border-color:rgba(52,211,153,.34);background:var(--ok-dim)}
.vs-h{display:flex;align-items:center;justify-content:space-between;gap:var(--s-100);
  margin-bottom:var(--s-200);padding-bottom:var(--s-100);
  border-bottom:1px solid var(--line)}
.vs-col.win .vs-h{border-bottom-color:rgba(52,211,153,.24)}
.vs-h b{font-size:var(--text-base);font-weight:600}
.vs-price{font-size:var(--text-2xl);font-weight:600;white-space:nowrap;
  font-variant-numeric:tabular-nums}
.vs-col.win .vs-price{color:var(--ok-ink)}
.vs ul{list-style:none;margin:0;padding:0;display:grid;gap:var(--s-75)}
.vs li{display:flex;align-items:flex-start;gap:var(--s-75);font-size:var(--text-sm);
  line-height:var(--lh-base);color:var(--ink-2)}
.vs li svg{width:15px;height:15px;flex:none;margin-top:3px}
.vs-col:not(.win) li svg{color:#B4553A}
.vs-col.win li svg{color:var(--ok-ink)}
.vs-note{margin-top:var(--s-200);font-size:var(--text-xs);line-height:var(--lh-xs);
  color:var(--muted)}


/* Hover only where there is a real pointer. On touch, :hover fires on
   tap and then stays stuck on the last thing tapped. */
@media (hover:hover) and (pointer:fine){
  .call:hover{background:var(--surface);border-color:var(--chrome);color:var(--chrome)}
  .btn:hover{background:var(--signal-dark);transform:translateY(-1px)}
  .btn-ghost:hover{background:var(--surface-2);border-color:var(--chrome);transform:none}
  .choice:hover{border-color:var(--chrome);background:var(--surface-2)}
  .slot:hover{border-color:var(--chrome);background:var(--surface-2)}
  .soundbtn:hover{background:rgba(0,0,0,.78);border-color:#fff}
  .cal-nav button:hover:not([disabled]){border-color:var(--chrome);background:var(--surface-2)}
  .cal-day.open:hover{border-color:var(--ok);background:var(--ok-dim)}
  .win:hover{border-color:var(--ok);background:var(--surface-2)}
}

/* ------------------------------------------------------- who we are */
.who-card{display:flex;gap:var(--s-300);align-items:center;padding:var(--s-300);
  border:1px solid var(--line);border-radius:var(--r-3xl);background:var(--surface)}
.who-card img{width:120px;height:120px;flex:none;border-radius:var(--r-full);
  object-fit:cover;outline:1px solid rgba(0,0,0,.1);outline-offset:-1px}
.who-card figcaption b{display:block;font-size:var(--text-lg);font-weight:600}
.who-card figcaption span{display:block;font-size:var(--text-sm);color:var(--muted);
  margin-bottom:var(--s-75)}
.who-card figcaption p{font-size:var(--text-sm);color:var(--ink-2);line-height:var(--lh-base)}
.who-empty{display:block}
.who-empty p{font-size:var(--text-base);color:var(--ink-2);line-height:var(--lh-lg)}
.who-empty p+p{margin-top:var(--s-75);font-size:var(--text-sm);color:var(--muted)}
.who-empty b{color:var(--ink)}


/* =====================================================================
   AD SCALE
   The complaint this block answers: the page read as a small widget
   floating in empty white. The fix is not more decoration, it is scale.
   The footage now opens the page at full height, the conversation
   overlaps it instead of sitting in a gap below it, and the sections
   underneath use the width they were being denied.
   ===================================================================== */

/* --------------------------------------------------------- the hero */
.hero{position:relative;isolation:isolate;padding:0}

/* Nearly the whole first screen on a phone. svh, not vh, so the mobile
   browser chrome cannot crop the bottom of the frame. */
/* Sized so the footage is still the dominant thing on the screen AND the
   phone number clears the fold underneath it. A full-height hero looked
   better and buried the number, which is the opposite of the job. */
.vhero{position:relative;margin:0;overflow:hidden;background:#0A0A0A;
  height:56svh;min-height:400px;max-height:620px}
@supports not (height:1svh){.vhero{height:56vh}}

.vhero-body{position:absolute;left:0;right:0;bottom:0;
  width:100%;max-width:var(--shell);margin:0 auto;
  padding:0 var(--s-200) var(--s-700)}
.vhero-kicker{display:inline-flex;align-items:center;font-size:var(--text-xs);
  line-height:var(--lh-xs);letter-spacing:.16em;text-transform:uppercase;
  font-weight:600;color:rgba(255,255,255,.72);margin-bottom:var(--s-100)}
.vhero-body h1{max-width:var(--read);font-size:var(--text-4xl);line-height:var(--lh-4xl);
  margin-bottom:var(--s-100)}
@media (min-width:640px){.vhero-body h1{font-size:var(--text-5xl);line-height:var(--lh-5xl)}}
.vhero-body .sub{max-width:36ch;font-size:var(--text-lg);line-height:var(--lh-lg);
  margin-bottom:var(--s-200)}
.vhero-body .rating{margin-bottom:var(--s-200)}
/* On a phone the first screen has to carry the footage, the headline, the
   stage strip AND the phone number. The sub-line, the rating row and the
   chips all repeat further down the page, so they yield here rather than
   pushing the number under the fold. */
/* ---------------------------------------------------- phone hero
   On a phone the copy comes OFF the footage entirely. No scrim, no text
   on top: the clip plays clean, which is the whole point of filming real
   work. Order is headline -> video -> lead card, so the form sits as high
   as it can while the tub is still the thing that catches the eye. */
@media (max-width:999px){
  .vhero{height:auto;min-height:0;max-height:none;background:transparent;
    display:flex;flex-direction:column;overflow:visible}

  .vhero-body{position:static;order:1;padding:var(--s-200) var(--s-200) var(--s-100)}
  /* Square crop, capped in svh. The cap is what keeps the phone number
     above the fold: measured against the sticky bar, 44svh is the largest
     the footage can be on a 390x844 phone with the number still clearing
     it. The aspect ratio makes it big; the cap makes it safe. */
  /* width:100% and align-self are load-bearing, not belt-and-braces.
     With only aspect-ratio + max-height, Safari honours the ratio by
     shrinking the WIDTH once max-height clamps the box — so the footage
     came out narrow and flush left instead of full width. Pinning the
     width makes the ratio govern height only; object-fit:cover on the
     video handles the crop when max-height bites. */
  .vhero-media{position:relative;order:2;overflow:hidden;
    width:100%;align-self:stretch;
    aspect-ratio:1/1;max-height:45svh;border-radius:var(--r-3xl)}
  /* The offer bar and the call block both give a little so the footage can
     take the space instead. The number stays the biggest text on screen. */
  .callnow{padding:var(--s-200) var(--s-300)}
  .callnow-n{font-size:clamp(1.9rem,8.5vw,2.5rem);margin:0}
  .callnow-s{font-size:var(--text-sm)}
  .vhero-kicker{display:none}
  /* Nothing over the footage on a phone. */
  .vhero-scrim{display:none}

  /* The copy is on the page background now, so it takes page colours. */
  .vhero-body h1{background:none;-webkit-text-fill-color:currentColor;
    color:var(--ink);font-size:var(--text-2xl);line-height:var(--lh-2xl);
    margin-bottom:0}
  .vstages{margin-bottom:var(--s-100)}
  .vhero-kicker{color:var(--muted)}
  #main .vhero-body .sub{color:var(--muted)}
  /* The sub-line goes (it repeats below); the rating and the trust chips
     stay, because the durability figure and the rating are first-screen
     content. Both compressed to single tight rows. */
  .vhero-body .sub{display:none}
  /* Scoped through #main: the over-the-video treatment for these two is
     itself #main-scoped and would otherwise keep them white — which on the
     light page background means invisible. */
  #main .vhero-body .rating{margin:0 0 var(--s-50);gap:var(--s-50)}
  #main .vhero-body .rating small{font-size:var(--text-xs);color:var(--muted)}
  #main .vhero-body .stars{font-size:13px}
  #main .vhero-body .chips{margin:0 0 var(--s-100);gap:var(--s-50);
    flex-wrap:wrap}
  #main .vhero-body .chip{background:var(--surface-2,#EEF2F4);
    border-color:var(--line-2);color:var(--ink-2);backdrop-filter:none;
    font-size:11px;line-height:1.3;padding:var(--s-25) var(--s-75)}
  #main .vhero-body .chip svg{width:13px;height:13px;color:var(--ok)}

  .vstages li{color:var(--ink);background:var(--surface-2,#EEF2F4);
    border-color:var(--line-2);backdrop-filter:none}
  .vstages li+li::before{border-left-color:var(--muted)}
  .vstages li:last-child{background:var(--ok-dim);border-color:rgba(15,138,70,.3);
    color:var(--ok-ink)}

  /* The card no longer overlaps footage, so it sits directly under it. */
  .hero-chat{margin-top:var(--s-200)}
}

/* Mid-height phones (~730px of viewport). The rating and trust rows cost
   about 26px, which is exactly enough to push the number under on these,
   so the footage gives that back rather than the number moving. */
@media (max-width:999px) and (min-height:721px) and (max-height:780px){
  .vhero-media{max-height:40svh}
}

/* Short phones (an SE is 375x667). Everything above the number has to give
   a little or the number itself never clears the fold. */
@media (max-width:999px) and (max-height:720px){
  .vhero-media{max-height:32svh}
  .vhero-body{padding-top:var(--s-100);padding-bottom:var(--s-75)}
  .vhero-body h1{font-size:var(--text-xl);line-height:var(--lh-xl)}
  .vstages li{font-size:10px;padding:var(--s-25) var(--s-75)}
  .vstages{margin-bottom:var(--s-75)}
  .offerbar{padding:var(--s-25) var(--s-100)}
  .callnow{padding:var(--s-200)}
  .callnow-n{font-size:clamp(1.75rem,7.5vw,2.25rem)}
}
/* The chips ride on moving footage, so they take glass rather than the
   light card treatment they have everywhere else on the page. */
.vhero-body .chips{margin:0}
.vhero-body .chip{background:rgba(255,255,255,.13);border-color:rgba(255,255,255,.26);
  color:#fff;backdrop-filter:blur(10px)}
.vhero-body .chip svg{color:#63E29B}

/* The conversation overlaps the footage. Two things sitting in separate
   bands with white between them is exactly what read as a widget. */
.hero-chat{position:relative;z-index:3;width:100%;max-width:var(--shell);
  margin:calc(var(--s-500) * -1) auto 0;padding:0 var(--s-200)}

@media (min-width:1000px){
  /* Full viewport of footage, with the chat floating on top of it. */
  .hero{min-height:100svh}
  .vhero{position:absolute;inset:0;height:100%;max-height:none;min-height:0}
  /* left to right on a wide frame, so the copy side stays readable and
     the right side keeps enough of the picture to be worth watching */
  /* Same rule as the phone: dark only under the copy column on the left,
     and the right side of the frame — where the tub is — left clean. */
  .vhero-scrim{background:linear-gradient(to right,
    rgba(0,0,0,.88) 0%,rgba(0,0,0,.66) 30%,rgba(0,0,0,.22) 52%,rgba(0,0,0,0) 70%,rgba(0,0,0,0) 100%)}
  .vhero-body{top:50%;bottom:auto;right:auto;transform:translateY(-50%);
    width:min(54%,620px);max-width:none;margin:0;
    padding:0 var(--s-500) 0 max(var(--s-400),calc((100vw - 1180px) / 2 + var(--s-300)))}
  .vhero-body h1{font-size:var(--text-6xl);line-height:var(--lh-6xl)}
  .vhero-body .sub{font-size:var(--text-xl);line-height:var(--lh-xl)}

  .hero-chat{width:min(100%,1180px);max-width:none;margin:0 auto;
    min-height:100svh;display:flex;align-items:center;justify-content:flex-end;
    padding:var(--s-700) var(--s-300)}
  /* The lead card now takes the slot the chat used to float in. */
  .hero-chat .herolead{width:100%;max-width:430px;
    max-height:calc(100svh - var(--s-800));overflow-y:auto}
}

/* ------------------------------------------------- the conversation */
/* A messenger, not a form: the head stays put, the thread scrolls, the
   composer is always there whether or not there is anything to type. */
.funnel-who{min-width:0}
.funnel-badge{margin-left:auto;flex:none;font-size:var(--text-xs);line-height:var(--lh-xs);
  font-weight:600;padding:var(--s-25) var(--s-75);border-radius:var(--r-full);
  background:var(--ok-dim);color:var(--ok-ink);border:1px solid rgba(15,138,70,.24)}

.thread{max-height:min(48vh,420px);overflow-y:auto;overscroll-behavior:contain;
  padding-right:var(--s-50);scrollbar-width:thin;
  scrollbar-color:var(--line-2) transparent}
.thread::-webkit-scrollbar{width:6px}
.thread::-webkit-scrollbar-thumb{background:var(--line-2);border-radius:var(--r-full)}

/* Options read as replies the customer could send, so they line up on
   their own side of the thread rather than as a stack of fields. */
.choices{justify-items:end}
.choice{width:auto;max-width:94%;margin-left:auto;border-radius:var(--r-3xl);
  border-color:rgba(14,76,138,.30);background:var(--brand-soft)}
.choice b{color:var(--ink)}

/* Suggested questions. The single clearest signal that something on the
   other end will actually answer you. */
.qr{display:flex;flex-wrap:wrap;gap:var(--s-50);margin-top:var(--s-100);
  justify-content:flex-end}
.qr[hidden]{display:none}
.qr button{font-size:var(--text-sm);line-height:var(--lh-sm);font-weight:500;
  padding:var(--s-50) var(--s-100);border-radius:var(--r-full);
  border:1px solid var(--line-2);background:var(--bg);color:var(--brand);
  cursor:pointer;
  transition:background-color var(--t-hover) ease,border-color var(--t-hover) ease,transform var(--t-press) var(--ease-out)}
.qr button:active{transform:scale(.96)}

.field .input{font-size:var(--text-base);padding:var(--s-100) var(--s-200)}
.field .btn{min-height:0;padding:var(--s-100) var(--s-200);flex:none}
/* the stage is where a real question is being asked, so it keeps the
   larger target size */
#stage .input,.modal .input{font-size:var(--text-lg);padding:var(--s-200)}

/* ------------------------------------------------------- the offer */
/* The discount is worth interrupting for once, after the price lands.
   Sheet on a phone, dialog on a desktop, and dismissible either way. */
.modal{position:fixed;inset:0;z-index:80;display:flex;align-items:flex-end;
  justify-content:center;padding:0}
.modal[hidden]{display:none}
.modal-veil{position:absolute;inset:0;background:rgba(6,18,30,.58);
  backdrop-filter:blur(4px);opacity:0;
  transition:opacity var(--t-enter) var(--ease-out)}
.modal.in .modal-veil{opacity:1}
.modal-card{position:relative;width:100%;max-width:440px;background:var(--bg);
  border:1px solid var(--line-2);border-bottom:0;
  border-radius:var(--r-4xl) var(--r-4xl) 0 0;
  padding:var(--s-400) var(--s-300) calc(var(--s-300) + env(safe-area-inset-bottom));
  box-shadow:0 -12px 48px rgba(11,32,51,.26);
  transform:translateY(24px);opacity:0;
  transition:transform var(--t-stage) var(--ease),opacity var(--t-enter) var(--ease-out)}
.modal.in .modal-card{transform:none;opacity:1}
@media (min-width:640px){
  .modal{align-items:center;padding:var(--s-300)}
  .modal-card{border-bottom:1px solid var(--line-2);border-radius:var(--r-4xl);
    padding:var(--s-400);box-shadow:0 32px 80px -24px rgba(11,32,51,.42);
    transform:translateY(12px) scale(.97)}
}
.modal-x{position:absolute;top:var(--s-100);right:var(--s-100);width:36px;height:36px;
  border-radius:var(--r-full);border:1px solid var(--line);background:var(--bg);
  color:var(--muted);cursor:pointer;display:grid;place-items:center;
  transition:background-color var(--t-hover) ease,color var(--t-hover) ease,transform var(--t-press) var(--ease-out)}
.modal-x:active{transform:scale(.96)}
.modal-x svg{width:15px;height:15px}

.promo-tag{display:inline-flex;align-items:center;gap:var(--s-50);
  font-size:var(--text-sm);line-height:var(--lh-sm);font-weight:600;
  color:var(--signal-ink);background:var(--signal-dim);
  border:1px solid rgba(196,71,15,.24);border-radius:var(--r-full);
  padding:var(--s-50) var(--s-100);margin-bottom:var(--s-200)}
.promo-h{font-size:var(--text-2xl);line-height:var(--lh-2xl);font-weight:600;
  letter-spacing:-.025em;margin-bottom:var(--s-75);text-wrap:balance}
.promo-p{font-size:var(--text-base);line-height:var(--lh-base);color:var(--muted);
  margin-bottom:var(--s-200)}
.promo-skip{display:block;width:100%;margin-top:var(--s-100);background:none;
  border:0;color:var(--muted);font-size:var(--text-sm);cursor:pointer;
  padding:var(--s-75);border-radius:var(--r-lg)}

/* ------------------------------------------------ booking on the page */
.lede{max-width:var(--read);font-size:var(--text-lg);line-height:var(--lh-lg);
  color:var(--muted);margin:calc(var(--s-300) * -1) 0 var(--s-400)}
.booker{display:grid;gap:var(--s-300);align-items:start}
@media (min-width:900px){
  .booker{grid-template-columns:minmax(0,1fr) minmax(0,400px);gap:var(--s-400)}
}
.booker-cal .cal{margin-top:0;padding:var(--s-100)}
.booker-cal .cal-day{font-size:var(--text-base)}
.booker-side{border:1px solid var(--line);border-radius:var(--r-3xl);
  background:var(--surface);padding:var(--s-300);min-height:180px}
.booker-side .wins{margin-top:var(--s-200)}
.booker-h{font-size:var(--text-lg);line-height:var(--lh-lg);font-weight:600;
  margin-bottom:var(--s-75)}
.booker-p{font-size:var(--text-sm);line-height:var(--lh-base);color:var(--muted)}
.booker-side .input{width:100%;margin-top:var(--s-75)}
.booker-side .btn{margin-top:var(--s-200)}

/* Booking on a phone. The day cells were sized for a desktop grid and
   came out below the 44px Apple/WCAG target, which is what makes a
   calendar feel fiddly to book on. Bigger cells, bigger type, and the
   times panel sits directly under the grid rather than off in a column. */
@media (max-width:899px){
  .booker{gap:var(--s-200)}
  .booker-cal .cal{padding:var(--s-75)}
  .booker-cal .cal-day{font-size:var(--text-lg);min-height:44px;border-radius:var(--r-xl)}
  .cal-grid{gap:var(--s-50)}
  .booker-side{padding:var(--s-200);min-height:0}
  /* Times are the thing being tapped; give them real targets too. */
  .booker-side .win,.booker-side .wins .btn{min-height:52px;font-size:var(--text-base)}
}

/* --------------------------------------- width the page was denied */
.h2{font-size:var(--text-3xl);line-height:var(--lh-3xl)}
@media (min-width:900px){
  .h2{font-size:var(--text-4xl);line-height:var(--lh-4xl)}
  .steps{grid-template-columns:repeat(3,1fr);gap:var(--s-400)}
  .prices{grid-template-columns:repeat(2,1fr);gap:var(--s-200)}
  .cards{grid-template-columns:repeat(4,1fr)}
  #gallery{display:grid;grid-template-columns:repeat(2,1fr);gap:var(--s-300)}
  #gallery figure{margin:0}
  .faq-grid{columns:2;column-gap:var(--s-500)}
  details.faq{break-inside:avoid}
  .reveal-line{font-size:var(--text-5xl);line-height:1.1}
}

@media (hover:hover) and (pointer:fine){
  .qr button:hover{background:var(--brand-soft);border-color:var(--brand)}
  .modal-x:hover{background:var(--surface-2);color:var(--ink)}
  .promo-skip:hover{color:var(--ink)}
}

/* a select has to look like the inputs beside it, not like the OS */
select.input{appearance:none;-webkit-appearance:none;cursor:pointer;
  background-image:url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 256 256' fill='%23566A7C'%3E%3Cpath d='M181.66,133.66l-48,48a8,8,0,0,1-11.32,0l-48-48A8,8,0,0,1,80,120h96a8,8,0,0,1,5.66,13.66Z'/%3E%3C/svg%3E");
  background-repeat:no-repeat;background-position:right var(--s-200) center;
  background-size:16px;padding-right:var(--s-500)}


/* =====================================================================
   PREMIUM PASS
   Header, before-and-after and the van. The 3D tub is gone: it read as a
   render, and a render undermines the one thing this page is selling.
   ===================================================================== */

/* ----------------------------------------------------------- header */
/* First thing on the page, so it carries the whole impression. The mark
   sits in a solid navy tile rather than floating as a bare glyph, the
   middle carries the three things a stranger wants to know, and the
   phone block reads as a real number rather than a generic button. */
.hdr{background:rgba(255,255,255,.78);
  backdrop-filter:saturate(180%) blur(20px);-webkit-backdrop-filter:saturate(180%) blur(20px);
  border-bottom:1px solid transparent;
  transition:border-color var(--t-stage) var(--ease-out),box-shadow var(--t-stage) var(--ease-out)}
/* the line and lift only appear once the page has moved under it */
.hdr.stuck{border-bottom-color:var(--line);
  box-shadow:0 8px 24px -18px rgba(11,32,51,.55)}
.hdr-in{padding:var(--s-75) var(--s-200);gap:var(--s-200)}

.logo-mark{width:38px;height:38px;border-radius:var(--r-xl);
  background:var(--brand);color:#fff;box-shadow:0 1px 2px rgba(11,32,51,.14)}
.logo-mark svg{width:24px;height:24px}
.logo-word b{font-size:var(--text-lg);letter-spacing:-.025em}
.logo-word em{font-size:9px;letter-spacing:.14em}

/* Hidden by default, shown beside the trust list from 1000px up. A phone
   header is the logo and the phone number; there is no room for a photo
   in it, and the van already has its own section further down. */
.hdr-van{display:none;width:112px;height:63px;object-fit:cover;flex:none;
  border-radius:var(--r-lg);border:1px solid var(--line-2)}
@media (min-width:1000px){.hdr-van{display:block}}
.hdr-trust{display:none;margin:0;padding:0;list-style:none;
  gap:var(--s-300);align-items:center}
.hdr-trust li{display:inline-flex;align-items:center;gap:var(--s-50);
  font-size:var(--text-sm);line-height:var(--lh-sm);font-weight:500;color:var(--ink-2);
  white-space:nowrap}
.hdr-trust svg{width:15px;height:15px;flex:none;color:var(--ok)}
@media (min-width:1060px){.hdr-trust{display:flex}}

.call{padding:var(--s-50);border:1px solid var(--line-2);border-radius:var(--r-full);
  background:var(--bg);gap:var(--s-75)}
.call-ico{width:34px;height:34px;flex:none;border-radius:var(--r-full);
  display:grid;place-items:center;background:var(--brand);color:#fff}
.call-ico svg{width:16px;height:16px}
.call-txt{display:none;flex-direction:column;line-height:1.15;padding-right:var(--s-75)}
.call-txt small{font-size:10px;font-weight:600;letter-spacing:.1em;
  text-transform:uppercase;color:var(--muted)}
.call-txt b{white-space:nowrap;font-size:var(--text-base);font-weight:600;color:var(--ink);
  font-variant-numeric:tabular-nums;font-feature-settings:"tnum" 1}
@media (min-width:560px){.call-txt{display:flex}}

/* -------------------------------------------- before and after, big */
/* The proof the category turns on, so it gets the width, the height and
   the frame. One registered pair runs as a drag slider; the others are
   honest side by side frames, because wiping between two different
   camera angles is a trick rather than a comparison. */
#gallery{display:grid;gap:var(--s-400)}
#gallery figure{margin:0}

.ba,.ba-pair{border-radius:var(--r-3xl);
  outline:1px solid rgba(0,0,0,.1);outline-offset:-1px;
  box-shadow:0 1px 2px rgba(11,32,51,.06),0 28px 56px -32px rgba(11,32,51,.42)}

.ba{aspect-ratio:4/3}
@media (min-width:900px){.ba{aspect-ratio:16/10}}

/* a fatter handle with a real grip, so it is obvious it can be dragged */
.ba-handle{width:3px;background:rgba(255,255,255,.92);
  box-shadow:0 0 0 1px rgba(0,0,0,.18),0 0 20px rgba(0,0,0,.45)}
.ba-handle::after{width:52px;height:52px;
  box-shadow:0 6px 20px rgba(0,0,0,.42),0 0 0 1px rgba(0,0,0,.06)}
.ba-handle::before{width:0;height:0;border:0;margin:0;
  background:transparent}

.ba-grip{position:absolute;top:50%;left:var(--split,50%);z-index:2;
  transform:translate(-50%,-50%);display:flex;align-items:center;gap:2px;
  pointer-events:none;color:#0B2033}
.ba-grip svg{width:15px;height:15px}

/* labels sit top corner and read as captions, not as badges */
.ba-tag{top:var(--s-200);bottom:auto;font-size:var(--text-xs);
  letter-spacing:.14em;font-weight:600;padding:var(--s-50) var(--s-100);
  background:rgba(0,0,0,.62);backdrop-filter:blur(10px);
  -webkit-backdrop-filter:blur(10px)}
.ba-tag.b{left:var(--s-200)} .ba-tag.a{right:var(--s-200)}

.ba-hint{position:absolute;bottom:var(--s-200);left:50%;transform:translateX(-50%);
  z-index:3;pointer-events:none;display:inline-flex;align-items:center;gap:var(--s-50);
  font-size:var(--text-xs);line-height:var(--lh-xs);font-weight:600;
  letter-spacing:.1em;text-transform:uppercase;color:#fff;
  background:rgba(0,0,0,.62);backdrop-filter:blur(10px);
  -webkit-backdrop-filter:blur(10px);
  padding:var(--s-50) var(--s-100);border-radius:var(--r-full);
  transition:opacity var(--t-enter) var(--ease-out),transform var(--t-enter) var(--ease-out)}
.ba-hint svg{width:13px;height:13px}
.ba.is-touched .ba-hint{opacity:0;transform:translate(-50%,6px)}

/* Stacked on a phone so each frame is full width and actually readable,
   side by side from 640px where there is room to compare at a glance. */
.ba-pair{display:grid;grid-template-columns:1fr;gap:2px;
  background:var(--line-2);overflow:hidden}
@media (min-width:640px){.ba-pair{grid-template-columns:1fr 1fr}}
.ba-pair figure{position:relative;margin:0}
.ba-pair img{width:100%;aspect-ratio:4/3;object-fit:cover;display:block;
  border-radius:0;outline:none}
.ba-pair figcaption{position:absolute;top:var(--s-200);left:var(--s-200);bottom:auto;
  font-size:var(--text-xs);line-height:var(--lh-xs);font-weight:600;letter-spacing:.14em;
  padding:var(--s-50) var(--s-100);border-radius:var(--r-full);
  background:rgba(0,0,0,.62);backdrop-filter:blur(10px);
  -webkit-backdrop-filter:blur(10px);color:#fff}

/* Footage in a gallery slot. Same frame as the pairs beside it so the row
   still reads as one set rather than a photo grid with a video dropped in. */
/* width:100% for the same reason the hero needs it: with only
   aspect-ratio, WebKit satisfies the ratio by shrinking the width and the
   slot comes out narrow and flush left. */
.ba-video{position:relative;overflow:hidden;border-radius:var(--r-3xl);
  background:var(--sunken);width:100%;aspect-ratio:var(--ba-ratio,4/3)}
@media (min-width:900px){.ba-video{aspect-ratio:var(--ba-ratio,16/10)}}
.ba-video video{width:100%;height:100%;object-fit:cover;display:block}

.ba-cap{margin-top:var(--s-200);font-size:var(--text-base);line-height:var(--lh-base);
  color:var(--muted);max-width:var(--read)}

.ba-cta{display:flex;flex-direction:column;align-items:center;gap:var(--s-200);
  margin-top:var(--s-600);text-align:center}
.ba-cta p{font-size:var(--text-xl);line-height:var(--lh-xl);font-weight:600;color:var(--ink)}
.ba-cta .btn{min-width:min(100%,320px)}

/* ----------------------------------------------------------- the van */
.van-card{margin:0 0 var(--s-400);border-radius:var(--r-3xl);overflow:hidden;
  border:1px solid var(--line);background:var(--surface);
  box-shadow:0 1px 2px rgba(11,32,51,.06),0 28px 56px -32px rgba(11,32,51,.38)}
.van-card img{width:100%;aspect-ratio:16/9;object-fit:cover;display:block}
.van-card figcaption{padding:var(--s-300)}
.van-card figcaption b{display:block;font-size:var(--text-lg);line-height:var(--lh-lg);
  font-weight:600;margin-bottom:var(--s-50)}
.van-card figcaption p{font-size:var(--text-base);line-height:var(--lh-lg);color:var(--muted)}
@media (min-width:900px){
  .van-card{display:grid;grid-template-columns:1.45fr 1fr;align-items:stretch}
  .van-card img{height:100%;aspect-ratio:auto;min-height:300px}
  .van-card figcaption{padding:var(--s-500) var(--s-400);align-self:center}
}

@media (hover:hover) and (pointer:fine){
  .call:hover{background:var(--brand-soft);border-color:var(--brand)}
}


/* ------------------------------------------------- where we work */
/* Eleven states is the fact, but a wall of other people's cities is
   cold. The visitor's own metro lights up the moment their ZIP comes
   back covered, which turns the list from "we are big" into "and yours". */
.area-here{display:block;margin-bottom:var(--s-300);padding:var(--s-100) var(--s-200);
  border-radius:var(--r-2xl);background:var(--ok-dim);color:var(--ok-ink);
  border:1px solid rgba(15,138,70,.24);font-size:var(--text-base);font-weight:600;
  animation:rise var(--t-enter) var(--ease-out) both}
.area-here[hidden]{display:none}

.metros{display:grid;grid-template-columns:repeat(2,1fr);gap:var(--s-75);
  margin:0;padding:0;list-style:none}
@media (min-width:640px){.metros{grid-template-columns:repeat(3,1fr)}}
@media (min-width:900px){.metros{grid-template-columns:repeat(4,1fr);gap:var(--s-100)}}
.metro{display:flex;flex-direction:column;gap:2px;padding:var(--s-100) var(--s-200);
  border:1px solid var(--line);border-radius:var(--r-2xl);background:var(--surface);
  transition:background-color var(--t-hover) ease,border-color var(--t-hover) ease}
.metro b{font-size:var(--text-sm);line-height:var(--lh-sm);font-weight:600;color:var(--ink)}
.metro span{font-size:var(--text-xs);line-height:var(--lh-xs);letter-spacing:.1em;
  text-transform:uppercase;color:var(--muted)}
.metro.on{background:var(--ok-dim);border-color:rgba(15,138,70,.34)}
.metro.on span{color:var(--ok-ink)}

.nearby{display:flex;flex-wrap:wrap;gap:var(--s-50);margin-top:var(--s-300)}
.nearby a{font-size:var(--text-sm);line-height:var(--lh-sm);color:var(--brand);
  text-decoration:none;padding:var(--s-50) var(--s-100);border-radius:var(--r-full);
  border:1px solid var(--line);background:var(--bg);
  transition:background-color var(--t-hover) ease,border-color var(--t-hover) ease}

@media (hover:hover) and (pointer:fine){
  .nearby a:hover{background:var(--brand-soft);border-color:var(--brand)}
}

/* Each photo states its own shape. Overhead tub shots are wide and lose
   their ends if they are forced into the default 4:3. */
.ba{aspect-ratio:var(--ba-ratio,4/3)}
@media (min-width:900px){.ba{aspect-ratio:var(--ba-ratio,16/10)}}
.ba-pair img{aspect-ratio:var(--ba-ratio,4/3)}

/* ------------------------------------------------- rating badges */
/* Each one links to the real profile. A star rating a customer cannot
   click through and verify reads as decoration, and one visitor who
   checks and finds nothing stops believing the rest of the page. */
.badges{display:flex;flex-wrap:wrap;gap:var(--s-100);margin:var(--s-300) 0 0;
  padding:0;list-style:none}
.badge a{display:flex;align-items:center;gap:var(--s-75);text-decoration:none;
  padding:var(--s-75) var(--s-200);border:1px solid var(--line);
  border-radius:var(--r-2xl);background:var(--surface);
  transition:background-color var(--t-hover) ease,border-color var(--t-hover) ease}
.badge-name{font-size:var(--text-sm);line-height:var(--lh-sm);font-weight:600;color:var(--ink)}
.badge-stars{display:inline-flex;gap:1px;color:#F5B841}
.badge-stars svg{width:13px;height:13px}
.badge-num{font-size:var(--text-sm);line-height:var(--lh-sm);color:var(--muted);
  font-variant-numeric:tabular-nums}
@media (hover:hover) and (pointer:fine){
  .badge a:hover{background:var(--surface-2);border-color:var(--brand)}
}

/* --------------------------------------------------- call fallback */
/* Shown when a tel: link has nowhere to go, which is every desktop
   without a dialer app. The button looked broken; now the number is on
   screen and on the clipboard. */
.toast{position:fixed;left:50%;bottom:calc(var(--s-400) + env(safe-area-inset-bottom));
  transform:translate(-50%,12px);z-index:90;
  display:flex;flex-direction:column;gap:2px;text-align:center;
  padding:var(--s-100) var(--s-300);border-radius:var(--r-2xl);
  background:var(--ink);color:#fff;
  box-shadow:0 12px 32px -12px rgba(11,32,51,.6);
  opacity:0;pointer-events:none;
  transition:opacity var(--t-enter) var(--ease-out),transform var(--t-enter) var(--ease-out)}
.toast.in{opacity:1;transform:translate(-50%,0)}
.toast b{font-size:var(--text-lg);line-height:var(--lh-lg);font-weight:600;
  font-variant-numeric:tabular-nums}
.toast span{font-size:var(--text-sm);line-height:var(--lh-sm);color:rgba(255,255,255,.72)}
@media (min-width:900px){.toast{bottom:var(--s-400)}}

/* ----------------------------------------- the call button on a phone */
/* It was a bare 34px circle with no label below 560px, and it is the only
   way to call until the sticky bar appears, which on a phone is not until
   the chat has scrolled off. An unlabelled icon does not read as a button,
   so the number itself is the label from 380px up. */
.call{padding:var(--s-75)}
@media (min-width:380px){
  .call-txt{display:flex}
}
@media (max-width:559px){
  .call-txt{padding-right:var(--s-50)}
  .call-txt small{display:none}
  .call-txt b{font-size:var(--text-sm);line-height:var(--lh-sm)}
  .logo-word em{display:none}
}

/* ------------------------------------------------------ legal pages */
.legal-lead{font-size:var(--text-sm);color:var(--muted);margin-bottom:var(--s-400)}
.legal-h{font-size:var(--text-lg);line-height:var(--lh-lg);font-weight:600;
  margin:var(--s-400) 0 var(--s-100)}
#main section p{color:var(--ink-2);line-height:var(--lh-lg);max-width:var(--read)}
#main section p+p{margin-top:var(--s-100)}
