/* Structural stylesheet — the shared layer, deliberately company-agnostic.
 *
 * Mobile-first: the base rules are the phone layout and every media query is min-width.
 * The reference site did the opposite — a desktop base with eight max-width overrides
 * stacked under it — and mobile is the render Google actually indexes, so it is the one
 * that should not be an override of something else.
 *
 * BREAKPOINTS. 40rem / 48rem / 64rem / 90rem, and nothing else. They are written as
 * literals because a custom property cannot be used inside a media query — declaring
 * --bp-* tokens that no query can reference is how the reference site ended up with five
 * breakpoint variables and zero uses of them. If a new width is genuinely needed, add it
 * to this list first.
 *
 * The visual design lands later. What is here is the contract it drops into: semantic
 * class names and the token block below. A restyle should touch the tokens and a theme
 * layer, not these rules.
 */

/* ── Tokens ──────────────────────────────────────────────────────────────── */

:root {
  color-scheme: light dark;

  --bg: #ffffff;
  --bg-sunken: #f4f4f5;
  --bg-elevated: #ffffff;
  --fg: #16171a;
  --fg-muted: #55585f;
  --accent: #0b6b58;
  --accent-contrast: #ffffff;
  --border: #d9dade;

  --font-body: system-ui, -apple-system, "Segoe UI", Roboto, sans-serif;

  /* Fluid scale. clamp() covers the sizes between breakpoints so type does not step. */
  --text-sm: 0.875rem;
  --text-base: clamp(1rem, 0.96rem + 0.2vw, 1.125rem);
  --text-lg: clamp(1.125rem, 1.05rem + 0.35vw, 1.375rem);
  --text-xl: clamp(1.375rem, 1.2rem + 0.8vw, 1.875rem);
  --text-2xl: clamp(1.75rem, 1.4rem + 1.6vw, 2.5rem);
  --text-3xl: clamp(2.125rem, 1.55rem + 2.6vw, 3.5rem);

  --space-1: 0.5rem;
  --space-2: 1rem;
  --space-3: 1.5rem;
  --space-4: 2.5rem;
  --space-5: 4rem;

  --radius: 10px;
  --measure: 68ch;
  --container: 78rem;
  --gutter: var(--space-2);

  /* 44px is the smallest thing a finger reliably hits; iOS zooms any input under 16px. */
  --tap-min: 44px;
  --input-min-size: 16px;
}

@media (min-width: 48rem) {
  :root { --gutter: var(--space-3); }
}
@media (min-width: 64rem) {
  :root { --gutter: var(--space-4); }
}

/* prefers-color-scheme is the default; [data-theme] exists so a future manual toggle can
   override it in both directions without either mechanism becoming the only one. */
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) {
    --bg: #0b0b0d;
    --bg-sunken: #141417;
    --bg-elevated: #1a1a1e;
    --fg: #f2f2f3;
    --fg-muted: #a2a5ac;
    --accent: #4fd1b0;
    --accent-contrast: #06120f;
    --border: #2c2d33;
  }
}
:root[data-theme="dark"] {
  --bg: #0b0b0d;
  --bg-sunken: #141417;
  --bg-elevated: #1a1a1e;
  --fg: #f2f2f3;
  --fg-muted: #a2a5ac;
  --accent: #4fd1b0;
  --accent-contrast: #06120f;
  --border: #2c2d33;
}

/* ── Reset ───────────────────────────────────────────────────────────────── */

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

html { -webkit-text-size-adjust: 100%; }

body {
  margin: 0;
  /* The page itself never scrolls sideways. Wide things (tables, code) scroll inside
     their own container — see .scroll-x. A Playwright guard fails the build otherwise. */
  overflow-x: hidden;
  background: var(--bg);
  color: var(--fg);
  font: 400 var(--text-base)/1.6 var(--font-body);
}

img, svg, video { max-width: 100%; height: auto; }

h1, h2, h3 { line-height: 1.2; text-wrap: balance; margin-block: 0 var(--space-2); }
h1 { font-size: var(--text-3xl); }
h2 { font-size: var(--text-2xl); }
h3 { font-size: var(--text-xl); }
p, li { text-wrap: pretty; }

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

:focus-visible {
  outline: 3px solid var(--accent);
  outline-offset: 2px;
  border-radius: 2px;
}

input, select, textarea, button {
  font: inherit;
  font-size: max(var(--input-min-size), 1rem);
  min-height: var(--tap-min);
}

/* ── Layout primitives ───────────────────────────────────────────────────── */

