/* ==========================================================================
   M&C Home Improvements
   Single stylesheet. No framework, no build step, no JavaScript.
   ========================================================================== */

/* The UA rule for [hidden] is display:none at attribute specificity, so any
   class that sets display — .form is display:grid — silently beats it and the
   element stays visible. Author-level !important is the standard fix. */
[hidden] { display: none !important; }

/* --- Fonts: self-hosted, latin subset, variable ------------------------- */
/* One family. Archivo's width axis does the work a second typeface usually
   would: headlines run wide, like lettering on a work truck or a yard sign;
   body copy stays at normal width. */
@font-face {
  font-family: 'Archivo';
  src: url('../fonts/archivo-latin.woff2') format('woff2-variations');
  font-weight: 100 900;
  font-stretch: 62% 125%;
  font-style: normal;
  font-display: swap;
}

/* --- Tokens ------------------------------------------------------------- */
:root {
  /* Midnight for the frame, limestone for the ground, bluestone for quiet
     text, and brass as the one warm note. */
  --bg:        #f3f2ee;
  --bg-sunk:   #e7e6e0;
  --bg-card:   #fbfbf9;
  --ink:       #121b2a;
  --ink-mid:   #3f4958;
  --ink-dim:   #5b6778;
  --line:      #d6d6cf;
  --line-soft: #e3e2dc;
  --dark:      #0f1a2b;
  --on-dark:   #f3f2ee;
  --on-dark-dim: #a3abb8;
  /* --clay is the accent slot the templates reference: brass dark enough to
     pass 4.5:1 as text on the limestone ground. */
  --clay:      #83632f;
  --brass:     #c4a068;

  --font-display: 'Archivo', system-ui, -apple-system, 'Segoe UI', sans-serif;
  --font-body: 'Archivo', system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;

  --wrap: 1180px;
  --gutter: clamp(1.25rem, 4vw, 2.5rem);
  --radius: 6px;
  --radius-lg: 6px;

  /* One easing curve for everything that moves, so the site feels of a piece. */
  --ease: cubic-bezier(.22, .61, .36, 1);
  --shadow-sm: 0 1px 2px rgba(17, 28, 46, .05), 0 2px 8px rgba(17, 28, 46, .04);
  --shadow-md: 0 2px 4px rgba(17, 28, 46, .04), 0 12px 32px -8px rgba(17, 28, 46, .16);

  /* Section rhythm: one knob drives vertical pace across the whole site. */
  --section-y: clamp(4rem, 9vw, 7.5rem);
}

/* --- Reset -------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: 1rem;
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  font-synthesis-weight: none;
  overflow-wrap: break-word;
}

img, picture, svg { display: block; max-width: 100%; }
img { height: auto; background: var(--bg-sunk); }

/* <picture> is only a wrapper, but a percentage height on the inner <img>
   resolves against it — so it has to carry the container's box, not shrink
   to the image. Any element that crops with object-fit needs this. */
.hero__media > picture,
.card__media > picture,
.split__media > picture { display: block; width: 100%; height: 100%; }

/* A hairline inside the edge of every photo. Pure black at low alpha, never a
   tinted neutral — a tinted outline picks up the surface behind it and reads
   as grime along the image edge. Skipped on the hero, which is full-bleed. */
.card__media img,
.split__media img,
.mosaic img,
.quote-feature__media img,
.prose img,
.wrap > img,
.wrap > picture img {
  outline: 1px solid rgba(0, 0, 0, 0.1);
  outline-offset: -1px;
  border-radius: var(--radius);
}

h1, h2, h3, h4 {
  font-family: var(--font-display);
  font-weight: 600;
  line-height: 1.08;
  letter-spacing: -0.02em;
  margin: 0;
  text-wrap: balance;
}
p { margin: 0; text-wrap: pretty; }
ul, ol { margin: 0; padding: 0; }

a { color: inherit; }

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

/* Phone numbers read as one unit and must not reflow between pages. */
.tel { font-variant-numeric: tabular-nums; letter-spacing: 0.01em; white-space: nowrap; }

/* --- Layout primitives -------------------------------------------------- */
.wrap {
  width: 100%;
  max-width: var(--wrap);
  margin-inline: auto;
  padding-inline: var(--gutter);
}
.section { padding-block: var(--section-y); }
.section--sunk { background: var(--bg-sunk); }
.section--dark { background: var(--dark); color: var(--on-dark); }
.section--tight { padding-block: clamp(2.5rem, 5vw, 4rem); }

.eyebrow {
  font-size: 0.75rem;
  font-weight: 500;
  letter-spacing: 0.14em;
  text-transform: uppercase;
  color: var(--ink-dim);
  margin: 0 0 1.25rem;
}
.section--dark .eyebrow { color: var(--on-dark-dim); }

/* Rule-and-label eyebrow used on the closing CTA. */
.eyebrow--ruled { display: flex; align-items: center; gap: 0.9rem; }
.eyebrow--ruled::before {
  content: '';
  width: 3rem;
  height: 1px;
  background: currentColor;
  opacity: 0.5;
}

.h-display { font-size: clamp(2.25rem, 6.2vw, 4.4rem); }
.h-section  { font-size: clamp(1.85rem, 4.2vw, 3rem); }
.h-sub      { font-size: clamp(1.35rem, 2.6vw, 1.85rem); }

.lede {
  font-size: clamp(1.02rem, 1.5vw, 1.15rem);
  color: var(--ink-mid);
  max-width: 62ch;
}
.section--dark .lede { color: var(--on-dark-dim); }

.prose > * + * { margin-top: 1.15em; }
.prose p { color: var(--ink-mid); max-width: 68ch; }
.prose h2 { margin-top: 2.2em; }
.prose h3 { margin-top: 1.8em; font-size: 1.2rem; letter-spacing: -0.01em; }

/* --- Buttons ------------------------------------------------------------ */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 0.5rem;
  padding: 0.85rem 1.5rem;
  font-family: var(--font-body);
  font-size: 0.925rem;
  font-weight: 700;
  line-height: 1;
  text-decoration: none;
  border: 1px solid transparent;
  border-radius: var(--radius);
  cursor: pointer;
  transition: background-color .18s ease, color .18s ease, border-color .18s ease, scale .12s ease;
}
/* Tactile press. 0.96 is the floor — anything smaller reads as exaggerated. */
.btn:active { scale: 0.96; }
@media (prefers-reduced-motion: reduce) { .btn:active { scale: 1; } }

