/* ============================================================================
   HANDY BROTHERS LLC — Stylesheet
   Vanilla CSS. No frameworks, no build step.

   HOW TO REBRAND: every colour, radius, shadow and spacing value lives in
   section 01 (Design tokens). Change it there and the whole site follows.

   TABLE OF CONTENTS
     01  Design tokens
     02  Reset & base
     03  Typography
     04  Layout primitives
     05  Buttons
     06  Header & navigation
     07  Hero
     08  Assurance bar
     09  Services
     10  Why choose us
     11  Process
     12  Projects + lightbox
     13  About
     14  Reviews
     15  FAQ
     16  Service area map
     17  Contact & form
     18  Footer
     19  Back-to-top & utilities
     20  Motion & reveal
     21  Case studies
     22  Responsive
     23  Page transitions
     24  Print
   ============================================================================ */


/* ==========================================================================
   01  DESIGN TOKENS
   ========================================================================== */
:root {
  /* --- Brand: cedar, the one warm note in a cold palette ------------ */
  --cedar:       #a85c2a;  /* button fills — white text passes AA (4.96:1) */
  --cedar-deep:  #8a4820;  /* hover / pressed */
  --cedar-text:  #8f4b22;  /* accent TEXT on light surfaces (5.8:1) */
  --cedar-soft:  #d9946a;  /* accent on dark surfaces (7.2:1) */
  --cedar-wash:  #f4ebe4;  /* tinted surfaces */

  /* --- Ground: charcoal ---------------------------------------------
     Every neutral below sits on hue 30 at 4-10% saturation — the same
     family as cedar, far enough from it to read as grey. They were a
     green-grey before, and the green was the loudest thing about them:
     at 150-165 degrees it tinted the page background, every hairline and
     all the secondary text at once.

     The lightness of each step is unchanged from that palette, which is
     why every contrast ratio the site passed before it still passes. Only
     hue and saturation moved. If these are ever regenerated, hold L. */
  --basalt-950:  #0e0d0c;  /* deepest band — used once, for the reasons block */
  --basalt-900:  #161514;
  --basalt-800:  #1e1d1c;
  --basalt-700:  #2a2826;
  --basalt-600:  #3c3a37;

  /* --- Fog: warm-neutral greys -------------------------------------- */
  --fog-600:     #5e5a56;  /* secondary text on light (6.4:1) */
  --fog-500:     #78746f;
  --fog-400:     #a19d99;  /* secondary text on dark (6.8:1) */
  --fog-300:     #cac8c5;
  --fog-200:     #dedcda;  /* hairlines */
  --fog-100:     #ebeae9;
  --fog-50:      #f3f2f1;  /* muted section background */
  --paper:       #f9f8f7;  /* page background */
  --white:       #fff;

  /* --- Text roles --------------------------------------------------- */
  --text:            var(--basalt-900);
  --text-muted:      var(--fog-600);
  --text-invert:     #f1efed;  /* light text on dark — same hue family as the greys */
  --text-invert-mut: var(--fog-400);

  /* --- Lines & surfaces on dark ------------------------------------- */
  --line:           var(--fog-200);
  --line-strong:    var(--fog-300);
  --line-dark:      rgba(255, 255, 255, .11);
  --surface-dark:   rgba(255, 255, 255, .035);
  --surface-dark-2: rgba(255, 255, 255, .065);

  /* --- Type --------------------------------------------------------- */
  --font-sans: "Archivo", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
               Helvetica, Arial, sans-serif;
  --font-display: var(--font-sans);
  /* Monospace carries every label, number and unit — the vernacular of
     a set of drawings, and where most of the "built" character lives. */
  --font-mono: "IBM Plex Mono", ui-monospace, SFMono-Regular, Menlo,
               Consolas, monospace;

  --fs-hero:  clamp(2.5rem, 1.35rem + 3.4vw, 3.9rem);
  --fs-h2:    clamp(2rem,   1.4rem + 2.4vw, 3.15rem);
  --fs-h3:    clamp(1.2rem, 1.1rem + 0.4vw, 1.4rem);
  --fs-lede:  clamp(1.06rem, 1rem + 0.45vw, 1.28rem);
  --fs-body:  1.0625rem;   /* 17px */
  --fs-sm:    0.9375rem;   /* 15px */
  --fs-xs:    0.8125rem;   /* 13px */
  --fs-mono:  0.75rem;     /* 12px — labels only */

  --track-tight:  -0.024em;
  --track-label:   0.14em;

  /* Headings run slightly narrow: sturdier, more engineered. */
  --stretch-display: 92%;

  /* --- Space -------------------------------------------------------- */
  --space-section: clamp(72px, 9vw, 132px);
  --gutter:        clamp(20px, 4vw, 40px);
  --wrap:          1220px;
  --wrap-narrow:   860px;

  /* --- Shape & depth ------------------------------------------------ */
  --r-sm:  4px;
  --r-md:  8px;
  --r-lg:  12px;
  --r-xl:  16px;
  --r-pill: 999px;

  --shadow-sm: 0 1px 2px rgba(17, 24, 25, .05),
               0 6px 16px -10px rgba(17, 24, 25, .16);
  --shadow-md: 0 2px 4px rgba(17, 24, 25, .05),
               0 18px 40px -18px rgba(17, 24, 25, .22);
  --shadow-lg: 0 30px 70px -28px rgba(17, 24, 25, .38);

  /* --- Motion -------------------------------------------------------
     The two linear() curves below are a damped harmonic oscillator sampled
     into stops — real spring physics, not a bezier that looks springy. They
     are what a JS animation library would compute at runtime; here the
     browser interpolates them on the compositor for free.

       x(t) = 1 - e^(-zwt) (cos(wd t) + (zw/wd) sin(wd t))

     --spring       damping .78 — settles with about 2% overshoot. Anything
                    that moves a long distance uses this: a hair of rebound
                    reads as weight, more reads as a toy.
     --spring-snap  damping .55 — about 12% overshoot. Short travel only,
                    where the eye reads the bounce as responsiveness: a
                    button under the cursor.

     Regenerate with the script in the commit that introduced them. */
  --ease: cubic-bezier(.22, .8, .32, 1);
  --spring: linear(0, 0.1176 6.3%, 0.3476 12.5%, 0.5771 18.8%, 0.7593 25%,
                   0.8845 31.3%, 0.9602 37.5%, 0.9999 43.8%, 1.0164 50%,
                   1.0199 56.3%, 1.0173 62.5%, 1.0126 68.8%, 1.0081 75%,
                   1.0046 81.3%, 1.0022 87.5%, 1.0007 93.8%, 1);
  --spring-snap: linear(0, 0.1704 5.6%, 0.5041 11.1%, 0.8149 16.7%,
                        1.0204 22.2%, 1.1129 27.8%, 1.123 33.3%, 1.0906 38.9%,
                        1.0475 44.4%, 1.0124 50%, 0.9917 55.6%, 0.9844 61.1%,
                        0.9855 66.7%, 0.9905 72.2%, 0.9958 77.8%, 0.9996 83.3%,
                        1.0015 88.9%, 1.002 94.4%, 1);
  --dur-spring: .72s;   /* a spring needs room to settle; .3s clips the tail */
  --stagger-step: 70ms; /* gap between neighbours in a staggered group */
  --dur:  .28s;

  /* --- Chrome ------------------------------------------------------- */
  --head-h: 74px;
  --z-header: 100;
  --z-drawer: 110;
  --z-lightbox: 200;
}

@media (max-width: 900px) { :root { --head-h: 66px; } }


/* ==========================================================================
   02  RESET & BASE
   ========================================================================== */
*, *::before, *::after { box-sizing: border-box; }

html {
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--head-h) + 20px);
  -webkit-text-size-adjust: 100%;
}

body {
  margin: 0;
  background: var(--paper);
  color: var(--text);
  font-family: var(--font-sans);
  font-size: var(--fs-body);
  line-height: 1.65;
  font-synthesis-weight: none;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: hidden;            /* safety net against stray wide children */
}

/* Locked while a dialog is open. position:fixed is what actually holds
   iOS Safari still; the saved offset is put back on unlock. */
body.is-locked {
  position: fixed;
  width: 100%;
  overflow: hidden;
}

img, svg, video { display: block; max-width: 100%; }
img { height: auto; }
a { color: inherit; text-decoration: none; }
ul, ol { margin: 0; padding: 0; list-style: none; }
button, input, select, textarea { font: inherit; color: inherit; }
button { cursor: pointer; }

:focus-visible {
  outline: 3px solid var(--cedar);
  outline-offset: 3px;
  border-radius: 4px;
}
.section--dark :focus-visible { outline-color: var(--cedar-soft); }

::selection { background: var(--cedar); color: #fff; }

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 300;
  background: var(--basalt-900);
  color: #fff;
  padding: 14px 20px;
  border-radius: 0 0 var(--r-md) 0;
  font-weight: 600;
}
.skip-link:focus { left: 0; }


/* ==========================================================================
   03  TYPOGRAPHY
   ========================================================================== */
h1, h2, h3, h4 {
  margin: 0 0 .5em;
  font-family: var(--font-display);
  font-stretch: var(--stretch-display);
  font-weight: 600;
  line-height: 1.08;
  letter-spacing: var(--track-tight);
  text-wrap: balance;
}

h1 { font-size: var(--fs-hero); font-weight: 600; }
h2 { font-size: var(--fs-h2); }
h3 { font-size: var(--fs-h3); line-height: 1.25; letter-spacing: -.015em; }
h4 { font-size: 1rem; letter-spacing: -.01em; }