.container {
  width: 100%;
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.site-main { display: block; }

.prose { max-width: var(--measure); }

.scroll-x { overflow-x: auto; -webkit-overflow-scrolling: touch; }

.button {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-height: var(--tap-min);
  padding: var(--space-1) var(--space-3);
  border-radius: var(--radius);
  background: var(--accent);
  color: var(--accent-contrast);
  font-weight: 600;
  text-decoration: none;
}

.skip-link {
  position: absolute;
  left: var(--space-2);
  top: -5rem;
  z-index: 20;
  padding: var(--space-1) var(--space-2);
  background: var(--bg-elevated);
  color: var(--fg);
  border: 2px solid var(--accent);
  border-radius: var(--radius);
  transition: top 120ms ease;
}
.skip-link:focus { top: var(--space-2); }

/* ── Header and navigation ───────────────────────────────────────────────── */

.site-header {
  padding: var(--space-2) var(--gutter);
  border-bottom: 1px solid var(--border);
  background: var(--bg);
}

.site-header__inner {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-2);
  width: 100%;
  max-width: var(--container);
  margin-inline: auto;
}

.brand {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);
  min-height: var(--tap-min);
  color: inherit;
  text-decoration: none;
  font-weight: 700;
}
.brand__mark { width: 2rem; height: 2rem; }
.brand__name { font-size: var(--text-lg); }

.site-nav { min-width: 0; }

.site-nav__summary {
  display: inline-flex;
  align-items: center;
  min-height: var(--tap-min);
  padding-inline: var(--space-2);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  cursor: pointer;
  list-style: none;
  font-weight: 600;
}
.site-nav__summary::-webkit-details-marker { display: none; }

.site-nav__list {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  margin: var(--space-2) 0 0;
  padding: 0;
  list-style: none;
}
.site-nav__list a {
  display: flex;
  align-items: center;
  min-height: var(--tap-min);
  color: inherit;
  text-decoration: none;
}
.site-nav__list a[aria-current="page"] { color: var(--accent); font-weight: 600; }
.site-nav__list .button { color: var(--accent-contrast); }

/* Mobile: the panel is a full-width row under the header. */
.site-nav { flex-basis: 100%; order: 3; }
.site-nav[open] .site-nav__list { display: flex; }

@media (min-width: 64rem) {
  /* Desktop: no disclosure, the links are simply always there.
     A closed <details> hides its content through ::details-content, not through a rule on
     the child — `display: block` on the <nav> looks like it should work and does nothing.
     So the pseudo-element is what gets overridden here. assets/js/nav.js additionally sets
     the `open` attribute, which is what carries older browsers that predate
     ::details-content; without JS and without that pseudo-element the nav degrades to a
     working disclosure button, which is usable rather than broken. */
  .site-nav { flex-basis: auto; order: 0; }
  .site-nav__summary { display: none; }
  .site-nav::details-content { content-visibility: visible; block-size: auto; }
  .site-nav > nav { display: block; }
  .site-nav__list {
    flex-direction: row;
    flex-wrap: wrap;
    align-items: center;
    justify-content: flex-end;
    gap: var(--space-3);
    margin: 0;
  }
}

/* ── Service-area ticker ─────────────────────────────────────────────────────
   One strip of place names that slides at a constant speed. The run is printed twice in
   the markup and the track moves by exactly half its own width, so the second copy is
   already in the viewport when the first leaves it and the loop has no seam. That is why
   there is no script here: the seam is the only thing a script would be needed for.

   `--ticker-dur` is set by the theme, because the right duration depends on how wide the
   run renders in the face the theme picks, and a constant speed means the duration has to
   follow that width. The fallback keeps the strip moving if a theme forgets to set it. */

.site-ticker { overflow: hidden; margin-inline: calc(-1 * var(--gutter)); }

.site-ticker__track {
  display: flex;
  width: max-content;
  animation: ticker-run var(--ticker-dur, 30s) linear infinite;
}
.site-ticker__run { display: flex; margin: 0; white-space: nowrap; }

/* WCAG 2.2.2: moving content that starts on its own needs a way to stop it. The global
   prefers-reduced-motion block above is the standing one; focus is the keyboard reaching
   the same switch. Hover does NOT stop it, by instruction — a pointer crossing the strip
   on its way down the page was halting it for no reason the visitor asked for. */
.site-ticker:focus-within .site-ticker__track { animation-play-state: paused; }

@keyframes ticker-run {
  from { transform: translateX(0); }
  to { transform: translateX(-50%); }
}

/* ── Footer ──────────────────────────────────────────────────────────────── */

.site-footer {
  margin-top: var(--space-5);
  padding: var(--space-4) var(--gutter) var(--space-3);
  border-top: 1px solid var(--border);
  background: var(--bg-sunken);
  font-size: var(--text-sm);
}

.site-footer__grid {
  display: grid;
  gap: var(--space-3);
  max-width: var(--container);
  margin-inline: auto;
}
@media (min-width: 40rem) { .site-footer__grid { grid-template-columns: repeat(2, minmax(0, 1fr)); } }
@media (min-width: 64rem) { .site-footer__grid { grid-template-columns: 1.4fr repeat(4, minmax(0, 1fr)); } }