.btn--solid { background: var(--ink); color: var(--bg); }
.btn--solid:hover { background: #1f2d45; box-shadow: var(--shadow-md); translate: 0 -1px; }

.btn--ghost { border-color: currentColor; color: inherit; }
.btn--ghost:hover { background: var(--ink); color: var(--bg); border-color: var(--ink); }

.btn--on-photo { border-color: rgba(255,255,255,.65); color: #fff; backdrop-filter: blur(2px); }
.btn--on-photo:hover { background: #fff; color: var(--ink); border-color: #fff; }

/* Text link that reads as a destination, not a button. */
.link-arrow {
  position: relative;
  display: inline-flex;
  align-items: center;
  gap: 0.55rem;
  font-size: 0.78rem;
  font-weight: 500;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  text-decoration: none;
  padding-bottom: 0.35rem;
  border-bottom: 1px solid currentColor;
}
/* Extend the tap target to 40px with a pseudo-element rather than min-height —
   a taller box would centre the text and leave the underline floating below it. */
.link-arrow::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  top: 50%;
  height: 40px;
  transform: translateY(-50%);
}
.link-arrow svg { transition: transform .2s ease; flex: none; }
.link-arrow:hover svg { transform: translateX(4px); }

/* --- Header ------------------------------------------------------------- */
.masthead {
  position: sticky;
  top: 0;
  z-index: 50;
  background: color-mix(in srgb, var(--bg) 88%, transparent);
  backdrop-filter: saturate(1.4) blur(12px);
  border-bottom: 1px solid var(--line-soft);
}
.masthead__inner {
  display: flex;
  align-items: center;
  gap: 1.5rem;
  min-height: 68px;
}

.masthead__inner { padding-block: 0.7rem; }

.wordmark {
  display: flex;
  flex-direction: column;
  justify-content: center;
  text-decoration: none;
  line-height: 1;
  flex: none;
  margin-right: auto;
  min-height: 44px;
}
/* The logo is the client's own artwork, rendered white for the navy chrome. */
.lockup { display: block; height: auto; background: none; }
.lockup--header { width: 170px; }
@media (max-width: 520px) { .lockup--header { width: 136px; } }

.nav { display: flex; align-items: center; gap: 1.6rem; list-style: none; }
.nav a {
  display: block;
  /* Padding lifts the hit area to 40px tall; the negative margin keeps the
     bar visually the same height it was. */
  padding-block: 0.66rem;
  margin-block: -0.66rem;
  font-size: 0.925rem;
  text-decoration: none;
  color: var(--ink-mid);
  transition: color .15s ease;
}
.nav a:hover, .nav a[aria-current='page'] { color: var(--ink); }
.nav a[aria-current='page'] { font-weight: 500; }

.masthead__cta { display: flex; align-items: center; gap: 1.1rem; flex: none; }
.callout {
  display: flex;
  flex-direction: column;
  justify-content: center;
  text-align: right;
  text-decoration: none;
  line-height: 1.2;
  min-height: 42px;
}
.callout__label {
  display: block;
  font-size: 0.6rem;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-dim);
}
.callout__num { font-weight: 700; font-size: 0.95rem; }

/* Mobile disclosure nav — native <details>, so it needs no JavaScript. */
.mobile-nav { display: none; margin-left: auto; }
.mobile-nav > summary {
  list-style: none;
  cursor: pointer;
  /* 22px of bars + 11px padding each side = a 44px square target. */
  padding: 0.7rem;
  margin: -0.7rem;
  display: grid;
  align-content: center;
  justify-items: center;
  gap: 5px;
  min-width: 44px;
  min-height: 44px;
}
.mobile-nav > summary::-webkit-details-marker { display: none; }
.mobile-nav > summary span {
  display: block;
  width: 22px;
  height: 1.5px;
  background: var(--ink);
  transition: transform .2s ease, opacity .2s ease;
}
.mobile-nav[open] > summary span:nth-child(1) { transform: translateY(6.5px) rotate(45deg); }
.mobile-nav[open] > summary span:nth-child(2) { opacity: 0; }
.mobile-nav[open] > summary span:nth-child(3) { transform: translateY(-6.5px) rotate(-45deg); }

.mobile-nav__panel {
  position: absolute;
  left: 0;
  right: 0;
  top: 100%;
  background: var(--bg);
  border-bottom: 1px solid var(--line);
  padding: 0.5rem var(--gutter) 0;
  max-height: calc(100dvh - 68px);
  overflow-y: auto;
}
.mobile-nav__panel ul { list-style: none; }
/* :not(.btn) — this rule is for the nav links. Without the exclusion it also
   won against .btn (0,1,1 against 0,1,0) and turned both call-to-action
   buttons into bare blocks: display:block killed the centring, `0.7rem 0`
   wiped their horizontal padding, and they picked up a stray bottom hairline. */
.mobile-nav__panel a:not(.btn) {
  display: block;
  padding: 0.7rem 0;
  border-bottom: 1px solid var(--line-soft);
  text-decoration: none;
  font-size: 1.02rem;
}

/* The last link's rule and the sticky bar's top border would otherwise stack
   into a doubled hairline once the list is scrolled to the end. */
.mobile-nav__panel li:last-child a { border-bottom: 0; }

/* The panel is a long list — six pages plus ten services — so on a phone the
   two actions that matter were a scroll away at the bottom. Sticky pins them
   to the foot of the panel, visible the moment the menu opens, with the list
   scrolling underneath. */
.mobile-nav__cta {
  position: sticky;
  bottom: 0;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: 0.6rem;
  margin-top: 0.9rem;
  padding: 0.85rem 0 calc(0.85rem + env(safe-area-inset-bottom, 0px));
  background: var(--bg);
  border-top: 1px solid var(--line);
}
.mobile-nav__cta .btn {
  width: 100%;
  margin: 0;
  padding-inline: 0.75rem;   /* 1.5rem would overflow the phone number at 2-up */
  min-height: 46px;
}

/* Phone button beside the hamburger on small screens. The number was only
   inside the menu, one tap further from the call than it should be. */
.mcall { display: none; }

@media (max-width: 900px) {
  .nav, .masthead__cta { display: none; }
  .mobile-nav { display: block; margin-left: 1rem; }
  .mcall {
    display: inline-flex;
    align-items: center;
    gap: 0.4rem;
    margin-left: auto;
    min-height: 44px;
    padding: 0 0.95rem;
    border: 1.5px solid var(--brass);
    border-radius: 999px;
    color: var(--ink);
    font-weight: 600;
    font-size: 0.9rem;
    text-decoration: none;
  }
}

/* --- Hero --------------------------------------------------------------- */
.hero { position: relative; isolation: isolate; background: var(--dark); }
.hero__media { position: absolute; inset: 0; z-index: -2; }
.hero__media img { width: 100%; height: 100%; object-fit: cover; }
.hero::after {
  content: '';
  position: absolute;
  inset: 0;
  z-index: -1;
  /* Weighted to the left so the headline holds contrast through the text
     column, then falls away so the right third of the photograph still reads —
     the work is the reason people are on the page. */
  background:
    linear-gradient(100deg, rgba(9,16,28,.88) 0%, rgba(9,16,28,.74) 38%, rgba(9,16,28,.42) 66%, rgba(9,16,28,.10) 100%),
    linear-gradient(to top, rgba(9,16,28,.42), transparent 42%);
}
/* On narrow screens the text spans the full width, so a horizontal scrim has
   nowhere to fall off to — go vertical instead. */
@media (max-width: 760px) {
  .hero::after {
    background:
      linear-gradient(to top, rgba(9,16,28,.90) 12%, rgba(9,16,28,.66) 55%, rgba(9,16,28,.42) 100%);
  }
}
.hero__inner {
  padding-block: clamp(5.5rem, 15vw, 10.5rem);
  color: #fff;
  max-width: 46rem;
}
.hero .eyebrow { color: rgba(255,255,255,.72); }
.hero h1 { color: #fff; }
.hero__lede {
  margin-top: 1.5rem;
  font-size: clamp(1.02rem, 1.6vw, 1.18rem);
  color: rgba(255,255,255,.86);
  max-width: 40rem;
}
.hero__lede a { color: #fff; text-underline-offset: 3px; }
/* Reused as a plain action row on interior pages, so the light-on-dark
   inversion below must stay scoped to the photographic hero. */
.hero__actions { display: flex; flex-wrap: wrap; gap: 0.85rem; margin-top: 2.25rem; }
.hero .hero__actions .btn--solid { background: var(--bg); color: var(--ink); }
.hero .hero__actions .btn--solid:hover { background: #fff; }

/* --- Trust bar ---------------------------------------------------------- */
.trustbar { background: var(--bg); border-bottom: 1px solid var(--line-soft); }
.trustbar ul {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  /* Tightened from 1.5rem: five trust items overran the 1180px wrap by 12px,
     which wrapped the row and left the separator dangling at the line end. */
  gap: 0.6rem 1.15rem;
  padding-block: 1.1rem;
  font-size: 0.875rem;
  color: var(--ink-mid);
  text-align: center;
}
/* Once the row wraps, the trailing separator lands at the end of a line where
   it reads as a typo. Hide it on the last item of each visual row instead. */
@media (max-width: 900px) {
  .trustbar ul { gap: 0.35rem 1.1rem; }
  .trustbar li:not(:last-child)::after { margin-left: 1.1rem; }
}
/* The separator gets its own margin — a flex `gap` here would also push the
   <strong> away from the label it belongs to. */
.trustbar li:not(:last-child)::after { content: '·'; color: var(--line); margin-left: 1.15rem; }
.trustbar strong { font-weight: 500; color: var(--ink); }

/* --- Section headers ---------------------------------------------------- */
.section__head { margin-bottom: clamp(2.5rem, 5vw, 3.75rem); }
.section__head .lede { margin-top: 1.1rem; }

/* --- Card grids --------------------------------------------------------- */
.grid { display: grid; gap: clamp(1.5rem, 3vw, 2.5rem); }
.grid--3 { grid-template-columns: repeat(3, 1fr); }
.grid--2 { grid-template-columns: repeat(2, 1fr); }
@media (max-width: 900px) { .grid--3 { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 620px) { .grid--3, .grid--2 { grid-template-columns: 1fr; } }

.card { display: flex; flex-direction: column; text-decoration: none; }
.card__media {
  overflow: hidden;
  border-radius: var(--radius);
  aspect-ratio: 4 / 3;
  background: var(--bg-sunk);
}
.card__media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform .5s cubic-bezier(.2,.6,.2,1);
}
.card:hover .card__media img { transform: scale(1.035); }
.card h3 { margin-top: 1.15rem; font-size: 1.22rem; }
.card p { margin-top: 0.55rem; color: var(--ink-mid); font-size: 0.925rem; }
.card__more {
  margin-top: 0.85rem;
  font-size: 0.78rem;
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-dim);
  transition: color .15s ease;
}
.card:hover .card__more { color: var(--clay); }

/* --- Split (text + image) ----------------------------------------------- */
.split {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(2rem, 5vw, 4.5rem);
  align-items: center;
}
.split--reverse .split__media { order: -1; }
.split__media img { border-radius: var(--radius); width: 100%; }
@media (max-width: 820px) {
  .split { grid-template-columns: 1fr; }
  .split--reverse .split__media { order: 0; }
}

/* Small stat/feature list used beside body copy. */
.points { list-style: none; display: grid; gap: 1.35rem; margin-top: 2rem; }
.points li { padding-left: 1.5rem; position: relative; }
.points li::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0.6em;
  width: 7px;
  height: 7px;
  background: var(--clay);
  border-radius: 50%;
}
.points strong { display: block; font-weight: 700; font-size: 0.95rem; }
.points span { color: var(--ink-mid); font-size: 0.925rem; }

/* --- Portfolio mosaic --------------------------------------------------- */
/* Column-based masonry keeps the staggered rhythm of the reference layout
   without needing JS to measure anything. */
.mosaic { columns: 3; column-gap: clamp(1rem, 2vw, 1.5rem); }
.mosaic figure { break-inside: avoid; margin: 0 0 clamp(1rem, 2vw, 1.5rem); }
.mosaic img { width: 100%; border-radius: var(--radius); }
.mosaic figcaption {
  margin-top: 0.6rem;
  font-size: 0.8rem;
  color: var(--ink-dim);
}
@media (max-width: 900px) { .mosaic { columns: 2; } }
@media (max-width: 560px) { .mosaic { columns: 1; } }

/* --- Reviews ------------------------------------------------------------ */
/* Lead testimonial paired with a photo of the kind of work it describes. */
.quote-feature {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(2rem, 5vw, 4.5rem);
  align-items: center;
}
@media (max-width: 820px) { .quote-feature { grid-template-columns: 1fr; } }
.quote-feature__media { margin: 0; }
.quote-feature__media img { border-radius: var(--radius); width: 100%; }
.quote-feature__media figcaption {
  margin-top: 0.7rem;
  font-size: 0.8rem;
  color: var(--ink-dim);
}

.quote-lead blockquote { margin: 0; }
.quote-lead p {
  font-family: var(--font-display);
  font-weight: 600;
  font-size: clamp(1.6rem, 3.4vw, 2.6rem);
  line-height: 1.16;
  letter-spacing: -0.02em;
  max-width: 20ch;
}
.quote-lead cite {
  display: block;
  margin-top: 1.75rem;
  font-style: normal;
  font-size: 0.9rem;
}
.quote-lead cite span { display: block; color: var(--ink-dim); font-size: 0.825rem; }

.quote-grid { display: grid; grid-template-columns: repeat(2, 1fr); gap: clamp(1.5rem, 3vw, 2.5rem); margin-top: clamp(2.5rem, 5vw, 4rem); }
@media (max-width: 720px) { .quote-grid { grid-template-columns: 1fr; } }
.quote-card {
  border-top: 1px solid var(--line);
  padding-top: 1.5rem;
}
.quote-card blockquote { margin: 0; color: var(--ink-mid); font-size: 0.95rem; }
.quote-card cite {
  display: block;
  margin-top: 1.1rem;
  font-style: normal;
  font-weight: 500;
  font-size: 0.875rem;
}
.quote-card cite span { font-weight: 400; color: var(--ink-dim); }

.stars { color: var(--clay); letter-spacing: 0.12em; font-size: 0.8rem; }

/* Invitation to leave a review. */
.review-cta {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: clamp(1.75rem, 4vw, 3.5rem);
  align-items: center;
  background: var(--bg-sunk);
  border-radius: var(--radius);
  padding: clamp(2rem, 4vw, 3rem);
}
.review-cta .lede { max-width: 46ch; }
.review-cta__actions { display: grid; gap: 1rem; justify-items: start; }
@media (max-width: 760px) { .review-cta { grid-template-columns: 1fr; } }

/* Full review list on the reviews page. */
.review-list { list-style: none; display: grid; gap: 0; }
.review-list li { border-top: 1px solid var(--line); padding-block: clamp(1.75rem, 3.5vw, 2.5rem); }
.review-list li:last-child { border-bottom: 1px solid var(--line); }
.review__meta {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.5rem 1rem;
  margin-bottom: 0.9rem;
}
.review__name { font-weight: 700; font-size: 0.95rem; }
.review__detail { font-size: 0.8rem; color: var(--ink-dim); }
.review-list p { color: var(--ink-mid); max-width: 72ch; }

/* --- FAQ ---------------------------------------------------------------- */
.faq { border-top: 1px solid var(--line); }
.faq details { border-bottom: 1px solid var(--line); }
.faq summary {
  list-style: none;
  cursor: pointer;
  padding-block: 1.4rem;
  padding-right: 2.5rem;
  position: relative;
  font-family: var(--font-display);
  font-weight: 600;
  font-size: 1.12rem;
  letter-spacing: -0.01em;
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after {
  content: '';
  position: absolute;
  right: 0.35rem;
  top: 50%;
  width: 11px;
  height: 11px;
  margin-top: -7px;
  border-right: 1.5px solid var(--ink-dim);
  border-bottom: 1.5px solid var(--ink-dim);
  transform: rotate(45deg);
  transition: transform .2s ease;
}
.faq details[open] summary::after { transform: rotate(-135deg); margin-top: -3px; }
.faq details > div { padding-bottom: 1.6rem; color: var(--ink-mid); max-width: 72ch; }
.faq details > div > * + * { margin-top: 0.9em; }

/* --- Area chips --------------------------------------------------------- */
.chips { list-style: none; display: flex; flex-wrap: wrap; gap: 0.6rem; }
.chips a {
  display: flex;
  align-items: center;
  min-height: 40px;
  padding: 0.5rem 1.1rem;
  border: 1px solid var(--line);
  border-radius: 100px;
  font-size: 0.875rem;
  text-decoration: none;
  color: var(--ink-mid);
  transition: border-color .15s ease, color .15s ease, background-color .15s ease;
}
.chips a:hover { border-color: var(--ink); color: var(--ink); background: var(--bg-card); }

/* --- Service area map ---------------------------------------------------- */
/* Inline SVG built from Census county boundaries (see tools/map.py). Inlined
   rather than <img> so it inherits the palette and needs no extra request. */
/* The map deliberately paints outside its column. The generated path data
   covers the whole mid-Atlantic (roughly -788..1220 x, -382..1989 y) while the
   viewBox frames just 1000x1326 around the DC area, so overflow:visible lets
   the surrounding counties bleed out as a faint background wash. */
.areamap { width: 100%; height: auto; overflow: visible; }

/* That bleed has to sit UNDER the text, and getting there needs a negative
   z-index rather than a low positive one. .reveal animates opacity and
   transform, which makes this element a stacking context — and a stacking
   context at z-index auto/0 paints in the positioned phase, i.e. on top of the
   in-flow text beside it and in the sections below. Negative z-index moves it
   into the phase before in-flow content, so it lands above the page
   background and below everything else. No ancestor between here and <body>
   paints a background, so nothing swallows it. */
.areamap-col { position: relative; z-index: -1; }
.areamap__context path {
  fill: color-mix(in srgb, var(--bg-sunk) 55%, var(--bg));
  stroke: var(--line);
  stroke-width: 1.5;
  stroke-linejoin: round;
}
.areamap__served path {
  fill: color-mix(in srgb, var(--clay) 46%, var(--bg));
  stroke: var(--ink);
  stroke-width: 2.5;
  stroke-linejoin: round;
}
.areamap__pins circle { fill: var(--clay); stroke: var(--bg); stroke-width: 3; }
.areamap__pins text {
  font-family: var(--font-body);
  font-size: 23px;          /* viewBox units — scales with the map */
  font-weight: 500;
  fill: var(--ink);
  paint-order: stroke;       /* halo keeps labels legible over any fill */
  stroke: var(--bg);
  stroke-width: 4.5;
  stroke-linejoin: round;
}
@media (max-width: 700px) {
  .areamap__pins text { font-size: 31px; stroke-width: 6; }
  .areamap__pins circle { r: 8; }
}

.map-grid {
  display: grid;
  /* The map takes the narrower column to keep the two sides in proportion.
     It used to run tall because Fredericksburg sat a long way south of the
     Beltway; the served area is compact now, so the SVG is roughly landscape
     and this split just keeps it from crowding the text. */
  grid-template-columns: 0.8fr 1.2fr;
  gap: clamp(2rem, 5vw, 4rem);
  align-items: center;
}
@media (max-width: 860px) { .map-grid { grid-template-columns: 1fr; } }

.map-legend { list-style: none; display: flex; flex-wrap: wrap; gap: 0.6rem 1.5rem; margin-top: 1.75rem; font-size: 0.85rem; color: var(--ink-mid); }
.map-legend li { display: flex; align-items: center; gap: 0.55rem; }
.map-legend i {
  width: 14px;
  height: 14px;
  border-radius: 3px;
  flex: none;
  background: color-mix(in srgb, var(--clay) 22%, var(--bg));
  border: 1.5px solid var(--ink);
}
.map-legend i.is-pin { width: 11px; height: 11px; border-radius: 50%; background: var(--clay); border: 0; }

/* --- Recurring service-area band ---------------------------------------- */
/* Map plus every city as a link, repeated across the site. The map bleeds out
   of its column here exactly as it does on /service-areas/, which needs the
   same negative z-index — and that only reads over a transparent ancestor.
   So the band's tint is painted by a pseudo-element one layer lower rather
   than by --sunk on the section itself: body background, then the tint at -2,
   then the map at -1, then all the text. That ordering is also what lets the
   bleed spill past the top and bottom edges of the tinted band onto the page
   ground, instead of being cut off at them. */
.areaband-section { position: relative; }
.areaband-section::before {
  content: "";
  position: absolute;
  inset: 0;
  background: var(--bg-sunk);
  z-index: -2;
}

.areaband {
  display: grid;
  grid-template-columns: minmax(0, 0.5fr) 1fr;
  gap: clamp(1.75rem, 4vw, 3.5rem);
  align-items: center;
}
.areaband__map {
  position: relative;
  z-index: -1;
  max-width: 17rem;
  width: 100%;
}
.areaband__lede {
  margin: 0.7rem 0 1.5rem;
  max-width: 48ch;
  color: var(--ink-mid);
  font-size: 0.95rem;
}
@media (max-width: 860px) {
  .areaband { grid-template-columns: 1fr; }
  .areaband__map { max-width: 15rem; margin-inline: auto; }
}

/* The band's copy of the map: bleeding like the hero, but without pin labels.
   Label type is set in viewBox units, so it scales with the map geometry, not
   the screen — the 23-unit default was tuned so the DC-area labels clear each
   other, and raising it makes them collide at any render size. Leaving it
   would need a ~478px map to read at 11px, too tall for a band on eleven
   pages. The chips alongside name every location, so the map here shows the
   shape of the coverage and nothing else. Strokes are thickened because they
   thin out along with everything else. */
.areamap--quiet .areamap__pins text { display: none; }
.areamap--quiet .areamap__pins circle { r: 9; stroke-width: 5; }
.areamap--quiet .areamap__served path { stroke-width: 5; }
.areamap--quiet .areamap__context path { stroke-width: 3; }

/* --- Closing CTA -------------------------------------------------------- */
.cta-close {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 2.5rem;
  align-items: center;
}
.cta-close h2 { max-width: 16ch; }
.cta-close__call { margin-top: 1.75rem; font-size: 0.9rem; color: var(--on-dark-dim); }
.cta-close__call a {
  display: inline-flex;
  align-items: center;
  min-height: 40px;
  padding-inline: 0.15rem;
  color: var(--on-dark);
  font-size: 1.05rem;
  font-weight: 700;
  text-underline-offset: 4px;
}
@media (max-width: 820px) { .cta-close { grid-template-columns: 1fr; } }

/* --- Form --------------------------------------------------------------- */
.form { display: grid; gap: 1.35rem; }
.field { display: grid; gap: 0.45rem; }
.field label { font-size: 0.85rem; font-weight: 500; }
.field .hint { font-size: 0.78rem; color: var(--ink-dim); font-weight: 400; }
.req { color: var(--clay); text-decoration: none; font-weight: 700; }
.field input, .field select, .field textarea {
  font: inherit;
  font-size: 0.95rem;
  color: var(--ink);
  background: var(--bg-card);
  border: 1px solid var(--line);
  border-radius: var(--radius);
  padding: 0.75rem 0.85rem;
  width: 100%;
  transition: border-color .15s ease, box-shadow .15s ease;
}
.field textarea { resize: vertical; min-height: 7.5rem; }
.field input:focus, .field select:focus, .field textarea:focus {
  outline: none;
  border-color: var(--ink);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--clay) 18%, transparent);
}
.field-row { display: grid; grid-template-columns: 1fr 1fr; gap: 1.35rem; }
@media (max-width: 620px) { .field-row { grid-template-columns: 1fr; } }
.form__note { font-size: 0.82rem; color: var(--ink-dim); }
/* Honeypot: bots fill it, humans never see it. */
.hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

.contact-grid { display: grid; grid-template-columns: 1.15fr 0.85fr; gap: clamp(2.5rem, 6vw, 5rem); align-items: start; }
@media (max-width: 900px) { .contact-grid { grid-template-columns: 1fr; } }

.contact-block { display: grid; gap: 1.75rem; }
.contact-block h2 {
  font-family: var(--font-body);
  font-size: 0.68rem;
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-dim);
  margin-bottom: 0.5rem;
  letter-spacing: 0.16em;
}
.contact-block a { text-underline-offset: 3px; }

