/* ============================================================
   SLATE Window Washing — Design System
   Retro emblem/badge identity, sourced directly from Kru's own
   logo artwork. Navy + cream + near-black, slab-serif display
   (Bevan) over a clean grotesque body (DM Sans).
   ============================================================ */

:root {
  --navy: #384B57;
  --navy-deep: #1E2A30;
  --cream: #D8C3A8;
  --paper: #F6F0E6;
  --ink: #232A2F;
  --glass: #6D8B94;
  --white: #FFFFFF;
  --line: rgba(35, 42, 47, 0.12);
  --line-on-dark: rgba(216, 195, 168, 0.22);
  --shadow: 0 10px 30px rgba(30, 42, 48, 0.12);
  --wrap: 1180px;
  --disp: 'Bevan', 'Georgia', serif;
  --body: 'DM Sans', system-ui, -apple-system, sans-serif;
  --radius: 10px;
}

*, *::before, *::after { box-sizing: border-box; }
html { scroll-behavior: smooth; -webkit-text-size-adjust: 100%; }
body {
  margin: 0;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--body);
  font-size: 17px;
  line-height: 1.65;
  padding-bottom: 72px;
}
@media (min-width: 900px) { body { padding-bottom: 0; } }
img { max-width: 100%; display: block; }
a { color: inherit; }

h1, h2, h3 { margin: 0; font-family: var(--disp); font-weight: 400; line-height: 1.12; letter-spacing: 0.002em; }
h1 { font-size: clamp(2.1rem, 6vw, 4rem); }
h2 { font-size: clamp(1.7rem, 4.4vw, 2.7rem); }
h3 { font-size: 1.28rem; }
p { margin: 0 0 1rem; max-width: 62ch; }
.wrap { max-width: var(--wrap); margin: 0 auto; padding: 0 24px; }
/* Centering a button inside a <p> doesn't work here — the global
   p{max-width:62ch} caps the paragraph, so text-align centres within
   that narrow box instead of the section. */
.cta-center { display: flex; justify-content: center; margin-top: 2rem; }

/* ---------- buttons ---------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 0.5rem;
  font-family: var(--body); font-weight: 700; font-size: 1rem;
  padding: 0.95rem 1.7rem; border-radius: 99px; border: 2px solid transparent;
  text-decoration: none; cursor: pointer; line-height: 1;
  transition: background 0.18s, color 0.18s, border-color 0.18s, transform 0.08s;
}
.btn:active { transform: translateY(1px); }
.btn-primary { background: var(--navy); color: var(--white); }
.btn-primary:hover { background: var(--navy-deep); }
.btn-ghost { background: transparent; color: var(--white); border-color: rgba(255,255,255,0.45); }
.btn-ghost:hover { background: rgba(255,255,255,0.12); }
.btn-outline { background: transparent; color: var(--navy); border-color: var(--navy); }
.btn-outline:hover { background: var(--navy); color: var(--white); }
.btn-block { width: 100%; }

/* ---------- header ----------
   Always solid. An earlier version went transparent-with-white-text
   over the hero photo and only darkened on scroll — fragile, and it
   kept reading as low-contrast depending on the photo. Not worth the
   risk: the header is readable on every page, every scroll position,
   no exceptions. */
.hdr {
  position: sticky; top: 0; z-index: 60;
  background: rgba(246, 240, 230, 0.96); backdrop-filter: blur(10px);
  border-bottom: 1px solid var(--line);
  box-shadow: 0 2px 14px rgba(30,42,48,0.06);
}
.hdr-in { display: flex; align-items: center; justify-content: space-between; gap: 1.2rem; padding: 0.85rem 24px; max-width: var(--wrap); margin: 0 auto; }
.hdr-logo { display: flex; align-items: center; gap: 0.65rem; text-decoration: none; flex: 0 0 auto; }
.hdr-logo img { height: 62px; width: auto; display: block; }
/* The badge is a circle with its own internal padding, so it reads smaller
   than its box. Below the desktop nav breakpoint it gets more height, and
   the header's vertical padding comes down to absorb most of it — the bar
   grows 7px, not 12px. */
@media (max-width: 979px) {
  .hdr-logo img { height: 74px; }
  .hdr-in { padding: 0.6rem 24px; }   /* 24px keeps the logo on the same left edge as .wrap content */
}
.hdr-nav { display: none; align-items: center; gap: 1.8rem; }
.hdr-nav a {
  font-size: 0.95rem; font-weight: 700; text-decoration: none; color: var(--ink);
  position: relative; padding: 0.3rem 0;
}
.hdr-nav a.active::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: -4px; height: 2px; background: currentColor;
}
.hdr-r { display: flex; align-items: center; gap: 1rem; }
.hdr-tel { display: none; text-decoration: none; font-weight: 700; font-size: 1rem; color: var(--ink); white-space: nowrap; }
.hdr .btn-primary { display: none; }
@media (min-width: 980px) {
  .hdr-nav { display: flex; }
  .hdr-tel { display: inline; }
  .hdr .btn-primary { display: inline-flex; padding: 0.7rem 1.4rem; font-size: 0.92rem; }
}
.hdr-burger {
  display: inline-flex; align-items: center; justify-content: center;
  width: 44px; height: 44px; padding: 0; margin: 0; border-radius: 50%; border: 1.5px solid var(--line);
  background: none; cursor: pointer; flex: 0 0 auto; line-height: 0;
}
.hdr-burger svg { width: 19px; height: 19px; stroke: var(--ink); }
@media (min-width: 980px) { .hdr-burger { display: none; } }

