/* =============================================================
   Pinnacle Housing Solutions - Design System (css/main.css)
   Foundation stylesheet. All pages load this file.
   Pages in /services/ load it as ../css/main.css
   Page-specific styles belong in css/pages/<page>.css
   ============================================================= */

/* ---------- Font ---------- */
@font-face {
  font-family: 'Outfit';
  src: url('../assets/fonts/outfit-latin.woff2') format('woff2');
  font-weight: 100 900;
  font-style: normal;
  font-display: swap;
}
@font-face {
  font-family: 'Cormorant Garamond';
  src: url('../assets/fonts/cormorant-garamond-latin.woff2') format('woff2');
  font-weight: 500 700;
  font-style: normal;
  font-display: swap;
}

/* ---------- Tokens ---------- */
:root {
  --navy-950: #081E31;
  --navy-800: #0D3355;
  --navy-600: #0C4F83;
  --navy-100: #E9F0F6;
  --ink: #16222E;
  --muted: #5A6875;
  --gold: #C2A14D;
  --gold-600: #A98A3C;
  --gold-700: #7A6329; /* darkest gold step: small gold text/icons on light backgrounds (>=4.5:1 on --paper and --stone) */
  --paper: #FAFAF8;
  --surface: #FFFFFF;
  --stone: #F2F0EA;
  --line: #E5E3DC;
  --dark-text: #F4F6F8;
  --dark-muted: #AAB8C4;
  --error: #A4342A; /* semantic form-error only; never decorative */
  --radius-card: 14px;
  --radius-input: 10px;
  --shadow-card: 0 20px 50px -24px rgb(8 30 49 / .25);
  --ease-out: cubic-bezier(.16, 1, .3, 1);
  --header-h: 72px;
  --font-stack: 'Outfit', -apple-system, 'Segoe UI', sans-serif;
  --font-display: 'Cormorant Garamond', Georgia, 'Times New Roman', serif;
}

/* ---------- Reset ---------- */
*, *::before, *::after { box-sizing: border-box; }
* { margin: 0; }
html { scroll-behavior: smooth; -webkit-text-size-adjust: 100%; }
body {
  font-family: var(--font-stack);
  font-size: 1.0625rem;
  line-height: 1.65;
  color: var(--ink);
  background: var(--paper);
  -webkit-font-smoothing: antialiased;
}
img, svg, video { display: block; max-width: 100%; height: auto; }
input, button, textarea, select { font: inherit; color: inherit; }
button { cursor: pointer; background: none; border: none; padding: 0; }
ul[class], ol[class] { list-style: none; padding: 0; }
a { color: var(--navy-600); text-decoration: none; }
a:hover { text-decoration: underline; text-underline-offset: 3px; }

:focus-visible {
  outline: 2px solid var(--navy-600);
  outline-offset: 2px;
  border-radius: 4px;
}

/* ---------- Typography ---------- */
h1, h2, h3 { font-weight: 600; color: var(--ink); text-wrap: balance; }
h1, .h1, h2, .h2 {
  font-family: var(--font-display);
  font-style: normal;
  letter-spacing: normal;
}
h1, .h1 {
  font-size: clamp(2.75rem, 5.5vw, 4.5rem);
  font-weight: 560;
  line-height: 1.08;
}
h2, .h2 {
  font-size: clamp(2.05rem, 3.6vw, 2.95rem);
  font-weight: 580;
  line-height: 1.12;
}
/* h2 elements that act as small UI labels stay in Outfit */
.footer-head, .contact-card-head, .q-step-title, .q-result-title {
  font-family: var(--font-stack);
}
h3, .h3 { font-size: 1.25rem; line-height: 1.35; }
p { color: var(--muted); max-width: 62ch; }
.eyebrow {
  display: block;
  font-size: .8125rem;
  font-weight: 600;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--navy-600);
  margin-bottom: .875rem;
}
.lede { font-size: 1.125rem; margin-top: 1rem; }

/* ---------- Layout ---------- */
.container {
  max-width: 1200px;
  margin-inline: auto;
  padding-inline: 24px;
}
.container-narrow { max-width: 720px; margin-inline: auto; padding-inline: 24px; }
.section { padding-block: 64px; }
@media (min-width: 960px) { .section { padding-block: 112px; } }
.section-stone { background: var(--stone); }
.section-head { margin-bottom: 2.5rem; }
@media (min-width: 960px) { .section-head { margin-bottom: 3.5rem; } }
[id] { scroll-margin-top: calc(var(--header-h) + 16px); }

/* Dark bands (navy-950 sections, footer) */
.band-dark { background: var(--navy-950); }
.band-dark h1, .band-dark h2, .band-dark h3 { color: var(--dark-text); }
.band-dark p { color: var(--dark-muted); }
.band-dark a { color: var(--dark-text); }
.band-dark .eyebrow { color: var(--gold); }
.band-dark :focus-visible { outline-color: var(--gold); }

/* ---------- Buttons ---------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: .5rem;
  border-radius: 999px;
  padding: .8125rem 1.75rem;
  font-weight: 600;
  font-size: 1rem;
  line-height: 1.2;
  white-space: nowrap;
  text-decoration: none;
  transition: transform .18s var(--ease-out), background-color .18s ease, color .18s ease, border-color .18s ease;
}
.btn:hover { text-decoration: none; transform: translateY(-1px); }
.btn:active { transform: scale(.98); }
.btn-gold { background: var(--gold); color: var(--navy-950); }
.btn-gold:hover { background: var(--gold-600); color: var(--navy-950); }
.btn-outline {
  border: 1.5px solid currentColor;
  color: var(--navy-600);
  background: transparent;
}
.btn-outline:hover { color: var(--navy-800); }
.band-dark .btn-outline, .on-dark.btn-outline { color: var(--dark-text); }
.band-dark .btn-outline:hover, .on-dark.btn-outline:hover { color: var(--dark-text); background-color: rgb(244 246 248 / .08); }
.btn-sm { padding: .625rem 1.375rem; font-size: .9375rem; }

/* ---------- Skip link ---------- */
.skip-link {
  position: absolute;
  top: -48px;
  left: 16px;
  z-index: 200;
  background: var(--navy-950);
  color: var(--dark-text);
  padding: .625rem 1.25rem;
  border-radius: 999px;
  transition: top .2s ease;
}
.skip-link:focus { top: 12px; }