/* --- Breadcrumb --------------------------------------------------------- */
.crumbs {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem;
  font-size: 0.8rem;
  color: var(--ink-dim);
  padding-top: 1.75rem;
}
.crumbs a { text-decoration: none; }
.crumbs a:hover { text-decoration: underline; }
.crumbs li:not(:last-child)::after { content: ' /'; }

/* --- Page header (interior pages) --------------------------------------- */
.pagehead { padding-block: clamp(3rem, 7vw, 5.5rem) clamp(2.5rem, 5vw, 4rem); }
.pagehead .lede { margin-top: 1.35rem; }
/* The page header's bottom padding already separates it from what follows.
   Without this, a following .section adds its own top padding on top and the
   two stack into a gap twice the size intended. */
.pagehead + .section { padding-top: 0; }

/* --- Footer ------------------------------------------------------------- */
.footer { padding-block: clamp(3.5rem, 7vw, 5.5rem) 2.5rem; border-top: 1px solid var(--line); }
.footer__logo {
  display: inline-block;
  margin-bottom: 2.5rem;
  text-decoration: none;
}
.footer__logo .lockup { width: 220px; }

.footer__cols {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: clamp(2rem, 4vw, 3rem);
}
@media (max-width: 760px) { .footer__cols { grid-template-columns: 1fr 1fr; } }
@media (max-width: 480px) { .footer__cols { grid-template-columns: 1fr; } }
.footer h2 {
  font-family: var(--font-body);
  font-size: 0.68rem;
  font-weight: 500;
  letter-spacing: 0.16em;
  text-transform: uppercase;
  color: var(--ink-dim);
  margin-bottom: 1rem;
}
.footer ul { list-style: none; display: grid; gap: 0.15rem; }
.footer li { display: flex; }
.footer a {
  display: flex;
  align-items: center;
  min-height: 40px;
  text-decoration: none;
  color: var(--ink-mid);
  font-size: 0.925rem;
}
.footer a:hover { color: var(--ink); text-decoration: underline; text-underline-offset: 3px; }
.footer address { font-style: normal; font-size: 0.925rem; color: var(--ink-mid); display: grid; gap: 0.15rem; }
.footer address > span { padding-block: 0.5rem; }
.footer__base {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: 1rem;
  align-items: center;
  margin-top: clamp(2.5rem, 5vw, 4rem);
  padding-top: 1.75rem;
  border-top: 1px solid var(--line);
}
.footer__base p { font-size: 0.78rem; color: var(--ink-dim); }
.footer__brand { font-family: var(--font-display); font-weight: 600; font-size: 1.05rem; }