p { margin: 0 0 1.1rem; }
p:last-child { margin-bottom: 0; }

strong, b { font-weight: 600; }

/* Small uppercase label with a leading rule. */
.eyebrow {
  display: inline-flex;
  align-items: flex-start;
  gap: 12px;
  margin: 0 0 20px;
  font-family: var(--font-mono);
  font-size: var(--fs-mono);
  font-weight: 500;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--cedar-text);
}
/* A rule that ends in a tick — how a dimension is marked on a drawing. */
.eyebrow::before {
  content: "";
  width: 30px;
  height: 7px;
  margin-top: .3em;
  border-left: 1.5px solid currentColor;
  border-bottom: 1.5px solid currentColor;
  flex: none;
}
.section--dark .eyebrow { color: var(--cedar-soft); }

.lede {
  font-size: var(--fs-lede);
  line-height: 1.6;
  color: var(--text-muted);
  max-width: 56ch;
}
.section--dark .lede { color: var(--text-invert-mut); }

/* Labels, units and figures all share the mono voice. */
.brand__sub,
.assurance__list,
.step__no,
.filter,
.project__caption span,
.review__meta,
.contact__label,
.field__label,
.footer h4,
.footer__legal,
.footer__bottom,
.lightbox__count,
.lightbox__caption,
.micro {
  font-family: var(--font-mono);
  font-weight: 500;
}

.micro {
  font-size: var(--fs-mono);
  line-height: 1.6;
  color: var(--text-muted);
}
.section--dark .micro { color: var(--text-invert-mut); }


/* ==========================================================================
   04  LAYOUT PRIMITIVES
   ========================================================================== */
.wrap {
  width: 100%;
  max-width: var(--wrap);
  margin-inline: auto;
  padding-inline: var(--gutter);
}
.wrap--narrow { max-width: var(--wrap-narrow); }

.section { padding-block: var(--space-section); }
.section--tight { padding-block: clamp(52px, 6vw, 84px); }
.section--muted { background: var(--fog-50); }
.section--dark {
  background: var(--basalt-900);
  color: var(--text-invert);
}
/* Deepest surface on the page — used once, for the reasons-to-hire band. */
.section--deep { background: var(--basalt-950); }
.section--dark h2,
.section--dark h3,
.section--dark h4 { color: #fff; }

.section-head {
  max-width: 62ch;
  margin-bottom: clamp(40px, 5vw, 68px);
}
.section-head--center {
  margin-inline: auto;
  text-align: center;
}
.section-head--center .eyebrow { justify-content: center; }
.section-head--center .lede { margin-inline: auto; }
.section-head h2 { margin-bottom: .45em; }


/* ==========================================================================
   05  BUTTONS
   ========================================================================== */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .6em;
  min-height: 52px;
  padding: 14px 28px;
  border: 1.5px solid transparent;
  border-radius: var(--r-sm);
  background: none;
  font-size: var(--fs-sm);
  font-weight: 600;
  letter-spacing: .005em;
  text-align: center;
  transition: background var(--dur) var(--ease),
              border-color var(--dur) var(--ease),
              color var(--dur) var(--ease),
              transform .34s var(--spring-snap),
              box-shadow .34s var(--ease);
}
/* Lifts and grows very slightly under the cursor. The scale is 2.5% — enough
   that the hand feels it, small enough that the label does not visibly
   resample. Pressing puts it flat again on a plain ease, because a spring on
   the way down reads as a wobble rather than a click. */
.btn:hover { transform: translateY(-2px) scale(1.025); }
.btn:active { transform: translateY(0) scale(.995); transition-timing-function: var(--ease); }

/* Touch screens have no hover; without this the lift sticks after a tap. */
@media (hover: none) {
  .btn:hover { transform: none; }
}
.btn svg { width: 18px; height: 18px; flex: none; }

.btn--primary {
  background: var(--cedar);
  border-color: var(--cedar);
  color: #fff;
  box-shadow: 0 12px 26px -14px rgba(168, 92, 42, .9);
}
.btn--primary:hover {
  background: var(--cedar-deep);
  border-color: var(--cedar-deep);
  box-shadow: 0 20px 38px -16px rgba(138, 72, 32, .95);
}

.btn--dark {
  background: var(--basalt-900);
  border-color: var(--basalt-900);
  color: #fff;
}
.btn--dark:hover {
  background: var(--basalt-700);
  border-color: var(--basalt-700);
  box-shadow: var(--shadow-md);
}

/* Outlined — adapts to the surface it sits on. */
.btn--outline {
  border-color: var(--line-strong);
  color: var(--text);
}
.btn--outline:hover {
  border-color: var(--basalt-900);
  background: var(--basalt-900);
  color: #fff;
  box-shadow: var(--shadow-sm);
}
.section--dark .btn--outline,
.hero .btn--outline {
  border-color: rgba(255, 255, 255, .28);
  color: #fff;
}
.section--dark .btn--outline:hover,
.hero .btn--outline:hover {
  background: rgba(255, 255, 255, .1);
  border-color: rgba(255, 255, 255, .55);
  color: #fff;
}

.btn--block { width: 100%; }
.btn[aria-busy="true"] { opacity: .6; pointer-events: none; }

/* Text link with an arrow that nudges on hover. */
.link-arrow {
  display: inline-flex;
  align-items: center;
  gap: .5em;
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--cedar-text);
}
.link-arrow svg { width: 16px; height: 16px; transition: transform var(--dur) var(--ease); }
.link-arrow:hover svg { transform: translateX(4px); }
.section--dark .link-arrow { color: var(--cedar-soft); }


/* ==========================================================================
   06  HEADER & NAVIGATION
   ========================================================================== */
.header {
  position: sticky;
  top: 0;
  z-index: var(--z-header);
  background: rgba(17, 24, 25, .78);
  -webkit-backdrop-filter: blur(14px) saturate(150%);
  backdrop-filter: blur(14px) saturate(150%);
  border-bottom: 1px solid rgba(255, 255, 255, .08);
  transition: background var(--dur) var(--ease),
              border-color var(--dur) var(--ease),
              box-shadow var(--dur) var(--ease);
  /* Named so a cross-document view transition carries it across rather
     than cross-fading it with the page. See section 23. */
  view-transition-name: site-header;
}
.header.is-stuck {
  background: rgba(17, 24, 25, .97);
  box-shadow: 0 14px 34px -24px rgba(0, 0, 0, .9);
}
.header__inner {
  display: flex;
  align-items: center;
  gap: 24px;
  height: var(--head-h);
}

/* --- Wordmark --- */
.brand {
  display: inline-flex;
  align-items: center;
  gap: 11px;
  margin-right: auto;
  color: #fff;
  flex: none;
}
.brand__mark {
  width: 42px;
  height: auto;
  flex: none;
}
.brand__text { display: flex; flex-direction: column; line-height: 1; }
.brand__name {
  font-family: var(--font-display);
  font-size: 1.02rem;
  font-weight: 700;
  letter-spacing: .07em;
  text-transform: uppercase;
  white-space: nowrap;
}
.brand__sub {
  margin-top: 5px;
  font-size: .68rem;               /* было .6rem — мелко для цветного текста */
  font-weight: 600;
  letter-spacing: .3em;
  text-transform: uppercase;
  color: #f0c3a6;                  /* светлее --cedar-soft: 10.9:1 на шапке */
}