/* =============================================================
   Header
   ============================================================= */
.site-header {
  position: sticky;
  top: 0;
  z-index: 100;
  height: var(--header-h);
  border-bottom: 1px solid transparent;
  transition: border-color .25s ease;
}
/* Blur lives on a pseudo-element: backdrop-filter on the header itself
   would turn it into the containing block for the fixed mobile menu. */
.site-header::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: rgb(250 250 248 / .88);
  -webkit-backdrop-filter: blur(12px);
  backdrop-filter: blur(12px);
  transition: background-color .25s ease;
}
.site-header.is-scrolled { border-bottom-color: var(--line); }
.header-inner {
  position: relative;
  z-index: 95; /* keeps logo + toggle above the fixed .mobile-menu overlay */
  height: var(--header-h);
  display: flex;
  align-items: center;
  gap: 1.5rem;
}
.brand { display: inline-flex; align-items: center; flex-shrink: 0; }
.brand img { height: 26px; width: auto; }

.site-nav { display: none; }
.header-actions { margin-left: auto; display: flex; align-items: center; gap: 1.25rem; }
.phone-link {
  display: inline-flex;
  align-items: center;
  gap: .4rem;
  font-weight: 600;
  color: var(--ink);
  white-space: nowrap;
}
.phone-link:hover { color: var(--navy-600); text-decoration: none; }
.phone-link svg { width: 16px; height: 16px; flex-shrink: 0; }
.header-actions .btn { display: none; }

/* Hamburger */
.nav-toggle {
  display: inline-flex;
  flex-direction: column;
  justify-content: center;
  gap: 6px;
  width: 44px;
  height: 44px;
  align-items: center;
  border-radius: 8px;
}
.nav-toggle-bar {
  width: 22px;
  height: 2px;
  background: var(--ink);
  border-radius: 2px;
  transition: transform .25s var(--ease-out), opacity .2s ease;
}
.nav-toggle[aria-expanded="true"] .nav-toggle-bar:first-child { transform: translateY(4px) rotate(45deg); }
.nav-toggle[aria-expanded="true"] .nav-toggle-bar:last-child { transform: translateY(-4px) rotate(-45deg); }

/* Mobile header: phone link becomes a tappable round icon left of the hamburger */
@media (max-width: 959.98px) {
  .header-actions { gap: .5rem; }
  .header-actions .phone-link {
    width: 44px;
    height: 44px;
    justify-content: center;
    border-radius: 999px;
    background: var(--navy-100);
    color: var(--navy-800);
  }
  .header-actions .phone-link span {
    position: absolute;
    width: 1px;
    height: 1px;
    overflow: hidden;
    clip: rect(0 0 0 0);
  }
  .header-actions .phone-link svg { width: 19px; height: 19px; }
}

@media (min-width: 960px) {
  .site-nav { display: block; }
  .header-actions .phone-link { display: inline-flex; }
  .header-actions .btn { display: inline-flex; }
  .nav-toggle { display: none; }
}

/* Desktop nav */
.nav-list { display: flex; align-items: center; gap: .25rem; }
.nav-item { position: relative; }
.nav-link {
  display: inline-flex;
  align-items: center;
  gap: .3rem;
  padding: .5rem .875rem;
  font-weight: 500;
  font-size: .9875rem;
  color: var(--ink);
  border-radius: 999px;
  text-decoration: none;
}
.nav-link:hover { color: var(--navy-600); text-decoration: none; }
.nav-link .chev { width: 12px; height: 12px; transition: transform .2s ease; }

/* Services dropdown: opens on hover/focus-within (desktop) and on .open via JS click */
.dropdown {
  position: absolute;
  top: calc(100% + 10px);
  left: 0;
  min-width: 240px;
  background: var(--surface);
  border: 1px solid var(--line);
  border-radius: var(--radius-card);
  box-shadow: var(--shadow-card);
  padding: .5rem;
  opacity: 0;
  visibility: hidden;
  transform: translateY(6px);
  transition: opacity .18s ease, transform .18s var(--ease-out), visibility .18s;
}
.dropdown a {
  display: block;
  padding: .625rem .875rem;
  border-radius: 8px;
  color: var(--ink);
  font-weight: 500;
  font-size: .9875rem;
}
.dropdown a:hover { background: var(--navy-100); color: var(--navy-600); text-decoration: none; }
.has-dropdown:hover .dropdown,
.has-dropdown:focus-within .dropdown,
.has-dropdown.open .dropdown {
  opacity: 1;
  visibility: visible;
  transform: translateY(0);
}
.has-dropdown:hover .chev,
.has-dropdown.open .chev { transform: rotate(180deg); }
/* Hover bridge so the pointer can travel to the panel */
.has-dropdown::after {
  content: "";
  position: absolute;
  left: 0;
  right: 0;
  top: 100%;
  height: 12px;
}

/* =============================================================
   Mobile overlay menu
   ============================================================= */
.mobile-menu {
  position: fixed;
  inset: 0;
  z-index: 90;
  padding: calc(var(--header-h) + 24px) 24px 40px;
  background: var(--navy-950);
  overflow-y: auto;
  opacity: 0;
  visibility: hidden;
  transition: opacity .25s ease, visibility .25s;
}
.mobile-menu.is-open { opacity: 1; visibility: visible; }
body.menu-open { overflow: hidden; }
body.menu-open .site-header { border-bottom-color: var(--navy-800); }
body.menu-open .site-header::before { background: var(--navy-950); }
body.menu-open .nav-toggle-bar { background: var(--dark-text); }
body.menu-open .brand img { filter: brightness(0) invert(1); }