/* --- Skip link ---------------------------------------------------------- */
.skip {
  position: absolute;
  left: -9999px;
  z-index: 100;
  padding: 0.75rem 1.25rem;
  background: var(--ink);
  color: var(--bg);
  text-decoration: none;
}
.skip:focus { left: 1rem; top: 1rem; }

/* --- Scroll reveal ------------------------------------------------------ */
/* Progressive enhancement via scroll-driven animations. Browsers without
   `animation-timeline` support simply render the content in place — there is
   no JS fallback and nothing is hidden by default. */
@supports (animation-timeline: view()) {
  @media (prefers-reduced-motion: no-preference) {
    .reveal {
      animation: reveal-in linear both;
      animation-timeline: view();
      /* Finish while the element is still entering, so nothing that is already
         on screen sits half-faded waiting for a scroll that may never come. */
      animation-range: entry 8% entry 78%;
    }
    @keyframes reveal-in {
      from { opacity: 0; transform: translateY(1rem); }
      to   { opacity: 1; transform: none; }
    }
  }
}

/* --- Print -------------------------------------------------------------- */
@media print {
  .masthead, .hero__media, .cta-close, .mobile-nav { display: none; }
  body { background: #fff; }
}

/* --- projects ------------------------------------------------------------
   Project tiles reuse .card and .card__media, so they pick up the site's
   hairline photo outline, corner radius, and image-scale hover for free.
   Only the type scale differs: these tile four across, so the title steps
   down from the .card default and the city rides above it as an eyebrow.
   ------------------------------------------------------------------------ */
.pgrid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: clamp(1.25rem, 2.5vw, 2rem);
  margin-top: 2.25rem;
}
@media (max-width: 1000px) { .pgrid { grid-template-columns: repeat(3, 1fr); } }
@media (max-width: 760px)  { .pgrid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 460px)  { .pgrid { grid-template-columns: 1fr; } }