/* --- Desktop nav --- */
.nav { display: flex; align-items: center; gap: 2px; }
.nav__link {
  position: relative;
  padding: 10px 14px;
  border-radius: var(--r-sm);
  font-size: var(--fs-sm);
  font-weight: 500;
  color: rgba(255, 255, 255, .72);
  transition: color var(--dur) var(--ease), background var(--dur) var(--ease);
}
.nav__link:hover { color: #fff; background: rgba(255, 255, 255, .08); }
.nav__link.is-current { color: #fff; }
.nav__link.is-current::after {
  content: "";
  position: absolute;
  left: 14px;
  right: 14px;
  bottom: 4px;
  height: 2px;
  border-radius: 2px;
  background: var(--cedar-soft);
}

.header__actions { display: flex; align-items: center; gap: 14px; }

.header__phone {
  display: none;
  align-items: center;
  gap: 8px;
  font-size: var(--fs-sm);
  font-weight: 600;
  color: #fff;
  white-space: nowrap;
}
.header__phone svg { width: 16px; height: 16px; color: var(--cedar-soft); }
.header__phone:hover { color: var(--cedar-soft); }

.header__cta {
  min-height: 42px;
  padding: 10px 20px;
  font-size: var(--fs-sm);
}

/* --- Burger --- */
.burger {
  display: none;
  width: 46px;
  height: 46px;
  padding: 13px 11px;
  border: 0;
  background: none;
  flex-direction: column;
  justify-content: space-between;
  flex: none;
}
.burger__bar {
  display: block;
  height: 2px;
  background: #fff;
  border-radius: 2px;
  transition: transform var(--dur) var(--ease), opacity .18s linear;
}
.burger[aria-expanded="true"] .burger__bar:nth-child(1) { transform: translateY(9px) rotate(45deg); }
.burger[aria-expanded="true"] .burger__bar:nth-child(2) { opacity: 0; }
.burger[aria-expanded="true"] .burger__bar:nth-child(3) { transform: translateY(-9px) rotate(-45deg); }

/* --- Mobile drawer --- */
/* A discrete property given a duration stays at its old value while the fade
   runs, so an opening dialog was still visibility:hidden when JS asked for
   focus and the request was dropped — focus never entered the drawer, the
   lightbox or the request widget (WCAG 2.4.3). Keeping the transition but
   splitting the directions fixes it: opening flips visibility at once, closing
   delays it until the opacity fade has finished, which is the only direction
   that ever needed it. */
.drawer {
  position: fixed;
  inset: 0;
  z-index: var(--z-drawer);
  display: grid;
  grid-template-rows: auto 1fr;
  background: var(--basalt-900);
  visibility: hidden;
  opacity: 0;
  transition: opacity var(--dur) var(--ease), visibility 0s linear var(--dur);
}
.drawer.is-open {
  visibility: visible;
  opacity: 1;
  transition: opacity var(--dur) var(--ease), visibility 0s linear 0s;
}
.drawer__top {
  display: flex;
  align-items: center;
  justify-content: space-between;
  height: var(--head-h);
  padding-inline: var(--gutter);
  border-bottom: 1px solid var(--line-dark);
}
.drawer__body {
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  padding: 26px var(--gutter) 40px;
  display: flex;
  flex-direction: column;
  gap: 26px;
}
.drawer__nav { display: flex; flex-direction: column; }
.drawer__link {
  padding: 16px 0;
  border-bottom: 1px solid var(--line-dark);
  font-family: var(--font-display);
  font-size: 1.4rem;
  font-weight: 500;
  letter-spacing: -.02em;
  color: #fff;
  transition: color var(--dur) var(--ease), padding-left var(--dur) var(--ease);
}
.drawer__link:hover { color: var(--cedar-soft); padding-left: 8px; }
.drawer__foot { display: grid; gap: 12px; }
.drawer__contact {
  display: flex;
  align-items: center;
  gap: 10px;
  font-size: var(--fs-sm);
  color: var(--text-invert-mut);
}
.drawer__contact svg { width: 17px; height: 17px; color: var(--cedar-soft); flex: none; }
.drawer__contact a { color: #fff; font-weight: 600; }

.icon-btn {
  width: 44px;
  height: 44px;
  display: grid;
  place-items: center;
  border: 0;
  border-radius: var(--r-sm);
  background: none;
  color: #fff;
}
.icon-btn svg { width: 22px; height: 22px; }
.icon-btn:hover { background: rgba(255, 255, 255, .1); }


/* ==========================================================================
   07  HERO
   ========================================================================== */
.hero {
  position: relative;
  isolation: isolate;
  background: var(--basalt-900);
  color: var(--text-invert);
  overflow: hidden;
}
.hero__bg {
  position: absolute;
  inset: 0;
  z-index: -1;
  /* The second glow was rgba(122,152,146) — a green-grey wash across the
     bottom of the first thing anyone sees, and the single biggest source
     of the green cast on the page. It is warm now, and the three stops
     underneath sit on hue 30 like every other neutral. Lightness of each
     stop is unchanged. */
  background:
    radial-gradient(880px 540px at 78% 2%, rgba(217, 148, 106, .15), transparent 60%),
    radial-gradient(1200px 720px at 26% 106%, rgba(168, 150, 132, .15), transparent 62%),
    linear-gradient(180deg, #131211 0%, #1d1c1b 54%, #151413 100%);
}
/* Faint blueprint grid, faded out toward the edges. */
.hero__bg::after {
  content: "";
  position: absolute;
  inset: 0;
  opacity: .55;
  background-image:
    linear-gradient(rgba(255, 255, 255, .04) 1px, transparent 1px),
    linear-gradient(90deg, rgba(255, 255, 255, .04) 1px, transparent 1px);
  background-size: 48px 48px;
  -webkit-mask-image: linear-gradient(180deg, #000 0%, rgba(0,0,0,.35) 46%, transparent 72%);
          mask-image: linear-gradient(180deg, #000 0%, rgba(0,0,0,.35) 46%, transparent 72%);
}

/* Three ridges receding into fog — the Cascades, at almost no contrast. */
.hero__ridge {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: -1;
  width: 100%;
  height: clamp(160px, 25vw, 300px);
  pointer-events: none;
}

.hero__inner {
  display: grid;
  /* The picker needs width to make its photographs legible, so the split is
     close to even rather than copy-led. */
  grid-template-columns: 1fr 1.02fr;
  gap: clamp(32px, 4vw, 56px);
  align-items: center;
  padding-block: clamp(64px, 8vw, 116px);
}
.hero__copy { max-width: 46ch; }
.hero h1 { margin-bottom: .38em; }
.hero h1 .accent {
  display: block;
  color: var(--cedar-soft);
}
.hero .lede { max-width: 46ch; color: var(--text-invert-mut); margin-bottom: 2.2rem; }

.hero__actions {
  display: flex;
  flex-wrap: wrap;
  gap: 14px;
  margin-bottom: 2.6rem;
}

/* Honest, claim-free reassurance list — no invented numbers. */
.hero__points {
  display: flex;
  flex-wrap: wrap;
  gap: 10px 26px;
  padding-top: 26px;
  border-top: 1px solid var(--line-dark);
}
.hero__points li {
  display: flex;
  align-items: center;
  gap: 9px;
  font-size: var(--fs-sm);
  color: var(--text-invert-mut);
}
.hero__points svg { width: 17px; height: 17px; color: var(--cedar-soft); flex: none; }

/* Framed visual with an offset accent rule behind it. */
.hero__media { position: relative; }
/* An offset rule behind the panel. It was drawn for a single photograph and
   still works here: it gives the picker an edge to sit against so it does
   not float in the middle of the hero. */
.hero__media::before {
  content: "";
  position: absolute;
  inset: 18px -16px -16px 18px;
  border: 1.5px solid rgba(217, 148, 106, .3);
  border-radius: var(--r-xl);
  z-index: -1;
}
/* --- The service picker -------------------------------------------------
   Six of our own finished jobs, used as the first question rather than as
   decoration. Each tile carries data-askpro-service, so the click opens the
   estimate form with the service already chosen and the visitor lands on
   step 2 instead of step 1. The point is to take one decision out of the
   start of the funnel, not to add a gallery.

   The label sits under the photograph rather than over it. An overlaid
   caption has to darken the picture to stay legible, and darkening a
   photograph of a white kitchen to protect white text is a bad trade — the
   photograph is the reason the tile works at all. */
.pick {
  padding: clamp(18px, 2vw, 24px);
  border: 1px solid rgba(255, 255, 255, .12);
  border-radius: var(--r-xl);
  background: rgba(255, 255, 255, .045);
  -webkit-backdrop-filter: blur(10px);
  backdrop-filter: blur(10px);
  box-shadow: var(--shadow-lg);
}
.pick__kicker {
  margin: 0 0 8px;
  font-family: var(--font-mono);
  font-size: var(--fs-mono);
  font-weight: 500;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--cedar-soft);
}
.pick__q {
  margin: 0 0 18px;
  font-size: clamp(1.2rem, 1.05rem + .5vw, 1.5rem);
  line-height: 1.2;
  letter-spacing: var(--track-tight);
  color: #fff;
}

.pick__grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: 12px;
}

.pick__tile {
  display: flex;
  flex-direction: column;
  width: 100%;
  padding: 0;
  border: 1px solid rgba(255, 255, 255, .12);
  border-radius: var(--r-md);
  background: var(--basalt-700);
  overflow: hidden;
  cursor: pointer;
  text-align: left;
  transition: transform .34s var(--spring-snap),
              border-color var(--dur) var(--ease),
              box-shadow var(--dur) var(--ease);
}
.pick__tile img {
  display: block;
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  transition: transform .5s var(--spring);
}
.pick__name {
  display: flex;
  align-items: center;
  min-height: 44px;
  padding: 9px 11px;
  background: rgba(255, 255, 255, .06);
  border-top: 1px solid rgba(255, 255, 255, .1);
  color: #fff;
  font-family: var(--font-mono);
  font-size: var(--fs-mono);
  font-weight: 600;
  letter-spacing: .04em;
  text-transform: uppercase;
  line-height: 1.25;
  transition: background var(--dur) var(--ease), color var(--dur) var(--ease);
}
.pick__tile:hover,
.pick__tile:focus-visible {
  transform: translateY(-3px);
  border-color: var(--cedar-soft);
  box-shadow: 0 18px 34px -18px rgba(0, 0, 0, .75);
}
.pick__tile:hover img,
.pick__tile:focus-visible img { transform: scale(1.06); }
.pick__tile:hover .pick__name,
.pick__tile:focus-visible .pick__name { background: var(--cedar); }
.pick__tile:active { transform: translateY(-1px); }

.pick__more { margin: 16px 0 0; }
.pick__link {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  padding: 0;
  border: 0;
  background: none;
  font-size: var(--fs-sm);
  color: var(--cedar-soft);
  text-decoration: underline;
  text-underline-offset: 4px;
  text-decoration-color: rgba(217, 148, 106, .45);
  cursor: pointer;
}
.pick__link svg { width: 15px; height: 15px; }
.pick__link:hover { color: #fff; }

@media (hover: none) {
  .pick__tile:hover { transform: none; }
}

@media (max-width: 1040px) {
  /* Stacked under the copy, the panel has the full column — six across is
     too thin to read, three is right at any width it can take here. */
  .pick { max-width: 620px; }
}

@media (max-width: 420px) {
  .pick__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}


/* ==========================================================================
   08  ASSURANCE BAR
   ========================================================================== */
.assurance {
  background: var(--basalt-800);
  border-top: 1px solid rgba(255, 255, 255, .06);
  color: var(--text-invert-mut);
}
.assurance__list {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 14px 32px;
  padding-block: 22px;
}
.assurance__list li {
  display: flex;
  align-items: center;
  gap: 11px;
  font-size: var(--fs-mono);
  letter-spacing: .05em;
  text-transform: uppercase;
}
.assurance__list svg { width: 19px; height: 19px; color: var(--cedar-soft); flex: none; }


/* ==========================================================================
   09  SERVICES
   --------------------------------------------------------------------------
   TO ADD A SERVICE: copy one <article class="service"> block in index.html
   and change the icon, title, text and list items. The grid reflows on its
   own — no CSS changes needed for any number of cards.
   ========================================================================== */
.services__grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(292px, 100%), 1fr));
  gap: 20px;
}

.service {
  display: flex;
  flex-direction: column;
  padding: 26px 24px 24px;
  background: var(--white);
  border: 1px solid var(--line);
  border-radius: var(--r-xl);
  box-shadow: var(--shadow-sm);
  transition: transform var(--dur) var(--ease),
              box-shadow var(--dur) var(--ease),
              border-color var(--dur) var(--ease);
}
.service:hover {
  transform: translateY(-4px);
  border-color: var(--fog-300);
  box-shadow: var(--shadow-md);
}
/* A small chip with depth: lit from the top edge, sitting just proud of the
   card. The gradient and the two inset shadows do the whole job — no images,
   nothing to load, and it stays crisp at any zoom. */
.service__icon {
  width: 44px;
  height: 44px;
  margin-bottom: 16px;
  display: grid;
  place-items: center;
  border-radius: 13px;
  background: linear-gradient(158deg, #fdf5ef 0%, #f2ddce 52%, #e2c1a8 100%);
  border: 1px solid rgba(168, 92, 42, .17);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, .95),
    inset 0 -2px 3px rgba(138, 72, 32, .13),
    0 2px 4px -1px rgba(17, 24, 25, .14),
    0 8px 14px -9px rgba(138, 72, 32, .4);
  color: var(--cedar-deep);
  transition: transform var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.service__icon svg {
  width: 21px;
  height: 21px;
  filter: drop-shadow(0 1px 0 rgba(255, 255, 255, .8));
}
/* The chip lifts a touch further than the card it sits on. */
.service:hover .service__icon {
  transform: translateY(-1px);
  box-shadow:
    inset 0 1px 0 rgba(255, 255, 255, .95),
    inset 0 -2px 3px rgba(138, 72, 32, .13),
    0 3px 6px -1px rgba(17, 24, 25, .16),
    0 12px 18px -10px rgba(138, 72, 32, .45);
}
.service h3 {
  margin-bottom: .45em;
  font-size: clamp(1.08rem, 1.02rem + .28vw, 1.24rem);
}
.service p {
  color: var(--text-muted);
  font-size: var(--fs-sm);
  line-height: 1.58;
}
.service__list {
  margin-top: 15px;
  padding-top: 15px;
  border-top: 1px solid var(--line);
  display: grid;
  gap: 8px;
}

/* Reusable checked list. */
.ticks li {
  position: relative;
  padding-left: 26px;
  font-size: var(--fs-sm);
  color: var(--text-muted);
}
.ticks li::before {
  content: "";
  position: absolute;
  left: 1px;
  top: .45em;
  width: 14px;
  height: 8px;
  border-left: 2px solid var(--cedar-text);
  border-bottom: 2px solid var(--cedar-text);
  border-radius: 1px;
  transform: rotate(-45deg);
}
.ticks--lg li { font-size: var(--fs-body); color: var(--text); padding-left: 30px; }
.section--dark .ticks li { color: var(--text-invert-mut); }
.section--dark .ticks li::before { border-color: var(--cedar-soft); }

.services__note {
  margin-top: 34px;
  padding: 20px 24px;
  border-left: 3px solid var(--cedar);
  border-radius: 0 var(--r-md) var(--r-md) 0;
  background: var(--fog-50);
  color: var(--text-muted);
  font-size: var(--fs-sm);
}


/* ==========================================================================
   10  WHY CHOOSE US
   ========================================================================== */
.why__grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(300px, 100%), 1fr));
  gap: 2px;
  background: var(--line-dark);
  border: 1px solid var(--line-dark);
  border-radius: var(--r-xl);
  overflow: hidden;
}
.why__item {
  padding: 34px 30px;
  background: var(--basalt-900);
  transition: background var(--dur) var(--ease);
}
.why__item:hover { background: var(--basalt-800); }
.why__item svg {
  width: 26px;
  height: 26px;
  margin-bottom: 18px;
  color: var(--cedar-soft);
}
.why__item h3 { margin-bottom: .5em; font-size: 1.12rem; }
.why__item p {
  margin: 0;
  font-size: var(--fs-sm);
  color: var(--text-invert-mut);
}