.mobile-nav > li + li { border-top: 1px solid var(--navy-800); }
.mobile-nav > li > a {
  display: block;
  padding: 1rem 0;
  font-size: 1.375rem;
  font-weight: 600;
  color: var(--dark-text);
}
.mobile-nav > li > a:hover { color: var(--gold); text-decoration: none; }
.mobile-group { padding: 1rem 0; }
.mobile-label {
  display: block;
  font-size: .8125rem;
  font-weight: 600;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--gold);
  margin-bottom: .5rem;
}
.mobile-group ul { list-style: none; padding: 0; }
.mobile-group a {
  display: block;
  padding: .5rem 0;
  font-size: 1.125rem;
  font-weight: 500;
  color: var(--dark-text);
}
.mobile-group a:hover { color: var(--gold); text-decoration: none; }
.mobile-cta {
  margin-top: 2rem;
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 1.25rem;
}
.mobile-cta .phone-link { display: inline-flex; color: var(--dark-text); font-size: 1.125rem; }
.mobile-cta .phone-link:hover { color: var(--gold); }
.mobile-menu :focus-visible { outline-color: var(--gold); }

/* =============================================================
   Reveal on scroll
   JS adds class "js" to <html>, IntersectionObserver adds .in-view.
   Usage: class="reveal" + optional inline style="--delay:.1s"
   ============================================================= */
html.js .reveal {
  opacity: 0;
  transform: translateY(20px);
  transition: opacity .6s var(--ease-out), transform .6s var(--ease-out);
  transition-delay: var(--delay, 0s);
}
html.js .reveal.in-view { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) {
  html.js .reveal { opacity: 1; transform: none; transition: none; }
}

/* =============================================================
   Cards & media
   ============================================================= */
.card { background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius-card); }
.img-rounded { border-radius: var(--radius-card); }

/* =============================================================
   Accordion (FAQ) - native <details>, works without JS
   ============================================================= */
.faq-list { max-width: 800px; }
.faq-item { border-bottom: 1px solid var(--line); }
.faq-item:first-child { border-top: 1px solid var(--line); }
.faq-q {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 1.5rem;
  padding: 1.25rem 0;
  font-weight: 600;
  font-size: 1.125rem;
  color: var(--ink);
  cursor: pointer;
  list-style: none;
}
.faq-q::-webkit-details-marker { display: none; }
.faq-q:hover { color: var(--navy-600); }
.faq-icon { position: relative; width: 18px; height: 18px; flex-shrink: 0; }
.faq-icon::before, .faq-icon::after {
  content: "";
  position: absolute;
  background: var(--navy-600);
  border-radius: 2px;
  transition: transform .3s var(--ease-out);
}
.faq-icon::before { left: 0; right: 0; top: 8px; height: 2px; }
.faq-icon::after { top: 0; bottom: 0; left: 8px; width: 2px; }
.faq-item[open] .faq-icon::after { transform: rotate(90deg) scaleY(0.01); }
.faq-item[open] .faq-icon::before { transform: rotate(180deg); }
.faq-a { padding: 0 0 1.5rem; max-width: 62ch; }
.faq-item[open] .faq-a { animation: faq-open .35s var(--ease-out); }
@keyframes faq-open {
  from { opacity: 0; transform: translateY(-6px); }
  to { opacity: 1; transform: none; }
}

/* =============================================================
   Cost tiers (service pages)
   A written price range for each level of a job. Shared component:
   every service page uses the same three-tier block so the "how much
   does X cost" answer is in real text on the page, not only inside
   the quote tool.
   ============================================================= */
.price-tiers { display: grid; gap: 0; margin-top: 2.5rem; }
@media (min-width: 900px) {
  .price-tiers { grid-template-columns: repeat(3, 1fr); gap: 0 3rem; }
}
.price-tier { padding-block: 1.75rem; border-top: 1px solid var(--line); }
@media (min-width: 900px) { .price-tier { padding-block: 2rem 0; } }
.price-tier h3 {
  font-size: .8125rem;
  font-weight: 600;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--navy-600);
}
.price-range {
  margin-top: .5rem;
  font-family: var(--font-display);
  font-size: clamp(1.75rem, 2.6vw, 2.25rem);
  font-weight: 560;
  line-height: 1.1;
  color: var(--ink);
  max-width: none;
}
.price-tier p + p { margin-top: .625rem; }
.price-tier .price-scope { max-width: 40ch; }
.price-note {
  margin-top: 2.5rem;
  padding-top: 1.5rem;
  border-top: 1px solid var(--line);
  font-size: .9375rem;
  max-width: 70ch;
}

/* =============================================================
   Areas we serve (town pages)
   .town-grid   cards linking to each town page
   .fact-list   the local specifics that make a town page worth
                reading: housing stock, permit office, quirks
   .town-links  inline row of sibling town links
   ============================================================= */