.pcard__meta {
  margin-top: 0.9rem;
  font-size: 0.7rem;
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-dim);
}
/* Tighter than the .card default — four across needs a smaller title. */
.pcard h3 { margin-top: 0.3rem; font-size: 1.02rem; line-height: 1.3; }
.pcard__mat { margin-top: 0.3rem; font-size: 0.85rem; color: var(--ink-mid); }
.pcard:hover h3 { color: var(--clay); }

/* --- Project page ------------------------------------------------------- */
.pfigure { margin: 0; }
.pfigure img {
  display: block;
  width: 100%;
  height: auto;
  border-radius: var(--radius);
  background: var(--bg-sunk);
  outline: 1px solid rgba(0, 0, 0, 0.1);
  outline-offset: -1px;
}
.pfigure figcaption {
  margin-top: 0.8rem;
  font-size: 0.85rem;
  color: var(--ink-dim);
}

.pspec {
  display: flex;
  flex-wrap: wrap;
  gap: 0.5rem 2.5rem;
  margin: 0 0 2rem;
  padding-bottom: 1.5rem;
  border-bottom: 1px solid var(--line-soft);
}
.pspec > div { display: flex; flex-direction: column; gap: 0.15rem; }
.pspec dt {
  font-size: 0.7rem;
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-dim);
}
.pspec dd { margin: 0; font-size: 1rem; }

/* Scope list on a project page. Sits inside .prose, so the heading and list
   reset the .prose defaults deliberately — it is a label above a spec list,
   not a section heading in the body copy. */
.pscope { margin: 0 0 1.75rem; }
.prose .pscope h2 {
  margin-top: 0;
  margin-bottom: 0.75rem;
  font-size: 0.7rem;
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-dim);
}
.pscope ul { list-style: none; padding: 0; margin: 0; display: grid; gap: 0.5rem; }
.pscope li {
  position: relative;
  padding-left: 1.1rem;
  font-size: 0.95rem;
  color: var(--ink-mid);
}
.pscope li::before {
  content: '';
  position: absolute;
  left: 0;
  top: 0.62em;
  width: 0.34rem;
  height: 0.34rem;
  border-radius: 50%;
  background: var(--clay);
}

/* --- Before / after --------------------------------------------------------
   Two figures side by side, each labelled. An unlabelled pair gets read in
   whichever order the viewer guesses, which is a coin toss. Stacks below
   720px, where side-by-side leaves both images too small to show anything. */
.ba {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(1rem, 2.5vw, 1.75rem);
}
@media (max-width: 720px) { .ba { grid-template-columns: 1fr; } }
.ba__half { position: relative; }
.ba__tag {
  position: absolute;
  top: 0.75rem;
  left: 0.75rem;
  z-index: 1;
  margin: 0;
  padding: 0.28rem 0.65rem;
  border-radius: 999px;
  background: var(--dark);
  color: var(--on-dark);
  font-size: 0.66rem;
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
}
.ba__tag--after { background: var(--clay); }

/* --- Service tree ----------------------------------------------------------
   A hub service card with its material pages listed beneath it. The chips are
   a sibling of the card rather than inside it: anchors cannot nest, and each
   material page needs to be its own link and its own tab stop. */
.svc-cell { display: flex; flex-direction: column; }
.svc-cell > .card { flex: 1 1 auto; }
.svc-cell__kids { margin-top: 0.9rem; gap: 0.4rem; }
.svc-cell__kids a { font-size: 0.76rem; padding: 0.3rem 0.7rem; }

/* The row a material page carries, so someone who landed here from search can
   reach the sibling materials and the overview without going back to /services/. */
.svc-parent {
  display: flex;
  flex-wrap: wrap;
  align-items: baseline;
  gap: 0.45rem 1.1rem;
  margin-bottom: var(--section-y);
  padding-bottom: 1.15rem;
  border-bottom: 1px solid var(--line-soft);
  font-size: 0.875rem;
}
.svc-parent > span {
  font-size: 0.7rem;
  font-weight: 500;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--ink-dim);
}

/* --- Service process steps ------------------------------------------------
   Numbered because the order is the point: each stage depends on the one
   before it, and the sequence is what the copy is arguing for. */
.process {
  list-style: none;
  margin: 2.5rem 0 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 2rem 3rem;
  counter-reset: none;
}
.process li {
  display: flex;
  gap: 1.1rem;
  align-items: flex-start;
}
.process__n {
  flex: none;
  width: 2.1rem;
  height: 2.1rem;
  border-radius: 50%;
  display: grid;
  place-items: center;
  background: var(--dark);
  color: var(--on-dark);
  font-family: var(--font-display);
  font-size: 0.95rem;
  /* Optical: the numeral's own bearing sits it a hair low in the circle. */
  line-height: 1;
  padding-bottom: 0.05em;
}
.process h3 { font-size: 1.05rem; margin-bottom: 0.4rem; }
.process p { color: var(--ink-mid); font-size: 0.925rem; margin: 0; }