/* ==========================================================================
   11  PROCESS
   --------------------------------------------------------------------------
   Four columns of type, no illustration. The rule above each number is the
   only ornament, and it is doing work: it marks where one step ends and the
   next begins, the way a dimension is marked on a drawing.
   ========================================================================== */
.steps {
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  gap: clamp(24px, 3vw, 44px);
  margin: 0;
  padding: 0;
  list-style: none;
  counter-reset: none;
}
/* A column, so the fact line can be pushed to the bottom with margin-top:
   auto. The four bodies are different lengths and the facts would otherwise
   sit at four different heights — which reads as sloppy rather than as
   organic, because the rules above them are already aligned. */
.step {
  display: flex;
  flex-direction: column;
  padding-top: 20px;
  border-top: 1.5px solid var(--line-strong);
}
.step__no {
  margin: 0 0 18px;
  font-family: var(--font-mono);
  font-size: var(--fs-sm);
  font-weight: 600;
  letter-spacing: .08em;
  font-variant-numeric: tabular-nums;
  color: var(--cedar-text);
}
.step__title {
  margin: 0 0 .5em;
  font-size: var(--fs-h3);
  letter-spacing: var(--track-tight);
}
.step__body {
  margin: 0 0 18px;
  font-size: var(--fs-sm);
  line-height: 1.65;
  color: var(--text-muted);
}
/* The line the step is actually worth reading for. Set in the mono voice so
   it reads as a specification rather than another sentence of prose. */
.step__fact {
  margin: auto 0 0;
  padding-left: 15px;
  border-left: 2px solid var(--cedar);
  font-family: var(--font-mono);
  font-size: var(--fs-mono);
  font-weight: 500;
  line-height: 1.55;
  letter-spacing: .03em;
  color: var(--text);
}

.steps__foot {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 14px 24px;
  margin-top: clamp(40px, 5vw, 64px);
}

@media (max-width: 900px) {
  .steps { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}

@media (max-width: 520px) {
  .steps { grid-template-columns: 1fr; gap: 0; }
  .step { padding: 20px 0 26px; }
  .step:last-child { padding-bottom: 0; }
}


/* ==========================================================================
   12  PROJECTS + LIGHTBOX
   --------------------------------------------------------------------------
   TO ADD A PROJECT: copy one <figure class="project"> block. Keep the
   data-category value in sync with the filter buttons above the grid.
   ========================================================================== */
.filters {
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
  margin-bottom: 28px;
}
.filter {
  min-height: 42px;
  padding: 9px 20px;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: var(--white);
  font-size: var(--fs-mono);
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--text-muted);
  transition: color var(--dur) var(--ease),
              background var(--dur) var(--ease),
              border-color var(--dur) var(--ease);
}
.filter:hover { border-color: var(--fog-400); color: var(--text); }
.filter[aria-pressed="true"] {
  background: var(--basalt-900);
  border-color: var(--basalt-900);
  color: #fff;
}

.projects__grid {
  columns: 3;
  column-gap: 18px;
}
.project {
  position: relative;
  display: inline-block;
  width: 100%;
  margin: 0 0 18px;
  border-radius: var(--r-lg);
  overflow: hidden;
  background: var(--fog-100);
  box-shadow: var(--shadow-sm);
  break-inside: avoid;
  -webkit-column-break-inside: avoid;
}
.project[hidden] { display: none; }

.project__btn {
  display: block;
  width: 100%;
  padding: 0;
  border: 0;
  background: none;
  text-align: left;
}
.project__btn img {
  display: block;
  width: 100%;
  height: auto;
  transition: transform .6s var(--ease);
}
.project__btn:hover img { transform: scale(1.045); }

.project__caption {
  position: absolute;
  inset: auto 0 0;
  padding: 56px 18px 16px;
  display: grid;
  gap: 3px;
  color: #fff;
  background: linear-gradient(transparent, rgba(10, 15, 16, .9));
  pointer-events: none;
}
.project__caption strong { font-size: 1.02rem; font-weight: 600; }
.project__caption span { font-size: var(--fs-xs); color: rgba(255, 255, 255, .74); }

.project__zoom {
  position: absolute;
  top: 14px;
  right: 14px;
  width: 38px;
  height: 38px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: rgba(17, 24, 25, .62);
  -webkit-backdrop-filter: blur(6px);
          backdrop-filter: blur(6px);
  color: #fff;
  opacity: 0;
  transform: scale(.9);
  transition: opacity var(--dur) var(--ease), transform var(--dur) var(--ease);
  pointer-events: none;
}
.project__zoom svg { width: 17px; height: 17px; }
.project__btn:hover .project__zoom,
.project__btn:focus-visible .project__zoom { opacity: 1; transform: scale(1); }

.projects__foot {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 14px;
  margin-top: 34px;
}
.projects__count { margin: 0; }