.town-grid { display: grid; gap: 1.5rem; margin-top: 2.5rem; }
@media (min-width: 700px) { .town-grid { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1000px) { .town-grid { grid-template-columns: repeat(3, 1fr); } }
.town-card {
  display: block;
  padding: 1.625rem 1.5rem 1.75rem;
  border: 1px solid var(--line);
  border-radius: var(--radius-card);
  background: var(--surface);
  text-decoration: none;
  transition: transform .2s var(--ease-out), border-color .2s ease, box-shadow .2s ease;
}
.town-card:hover {
  text-decoration: none;
  transform: translateY(-2px);
  border-color: var(--gold);
  box-shadow: var(--shadow-card);
}
.town-card h3 { font-size: 1.1875rem; }
.town-card p { margin-top: .5rem; font-size: .9375rem; }
.town-card .town-go {
  display: inline-block;
  margin-top: 1rem;
  font-size: .875rem;
  font-weight: 600;
  color: var(--gold-700);
}

.fact-list { margin-top: 2rem; max-width: 780px; }
.fact-list > div { padding-block: 1.5rem; border-top: 1px solid var(--line); }
.fact-list > div:last-child { border-bottom: 1px solid var(--line); }
.fact-list dt { font-weight: 600; color: var(--ink); }
.fact-list dd { margin: .375rem 0 0; color: var(--muted); max-width: 66ch; }

/* One short brief per municipality inside a town's ZIP. Two columns on
   desktop so a list of eight or eleven stays scannable. */
.area-briefs { max-width: none; margin-top: 2.5rem; }
@media (min-width: 900px) {
  .area-briefs { display: grid; grid-template-columns: repeat(2, 1fr); column-gap: 3.5rem; }
}
.area-briefs > div { padding-block: 1.375rem; border-top: 1px solid var(--line); }
.area-briefs > div:last-child { border-bottom: none; }
@media (min-width: 900px) {
  .area-briefs > div:nth-last-child(-n+2) { border-bottom: 1px solid var(--line); }
}
@media (max-width: 899px) {
  .area-briefs > div:last-child { border-bottom: 1px solid var(--line); }
}
.area-briefs dt { font-size: 1.0625rem; }
.area-briefs dd { font-size: .9375rem; max-width: 52ch; }

.town-links { display: flex; flex-wrap: wrap; gap: .625rem 1.5rem; margin-top: 1.25rem; }
.town-links a { font-weight: 600; }

/* =============================================================
   Forms
   Labels sit ABOVE inputs. Error text uses .field-error + aria-describedby.
   ============================================================= */
.field { display: flex; flex-direction: column; gap: .375rem; margin-bottom: 1.25rem; }
.field label { font-weight: 600; font-size: .9375rem; color: var(--ink); }
.field-hint { font-size: .875rem; color: var(--muted); }
.input,
.field input,
.field select,
.field textarea {
  width: 100%;
  padding: .75rem .875rem;
  border: 1.5px solid var(--line);
  border-radius: var(--radius-input);
  background: var(--surface);
  color: var(--ink);
  transition: border-color .15s ease, box-shadow .15s ease;
}
.field textarea { min-height: 130px; resize: vertical; }
.field input:focus-visible,
.field select:focus-visible,
.field textarea:focus-visible {
  outline: 2px solid var(--navy-600);
  outline-offset: 2px;
  border-color: var(--navy-600);
}
.field.has-error input,
.field.has-error select,
.field.has-error textarea { border-color: var(--error); }
.field-error { display: none; font-size: .875rem; font-weight: 500; color: var(--error); }
.field.has-error .field-error { display: block; }
.form-success {
  background: var(--navy-100);
  border: 1px solid var(--navy-600);
  border-radius: var(--radius-card);
  padding: 1.5rem;
}
.form-success h3 { color: var(--navy-800); margin-bottom: .375rem; }
.form-consent { font-size: .8125rem; color: var(--muted); }

/* =============================================================
   Trust strip (slim fact row on --stone)
   ============================================================= */
.trust-strip { background: var(--stone); padding-block: 1.375rem; }
.trust-row {
  display: flex;
  flex-wrap: wrap;
  gap: .75rem 2.5rem;
  align-items: center;
  justify-content: center;
}

/* --- Looping marquee ---
   js/main.js wraps a .trust-row in .trust-marquee > .trust-track and clones the
   items once, then measures the first copy and sets --trust-w and --trust-time.
   Translating by exactly one copy's width means the loop has no seam. Without
   JS the row stays the centred wrapping flex row above, which is why every
   rule here is scoped to .trust-track. */
.trust-marquee {
  overflow: hidden;
  /* Match the site's content width. Left full-bleed, a wide monitor shows more
     than one pass of the strip at once and the same badge appears twice. */
  max-width: 1200px;
  margin-inline: auto;
  /* fade the ends so items enter and leave instead of getting chopped */
  -webkit-mask-image: linear-gradient(90deg, transparent, #000 6%, #000 94%, transparent);
          mask-image: linear-gradient(90deg, transparent, #000 6%, #000 94%, transparent);
}
.trust-track {
  display: flex;
  width: max-content;
  max-width: none;
  flex-wrap: nowrap;
}
.trust-track .trust-row {
  flex-wrap: nowrap;
  justify-content: flex-start;
  width: max-content;
  max-width: none;
  padding-inline: 0;
  margin-inline: 0;
  /* js/main.js widens this until one pass of the strip is wider than the
     screen, so the same item is never on screen twice */
  gap: var(--trust-gap, 2.5rem);
  padding-right: var(--trust-gap, 2.5rem);
}
@media (prefers-reduced-motion: no-preference) {
  .trust-track.is-looping {
    animation: trust-scroll var(--trust-time, 40s) linear infinite;
  }
  /* let people read an item they are interested in */
  .trust-marquee:hover .trust-track.is-looping,
  .trust-marquee:focus-within .trust-track.is-looping { animation-play-state: paused; }
}
@keyframes trust-scroll {
  from { transform: translate3d(0, 0, 0); }
  to   { transform: translate3d(calc(var(--trust-w, 0px) * -1), 0, 0); }
}

.trust-item {
  display: inline-flex;
  align-items: center;
  gap: .5rem;
  font-size: .9375rem;
  font-weight: 500;
  color: var(--ink);
  white-space: nowrap;
}
.trust-item svg { width: 17px; height: 17px; flex-shrink: 0; color: var(--gold-700); }

/* Narrow screens: an item on one nowrap line can end up wider than the phone
   (the service-area line is over 400px), so it could never be read in full.
   Let items wrap into a capped block instead, tighten the spacing, and pull
   the end fades in so less of each item is hidden. js/main.js also slows the
   scroll down here. */
@media (max-width: 700px) {
  .trust-item {
    white-space: normal;
    align-items: flex-start;
    line-height: 1.35;
  }
  .trust-item svg { margin-top: .18em; }
  .trust-track .trust-item { max-width: min(74vw, 270px); }
  .trust-marquee {
    -webkit-mask-image: linear-gradient(90deg, transparent, #000 3%, #000 97%, transparent);
            mask-image: linear-gradient(90deg, transparent, #000 3%, #000 97%, transparent);
  }
}

/* =============================================================
   Hero (home: full-bleed image + navy scrim, left content)
   ============================================================= */
.hero {
  position: relative;
  min-height: 92vh;
  min-height: 92dvh;
  display: flex;
  align-items: center;
  overflow: hidden;
}
.hero-media { position: absolute; inset: 0; }
.hero-media img { width: 100%; height: 100%; object-fit: cover; }
.hero-scrim {
  position: absolute;
  inset: 0;
  background: linear-gradient(100deg, rgb(8 30 49 / .88) 0%, rgb(8 30 49 / .62) 45%, rgb(8 30 49 / .22) 80%);
}
.hero-content { position: relative; z-index: 1; padding-block: 7rem; max-width: 640px; }
.hero-content .eyebrow { color: var(--gold); }
.hero-content h1 { color: #F4F6F8; }
.hero-sub { margin-top: 1.25rem; font-size: 1.1875rem; color: var(--dark-text); }
.hero-ctas { margin-top: 2.25rem; display: flex; flex-wrap: wrap; gap: 1rem; }
.hero .btn-outline { color: var(--dark-text); }
.hero :focus-visible { outline-color: var(--gold); }

/* Service-page variant of the same hero: shorter than the home hero so the
   page's own content starts above the fold, and the inline link + phone
   number restyled for the dark scrim. Used on all four service pages;
   only the image and the copy change per page. */
.hero-service { min-height: 70vh; min-height: 70dvh; }
.hero-service .hero-sub { max-width: 52ch; }
.hero-service .hero-sub a { color: var(--gold); }
.hero-service .phone-link { color: var(--dark-text); }
.hero-service .phone-link:hover { color: var(--gold); }

/* =============================================================
   Services asymmetric grid (home)
   Areas: kitchen 2/3 + basement 1/3, then waterproofing 1/3 + bath 2/3
   ============================================================= */
.services-grid { display: grid; gap: 1.5rem; }
@media (min-width: 720px) {
  .services-grid {
    grid-template-columns: repeat(3, 1fr);
    grid-template-areas:
      "kitchen kitchen basement"
      "water bath bath";
  }
  .svc-kitchen { grid-area: kitchen; }
  .svc-basement { grid-area: basement; }
  .svc-water { grid-area: water; }
  .svc-bath { grid-area: bath; }
}
.service-card {
  display: block;
  color: var(--ink);
  text-decoration: none;
  border-radius: var(--radius-card);
}
.service-card:hover { text-decoration: none; }
.service-card figure {
  overflow: hidden;
  border-radius: var(--radius-card);
  aspect-ratio: 4 / 3;
  background: var(--stone);
}
@media (min-width: 720px) {
  .service-card.is-wide figure { aspect-ratio: 16 / 9; }
}
.service-card img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  transition: transform .7s var(--ease-out);
}
.service-card:hover img, .service-card:focus-visible img { transform: scale(1.04); }
.service-card h3 { margin-top: 1rem; }
.service-card p { margin-top: .25rem; font-size: .9875rem; }
.card-arrow {
  display: inline-flex;
  align-items: center;
  gap: .375rem;
  margin-top: .625rem;
  font-weight: 600;
  font-size: .9375rem;
  color: var(--navy-600);
}
.card-arrow svg { width: 15px; height: 15px; transition: transform .25s var(--ease-out); }
.service-card:hover .card-arrow svg, .service-card:focus-visible .card-arrow svg { transform: translateX(4px); }

/* =============================================================
   Split section (image + content, no card boxes)
   ============================================================= */
.split { display: grid; gap: 2.5rem; align-items: center; }
@media (min-width: 900px) {
  .split { grid-template-columns: 1fr 1fr; gap: 4rem; }
  .split.split-wide-text { grid-template-columns: .9fr 1.1fr; }
}
.point-list { margin-top: 2rem; display: flex; flex-direction: column; gap: 1.5rem; }
.point { display: flex; gap: 1rem; align-items: flex-start; }
.point-icon {
  flex-shrink: 0;
  width: 40px;
  height: 40px;
  display: grid;
  place-items: center;
  border-radius: 999px;
  background: var(--navy-100);
  color: var(--navy-600);
}
.point-icon svg { width: 18px; height: 18px; }
.point h3 { font-size: 1.125rem; }
.point p { margin-top: .125rem; font-size: .9875rem; }

/* =============================================================
   Projects masonry-feel grid (home)
   ============================================================= */
.projects-grid { display: grid; gap: 2rem; }
@media (min-width: 720px) {
  .projects-grid { grid-template-columns: 1fr 1fr; gap: 2.5rem; }
  .projects-grid > :nth-child(even) { margin-top: 3.5rem; }
}
.project-card { display: block; }
.project-card figure { overflow: hidden; border-radius: var(--radius-card); background: var(--stone); }
.project-card.is-tall figure { aspect-ratio: 4 / 5; }
.project-card.is-wide figure { aspect-ratio: 16 / 10; }
.project-card img { width: 100%; height: 100%; object-fit: cover; }
.project-card h3 { margin-top: 1rem; }
.project-meta {
  margin-top: .125rem;
  font-size: .875rem;
  font-weight: 600;
  letter-spacing: .06em;
  text-transform: uppercase;
  color: var(--gold-700);
}
.project-card > p { margin-top: .375rem; font-size: .9875rem; }

/* =============================================================
   Process timeline (home: dark band, vertical line, gold numbers)
   ============================================================= */
.timeline { position: relative; max-width: 680px; }
.timeline::before {
  content: "";
  position: absolute;
  left: 19px;
  top: 8px;
  bottom: 8px;
  width: 1px;
  background: var(--navy-800);
}
.timeline li { position: relative; padding: 0 0 2.25rem 4rem; }
.timeline li:last-child { padding-bottom: 0; }
.step-num {
  position: absolute;
  left: 0;
  top: 0;
  width: 40px;
  height: 40px;
  display: grid;
  place-items: center;
  border-radius: 999px;
  background: var(--navy-950);
  border: 1px solid var(--gold);
  color: var(--gold);
  font-weight: 600;
  font-size: .9375rem;
}
.timeline h3 { color: var(--dark-text); }
.timeline p { margin-top: .25rem; font-size: .9875rem; }

/* Horizontal 5-step strip (service pages: light bg) */
.process-strip { display: grid; gap: 1.75rem; counter-reset: step; }
@media (min-width: 900px) { .process-strip { grid-template-columns: repeat(5, 1fr); gap: 1.5rem; } }
.process-strip li { counter-increment: step; }
.process-strip li::before {
  content: counter(step, decimal-leading-zero);
  display: block;
  font-weight: 600;
  color: var(--gold-700);
  font-size: .9375rem;
  margin-bottom: .5rem;
}
.process-strip h3 { font-size: 1.0625rem; }
.process-strip p { margin-top: .25rem; font-size: .9375rem; }

/* =============================================================
   CTA band
   Home: light split with image. Service pages: add .band-dark instead.
   ============================================================= */
.cta-split { display: grid; gap: 2.5rem; align-items: center; }
@media (min-width: 900px) { .cta-split { grid-template-columns: 1.15fr .85fr; gap: 4rem; } }
.cta-actions { margin-top: 2rem; display: flex; flex-wrap: wrap; align-items: center; gap: 1.25rem; }
.cta-alt { margin-top: 1.25rem; font-size: .9875rem; }

/* =============================================================
   Footer
   ============================================================= */
.site-footer { background: var(--navy-950); border-top: 1px solid var(--gold); padding: 5.5rem 0 3rem; }
.site-footer h2, .site-footer h3 { color: var(--dark-text); }
.site-footer p { color: var(--dark-muted); }
.footer-top { display: grid; gap: 3rem; }
@media (min-width: 900px) { .footer-top { grid-template-columns: 1.2fr 2fr; gap: 4rem; } }
.footer-brand img { height: 30px; width: auto; }
.footer-tagline {
  font-family: var(--font-display);
  margin-top: 1.5rem;
  font-size: 1.375rem;
  font-weight: 560;
  line-height: 1.4;
  color: var(--dark-text);
  max-width: 26ch;
}
.footer-cols { display: grid; gap: 2rem; grid-template-columns: 1fr; }
@media (min-width: 560px) { .footer-cols { grid-template-columns: repeat(3, 1fr); } }
.footer-head {
  font-size: .8125rem;
  font-weight: 600;
  letter-spacing: .12em;
  text-transform: uppercase;
  color: var(--gold);
  margin-bottom: 1rem;
}
.footer-list li + li { margin-top: .625rem; }
.footer-list a { color: var(--dark-muted); font-size: .9875rem; }
.footer-list a:hover { color: var(--dark-text); text-decoration: none; }
.footer-areas {
  margin-top: 3rem;
  padding-top: 2rem;
  border-top: 1px solid var(--navy-800);
  font-size: .875rem;
  max-width: none;
}
.footer-bottom {
  margin-top: 1.75rem;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: 1rem 2rem;
  justify-content: space-between;
}
.footer-bottom p { font-size: .875rem; }
.footer-social { display: flex; gap: .875rem; }
.footer-social a {
  display: grid;
  place-items: center;
  width: 38px;
  height: 38px;
  border-radius: 999px;
  border: 1px solid var(--navy-800);
  color: var(--dark-muted);
  transition: color .18s ease, border-color .18s ease;
}
.footer-social a:hover { color: var(--gold); border-color: var(--gold); text-decoration: none; }
.footer-social svg { width: 17px; height: 17px; }
.site-footer :focus-visible { outline-color: var(--gold); }

/* =============================================================
   Luxury finish pass
   ============================================================= */

/* Text selection */
::selection { background: var(--navy-950); color: var(--paper); }
.band-dark ::selection,
.site-footer ::selection,
.mobile-menu ::selection,
.hero ::selection { background: var(--gold); color: var(--navy-950); }

/* Slow Ken Burns on the home hero image (runs once) */
@media (prefers-reduced-motion: no-preference) {
  .hero-media img { animation: hero-drift 22s var(--ease-out) forwards; }
}
@keyframes hero-drift {
  from { transform: scale(1); }
  to { transform: scale(1.06); }
}

/* Inline text links + footer links: underline slides in */
p a,
.footer-list a {
  text-decoration: none;
  background-image: linear-gradient(currentColor, currentColor);
  background-size: 0 1px;
  background-position: 0 100%;
  background-repeat: no-repeat;
  transition: background-size .3s var(--ease-out), color .18s ease;
}
p a:hover, p a:focus-visible,
.footer-list a:hover, .footer-list a:focus-visible {
  text-decoration: none;
  background-size: 100% 1px;
}

/* Active nav item (aria-current set per page; .is-active on the Services
   trigger when a service page is open) */
.nav-link[aria-current="page"],
.drop-toggle.is-active { color: var(--navy-600); }
.dropdown a[aria-current="page"] { background: var(--navy-100); color: var(--navy-600); }
.mobile-nav > li > a[aria-current="page"],
.mobile-group a[aria-current="page"] { color: var(--gold); }

/* =============================================================
   Reduced motion: kill everything
   ============================================================= */
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: .01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .01ms !important;
  }
}

/* =============================================================
   --- bespoke motifs ---
   Home-page drafting-table motifs: shared draw-in pattern,
   process timeline icons, peak mark, blueprint grid texture.
   Append-only block; nothing above this line was changed.
   ============================================================= */

/* Shared draw-in for line-work SVGs (paths carry pathLength="1").
   Triggered by .in-view, which main.js adds to .reveal hosts. */
.draw { stroke-dasharray: 1; stroke-dashoffset: 1; }
.in-view .draw {
  stroke-dashoffset: 0;
  transition: stroke-dashoffset 1.1s cubic-bezier(.16,1,.3,1) .15s;
}
/* Stagger icon primitives in drawing order (.12s steps after the .15s base) */
.in-view .step-icon .draw:nth-child(2) { transition-delay: .27s; }
.in-view .step-icon .draw:nth-child(3) { transition-delay: .39s; }
.in-view .step-icon .draw:nth-child(4) { transition-delay: .51s; }
.in-view .step-icon .draw:nth-child(5) { transition-delay: .63s; }
/* No JS: main.js never adds .in-view, so keep line work visible */
html:not(.js) .draw { stroke-dashoffset: 0; }
@media (prefers-reduced-motion: reduce) {
  .draw { stroke-dashoffset: 0; transition: none; }
}

/* a. Process timeline icons (gold line work on the dark band) */
.step-head { display: flex; align-items: center; gap: .875rem; }
.step-icon { width: 26px; height: 26px; flex: none; stroke: var(--gold); }

/* b. Peak mark: gold hairline with the logo's open triangle peak */
.peak-mark {
  display: block;
  width: 72px;
  height: 12px;
  margin-bottom: 14px;
  stroke: var(--gold);
}

/* c. Blueprint graph paper on stone sections.
   Three stacked layers so the paper reads as a real drafting sheet:
     1. ::before - fine 24px grid + heavier 120px major grid (the paper)
     2. ::after  - a brighter copy of the same grids, masked to a wide
                   diagonal band that travels across the section, so the
                   ruling catches light like a sheet on a drafting table
     3. .draft-bg (markup) - the line-work fragments that draw themselves in
   Both pseudo-elements sit at z-index 0; section containers are lifted to 1. */
.section-stone {
  position: relative;
  isolation: isolate;
  --grid-fine: 24px;
  --grid-major: 120px;
  --grid-ink: 12 79 131; /* navy-600 */
}
.section-stone > .container,
.section-stone > .container-narrow { position: relative; z-index: 1; }

.section-stone::before,
.section-stone::after {
  content: "";
  position: absolute;
  inset: 0;
  z-index: 0;
  pointer-events: none;
}

/* 1. the paper */
.section-stone::before {
  background-image:
    repeating-linear-gradient(0deg,  rgb(var(--grid-ink) / .085) 0 1px, transparent 1px var(--grid-major)),
    repeating-linear-gradient(90deg, rgb(var(--grid-ink) / .085) 0 1px, transparent 1px var(--grid-major)),
    repeating-linear-gradient(0deg,  rgb(var(--grid-ink) / .038) 0 1px, transparent 1px var(--grid-fine)),
    repeating-linear-gradient(90deg, rgb(var(--grid-ink) / .038) 0 1px, transparent 1px var(--grid-fine));
  /* ease the ruling off behind the centred copy so text stays crisp */
  -webkit-mask-image: radial-gradient(74% 68% at 50% 50%, rgb(0 0 0 / .35) 0%, #000 100%);
          mask-image: radial-gradient(74% 68% at 50% 50%, rgb(0 0 0 / .35) 0%, #000 100%);
}

/* 2. the light rake: same ruling, brighter, revealed through a moving band */
.section-stone::after {
  background-image:
    repeating-linear-gradient(0deg,  rgb(var(--grid-ink) / .19) 0 1px, transparent 1px var(--grid-major)),
    repeating-linear-gradient(90deg, rgb(var(--grid-ink) / .19) 0 1px, transparent 1px var(--grid-major)),
    repeating-linear-gradient(0deg,  rgb(var(--grid-ink) / .09) 0 1px, transparent 1px var(--grid-fine)),
    repeating-linear-gradient(90deg, rgb(var(--grid-ink) / .09) 0 1px, transparent 1px var(--grid-fine));
  -webkit-mask-image: linear-gradient(102deg, transparent 32%, #000 47%, #000 53%, transparent 68%);
          mask-image: linear-gradient(102deg, transparent 32%, #000 47%, #000 53%, transparent 68%);
  -webkit-mask-size: 240% 100%;
          mask-size: 240% 100%;
  -webkit-mask-repeat: no-repeat;
          mask-repeat: no-repeat;
  -webkit-mask-position: -140% 0;
          mask-position: -140% 0;
  animation: paper-rake 22s linear infinite;
}
@keyframes paper-rake {
  from { -webkit-mask-position: -140% 0; mask-position: -140% 0; }
  to   { -webkit-mask-position:  240% 0; mask-position:  240% 0; }
}

/* --- ambient draft layer --- */
/* Looping "drafting in progress" line work over the graph paper.
   Markup in docs/PARTIALS.md section (k): one .draft-bg (aria-hidden)
   as FIRST child of the stone section, holding five .dfrag SVGs. The
   fragments are CSS-positioned corner pieces so they stay visible at
   every viewport width; with JS they are re-placed each cycle. */
.draft-bg {
  position: absolute;
  inset: 0;
  overflow: hidden;
  pointer-events: none;
  z-index: 0;
  /* ink alpha lives on the colour, not on opacity, so the gold pen layer
     below can glow at full strength over faint navy line work */
  color: rgb(12 79 131 / .26);
  /* pull the line work well back where the centred copy sits, leave it
     at full strength out towards the edges of the sheet */
  -webkit-mask-image: radial-gradient(70% 66% at 50% 50%, rgb(0 0 0 / .12) 0%, rgb(0 0 0 / .5) 55%, rgb(0 0 0 / .92) 100%);
          mask-image: radial-gradient(70% 66% at 50% 50%, rgb(0 0 0 / .12) 0%, rgb(0 0 0 / .5) 55%, rgb(0 0 0 / .92) 100%);
}
.dfrag {
  position: absolute;
  stroke: currentColor;
  fill: none;
  stroke-width: 1.5;
  stroke-linecap: round;
  stroke-linejoin: round;
  height: auto;
}
/* NB: no vector-effect here. non-scaling-stroke makes dash lengths
   screen-space, which would break the pathLength="1" normalisation the
   whole draw cycle depends on. Every fragment renders near 1:1 anyway. */

/* Two fragments below 960px, four up to 1280px, five only on the widest
   sheets: the layer should read as margin notes, never as a crowd. */
.dfrag-a { top: 24px; right: 24px; width: min(420px, 48vw); }
.dfrag-b { bottom: 20px; left: 20px; width: min(370px, 52vw); }
.dfrag-c { display: none; right: 40px; top: 40%; width: 145px; }
.dfrag-d { display: none; left: 6%; top: 16px; width: 180px; }
.dfrag-e { display: none; right: 30%; bottom: 24px; width: 140px; }
@media (min-width: 960px) { .dfrag-c, .dfrag-d { display: block; } }
@media (min-width: 1280px) { .dfrag-e { display: block; } }

/* The pen: js/main.js clones each fragment's line work into a second
   <g class="pen"> layer. It carries a short dash that rides the head of
   the stroke as it draws, so a gold point of light traces every line. */
.dfrag .pen {
  stroke: var(--gold-600);
  stroke-width: 2.4;
  stroke-linecap: round;
  filter: drop-shadow(0 0 3px rgb(194 161 77 / .8))
          drop-shadow(0 0 9px rgb(194 161 77 / .45));
}
/* opacity belongs on the shapes, not the group: a group at opacity 0
   would flatten whatever the keyframes do to its children */
.dfrag .pen * { stroke-dasharray: .05 .95; opacity: 0; }

/* Draw cycle: every shape carries pathLength="1", so dasharray 1
   normalizes rects and circles too. The negative delay on the first
   fragment means line work is already on the paper at first glance. */
.dfrag .ink path,
.dfrag .ink circle,
.dfrag .ink rect,
.dfrag > path,
.dfrag > circle,
.dfrag > rect {
  stroke-dasharray: 1;
  stroke-dashoffset: 1;
  animation: draft-cycle 24s linear infinite;
}
.dfrag .pen path,
.dfrag .pen circle,
.dfrag .pen rect {
  stroke-dashoffset: 1;
  animation: pen-cycle 24s linear infinite;
}
.dfrag-a * { animation-delay: -4s; }
.dfrag-b * { animation-delay: 4s; }
.dfrag-c * { animation-delay: 12s; }
.dfrag-d * { animation-delay: -12s; }
.dfrag-e * { animation-delay: 8s; }
@keyframes draft-cycle {
  0% { stroke-dashoffset: 1; opacity: 0; }
  5% { opacity: 1; }
  16% { stroke-dashoffset: 0; }
  58% { stroke-dashoffset: 0; opacity: 1; }
  68% { opacity: 0; }
  100% { stroke-dashoffset: 1; opacity: 0; }
}
@keyframes pen-cycle {
  0% { stroke-dashoffset: 1; opacity: 0; }
  4% { opacity: .7; }
  16% { stroke-dashoffset: 0; opacity: .7; }
  20% { stroke-dashoffset: 0; opacity: 0; }
  100% { stroke-dashoffset: 0; opacity: 0; }
}

/* JS mode: js/main.js repositions each fragment to a random spot in
   the section every cycle and replays a single run (.run). The
   infinite corner loop above stays as the no-JS fallback. Wrapped in
   no-preference so reduced-motion users keep the static fallback. */
@media (prefers-reduced-motion: no-preference) {
  html.js .dfrag .ink path,
  html.js .dfrag .ink circle,
  html.js .dfrag .ink rect,
  html.js .dfrag .pen path,
  html.js .dfrag .pen circle,
  html.js .dfrag .pen rect {
    animation: none;
    opacity: 0;
  }
  html.js .dfrag.run .ink path,
  html.js .dfrag.run .ink circle,
  html.js .dfrag.run .ink rect {
    animation: draft-run 13s linear 1 both;
  }
  html.js .dfrag.run .pen path,
  html.js .dfrag.run .pen circle,
  html.js .dfrag.run .pen rect {
    animation: pen-run 13s linear 1 both;
  }
}
@keyframes draft-run {
  0% { stroke-dashoffset: 1; opacity: 0; }
  6% { opacity: 1; }
  24% { stroke-dashoffset: 0; }
  68% { stroke-dashoffset: 0; opacity: 1; }
  80% { opacity: 0; }
  100% { stroke-dashoffset: 0; opacity: 0; }
}
@keyframes pen-run {
  0% { stroke-dashoffset: 1; opacity: 0; }
  5% { opacity: .7; }
  24% { stroke-dashoffset: 0; opacity: .7; }
  29% { stroke-dashoffset: 0; opacity: 0; }
  100% { stroke-dashoffset: 0; opacity: 0; }
}

/* No JS: main.js never adds .js, so the CSS corner loop above runs. */

/* Reduced motion: static line work at rest, no loop, no rake. */
@media (prefers-reduced-motion: reduce) {
  .section-stone::after { animation: none; opacity: 0; }
  .draft-bg * {
    animation: none;
    stroke-dasharray: none;
    stroke-dashoffset: 0;
  }
  .draft-bg { color: rgb(12 79 131 / .22); }
  .dfrag .pen { display: none; }
}