@media (max-width: 760px) {
  .process { grid-template-columns: 1fr; gap: 1.75rem; }
}

/* --- Single review pulled onto a service page ---------------------------- */
.pullquote {
  max-width: 60ch;
  margin: 0 auto;
  padding: 2.5rem 2.75rem;
  background: var(--bg-card);
  border: 1px solid var(--line-soft);
  border-radius: var(--radius-lg);
  text-align: center;
}
.pullquote blockquote { margin: 1rem 0 0; }
.pullquote blockquote p {
  font-family: var(--font-display);
  font-size: 1.15rem;
  line-height: 1.55;
  color: var(--ink);
  text-wrap: pretty;
}
.pullquote figcaption {
  margin-top: 1.25rem;
  font-size: 0.875rem;
  font-weight: 500;
}
.pullquote figcaption span {
  display: block;
  font-weight: 400;
  color: var(--ink-dim);
  font-size: 0.8rem;
  margin-top: 0.2rem;
}

@media (max-width: 620px) {
  .pullquote { padding: 2rem 1.5rem; }
  .pullquote blockquote p { font-size: 1.05rem; }
}

/* --- Warranty band on service pages --------------------------------------
   Dark so it reads as a distinct claim rather than as more page copy, and
   placed directly under the page head so it lands above the fold. */
.wband { background: var(--dark); color: var(--on-dark); margin-bottom: var(--section-y); }
/* Where the band is followed by a padded section rather than a bare .wrap, the
   section already brings a full section's worth of top padding — the band's own
   margin on top of that stacks to roughly 180px of empty ground. Service pages
   still need the full margin, because what follows them there is an unpadded
   feature image. */
.wband:has(+ .section) { margin-bottom: clamp(0.75rem, 1.5vw, 1.5rem); }
.wband__inner {
  display: grid;
  grid-template-columns: auto 1fr auto;
  align-items: center;
  gap: 1.5rem 3rem;
  padding-block: 1.6rem;
}
.wband__head {
  font-family: var(--font-display);
  font-size: 1.2rem;
  line-height: 1.2;
  /* Tabular figures keep the leading numeral aligned with the list below. */
  font-variant-numeric: tabular-nums;
}
.wband__sub { color: var(--on-dark-dim); font-size: 0.8rem; margin-top: 0.25rem; }
.wband__list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: 0.4rem 2rem;
  border-left: 1px solid rgba(255, 255, 255, 0.16);
  padding-left: 3rem;
}
.wband__list li { font-size: 0.85rem; color: var(--on-dark-dim); }
.wband__list strong {
  color: var(--on-dark);
  font-weight: 500;
  font-variant-numeric: tabular-nums;
}
.wband__link {
  color: var(--on-dark);
  font-size: 0.85rem;
  font-weight: 500;
  text-decoration: none;
  border-bottom: 1px solid rgba(255, 255, 255, 0.35);
  padding-bottom: 0.1rem;
  white-space: nowrap;
}
.wband__link:hover { border-bottom-color: var(--on-dark); }

@media (max-width: 1080px) {
  .wband__inner { grid-template-columns: 1fr; gap: 1.1rem; }
  .wband__list { border-left: 0; padding-left: 0; }
}

/* --- Warranty page term table -------------------------------------------- */
.wtable { border-top: 1px solid var(--line); }
.wtable__row {
  display: grid;
  grid-template-columns: 7rem 1fr;
  gap: 2rem;
  align-items: baseline;
  padding-block: 1.6rem;
  border-bottom: 1px solid var(--line);
}
.wtable__term {
  display: flex;
  align-items: baseline;
  gap: 0.4rem;
  font-family: var(--font-display);
}
.wtable__term strong { font-size: 2rem; font-weight: 600; font-variant-numeric: tabular-nums; }
.wtable__term span { font-size: 0.8rem; color: var(--ink-dim); }
.wtable__row h3 { font-size: 1.1rem; }
.wtable__svc { margin-top: 0.4rem; font-size: 0.875rem; color: var(--ink-dim); }

@media (max-width: 620px) {
  .wtable__row { grid-template-columns: 1fr; gap: 0.5rem; }
}

/* --- Estimate form: in-place confirmation --------------------------------
   Replaces the form after a successful background post. `hidden` does the
   showing and hiding, so without JavaScript the form stays and this never
   appears. */
.formdone {
  border: 1px solid var(--line);
  background: var(--bg-card);
  border-radius: 4px;
  padding: 3rem 2.5rem;
  text-align: center;
  outline: none;
}
.formdone__mark {
  width: 2.75rem;
  height: 2.75rem;
  margin: 0 auto 1.25rem;
  border-radius: 50%;
  background: var(--dark);
  color: var(--on-dark);
  display: grid;
  place-items: center;
  font-size: 1.35rem;
  /* The glyph sits optically high in its em box; nudge it back to centre. */
  line-height: 1;
  padding-top: 0.1em;
}
.formdone__head {
  font-family: var(--font-display);
  font-size: 1.6rem;
  line-height: 1.2;
}
.formdone__sub {
  margin-top: 0.75rem;
  color: var(--ink-mid);
  font-size: 0.925rem;
  max-width: 46ch;
  margin-inline: auto;
  text-wrap: pretty;
}
.form__error {
  color: #9c2f2f;
  font-size: 0.875rem;
  background: #fbf0ee;
  border: 1px solid #eccfc9;
  border-radius: 3px;
  padding: 0.7rem 0.9rem;
}

/* ==========================================================================
   M&C theme
   One light theme, whatever the visitor's system setting: limestone ground,
   navy and brass as accents. The masthead, footer and closing card are
   navy chrome; the page itself never flips theme mid-scroll. The one bold move is the hero: the photograph cut
   to the gable of a house, under the same brass roofline as the logo.
   ========================================================================== */
:root {
  color-scheme: light;
  --btn:       #121b2a;
  --btn-ink:   #f3f2ee;
  --btn-hover: #24314a;
  --frame:     #0f1a2b;
  --frame-deep:#0b1422;
}
/* Chrome regions: navy in either mode, so their tokens are fixed. */
.masthead, .footer, .cta-close {
  --bg:        var(--frame);
  --bg-card:   #152238;
  --bg-sunk:   var(--frame-deep);
  --ink:       #f3f2ee;
  --ink-mid:   #c0c7d2;
  --ink-dim:   #939cab;
  --line:      rgba(255, 255, 255, .14);
  --line-soft: rgba(255, 255, 255, .08);
  --clay:      var(--brass);
  --btn:       var(--brass);
  --btn-ink:   #0f1a2b;
  --btn-hover: #d5b47e;
  color: var(--ink);
}

::selection { background: color-mix(in srgb, var(--brass) 40%, transparent); color: inherit; }

/* --- Type ------------------------------------------------------------------
   Perfect-fourth scale (1.333) from a 17px body. Headlines run wide and heavy;
   body copy stays at normal width with generous leading. */
body { font-size: 1.0625rem; line-height: 1.62; font-stretch: 100%; }
h1, h2, h3, h4 { font-stretch: 112%; font-weight: 700; letter-spacing: -0.02em; line-height: 1.06; }
.h-display { font-stretch: 118%; font-weight: 800; letter-spacing: -0.03em; line-height: 1.02; }
.h-section { font-size: clamp(1.9rem, 4vw, 2.85rem); }
.h-sub     { font-size: clamp(1.4rem, 2.5vw, 1.78rem); }
.card h3, .pcard h3, .process h3, .wtable__row h3 { font-stretch: 108%; letter-spacing: -0.01em; }
.lede { font-size: clamp(1.06rem, 1.5vw, 1.2rem); line-height: 1.6; max-width: 60ch; }
.prose p { max-width: 65ch; }