/* --- Lightbox --- */
.lightbox {
  position: fixed;
  inset: 0;
  z-index: var(--z-lightbox);
  display: grid;
  grid-template-rows: 1fr auto;
  place-items: center;
  padding: clamp(16px, 4vw, 48px);
  background: rgba(9, 13, 14, .94);
  -webkit-backdrop-filter: blur(6px);
          backdrop-filter: blur(6px);
  visibility: hidden;
  opacity: 0;
  transition: opacity var(--dur) var(--ease), visibility 0s linear var(--dur);
}
.lightbox.is-open {
  visibility: visible;
  opacity: 1;
  transition: opacity var(--dur) var(--ease), visibility 0s linear 0s;
}
.lightbox__stage {
  display: grid;
  place-items: center;
  width: 100%;
  min-height: 0;
}
.lightbox__img {
  max-width: min(1100px, 100%);
  max-height: calc(100dvh - 190px);
  width: auto;
  border-radius: var(--r-md);
  box-shadow: var(--shadow-lg);
}
.lightbox__bar {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 16px;
  width: 100%;
  padding-top: 20px;
  color: #fff;
  text-align: center;
}
.lightbox__caption { font-size: var(--fs-sm); color: rgba(255, 255, 255, .82); }
.lightbox__count { font-size: var(--fs-xs); color: rgba(255, 255, 255, .5); font-variant-numeric: tabular-nums; }

.lightbox__close,
.lightbox__nav {
  position: absolute;
  display: grid;
  place-items: center;
  border: 1px solid rgba(255, 255, 255, .22);
  border-radius: 50%;
  background: rgba(255, 255, 255, .08);
  color: #fff;
  transition: background var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.lightbox__close:hover,
.lightbox__nav:hover { background: rgba(255, 255, 255, .2); border-color: rgba(255, 255, 255, .5); }
.lightbox__close { top: 18px; right: 18px; width: 46px; height: 46px; }
.lightbox__close svg { width: 20px; height: 20px; }
.lightbox__nav { top: 50%; width: 50px; height: 50px; margin-top: -25px; }
.lightbox__nav svg { width: 22px; height: 22px; }
.lightbox__nav--prev { left: 14px; }
.lightbox__nav--next { right: 14px; }


/* ==========================================================================
   13  ABOUT
   ========================================================================== */
.about__grid {
  display: grid;
  grid-template-columns: .95fr 1.05fr;
  gap: clamp(32px, 5vw, 72px);
  align-items: center;
}
.about__media {
  position: relative;
  border-radius: var(--r-xl);
  overflow: hidden;
  box-shadow: var(--shadow-md);
}
.about__media img {
  width: 100%;
  aspect-ratio: 3 / 4;
  object-fit: cover;
}
.about__badge {
  position: absolute;
  left: 20px;
  right: 20px;
  bottom: 20px;
  padding: 18px 22px;
  border: 1px solid rgba(255, 255, 255, .14);
  border-radius: var(--r-md);
  background: rgba(17, 24, 25, .88);
  -webkit-backdrop-filter: blur(10px);
          backdrop-filter: blur(10px);
  color: #fff;
}
.about__badge strong { display: block; font-size: 1.02rem; line-height: 1.3; }
.about__badge span { font-size: var(--fs-xs); color: var(--cedar-soft); }
.about__body p { color: var(--text-muted); }
.about__body .ticks { margin: 26px 0 30px; display: grid; gap: 12px; }


/* ==========================================================================
   14  REVIEWS
   --------------------------------------------------------------------------
   PLACEHOLDER STATE: each .review carries data-placeholder. Delete that
   attribute and replace the text with a real review to switch it to the
   finished style. See the template comment in index.html.
   ========================================================================== */
.reviews__grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(280px, 100%), 1fr));
  gap: 20px;
}
.review {
  display: flex;
  flex-direction: column;
  gap: 14px;
  margin: 0;
  padding: 30px 28px;
  border: 1px solid var(--line-dark);
  border-radius: var(--r-lg);
  background: var(--surface-dark);
}
.review__quote {
  margin: 0;
  font-size: 1.02rem;
  line-height: 1.6;
  color: #e9e7e3;
}
.review__meta {
  margin-top: auto;
  padding-top: 4px;
  font-size: var(--fs-sm);
  color: var(--text-invert-mut);
}
.review__stars { color: var(--cedar-soft); letter-spacing: .16em; font-size: 1rem; }

/* Unfilled slot — deliberately reads as "to do", never as a real review. */
.reviews__cta {
  margin-top: 32px;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 14px;
}


/* --- Google profile ------------------------------------------------------
   Sits under the reviews as a quiet verification strip, not an advert. The
   only colour in it is Google's own mark, at the size a favicon runs. */
.gverify {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 18px 24px;
  margin-top: 34px;
  padding: 22px 26px;
  border: 1px solid var(--line-dark);
  border-radius: var(--r-lg);
  background: var(--surface-dark);
}
.gverify[hidden] { display: none; }
.gverify__mark {
  display: grid;
  place-items: center;
  width: 44px;
  height: 44px;
  flex: none;
  border-radius: 50%;
  background: var(--surface-dark-2);
  border: 1px solid var(--line-dark);
  color: var(--cedar-soft);
}
/* A star, not the Google G. Google's brand guidelines forbid recolouring
   their mark and restrict third-party use of the monochrome version, so the
   choice was the four-colour logo or no logo — and the owner wanted the
   green gone. Naming Google in the text is ordinary nominative use and
   needs no mark at all. */
.gverify__mark svg { width: 22px; height: 22px; fill: currentColor; }
.gverify__text { flex: 1 1 240px; min-width: 0; }
.gverify__label {
  margin: 0 0 3px;
  font-family: var(--font-mono);
  font-size: var(--fs-mono);
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--cedar-soft);
}
.gverify__line { margin: 0; font-size: var(--fs-sm); color: var(--text-invert-mut); }
.gverify__actions { display: flex; flex-wrap: wrap; gap: 10px; }


/* --- Payment methods -----------------------------------------------------
   A strip under the reasons-to-hire grid. Names only: every one of these is
   recognised as a word, and six borrowed logos would shout louder than
   anything else on the page. */
.pays {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 14px 26px;
  margin-top: 30px;
  padding: 18px 24px;
  border: 1px solid var(--line-dark);
  border-radius: var(--r-lg);
  background: var(--surface-dark);
}
.pays__label {
  margin: 0;
  font-family: var(--font-mono);
  font-size: var(--fs-mono);
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--cedar-soft);
}
.pays__list {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 10px;
  margin: 0;
  padding: 0;
  list-style: none;
}
.pays__list li {
  padding: 6px 13px;
  border: 1px solid var(--line-dark);
  border-radius: var(--r-pill);
  background: var(--surface-dark-2);
  font-size: var(--fs-sm);
  color: var(--text-invert);
  white-space: nowrap;
}


/* --- Generated pages -----------------------------------------------------
   Breadcrumbs and the photo strip used by the service pages. Both live here
   rather than in a stylesheet of their own: they are made of the same tokens
   as everything else and there is no reason to ship a second file for them. */
.crumbs {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 8px;
  max-width: var(--wrap);
  margin: 0 auto;
  padding: 22px var(--gutter) 0;
  font-family: var(--font-mono);
  font-size: var(--fs-mono);
  letter-spacing: .06em;
  color: var(--text-muted);
}
.crumbs a { color: var(--text-muted); text-decoration: none; }
.crumbs a:hover { color: var(--cedar-text); text-decoration: underline; }
.crumbs__sep { color: var(--line-strong); }
.crumbs [aria-current="page"] { color: var(--text); }

.service__more {
  display: flex;
  flex-wrap: wrap;
  gap: 4px 16px;
  margin: 16px 0 0;
  font-family: var(--font-mono);
  font-size: var(--fs-mono);
  letter-spacing: .06em;
  text-transform: uppercase;
}
.service__more a { color: var(--cedar-text); }

.shots {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(min(240px, 100%), 1fr));
  gap: 18px;
}
.shot {
  margin: 0;
  overflow: hidden;
  border-radius: var(--r-lg);
  box-shadow: var(--shadow-sm);
}
.shot img {
  display: block;
  width: 100%;
  height: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
}


/* ==========================================================================
   15  FAQ
   ========================================================================== */
