/* ============================================================
   KCR LANDSCAPING SERVICES — site.css

   "Turf & tarmac" system: a warm near-black canvas lifted straight
   out of the KCR embroidered patch, a faithful forest green for
   blocks and fills, and a brightened grass green for accents that
   have to survive on a dark background. Saira Condensed 900 uppercase
   display with a hard forest-green block highlight, IBM Plex Sans
   body, IBM Plex Sans Condensed tracked labels. Zero border-radius
   throughout; mower-stripe rules are the only background decoration.

   Deliberately NOT the "poured concrete + safety orange" skin used on
   Sunny Design Construction, and NOT the black/white Anton system on
   Affordable Repair & Renovations. The section skeleton is shared
   across all three; the skin is not.

   The three darkest surfaces (--loam, --peat, --soil) are sampled
   from the logo file itself, so the patch sits on the page without a
   visible seam around it.
   ============================================================ */

:root {
  /* Surfaces — dark. Sampled from the KCR patch backing. */
  --soil: #14150F;          /* deepest */
  --loam: #1A1B15;          /* section base */
  --peat: #21221B;          /* card */
  --moss: #2B2D23;          /* card hover / hairlines */

  /* Surfaces — light (inversions) */
  --chaff: #CFCBB6;
  --chaff-lt: #E8E4D5;
  --chaff-dk: #ABA692;

  /* Greens. Two of them, on purpose:
     --forest is the logo's own deep green, used for large blocks and
     fills that carry --bone text on top (5.7:1).
     --turf is that same hue pushed brighter, because the deep green
     is unreadable as small text on a near-black ground (1.9:1).
     Never use --forest for text on a dark surface. */
  --forest: #35682C;
  --forest-dk: #2A5323;
  --turf: #6DA83C;          /* 6.1:1 on --loam */
  --turf-dk: #5C9130;

  /* Text */
  --bone: #F2EFE2;
  --husk: #A8A492;          /* muted on dark — 7.3:1 on --loam */
  --husk-dk: #857F6E;
  --ink: #14150F;           /* text on light */
  --ink-mid: #4E4A3D;

  /* Type — Saira Condensed is far narrower than Archivo Black, so the
     display sizes below run noticeably larger to land the same visual
     mass on the page. */
  --font-display: 'Saira Condensed', 'Arial Narrow', 'Helvetica Neue', sans-serif;
  --font-sans: 'IBM Plex Sans', ui-sans-serif, system-ui, -apple-system, 'Segoe UI', Roboto, sans-serif;
  --font-cond: 'IBM Plex Sans Condensed', 'IBM Plex Sans', 'Arial Narrow', sans-serif;
  --track-wide: 0.24em;

  /* Layout */
  --page-max: min(92vw, 1680px);
  --gutter: clamp(20px, 3.2vw, 56px);

  /* Radius — this system is hard-edged on purpose */
  --r-btn: 0px;
  --r-card: 0px;
}

/* ---------- Reset ---------- */
*, *::before, *::after { box-sizing: border-box; }
html { scroll-behavior: smooth; }
/* Anchored sections stop clear of the fixed nav */
[id] { scroll-margin-top: 140px; }   /* clears the 126px nav bar */
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }
body {
  margin: 0;
  background: var(--loam);
  color: var(--husk);
  font-family: var(--font-sans);
  font-size: 16px;
  font-weight: 400;
  line-height: 1.55;
  -webkit-font-smoothing: antialiased;
  overflow-x: hidden;
}
img, video { display: block; max-width: 100%; }
h1, h2, h3, h4, p, ul, blockquote, figure { margin: 0; }
ul { padding: 0; list-style: none; }
a { color: inherit; text-decoration: none; }
button { font: inherit; color: inherit; background: none; border: 0; cursor: pointer; }
cite { font-style: normal; }

:focus-visible {
  outline: 3px solid var(--turf);
  outline-offset: 2px;
}

.container {
  max-width: var(--page-max);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  z-index: 100;
  background: var(--turf);
  color: var(--ink);
  font-weight: 600;
  padding: 12px 20px;
}
.skip-link:focus { left: 12px; top: 12px; }

/* ---------- Dither/hairline prevention (house rule) ----------
   Every large flat dark section = 2-stop gradient + noise overlay. */