.site-footer__name { font-weight: 700; margin: 0 0 var(--space-1); }
.site-footer__meta, .site-footer__contact { color: var(--fg-muted); margin: 0 0 var(--space-1); }
.site-footer__heading { font-size: var(--text-sm); text-transform: uppercase; letter-spacing: 0.06em; color: var(--fg-muted); margin: 0 0 var(--space-1); }
.site-footer__group ul { list-style: none; margin: 0; padding: 0; }
.site-footer__group a,
.site-footer__legal a {
  display: flex;
  align-items: center;
  min-height: var(--tap-min);
  color: inherit;
  text-decoration: none;
}
.site-footer__group a:hover, .site-footer__legal a:hover { text-decoration: underline; }

.site-footer__bottom {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  justify-content: space-between;
  align-items: center;
  max-width: var(--container);
  margin: var(--space-3) auto 0;
  padding-top: var(--space-2);
  border-top: 1px solid var(--border);
  color: var(--fg-muted);
}
.site-footer__legal { display: flex; flex-wrap: wrap; gap: var(--space-2); list-style: none; margin: 0; padding: 0; }

/* ── Motion ──────────────────────────────────────────────────────────────── */

@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* ── Page furniture ──────────────────────────────────────────────────────── */

.page-hero {
  padding-block: var(--space-4) var(--space-3);
  border-bottom: 1px solid var(--border);
  background: var(--bg-sunken);
}
.page-hero__subtitle { font-size: var(--text-lg); color: var(--fg-muted); margin-block: 0 var(--space-1); }
.page-hero__tagline { font-weight: 600; margin-block: 0 var(--space-2); }
.page-hero__intro { max-width: var(--measure); font-size: var(--text-lg); margin-block: 0; }

.badge {
  display: inline-block;
  margin: 0 0 var(--space-2);
  padding: 0.2em 0.7em;
  border: 1px solid var(--accent);
  border-radius: 999px;
  color: var(--accent);
  font-size: var(--text-sm);
  font-weight: 600;
  letter-spacing: 0.03em;
  text-transform: uppercase;
}

.breadcrumb ol {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-1);
  margin: 0 0 var(--space-2);
  padding: 0;
  list-style: none;
  font-size: var(--text-sm);
  color: var(--fg-muted);
}
.breadcrumb li + li::before { content: "/"; margin-right: var(--space-1); color: var(--border); }
.breadcrumb a { color: inherit; }

/* ── Content sections ────────────────────────────────────────────────────── */

.site-main section { margin-block: var(--space-4); }

.prose > * + * { margin-block-start: var(--space-2); }
.prose h2 { margin-block-start: var(--space-4); }
.prose h3 { margin-block-start: var(--space-3); }
.prose ul, .prose ol { padding-inline-start: 1.4em; }
.prose li + li { margin-block-start: 0.4em; }

/* A markdown table arrives with no wrapper of its own, so it has to fit on its own.
   Do NOT reach for `display: block; overflow-x: auto` here — it was tried, and turning a
   table into a block box stops the cells wrapping, which pushed the comparison table on
   /services/ 36px past a 320px viewport. Auto layout plus wrappable cells is what fits. */
.prose table { width: 100%; border-collapse: collapse; }
.prose th, .prose td {
  padding: var(--space-1) var(--space-2);
  border-bottom: 1px solid var(--border);
  text-align: left;
  vertical-align: top;
  overflow-wrap: anywhere;
}
.prose th { font-weight: 600; }

/* ── Legal documents ─────────────────────────────────────────────────────── */

/* The effective date and version are the two things a reader needs to know which text
   they are looking at, so they sit under the heading rather than in a footer nobody
   scrolls to. Secondary weight: they inform, they are not the document. */
.legal__meta {
  margin-block-start: var(--space-2);
  color: var(--fg-muted);
  font-size: var(--text-sm);
  line-height: 1.6;
}

.legal__contact {
  margin-block-start: var(--space-4);
  padding-block-start: var(--space-3);
  border-top: 1px solid var(--border);
}

.card__meta { margin-block-start: var(--space-1) !important; color: var(--fg-muted) !important; font-size: var(--text-sm); }

/* ── Forms ───────────────────────────────────────────────────────────────── */

.estimate-form { margin-block-start: var(--space-3); max-width: var(--measure); }

.estimate-form__grid {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-2);
}
@media (min-width: 40rem) {
  .estimate-form__grid { grid-template-columns: 1fr 1fr; }
}

.field { margin: 0; }
.field label { display: block; font-weight: 600; margin-block-end: 0.35em; }