.faq { display: grid; gap: 12px; }
.faq__item {
  border: 1px solid var(--line);
  border-radius: var(--r-md);
  background: var(--white);
  overflow: hidden;
  transition: border-color var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.faq__item[open] { border-color: var(--fog-300); box-shadow: var(--shadow-sm); }
.faq__q {
  position: relative;
  display: block;
  padding: 20px 60px 20px 24px;
  font-family: var(--font-display);
  font-size: 1.05rem;
  font-weight: 600;
  letter-spacing: -.015em;
  list-style: none;
  cursor: pointer;
}
.faq__q::-webkit-details-marker { display: none; }
.faq__q::after,
.faq__q::before {
  content: "";
  position: absolute;
  right: 26px;
  top: 50%;
  background: var(--cedar-text);
  border-radius: 2px;
  transition: transform var(--dur) var(--ease), opacity var(--dur) var(--ease);
}
.faq__q::before { width: 14px; height: 2px; margin-top: -1px; }
.faq__q::after  { width: 2px; height: 14px; margin-top: -7px; margin-right: 6px; }
.faq__item[open] .faq__q::after { transform: rotate(90deg); opacity: 0; }
.faq__a {
  padding: 0 24px 22px;
  color: var(--text-muted);
  font-size: var(--fs-sm);
}


/* ==========================================================================
   16  SERVICE AREA MAP
   --------------------------------------------------------------------------
   The map is a Leaflet canvas dropped into the same card shape the rest of
   the page uses. Everything inside it — the dashed boundary, the pins, the
   two zoom buttons — is drawn from the tokens above, so the map reads as
   part of the site rather than an embed sitting on top of it.
   ========================================================================== */
.area__grid {
  display: grid;
  grid-template-columns: .9fr 1.1fr;
  gap: clamp(32px, 5vw, 72px);
  align-items: center;
}

/* Two columns of towns: the list answers "do you come to me?" on its own,
   which is what keeps the map optional rather than load-bearing. */
.area__towns {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 10px 28px;
  margin: 30px 0 0;
  padding: 0;
  list-style: none;
}

.area__note {
  margin-top: 26px;
  padding: 18px 22px;
  border-left: 3px solid var(--cedar);
  border-radius: 0 var(--r-md) var(--r-md) 0;
  background: var(--white);
  color: var(--text-muted);
  font-size: var(--fs-sm);
}

.area__map { margin: 0; }

.area__canvas {
  height: clamp(360px, 44vw, 520px);
  border: 1px solid var(--line);
  border-radius: var(--r-xl);
  background: var(--fog-100);
  box-shadow: var(--shadow-md);
  overflow: hidden;
  /* Keeps Leaflet's stacked panes from painting over the rounded corners. */
  isolation: isolate;
}

/* Before the tiles arrive, and if they never do, the frame still says
   something true instead of sitting there as an empty grey box. */
.area__canvas::after {
  content: "Map unavailable \2014 we cover roughly 35 miles around Vancouver, WA";
  display: grid;
  place-items: center;
  height: 100%;
  padding: 24px;
  text-align: center;
  font-family: var(--font-mono);
  font-size: var(--fs-sm);
  letter-spacing: .06em;
  color: var(--fog-500);
}
.area__canvas[data-state="loading"]::after {
  content: "Loading map\2026";
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  font-size: var(--fs-mono);
}
.area__canvas[data-state="ready"]::after { content: none; }

/* The tiles arrive in full colour; this pulls them back to the page's palette
   without touching the boundary, the pin or the labels drawn on top. */
.area__canvas .leaflet-tile-pane {
  filter: grayscale(1) contrast(.86) brightness(1.06) opacity(.86);
}

.area__canvas .leaflet-container {
  height: 100%;
  background: var(--fog-100);
  font-family: var(--font-sans);
  font-size: var(--fs-xs);
}

/* Attribution is required by the tile licence, so it stays — just quiet. */
.area__canvas .leaflet-control-attribution {
  padding: 3px 9px;
  border-radius: var(--r-sm) 0 0 0;
  background: rgba(255, 255, 255, .84);
  color: var(--fog-500);
  font-family: var(--font-mono);
  font-size: 10px;
}
.area__canvas .leaflet-control-attribution a { color: var(--fog-600); }

/* --- Pins ---------------------------------------------------------------
   The icon itself is a zero-size anchor at the exact coordinate; the dot and
   the label hang off it, so the pin never drifts as the map zooms. */
.area__marker { position: relative; }
.area__dot {
  position: absolute;
  left: 0;
  top: 0;
  width: 12px;
  height: 12px;
  border-radius: 50%;
  background: var(--cedar);
  box-shadow: 0 0 0 3px var(--white), var(--shadow-sm);
  transform: translate(-50%, -50%);
}
.area__label {
  position: absolute;
  left: 0;
  top: 12px;
  padding: 3px 9px;
  border-radius: var(--r-pill);
  background: rgba(255, 255, 255, .92);
  color: var(--fog-600);
  font-family: var(--font-mono);
  font-size: 10px;
  letter-spacing: .08em;
  text-transform: uppercase;
  white-space: nowrap;
  transform: translateX(-50%);
}
.area__marker--base .area__dot {
  width: 18px;
  height: 18px;
  box-shadow: 0 0 0 4px var(--white), 0 0 0 5px rgba(168, 92, 42, .28), var(--shadow-sm);
}
.area__marker--base .area__label {
  top: 17px;
  background: var(--basalt-900);
  color: #fff;
  font-weight: 500;
}

/* --- Zoom ---------------------------------------------------------------
   Two buttons, no layers switcher, no scale bar. Wheel zoom stays off so the
   page never traps a scroll. */
.area__zoom {
  display: grid;
  gap: 6px;
  margin: 0 12px 12px 0;
}
.area__zoom button {
  width: 38px;
  height: 38px;
  display: grid;
  place-items: center;
  border: 1px solid var(--line);
  border-radius: var(--r-sm);
  background: var(--white);
  color: var(--text);
  font-family: var(--font-mono);
  font-size: 17px;
  line-height: 1;
  cursor: pointer;
  box-shadow: var(--shadow-sm);
  transition: background var(--dur) var(--ease), border-color var(--dur) var(--ease);
}
.area__zoom button:hover {
  background: var(--fog-50);
  border-color: var(--line-strong);
}

.area__legend {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 24px;
  margin-top: 16px;
  font-family: var(--font-mono);
  font-size: var(--fs-mono);
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--fog-600);
}
.area__key {
  display: inline-flex;
  align-items: center;
  gap: 9px;
}
.area__key-dot {
  width: 11px;
  height: 11px;
  border-radius: 50%;
  background: var(--cedar);
  box-shadow: 0 0 0 2px var(--white), 0 0 0 3px rgba(168, 92, 42, .3);
}
.area__key-line {
  width: 24px;
  border-top: 2px dashed var(--cedar);
}


/* ==========================================================================
   17  CONTACT & FORM
   ========================================================================== */
.contact__grid {
  display: grid;
  grid-template-columns: .9fr 1.1fr;
  gap: clamp(32px, 5vw, 68px);
  align-items: start;
}
.contact__list { display: grid; gap: 20px; margin-top: 32px; }
.contact__list li { display: flex; gap: 15px; align-items: flex-start; }
.contact__icon {
  width: 42px;
  height: 42px;
  display: grid;
  place-items: center;
  border-radius: var(--r-md);
  background: rgba(217, 148, 106, .14);
  color: var(--cedar-soft);
  flex: none;
}
.contact__icon svg { width: 20px; height: 20px; }
.contact__label {
  display: block;
  font-size: var(--fs-mono);
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--text-invert-mut);
}
.contact__value {
  font-size: 1.05rem;
  font-weight: 500;
  color: #fff;
}
a.contact__value:hover { color: var(--cedar-soft); }

/* --- Form --- */
.form {
  display: grid;
  gap: 18px;
  padding: clamp(26px, 3.4vw, 38px);
  border-radius: var(--r-xl);
  background: var(--white);
  color: var(--text);
  box-shadow: var(--shadow-lg);
}
.form__row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 18px;
}
.field {
  display: grid;
  gap: 7px;
  margin: 0;
  align-content: start;
}
.field__label {
  font-size: var(--fs-mono);
  letter-spacing: .08em;
  text-transform: uppercase;
  color: var(--text-muted);
}
.field__req { color: var(--cedar-text); }
.field__opt { font-weight: 400; color: var(--fog-500); }

.field input,
.field select,
.field textarea {
  width: 100%;
  min-height: 50px;
  padding: 13px 15px;
  border: 1.5px solid var(--line);
  border-radius: var(--r-md);
  background: var(--fog-50);
  font-size: var(--fs-sm);
  transition: border-color var(--dur) var(--ease), background var(--dur) var(--ease);
}
.field textarea { min-height: 130px; resize: vertical; line-height: 1.6; }
.field select { appearance: none; -webkit-appearance: none; padding-right: 42px;
  background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'%3E%3Cpath d='M7 10l5 5 5-5' fill='none' stroke='%235e6570' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'/%3E%3C/svg%3E");
  background-repeat: no-repeat;
  background-position: right 14px center;
  background-size: 20px 20px;
}
.field input:focus,
.field select:focus,
.field textarea:focus {
  outline: none;
  border-color: var(--cedar);
  background: var(--white);
  box-shadow: 0 0 0 3px rgba(168, 92, 42, .14);
}
.field input[aria-invalid="true"],
.field select[aria-invalid="true"],
.field textarea[aria-invalid="true"] {
  border-color: #c0392b;
  background: #fdf5f4;
}
.field__error {
  display: none;
  font-size: var(--fs-xs);
  font-weight: 500;
  color: #a52c1e;
}
.field__error:not(:empty) { display: block; }

.form__note { margin: 0; }
.form__status {
  display: none;
  margin: 0;
  padding: 14px 16px;
  border-radius: var(--r-md);
  font-size: var(--fs-sm);
  font-weight: 500;
}
/* Success, without green. The meaning is carried by the words and by the
   tick, not by hue — which is how it should have been anyway, since a
   colour-blind visitor never got the green/red distinction. Failure keeps
   red, because red is the one signal worth shouting. */
