/* ==========================================================================
   JetClean Exteriors
   Palette sampled directly from the logo artwork.
   Signature device: "the wash line" — the hard edge between grime and clean.
   ========================================================================== */

:root{
  /* brand — sampled from logo-original.jpg */
  --navy:      #032C4B;
  --ink:       #04203A;
  --jet:       #125A93;   /* wave, dark */
  --spray:     #3690CC;   /* wave, crest */
  --mist:      #DCF0FA;   /* logo field */

  /* materials — the surfaces he cleans */
  --stone:     #E9E2D6;   /* sandstone */
  --stone-dk:  #C9BFAE;
  --grime:     #6F7D55;   /* the algae that comes off */
  --grime-dk:  #68754F;   /* same green, dark enough for white 10px text */
  --field-line:#7E8C99;   /* form/chip borders — --line is only 1.2:1 */

  --paper:     #FFFFFF;
  --paper-2:   #F7F9FB;
  --line:      #DCE3EA;
  --muted:     #5B6B73;   /* logo roof grey */

  --sp: clamp(3.5rem, 7vw, 6.5rem);   /* section rhythm */
  --radius: 14px;
  --shadow: 0 1px 2px rgba(4,32,58,.06), 0 12px 28px -12px rgba(4,32,58,.18);

  --font-display: "Archivo", system-ui, sans-serif;
  --font-body: "Karla", system-ui, sans-serif;
}

*, *::before, *::after{ box-sizing: border-box; }

html{ -webkit-text-size-adjust: 100%; scroll-behavior: smooth; scrollbar-gutter: stable; }
@media (prefers-reduced-motion: reduce){ html{ scroll-behavior: auto; } }

body{
  margin:0;
  font-family: var(--font-body);
  font-size: clamp(1rem, .96rem + .2vw, 1.075rem);
  line-height: 1.62;
  color: var(--ink);
  background: var(--paper);
  -webkit-font-smoothing: antialiased;
}

img{ max-width:100%; height:auto; display:block; }

h1,h2,h3{
  font-family: var(--font-display);
  font-weight: 800;
  line-height: 1.02;
  letter-spacing: -0.025em;
  margin: 0;
  font-stretch: 112%;
}

a{ color: var(--jet); }

.wrap{ width:min(1180px, 92vw); margin-inline:auto; }

:focus-visible{
  outline: 3px solid var(--spray);
  outline-offset: 3px;
  border-radius: 3px;
}
/* Spray only clears 3:1 on pale backgrounds. Over the hero photo it drops to
   1.9:1 and on --mist to 2.97:1, so those two get their own ring colour.
   The hero backdrop runs from near-black to near-white depending on where the
   scrim is thin, so no single colour is safe there — it gets a white ring
   inside a dark halo, and whichever way the photo goes, one of the two shows. */
.hero :focus-visible{
  outline-color:#fff;
  box-shadow: 0 0 0 8px rgba(4,32,58,.85);
}
.section-tint :focus-visible,
.checks input:focus-visible{ outline-color: var(--jet); }

.skip{
  position:absolute; left:-9999px;
  background: var(--navy); color:#fff; padding:.8rem 1.2rem; z-index:100;
  font-weight:600;
}
.skip:focus{ left:1rem; top:1rem; }

/* ---------------------------------------------------------------- buttons */
.btn{
  --btn-bg: transparent;
  --btn-fg: var(--navy);
  display:inline-flex; align-items:center; gap:.55rem;
  font-family: var(--font-display);
  font-weight: 700; font-size: .975rem; letter-spacing: -0.005em;
  padding: .85rem 1.5rem;
  background: var(--btn-bg); color: var(--btn-fg);
  border: 2px solid currentColor; border-radius: 999px;
  text-decoration:none; cursor:pointer;
  transition: transform .16s ease, background-color .16s ease, color .16s ease, box-shadow .16s ease;
}
.btn:hover{ transform: translateY(-2px); }
.btn:active{ transform: translateY(0); }

.btn-primary{
  --btn-bg: var(--jet); --btn-fg:#fff;
  border-color: var(--jet);
  box-shadow: 0 10px 22px -12px rgba(18,90,147,.9);
}
.btn-primary:hover{ --btn-bg: var(--navy); border-color: var(--navy); }

.btn-ghost{ --btn-fg: var(--navy); border-color: var(--stone-dk); }
.btn-ghost:hover{ border-color: var(--navy); }

/* ----------------------------------------------------------------- header */
.site-header{
  position: sticky; top:0; z-index:50;
  background: rgba(255,255,255,.92);
  backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--line);
}
.header-inner{
  display:flex; align-items:center; gap:1.5rem;
  padding-block: .7rem;
}
.brand{ display:flex; align-items:center; gap:.65rem; text-decoration:none; margin-right:auto; }
.brand-mark{ border-radius:9px; width:44px; height:44px; }
.brand-text{ display:flex; flex-direction:column; line-height:1; }
.brand-name{
  font-family: var(--font-display); font-weight:900; font-stretch:118%;
  font-size:1.28rem; color: var(--navy); letter-spacing:-0.03em;
}
.brand-sub{
  font-family: var(--font-display); font-weight:600;
  font-size:.62rem; letter-spacing:.30em; text-transform:uppercase;
  color: var(--spray); margin-top:.2rem;
}

.nav{ display:flex; gap:1.75rem; }
.nav a{
  font-family: var(--font-display); font-weight:600; font-size:.94rem;
  color: var(--navy); text-decoration:none; position:relative; padding-block:.3rem;
}
.nav a::after{
  content:""; position:absolute; left:0; right:100%; bottom:0; height:2px;
  background: var(--spray); transition: right .25s ease;
}
.nav a:hover::after{ right:0; }