/* Labels are sentence case at reading size, never tracked-out capitals. */
.eyebrow, .card__more, .link-arrow, .footer h2, .contact-block h2, .callout__label,
.pcard__meta, .pspec dt, .prose .pscope h2, .svc-parent > span, .ba__tag {
  text-transform: none;
  letter-spacing: 0;
}
.eyebrow { font-size: 0.95rem; font-weight: 600; color: var(--clay); margin-bottom: 1rem; }
.footer h2, .contact-block h2 { font-family: var(--font-display); font-size: 0.9rem; font-weight: 700; color: var(--ink); }
.callout__label { font-size: 0.72rem; color: var(--ink-dim); }
.pcard__meta, .pspec dt { font-size: 0.82rem; font-weight: 600; }

/* --- Buttons: one 6px radius, a solid weight, a physical press ------------ */
.btn {
  border-radius: var(--radius);
  padding: 1rem 1.5rem;
  font-size: 0.95rem;
  font-weight: 700;
  font-stretch: 108%;
  letter-spacing: 0;
  white-space: nowrap;
  transition: background-color .2s var(--ease), color .2s var(--ease), border-color .2s var(--ease), translate .12s ease;
}
.btn:active { scale: 1; translate: 0 1px; }
.btn--solid { background: var(--btn); color: var(--btn-ink); }
.btn--solid:hover { background: var(--btn-hover); }
.hero .hero__actions .btn--solid { background: var(--btn); color: var(--btn-ink); }
.hero .hero__actions .btn--solid:hover { background: var(--btn-hover); }
.btn--ghost { border-color: var(--line); color: var(--ink); }
.btn--ghost:hover { background: var(--ink); color: var(--bg); border-color: var(--ink); }
.btn--on-photo { border-color: var(--line); color: var(--ink); background: none; backdrop-filter: none; }
.btn--on-photo:hover { background: var(--ink); color: var(--bg); border-color: var(--ink); }
.mobile-nav__cta .btn { white-space: normal; }

.link-arrow { font-size: 0.95rem; font-weight: 600; border-bottom: 2px solid var(--brass); padding-bottom: 0.2rem; }
/* Links say where they go; a trailing arrow adds nothing the underline does not. */
.link-arrow svg { display: none; }

/* --- Masthead ------------------------------------------------------------- */
.masthead { background: var(--frame); backdrop-filter: none; border-bottom: 1px solid rgba(255,255,255,.07); }
.masthead__inner { min-height: 72px; }
.nav a { position: relative; color: var(--ink-mid); font-size: 0.95rem; }
.nav a:hover, .nav a[aria-current='page'] { color: var(--ink); }
.nav a::after {
  content: '';
  position: absolute;
  left: 0; right: 0;
  bottom: 0.3rem;
  height: 2px;
  background: var(--brass);
  scale: 0 1;
  transform-origin: left;
  transition: scale .3s var(--ease);
}
.nav a:hover::after, .nav a[aria-current='page']::after { scale: 1 1; }
.mobile-nav__panel, .mobile-nav__cta { background: var(--frame); }

/* --- Hero: one photograph across the full width, copy on a limestone scrim
   The scrim is weighted left so the copy column reads as the page ground and
   the right side of the photograph shows through. */
.hero--photo { background: var(--bg); }
.hero--photo::after {
  background:
    linear-gradient(100deg, rgba(243,242,238,.97) 0%, rgba(243,242,238,.92) 38%, rgba(243,242,238,.55) 62%, rgba(243,242,238,0) 88%);
}
.hero--photo .hero__inner { padding-block: clamp(5rem, 12vw, 8.5rem); max-width: var(--wrap); color: var(--ink); }
.hero--photo .eyebrow { color: var(--clay); }
.hero--photo h1 { color: var(--ink); font-size: clamp(2.2rem, 4.2vw, 3.5rem); font-stretch: 112%; max-width: 17ch; text-wrap: balance; }
.hero--photo .hero__lede { color: var(--ink-mid); margin-top: 1.5rem; max-width: 52ch; }
.hero--photo .hero__lede a { color: var(--ink); }
.hero--photo .hero__actions { margin-top: 2.25rem; }
.hero--photo .hero__actions .btn--solid { background: var(--btn); color: var(--btn-ink); }
.hero--photo .btn--ghost { border-color: var(--ink); color: var(--ink); background: rgba(243,242,238,.6); }
.hero--photo + .trustbar ul { border-top: 0; }
/* A brass rule under the hero ties it to the navy masthead above. */
.hero--photo { border-bottom: 3px solid var(--brass); }
/* Wide screens: the photograph runs the full width, darkened on the left
   where the copy sits in white, as on phones. It is portrait, so it is framed
   on the wall, planting, and awning band. */