.field input,
.field select,
.field textarea {
  width: 100%;
  min-height: var(--tap-min);
  /* 16px minimum: iOS zooms the whole page when it focuses anything smaller, and the
     layout test asserts it. */
  font-size: var(--input-min-size);
  font-family: inherit;
  color: var(--fg);
  background: var(--bg-elevated);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: var(--space-1);
}
.field textarea { min-height: 6rem; resize: vertical; }

.field--check label { display: flex; gap: var(--space-1); align-items: flex-start; font-weight: 400; }
.field--check input { width: auto; min-height: 0; margin-block-start: 0.25em; }

.estimate-form__consent { color: var(--fg-muted); font-size: var(--text-sm); }
.estimate-form__consent p { margin: 0; }

.estimate-form__status:empty { display: none; }
.estimate-form__status { margin-block-start: var(--space-2); font-weight: 600; }
.estimate-form__status--error { color: #b3261e; }
@media (prefers-color-scheme: dark) {
  :root:not([data-theme="light"]) .estimate-form__status--error { color: #ff9a92; }
}
:root[data-theme="dark"] .estimate-form__status--error { color: #ff9a92; }

/* The honeypot. Clipped rather than display:none — some bots skip fields they can tell are
   hidden, and this one exists to be filled in by exactly those that do not look.

   The INPUT is constrained too, not only its wrapper. overflow:hidden clips what is
   painted, but getBoundingClientRect still reports the element's full box, so a
   default-width input inside a 1px wrapper reads as 183px hanging off the right edge —
   which is what the 320px overflow test caught. Do not remove these rules to "tidy up":
   put the field back the way it was and the test goes red again. */
.honeypot {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}
.honeypot input,
.honeypot label {
  width: 1px;
  height: 1px;
  min-height: 0;
  padding: 0;
  border: 0;
  font-size: 1px;
}

/* Available to any label that must exist for a screen reader and not on screen. */
.visually-hidden {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
}

.build-detail li + li { margin-block-start: 0.4em; }

/* ── FAQ and gallery ─────────────────────────────────────────────────────── */

.faq dt { font-weight: 600; margin-block-start: var(--space-3); }
.faq dd { margin: var(--space-1) 0 0; padding: 0; color: var(--fg-muted); }

.gallery {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr));
  gap: var(--space-2);
  margin: var(--space-3) 0 0;
  padding: 0;
  list-style: none;
}
.gallery figure { margin: 0; }
.gallery img { width: 100%; height: auto; border-radius: var(--radius); display: block; }
.gallery__caption { margin-block-start: var(--space-1); color: var(--fg-muted); font-size: var(--text-sm); }

.swatches {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(9rem, 1fr));
  gap: var(--space-2);
  margin: var(--space-3) 0 0;
  padding: 0;
  list-style: none;
}
.swatch { display: flex; flex-direction: column; gap: var(--space-1); }
.swatch img {
  width: 100%;
  aspect-ratio: 1;
  object-fit: cover;
  border-radius: var(--radius);
  border: 1px solid var(--border);
}
.swatch__name { font-size: var(--text-sm); color: var(--fg-muted); }

.build {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr));
  gap: var(--space-2);
  margin: var(--space-3) 0 0;
  padding: 0;
  list-style: none;
  counter-reset: build;
}
.build__step {
  counter-increment: build;
  padding: var(--space-2);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg-elevated);
}
.build__step h3 { font-size: var(--text-lg); margin-block: 0 var(--space-1); }
.build__step h3::before {
  content: counter(build) ". ";
  color: var(--accent);
}
.build__step p { margin: 0; color: var(--fg-muted); }

.specs { width: 100%; border-collapse: collapse; margin-top: var(--space-2); }
.specs th, .specs td { padding: var(--space-1) var(--space-2); border-bottom: 1px solid var(--border); text-align: left; vertical-align: top; }
.specs th { width: 40%; font-weight: 600; }
.specs td { color: var(--fg-muted); }

.cards {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(15rem, 1fr));
  gap: var(--space-2);
  margin: var(--space-3) 0 0;
  padding: 0;
  list-style: none;
}
.card {
  padding: var(--space-2);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  background: var(--bg-elevated);
}
.card h3 { font-size: var(--text-lg); margin-block: 0 var(--space-1); }
.card h3 a { text-decoration: none; }
.card p { margin: 0; color: var(--fg-muted); }
.card__price { margin-block-start: var(--space-1) !important; font-weight: 600; color: var(--fg) !important; }

.price { font-size: var(--text-xl); font-weight: 700; }

.cta {
  margin-block: var(--space-5) 0 !important;
  padding-block: var(--space-4);
  background: var(--bg-sunken);
  border-block: 1px solid var(--border);
}
.cta h2 { margin-block-start: 0; }
.cta p { max-width: var(--measure); }
.cta .button + .button { margin-inline-start: var(--space-1); }

.button--quiet {
  background: transparent;
  color: var(--fg);
  border: 1px solid var(--border);
}