.btn-call{ --btn-bg: var(--navy); --btn-fg:#fff; border-color: var(--navy); padding:.7rem 1.25rem; }
.btn-call svg{ width:17px; height:17px; fill: currentColor; }
.btn-call:hover{ --btn-bg: var(--jet); border-color: var(--jet); }

/* ------------------------------------------------------------------- hero */
.hero{
  background:
    radial-gradient(120% 90% at 88% 0%, var(--mist) 0%, transparent 62%),
    linear-gradient(180deg, #fff 0%, var(--paper-2) 100%);
  padding-block: clamp(2.5rem, 5vw, 4.5rem) var(--sp);
  overflow: hidden;
}
.hero-inner{
  display:grid; grid-template-columns: 1.05fr .95fr;
  gap: clamp(2rem, 5vw, 4.5rem); align-items:center;
}

.eyebrow{
  font-family: var(--font-display); font-weight:700;
  font-size:.72rem; letter-spacing:.24em; text-transform:uppercase;
  color: var(--jet); margin:0 0 1.1rem;
  display:flex; align-items:center; gap:.75rem;
}
.eyebrow::before{
  content:""; width:34px; height:3px; border-radius:2px;
  background: linear-gradient(90deg, var(--grime) 0 42%, var(--spray) 42%);
}

.hero-title{
  font-size: clamp(3.4rem, 9.5vw, 6.4rem);
  font-weight:900; font-stretch:120%;
  letter-spacing:-0.045em; color: var(--navy);
  margin-bottom: 1.4rem;
}
.hero-title em{
  font-style:normal; color: var(--jet);
  display:inline-block;
  /* the wash line, drawn under the promise: grime, the jet, then clean */
  background-image: linear-gradient(90deg, var(--grime) 0 16%, var(--spray) 16% 23%, var(--mist) 23%);
  background-repeat: no-repeat;
  background-size: 100% .1em;
  background-position: 0 92%;
  padding-inline: .04em;
}

.hero-lead{
  font-size: clamp(1.06rem, 1rem + .35vw, 1.22rem);
  color: #2C4358; max-width: 34em; margin: 0 0 2rem;
}

.hero-actions{ display:flex; flex-wrap:wrap; gap:.85rem; margin-bottom:2.25rem; }

.hero-marks{
  list-style:none; margin:0; padding:0;
  display:flex; flex-wrap:wrap; gap:.6rem 1.6rem;
  font-family: var(--font-display); font-weight:600; font-size:.87rem;
  color: var(--muted);
}
.hero-marks li{ display:flex; align-items:center; gap:.5rem; }
.hero-marks li::before{
  content:""; width:7px; height:7px; border-radius:50%;
  background: var(--spray); flex:none;
}

/* ------------------------------------------------ the reveal (signature) */
.reveal{ margin:0; }
.reveal-frame{
  position:relative; aspect-ratio: 4/5;
  border-radius: var(--radius); overflow:hidden;
  box-shadow: var(--shadow);
  background: var(--stone);
  isolation:isolate;
  --pos: 62%;
}
.reveal-img{ width:100%; height:100%; object-fit:cover; }
.reveal-clean{
  position:absolute; inset:0;
  clip-path: inset(0 0 0 var(--pos));
}
.reveal-line{
  position:absolute; top:0; bottom:0; left: var(--pos);
  width:3px; margin-left:-1.5px;
  background: linear-gradient(180deg, rgba(255,255,255,.35), #fff 12%, #fff 88%, rgba(255,255,255,.35));
  box-shadow: 0 0 14px 1px rgba(54,144,204,.75);
  pointer-events:none;
}
.reveal-grip{
  position:absolute; top:50%; left:50%; transform: translate(-50%,-50%);
  width:52px; height:52px; border-radius:50%;
  background: rgba(255,255,255,.94);
  box-shadow: 0 4px 16px rgba(4,32,58,.32);
  display:grid; place-items:center;
}
.reveal-grip::before,
.reveal-grip::after{
  content:""; position:absolute;
  width:0; height:0; border-block:5px solid transparent;
}
.reveal-grip::before{ left:13px; border-right:7px solid var(--jet); }
.reveal-grip::after{ right:13px; border-left:7px solid var(--jet); }

.reveal-input{
  position:absolute; inset:0; width:100%; height:100%;
  margin:0; opacity:0; cursor: ew-resize;
  -webkit-appearance:none; appearance:none; background:transparent;
}
.reveal-input::-webkit-slider-thumb{ -webkit-appearance:none; width:56px; height:100%; }
.reveal-input::-moz-range-thumb{ width:56px; height:100%; border:0; opacity:0; }
.reveal-frame:has(.reveal-input:focus-visible){ outline:3px solid var(--spray); outline-offset:3px; }

.reveal figcaption{
  margin-top:.9rem;
  font-family: var(--font-display); font-weight:600; font-size:.82rem;
  letter-spacing:.02em; color: var(--muted); text-align:center;
}

/* before / after tags */
.tag{
  position:absolute; top:.85rem; z-index:3;
  font-family: var(--font-display); font-weight:700;
  font-size:.68rem; letter-spacing:.14em; text-transform:uppercase;
  padding:.36rem .7rem; border-radius:6px; color:#fff;
  pointer-events:none;
}
.tag-before{ left:.85rem; background: var(--grime-dk); }
.tag-after{ right:.85rem; background: var(--jet); }

/* --------------------------------------------------------------- sections */
.section{ padding-block: var(--sp); }
.section-dark{ background: var(--navy); color: #E4EEF6; }
.section-tint{ background: var(--mist); }

.section-head{ max-width: 46rem; margin-bottom: clamp(2.25rem, 4vw, 3.25rem); }
.section-title{
  font-size: clamp(2.1rem, 1.6rem + 2.1vw, 3.35rem);
  font-weight:900; font-stretch:114%; color: var(--navy);
  margin-bottom: 1rem;
}
.section-dark .section-title{ color:#fff; }
.section-title::before{
  content:""; display:block; width:96px; height:5px; border-radius:3px;
  margin-bottom:1.15rem;
  background: linear-gradient(90deg, var(--grime) 0 34%, var(--spray) 34% 44%, var(--stone-dk) 44%);
}
.section-dark .section-title::before{
  background: linear-gradient(90deg, var(--grime) 0 34%, var(--spray) 34% 44%, rgba(255,255,255,.35) 44%);
}
.section-note{ color: var(--muted); font-size:1.06rem; margin:0; }
.section-dark .section-note{ color: #A9C2D6; }

/* --------------------------------------------------------------- services */
.services{ display:grid; grid-template-columns: repeat(2, 1fr); gap: clamp(1.1rem, 2.4vw, 1.9rem); }
.service{
  background: var(--paper);
  border:1px solid var(--line); border-left:5px solid var(--spray);
  border-radius: var(--radius);
  padding: clamp(1.6rem, 3vw, 2.4rem);
  box-shadow: var(--shadow);
}
.service:nth-child(2){ border-left-color: var(--grime); }
.service-name{
  font-size: clamp(1.45rem, 1.2rem + .9vw, 1.95rem);
  color: var(--navy); margin-bottom:.85rem;
}
.service-what{ color:#33495C; margin:0 0 1.4rem; }

/* ------------------------------------------------------------- work grid */
.grid{
  display:grid; grid-template-columns: repeat(3, 1fr);
  gap: clamp(1.1rem, 2.2vw, 1.75rem);
}
.job{
  margin:0; background: rgba(255,255,255,.055);
  border:1px solid rgba(255,255,255,.12);
  border-radius: var(--radius); overflow:hidden;
}
.pair{ display:grid; grid-template-columns: 1fr 1fr; gap:2px; background: rgba(255,255,255,.14); }
.shot{ position:relative; aspect-ratio: 3/4; overflow:hidden; }
.shot img{ width:100%; height:100%; object-fit:cover; }
.shot .tag{ top:.55rem; font-size:.6rem; padding:.28rem .55rem; letter-spacing:.1em; }
.shot .tag-before{ left:.55rem; }
.shot .tag-after{ right:.55rem; }

.job figcaption{ padding: 1rem 1.15rem 1.2rem; }
.job figcaption strong{
  display:block;
  font-family: var(--font-display); font-weight:700; font-size:1.02rem;
  color:#fff; letter-spacing:-0.01em;
}
.job figcaption span{ display:block; font-size:.88rem; color:#9FB9CF; margin-top:.2rem; }

/* ------------------------------------------------------------------ area */
.area{ display:grid; grid-template-columns: 1fr 1.15fr; gap: clamp(2rem,4vw,3.5rem); align-items:center; }
.area-copy p{ color:#31485C; max-width:32em; margin:0 0 1.8rem; }
.area-shot{ margin:0; border-radius: var(--radius); overflow:hidden; box-shadow: var(--shadow); }

/* ------------------------------------------------------------------ form */

.contact{ margin:2rem 0 0; display:grid; gap:1.1rem; }
.contact div{ display:grid; gap:.15rem; }
.contact dt{
  font-family: var(--font-display); font-weight:700;
  font-size:.68rem; letter-spacing:.18em; text-transform:uppercase; color: var(--muted);
}
.contact dd{ margin:0; font-size:1.1rem; font-weight:600; }
.contact a{ color: var(--navy); text-decoration-color: var(--spray); text-underline-offset:3px; }
.contact a:hover{ color: var(--jet); }

.form{
  background: var(--paper-2); border:1px solid var(--line);
  border-radius: var(--radius); padding: clamp(1.5rem, 3vw, 2.4rem);
  display:grid; gap:1.15rem;
}
.field{ display:grid; gap:.42rem; margin:0; padding:0; border:0; }
.field label, .field legend{
  font-family: var(--font-display); font-weight:700; font-size:.83rem;
  color: var(--navy); padding:0;
}
.opt{ font-weight:500; color: var(--muted); letter-spacing:0; }

.field input[type="text"],
.field input[type="tel"],
.field input[type="email"],
.field textarea{
  font: inherit; color: var(--ink);
  padding:.8rem .95rem;
  border:1.5px solid var(--field-line); border-radius:9px;
  background:#fff; width:100%;
  transition: border-color .15s ease, box-shadow .15s ease;
}
.field input[type="text"]:focus,
.field input[type="tel"]:focus,
.field input[type="email"]:focus,
.field textarea:focus{
  outline:none; border-color: var(--spray);
  box-shadow: 0 0 0 3px rgba(54,144,204,.18);
}
.field textarea{ resize:vertical; min-height:110px; }
/* opacity:1 or Firefox re-applies its own fade over the colour */
.field ::placeholder{ color: var(--muted); opacity:1; }
.field[data-invalid] input, .field[data-invalid] textarea{ border-color:#C0392B; }

.checks{ display:flex; flex-wrap:wrap; gap:.5rem; margin-top:.25rem; }
.checks label{
  display:flex; align-items:center; gap:.5rem;
  font-family: var(--font-body); font-weight:500; font-size:.95rem; color:#33495C;
  background:#fff; border:1.5px solid var(--field-line); border-radius:999px;
  padding:.5rem .95rem; cursor:pointer; min-height:44px;
  transition: border-color .15s ease, background-color .15s ease;
}
.checks label:hover{ border-color: var(--spray); }
.checks input{ accent-color: var(--jet); width:16px; height:16px; }
.checks label:has(input:checked){ border-color: var(--jet); background: var(--mist); }

.err{ margin:0; font-size:.83rem; color:#C0392B; min-height:0; }
.err:empty{ display:none; }

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

.btn-submit{ justify-content:center; width:100%; margin-top:.35rem; }

.form-status{ margin:0; font-weight:600; font-size:.95rem; min-height:1.4em; }
.form-status[data-state="ok"]{ color:#1B7A4B; }
.form-status[data-state="err"]{ color:#C0392B; }

/* ---------------------------------------------------------------- footer */
.site-footer{ background: var(--ink); color:#93AEC4; padding-block: 3rem 2.5rem; }
.footer-inner{ display:grid; gap:1.6rem; }
.footer-brand{ display:flex; align-items:center; gap:.85rem; }
.footer-brand img{ border-radius:8px; }
.footer-name{
  font-family: var(--font-display); font-weight:800; font-stretch:112%;
  color:#fff; margin:0; font-size:1.1rem;
}
.footer-line{ margin:.1rem 0 0; font-size:.9rem; }
.footer-nav{ display:flex; flex-wrap:wrap; gap:1.5rem; }
.footer-nav a{
  color:#CFE0EE; text-decoration:none;
  font-family: var(--font-display); font-weight:600; font-size:.92rem;
}
.footer-nav a:hover{ color:#fff; text-decoration:underline; text-underline-offset:3px; }
.copyright{ margin:0; font-size:.83rem; color:#8AA5BC; }

/* ------------------------------------------------------------ responsive */
@media (max-width: 1000px){
  .nav{ display:none; }
  .hero-inner{ grid-template-columns: 1fr; }
  .grid{ grid-template-columns: repeat(2, 1fr); }
  .area{ grid-template-columns: 1fr; }
}

@media (max-width: 640px){
  .header-inner{ gap:.75rem; }
  .btn-call span{ display:none; }
  .btn-call{ padding:.7rem .85rem; }
  .services{ grid-template-columns: 1fr; }
  .grid{ grid-template-columns: 1fr; }
  .job{ max-width: 480px; margin-inline:auto; width:100%; }
  .hero-actions .btn{ width:100%; justify-content:center; }
}

@media (prefers-reduced-motion: reduce){
  *, *::before, *::after{
    animation-duration:.01ms !important; animation-iteration-count:1 !important;
    transition-duration:.01ms !important;
  }
  .btn:hover, .btn-box:hover{ transform:none; }
}

/* Visually hidden, still read aloud. Used by the star ratings, the gallery
   count and the "opens in a new tab" hints. */
.vh{
  position:absolute; width:1px; height:1px;
  margin:-1px; padding:0; border:0;
  clip-path: inset(50%); overflow:hidden; white-space:nowrap;
}


/* ==========================================================================
   Banner + hero — append to css/styles.css, after everything else.
   Two rules of thumb in here: the bar is solid so it stays legible sitting on
   the photo, and the phone gets real navigation instead of none.
   ========================================================================== */

/* The bar is sticky and solid, so anything you jump to needs to clear it. */
.hero, .section{ scroll-margin-top: clamp(4.75rem, 4rem + 2vw, 5.75rem); }

/* ----------------------------------------------------------------- banner */

/* OVERRIDES existing: .site-header — was white and translucent. It now sits
   over a photo, and a blurred pale bar over paving is unreadable. */
.site-header{
  background: var(--ink);
  backdrop-filter: none;
  border-bottom: 1px solid rgba(255,255,255,.10);
}

/* OVERRIDES existing: .brand-mark — 40px inside the chip keeps the bar short
   enough that the hero button still clears the fold on a small phone. */
.brand-mark{ width:40px; height:40px; border-radius:7px; }

/* The logo has a pale blue baked into it and no transparency, so it gets its
   own light chip rather than floating as a pale square on the dark bar. */
.brand-chip{
  display:grid; place-items:center; flex:none;
  padding:5px; border-radius:11px;
  background: var(--paper);
  box-shadow: 0 2px 10px rgba(0,0,0,.30);
}

/* OVERRIDES existing: .brand-name — navy on near-black reads as nothing. */
.brand-name{ color:#fff; }

/* OVERRIDES existing: .nav a / .nav — navy links on the dark bar, and the
   reference spreads them out with a lot more air than 1.75rem. */
.nav{ gap: clamp(1.6rem, 3vw, 2.9rem); align-items:center; }
.nav a{ color:#CFE0EE; font-size:.98rem; letter-spacing:.012em; }
.nav a:hover{ color:#fff; }

/* current section — colour plus a permanent underline, never colour alone */
.nav a.is-active{ color: var(--spray); }
.nav a.is-active::after{ right:0; }

/* OVERRIDES existing: .btn-call — navy on --ink is invisible. */
.btn-call{ --btn-bg: var(--jet); --btn-fg:#fff; border-color: var(--jet); }
.btn-call:hover{ --btn-bg: var(--spray); border-color: var(--spray); --btn-fg: var(--ink); }

/* ------------------------------------------------------------ nav toggle */
.nav-toggle{
  display:none;                 /* earns its place only once JS is running */
  align-items:center; gap:.55rem;
  min-width:44px; min-height:44px;
  padding:.5rem .85rem;
  background: transparent; color:#fff;
  border:1.5px solid rgba(255,255,255,.30); border-radius:10px;
  font-family: var(--font-display); font-weight:700; font-size:.86rem;
  letter-spacing:.04em; text-transform:uppercase;
  cursor:pointer; -webkit-user-select:none; user-select:none;
  transition: background-color .16s ease, border-color .16s ease;
}
.nav-toggle:hover{ background: rgba(255,255,255,.08); border-color: rgba(255,255,255,.55); }

.nav-toggle-bars{ position:relative; width:20px; height:14px; flex:none; }
.nav-toggle-bars span{
  position:absolute; left:0; right:0; height:2px; border-radius:2px;
  background: currentColor;
  transition: top .2s ease, transform .2s ease, opacity .12s ease;
}
.nav-toggle-bars span:nth-child(1){ top:0; }
.nav-toggle-bars span:nth-child(2){ top:6px; }
.nav-toggle-bars span:nth-child(3){ top:12px; }

.site-header[data-nav="open"] .nav-toggle-bars span:nth-child(1){ top:6px; transform: rotate(45deg); }
.site-header[data-nav="open"] .nav-toggle-bars span:nth-child(2){ opacity:0; }
.site-header[data-nav="open"] .nav-toggle-bars span:nth-child(3){ top:6px; transform: rotate(-45deg); }

/* page must not scroll behind the open drawer */
.nav-open, .nav-open body{ overflow:hidden; }

@keyframes nav-drop{
  from{ opacity:0; transform: translateY(-10px); }
  to{ opacity:1; transform:none; }
}

/* ------------------------------------------------------------------- hero */

/* OVERRIDES existing: .hero — was a pale two-column band. It is now the
   full-bleed photo the client asked for. */
.hero{
  position:relative; isolation:isolate;
  display:flex; align-items:center;
  padding-block: clamp(2.75rem, 6vw, 5.5rem);
  background: var(--ink);          /* what shows while the photo decodes */
  overflow:hidden;
  min-height: 84vh;                                /* fallback: no svh */
  min-height: clamp(30rem, 84svh, 48rem);          /* svh, so the button
                                                      clears the fold with
                                                      the browser chrome out */
}

.hero > picture{ position:absolute; inset:0; z-index:0; display:block; }
.hero-photo{
  width:100%; height:100%; object-fit:cover; object-position:50% 62%;
}

/* The scrim. One flat wash over warm mid-tone paving goes muddy, so it is two
   layers of --ink and --navy: heavy across the left where the words are, thin
   on the right so the hedge and the clean paving still read.
   The paving carries near-white highlights, so the stops are set for the worst
   case — a white pixel under the thinnest part of the wash still leaves the
   headline at 6.4:1. Move them and re-check the numbers. */
.hero::after{
  content:""; position:absolute; inset:0; z-index:1; pointer-events:none;
  background:
    linear-gradient(100deg,
      rgba(4,32,58,.88) 0%,
      rgba(4,32,58,.85) 60%,
      rgba(3,44,75,.64) 86%,
      rgba(3,44,75,.46) 100%),
    linear-gradient(180deg,
      rgba(4,32,58,.62) 0%,
      rgba(4,32,58,.22) 38%,
      rgba(4,32,58,.78) 100%);
}

/* OVERRIDES existing: .hero-inner — no longer a two-column grid. */
.hero-inner{ position:relative; z-index:2; display:block; }
.hero-copy{ max-width: 50rem; }

/* OVERRIDES existing: .eyebrow colour, inside the hero only. */
.hero .eyebrow{ color: var(--mist); }

/* OVERRIDES existing: .hero-title — white, and sized so that even at three
   lines the button still clears the fold on a small phone. No text-wrap
   balance: it pulls this one onto an extra line and costs more than it buys. */
.hero-title{
  font-size: clamp(1.95rem, 5.4vw, 3.6rem);
  line-height: 1.02; letter-spacing: -0.038em;
  color:#fff;
  margin: 0 0 1.15rem;
  text-shadow: 0 2px 18px rgba(4,32,58,.45);
}

/* OVERRIDES existing: .hero-title em — was --jet, which is far too dark to sit
   on the photo. White text, and the wash line under it carries the accent.
   Inline + clone so the rule redraws per line if the place name wraps. */
.hero-title em{
  display:inline; color:#fff;
  -webkit-box-decoration-break: clone;
          box-decoration-break: clone;
  background-image: linear-gradient(90deg, var(--grime) 0 16%, var(--spray) 16% 23%, var(--mist) 23%);
  background-size: 100% .085em;
  background-position: 0 96%;
}

/* OVERRIDES existing: .hero-lead — light on the photo. */
.hero-lead{
  color: var(--mist);
  font-size: clamp(1.04rem, .98rem + .42vw, 1.26rem);
  max-width: 33em; margin: 0 0 1.9rem;
  text-shadow: 0 1px 12px rgba(4,32,58,.5);
}

.hero-actions{ align-items:center; gap:1rem; }

/* OVERRIDES existing: .hero-marks — light on the photo. */
.hero-marks{ color:#CFE0EE; font-size:.9rem; gap:.55rem 1.7rem; }

/* --------------------------------------------------------- the blue box */
/* He asked for a solid blue box, so this one is not the pill used elsewhere. */
.btn-box{
  display:inline-flex; align-items:center; justify-content:center;
  font-family: var(--font-display); font-weight:800;
  font-size: clamp(1rem, .95rem + .25vw, 1.1rem); letter-spacing:.004em;
  padding: 1.05rem 2.15rem;
  background: var(--jet); color:#fff;
  border:2px solid var(--jet); border-radius:6px;
  text-decoration:none; cursor:pointer;
  box-shadow: 0 16px 30px -12px rgba(0,0,0,.75), inset 0 -3px 0 rgba(0,0,0,.20);
  transition: transform .16s ease, background-color .16s ease, border-color .16s ease, box-shadow .16s ease;
}
.btn-box:hover{
  background: var(--navy); border-color: var(--navy);
  transform: translateY(-2px);
  box-shadow: 0 20px 34px -12px rgba(0,0,0,.8), inset 0 -3px 0 rgba(0,0,0,.20);
}
.btn-box:active{ transform: translateY(0); }

/* the outline twin, for the dark background */
.btn-ghost-dark{
  --btn-fg:#fff;
  border-color: rgba(255,255,255,.55);
  background: rgba(4,32,58,.42);
}
.btn-ghost-dark:hover{ border-color:#fff; background: rgba(4,32,58,.65); }

/* -------------------------------------------------- before / after band */
.reveal-band{
  background: var(--paper-2);
  border-bottom: 1px solid var(--line);
  padding-block: clamp(3rem, 5.5vw, 5rem);
}
.reveal-band-inner{
  display:grid; grid-template-columns: 1fr minmax(0, 460px);
  gap: clamp(2rem, 5vw, 4rem); align-items:center;
}
.reveal-band .section-title{ margin-bottom:.9rem; }
.reveal-band .reveal{ max-width:440px; margin-inline:auto; width:100%; }

/* ------------------------------------------------------------ responsive */
@media (max-width: 1000px){
  /* OVERRIDES existing: @media (max-width:1000px){ .nav{ display:none } } —
     that left every phone with no navigation at all. Without JS the links
     wrap onto a second row of the bar; with JS they become a drawer. */
  .nav{
    display:flex; order:9; width:100%;
    flex-wrap:wrap; gap:.85rem 1.5rem; padding-bottom:.35rem;
  }
  .header-inner{ flex-wrap:wrap; row-gap:.55rem; }

  .nav-js .nav-toggle{ display:inline-flex; }

  .nav-js .nav{
    display:none; order:0; width:auto;
    position:absolute; top:100%; left:0; right:0;
    flex-direction:column; flex-wrap:nowrap; gap:0;
    align-items:stretch;          /* the row rule centres them; not here */
    padding:.25rem 4vw 1.1rem;
    background: var(--ink);
    border-top:1px solid rgba(255,255,255,.12);
    border-bottom:3px solid var(--spray);
    box-shadow: 0 20px 34px -16px rgba(0,0,0,.7);
    max-height: calc(100svh - 4.5rem); overflow-y:auto;
  }
  .nav-js .site-header[data-nav="open"] .nav{
    display:flex; animation: nav-drop .22s ease both;
  }
  .nav-js .nav a{
    padding:1rem .2rem; font-size:1.06rem;
    border-bottom:1px solid rgba(255,255,255,.09);
  }
  .nav-js .nav a:last-child{ border-bottom:0; }
  .nav-js .nav a::after{ display:none; }  /* separators do that job here */
  /* The bar keeps colour + underline for the current section. In the drawer the
     underline is switched off above, so the marker comes back as a side bar —
     never colour on its own. */
  .nav-js .nav a.is-active::after{
    display:block; left:0; right:auto; top:.55rem; bottom:.55rem;
    width:3px; height:auto; border-radius:2px;
  }
  .nav-js .nav a{ padding-left:.85rem; }

  /* The copy runs nearly the full width down here, so the scrim can no longer
     taper off to the right. Vertical only, and heavier. */
  .hero::after{
    background:
      linear-gradient(180deg,
        rgba(4,32,58,.84) 0%,
        rgba(4,32,58,.72) 45%,
        rgba(4,32,58,.88) 100%);
  }

  .reveal-band-inner{ grid-template-columns:1fr; }
}

@media (max-width: 640px){
  .hero-copy{ max-width:none; }
  .hero-actions .btn-box{ width:100%; }
  .hero-title{ letter-spacing:-0.03em; }
  /* tracked-out capitals cost a whole extra line on a phone */
  .hero .eyebrow{ font-size:.65rem; letter-spacing:.16em; margin-bottom:.85rem; }
  /* every pixel saved here is a pixel the quote button gains above the fold */
  .hero{ padding-block: 2.1rem; }
  .hero-lead{ margin-bottom:1.6rem; }

  /* the bar has to hold brand + call + Menu on one row at 375px */
  .brand-mark{ width:36px; height:36px; }
  .brand-chip{ padding:4px; border-radius:9px; }
  .brand-name{ font-size:1.12rem; }
  .brand-sub{ font-size:.58rem; letter-spacing:.22em; }
  .nav-toggle{ padding:.5rem .7rem; }
}

/* Below this the word "Menu" no longer fits beside the call button, so the
   button goes icon-only. The name stays on it for screen readers. */
@media (max-width: 359px){
  .nav-toggle{ padding:.5rem; justify-content:center; }
  .nav-toggle-text{ position:absolute; left:-9999px; width:1px; height:1px; overflow:hidden; }
}


/* ----------------------------------------------------- services (rebuilt)
   Eight surfaces across two groups. The group colour is set once per card as
   custom properties, so nothing depends on where the card sits in the grid.
   -------------------------------------------------------------------------- */

/* OVERRIDES existing: .services — two cards side by side left the softwashing
   card three-quarters empty, so the cards stack and the surfaces run two-up
   inside them instead. */
.services{
  grid-template-columns: 1fr;
  gap: clamp(1.25rem, 2.6vw, 2rem);
}

/* OVERRIDES existing: .service — the left edge now takes the group colour from
   the card's own modifier class rather than from :nth-child(2). */
.service{ border-left-color: var(--svc-key, var(--spray)); }

/* OVERRIDES existing: .service:nth-child(2) — same reason; the positional rule
   would otherwise still win on specificity. */
.service:nth-child(2){ border-left-color: var(--svc-key, var(--spray)); }

/* OVERRIDES existing: .service-what — it is a full-width card now, so the
   intro needs a measure it can be read at. */
.service-what{ max-width: 56ch; }

.service-pressure{
  --svc-key:  var(--spray);
  --svc-ink:  var(--jet);
  --svc-wash: var(--mist);
  --svc-line: linear-gradient(90deg, var(--grime) 0 45%, var(--spray) 45%);
}
.service-soft{
  --svc-key:  var(--grime);
  --svc-ink:  #4E5A3B;      /* grime, dropped far enough to read on white */
  --svc-wash: #EEF1E6;
  --svc-line: linear-gradient(90deg, var(--grime) 0 45%, var(--stone-dk) 45%);
}

.service-head{
  display:flex; align-items:center; gap:1rem;
  margin-bottom:1.05rem;
}
.service-icon{
  flex:none; width:3rem; height:3rem; padding:.6rem;
  border-radius:12px;
  background: var(--svc-wash); color: var(--svc-ink);
  fill:none; stroke:currentColor; stroke-width:1.75;
  stroke-linecap:round; stroke-linejoin:round;
}
.service-kicker{
  font-family: var(--font-display); font-weight:700;
  font-size:.7rem; letter-spacing:.2em; text-transform:uppercase;
  color: var(--svc-ink); margin:0 0 .35rem;
}

/* the surfaces: two up on desktop, each one sitting under its own wash line */
.service-surfaces{
  list-style:none; margin:0; padding:0;
  display:grid; grid-template-columns: repeat(2, minmax(0,1fr));
  gap: clamp(1.1rem, 2.2vw, 1.6rem) clamp(1.5rem, 3vw, 2.75rem);
}
.service-soft .service-surfaces{ grid-template-columns: 1fr; }
.service-soft .surface{ max-width: 44rem; }

.surface{
  position:relative;
  padding-top: 1rem;
  border-top: 1px solid var(--line);
}
.surface::before{
  content:""; position:absolute; left:0; top:-1px;
  width:38px; height:3px; border-radius:2px;
  background: var(--svc-line);
}
.surface-name{
  font-family: var(--font-display); font-weight:700;
  font-size:1.04rem; line-height:1.25; letter-spacing:-0.012em;
  color: var(--navy); margin:0 0 .35rem;
}
.surface-note{ margin:0; font-size:.96rem; color:#33495C; }

/* he listed fascias under pressure washing; it is a soft-brush job, so say so */
.surface-flag{
  display:inline-block; vertical-align:.12em; margin-left:.45rem;
  font-family: var(--font-display); font-weight:700;
  font-size:.66rem; letter-spacing:.1em; text-transform:uppercase;
  background: var(--mist); color: var(--jet);
  padding:.22rem .5rem; border-radius:5px;
}

.service-cta{ margin:1.7rem 0 0; }
.service-cta a{
  display:inline-flex; align-items:center; gap:.5rem;
  font-family: var(--font-display); font-weight:700; font-size:.95rem;
  color: var(--svc-ink); text-decoration:none;
  border-bottom:2px solid var(--svc-key); padding-bottom:.15rem;
  transition: color .16s ease, border-color .16s ease;
}
.service-cta a:hover{ color: var(--navy); border-bottom-color: var(--navy); }
.service-cta svg{
  width:17px; height:17px; flex:none;
  fill:none; stroke:currentColor; stroke-width:2;
  stroke-linecap:round; stroke-linejoin:round;
  transition: transform .16s ease;
}
.service-cta a:hover svg{ transform: translateX(3px); }

@media (max-width: 760px){
  .service-surfaces{ grid-template-columns: 1fr; }
  .service-head{ gap:.85rem; }
  .service-icon{ width:2.6rem; height:2.6rem; padding:.5rem; }
}

@media (prefers-reduced-motion: reduce){
  .service-cta a:hover svg{ transform:none; }
}


/* --------------------------------------------------------------- gallery */
/* One block per job, and a block cannot be split: before on the left, after on
   the right, with the wash line down the middle. The old multi-column masonry
   packed tightly but broke pairs across column boundaries — you would get a
   "before" in one column and its "after" somewhere else — which is the whole
   point of the photo lost to a layout decision. Blocks tile 1 / 2 / 3 across.
   Every tile shares one aspect ratio so the rows line up; both halves of a pair
   come from the same shot, so they crop identically and stay comparable. */

.gallery-controls{
  display:none;                      /* revealed once the script is in, below */
  flex-wrap:wrap; align-items:center; gap:1rem 1.5rem;
  margin-bottom: clamp(1.5rem, 3vw, 2.25rem);
}
.gallery[data-enhanced] .gallery-controls{ display:flex; }

.chips{ display:flex; flex-wrap:wrap; gap:.5rem; }
.chip{
  min-height:44px;
  display:inline-flex; align-items:center; gap:.4rem;
  font-family: var(--font-display); font-weight:700; font-size:.88rem;
  color: var(--navy); background: var(--paper);
  /* --line is only 1.3:1 here; an unpressed toggle has to look like a control */
  border:1.5px solid var(--field-line); border-radius:999px;
  padding:.5rem 1rem; cursor:pointer;
  transition: border-color .15s ease, background-color .15s ease, color .15s ease;
}
.chip:hover{ border-color: var(--spray); }
.chip-n{ font-weight:600; color: var(--muted); margin-left:.3rem; }
.chip[aria-pressed="true"]{
  background: var(--jet); border-color: var(--jet); color:#fff;
}
.chip[aria-pressed="true"] .chip-n{ color: rgba(255,255,255,.72); }

.gallery-count{
  margin:0; font-family: var(--font-display); font-weight:600;
  font-size:.86rem; color: var(--muted);
}
.gallery-count:empty{ display:none; }

.gallery-grid{
  display:grid;
  grid-template-columns: 1fr;
  gap: clamp(1.6rem, 3vw, 2.3rem) clamp(1rem, 2vw, 1.6rem);
  align-items:start;
}
@media (min-width: 700px){ .gallery-grid{ grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1100px){ .gallery-grid{ grid-template-columns: repeat(3, 1fr); } }

/* surface headings run the full width of the grid */
.gal-head{
  grid-column: 1 / -1;
  display:flex; align-items:center; gap:.9rem;
  margin: clamp(.4rem, 1.5vw, 1.1rem) 0 0;
  font-family: var(--font-display); font-weight:700; font-size:.74rem;
  letter-spacing:.2em; text-transform:uppercase; color: var(--muted);
}
.gal-head::after{ content:""; flex:1; height:1px; background: var(--line); }
.gal-head:first-child{ margin-top:0; }
.gal-head[hidden]{ display:none; }

.gal-job{ margin:0; }
.gal-job[hidden]{ display:none; }

/* the 3px seam is the wash line: grime one side, clean the other */
.gal-pair{
  display:grid; grid-template-columns: 1fr 1fr; gap:3px;
  background: var(--stone-dk);
  border-radius:12px; overflow:hidden;
  box-shadow: var(--shadow);
}

.tile{ margin:0; }
.tile[hidden]{ display:none; }

.tile-open{
  display:block; position:relative;
  aspect-ratio: 4/5;
  background: var(--stone);
}
.tile-open img{
  width:100%; height:100%; object-fit:cover;
  transition: transform .35s ease;
}
.tile-open:hover img{ transform: scale(1.04); }

.tile-open .tag{
  top:.6rem; font-size:.62rem; padding:.3rem .6rem; letter-spacing:.1em;
}
.tile-open .tag-before{ left:.6rem; }
.tile-open .tag-after{ right:.6rem; }

/* the magnifier only turns up when you're actually pointing at the tile */
.tile-zoom{
  position:absolute; right:.6rem; bottom:.6rem; z-index:3;
  width:34px; height:34px; border-radius:50%;
  display:grid; place-items:center;
  background: rgba(255,255,255,.94);
  opacity:0; transform: translateY(4px);
  transition: opacity .18s ease, transform .18s ease;
}
.tile-zoom svg{ width:18px; height:18px; fill: var(--jet); }
.tile-open:hover .tile-zoom,
.tile-open:focus-visible .tile-zoom{ opacity:1; transform: none; }

/* One caption per job instead of one per photo — half as much text, and it
   labels the thing you actually care about: the job, not the frame. */
.gal-cap{ margin:.7rem .15rem 0; font-family: var(--font-display); }
.gal-cap strong{
  display:block; font-weight:700; font-size:.98rem;
  color: var(--navy); letter-spacing:-0.01em;
}
.gal-cap span{
  display:block; font-weight:500; font-size:.84rem;
  color: var(--muted); margin-top:.12rem;
}

/* -------------------------------------------------------------- lightbox */
/* <dialog> where it exists; where it doesn't, the script sets the open
   attribute by hand and this rule set still stands the thing up. */
.lightbox{
  position:fixed; inset:0; z-index:200;
  width:100%; height:100%; max-width:100%; max-height:100%;
  margin:0; padding:0; border:0;
  background: rgba(4,32,58,.94);
  color:#fff;
}
.lightbox:not([open]){ display:none; }
.lightbox::backdrop{ background: rgba(4,32,58,.6); }

.lightbox-inner{
  position:relative; height:100%;
  display:grid; place-items:center;
  padding: 3.5rem clamp(3.5rem, 8vw, 5.5rem);
}

.lightbox-figure{ margin:0; max-width:100%; }
.lightbox-img{
  width:auto; height:auto;
  max-width: min(1100px, 100%); max-height: 72vh;
  border-radius:10px; background: rgba(255,255,255,.06);
  transition: opacity .18s ease;
}
.lightbox-img.is-loading{ opacity:0; }

.lightbox-cap{
  display:flex; flex-wrap:wrap; align-items:baseline; gap:.4rem .9rem;
  margin-top:.9rem;
  font-family: var(--font-display); font-weight:600; font-size:.92rem;
}
.lightbox-text{ color:#E4EEF6; }
.lightbox-count{ color:#9FBBD2; font-size:.82rem; letter-spacing:.06em; }

.lightbox-nav{
  position:absolute; z-index:2;
  width:46px; height:46px; border-radius:50%;
  display:grid; place-items:center;
  background: rgba(255,255,255,.14); color:#fff;
  border:1.5px solid rgba(255,255,255,.28);
  cursor:pointer;
  transition: background-color .15s ease, border-color .15s ease;
}
.lightbox-nav svg{ width:22px; height:22px; fill: currentColor; }
.lightbox-nav:hover{ background: var(--jet); border-color: var(--jet); }

.lightbox-prev{ left: clamp(.6rem, 2vw, 1.5rem); top:50%; transform: translateY(-50%); }
.lightbox-next{ right: clamp(.6rem, 2vw, 1.5rem); top:50%; transform: translateY(-50%); }
.lightbox-close{ top: clamp(.6rem, 2vw, 1.5rem); right: clamp(.6rem, 2vw, 1.5rem); }

.lightbox[open]{ animation: lb-fade .18s ease-out; }
.lightbox[open] .lightbox-figure{ animation: lb-rise .22s ease-out; }
@keyframes lb-fade{ from{ opacity:0; } }
@keyframes lb-rise{ from{ opacity:0; transform: translateY(10px); } }

@media (max-width: 640px){
  /* One job per row on a phone, so before and after are still side by side —
     you should never have to scroll to compare them. */
  .gal-head{ font-size:.68rem; letter-spacing:.16em; }
  .lightbox-inner{ padding: 4rem .8rem 1rem; }
  .lightbox-img{ max-height: 62vh; }
  .lightbox-prev{ left:.6rem; }
  .lightbox-next{ right:.6rem; }
}

@media (prefers-reduced-motion: reduce){
  .lightbox[open],
  .lightbox[open] .lightbox-figure{ animation: none; }
  .tile-open:hover img{ transform: none; }
}


/* ---------------------------------------------------------------- reviews */
/* Quietest tint on the sheet so it reads as a breather between the dark work
   grid and whatever follows. Earns its top edge with the wash line instead of
   a border. */
.reviews{ position:relative; background: var(--paper-2); }
.reviews::before{
  content:""; position:absolute; top:0; left:0; right:0; height:5px;
  background: linear-gradient(90deg, var(--grime) 0 20%, var(--spray) 20% 28%, var(--mist) 28%);
}

/* draft notice — goes in the bin with the placeholders */
.draft-note{
  margin: 0 0 clamp(1.6rem, 3vw, 2.4rem);
  padding: .8rem 1.15rem;
  border: 2px dashed var(--stone-dk); border-radius: 10px;
  background: var(--stone); color: var(--ink);
  font-family: var(--font-display); font-weight:600; font-size:.9rem;
}
.draft-note strong{ font-weight:800; }

/* An empty slot, drawn as one. Dashed edge means nothing real is in here yet;
   once the words are pasted in, the .fill-slot / .fill-blank classes come off. */
.fill-slot{
  margin: 0 0 1.05rem;
  padding: clamp(.85rem, 2vw, 1.15rem) clamp(1rem, 2.2vw, 1.35rem);
  /* jet, not spray: spray on mist is 2.97:1 and the dashed edge is the thing
     telling you this is empty */
  border: 2px dashed var(--jet); border-radius: 10px;
  background: var(--mist);
}
.fill-slot p{
  margin:0;
  font-family: var(--font-display); font-weight:700;
  font-size:.82rem; letter-spacing:.11em; line-height:1.55; text-transform:uppercase;
  color: var(--jet);
}
.fill-blank{ border-bottom: 2px dashed var(--spray); color: var(--muted); }

/* ---------------------------------------------------- the named endorsement */
.endorse{
  display:grid;
  grid-template-columns: minmax(0,.78fr) minmax(0,1.22fr);
  gap: clamp(1.4rem, 3.4vw, 3rem); align-items:start;
  margin: 0 0 clamp(1.6rem, 3.2vw, 2.6rem);
  padding: clamp(1.5rem, 3.2vw, 2.6rem);
  background: var(--paper);
  border:1px solid var(--line); border-left:5px solid var(--jet);
  border-radius: var(--radius);
  box-shadow: var(--shadow);
}
.endorse .eyebrow{ margin-bottom:.9rem; }
.endorse-name{
  font-size: clamp(1.6rem, 1.25rem + 1.4vw, 2.3rem);
  color: var(--navy);
}
.endorse-job{
  margin:.8rem 0 0;
  font-family: var(--font-display); font-weight:600; font-size:.88rem;
  color: var(--muted);
}

/* ------------------------------------------------------------ review cards */
.reviews-list{ display:grid; gap: clamp(1.1rem, 2.4vw, 1.75rem); }
.review{
  display:grid;
  grid-template-columns: minmax(0,1.05fr) minmax(0,.95fr);
  gap: clamp(1.2rem, 3vw, 2.4rem); align-items:center;
  margin:0; padding: clamp(1.15rem, 2.4vw, 1.8rem);
  background: var(--paper);
  border:1px solid var(--line); border-radius: var(--radius);
  box-shadow: var(--shadow);
}
/* Photo swaps sides down the list so it reads as a rhythm, not a stack.
   The column widths swap with it, so the photo is the same size either way and
   the cards stay the same height. */
.reviews-list .review:nth-child(even){ grid-template-columns: minmax(0,.95fr) minmax(0,1.05fr); }
.reviews-list .review:nth-child(even) .review-shot{ order:-1; }

.review-shot{ border-radius:10px; overflow:hidden; background: var(--stone); }
.review-shot img{ width:100%; height:auto; aspect-ratio: 4/3; object-fit:cover; }

/* Jet, not amber. Amber on a near-white card is nowhere near legible. */
.stars{ display:flex; align-items:center; gap:.14rem; margin:0 0 .85rem; color: var(--jet); }
.stars svg{ width:19px; height:19px; fill: currentColor; flex:none; }

.review-who{ margin:0; }
.review-name{
  margin:0;
  font-family: var(--font-display); font-weight:700; font-size:1.02rem;
  letter-spacing:-0.01em; color: var(--navy);
}
.review-meta{ margin:.15rem 0 0; font-size:.86rem; color: var(--muted); }

/* --------------------------------------------------------- read them all */
.reviews-more{
  margin: clamp(1.8rem, 3.4vw, 2.6rem) 0 0;
  display:flex; flex-wrap:wrap; align-items:center; gap:.9rem 1.25rem;
}
/* --stone-dk is only 1.7:1 on this band, so the button's own outline would not
   read as a control. Same neutral as the form and the filter chips. */
.reviews-more .btn-ghost{ --btn-bg: var(--paper); border-color: var(--field-line); }
.reviews-note{ margin:0; font-size:.86rem; color: var(--muted); }

/* --------------------------------------------------------------- utilities */
/* holds the <symbol> only; nothing paints from it */
.svg-sprite{ display:none; }

/* Stacks earlier than the 1000px rule elsewhere: a review card needs real
   width on both sides before the quote column gets uncomfortable. */
@media (max-width: 860px){
  .endorse{ grid-template-columns: 1fr; }
  /* the even-card selector above is more specific, so it has to be named again */
  .review,
  .reviews-list .review:nth-child(even){ grid-template-columns: 1fr; }
  .reviews-list .review .review-shot,
  .reviews-list .review:nth-child(even) .review-shot{ order:-1; }
  .review-shot img{ aspect-ratio: 16/10; }
}

@media (max-width: 640px){
  .reviews-more .btn{ width:100%; justify-content:center; }
}


/* --------------------------------------------------------------- contact */
/* Sticky header is ~62px, so anchored jumps need clearing.
   The same would suit the other section ids if anyone wants to add it. */
#contact, .anchor-alias{ scroll-margin-top: 5.5rem; }

/* #quote is the old id for this section and links still point at it.
   Zero-height target, nothing to see. */
.anchor-alias{ display:block; height:0; }


/* Form column comes first in the source, so it stays first when this stacks
   on mobile and the tab order never disagrees with what's on screen. */
.contact-grid{
  display:grid; grid-template-columns: 1.1fr .9fr;
  gap: clamp(2rem, 4.5vw, 4rem); align-items:start;
}

.contact-sub{
  font-size: clamp(1.2rem, 1.08rem + .4vw, 1.45rem);
  color: var(--navy); margin-bottom:.85rem;
}
.form-intro{ color: var(--muted); max-width:38em; margin:0 0 1.5rem; }

.contact-aside{ display:grid; gap: clamp(1.9rem, 3.5vw, 2.75rem); }
.contact-block .contact{ margin-top:0; }
/* long email address in a narrow column */
.contact-block .contact dd{ overflow-wrap:anywhere; }
/* the areas line isn't a link, so it doesn't need the weight the rest carry */
.contact dd.contact-note{ font-weight:500; font-size:1rem; color:#33495C; }

/* ------------------------------------------------------------ service map */
.service-map{ margin:0; }
.map-frame{
  position:relative;
  aspect-ratio: 4/3; min-height:260px;   /* Google won't render below 200px */
  border:1px solid var(--line); border-radius: var(--radius);
  background: var(--mist); overflow:hidden;
  box-shadow: var(--shadow);
}
.map-embed{ position:absolute; inset:0; display:block; width:100%; height:100%; border:0; }

/* Sits behind the iframe, so it only ever shows if the embed is blocked —
   and plenty of people block third-party embeds. The figcaption below carries
   the same information for everyone else, which is why this is aria-hidden. */
.map-fallback{
  position:absolute; inset:0; margin:0; padding:1.5rem;
  display:grid; place-items:center; text-align:center;
  font-family: var(--font-display); font-weight:600;
  color: var(--jet); background: var(--mist);
}

.service-map figcaption{
  margin-top:.85rem; font-size:.92rem; color: var(--muted);
}
.service-map figcaption a{
  color: var(--jet); font-weight:600;
  text-decoration-color: var(--spray); text-underline-offset:3px;
  white-space:nowrap;
}
.service-map figcaption a:hover{ color: var(--navy); }

/* ------------------------------------------------------------ responsive */
@media (max-width: 1000px){
  .contact-grid{ grid-template-columns: 1fr; }
}

/* ------------------------------------------------------ sticky contact */
/* It sits under the header (z-50) so the mobile drawer covers it, and under
   the lightbox, which is in the top layer anyway. */
.fab{
  position: fixed;
  right: clamp(.85rem, 2.5vw, 1.5rem);
  bottom: calc(clamp(.85rem, 2.5vw, 1.5rem) + env(safe-area-inset-bottom, 0px));
  z-index: 40;
  display: inline-flex; align-items: center; gap: .55rem;
  min-height: 52px; padding: .85rem 1.4rem;
  font-family: var(--font-display); font-weight: 800; font-size: .95rem;
  letter-spacing: -0.004em;
  color: #fff; background: var(--jet);
  border: 2px solid var(--jet); border-radius: 999px;
  text-decoration: none; cursor: pointer;
  box-shadow: 0 12px 30px -8px rgba(4,32,58,.55), 0 2px 6px rgba(4,32,58,.28);
  /* hidden until main.js says otherwise, so it can never cover the form */
  opacity: 0; transform: translateY(14px) scale(.96); pointer-events: none;
  transition: opacity .22s ease, transform .22s ease,
              background-color .16s ease, border-color .16s ease;
}
.fab[data-show]{ opacity:1; transform:none; pointer-events:auto; }
.fab:hover{ background: var(--navy); border-color: var(--navy); }
.fab:active{ transform: translateY(1px); }
.fab-icon{ width:19px; height:19px; fill: currentColor; flex:none; }

/* It floats over whatever happens to be behind it — white gallery one moment,
   navy work grid the next — so the ring is white inside a dark halo and one of
   the two always shows. Same trick as the hero. */
.fab:focus-visible{
  outline: 3px solid #fff; outline-offset: 2px;
  box-shadow: 0 0 0 8px rgba(4,32,58,.85), 0 12px 30px -8px rgba(4,32,58,.55);
}

/* the drawer owns the screen while it is open */
.nav-open .fab{ opacity:0; pointer-events:none; transform: translateY(14px) scale(.96); }

@media (max-width: 380px){
  .fab{ padding:.8rem 1.15rem; font-size:.9rem; gap:.45rem; }
}

@media (prefers-reduced-motion: reduce){
  .fab{ transform:none; }
  .fab[data-show]{ transform:none; }
  .fab:active{ transform:none; }
}


/* ==========================================================================
   MULTI-PAGE REBUILD
   The site is no longer one scrolling page. Header, footer, reviews and the
   process boxes are now shared furniture that has to look identical on eight
   different pages, so everything below is written to work anywhere rather
   than to sit in one known place on one known page.
   ========================================================================== */

/* ------------------------------------------------------------------ topbar */
/* The socials sit above the bar, not in it. Three more things in the header
   row and the bar cannot hold brand + nav + call button at 1024px. This strip
   deliberately does NOT stick — only the bar below it does, so the sticky
   height stays where it was. */
.topbar{
  background: #021A2F;
  border-bottom: 1px solid rgba(255,255,255,.08);
  color: #A9C2D6;
}
.topbar-inner{
  display:flex; align-items:center; justify-content:space-between;
  gap:1rem; padding-block:.4rem; flex-wrap:wrap;
}

.social{ display:flex; align-items:center; gap:.4rem; list-style:none; margin:0; padding:0; }
.social a{
  display:grid; place-items:center;
  width:34px; height:34px; border-radius:9px;
  color:#CFE0EE; background: rgba(255,255,255,.08);
  transition: background-color .16s ease, color .16s ease, transform .16s ease;
}
.social a:hover{ background:#fff; color: var(--ink); transform: translateY(-1px); }
.social svg{ width:17px; height:17px; fill: currentColor; }
/* The Google mark is four fixed colours — it cannot take currentColor, so it
   gets a permanent white chip to sit on instead of inheriting the strip. */
.social .social-google{ background:#fff; }
.social .social-google:hover{ background:#fff; transform: translateY(-1px); }
.social .social-google svg{ fill:none; }

.topbar-links{ display:flex; align-items:center; gap:.35rem 1.1rem; flex-wrap:wrap; }
.topbar-link{
  display:inline-flex; align-items:center; gap:.45rem;
  font-family: var(--font-display); font-weight:600; font-size:.85rem;
  color:#CFE0EE; text-decoration:none; padding-block:.3rem;
}
.topbar-link:hover{ color:#fff; text-decoration:underline; text-underline-offset:3px; }
.topbar-link svg{ width:15px; height:15px; fill: currentColor; flex:none; }
.topbar-link.is-wa svg{ color:#5AE092; }

@media (max-width: 560px){
  .topbar-inner{ justify-content:center; }
  /* the phone is already a button in the bar below; at this width the strip
     keeps the icons and drops the repeat */
  .topbar-link.is-phone{ display:none; }
}

/* ------------------------------------------------------- services dropdown */
.nav-item{ position:relative; display:flex; align-items:center; gap:.15rem; }
.nav-sub-toggle{
  display:inline-grid; place-items:center;
  width:26px; height:26px; padding:0;
  background:none; border:0; border-radius:6px;
  color:#CFE0EE; cursor:pointer;
}
.nav-sub-toggle:hover{ color:#fff; background: rgba(255,255,255,.10); }
.nav-sub-toggle svg{ width:11px; height:11px; fill: currentColor; transition: transform .18s ease; }
.nav-item[data-open] .nav-sub-toggle svg{ transform: rotate(180deg); }

.nav-sub{
  position:absolute; top:100%; left:-.9rem; z-index:60;
  display:none; min-width:15.5rem;
  list-style:none; margin:.55rem 0 0; padding:.4rem;
  background: var(--ink);
  border:1px solid rgba(255,255,255,.14); border-radius:12px;
  box-shadow: 0 22px 44px -18px rgba(0,0,0,.85);
}
/* Bridges the gap between the link and the panel. Without it the panel closes
   the moment the pointer crosses the margin above it. */
.nav-sub::before{ content:""; position:absolute; left:0; right:0; top:-.7rem; height:.7rem; }
.nav-item[data-open] > .nav-sub,
.nav-item:hover > .nav-sub,
.nav-item:focus-within > .nav-sub{ display:block; }
.nav-sub a{
  display:block; padding:.62rem .8rem; border-radius:8px;
  font-size:.94rem; color:#CFE0EE;
}
.nav-sub a::after{ display:none; }
.nav-sub a:hover{ background: rgba(255,255,255,.10); color:#fff; }
.nav-sub a[aria-current="page"]{ color: var(--spray); background: rgba(54,144,204,.14); }

/* current PAGE, not current section — same treatment the scrollspy used */
.nav a[aria-current="page"]{ color: var(--spray); }
.nav > a[aria-current="page"]::after,
.nav-item > a[aria-current="page"]::after{ right:0; }

@media (max-width: 1000px){
  /* In the drawer the panel is just an indented list. A dropdown inside a
     drawer is two disclosures deep for no gain, so the arrow button goes. */
  .nav-js .nav-item{ display:block; }
  /* The other drawer links are flex children of a stretched column, so they
     fill the width on their own. "Services" is one level down inside .nav-item
     and stays inline unless told otherwise — which left it with a tap target
     and an underline only as wide as the word. */
  .nav-js .nav-item > a{ display:block; }
  .nav-js .nav-sub-toggle{ display:none; }
  .nav-js .nav-sub{
    position:static; display:block; min-width:0;
    margin:0 0 .25rem; padding:0 0 0 .9rem;
    background:none; border:0; box-shadow:none;
  }
  .nav-js .nav-sub::before{ display:none; }
  .nav-js .nav-sub a{
    padding:.72rem .2rem .72rem .85rem; font-size:.98rem; border-radius:0;
    border-left:2px solid rgba(255,255,255,.18);
    border-bottom:1px solid rgba(255,255,255,.07);
  }
  .nav-js .nav-sub li:last-child a{ border-bottom:0; }
}

/* -------------------------------------------------------------- page heads */
/* Interior pages get the dark band the home page gets from the hero photo, so
   the bar never floats on white with nothing under it. */
.page-head{
  position:relative; isolation:isolate; overflow:hidden;
  background: var(--ink); color:#E4EEF6;
  padding-block: clamp(2.6rem, 5.5vw, 4.5rem);
}
.page-head-photo{
  position:absolute; inset:0; z-index:0;
  width:100%; height:100%; object-fit:cover; object-position:50% 58%;
}
/* Same trick as the hero: heavy across the left where the words are, thin on
   the right so the photo still reads as a photo. The first pass here was so
   dark the picture may as well not have loaded. Worst case for the headline is
   a near-white pixel under the thinnest part of the wash on the LEFT, which
   still leaves white text at 13:1 — the thin right-hand end never has type
   over it at this width. */
.page-head::after{
  content:""; position:absolute; inset:0; z-index:1; pointer-events:none;
  background:
    linear-gradient(100deg, rgba(4,32,58,.90) 0%, rgba(4,32,58,.82) 52%, rgba(3,44,75,.42) 100%),
    linear-gradient(180deg, rgba(4,32,58,.50) 0%, rgba(4,32,58,.18) 45%, rgba(4,32,58,.72) 100%);
}
/* Below this the copy runs nearly the full width, so the wash can no longer
   taper off to the right. Vertical only, and heavier. */
@media (max-width: 1000px){
  .page-head::after{
    background: linear-gradient(180deg,
      rgba(4,32,58,.86) 0%, rgba(4,32,58,.74) 45%, rgba(4,32,58,.90) 100%);
  }
}
.page-head .wrap{ position:relative; z-index:2; }

/* The eyebrow brings its own dash and the title brings the wash line. Stacked
   20px apart they read as a mistake, so in here the eyebrow goes without. */
.page-head .eyebrow::before{ display:none; }
.page-title{
  font-size: clamp(2.2rem, 1.65rem + 2.5vw, 3.7rem);
  font-weight:900; font-stretch:116%; letter-spacing:-0.038em;
  color:#fff; margin:0 0 1rem;
}
.page-title::before{
  content:""; display:block; width:96px; height:5px; border-radius:3px;
  margin-bottom:1.1rem;
  background: linear-gradient(90deg, var(--grime) 0 34%, var(--spray) 34% 44%, rgba(255,255,255,.4) 44%);
}
.page-lead{ color:#C4DAEA; font-size: clamp(1.02rem,.98rem+.4vw,1.2rem); max-width:46ch; margin:0 0 1.7rem; }
.page-head .eyebrow{ color: var(--mist); }
.page-actions{ display:flex; flex-wrap:wrap; gap:.85rem; }

/* crumbs — cheap orientation once there is more than one page */
.crumbs{ margin:0 0 1.2rem; font-size:.84rem; color:#9FB9CF; }
.crumbs a{ color:#CFE0EE; text-decoration:none; }
.crumbs a:hover{ color:#fff; text-decoration:underline; text-underline-offset:3px; }
.crumbs span{ padding-inline:.45rem; }

/* -------------------------------------------------------------- the promise */
.promise{
  background: var(--mist); border-bottom:1px solid var(--line);
  padding-block: clamp(1.5rem, 3vw, 2.35rem);
}
.promise p{
  margin:0; text-align:center;
  font-family: var(--font-display); font-weight:700;
  font-size: clamp(1.06rem, 1rem + .6vw, 1.55rem);
  letter-spacing:-0.018em; color: var(--navy);
  max-width: 34ch; margin-inline:auto; line-height:1.24;
}

/* ------------------------------------------------------- what do we offer? */
/* Photo and words swap sides down the list, exactly as the brief draws it. */
.offers{ display:grid; gap: clamp(2.2rem, 5vw, 4rem); }
.offer{
  display:grid; grid-template-columns: minmax(0,1fr) minmax(0,1fr);
  gap: clamp(1.5rem, 4vw, 3.25rem); align-items:center;
}
.offer-shot{
  display:block; margin:0; position:relative; aspect-ratio: 4/3;
  border-radius: var(--radius); overflow:hidden;
  box-shadow: var(--shadow); background: var(--stone);
}
.offer-shot img{ width:100%; height:100%; object-fit:cover; transition: transform .45s ease; }
.offer-shot:hover img{ transform: scale(1.045); }
.offer.is-flipped .offer-shot{ order:2; }

.offer-name{
  font-size: clamp(1.6rem, 1.3rem + 1.3vw, 2.35rem);
  color: var(--navy); margin:0 0 .85rem;
}
.offer-name a{ color:inherit; text-decoration:none; }
.offer-name a:hover{ color: var(--jet); }
/* the whole tile is clickable, but the name keeps a real focusable link so the
   keyboard and the screen reader both get one clear target per service */
.offer-name a::after{ content:""; position:absolute; inset:0; z-index:3; }
.offer-copy{ position:relative; }
.offer-copy p{ color:#33495C; margin:0 0 1.3rem; max-width:44ch; }
.offer-go{
  display:inline-flex; align-items:center; gap:.5rem;
  font-family: var(--font-display); font-weight:700; font-size:.95rem;
  color: var(--jet); border-bottom:2px solid var(--spray); padding-bottom:.15rem;
}
.offer-go svg{
  width:17px; height:17px; flex:none;
  fill:none; stroke:currentColor; stroke-width:2;
  stroke-linecap:round; stroke-linejoin:round; transition: transform .16s ease;
}
.offer:hover .offer-go{ color: var(--navy); border-bottom-color: var(--navy); }
.offer:hover .offer-go svg{ transform: translateX(3px); }

@media (max-width: 820px){
  .offer{ grid-template-columns:1fr; gap:1.4rem; }
  .offer.is-flipped .offer-shot{ order:0; }
}
@media (prefers-reduced-motion: reduce){
  .offer-shot:hover img{ transform:none; }
  .offer:hover .offer-go svg{ transform:none; }
}

/* ------------------------------------------------------ selling-point cards */
/* The numbered points down a service page. They borrow .service-cta for the
   arrow link, which is why each one sets the two --svc- properties. */
.pillars{ display:grid; gap: clamp(1.1rem, 2.4vw, 1.75rem); }
.pillar{
  --svc-key: var(--spray);
  --svc-ink: var(--jet);
  margin:0; padding: clamp(1.35rem, 2.9vw, 2.1rem);
  background: var(--paper);
  border:1px solid var(--line); border-left:5px solid var(--svc-key);
  border-radius: var(--radius); box-shadow: var(--shadow);
}
.pillars-soft .pillar{ --svc-key: var(--grime); --svc-ink:#4E5A3B; }
.pillar-n{
  display:inline-grid; place-items:center;
  width:2.1rem; height:2.1rem; border-radius:8px; margin-bottom:.85rem;
  background: var(--mist); color: var(--svc-ink);
  font-family: var(--font-display); font-weight:800; font-size:1rem;
}
.pillars-soft .pillar-n{ background:#EEF1E6; }
.pillar-name{
  font-size: clamp(1.24rem, 1.1rem + .65vw, 1.65rem);
  color: var(--navy); margin:0 0 .7rem;
}
.pillar p{ margin:0 0 .9rem; color:#33495C; max-width:62ch; }
.pillar p:last-of-type{ margin-bottom:0; }
.pillar .service-cta{ margin-top:1.25rem; }

/* ----------------------------------------------------------- our process */
/* Three boxes side by side, as drawn. They stay side by side down to tablet,
   then stack — a three-across grid at 380px is three unreadable columns. */
.process{
  display:grid; grid-template-columns: repeat(3, minmax(0,1fr));
  gap: clamp(1rem, 2.4vw, 1.75rem);
  counter-reset: step;
}
.process-step{
  position:relative; margin:0;
  padding: clamp(1.35rem, 2.8vw, 2rem);
  background: var(--paper);
  border:1px solid var(--line); border-radius: var(--radius);
  box-shadow: var(--shadow);
}
/* the wash line again, one step further along in each box */
.process-step::before{
  content:""; position:absolute; left:0; top:-1px; height:4px;
  border-radius: var(--radius) var(--radius) 0 0;
  background: linear-gradient(90deg, var(--grime) 0 42%, var(--spray) 42% 52%, var(--mist) 52%);
}
.process-step:nth-child(1)::before{ left:0; width:34%; }
.process-step:nth-child(2)::before{ left:0; width:67%; }
.process-step:nth-child(3)::before{ left:0; right:0; width:auto; }

.step-n{
  display:block;
  font-family: var(--font-display); font-weight:800;
  font-size:.7rem; letter-spacing:.2em; text-transform:uppercase;
  color: var(--jet); margin-bottom:.55rem;
}
.step-name{
  font-size: clamp(1.1rem, 1rem + .5vw, 1.35rem);
  color: var(--navy); margin:0 0 .6rem;
}
.process-step p{ margin:0; color:#33495C; font-size:.98rem; }

.section-dark .process-step{
  background: rgba(255,255,255,.055);
  border-color: rgba(255,255,255,.13); box-shadow:none;
}
.section-dark .step-name{ color:#fff; }
.section-dark .step-n{ color: var(--spray); }
.section-dark .process-step p{ color:#B6CCDF; }

@media (max-width: 860px){
  .process{ grid-template-columns:1fr; }
  .process-step::before{ left:0 !important; right:0 !important; width:auto !important; }
}

/* -------------------------------------------------------- page + side rail */
/* "A carousel of reviews on each page, on the left or right, showing one at a
   time." It is a column beside the content on a desktop and a normal block
   under it on a phone — a sticky carousel on a 375px screen is a thing in the
   way of the content it is meant to support. */
.with-rail{
  display:grid; grid-template-columns: minmax(0,1fr) 320px;
  gap: clamp(2rem, 4vw, 3.5rem); align-items:start;
}
@media (max-width: 1060px){
  .with-rail{ grid-template-columns:1fr; }
}

.rail{
  position:sticky; top: 5.6rem;
  margin:0; padding: clamp(1.15rem, 2.4vw, 1.5rem);
  background: var(--paper);
  border:1px solid var(--line); border-radius: var(--radius);
  box-shadow: var(--shadow);
}
@media (max-width: 1060px){
  .rail{ position:static; max-width: 34rem; }
}
.rail-head{ display:flex; align-items:baseline; justify-content:space-between; gap:.75rem; margin-bottom:.9rem; }
.rail-kicker{
  margin:0;
  font-family: var(--font-display); font-weight:700;
  font-size:.68rem; letter-spacing:.2em; text-transform:uppercase; color: var(--muted);
}
.rail-view{ min-height: 13.5rem; }
.rail-slide{ animation: rail-in .28s ease both; }
@keyframes rail-in{ from{ opacity:0; transform: translateY(6px); } to{ opacity:1; transform:none; } }
.rail-quote{ margin:0 0 .9rem; font-size:.99rem; color:#25384A; }
.rail-quote p{ margin:0; }
.rail .stars{ margin-bottom:.7rem; }
.rail .fill-slot{ margin-bottom:.9rem; }
.rail .fill-slot p{ font-size:.72rem; letter-spacing:.09em; }

.rail-foot{
  display:flex; align-items:center; gap:.5rem;
  margin-top:1.1rem; padding-top:.9rem; border-top:1px solid var(--line);
}
.rail-btn{
  display:grid; place-items:center;
  width:38px; height:38px; flex:none;
  background: var(--paper); color: var(--navy);
  border:1.5px solid var(--field-line); border-radius:50%; cursor:pointer;
  transition: border-color .15s ease, background-color .15s ease, color .15s ease;
}
.rail-btn:hover{ border-color: var(--jet); background: var(--jet); color:#fff; }
.rail-btn svg{ width:15px; height:15px; fill: currentColor; }
.rail-count{ margin:0 0 0 auto; font-size:.82rem; color: var(--muted); font-variant-numeric: tabular-nums; }
.rail-more{
  display:inline-block; margin-top:.9rem;
  font-family: var(--font-display); font-weight:700; font-size:.9rem;
  color: var(--jet); text-decoration-color: var(--spray); text-underline-offset:3px;
}

/* --------------------------------------------------------- review tiles */
/* Tiled, not a carousel — the brief is explicit about that. Photo, five
   stars, the words. */
.review-tiles{
  display:grid; grid-template-columns: repeat(auto-fill, minmax(min(100%, 300px), 1fr));
  gap: clamp(1.1rem, 2.4vw, 1.75rem);
}
.review-tile{
  display:flex; flex-direction:column; margin:0;
  background: var(--paper);
  border:1px solid var(--line); border-radius: var(--radius);
  box-shadow: var(--shadow); overflow:hidden;
}
.review-tile-shot{ background: var(--stone); }
.review-tile-shot img{ width:100%; height:auto; aspect-ratio: 4/3; object-fit:cover; }
.review-tile-body{
  display:flex; flex-direction:column; flex:1;
  padding: clamp(1.1rem, 2.2vw, 1.45rem);
}
.review-tile-body blockquote{ margin:0 0 1rem; color:#25384A; }
.review-tile-body blockquote p{ margin:0; }
.review-tile-body .review-who{ margin-top:auto; }

/* -------------------------------------------------------- contact methods */
.methods{
  display:grid; grid-template-columns: repeat(auto-fit, minmax(min(100%, 210px), 1fr));
  gap:.75rem; list-style:none; margin:0; padding:0;
}
.method{
  display:flex; align-items:center; gap:.8rem;
  padding:.9rem 1.05rem; min-height:60px;
  background: var(--paper); color: var(--navy);
  border:1px solid var(--line); border-radius:12px;
  text-decoration:none;
  transition: border-color .15s ease, transform .15s ease, box-shadow .15s ease;
}
.method:hover{ border-color: var(--spray); transform: translateY(-2px); box-shadow: var(--shadow); }
.method-icon{ display:grid; place-items:center; width:34px; height:34px; flex:none; border-radius:9px; background: var(--mist); color: var(--jet); }
.method-icon svg{ width:18px; height:18px; fill: currentColor; }
.method-text{ display:grid; gap:.1rem; min-width:0; }
.method-label{
  font-family: var(--font-display); font-weight:700;
  font-size:.66rem; letter-spacing:.16em; text-transform:uppercase; color: var(--muted);
}
.method-value{ font-weight:600; font-size:.98rem; overflow-wrap:anywhere; }

/* WhatsApp keeps its own green, because a green WhatsApp button is a thing
   people recognise without reading it. Ink on #25D366 is 8.4:1. */
.btn-wa{ --btn-bg:#25D366; --btn-fg: var(--ink); border-color:#25D366; }
.btn-wa:hover{ --btn-bg:#1EBE5B; border-color:#1EBE5B; }
.btn-wa svg{ width:19px; height:19px; fill: currentColor; flex:none; }
.method-wa .method-icon{ background:#DFF7E7; color:#0B7F3F; }

/* ------------------------------------------------------------ map radius */
/* "Map radius with how far we go." Google's keyless embed cannot draw one, so
   the ring is ours, sitting on top. main.js sizes it from the real
   metres-per-pixel at the embed's zoom, so it is to scale rather than
   decorative — but it is still labelled "approximate", because the edge of a
   service area is a conversation, not a line on a map. */
.map-radius{
  position:absolute; left:50%; top:50%; z-index:2;
  width: var(--dia, 62%); aspect-ratio:1;
  transform: translate(-50%,-50%);
  border:2px dashed rgba(4,32,58,.8); border-radius:50%;
  background: rgba(54,144,204,.15);
  pointer-events:none;
}
/* The ring's size in pixels comes from the zoom, not from the frame — 15 miles
   is 249px whether the map is 500px wide or 340px. On a phone a 4:3 frame is
   only 260px tall, so the circle ends up touching both edges. Squaring the
   frame gives it room without changing the scale. */
@media (max-width: 700px){
  .map-frame{ aspect-ratio: 1/1; }
}

.map-radius-label{
  position:absolute; left:50%; bottom:.6rem; z-index:3;
  transform: translateX(-50%);
  margin:0; padding:.35rem .7rem;
  background: rgba(4,32,58,.9); color:#fff; border-radius:6px;
  font-family: var(--font-display); font-weight:700; font-size:.72rem;
  letter-spacing:.04em; white-space:nowrap; pointer-events:none;
}

/* ------------------------------------------------------------------ about */
.about-grid{
  display:grid; grid-template-columns: minmax(0,1.15fr) minmax(0,.85fr);
  gap: clamp(2rem, 4.5vw, 3.5rem); align-items:start;
}
.about-copy p{ color:#33495C; max-width:60ch; }
.about-shot{ margin:0; border-radius: var(--radius); overflow:hidden; box-shadow: var(--shadow); }
.facts{
  display:grid; gap:.9rem; list-style:none; margin:1.8rem 0 0; padding:0;
}
.fact{
  display:flex; gap:.85rem; align-items:flex-start;
  padding:1rem 1.15rem;
  background: var(--paper-2); border:1px solid var(--line); border-radius:12px;
}
.fact svg{ width:20px; height:20px; flex:none; margin-top:.15rem; fill:none; stroke: var(--jet); stroke-width:2; stroke-linecap:round; stroke-linejoin:round; }
.fact strong{ display:block; font-family: var(--font-display); color: var(--navy); }
.fact span{ font-size:.94rem; color:#33495C; }
@media (max-width: 900px){ .about-grid{ grid-template-columns:1fr; } }

/* ------------------------------------------------------------- odds + ends */
/* A plain band that ends a page with the one thing we want next. */
.cta-band{ background: var(--navy); color:#E4EEF6; padding-block: clamp(2.5rem,5vw,4rem); }
.cta-band-inner{ display:flex; flex-wrap:wrap; align-items:center; justify-content:space-between; gap:1.5rem; }
.cta-band h2{ color:#fff; font-size: clamp(1.6rem,1.3rem+1.4vw,2.4rem); margin:0 0 .5rem; }
.cta-band p{ margin:0; color:#A9C2D6; max-width:44ch; }
.cta-band .btn-ghost{ --btn-fg:#fff; border-color: rgba(255,255,255,.55); }
.cta-band .btn-ghost:hover{ border-color:#fff; }

/* Footer gains a real column layout once there are pages to link to. */
.footer-inner{ grid-template-columns: minmax(0,1.3fr) repeat(2, minmax(0,1fr)); gap: 2rem; align-items:start; }
.footer-col h2{
  font-family: var(--font-display); font-weight:700;
  font-size:.7rem; letter-spacing:.2em; text-transform:uppercase;
  color:#fff; margin:0 0 .9rem;
}
.footer-links{ display:grid; gap:.55rem; }
.footer-links a{
  color:#CFE0EE; text-decoration:none;
  font-family: var(--font-display); font-weight:600; font-size:.92rem;
}
.footer-links a:hover{ color:#fff; text-decoration:underline; text-underline-offset:3px; }
.footer-social{ margin-top:1.1rem; }
.footer-bottom{
  grid-column:1/-1; display:flex; flex-wrap:wrap; gap:.6rem 1.5rem;
  align-items:center; justify-content:space-between;
  margin-top:.6rem; padding-top:1.4rem; border-top:1px solid rgba(255,255,255,.12);
}
@media (max-width: 760px){
  .footer-inner{ grid-template-columns:1fr; gap:1.8rem; }
}

/* Both of these tile against the viewport, but inside .with-rail they only get
   what is left after the 320px review column. Left alone, the gallery would try
   three pairs across an 800px column — six photos on one row, none of them big
   enough to be worth looking at. */
@media (min-width: 1061px){
  .with-rail .gallery-grid{ grid-template-columns: repeat(2, 1fr); }
}
.with-rail .process{ grid-template-columns: repeat(auto-fit, minmax(min(100%, 215px), 1fr)); }