@media (min-width: 761px) {
  .hero--photo::after {
    background: linear-gradient(90deg, rgba(9,16,28,.82) 0%, rgba(9,16,28,.62) 40%, rgba(9,16,28,.15) 75%, rgba(9,16,28,0) 100%);
  }
  .hero--photo .hero__media img { object-position: 50% 55%; }
  .hero--photo .eyebrow { color: rgba(255,255,255,.85); }
  .hero--photo h1 { color: #fff; }
  .hero--photo .hero__lede { color: rgba(255,255,255,.88); }
  .hero--photo .hero__lede a { color: #fff; }
  .hero--photo .hero__actions .btn--solid { background: var(--brass); color: var(--ink); }
  .hero--photo .btn--ghost { border-color: rgba(255,255,255,.8); color: #fff; background: transparent; }
}

/* Phones: the photograph runs clear at the top and darkens toward the
   bottom, where the copy sits in white. Overrides the limestone scrim above. */
@media (max-width: 760px) {
  .hero--photo::after {
    background: linear-gradient(to bottom, rgba(9,16,28,0) 0%, rgba(9,16,28,.08) 25%, rgba(9,16,28,.55) 50%, rgba(9,16,28,.82) 100%);
  }
  /* Sized so both actions land on the first screen even on a short phone. */
  .hero--photo .hero__inner { padding-block: 4.5rem 1.75rem; color: #fff; }
  .hero--photo h1 { font-size: clamp(1.9rem, 8.4vw, 2.4rem); }
  .hero--photo .hero__lede { margin-top: 1rem; font-size: 0.98rem; }
  .hero--photo .hero__actions { margin-top: 1.5rem; flex-wrap: nowrap; gap: 0.6rem; }
  .hero--photo .hero__actions .btn { flex: 1 1 0; padding-inline: 0.75rem; white-space: nowrap; }
  .hero--photo .eyebrow { color: rgba(255,255,255,.9); }
  .hero--photo h1 { color: #fff; }
  .hero--photo .hero__lede { color: rgba(255,255,255,.88); }
  .hero--photo .hero__lede a { color: #fff; }
  .hero--photo .hero__actions .btn--solid { background: var(--ink); color: #fff; }
  .hero--photo .btn--ghost { border-color: rgba(255,255,255,.75); color: #fff; background: transparent; }
}

/* Scroll reveals are retired: content below the hero is simply there. */
.reveal { animation: none !important; }

/* --- Trust bar: a ruled ledger directly under the hero -------------------- */
.trustbar { background: none; border: 0; }
.trustbar ul {
  border-block: 1px solid var(--line);
  padding: 1.1rem 0;
  gap: 0.75rem 0;
}
.trustbar li { padding-inline: clamp(0.6rem, 1.2vw, 1.1rem); white-space: nowrap; font-size: 0.9rem; }
@media (min-width: 1101px) { .trustbar ul { flex-wrap: nowrap; justify-content: space-between; } .trustbar li:first-child { padding-left: 0; } .trustbar li:last-child { padding-right: 0; } }
.trustbar li:not(:last-child)::after { content: none; }
.trustbar li:not(:last-child) { border-right: 1px solid var(--line); }
.trustbar strong { font-weight: 700; color: var(--ink); }
.trustbar a { text-decoration: none; }
@media (max-width: 1100px) {
  .trustbar li { white-space: normal; padding-inline: 0; }
  .trustbar li:not(:last-child) { border-right: 0; }
  .trustbar ul { display: grid; grid-template-columns: 1fr 1fr; text-align: left; }
}
@media (max-width: 340px) { .trustbar ul { grid-template-columns: 1fr; } }

/* --- Interior page head ----------------------------------------------------
   Same ground as the page, separated from the body by a rule, not by a
   theme flip. */
.crumbs { color: var(--ink-dim); padding-top: 1.5rem; font-size: 0.85rem; }
.crumbs a:hover { color: var(--ink); }
.pagehead { padding-block: clamp(2.5rem, 6vw, 4.5rem) clamp(2.5rem, 5vw, 4rem); border-bottom: 1px solid var(--line); }
.pagehead .lede { color: var(--ink-mid); }
.pagehead + .section { padding-top: clamp(3rem, 6vw, 5rem); }
.pagehead + .section--tight { padding-top: clamp(2.5rem, 5vw, 3.5rem); }
.pagehead:has(+ .wband) { border-bottom: 0; }

/* --- Service grid: an uneven bond rather than three equal columns -------- */
.grid--bento { grid-template-columns: repeat(4, 1fr); gap: clamp(1.5rem, 2.6vw, 2.25rem) clamp(1.25rem, 2vw, 1.75rem); }
/* Twelve services in a four-column bond: two wide tiles per pair of rows,
   staggered so no two wide tiles stack. 12 cards + 4 extra cells = 16. */
.grid--bento > .card:is(:nth-child(1), :nth-child(6), :nth-child(7), :nth-child(12)) { grid-column: span 2; }
.grid--bento > .card:is(:nth-child(1), :nth-child(6), :nth-child(7), :nth-child(12)) .card__media { aspect-ratio: 16 / 9.4; }
.grid--bento > .card:is(:nth-child(1), :nth-child(6), :nth-child(7), :nth-child(12)) h3 { font-size: 1.5rem; }
@media (max-width: 1000px) {
  .grid--bento { grid-template-columns: repeat(2, 1fr); }
  .grid--bento > .card:nth-child(n) { grid-column: auto; }
  .grid--bento > .card:nth-child(n) .card__media { aspect-ratio: 4 / 3; }
}
@media (max-width: 620px) { .grid--bento { grid-template-columns: 1fr; } }

/* --- Cards: photographs, not boxes --------------------------------------- */
.card__media { border-radius: var(--radius); }
.card__media img { transition: transform .8s var(--ease); }
.card:hover .card__media img { transform: scale(1.03); }
.card h3 { margin-top: 1.1rem; font-size: 1.2rem; }
.card:hover h3 { text-decoration: underline; text-decoration-color: var(--brass); text-decoration-thickness: 2px; text-underline-offset: 5px; }
.card__more { font-size: 0.9rem; font-weight: 600; color: var(--clay); }
.card:hover .card__more { color: var(--clay); }
@media (prefers-reduced-motion: reduce) { .card:hover .card__media img { transform: none; } }

.split__media img, .quote-feature__media img, .mosaic img, .pfigure img, .pcard img { border-radius: var(--radius); }
.points li::before { background: var(--brass); border-radius: 0; width: 8px; height: 2px; top: 0.8em; }
.process__n { background: var(--brass); color: #0f1a2b; font-weight: 800; font-stretch: 110%; border-radius: var(--radius); }
.stars { color: var(--brass); }

/* --- Reviews: one quote given the full width, two short ones below ------- */
.quote-feature--solo { grid-template-columns: 1fr; }
.quote-feature--solo .quote-lead blockquote p { max-width: 34ch; font-size: clamp(1.55rem, 3vw, 2.3rem); font-stretch: 108%; line-height: 1.18; }
.quote-card { border-top: 2px solid var(--brass); padding-top: 1.5rem; }
/* Landing-page quotes are snippets: three lines, full text on /reviews/. */
.quote-card blockquote p, .pullquote blockquote p {
  display: -webkit-box;
  -webkit-box-orient: vertical;
  -webkit-line-clamp: 3;
  overflow: hidden;
}
.quote-card cite, .quote-lead cite, .pullquote figcaption { display: grid; gap: 0.1rem; font-size: 0.875rem; }
.quote-card cite strong, .quote-lead cite strong { font-weight: 700; color: var(--ink); }
.quote-card cite span, .quote-lead cite span, .pullquote figcaption span { display: block; color: var(--ink-dim); font-size: 0.82rem; margin: 0; }
.review__detail span { display: block; }

.review-cta { border-radius: var(--radius); background: var(--bg-card); border: 1px solid var(--line); }
.pullquote { border-radius: var(--radius); border-top: 2px solid var(--brass); background: var(--bg-card); }
.chips a { border-radius: var(--radius); }
.formdone, .form__error { border-radius: var(--radius); }
.field input, .field select, .field textarea { border-radius: var(--radius); padding: 0.85rem 1rem; }
.field input:focus, .field select:focus, .field textarea:focus { border-color: var(--clay); box-shadow: 0 0 0 3px color-mix(in srgb, var(--brass) 25%, transparent); }

/* Warranty band under a page head: a strip with a brass top edge. */
.wband {
  --on-dark: var(--ink);
  --on-dark-dim: var(--ink-mid);
  background: var(--bg-card);
  border-bottom: 1px solid var(--line);
  box-shadow: inset 0 3px 0 var(--brass);
}
.wband__head { font-stretch: 110%; font-weight: 700; }
.wband__list { border-left-color: var(--line); }
.wband__link { border-bottom-color: var(--brass); }

/* No section inverts the page theme. */
.section--dark { background: var(--bg-sunk); color: var(--ink); }
.section--dark .eyebrow { color: var(--clay); }
.section--dark .lede { color: var(--ink-mid); }

/* --- Closing call to action: an inset navy card (chrome, elevated) ------- */
.cta-section { padding-block: 0 var(--section-y); }
.cta-close {
  background: var(--frame);
  border-radius: var(--radius);
  padding: clamp(2.25rem, 6vw, 4.5rem);
}
.cta-close__call { color: var(--ink-mid); }
.cta-close__call a { color: var(--ink); }

/* --- Footer --------------------------------------------------------------- */
.footer { background: var(--frame-deep); border-top: 0; }
.footer a:hover { color: var(--brass); text-decoration: none; }
.footer__base p { color: var(--ink-dim); }
.footer__brand { font-stretch: 112%; }

/* --- Stillness -------------------------------------------------------------
   Nothing on the page moves on its own. Hover and press states change colour
   only: no zooming photographs, no sliding underlines, no nudged buttons. */
.card__media img, .card:hover .card__media img { transition: none; transform: none; }
.nav a::after { transition: none; }
.btn:active { translate: none; scale: 1; }

/* --- Tap targets ---------------------------------------------------------
   Standalone small links (breadcrumbs, "see more" links, footer, review
   links) get an invisible 44px-tall hit area without changing their layout.
   Links inside running text are exempt, as WCAG 2.5.8 allows. */
.crumbs a, .link-arrow, .wband__link, a.hit { position: relative; }
.crumbs a::before, .link-arrow::before, .wband__link::before, a.hit::before {
  content: '';
  position: absolute;
  left: -4px;
  right: -4px;
  top: 50%;
  height: 44px;
  transform: translateY(-50%);
}
.footer a { min-height: 44px; }

.estimate-call {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 0.75rem 1rem;
  margin-top: 1.5rem;
  color: var(--ink-mid);
}
.estimate-call .btn { display: inline-flex; align-items: center; gap: 0.5rem; }

/* Urgent-repair box at the top of a service page (chimney repair). */
.urgent {
  margin-top: 1.75rem;
  max-width: 62ch;
  padding: 1.25rem 1.4rem;
  border-left: 3px solid var(--brass);
  background: color-mix(in srgb, var(--brass) 10%, transparent);
  display: grid;
  gap: 0.65rem;
  justify-items: start;
}
.urgent__head { font-weight: 700; font-size: 1.1rem; color: var(--ink); }
.urgent p { color: var(--ink-mid); }
.urgent__creds { font-size: 0.875rem; font-weight: 600; }
.urgent .btn { display: inline-flex; align-items: center; gap: 0.5rem; }

/* Between the mobile breakpoint and full desktop the masthead is one item
   too wide; the phone number drops out of it (the button and the mobile
   nav still carry it). */
@media (min-width: 901px) and (max-width: 1100px) {
  .masthead__cta .callout { display: none; }
}