.noise-overlay {
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='200' height='200'><filter id='n'><feTurbulence type='fractalNoise' baseFrequency='0.9' numOctaves='2' stitchTiles='stitch'/></filter><rect width='100%25' height='100%25' filter='url(%23n)' opacity='0.5'/></svg>");
  position: absolute;
  inset: 0;
  opacity: 0.035;
  mix-blend-mode: overlay;
  pointer-events: none;
}
.sec-loam {
  position: relative;
  background: linear-gradient(180deg, #20211A 0%, #1A1B15 55%, #17180F 100%);
}
.sec-soil {
  position: relative;
  background: linear-gradient(180deg, #1B1C16 0%, #14150F 60%, #101109 100%);
}
.sec-inner { position: relative; z-index: 1; }
@supports not (mix-blend-mode: overlay) {
  .noise-overlay { opacity: 0.02; }
}

/* ---------- Background decoration ----------
   Mower striping only — the alternating light/dark bands a ride-on
   leaves in cut turf. Shallow angle (-14deg) and two greens rather
   than the -45deg hazard chevron this skeleton shipped with; a steep
   chevron reads "construction site", which is the sibling site's job.
   A blueprint grid used to sit behind the dark sections; it read as a
   checkerboard and was removed. The sections carry their 2-stop
   gradient + noise overlay and nothing else. */
.turf-rule {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 14px;
  pointer-events: none;
  background-image: repeating-linear-gradient(
    -14deg,
    var(--forest) 0 26px,
    var(--forest-dk) 26px 52px
  );
}

/* ---------- Type voices ---------- */
.label {
  font-family: var(--font-cond);
  font-size: 14px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: var(--track-wide);
  color: var(--turf);
  margin-bottom: 18px;
}

/* Saira Condensed carries far less width per character than the Archivo
   Black this skeleton was drawn against, so the sizes run ~35% larger to
   land the same mass — and, being condensed, it still fits MORE words per
   line at that size. Headlines here can run longer than the sibling
   sites' before they wrap. */
.display {
  font-family: var(--font-display);
  font-weight: 900;
  text-transform: uppercase;
  color: var(--bone);
  /* loose enough that the .hl block clears the line above it */
  line-height: 1.1;
  letter-spacing: 0;
}
.display--lg { font-size: clamp(40px, 5.6vw, 92px); }
.display--md { font-size: clamp(31px, 4vw, 60px); }

/* The one display trick: a hard forest-green block behind the accent
   words — the same green field and bone lettering as the banner across
   the KCR patch, so the headline and the logo read as one system.

   Uses --forest, NOT --turf: the bright accent green with dark text on
   it reads like a highlighter pen next to the deep green in the patch.
   Deep green + --bone lettering is 5.7:1 and matches the badge.

   inline-block, NOT a plain inline: on an inline element the background
   paints over the font's content area, which spills out of the line box
   and collides with the line above. As an inline-block the box
   contributes its own height to the line box, so the lines push apart
   instead of overlapping, and the block height becomes ours to set via
   line-height + padding. */
.hl {
  display: inline-block;
  background: var(--forest);
  color: var(--bone);
  line-height: 1.04;
  padding: 0.1em 0.17em 0.14em;
  margin-top: 0.06em;   /* breathing room above the block */
}

.body-copy {
  font-weight: 400;
  font-size: 18px;
  line-height: 1.6;
  color: var(--husk);
}

/* ---------- Buttons ---------- */
.btn-primary {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  background: var(--turf);
  color: var(--ink);
  border-radius: var(--r-btn);
  padding: 17px 30px;
  font-size: 17px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  transition: background-color 0.2s ease;
}
.btn-primary:hover { background: #7FBF4A; }
.btn-primary .arr { transition: transform 0.2s ease; }
.btn-primary:hover .arr { transform: translateX(3px); }

.btn-ghost {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: 10px;
  background: transparent;
  color: var(--bone);
  border: 2px solid rgba(242, 239, 226, 0.45);
  border-radius: var(--r-btn);
  padding: 15px 28px;
  font-size: 17px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  transition: border-color 0.2s ease, background-color 0.2s ease;
}
.btn-ghost:hover { border-color: var(--turf); background: rgba(109, 168, 60, 0.1); }

.arrow-link {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  color: var(--bone);
  font-size: 17px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.03em;
  border-bottom: 2px solid var(--turf);
  padding: 9px 0 7px;   /* 44px tall */
  transition: color 0.2s ease;
}
.arrow-link:hover { color: var(--turf); }
.arrow-link .arr { transition: transform 0.2s ease; }
.arrow-link:hover .arr { transform: translateX(3px); }

/* Was Barlow Condensed 600 with 0.24em tracking — at this size the
   condensed cut read spindly, especially on phones. Full-width Barlow
   at 700 with tight tracking holds up far better. */
.pill-badge {
  display: inline-block;
  font-family: var(--font-sans);
  font-size: 16px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.05em;
  color: var(--ink);
  background: var(--turf);
  padding: 9px 18px;
}

/* ---------- Nav ----------
   Transparent at the top of the page (the big .hero-brand logo owns
   that space); goes solid past the hero, which also reveals the small
   .nav-brand logo in the bar. */
.nav {
  position: fixed;
  top: 0; left: 0; right: 0;
  z-index: 50;
  background: transparent;
  border-bottom: 2px solid transparent;
  transition: background-color 0.35s ease, border-color 0.35s ease;
}
.nav--solid {
  background: rgba(20, 21, 15, 0.94);
  backdrop-filter: blur(20px);
  -webkit-backdrop-filter: blur(20px);
  border-bottom-color: var(--turf);
}
.nav-inner {
  max-width: var(--page-max);
  margin-inline: auto;
  /* Padding is tight because the badge itself is what sets the bar
     height now — at 108px the old 14px padding made a 136px bar. */
  padding: 9px var(--gutter);
  display: grid;
  grid-template-columns: 1fr auto 1fr;
  align-items: center;
  gap: 24px;
}
.nav-brand {
  justify-self: start;
  opacity: 0;
  visibility: hidden;
  transition: opacity 0.3s ease, visibility 0s linear 0.3s;
}
.nav--solid .nav-brand {
  opacity: 1;
  visibility: visible;
  transition: opacity 0.3s ease;
}
/* Near-square badge (0.80:1), so height is doing the work of width: at
   46px tall it was only 37px wide and "LANDSCAPING SERVICES" was an
   illegible smudge. Sized so the full lockup actually reads.
   NOTE: .nav-brand is visibility:hidden (not display:none) until the bar
   goes solid, so it still occupies layout — the bar is this tall from
   first paint and nothing reflows when the logo fades in. */
.nav-brand img { display: block; height: 108px; width: auto; }
.nav-links { display: flex; align-items: center; gap: 4px; justify-self: center; }
.nav-link {
  position: relative;
  font-family: var(--font-cond);
  font-size: 17px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  padding: 10px 14px;
  color: var(--husk);
  transition: color 0.2s ease;
}
.nav-link::after {
  content: '';
  position: absolute;
  left: 14px;
  right: 14px;
  bottom: 4px;
  height: 3px;
  background: var(--turf);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.22s ease;
}
.nav-link:hover { color: var(--bone); }
.nav-link:hover::after,
.nav-link:focus-visible::after { transform: scaleX(1); }
/* Links sit on raw footage while the bar is transparent */
.nav:not(.nav--solid) .nav-link {
  color: #E8E4D5;
  text-shadow: 0 1px 10px rgba(0, 0, 0, 0.7);
}
.nav:not(.nav--solid) .nav-link:hover { color: var(--bone); }
/* Right-hand action pair. The wrapper is the grid child now (the nav is
   still `1fr auto 1fr`: brand / links / actions), so .nav-cta no longer
   positions itself. */
.nav-actions {
  justify-self: end;
  display: flex;
  align-items: center;
  gap: 14px;
}

/* Secondary: the phone number, outlined rather than filled so it does not
   compete with Book Now. Still a full-size tap target. */
.nav-call {
  display: inline-flex;
  align-items: center;
  border: 2px solid rgba(242, 239, 226, 0.32);
  color: var(--bone);
  padding: 10px 18px;
  font-size: 16px;
  font-weight: 700;
  letter-spacing: 0.02em;
  white-space: nowrap;
  transition: border-color 0.2s ease, color 0.2s ease;
}
.nav-call:hover { border-color: var(--turf); color: var(--turf); }

.nav-cta {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  background: var(--turf);
  color: var(--ink);
  padding: 12px 20px;
  font-size: 16px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.02em;
  white-space: nowrap;
  transition: background-color 0.2s ease;
}
.nav-cta:hover { background: #7FBF4A; }
.nav-cta .arr { font-size: 13px; }

/* 44x44 minimum: this is the primary mobile nav control. The bars stay
   24px wide; the box around them grows to a proper tap target. */
.menu-btn {
  display: none; flex-direction: column; align-items: center;
  justify-content: center; gap: 5px; padding: 11px 10px;
  min-width: 44px; min-height: 44px;
}
.menu-btn .bar {
  width: 24px; height: 2.5px;
  background: var(--bone);
  transition: transform 0.2s ease, opacity 0.2s ease;
}
.menu-btn[aria-expanded="true"] .bar:nth-child(1) { transform: translateY(7.5px) rotate(45deg); }
.menu-btn[aria-expanded="true"] .bar:nth-child(2) { opacity: 0; }
.menu-btn[aria-expanded="true"] .bar:nth-child(3) { transform: translateY(-7.5px) rotate(-45deg); }

.mobile-menu {
  position: fixed;
  inset: 0;
  z-index: 60; /* above the nav — the dialog owns the screen */
  background: rgba(20, 21, 15, 0.98);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 26px;
  opacity: 0;
  visibility: hidden;
  /* Closing: stay visible through the fade, then hide.
     Opening (.open): flip to visible immediately — a hidden element
     cannot take focus, and the dialog focuses its first link on open. */
  transition: opacity 0.25s ease, visibility 0s linear 0.25s;
}
.mobile-menu.open {
  opacity: 1;
  visibility: visible;
  transition: opacity 0.25s ease, visibility 0s linear 0s;
}
.mobile-menu a {
  font-family: var(--font-display);
  font-weight: 900;
  font-size: clamp(28px, 8vw, 40px);
  text-transform: uppercase;
  letter-spacing: -0.01em;
  color: var(--bone);
}
.mobile-menu .mobile-menu-cta {
  font-family: var(--font-sans);
  font-size: 16px;
  font-weight: 600;
  letter-spacing: 0.06em;
  background: var(--turf);
  color: var(--ink);
  padding: 15px 28px;
}
.menu-close {
  position: absolute;
  top: 18px;
  right: 20px;
  font-size: 38px;
  line-height: 1;
  color: var(--bone);
  padding: 10px;
}

/* ---------- Hero ---------- */
.hero {
  position: relative;
  min-height: 100svh;
  display: flex;
  align-items: center;
  overflow: hidden;
  background: var(--soil);
}
.hero-media { position: absolute; inset: 0; }
.hero-media video,
.hero-media .hero-poster {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  opacity: 0;
  transition: opacity 1s ease;
  /* Light grade only — the footage stays clearly visible */
  filter: saturate(1.02) contrast(1.05) brightness(1.04);
}
.hero-media video.active,
.hero-media .hero-poster.active { opacity: 1; }
/* Scrim is deliberately light: the clip should read as footage, not as a
   dark wash. Legibility is carried by the type itself (text-shadow below
   + the solid orange block on the headline), not by drowning the video. */
.hero-scrim {
  position: absolute;
  inset: 0;
  background:
    linear-gradient(90deg, rgba(20, 21, 15, 0.58) 0%, rgba(20, 21, 15, 0.2) 52%, rgba(20, 21, 15, 0.08) 100%),
    linear-gradient(180deg, rgba(20, 21, 15, 0.36) 0%, rgba(20, 21, 15, 0) 26%, rgba(20, 21, 15, 0) 62%, #1A1B15 100%);
  pointer-events: none;
}

/* Big page-top logo — parked over the hero, scrolls away with the page.
   Pinned to the viewport gutter (not the container line) so it stays
   clear of the centered nav links at every width. */
.hero-brand {
  position: absolute;
  z-index: 3;
  top: 20px;
  left: var(--gutter);
}
.hero-brand img {
  display: block;
  height: clamp(84px, 8.2vw, 138px);
  width: auto;
  filter: drop-shadow(0 2px 16px rgba(0, 0, 0, 0.6));
}
.hero-inner {
  position: relative;
  z-index: 2;
  width: 100%;
  max-width: var(--page-max);
  margin-inline: auto;
  padding: 130px var(--gutter) 100px;
  display: grid;
  grid-template-columns: minmax(0, 1fr) 420px;
  gap: clamp(36px, 5vw, 80px);
  align-items: center;
}
.hero-text { display: flex; flex-direction: column; align-items: flex-start; gap: 24px; }
/* Bright footage behind — the type carries its own contrast so the scrim
   can stay light. Two stacked shadows: a tight one for edge definition,
   a wide one to knock back whatever is directly behind the glyphs. */
.hero-title {
  text-shadow: 0 2px 10px rgba(20, 21, 15, 0.85), 0 4px 40px rgba(20, 21, 15, 0.75);
}
.hero-sub {
  text-shadow: 0 1px 6px rgba(20, 21, 15, 0.95), 0 2px 22px rgba(20, 21, 15, 0.8);
}
.hero-title {
  font-family: var(--font-display);
  font-weight: 900;
  /* capped so "LIKE IT'S OURS." holds one line beside the quote panel */
  font-size: clamp(42px, 4.8vw, 84px);
  line-height: 1.16;
  text-transform: uppercase;
  letter-spacing: -0.02em;
  color: var(--bone);
}
/* the orange block sits tight around the accent line */
.hero-title .hl { text-shadow: none; }
.hero-sub {
  font-weight: 400;
  font-size: 17.5px;
  line-height: 1.6;
  color: rgba(242, 239, 226, 0.95);
  max-width: 540px;
}
.hero-ctas {
  display: flex;
  align-items: center;
  gap: 14px;
  flex-wrap: wrap;
}

/* Credential badges under the hero CTAs. Their real job is on phones,
   where the stacked layout otherwise leaves a dead gap between the CTAs
   and the quote panel — but they earn their place on desktop too. */
.hero-badges {
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 1fr));
  gap: 10px;
  width: 100%;
  max-width: 520px;
  margin-top: 4px;
}
.hero-badges li {
  display: flex;
  align-items: center;
  gap: 10px;
  padding: 11px 14px;
  background: rgba(20, 17, 13, 0.62);
  backdrop-filter: blur(8px);
  -webkit-backdrop-filter: blur(8px);
  border: 1px solid rgba(242, 239, 226, 0.16);
  border-left: 4px solid var(--turf);
  font-family: var(--font-sans);
  font-size: 15px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.02em;
  line-height: 1.2;
  color: var(--bone);
}
.hero-badges svg {
  width: 21px;
  height: 21px;
  flex: none;
  color: var(--turf);
}

/* Quote panel */
.quote-panel {
  background: rgba(20, 17, 13, 0.8);
  backdrop-filter: blur(18px);
  -webkit-backdrop-filter: blur(18px);
  border: 2px solid rgba(242, 239, 226, 0.14);
  border-top: 5px solid var(--turf);
  padding: 26px 26px 24px;
}
.quote-label { margin-bottom: 8px; }
.quote-title {
  font-family: var(--font-display);
  font-weight: 900;
  font-size: 23px;
  line-height: 1.1;
  text-transform: uppercase;
  letter-spacing: -0.015em;
  color: var(--bone);
  margin-bottom: 16px;
}
.q-label {
  display: block;
  font-family: var(--font-cond);
  font-size: 13px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.18em;
  color: var(--husk);
  margin: 14px 0 6px;
}
.q-input {
  width: 100%;
  background: rgba(242, 239, 226, 0.07);
  border: 1px solid rgba(242, 239, 226, 0.18);
  border-radius: 0;
  color: var(--bone);
  font-family: var(--font-sans);
  font-size: 15px;
  padding: 13px 14px;   /* 47px tall — clears the 44px tap minimum */
  transition: border-color 0.2s ease;
}
.q-input:focus { outline: none; border-color: var(--turf); }
.q-input:focus-visible { outline: none; }
.q-input.q-invalid { border-color: #8AC756; }
.q-select {
  appearance: none;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' width='10' height='6'><path d='M0 0l5 6 5-6z' fill='%23FF5B04'/></svg>");
  background-repeat: no-repeat;
  background-position: right 14px center;
}
.q-select option { background: #21221B; color: var(--bone); }
.q-textarea {
  resize: vertical;
  min-height: 74px;
  line-height: 1.5;
}
.q-optional {
  text-transform: none;
  letter-spacing: 0.04em;
  color: var(--husk-dk);
}
.q-submit { width: 100%; margin-top: 20px; }
.q-note {
  margin-top: 12px;
  font-size: 13px;
  color: var(--husk-dk);
  text-align: center;
}
.q-error {
  margin-top: 12px;
  font-size: 13.5px;
  font-weight: 500;
  color: #9BD16B;
  text-align: center;
}

/* Post-submit panel — every contact route stays reachable by hand,
   because a sms:/mailto: draft does not open everywhere. */
.q-done[hidden] { display: none; }
.q-done-head {
  font-family: var(--font-display);
  font-weight: 900;
  font-size: 21px;
  line-height: 1.15;
  text-transform: uppercase;
  color: var(--bone);
  margin-bottom: 10px;
}
.q-done-copy {
  font-size: 14.5px;
  color: var(--husk);
  margin-bottom: 20px;
}
.q-done-actions { display: flex; flex-direction: column; gap: 12px; }
.q-copy { width: 100%; }
.q-copy.copied { background: var(--chaff); }
.q-done-link {
  display: block;
  text-align: center;
  border: 2px solid rgba(242, 239, 226, 0.28);
  padding: 12px 16px;
  font-family: var(--font-cond);
  font-size: 16px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--bone);
  transition: border-color 0.2s ease, color 0.2s ease;
}
.q-done-link:hover { border-color: var(--turf); color: var(--turf); }
.q-restart {
  display: block;
  margin: 18px auto 0;
  font-family: var(--font-cond);
  font-size: 15px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.14em;
  color: var(--husk-dk);
  padding: 6px;
}
.q-restart:hover { color: var(--bone); }

.hero-dots {
  position: absolute;
  left: 0; right: 0;
  bottom: 26px;
  display: flex;
  justify-content: center;
  gap: 10px;
  z-index: 3;
}
/* The visible mark is a 30x5 bar, but the button carries transparent
   padding so the actual tap target clears 44px. */
.hero-dot {
  width: 30px;
  height: 5px;
  padding: 20px 8px;
  background: rgba(242, 239, 226, 0.3);
  background-clip: content-box;
  box-sizing: content-box;
  transition: background-color 0.2s ease, transform 0.2s ease;
}
.hero-dot:hover { background: rgba(242, 239, 226, 0.7); background-clip: content-box; }
.hero-dot[aria-current="true"] {
  background: var(--turf);
  background-clip: content-box;
  transform: scaleY(1.6);
}
.hero.no-motion .hero-dots { display: none; }

/* ---------- Trust tag pills ---------- */
.trust-tags {
  margin-top: 28px;
  display: flex;
  flex-wrap: wrap;
  gap: 10px;
}
.trust-tags li {
  font-family: var(--font-cond);
  font-size: 14px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.16em;
  color: var(--bone);
  border: 2px solid rgba(242, 239, 226, 0.2);
  border-left: 4px solid var(--turf);
  padding: 8px 16px;
}

/* ---------- Services ---------- */
.services { overflow: hidden; }
.services .sec-inner { padding-block: clamp(80px, 10vw, 140px); }
.sec-head { text-align: center; margin-bottom: clamp(40px, 5vw, 64px); }
.sec-head .display { margin-bottom: 18px; }
.sec-sub { max-width: 620px; margin-inline: auto; }
.service-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 2px;
}
.service-card {
  position: relative;
  background: var(--peat);
  overflow: hidden;
  transition: background-color 0.25s ease;
}
.service-card::after {
  /* orange rule that draws in on hover */
  content: '';
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 4px;
  background: var(--turf);
  transform: scaleX(0);
  transform-origin: left;
  transition: transform 0.35s ease;
}
.service-card:hover { background: var(--moss); }
.service-card:hover::after { transform: scaleX(1); }
.service-media {
  aspect-ratio: 3 / 2;
  overflow: hidden;
}
.service-media img {
  width: 100%; height: 100%;
  object-fit: cover;
  transition: transform 0.9s ease;
}
.service-card:hover .service-media img { transform: scale(1.05); }
.service-body { padding: 26px 28px 34px; }
.service-body .num {
  font-family: var(--font-display);
  font-weight: 900;
  font-size: 15px;
  letter-spacing: 0.04em;
  color: var(--turf);
  margin-bottom: 12px;
}
.card-title {
  font-family: var(--font-display);
  font-weight: 900;
  font-size: 20px;
  line-height: 1.12;
  text-transform: uppercase;
  letter-spacing: -0.01em;
  color: var(--bone);
  margin-bottom: 12px;
}
.service-body p:not(.num) {
  font-size: 15px;
  line-height: 1.6;
  color: var(--husk);
}
.services-more { text-align: center; margin-top: 34px; display: none; }

/* ---------- About / photo band ---------- */
.about-band {
  position: relative;
  min-height: min(92vh, 800px);
  display: flex;
  align-items: flex-end;
  overflow: hidden;
  background: var(--loam);
}
.about-bg {
  position: absolute;
  inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
}
.about-scrim {
  position: absolute;
  inset: 0;
  background:
    linear-gradient(180deg, #1A1B15 0%, rgba(26, 27, 21, 0.12) 26%, rgba(20, 21, 15, 0.74) 74%, #1A1B15 100%),
    linear-gradient(90deg, rgba(20, 21, 15, 0.86) 0%, rgba(20, 21, 15, 0.4) 44%, rgba(20, 21, 15, 0.04) 72%);
}
.about-content {
  position: relative;
  z-index: 1;
  width: 100%;
  max-width: var(--page-max);
  margin-inline: auto;
  padding: clamp(64px, 9vw, 120px) var(--gutter);
}
.about-content .display { margin-bottom: 22px; }
.about-copy {
  max-width: 560px;
  margin-bottom: 28px;
  color: rgba(243, 240, 234, 0.94);
  text-shadow: 0 1px 12px rgba(0, 0, 0, 0.6);
}

/* ---------- Reviews carousel ----------
   Six cards, three in view at a time, paged by arrows or dots. Same
   scroll-snap mechanics as the work gallery so both behave identically. */
.reviews { overflow: hidden; }
.reviews .sec-inner { padding-block: clamp(80px, 10vw, 140px); }
.reviews-carousel { position: relative; }
.reviews-track {
  display: flex;
  gap: 16px;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  padding-bottom: 6px;
  scrollbar-width: thin;
  scrollbar-color: var(--turf) transparent;
}
.review-card {
  flex: 0 0 calc((100% - 32px) / 3);   /* three across, two 16px gaps */
  scroll-snap-align: start;
  display: flex;
  flex-direction: column;
  background: var(--peat);
  border-top: 4px solid var(--turf);
  padding: 30px 30px 28px;
}
/* Chip marking a card that still holds placeholder copy. Delete the
   element (not just the text) once a real review goes in. */
.rv-placeholder {
  align-self: flex-start;
  font-family: var(--font-cond);
  font-size: 12px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.18em;
  color: var(--ink);
  background: var(--chaff-dk);
  padding: 4px 10px;
  margin-bottom: 18px;
}
.rv-quote { flex: 1; quotes: "“" "”"; }
.rv-quote p {
  font-size: 16.5px;
  line-height: 1.62;
  color: var(--husk);
}
.rv-quote p::before { content: open-quote; }
.rv-quote p::after  { content: close-quote; }
.rv-cite {
  display: block;
  margin-top: 24px;
  padding-top: 18px;
  border-top: 1px solid rgba(242, 239, 226, 0.12);
}
.rv-name {
  display: block;
  font-family: var(--font-display);
  font-weight: 900;
  font-size: 16px;
  text-transform: uppercase;
  letter-spacing: -0.01em;
  color: var(--bone);
}
.rv-meta {
  display: block;
  margin-top: 5px;
  font-family: var(--font-cond);
  font-size: 13px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: var(--track-wide);
  color: var(--husk-dk);
}
/* Arrows sit in the control row under the track, not floating over the
   first and last card — at this container width there is no outside
   margin left to park them in. */
.rv-controls {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 18px;
  margin-top: 30px;
}
.rv-btn {
  width: 46px;
  height: 46px;
  flex: none;
  border: 2px solid var(--turf);
  background: transparent;
  color: var(--bone);
  font-size: 18px;
  transition: background-color 0.2s ease, color 0.2s ease;
}
.rv-btn:hover { background: var(--turf); color: var(--ink); }
html:not(.js) .rv-controls { display: none; }

.rv-dots {
  display: flex;
  justify-content: center;
  gap: 10px;
}
.rv-dot {
  width: 34px;
  height: 5px;
  padding: 14px 6px;
  background: rgba(242, 239, 226, 0.25);
  background-clip: content-box;
  box-sizing: content-box;
  transition: background-color 0.2s ease;
}
.rv-dot:hover { background: rgba(242, 239, 226, 0.6); background-clip: content-box; }
.rv-dot[aria-current="true"] { background: var(--turf); background-clip: content-box; }

/* ---------- Work gallery ---------- */
.worklog { overflow: hidden; }
.worklog .sec-inner { padding-block: clamp(80px, 10vw, 140px); }
.gallery { position: relative; }
.gallery-track {
  display: flex;
  gap: 2px;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  padding-bottom: 10px;
  scrollbar-width: thin;
  scrollbar-color: var(--turf) transparent;
}
.gallery-item {
  flex: 0 0 clamp(290px, 35vw, 500px);
  scroll-snap-align: start;
  margin: 0;
}
.gallery-zoom {
  display: block;
  width: 100%;
  padding: 0;
  overflow: hidden;
  cursor: zoom-in;
  background: var(--peat);
}
.gallery-zoom img {
  width: 100%;
  aspect-ratio: 3 / 2;
  object-fit: cover;
  transition: transform 0.9s ease;
}
.gallery-zoom:hover img { transform: scale(1.05); }
.gallery-item figcaption {
  margin-top: 14px;
  padding-right: 12px;
  font-size: 15px;
  color: var(--husk);
}
.job-type {
  display: block;
  font-family: var(--font-cond);
  font-size: 13px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: var(--track-wide);
  color: var(--turf);
  margin-bottom: 4px;
}
.gal-btn {
  position: absolute;
  top: calc(50% - 24px);
  transform: translateY(-50%);
  z-index: 2;
  width: 46px;
  height: 46px;
  border: 2px solid var(--turf);
  background: rgba(20, 21, 15, 0.85);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  color: var(--bone);
  font-size: 18px;
  transition: background-color 0.2s ease, color 0.2s ease;
}
.gal-btn:hover { background: var(--turf); color: var(--ink); }
.gal-prev { left: -10px; }
.gal-next { right: -10px; }
html:not(.js) .gal-btn { display: none; }

/* Lightbox */
.lightbox {
  position: fixed;
  inset: 0;
  z-index: 70;
  background: rgba(15, 13, 10, 0.95);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: clamp(16px, 4vw, 48px);
}
.lightbox[hidden] { display: none; }
.lightbox-figure { margin: 0; max-width: min(1100px, 92vw); }
.lightbox-figure img {
  max-width: 100%;
  max-height: 76vh;
  margin-inline: auto;
  border-bottom: 5px solid var(--turf);
}
.lightbox-figure figcaption {
  margin-top: 18px;
  text-align: center;
  font-family: var(--font-cond);
  font-size: 15px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: var(--track-wide);
  color: var(--bone);
}
.lightbox-close {
  position: absolute;
  top: 16px;
  right: 20px;
  font-size: 38px;
  line-height: 1;
  color: var(--bone);
  padding: 10px;
  z-index: 2;
}
.lightbox-nav {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  width: 48px;
  height: 48px;
  border: 2px solid var(--turf);
  background: rgba(20, 21, 15, 0.7);
  color: var(--bone);
  font-size: 18px;
  z-index: 2;
  transition: background-color 0.2s ease, color 0.2s ease;
}
.lightbox-nav:hover { background: var(--turf); color: var(--ink); }
.lightbox-prev { left: clamp(8px, 2vw, 28px); }
.lightbox-next { right: clamp(8px, 2vw, 28px); }

.log-note {
  max-width: 900px;
  margin: 28px auto 0;
  text-align: center;
  font-size: 14.5px;
  color: var(--husk-dk);
}

/* ---------- CTA band ---------- */
.cta-band {
  position: relative;
  min-height: min(78vh, 680px);
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  overflow: hidden;
  background: var(--soil);
}
.cta-band video {
  position: absolute;
  inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
  filter: saturate(1) contrast(1.04) brightness(1.06);
}
.cta-scrim {
  position: absolute;
  inset: 0;
  /* light enough that the aerial actually reads as Florida rooftops */
  background:
    linear-gradient(180deg, #1A1B15 0%, rgba(20, 21, 15, 0.5) 24%, rgba(20, 21, 15, 0.5) 76%, #14150F 100%);
}
.cta-content {
  position: relative;
  z-index: 1;
  padding: 100px var(--gutter);
}
/* Label sits on moving mid-tone footage — orange loses too much
   contrast there, so this one goes bone with a shadow */
.cta-content .label {
  color: var(--bone);
  text-shadow: 0 1px 12px rgba(0, 0, 0, 0.9);
}
.cta-content .display {
  text-shadow: 0 2px 30px rgba(0, 0, 0, 0.6);
  margin-bottom: 34px;
}
.cta-content .display .hl { text-shadow: none; }
.cta-ctas { justify-content: center; }

/* ---------- Footer ---------- */
.footer {
  position: relative;
  background: linear-gradient(180deg, #161710 0%, #101108 55%, #0E0F0A 100%);
  padding: clamp(64px, 8vw, 100px) 0 0;
}
.footer-inner {
  position: relative;
  z-index: 1;
  max-width: var(--page-max);
  margin-inline: auto;
  padding-inline: var(--gutter);
}
/* The services column carries all sixteen services in two sub-columns, so
   it needs roughly double the width of the contact/area columns — at an
   even 1fr each sub-column lands near 110px and every second entry wraps. */
.footer-grid {
  display: grid;
  grid-template-columns: 1.15fr 2fr 1.05fr 1.05fr;
  gap: 40px;
  padding-bottom: 56px;
}
/* Between ~769 and 1150 the four-column footer squeezes the two service
   sub-columns to ~110px and half the entries wrap. Drop to a 2-up footer
   early and let the services block take a full row instead. */
@media (max-width: 1150px) {
  .footer-grid { grid-template-columns: 1fr 1fr; }
  .footer-services { grid-column: 1 / -1; }
}

.footer-logo { display: inline-block; }
.footer-logo img { display: block; height: 78px; width: auto; }
.footer-brand p {
  margin-top: 20px;
  font-size: 14.5px;
  line-height: 1.65;
  color: var(--husk-dk);
  max-width: 310px;
}
.footer h4 {
  font-family: var(--font-cond);
  font-size: 14px;
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: var(--track-wide);
  color: var(--turf);
  margin-bottom: 18px;
}
.footer li { margin-bottom: 2px; font-size: 14.5px; }
/* inline-block + padding so each footer link is a comfortable tap target */
.footer li a,
.footer li span {
  display: inline-block;
  padding: 8px 0;
}
/* Sixteen services is a tall single column next to three short ones, which
   leaves a dead gap across the rest of the footer. Flow it into two columns
   so the block is ~8 rows and the four columns roughly agree in height.
   `break-inside: avoid` stops a link splitting across the column boundary. */
.footer-services ul { columns: 2; column-gap: 28px; }
.footer-services li { break-inside: avoid; }

.footer li a { color: var(--husk); transition: color 0.2s ease; }
.footer li a:hover { color: var(--turf); }
.footer li span { color: var(--husk-dk); }
.footer-bottom {
  display: flex;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 10px;
  padding: 24px 0 28px;
  border-top: 1px solid rgba(242, 239, 226, 0.1);
  font-family: var(--font-cond);
  font-size: 14px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: var(--husk-dk);
}

/* ---------- Mobile sticky CTAs ----------
   Two free-standing buttons, not a docked panel — they float over the
   page, hide while the hero is on screen, come back past it, and duck
   away again over the footer. */
.mobile-bar {
  position: fixed;
  left: 0; right: 0; bottom: 0;
  z-index: 45;
  display: none;
  gap: 10px;
  background: transparent;
  border-top: 0;
  padding: 0 14px calc(16px + env(safe-area-inset-bottom));
  pointer-events: none; /* only the buttons themselves are clickable */
  visibility: visible;
  transition: transform 0.3s ease, opacity 0.3s ease, visibility 0s 0s;
}
/* visibility:hidden pulls the off-screen buttons out of the tab order */
.mobile-bar.hidden-bar {
  transform: translateY(140%);
  opacity: 0;
  visibility: hidden;
  transition: transform 0.3s ease, opacity 0.3s ease, visibility 0s 0.3s;
}
.mobile-bar a {
  flex: 1;
  pointer-events: auto;
  text-align: center;
  padding: 17px 0;
  font-family: var(--font-sans);
  font-size: 18px;
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.02em;
  /* each button carries its own surface + shadow now that there is no
     bar behind them to sit on */
  box-shadow: 0 10px 30px rgba(0, 0, 0, 0.55);
}
.mobile-bar .mb-call {
  flex: 1.35;
  background: var(--turf);
  color: var(--ink);
}
.mobile-bar .mb-text {
  background: rgba(20, 21, 15, 0.94);
  backdrop-filter: blur(12px);
  -webkit-backdrop-filter: blur(12px);
  border: 2px solid var(--turf);
  color: var(--bone);
}

/* ---------- Reveal on scroll ----------
   Hidden state is gated on .js so content renders without JavaScript. */
.js .reveal {
  opacity: 0;
  transform: translateY(22px);
  transition: opacity 0.85s cubic-bezier(0.455, 0.03, 0.515, 0.955),
              transform 0.85s cubic-bezier(0.455, 0.03, 0.515, 0.955);
}
.js .reveal.in { opacity: 1; transform: none; }
@media (prefers-reduced-motion: reduce) {
  .js .reveal { opacity: 1; transform: none; transition: none; }
  .hero-media video, .hero-media .hero-poster { transition: none; }
  .gallery-track { scroll-snap-type: none; }
}

/* ---------- Responsive ---------- */
@media (max-width: 1100px) {
  .hero-inner { grid-template-columns: minmax(0, 1fr) 340px; }
}

@media (max-width: 1024px) {
  .service-grid { grid-template-columns: repeat(2, 1fr); }
}

@media (max-width: 900px) {
  /* On phones the 92vw page-max and the gutter were BOTH insetting the
     content (~35px a side), leaving everything in a narrow column. Let
     the gutter alone do the work here. */
  :root { --page-max: 100vw; }

  /* two reviews in view on tablets */
  .review-card { flex-basis: calc((100% - 16px) / 2); }

  /* Everything starts ~20px lower on phones — the nav logo was sitting
     tight against the top edge (and under notches/status bars). */
  .nav-inner {
    display: flex;
    gap: 16px;
    padding-top: calc(11px + env(safe-area-inset-top));
    padding-bottom: 11px;
  }
  [id] { scroll-margin-top: 146px; }
  .nav-brand { margin-right: auto; }
  /* At 42px the badge was 34px wide and unreadable on a phone. */
  .nav-brand img { height: 100px; }
  .nav-links { display: none; }
  /* The number is in the burger and on the sticky bottom bar, so the nav
     keeps only the booking action — the bar is not wide enough for both
     alongside a 100px badge and a 44px burger. */
  .nav-call { display: none; }
  .nav-actions { gap: 10px; }
  /* Over the hero the booking button is redundant — the hero carries its
     own CTA and the sticky bottom bar takes over past it — and it crowded
     the burger. Hold it back and fade it in with the badge, so the logo,
     this button and the bottom bar all arrive on one transition when the
     bar goes solid. visibility (not display) keeps it in the grid, so the
     burger does not shift when it appears, and pulls it out of the tab
     order while hidden. The burger itself stays visible throughout. */
  .nav-cta {
    padding: 11px 15px;
    font-size: 15px;
    opacity: 0;
    visibility: hidden;
    transition: opacity 0.3s ease, visibility 0s linear 0.3s;
  }
  .nav--solid .nav-cta {
    opacity: 1;
    visibility: visible;
    transition: opacity 0.3s ease;
  }
  .menu-btn { display: flex; margin-left: 0; }
  /* No-JS fallback: the hamburger does nothing without JS, so hide it
     and keep the call CTA reachable in the bar instead. */
  html:not(.js) .menu-btn { display: none; }
  html:not(.js) .nav-call { display: inline-flex; }

  /* First screen = headline block up top, clean footage below it;
     the quote panel starts past the fold. Row 1 fills the initial
     viewport (206px = hero paddings); vh line is the no-svh fallback. */
  .hero-inner {
    grid-template-columns: 1fr;
    grid-template-rows: minmax(calc(100vh - 336px), auto) auto;
    grid-template-rows: minmax(calc(100svh - 336px), auto) auto;
    align-items: start;
    padding-top: 246px; /* clears the doubled .hero-brand above it */
    padding-bottom: 90px;
    gap: 48px;
  }
  .quote-panel { max-width: 480px; width: 100%; justify-self: center; }
  /* fills the dead space the stacked hero used to leave under the CTAs */
  .hero-badges { max-width: none; margin-top: 10px; }

  /* Services collapse (JS adds .collapsed; without JS all six show) */
  .service-grid.collapsed .service-card:nth-child(n + 4) { display: none; }
  .services-more { display: block; }

  /* Links are in the burger now — the big logo gets the top back */
  /* Doubled. Pulled up to 26px so the bigger badge does not eat the
     whole first screen; .hero-inner padding-top below is what keeps the
     headline clear of it (26 + 184 = 210, so 246 leaves a real gap). */
  .hero-brand { top: calc(26px + env(safe-area-inset-top)); }
  .hero-brand img { height: 184px; }
  .gallery-item { flex-basis: min(86vw, 420px); }
}

@media (max-width: 768px) {
  .mobile-bar { display: flex; }
  .footer { padding-bottom: 82px; } /* clear the sticky bar */
  .hero-sub { font-size: 16.5px; }
  /* Phones: only as much wash as the text block actually needs, then
     clear through the middle so the footage reads on the opening screen */
  .hero-scrim {
    background:
      linear-gradient(180deg, rgba(20, 21, 15, 0.5) 0%, rgba(20, 21, 15, 0.34) 30%, rgba(20, 21, 15, 0.06) 56%, rgba(20, 21, 15, 0.24) 80%, #1A1B15 100%);
  }
  .about-scrim {
    background:
      linear-gradient(180deg, #1A1B15 0%, rgba(26, 27, 21, 0.3) 24%, rgba(20, 21, 15, 0.82) 68%, #1A1B15 100%);
  }
  .gal-btn { display: none; } /* touch: swipe the track instead */

  /* ---- Reviews on phones ----
     One card at a time, but sized so the next one peeks in at the edge:
     a flush 100% card gives no hint that the track scrolls at all. */
  .reviews-track { gap: 12px; }
  .review-card {
    flex-basis: 86%;
    padding: 26px 24px 24px;
  }
  .rv-quote p { font-size: 16px; }

  /* Six pages means six dots — at full size the pager overflowed the
     container and clipped the arrows off both edges. Shrink it to fit. */
  .rv-controls { gap: 12px; margin-top: 24px; }
  .rv-btn { width: 44px; height: 44px; }
  .rv-dots { gap: 6px; }
  /* The visible dot stays 9px; the padded hit area is what grows.
     Full 44px width per dot would overflow the row, so height carries
     the tap target and the gap keeps neighbours from being mis-hit. */
  .rv-dot {
    width: 9px;
    height: 5px;
    padding: 19px 6px;
  }

  /* keep the trailing note clear of the floating call/estimate buttons */
  .reviews .log-note { margin-bottom: 56px; }
  .footer-grid { grid-template-columns: 1fr 1fr; }
  .footer-services { grid-column: 1 / -1; }
}

@media (max-width: 560px) {
  .hero-brand img { height: 148px; }
  /* Row 1 fills the first screen, so the subtraction has to track the
     paddings actually in force here (206 top + 90 bottom), not the
     336 the >560 block subtracts. */
  .hero-inner {
    padding-top: 206px;
    grid-template-rows: minmax(calc(100vh - 296px), auto) auto;
    grid-template-rows: minmax(calc(100svh - 296px), auto) auto;
  }
  /* Scale the headline to the phone so it holds two lines, not three */
  .hero-title { font-size: clamp(29px, 8.4vw, 44px); }
  .footer-logo img { height: 64px; }
  .footer li a,
  .footer li span { padding: 11px 0; }  /* 44px tap target */
  .footer-services ul { columns: 1; }
  .service-grid { grid-template-columns: 1fr; }
  .footer-grid { grid-template-columns: 1fr; gap: 32px; }
  .hero-ctas { flex-direction: column; align-items: stretch; width: 100%; }
  .hero-ctas .btn-primary, .hero-ctas .btn-ghost { width: 100%; }
  .cta-ctas { align-items: center; }
  .quote-panel { max-width: none; }
}