.form__status--ok  {
  display: block;
  background: var(--cedar-wash);
  border: 1px solid #e0c3ae;
  color: #7a3f1c;
}
.form__status--bad { display: block; background: #fdecea; border: 1px solid #f2c2bc; color: #96271a; }

/* Honeypot — off-screen, never shown to people. */
.hp {
  position: absolute;
  left: -9999px;
  width: 1px;
  height: 1px;
  opacity: 0;
}


/* ==========================================================================
   18  FOOTER
   ========================================================================== */
.footer {
  background: var(--basalt-800);
  color: var(--text-invert-mut);
  padding-top: clamp(56px, 6vw, 84px);
}
.footer__grid {
  display: grid;
  grid-template-columns: 1.7fr 1fr 1fr 1.2fr;
  gap: 40px;
  padding-bottom: 48px;
}
.footer__about { max-width: 34ch; font-size: var(--fs-sm); line-height: 1.65; }
.footer .brand { margin: 0 0 18px; }
.footer h3 {
  margin-bottom: 18px;
  font-size: var(--fs-mono);
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: #fff;
}
.footer__links { display: grid; gap: 2px; }
.footer__links a,
.footer__contact a {
  display: inline-block;
  padding: 5px 0;
  font-size: var(--fs-sm);
  transition: color var(--dur) var(--ease);
}
.footer__links a:hover,
.footer__contact a:hover { color: var(--cedar-soft); }
.footer__contact { display: grid; gap: 2px; }
.footer__legal {
  margin-top: 18px;
  font-size: var(--fs-xs);
  color: var(--text-invert-mut);   /* --fog-500 давал 3.7:1, нужно 4.5:1 */
}
.footer__bottom {
  display: flex;
  flex-wrap: wrap;
  gap: 8px 24px;
  justify-content: space-between;
  padding-block: 22px;
  border-top: 1px solid var(--line-dark);
  font-size: var(--fs-xs);
}
.footer__bottom p { margin: 0; }


/* ==========================================================================
   19  BACK TO TOP & UTILITIES
   ========================================================================== */
.to-top {
  position: fixed;
  right: 20px;
  bottom: 20px;
  z-index: 90;
  width: 46px;
  height: 46px;
  display: grid;
  place-items: center;
  border-radius: 50%;
  background: var(--basalt-900);
  color: #fff;
  box-shadow: var(--shadow-md);
  opacity: 0;
  transform: translateY(10px);
  pointer-events: none;
  transition: opacity var(--dur) var(--ease),
              transform var(--dur) var(--ease),
              background var(--dur) var(--ease);
}
.to-top.is-visible { opacity: 1; transform: none; pointer-events: auto; }
.to-top:hover { background: var(--cedar); }
.to-top svg { width: 20px; height: 20px; }

.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}


/* ==========================================================================
   20  MOTION & REVEAL
   --------------------------------------------------------------------------
   The hidden state is applied only when JS is running (html.js). Without
   JS every element stays visible — the page never ends up blank.
   ========================================================================== */
.js .reveal {
  opacity: 0;
  transform: translateY(26px);
  transition: opacity var(--dur-spring) var(--ease),
              transform var(--dur-spring) var(--spring);
  /* Opacity stays on a plain ease. A spring on opacity would overshoot past
     1, which clamps, and the element would appear to hesitate at the end. */
}
.js .reveal.is-visible { opacity: 1; transform: none; }

/* Staggered groups.
   A container marked .stagger hands each child an index in --d when the
   group first comes into view, and the child's delay is that index times
   one step. The whole group is triggered by one observer entry rather than
   one per child, so neighbours stay in lockstep however fast you scroll —
   a per-element observer fires in whatever order the scroll happened to
   cross them, and the sequence falls apart. */
.js .stagger > * {
  opacity: 0;
  transform: translateY(22px);
  transition: opacity var(--dur-spring) var(--ease),
              transform var(--dur-spring) var(--spring);
  transition-delay: calc(var(--d, 0) * var(--stagger-step));
}
.js .stagger.is-visible > * { opacity: 1; transform: none; }

/* A staggered group inside a .reveal would wait for the parent's own fade
   before it started; collapse that to a single movement. */
.js .reveal.stagger { opacity: 1; transform: none; transition: none; }

/* Failsafe (see the inline script in <head>): nothing stays hidden. */
.reveal-all .reveal { opacity: 1; transform: none; }


/* ==========================================================================
   21  CASE STUDIES
   --------------------------------------------------------------------------
   Used by /projects/ and the four project pages, plus the featured strip on
   the home page. Same tokens as everything else — no new colours, no new
   type scale, and no JavaScript beyond the .reveal observer that already
   runs site-wide.

   The photographs decide the layout here. They come off a phone at 4:3 and
   3:4 in roughly equal numbers, so nothing crops them to a fixed shape: each
   figure carries the picture's own aspect-ratio and the grid works around it.
   ========================================================================== */

/* --- Hero: copy beside the strongest finished photo ---------------------- */
.case-hero__inner {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.05fr);
  gap: clamp(32px, 5vw, 64px);
  align-items: center;
}
.case-hero h1 { margin-bottom: .5em; }
.case-hero .lede { max-width: 46ch; }

.case-hero__media {
  margin: 0;
  position: relative;
  border-radius: var(--r-lg);
  overflow: hidden;
  box-shadow: var(--shadow-md);
}
.case-hero__media img {
  display: block;
  width: 100%;
  height: auto;
}

/* The headline figures, restated as one mono line under the lede. */
.case-line {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 6px 14px;
  margin: 26px 0 0;
  font-family: var(--font-mono);
  font-size: var(--fs-sm);
  font-weight: 500;
  letter-spacing: .04em;
  color: var(--text);
}
.case-line span { display: inline-flex; align-items: center; gap: 14px; }
.case-line span::after {
  content: "";
  width: 4px;
  height: 4px;
  border-radius: 50%;
  background: var(--line-strong);
}
.case-line span:last-child::after { display: none; }

.case-jump {
  display: inline-flex;
  align-items: center;
  gap: 10px;
  margin-top: 30px;
  font-family: var(--font-mono);
  font-size: var(--fs-mono);
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--cedar-text);
  text-decoration: none;
}
.case-jump:hover { text-decoration: underline; }
.case-jump svg { width: 14px; height: 14px; }

/* --- Figures band: the numbers, given room ------------------------------ */
.figures {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(190px, 100%), 1fr));
  gap: 1px;
  background: var(--line-dark);
  border: 1px solid var(--line-dark);
  border-radius: var(--r-md);
  overflow: hidden;
}
.figure {
  padding: 26px clamp(20px, 2.4vw, 30px);
  background: var(--basalt-900);
}
.figure__k {
  margin: 0 0 10px;
  font-family: var(--font-mono);
  font-size: var(--fs-mono);
  font-weight: 500;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--cedar-soft);
}
.figure__v {
  margin: 0;
  font-family: var(--font-mono);
  font-size: clamp(1.1rem, .95rem + .55vw, 1.4rem);
  font-weight: 600;
  line-height: 1.28;
  text-wrap: balance;
  letter-spacing: var(--track-tight);
  font-variant-numeric: tabular-nums;
  color: #fff;
}
.figure__n {
  margin: 8px 0 0;
  font-size: var(--fs-xs);
  line-height: 1.5;
  color: var(--text-invert-mut);
}

/* --- The story, as numbered stages -------------------------------------- */
.stages {
  display: grid;
  gap: clamp(38px, 5vw, 62px);
  margin: 0;
  padding: 0;
  list-style: none;
  counter-reset: stage;
}
.stage {
  display: grid;
  grid-template-columns: 64px minmax(0, 1fr);
  gap: clamp(18px, 3vw, 34px);
  align-items: start;
}
.stage::before {
  counter-increment: stage;
  content: counter(stage, decimal-leading-zero);
  font-family: var(--font-mono);
  font-size: var(--fs-sm);
  font-weight: 600;
  letter-spacing: .04em;
  color: var(--cedar-text);
  padding-top: .35em;
  border-top: 1.5px solid var(--line-strong);
}
.stage h3 { margin: 0 0 .5em; }
.stage p { margin: 0 0 1em; max-width: 62ch; color: var(--text-muted); }
.stage p:last-child { margin-bottom: 0; }
.stage .ticks { margin-top: 14px; }
.stage figure { margin: 22px 0 0; }
.stage figure img {
  display: block;
  width: 100%;
  max-width: 560px;
  height: auto;
  border-radius: var(--r-md);
  box-shadow: var(--shadow-sm);
}
.stage figcaption {
  margin-top: 10px;
  font-family: var(--font-mono);
  font-size: var(--fs-mono);
  letter-spacing: .05em;
  color: var(--text-muted);
}

/* --- Staggered gallery --------------------------------------------------
   A masonry column layout rather than a grid of identical rectangles: the
   pictures keep their own proportions and the eye has somewhere to go. */
.plates {
  columns: 3;
  column-gap: 18px;
}
.plates figure {
  margin: 0 0 18px;
  break-inside: avoid;
  border-radius: var(--r-lg);
  overflow: hidden;
  box-shadow: var(--shadow-sm);
  background: var(--fog-100);
}
.plates img {
  display: block;
  width: 100%;
  height: auto;
}

/* --- Before / after: shown side by side, never as a wipe ----------------
   A slider implies the two frames line up. These were taken a month apart
   from roughly the same corner, not from a tripod, so they are presented as
   two labelled pictures and left honest. */
.compare {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(300px, 100%), 1fr));
  gap: clamp(16px, 2.4vw, 26px);
}
.compare figure {
  margin: 0;
  position: relative;
  border-radius: var(--r-lg);
  overflow: hidden;
  box-shadow: var(--shadow-sm);
}
.compare img { display: block; width: 100%; height: auto; }
.compare figcaption {
  position: absolute;
  top: 14px;
  left: 14px;
  padding: 7px 14px;
  border-radius: var(--r-pill);
  background: rgba(17, 24, 25, .82);
  color: #fff;
  font-family: var(--font-mono);
  font-size: var(--fs-mono);
  font-weight: 600;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
}

/* --- Scale callout: the one number worth saying loudly ------------------- */
.scale {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  gap: 26px clamp(38px, 6vw, 84px);
}
.scale > span {
  display: flex;
  flex-direction: column;
  gap: 10px;
}
.scale__v {
  font-family: var(--font-mono);
  font-size: clamp(2.4rem, 1.5rem + 3.8vw, 4.4rem);
  font-weight: 600;
  line-height: 1;
  letter-spacing: -0.03em;
  font-variant-numeric: tabular-nums;
  color: #fff;
}
.scale__k {
  font-family: var(--font-mono);
  font-size: var(--fs-mono);
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--cedar-soft);
}