.mobile-nav {
  position: fixed; inset: 0; z-index: 90; background: var(--navy-deep);
  display: flex; flex-direction: column; padding: 1.4rem 24px 2rem;
  transform: translateY(-100%); transition: transform 0.3s ease;
}
.mobile-nav.is-open { transform: translateY(0); }
.mobile-nav-top { display: flex; align-items: center; justify-content: space-between; margin-bottom: 2.4rem; }
.mobile-nav-top img { height: 46px; }
.mobile-nav-close { width: 44px; height: 44px; padding: 0; margin: 0; border-radius: 50%; border: 1.5px solid var(--line-on-dark); background: none; cursor: pointer; display: flex; align-items: center; justify-content: center; line-height: 0; }
.mobile-nav-close svg { width: 18px; height: 18px; stroke: var(--cream); }
.mobile-nav a.active { color: var(--cream); }
.mobile-nav a.active::before {
  content: ""; display: inline-block; vertical-align: middle;
  width: 10px; height: 10px; border-radius: 50%; background: var(--cream);
  margin-right: 0.6rem; margin-top: -0.2em;
}
.mobile-nav a {
  font-family: var(--disp); font-size: 1.7rem; color: var(--paper); text-decoration: none;
  padding: 0.75rem 0; border-bottom: 1px solid var(--line-on-dark);
}
.mobile-nav-cta { margin-top: 1.6rem; display: flex; flex-direction: column; gap: 0.8rem; }

/* ---------- hero ---------- */
.hero {
  position: relative; min-height: 60vh; display: flex; align-items: flex-end;
  background-size: cover; background-position: center; overflow: hidden;
}
.hero::after {
  content: ""; position: absolute; inset: 0; z-index: 1;
  background: linear-gradient(180deg, rgba(20,28,32,0.3) 0%, rgba(20,28,32,0.5) 60%, rgba(20,28,32,0.88) 100%);
}
.hero-in { position: relative; z-index: 2; padding: 2.5rem 0 3.6rem; width: 100%; }
.hero .lede { font-family: var(--body); font-size: 1rem; font-weight: 700; color: var(--cream); letter-spacing: 0.01em; margin-bottom: 0.9rem; }
.hero h1 { color: var(--white); max-width: 16ch; }
.hero-sub { color: rgba(255,255,255,0.86); font-size: 1.12rem; max-width: 46ch; margin: 1.1rem 0 1.8rem; }
.hero-cta { display: flex; flex-wrap: wrap; gap: 0.8rem; }
.page-hero {
  min-height: 42vh; align-items: center;
}
.page-hero .hero-in { padding: 4.5rem 24px 2.6rem; }   /* keep .wrap's side gutter so copy never touches the screen edge */

/* ---------- asymmetric split hero (homepage) ----------
   Broken-grid composition: copy pinned left on a plain paper ground
   (no photo-contrast gamble for the header to fight), photo bleeds
   to the true right edge of the viewport, and the badge logo sits
   oversized and rotated across the seam like a wax stamp. */
.hero-split {
  display: grid; grid-template-columns: 1fr;
}
@media (min-width: 960px) {
  .hero-split { grid-template-columns: minmax(380px, 46%) 1fr; min-height: 84vh; }
}
.hero-split-copy {
  display: flex; flex-direction: column; justify-content: center; position: relative; z-index: 2;
  padding: 3.4rem 24px 3rem; background: var(--paper);
}
@media (min-width: 960px) { .hero-split-copy { padding: 4rem clamp(24px, 5vw, 64px) 4rem clamp(24px, 6vw, 80px); } }
.hero-split h1 { color: var(--ink); max-width: 15ch; font-size: clamp(2.05rem, 4.4vw, 3.4rem); }
.hero-split .lede { color: var(--navy); font-weight: 700; font-size: 0.95rem; margin-bottom: 0.8rem; }
.hero-split .hero-sub { color: #4C565B; font-size: 1.04rem; max-width: 44ch; margin: 1.1rem 0 1.7rem; }
.hero-split-photo { position: relative; min-height: 42vh; overflow: hidden; }
.hero-split-photo img { width: 100%; height: 100%; object-fit: cover; display: block; }
/* Dust/water-spot film painted over the hero photo; wiping it with the
   cursor erases a persistent trail (js/main.js). Pointer-capable
   devices only — on touch it would fight the page scroll.
   z-index MUST stay below .hero-split-copy's 2: the copy block comes
   first in the DOM, so at equal z-index this canvas painted over the
   badge stamp and dirtied the logo. */
/* pointer-events stays off so the canvas can never swallow a tap or
   block scrolling on touch — the drag listener lives on the wrapper. */
.hero-grime { position: absolute; inset: 0; z-index: 1; pointer-events: none; transition: opacity 0.6s ease; }
.hero-grime.is-cleared { opacity: 0; }
/* Hide the system cursor only where the squeegee actually replaces it:
   pointer-capable and wide enough for a 190px tool to make sense. */
@media (hover: hover) and (pointer: fine) and (min-width: 960px) {
  .hero-split-photo { cursor: none; }
}
@media (prefers-reduced-motion: reduce) { .hero-grime { display: none !important; } }

/* Quiet nudge so desktop visitors discover the wipe. Fades for good the
   moment they start — never reappears, never blocks a click. */
.wipe-cue {
  position: absolute; z-index: 3; left: 50%; bottom: 1.6rem; transform: translateX(-50%);
  margin: 0; padding: 0.5rem 1rem; border-radius: 99px; white-space: nowrap;
  background: rgba(20,28,32,0.55); backdrop-filter: blur(6px);
  color: rgba(255,255,255,0.88); font-size: 0.82rem; font-weight: 700;
  pointer-events: none; display: none; opacity: 0; transition: opacity 0.5s ease;
}
@media (hover: hover) and (pointer: fine) and (min-width: 960px) {
  .wipe-cue { display: block; opacity: 1; }
}
.hero-split-photo.is-wiped .wipe-cue { opacity: 0; }
@media (prefers-reduced-motion: reduce) { .wipe-cue { display: none !important; } }

/* Squeegee that replaces the cursor over the glass and pivots to face
   the direction you're dragging. */
.squeegee {
  /* z-index 1, not 4: it passes UNDER the headline block (2), the badge
     stamp (3) and the wipe cue (3), so the tool reads as a quiet thing
     moving across the glass instead of sweeping over the brand. It still
     sits above the grime canvas — same z-index, but later in the DOM —
     which is correct: the squeegee is on top of the dirt it removes. */
  position: absolute; z-index: 1; width: 300px; height: 300px;
  pointer-events: none; opacity: 0; transition: opacity 0.18s;
  left: 0; top: 0; will-change: transform;
  /* Pivot on the handle grip — that's the hand, so it's what tracks the
     cursor while the blade swings around behind it. 300/128 scale puts
     the grip at ~150px, ~73px. */
  transform-origin: 150px 73px;
  filter: drop-shadow(0 4px 10px rgba(20,28,32,0.3));
}
.squeegee.is-visible { opacity: 0.82; }
@media (prefers-reduced-motion: reduce) { .squeegee { display: none !important; } }
@media (min-width: 960px) {
  /* The photo is portrait (2000x2666). Left in normal flow it stretched
     the grid row to ~1037px and left a dead band above the headline, so
     it's taken out of flow — the copy column sets the height, the photo
     just fills whatever that is. */
  .hero-split-photo { min-height: 0; }
  .hero-split-photo img { position: absolute; inset: 0; }
}
/* ---------- mobile hero: type painted on the glass ----------
   Below 960px the split collapses: the photo becomes the whole stage and
   the copy column lifts off the paper and sits ON it. The headline gets
   its own cream ground so legibility never depends on what the photo is
   doing underneath — and so it still reads once the squeegee has wiped
   the grime away. The band is painted on an inner <span>, not the h1:
   the h1 is a flex item, and flex items are blockified, so `display:
   inline` on it computes to `block` and the ragged per-line bands
   collapse into one solid slab. */
@media (max-width: 959px) {
  .hero-split {
    position: relative; z-index: 1;
    min-height: clamp(460px, 68vh, 600px);
  }
  .hero-split-photo { position: absolute; inset: 0; min-height: 0; }
  /* Scrim sits ABOVE the grime canvas (z1), not between it and the photo,
     so the headline has exactly the same contrast before and after the
     squeegee clears the dirt. Brand navy rather than black — a neutral
     black tint greys out the warm wood and stone in the photo. */
  .hero-split-photo::after {
    content: ""; position: absolute; inset: 0; z-index: 2; pointer-events: none;
    background: linear-gradient(180deg, rgba(30,42,48,0.30) 0%, rgba(30,42,48,0.42) 45%, rgba(30,42,48,0.34) 100%);
  }
  .hero-split-copy {
    position: relative; z-index: 3; background: transparent;
    justify-content: center; align-items: center; text-align: center;
    padding: 1.4rem 22px 2rem;
  }
  /* The eyebrow is gone from the markup; the sub-head stays on desktop
     where the paper column needs the substance, but off the photo. */
  .hero-split .hero-sub { display: none; }
  .hero-split h1 { max-width: 16ch; font-size: clamp(2rem, 8.4vw, 2.6rem); line-height: 1.16; }
  /* Plain white type. Contrast comes from the scrim over the photo, not
     from anything drawn on the letterforms — an outline here read as an
     Instagram caption. One soft shadow only, for separation, not effect. */
  .hero-split h1 .h1-paint {
    color: var(--white);
    text-shadow: 0 2px 18px rgba(20, 28, 32, 0.45);
  }
  .hero-split .hero-cta .btn-outline { backdrop-filter: none; background: rgba(30, 42, 48, 0.22); }
  .hero-split .hero-cta { margin-top: 1.6rem; gap: 0.6rem; justify-content: center; }
  .hero-split .hero-cta .btn { padding: 0.82rem 1.1rem; font-size: 0.93rem; }
  /* btn-outline is navy-on-navy over a photo — swap to cream on glass */
  .hero-split .hero-cta .btn-outline {
    color: var(--paper); border-color: rgba(246, 240, 230, 0.75);
    background: rgba(30, 42, 48, 0.34); backdrop-filter: blur(6px);
  }
  .hero-split .hero-cta .btn-outline:hover { background: rgba(30, 42, 48, 0.62); color: var(--white); }
}
.hero-stamp {
  position: absolute; z-index: 3; width: 92px; height: 92px; pointer-events: none;
  top: -46px; right: 20px; transform: rotate(-9deg);
  filter: drop-shadow(0 8px 18px rgba(20,28,32,0.3));
}
@media (min-width: 960px) {
  /* straddles the vertical seam into the photo column. Anchored to the
     column's midpoint, not its bottom — the copy block runs taller than
     the viewport, so a bottom offset put the stamp below the fold. */
  .hero-stamp { width: 150px; height: 150px; top: 50%; right: 0; bottom: auto; transform: translate(50%, -50%) rotate(-9deg); }
}
.hero-stamp img { width: 100%; height: 100%; }
@media (max-width: 959px) {
  /* Badge drops to the foot of the photo so the trust marquee below runs
     behind it — the seam the stamp straddles on desktop, rebuilt for a
     single column. Must come after the base rule, not inside the mobile
     hero block above it: same specificity, so source order decides. */
  .hero-stamp { top: auto; bottom: -40px; right: 16px; width: 86px; height: 86px; z-index: 5; }
}

/* ---------- trust strip: continuous marquee ----------
   Track holds two identical runs of the list (the clone is built in JS
   and hidden from screen readers), so translating -50% loops seamlessly.
   Duration is set from the measured width to keep the speed constant at
   any viewport. Pauses on hover; static for reduced-motion. */
.trust { background: var(--navy); padding: 1.05rem 0; overflow: hidden; }
.trust-viewport {
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 5%, #000 95%, transparent);
  mask-image: linear-gradient(90deg, transparent, #000 5%, #000 95%, transparent);
}
.trust-track { display: flex; width: max-content; will-change: transform; }
.trust-track.is-rolling { animation: trust-roll var(--trust-dur, 50s) linear infinite; }
.trust-viewport:hover .trust-track.is-rolling,
.trust-viewport:focus-within .trust-track.is-rolling { animation-play-state: paused; }
@keyframes trust-roll {
  from { transform: translate3d(0, 0, 0); }
  to   { transform: translate3d(-50%, 0, 0); }
}
.trust-row {
  display: flex; align-items: center; list-style: none; margin: 0; padding: 0; flex: 0 0 auto;
}
.trust-row li {
  font-size: 0.92rem; font-weight: 700; color: var(--white); white-space: nowrap;
  padding: 0 1.6rem; border-right: 1px solid rgba(255,255,255,0.26);
}
@media (prefers-reduced-motion: reduce) {
  .trust-track { animation: none !important; width: 100%; justify-content: center; }
  .trust-track .trust-row[aria-hidden="true"] { display: none; }
  .trust-row { flex-wrap: wrap; justify-content: center; }
  .trust-viewport { -webkit-mask-image: none; mask-image: none; }
}

/* ---------- sections ---------- */
.sec { padding: 5rem 0; }
/* 5rem top and bottom is right at desktop measure but reads as dead
   space on a 390px screen, where it costs ~160px per section. */
@media (max-width: 639px) { .sec { padding: 3.4rem 0; } }
.sec-navy { background: var(--navy-deep); color: var(--paper); }
.sec-navy h2, .sec-navy h3 { color: var(--white); }
.sec-navy p { color: rgba(246,240,230,0.78); }
.sec-tint { background: #EEF1F1; }
.shead { max-width: 56ch; margin-bottom: 2.6rem; }
.shead p { color: #5B6A70; font-size: 1.06rem; margin-top: 0.9rem; }
.sec-navy .shead p { color: rgba(246,240,230,0.78); }
.shead-badge { display: inline-flex; align-items: center; gap: 0.5rem; margin-bottom: 0.9rem; }
.shead-badge svg { width: 22px; height: 22px; stroke: var(--navy); }
.sec-navy .shead-badge svg { stroke: var(--cream); }
.shead-badge span { font-weight: 700; font-size: 0.86rem; color: var(--navy); }
.sec-navy .shead-badge span { color: var(--cream); }

/* ---------- services grid ---------- */
.grid { display: grid; gap: 1.3rem; }
.g3 { grid-template-columns: 1fr; }
@media (min-width: 700px) { .g3 { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1000px) { .g3 { grid-template-columns: repeat(3, 1fr); } }
.g2 { grid-template-columns: 1fr; }
@media (min-width: 760px) { .g2 { grid-template-columns: repeat(2, 1fr); } }

.svc-card {
  background: var(--white); border: 1px solid var(--line); border-radius: var(--radius);
  padding: 1.9rem 1.7rem; position: relative;
  transition: box-shadow 0.2s, transform 0.2s, border-color 0.2s;
}
.svc-card:hover { box-shadow: var(--shadow); transform: translateY(-3px); border-color: var(--navy); }
.svc-icon {
  width: 46px; height: 46px; border-radius: 50%; background: rgba(56,75,87,0.1);
  display: flex; align-items: center; justify-content: center; margin-bottom: 1.1rem;
}
.svc-icon svg { width: 23px; height: 23px; stroke: var(--navy); fill: none; stroke-width: 2; }
.svc-card h3 { margin-bottom: 0.6rem; }
.svc-card p { font-size: 0.97rem; color: #4C565B; margin: 0; }
/* Used standalone under the services index as well as inside a card —
   the card-scoped rule below never reached it, so it had no padding and
   sat at a 20px tap height. */
.svc-link { display: inline-flex; align-items: center; padding: 0.6rem 0; font-weight: 700; color: var(--navy); text-decoration: none; border-bottom: 1px solid rgba(56,75,87,0.35); }
.svc-card .svc-link { display: inline-flex; margin-top: 0.9rem; font-weight: 700; font-size: 0.92rem; color: var(--navy); text-decoration: none; border-bottom: 1px solid rgba(56,75,87,0.35); }

/* ---------- service index: expandable list (homepage) ---------- */
.svc-index { border-top: 1px solid var(--line); }
.svc-row { border-bottom: 1px solid var(--line); }
.svc-row summary {
  list-style: none; cursor: pointer; display: flex; align-items: center; gap: 1.3rem;
  padding: 1.5rem 0; -webkit-tap-highlight-color: transparent;
}
.svc-row summary::-webkit-details-marker { display: none; }
.svc-row-num { font-family: var(--disp); font-size: 1.1rem; color: var(--navy); opacity: 0.45; flex: 0 0 auto; width: 2.4ch; }
.svc-row-title { font-family: var(--disp); font-size: clamp(1.15rem, 2.6vw, 1.55rem); flex: 1; font-weight: 400; }
.svc-row-toggle {
  width: 32px; height: 32px; border-radius: 50%; border: 1.5px solid var(--line); flex: 0 0 auto;
  display: flex; align-items: center; justify-content: center; transition: transform 0.25s, border-color 0.25s;
}
.svc-row-toggle svg { width: 14px; height: 14px; stroke: var(--navy); }
.svc-row[open] .svc-row-toggle { transform: rotate(45deg); border-color: var(--navy); }
/* Outer is the height-animating shell (no padding, so it can reach a
   true 0); the inner holds the layout and spacing. */
.svc-row-body { overflow: hidden; }
.svc-row-inner { display: grid; gap: 1.4rem; padding: 0 0 1.9rem 3.7rem; }
@media (min-width: 700px) { .svc-row-inner { grid-template-columns: 1fr 240px; align-items: center; } }
.svc-row-inner p { color: #4C565B; font-size: 0.98rem; margin: 0; }
.svc-row-inner img { border-radius: 8px; width: 100%; aspect-ratio: 4/3; object-fit: cover; }

/* ---------- why us: alternating ---------- */
.feature-row { display: grid; gap: 2.4rem; align-items: center; }
@media (min-width: 900px) { .feature-row { grid-template-columns: 1fr 1fr; gap: 3.6rem; } }
.feature-row.flip .feature-photo { order: -1; }
@media (min-width: 900px) { .feature-row.flip .feature-media { order: 2; } }
.feature-media { border-radius: var(--radius); overflow: hidden; box-shadow: var(--shadow); }
.feature-media img { width: 100%; height: 100%; object-fit: cover; aspect-ratio: 4/3; }
.feature-list { list-style: none; margin: 1.6rem 0 0; padding: 0; display: grid; gap: 1.3rem; }
.feature-list h3 { margin-bottom: 0.3rem; font-size: 1.08rem; }
.feature-list p { font-size: 0.96rem; color: #4C565B; margin: 0; }

/* ---------- process: connected path ---------- */
.process-row { display: grid; gap: 2.4rem; position: relative; }
@media (min-width: 800px) {
  .process-row { grid-template-columns: repeat(3, 1fr); gap: 1.5rem; }
}
.process-step { position: relative; padding-top: 0.3rem; }
/* Connector runs from each node to the next one. Drawn per-step rather
   than as one line across the row: the nodes sit at the START of each
   column, not centred in it, so a row-wide line with percentage insets
   overshot past the last node and dangled into empty space. Anchoring
   to each step makes it self-correcting at any column width. */
@media (min-width: 800px) {
  .process-step::after {
    content: ""; position: absolute; top: 28px; left: 60px; right: -12px; height: 1px;
    background-image: linear-gradient(90deg, var(--cream) 0 10px, transparent 10px 20px);
    background-size: 20px 1px; background-repeat: repeat-x; opacity: 0.5;
    transform-origin: left center;
    transition: transform 0.6s cubic-bezier(.4,0,.2,1);
  }
  .process-step:last-child::after { content: none; }
  /* Hidden start-state only applies once JS confirms it will animate —
     otherwise the steps must be visible by default. */
  .process-row.will-draw .process-step::after { transform: scaleX(0); }
  .process-row.is-drawn .process-step:nth-child(1)::after { transform: scaleX(1); transition-delay: 0.25s; }
  .process-row.is-drawn .process-step:nth-child(2)::after { transform: scaleX(1); transition-delay: 0.75s; }
}
/* Below the 3-up breakpoint the same path runs vertically down the left
   edge, threading node to node, and draws top-to-bottom on scroll. */
@media (max-width: 799px) {
  /* Node moves into a left gutter and the copy indents past it, so the
     thread has a clear channel to run down. Left in the flow it crossed
     straight through the paragraph text. */
  .process-step { padding-top: 0; padding-left: 68px; min-height: 48px; }
  .process-step .process-node { position: absolute; left: 0; top: 0; margin-bottom: 0; }
  .process-step::after {
    content: ""; position: absolute; left: 23px; top: 56px; bottom: -2.4rem; width: 1px;
    background-image: linear-gradient(180deg, var(--cream) 0 10px, transparent 10px 20px);
    background-size: 1px 20px; background-repeat: repeat-y; opacity: 0.5;
    transform-origin: center top;
    transition: transform 0.6s cubic-bezier(.4,0,.2,1);
  }
  .process-step:last-child::after { content: none; }
  .process-row.will-draw .process-step::after { transform: scaleY(0); }
  .process-row.is-drawn .process-step:nth-child(1)::after { transform: scaleY(1); transition-delay: 0.25s; }
  .process-row.is-drawn .process-step:nth-child(2)::after { transform: scaleY(1); transition-delay: 0.75s; }
}

/* nodes land just before the line reaches them */
.process-node { transition: opacity 0.4s ease, transform 0.4s cubic-bezier(.22,1,.36,1); }
.process-row.will-draw .process-node { opacity: 0; transform: scale(0.75); }
.process-row.is-drawn .process-step:nth-child(1) .process-node { opacity: 1; transform: scale(1); transition-delay: 0.1s; }
.process-row.is-drawn .process-step:nth-child(2) .process-node { opacity: 1; transform: scale(1); transition-delay: 0.68s; }
.process-row.is-drawn .process-step:nth-child(3) .process-node { opacity: 1; transform: scale(1); transition-delay: 1.18s; }
@media (prefers-reduced-motion: reduce) {
  .process-step::after { transform: none !important; transition: none !important; }
  .process-node { opacity: 1 !important; transform: none !important; transition: none !important; }
}
.process-node {
  width: 48px; height: 48px; border-radius: 50%; border: 1.5px solid var(--cream);
  display: flex; align-items: center; justify-content: center; margin-bottom: 1.1rem; position: relative; z-index: 1;
  background: var(--navy-deep); font-family: var(--disp); font-size: 1.1rem; color: var(--cream);
}
.process-step h3 { color: var(--white); margin-bottom: 0.5rem; }
.process-step p { color: rgba(246,240,230,0.78); font-size: 0.97rem; }

/* ---------- gallery ---------- */
.gal-grid { display: grid; gap: 0.9rem; grid-template-columns: 1fr; }
@media (min-width: 640px) { .gal-grid { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 980px) {
  .gal-grid { grid-template-columns: repeat(4, 1fr); grid-auto-rows: 170px; }
  .gal-grid .tall { grid-row: span 2; }
  .gal-grid .wide { grid-column: span 2; }
}
/* On a phone, four full-width photos stacked is a very long scroll for
   a teaser. The teaser (not the full gallery) becomes a snapped
   filmstrip instead: one card at a time, the next one peeking so the
   swipe is discoverable, bled to both screen edges. */
@media (max-width: 639px) {
  .gal-peek {
    display: flex; gap: 0.7rem; overflow-x: auto; overscroll-behavior-x: contain;
    scroll-snap-type: x mandatory; -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    padding: 0 24px 0.2rem; margin: 0 -24px; scroll-padding-left: 24px;
  }
  .gal-peek::-webkit-scrollbar { display: none; }
  .gal-peek .gal-item { flex: 0 0 80%; scroll-snap-align: start; aspect-ratio: 4 / 3; }
}
/* The full gallery page keeps a grid, but two up rather than one — a
   single column turns 7 photos into an endless column on a phone. */
@media (max-width: 639px) {
  .gal-grid:not(.gal-peek) { grid-template-columns: repeat(2, 1fr); gap: 0.7rem; }
  .gal-grid:not(.gal-peek) .gal-item { aspect-ratio: 1 / 1; }
  .gal-grid:not(.gal-peek) .gal-item.wide { grid-column: span 2; aspect-ratio: 16 / 10; }
}
.gal-item { border-radius: 8px; overflow: hidden; position: relative; cursor: pointer; background: var(--navy-deep); }
.gal-item img { width: 100%; height: 100%; object-fit: cover; transition: transform 0.4s; }
.gal-item:hover img { transform: scale(1.04); }
.gal-cap {
  position: absolute; left: 0; right: 0; bottom: 0; padding: 0.9rem 1rem 0.7rem;
  background: linear-gradient(0deg, rgba(30,42,48,0.82), transparent);
  color: var(--white); font-size: 0.85rem; font-weight: 700; opacity: 0; transition: opacity 0.2s;
}
.gal-item:hover .gal-cap { opacity: 1; }

/* lightbox */
.lightbox { position: fixed; inset: 0; z-index: 100; background: rgba(30,42,48,0.94); display: none; align-items: center; justify-content: center; padding: 3rem 1.5rem; }
.lightbox.is-open { display: flex; }
.lightbox img { max-width: min(92vw, 1100px); max-height: 82vh; object-fit: contain; border-radius: 6px; }
.lightbox-close { position: absolute; top: 1.4rem; right: 1.4rem; width: 46px; height: 46px; padding: 0; margin: 0; border-radius: 50%; border: 1.5px solid rgba(255,255,255,0.4); background: none; cursor: pointer; display: flex; align-items: center; justify-content: center; line-height: 0; }
.lightbox-close svg { width: 18px; height: 18px; stroke: var(--white); }

/* ---------- reviews ---------- */
.review-cta { background: var(--white); border: 1px solid var(--line); border-radius: var(--radius); padding: 2.6rem; text-align: center; max-width: 640px; margin: 0 auto; }
.review-stars { color: var(--navy); font-size: 1.4rem; letter-spacing: 0.1em; margin-bottom: 0.9rem; }
.review-cta p { max-width: 48ch; margin: 0 auto 1.6rem; color: #4C565B; }

/* ---------- service area: real map + pins ---------- */
.area-grid { display: grid; gap: 2.4rem; align-items: center; }
@media (min-width: 900px) { .area-grid { grid-template-columns: 1.05fr 0.95fr; gap: 3.4rem; } }
.map-frame {
  position: relative; border-radius: var(--radius); overflow: hidden;
  border: 1px solid var(--line-on-dark); box-shadow: 0 16px 40px rgba(0,0,0,0.35);
}
.map-frame img { width: 100%; height: auto; display: block; }
.map-credit { font-size: 0.72rem; color: rgba(246,240,230,0.45); margin: 0.6rem 0 0; }

/* Pins are positioned by percentage derived from real lat/lng, so they
   stay accurate at any width — including mobile, where an SVG text
   label would have been unreadable. */
.map-pin {
  position: absolute;
  /* The +8px cancels the bottom padding below, so the mark still lands
     exactly on its lat/lng coordinate rather than 8px north of it. */
  transform: translate(-50%, calc(-100% + 8px));
  display: flex; flex-direction: column; align-items: center; gap: 3px;
  /* Bottom padding pushes the hit area past the 44px minimum without
     moving the mark, which has to stay exactly on its coordinate. */
  padding: 0 0 8px; margin: 0; border: 0; background: none; cursor: pointer; line-height: 1;
  -webkit-tap-highlight-color: transparent;
}
.pin-mark {
  width: 15px; height: 15px; border-radius: 50%;
  background: var(--cream); border: 3px solid var(--navy-deep);
  box-shadow: 0 0 0 2px rgba(216,195,168,0.55), 0 3px 8px rgba(0,0,0,0.5);
  order: 2; transition: transform 0.22s cubic-bezier(.22,1,.36,1), box-shadow 0.22s ease;
}
.pin-name {
  order: 1; font-family: var(--body); font-size: 0.8rem; font-weight: 800;
  color: var(--navy-deep); background: var(--cream); white-space: nowrap;
  padding: 5px 10px; border-radius: 99px; box-shadow: 0 2px 8px rgba(0,0,0,0.4);
  transition: transform 0.22s cubic-bezier(.22,1,.36,1);
}
@media (min-width: 560px) { .pin-name { font-size: 0.84rem; } }
.map-pin:hover .pin-mark, .map-pin:focus-visible .pin-mark, .map-pin.is-active .pin-mark {
  transform: scale(1.35); box-shadow: 0 0 0 5px rgba(216,195,168,0.3), 0 3px 10px rgba(0,0,0,0.55);
}
.map-pin:hover .pin-name, .map-pin:focus-visible .pin-name, .map-pin.is-active .pin-name { transform: scale(1.06); }
.map-pin:focus { outline: none; }
.map-pin:focus-visible .pin-name { outline: 2px solid var(--cream); outline-offset: 2px; }

/* The selected pin carries the signal: a full ring, so the eye goes
   straight to the area you tapped. The other two keep a faint, small
   pulse so they still read as live without competing. */
.pin-mark { position: relative; }
.pin-mark::after {
  content: ""; position: absolute; left: 50%; top: 50%;
  width: 15px; height: 15px; margin: -7.5px 0 0 -7.5px;
  border-radius: 50%; border: 2px solid rgba(216, 195, 168, 0.9);
  pointer-events: none;
  animation: pin-pulse-idle 3.4s ease-out infinite;
}
.map-pin[data-area="centennial"] .pin-mark::after { animation-delay: 1.1s; }
.map-pin[data-area="north-lv"] .pin-mark::after { animation-delay: 2.2s; }
.map-pin.is-active .pin-mark::after {
  animation: pin-pulse 2.4s cubic-bezier(.22, 1, .36, 1) infinite;
  animation-delay: 0s;
}
.map-pin:hover .pin-mark::after,
.map-pin:focus-visible .pin-mark::after { animation: none; opacity: 0; }
@keyframes pin-pulse {
  0%   { transform: scale(1);   opacity: 0.85; }
  70%  { transform: scale(3.2); opacity: 0; }
  100% { transform: scale(3.2); opacity: 0; }
}
@keyframes pin-pulse-idle {
  0%   { transform: scale(1);   opacity: 0.3; }
  60%  { transform: scale(1.7); opacity: 0; }
  100% { transform: scale(1.7); opacity: 0; }
}
@media (prefers-reduced-motion: reduce) { .pin-mark::after { animation: none !important; opacity: 0; } }

.area-list { list-style: none; margin: 0; padding: 0; display: grid; gap: 0.5rem; }
.area-list li {
  cursor: pointer; padding: 1rem 1.2rem; border-radius: var(--radius);
  border: 1px solid transparent; transition: background 0.22s ease, border-color 0.22s ease;
}
.area-list li h3 { color: rgba(246,240,230,0.82); font-size: 1.05rem; margin-bottom: 0.25rem; transition: color 0.22s ease; }
.area-list li p { color: rgba(246,240,230,0.6); font-size: 0.94rem; margin: 0; max-width: 46ch; }
.area-list li.is-active { background: rgba(216,195,168,0.09); border-color: rgba(216,195,168,0.3); }
.area-list li.is-active h3 { color: var(--white); }
.area-note { color: rgba(246,240,230,0.6); font-size: 0.92rem; margin: 1.4rem 0 1.2rem; }
@media (prefers-reduced-motion: reduce) {
  .pin-mark, .pin-name, .area-list li { transition: none !important; }
}

/* ---------- FAQ ---------- */
.faq { max-width: 820px; margin: 0 auto; border-top: 1px solid var(--line); }
.faq details { border-bottom: 1px solid var(--line); }
.faq summary {
  cursor: pointer; list-style: none; padding: 1.3rem 2.4rem 1.3rem 0; position: relative;
  font-weight: 700; font-size: 1.05rem;
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after {
  content: ""; position: absolute; right: 0.4rem; top: 1.7rem; width: 9px; height: 9px;
  border-right: 2px solid var(--navy); border-bottom: 2px solid var(--navy);
  transform: rotate(45deg); transition: transform 0.2s;
}
.faq details[open] summary::after { transform: rotate(-135deg); }
.faq .ans { overflow: hidden; }
.faq .ans-inner { padding: 0 1.5rem 1.4rem 0; color: #4C565B; font-size: 0.98rem; }

/* Accordion open/close. Height is driven by JS (details can't transition
   from display:none), opacity and a small lift ride along with it. */
/* 340ms was long enough that the layout shift from the sibling closing
   read as a slow slide rather than a direct response to the tap. */
.svc-row-body, .faq .ans { transition: height 0.2s cubic-bezier(.4,0,.2,1), opacity 0.15s ease; }
.svc-row-inner, .ans-inner { transition: transform 0.2s cubic-bezier(.4,0,.2,1); }
.svc-row-body.is-collapsing .svc-row-inner,
.faq .ans.is-collapsing .ans-inner { transform: translateY(-6px); }
@media (prefers-reduced-motion: reduce) {
  .svc-row-body, .faq .ans, .svc-row-inner, .ans-inner { transition: none !important; }
}

/* ---------- final CTA ---------- */
.cta-band { background: var(--navy-deep); padding: 4.2rem 0; text-align: center; }
.cta-band h2 { color: var(--white); max-width: 16ch; margin: 0 auto; }
.cta-band p { color: rgba(246,240,230,0.8); margin: 1rem auto 1.8rem; max-width: 42ch; }
.cta-row { display: flex; flex-wrap: wrap; gap: 0.8rem; justify-content: center; }

/* ---------- footer ---------- */
.ftr { background: var(--navy-deep); color: #A9B6BB; padding: 3.6rem 0 1.8rem; font-size: 0.93rem; border-top: 1px solid var(--line-on-dark); }
.ftr-g { display: grid; gap: 2.2rem; }
@media (min-width: 780px) { .ftr-g { grid-template-columns: 1.6fr 1fr 1fr; } }
.ftr-logo img { height: 64px; margin-bottom: 1rem; }
.ftr-tag { max-width: 36ch; color: #93A1A6; }
.ftr h4 { font-size: 0.9rem; font-weight: 700; color: var(--cream); margin: 0 0 0.9rem; }
.ftr ul { list-style: none; padding: 0; margin: 0; display: grid; gap: 0.5rem; }
.ftr a { color: #C3CDD1; text-decoration: none; }
.ftr a:hover { text-decoration: underline; }
/* Footer links were 20px tall — under the 44px minimum touch target on a
   phone, where they sit in a tight stack and are easy to mis-tap. The
   padding is on the anchor, not the li, so the tap area grows with it. */
@media (max-width: 639px) {
  .ftr ul { gap: 0; }
  .ftr ul a { display: block; padding: 0.62rem 0; }
  .ftr-b a { display: inline-flex; align-items: center; min-height: 44px; padding: 0 0.1rem; }
  .ftr-tel { display: inline-flex; align-items: center; min-height: 44px; }
  /* Standalone contact actions, not links inside a sentence — those are
     deliberately left at their natural height, since padding a link in
     running prose breaks the line rhythm and overlaps its neighbours. */
  .contact-info li > div > a { display: inline-flex; align-items: center; min-height: 44px; }
}
.ftr-tel { font-family: var(--disp); font-size: 1.3rem; color: var(--white) !important; text-decoration: none !important; }
.ftr-b { border-top: 1px solid var(--line-on-dark); margin-top: 2.4rem; padding-top: 1.3rem; display: flex; flex-wrap: wrap; gap: 0.7rem 1.5rem; justify-content: space-between; font-size: 0.82rem; }
.ftr-b nav { display: flex; gap: 1.3rem; }

/* ---------- mobile sticky bar ---------- */
.mbar { position: fixed; left: 0; right: 0; bottom: 0; z-index: 70; display: flex; gap: 0.55rem; padding: 0.6rem 0.7rem calc(0.6rem + env(safe-area-inset-bottom)); background: rgba(246,240,230,0.97); border-top: 1px solid var(--line); box-shadow: 0 -4px 20px rgba(30,42,48,0.12); backdrop-filter: blur(8px); }
.mbar .btn { flex: 1; padding: 0.9rem 0.5rem; font-size: 0.93rem; }
@media (min-width: 900px) { .mbar { display: none; } }

/* ---------- contact form ---------- */
.contact-grid { display: grid; gap: 2.4rem; }
@media (min-width: 940px) { .contact-grid { grid-template-columns: 1fr 1fr; gap: 3.4rem; } }
.form-card { background: var(--white); border: 1px solid var(--line); border-radius: var(--radius); padding: 2rem 1.9rem; box-shadow: var(--shadow); }
.field { margin-bottom: 1rem; }
.field label { display: block; font-size: 0.88rem; font-weight: 700; margin-bottom: 0.4rem; }
.field label .opt { font-weight: 500; opacity: 0.6; }
.field input, .field select, .field textarea {
  width: 100%; padding: 0.85rem 0.95rem; font-size: 1rem; font-family: inherit; color: var(--ink);
  border: 1.5px solid var(--line); border-radius: 8px; background: var(--paper);
}
.field textarea { resize: vertical; min-height: 110px; }
.field input:focus, .field select:focus, .field textarea:focus { outline: none; border-color: var(--navy); background: var(--white); }
.hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }
.ferr { background: #FBEDEB; border: 1px solid #E3B6AE; color: #9E2F27; padding: 0.65rem 0.85rem; border-radius: 8px; font-size: 0.88rem; font-weight: 600; margin: 0 0 0.9rem; }
.fok { background: #EAF1EC; border: 1px solid #B7D2C0; color: #2D5D40; padding: 0.9rem 1rem; border-radius: 8px; font-size: 0.95rem; font-weight: 600; }
.contact-info ul { list-style: none; padding: 0; margin: 1.6rem 0 0; display: grid; gap: 1rem; }
.contact-info li { display: flex; align-items: flex-start; gap: 0.8rem; }
.contact-info svg { width: 20px; height: 20px; stroke: var(--navy); flex: 0 0 auto; margin-top: 0.15rem; }
.contact-info a { text-decoration: none; font-weight: 700; }

/* ---------- legal pages ---------- */
.legal { max-width: 760px; }
.legal h2 { font-size: 1.3rem; margin: 2.2rem 0 0.7rem; }
.legal p, .legal li { color: #4C565B; }

:where(a, button, input, summary):focus-visible { outline: 3px solid var(--navy); outline-offset: 2px; border-radius: 3px; }

@media (prefers-reduced-motion: reduce) {
  * { animation: none !important; transition: none !important; scroll-behavior: auto !important; }
}

/* ================= REVIEW CAROUSEL (frosted panes in a 3D row) ================= */
.rv-head { max-width: 40rem; margin: 0 0 2.6rem; }
.rv-head h2 { margin: 0 0 0.6rem; }
.rv-head p { margin: 0; }
.rv { --w: clamp(260px, 80vw, 380px); --step: calc(var(--w) * 0.66); overflow: hidden; background: linear-gradient(180deg, #425865 0%, #384B57 100%); }  /* lighter than the deep-navy service-area band that follows */
.rv-stage {
  list-style: none; margin: 0 auto; padding: 0;
  position: relative; height: 22rem;
  perspective: 1300px; touch-action: pan-y; user-select: none;
}
.rv-card {
  position: absolute; left: 50%; top: 0;
  width: var(--w); min-height: 19rem; padding: 1.7rem 1.6rem 1.5rem;
  display: flex; flex-direction: column; gap: 1rem;
  color: var(--paper); cursor: pointer; overflow: hidden;
  background: linear-gradient(140deg, rgba(88,112,124,0.78), rgba(48,66,76,0.78));
  border: 1px solid var(--line-on-dark); border-radius: var(--radius);
  -webkit-backdrop-filter: blur(14px); backdrop-filter: blur(14px);
  box-shadow: 0 24px 40px -18px rgba(0,0,0,0.55);
  transform:
    translateX(-50%)
    translateX(calc(var(--o, 0) * var(--step)))
    translateZ(calc(var(--a, 0) * -110px))
    rotateY(calc(var(--o, 0) * -32deg))
    scale(calc(1 - var(--a, 0) * 0.07));
  opacity: calc(1 - var(--a, 0) * 0.3);
  transition: transform 0.6s cubic-bezier(.2,.7,.2,1), opacity 0.6s ease;
}
/* the glare a window pane catches */
.rv-card::after {
  content: ""; position: absolute; inset: 0; pointer-events: none;
  background: linear-gradient(112deg, transparent 38%, rgba(255,255,255,0.09) 44%, rgba(255,255,255,0.09) 50%, transparent 56%);
}
.rv-card.is-active { background: linear-gradient(140deg, rgba(100,126,138,0.97), rgba(58,78,89,0.97)); cursor: default; }
.rv-card.is-hidden { opacity: 0; pointer-events: none; }
.rv-stars { margin: 0; color: var(--cream); font-size: 1.15rem; letter-spacing: 0.12em; }
.rv-card blockquote { margin: 0; font-size: 1.04rem; line-height: 1.6; color: var(--paper); }
.rv-who { margin: auto 0 0; font-family: var(--disp); font-size: 1rem; color: var(--white); display: flex; flex-direction: column; gap: 0.15rem; }
.rv-who span { font-family: var(--body); font-size: 0.85rem; color: rgba(246,240,230,0.62); }
.rv-controls { display: flex; align-items: center; justify-content: center; gap: 1.2rem; margin-top: 1.4rem; }
.rv-btn {
  width: 2.9rem; height: 2.9rem; border-radius: 50%; cursor: pointer;
  display: grid; place-items: center; color: var(--paper);
  background: transparent; border: 1px solid var(--line-on-dark);
  transition: background 0.2s, border-color 0.2s;
}
.rv-btn:hover { background: rgba(246,240,230,0.1); border-color: var(--cream); }
.rv-btn:focus-visible, .rv-card:focus-visible { outline: 2px solid var(--cream); outline-offset: 3px; }
.rv-btn svg { width: 1.1rem; height: 1.1rem; stroke: currentColor; fill: none; stroke-width: 2; stroke-linecap: round; stroke-linejoin: round; }
.rv-status { min-width: 4.5rem; text-align: center; color: rgba(246,240,230,0.78); font-size: 0.95rem; }
.rv-more { text-align: center; margin-top: 2rem; }
/* Without JS or if the data fails to load, the section still points to Google */
.rv:not(.rv-ready) .rv-stage, .rv:not(.rv-ready) .rv-controls { display: none; }
@media (max-width: 639px) {
  .rv-stage { height: 23.5rem; }
  .rv-head { margin-bottom: 2rem; }
}
@media (prefers-reduced-motion: reduce) {
  .rv-card { transition: none; }
}