/* --- Project cards: /projects/ and the home-page strip ------------------- */
/* Four cards read better two-up than four-across: the photograph is what
   sells a case study and a quarter-width thumbnail is not a photograph. */
.cases {
  display: grid;
  grid-template-columns: 1fr;
  gap: clamp(20px, 2.6vw, 30px);
}

@media (min-width: 740px) {
  .cases { grid-template-columns: repeat(2, minmax(0, 1fr)); }
}
.case-card {
  position: relative;
  display: flex;
  flex-direction: column;
  border: 1px solid var(--line);
  border-radius: var(--r-lg);
  background: var(--white);
  overflow: hidden;
  box-shadow: var(--shadow-sm);
  transition: transform var(--dur) var(--ease), box-shadow var(--dur) var(--ease);
}
.case-card:hover,
.case-card:focus-within {
  transform: translateY(-3px);
  box-shadow: var(--shadow-md);
}
.case-card__media { margin: 0; background: var(--fog-100); }
.case-card__media img {
  display: block;
  width: 100%;
  height: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
}
.case-card__body {
  display: flex;
  flex-direction: column;
  flex: 1;
  padding: 24px clamp(20px, 2vw, 26px) 26px;
}
.case-card__kind {
  margin: 0 0 12px;
  font-family: var(--font-mono);
  font-size: var(--fs-mono);
  font-weight: 500;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--cedar-text);
}
.case-card__t { margin: 0 0 .45em; font-size: var(--fs-h3); }
.case-card__t a {
  color: inherit;
  text-decoration: none;
}
/* The whole card is the target; the link keeps the accessible name. */
.case-card__t a::after {
  content: "";
  position: absolute;
  inset: 0;
}
.case-card__t a:hover { color: var(--cedar-text); }
.case-card p { margin: 0 0 18px; color: var(--text-muted); font-size: var(--fs-sm); }
.case-card__stats {
  display: flex;
  flex-wrap: wrap;
  gap: 6px;
  margin: auto 0 18px;
  padding: 0;
  list-style: none;
}
.case-card__stats li {
  padding: 5px 11px;
  border: 1px solid var(--line);
  border-radius: var(--r-pill);
  background: var(--fog-50);
  font-family: var(--font-mono);
  font-size: var(--fs-mono);
  font-weight: 500;
  letter-spacing: .04em;
  font-variant-numeric: tabular-nums;
  color: var(--text);
}
.case-card__go {
  display: inline-flex;
  align-items: center;
  gap: 9px;
  font-family: var(--font-mono);
  font-size: var(--fs-mono);
  font-weight: 600;
  letter-spacing: var(--track-label);
  text-transform: uppercase;
  color: var(--cedar-text);
}
.case-card__go svg { width: 15px; height: 15px; }

/* --- The pricing caveat, wherever a figure appears ----------------------- */
.caveat {
  margin: 22px 0 0;
  padding-left: 16px;
  border-left: 2px solid var(--line-strong);
  font-size: var(--fs-sm);
  line-height: 1.6;
  color: var(--text-muted);
  max-width: 78ch;
}
.section--dark .caveat {
  border-left-color: var(--line-dark);
  color: var(--text-invert-mut);
}

@media (max-width: 1040px) {
  .plates { columns: 2; }
}

@media (max-width: 860px) {
  .case-hero__inner { grid-template-columns: 1fr; }
  .case-hero__media { max-width: 620px; }
}

@media (max-width: 560px) {
  .plates { columns: 1; }
  .stage { grid-template-columns: 1fr; gap: 14px; }
  .stage::before { width: 46px; }
  .figure { padding: 20px; }
}

/* ==========================================================================
   22  RESPONSIVE
   ========================================================================== */
@media (min-width: 1120px) {
  .header__phone { display: inline-flex; }
}

@media (max-width: 1040px) {
  .hero__inner { grid-template-columns: 1fr; }
  .hero__copy { max-width: 46ch; }
  .hero__media { max-width: 620px; }
  .hero__media::before { inset: 14px -12px -12px 14px; }
  .assurance__list { grid-template-columns: repeat(2, 1fr); }
  .about__grid,
  .area__grid,
  .contact__grid { grid-template-columns: 1fr; }
  .about__media { max-width: 560px; }
  .projects__grid { columns: 2; }
  .footer__grid { grid-template-columns: 1fr 1fr; gap: 34px; }
}

@media (max-width: 900px) {
  .steps { grid-template-columns: 1fr; gap: 40px; }
  .step:not(:last-child)::before {
    inset: auto auto -40px 34px;
    width: 2px;
    height: 40px;
  }
  .step:not(:last-child)::after {
    inset: auto auto -26px 31px;
    margin-top: 0;
    transform: rotate(135deg);
  }

  .nav,
  .header__cta { display: none; }
  .burger { display: flex; }
  .header__actions { gap: 4px; }
}

@media (max-width: 620px) {
  .form__row { grid-template-columns: 1fr; }
  .gverify { padding: 20px; gap: 14px 18px; }
  .gverify__actions { width: 100%; }
  .gverify__actions .btn { flex: 1 1 100%; }
  .pays { padding: 16px 18px; gap: 12px 16px; }
  .area__canvas { height: clamp(300px, 64vw, 420px); }
  .area__legend { gap: 8px 18px; }
  .hero__actions { gap: 12px; }
  .hero__actions .btn { width: 100%; }
  .hero__media::before { display: none; }
  .assurance__list { grid-template-columns: 1fr; gap: 12px; padding-block: 20px; }
  .footer__grid { grid-template-columns: 1fr; gap: 32px; }
  .service { padding: 22px 20px; }
  .projects__grid { columns: 1; }
  .why__item { padding: 28px 24px; }
  .lightbox__nav { width: 44px; height: 44px; margin-top: -22px; }
  .lightbox__nav--prev { left: 8px; }
  .lightbox__nav--next { right: 8px; }
  .lightbox__img { max-height: calc(100dvh - 170px); }
  .to-top { right: 14px; bottom: 14px; }
  .drawer__link { font-size: 1.25rem; }
}

@media (max-width: 380px) {
  .brand__name { font-size: .92rem; }
  .brand__sub { letter-spacing: .26em; }
}

/* Anyone who asked for less motion gets none of it. */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
    scroll-behavior: auto !important;
  }
  .js .reveal,
  .js .stagger > * { opacity: 1; transform: none; transition-delay: 0s !important; }
  .btn:hover, .btn:active { transform: none; }
  .pick__tile:hover, .pick__tile:focus-visible { transform: none; }
  .pick__tile:hover img, .pick__tile:focus-visible img { transform: none; }
}


/* ==========================================================================
   23  PAGE TRANSITIONS
   --------------------------------------------------------------------------
   Cross-document view transitions. The browser takes a picture of the old
   page, a picture of the new one, and animates between them — so clicking
   from the home page to a project no longer flashes white.

   This is the whole implementation. There is no JavaScript behind it, no
   router, and no interception of clicks: the navigation is still an ordinary
   link to an ordinary HTML file, which is the only reason it can be added to
   a site with no build step at all.

   Support is Chrome/Edge 126+ and Safari 18.2+. Firefox has not shipped it.
   Where it is missing the browser ignores the at-rule and navigates the way
   it always did — nothing to detect and nothing to fall back to.

   Both documents have to opt in, which every page here does: they all load
   this stylesheet.
   ========================================================================== */
@view-transition {
  navigation: auto;
}

/* The header carries view-transition-name: site-header (set on .header up in
   section 06). Naming it is what makes the browser carry the same header
   across the navigation instead of cross-fading it with the rest of the
   page — the difference between "the site animated" and "the page I was
   looking at turned into the next one". */

@media (prefers-reduced-motion: no-preference) {
  /* The old page leaves by fading and settling back a little; the new one
     arrives from slightly below. The distances are small on purpose — a
     transition between two pages of the same site should read as one moving,
     not as a slide deck. */
  @keyframes vt-out {
    to { opacity: 0; transform: translateY(-8px) scale(.995); }
  }

  @keyframes vt-in {
    from { opacity: 0; transform: translateY(14px); }
  }

  ::view-transition-old(root) {
    animation: vt-out .26s var(--ease) both;
  }

  ::view-transition-new(root) {
    animation: vt-in .42s var(--spring) both;
  }
}

/* An explicit off switch. The blanket reduced-motion rule further down sets
   animation-duration on *, but ::view-transition-* pseudo-elements live in
   their own tree and that rule never reaches them. */
@media (prefers-reduced-motion: reduce) {
  ::view-transition-old(root),
  ::view-transition-new(root) {
    animation: none;
  }
}


/* ==========================================================================
   24  PRINT
   ========================================================================== */
@media print {
  .header, .drawer, .to-top, .filters, .lightbox, .hero__bg,
  .hero__actions, .project__zoom { display: none !important; }
  body { background: #fff; color: #000; font-size: 11pt; }
  .section, .hero__inner { padding-block: 18pt; }
  .section--dark, .hero, .footer, .assurance {
    background: #fff !important;
    color: #000 !important;
  }
  .section--dark h2, .section--dark h3, .footer h4 { color: #000 !important; }
  a[href^="http"]::after,
  a[href^="mailto"]::after,
  a[href^="tel"]::after { content: " (" attr(href) ")"; font-size: 9pt; }
  .form, .service, .review, .faq__item { break-inside: avoid; }
}
