:root {
  --ink: #f5f1e8;
  --ink-dim: rgba(245, 241, 232, 0.65);
  --bg: #07060a;
  --bg-2: #0e0c11;
  --accent: #e0a458;      /* warm amber/gold */
  --accent-bright: #f4c07a;
  --line: rgba(224, 164, 88, 0.22);

  /* Cream palette — used by a handful of sections (see the "Cream section
     override" block further down) to break up a site that read as too uniformly
     dark end-to-end. Kept in the same warm family as --ink/--accent rather than
     a neutral white, so it still feels like the same brand, just inverted. */
  --cream: #f4ede1;
  --cream-2: #e8dcc5;      /* deeper tone for cards/components nested inside a cream section */
  --cream-ink: #211a12;
  --cream-ink-dim: rgba(33, 26, 18, 0.68);
  --cream-line: rgba(33, 26, 18, 0.14);
  --cream-accent: #9c6a28;        /* darker bronze than --accent — the light amber reads too pale on a light bg */
  --cream-accent-bright: #7d5420; /* hover goes darker on a light bg, mirroring how it goes brighter on dark */

  /* Spacing scale - borrowed from antigravity.google's real 12-step token system
     (4/8/16/24/36/48/60/80/88/120/180px), applied to section rhythm + card padding
     instead of ad hoc one-off pixel values. */
  --space-xs: 4px;
  --space-sm: 8px;
  --space-md: 16px;
  --space-lg: 24px;
  --space-xl: 36px;
  --space-2xl: 48px;
  --space-3xl: 60px;
  --space-4xl: 80px;
  --space-5xl: 88px;
  --space-6xl: 120px;
  --space-7xl: 180px;
}

* { margin: 0; padding: 0; box-sizing: border-box; }
html { scrollbar-width: none; }
html::-webkit-scrollbar { display: none; }

body {
  background: var(--bg);
  color: var(--ink);
  font-family: "Inter", system-ui, sans-serif;
  overflow-x: hidden;
}

h1, h2, h3 { font-family: "Playfair Display", Georgia, serif; }

/* ---------- Accessibility: focus states + reduced motion ----------
   Added after a ui-ux-pro-max review: the site had zero visible focus
   indicators outside the contact form, and no motion accommodation despite
   being unusually animation-heavy (3 pinned video-scrubs, glow-card cursor
   tracking, blinking cursor). */
.sr-only {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

a:focus-visible,
button:focus-visible,
input:focus-visible {
  outline: 2px solid var(--accent-bright);
  outline-offset: 3px;
  border-radius: 4px;
}
.nav-cta:focus-visible,
.btn-primary:focus-visible,
.cta-group .btn-secondary:focus-visible,
.contact-card:focus-visible,
.estimate-form button:focus-visible {
  outline: 2px solid var(--accent-bright);
  outline-offset: 3px;
}
.estimate-form input:focus-visible {
  outline: 2px solid var(--accent-bright);
  outline-offset: 2px;
  border-color: var(--accent);
}

@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;
  }
  .scroll-hint .cursor { animation: none; opacity: 1; }
  .glow-card { background-image: none; }
  .glow-card::before, .glow-card::after { display: none; }
}

/* ---------- Nav ---------- */
.nav {
  position: fixed;
  top: 18px; left: 18px; right: 18px;
  z-index: 50;
  display: flex;
  justify-content: space-between;
  align-items: center;
  padding: 12px 22px;
  font-size: 15px;
  letter-spacing: 0.2em;
  text-transform: uppercase;
  border-radius: 999px;
  background: rgba(10, 8, 6, 0.5);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  border: 1px solid rgba(224, 164, 88, 0.18);
}
.nav-brand { display: flex; align-items: center; gap: 14px; font-weight: 600; text-decoration: none; color: var(--ink); }
.nav-brand .dim { color: var(--accent); margin: 0 4px; }
.nav-logo { width: 60px; height: 60px; border-radius: 50%; display: block; }
.nav-cta {
  color: #1a1408;
  background: var(--accent);
  padding: 13px 26px;
  border-radius: 999px;
  text-decoration: none;
  font-family: "JetBrains Mono", monospace;
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  font-size: 12px;
  box-shadow: 0 0 24px rgba(224, 164, 88, 0.35);
  transition: transform 0.2s, box-shadow 0.2s;
}
.nav-cta:hover { transform: translateY(-1px); box-shadow: 0 0 32px rgba(224, 164, 88, 0.55); }

.nav-links { display: flex; align-items: center; gap: 28px; list-style: none; margin: 0; padding: 0; }
.nav-links a { color: var(--ink-dim); text-decoration: none; font-size: 12px; letter-spacing: 0.14em; transition: color 0.2s ease; }
.nav-links a:hover { color: var(--accent); }

/* Hamburger toggle, hidden on desktop, shown only under the mobile breakpoint (see
   the @media block below). Bars animate into an X via the aria-expanded attribute,
   which nav-toggle.js flips on click, so the visual state always matches what a
   screen reader is told. */
.nav-toggle {
  display: none;
  flex-direction: column;
  justify-content: center;
  align-items: center;
  gap: 5px;
  width: 34px; height: 34px;
  background: transparent;
  border: none;
  cursor: pointer;
  padding: 0;
  flex-shrink: 0;
}
.nav-toggle-bar { width: 20px; height: 2px; background: var(--ink); transition: transform 0.25s ease, opacity 0.25s ease; }
.nav-toggle[aria-expanded="true"] .nav-toggle-bar:nth-child(1) { transform: translateY(7px) rotate(45deg); }
.nav-toggle[aria-expanded="true"] .nav-toggle-bar:nth-child(2) { opacity: 0; }
.nav-toggle[aria-expanded="true"] .nav-toggle-bar:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }

/* Mobile dropdown panel — a separate floating panel below the nav pill (not part
   of the pill itself), shown/hidden via the .open class toggled by JS. Present in
   the DOM at all viewport widths but forced display:none outside the mobile
   breakpoint below, so it can never accidentally show on desktop. */
.nav-mobile {
  display: none;
  position: fixed;
  top: 86px; left: 18px; right: 18px;
  z-index: 49;
  flex-direction: column;
  background: rgba(10, 8, 6, 0.94);
  backdrop-filter: blur(14px);
  -webkit-backdrop-filter: blur(14px);
  border: 1px solid rgba(224, 164, 88, 0.18);
  border-radius: 20px;
  padding: 8px;
  opacity: 0;
  transform: translateY(-10px);
  pointer-events: none;
  transition: opacity 0.25s ease, transform 0.25s ease;
}
.nav-mobile.open { opacity: 1; transform: translateY(0); pointer-events: auto; }
.nav-mobile a {
  color: var(--ink);
  text-decoration: none;
  padding: 15px 16px;
  font-size: 13px;
  letter-spacing: 0.1em;
  text-transform: uppercase;
  border-bottom: 1px solid rgba(245, 241, 232, 0.08);
}
.nav-mobile a:last-child { border-bottom: none; }
.nav-mobile-cta {
  margin-top: 6px;
  text-align: center;
  background: var(--accent);
  color: #1a1408 !important;
  border-radius: 12px;
  font-weight: 600;
}

/* ---------- Cinematic scrub sections ---------- */
.cinematic { position: relative; height: 480vh; }
.sticky {
  position: sticky;
  top: 0; height: 100vh; width: 100%;
  overflow: hidden;
  display: grid; place-items: center;
  background: #050408;
}
.sticky canvas {
  position: absolute; inset: 0;
  width: 100%; height: 100%;
  object-fit: cover;
}
.vignette {
  position: absolute; inset: 0;
  pointer-events: none;
  background:
    radial-gradient(120% 90% at 50% 45%, transparent 40%, rgba(0,0,0,0.68) 100%),
    linear-gradient(180deg, rgba(0,0,0,0.5) 0%, transparent 22%, transparent 68%, rgba(0,0,0,0.75) 100%);
}

.overlay { position: relative; z-index: 10; text-align: center; padding: 0 24px; }
.reveal-line {
  position: absolute;
  left: 50%; top: 50%;
  transform: translate(-50%, -50%);
  width: max-content; max-width: 90vw;
  opacity: 0;
  will-change: opacity, transform;
}
h1.reveal-line {
  font-weight: 600;
  font-size: clamp(2.6rem, 8vw, 6.5rem);
  letter-spacing: 0.01em;
  line-height: 1.05;
  color: var(--ink);
  text-shadow: 0 2px 8px rgba(0,0,0,0.75), 0 8px 40px rgba(0,0,0,0.65), 0 0 60px rgba(224, 164, 88, 0.2);
}
h2.reveal-line {
  font-weight: 600;
  font-size: clamp(1.9rem, 5.5vw, 3.6rem);
  line-height: 1.15;
  color: var(--ink);
  text-shadow: 0 2px 8px rgba(0,0,0,0.75), 0 8px 40px rgba(0,0,0,0.65);
}
.reveal-line.sub {
  font-family: "Inter", sans-serif;
  font-weight: 400;
  font-size: clamp(1rem, 2.4vw, 1.5rem);
  line-height: 1.5;
  letter-spacing: 0.02em;
  color: var(--ink);
  text-shadow: 0 2px 6px rgba(0,0,0,0.8), 0 6px 30px rgba(0,0,0,0.7);
  max-width: 46rem;
}
/* Cinematic-overlay CTA — sharp-cornered buttons (a solid primary + an optional
   outlined secondary), replacing the old single pill-shaped "Get a Free Estimate"
   button Danny flagged as generic on both the hero and the service-area scrub.
   Deliberately not pill-shaped (border-radius: 3px) so it reads as a distinct,
   more considered choice than the nav's own pill CTA. Shared/generic (.cta-group)
   rather than hero-specific, since the area scrub reuses it too, just with one
   button instead of two. */
.reveal-line.cta-group {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: 14px;
}
.btn-primary,
.cta-group .btn-secondary {
  display: inline-flex;
  align-items: center;
  font-family: "JetBrains Mono", monospace;
  font-weight: 600;
  text-transform: uppercase;
  font-size: 0.78rem;
  letter-spacing: 0.08em;
  padding: 16px 30px;
  border-radius: 3px;
  text-decoration: none;
  white-space: nowrap;
  transition: transform 0.2s ease, box-shadow 0.2s ease, background 0.2s ease, border-color 0.2s ease, color 0.2s ease;
}
.btn-primary {
  color: #1a1408;
  background: var(--accent);
  border: 1px solid var(--accent);
  box-shadow: 0 0 30px rgba(224, 164, 88, 0.4);
}
.btn-primary:hover {
  background: var(--accent-bright);
  border-color: var(--accent-bright);
  transform: translateY(-1px);
  box-shadow: 0 0 40px rgba(224, 164, 88, 0.6);
}
.cta-group .btn-secondary {
  color: var(--ink);
  background: rgba(10, 8, 6, 0.35);
  border: 1px solid rgba(245, 241, 232, 0.4);
}
.cta-group .btn-secondary:hover {
  border-color: var(--accent);
  color: var(--accent);
  background: rgba(224, 164, 88, 0.08);
  transform: translateY(-1px);
}

/* ---------- Progress ---------- */
.progress {
  position: absolute;
  left: 32px; right: 32px; bottom: 40px;
  height: 2px;
  background: rgba(245,241,232,0.12);
  z-index: 12;
}
.progress-fill {
  height: 100%; width: 0%;
  background: linear-gradient(90deg, var(--accent), var(--accent-bright));
  box-shadow: 0 0 12px var(--accent);
  transition: width 0.05s linear;
}
.scroll-hint {
  position: absolute; bottom: 12px; left: 50%;
  transform: translateX(-50%);
  z-index: 12;
  display: flex; flex-direction: column; align-items: center; gap: 8px;
  font-family: "JetBrains Mono", monospace;
  font-size: 11px; letter-spacing: 0.3em;
  color: var(--ink-dim);
  transition: opacity 0.4s;
}
.scroll-hint .cursor {
  width: 2px; height: 14px;
  background: var(--accent);
  animation: blink 1s step-end infinite;
}
@keyframes blink { 50% { opacity: 0; } }

/* ---------- Reveal-on-scroll (non-canvas sections) ---------- */
.reveal { opacity: 0; transform: translateY(36px); transition: opacity 0.7s ease, transform 0.7s ease; }
.reveal.in { opacity: 1; transform: translateY(0); }

/* ---------- Staggered card reveal ----------
   The whole-section .reveal fade above was too subtle to register during an actual
   scroll (only a 24-36px shift on a large block). This animates each card in a grid
   individually, one after another, which is unmistakably visible regardless of scroll
   speed. Applied to every repeating card type: strip-item, service-card, process-card,
   work-card, faq-item, contact-card. */
.stagger-item {
  opacity: 0;
  transform: translateY(32px);
  /* Declares border-color too, even though most stagger-items don't have a hover
     border effect — elements that ALSO carry .glow-card (Service/Process cards) need
     it here, since CSS `transition` shorthand isn't additive: whichever rule matching
     the same element comes later in the cascade replaces the whole property list, not
     just adds to it. Keeping both rules' full property sets in sync avoids that trap. */
  transition: opacity 0.65s cubic-bezier(0.16, 1, 0.3, 1), transform 0.65s cubic-bezier(0.16, 1, 0.3, 1), border-color 0.25s ease, background-color 0.3s ease, color 0.3s ease;
}
.stagger-item.in { opacity: 1; transform: translateY(0); }
.stagger-item:nth-child(1) { transition-delay: 0ms; }
.stagger-item:nth-child(2) { transition-delay: 90ms; }
.stagger-item:nth-child(3) { transition-delay: 180ms; }
.stagger-item:nth-child(4) { transition-delay: 270ms; }
.stagger-item:nth-child(5) { transition-delay: 360ms; }
.stagger-item:nth-child(6) { transition-delay: 450ms; }
.stagger-item:nth-child(7) { transition-delay: 540ms; }
.stagger-item:nth-child(8) { transition-delay: 630ms; }
.stagger-item:nth-child(9) { transition-delay: 720ms; }
.stagger-item:nth-child(10) { transition-delay: 810ms; }

/* ---------- Copy-level reveal ----------
   Whole-SECTION reveals were removed 2026-09-12: animating opacity+transform on
   full-viewport-sized elements is expensive to composite and read as scroll lag on
   mobile. This is the replacement for the three cards under the hero: the card box
   never moves, the copy inside it animates in line by line. Each line steps 70ms
   after the previous, and --card-delay offsets each card so the three still cascade
   left to right rather than firing as one block. */
.text-stagger > * {
  opacity: 0;
  transform: translateY(14px);
  transition: opacity 0.55s cubic-bezier(0.16, 1, 0.3, 1),
              transform 0.55s cubic-bezier(0.16, 1, 0.3, 1);
}
.text-stagger.in > * { opacity: 1; transform: none; }
.text-stagger > *:nth-child(1) { transition-delay: calc(var(--card-delay, 0ms) + 0ms); }
.text-stagger > *:nth-child(2) { transition-delay: calc(var(--card-delay, 0ms) + 70ms); }
.text-stagger > *:nth-child(3) { transition-delay: calc(var(--card-delay, 0ms) + 140ms); }
.text-stagger > *:nth-child(4) { transition-delay: calc(var(--card-delay, 0ms) + 210ms); }
/* nth-of-type, not nth-child: .strip's first child is a screen-reader-only h2. */
.strip-item:nth-of-type(2) { --card-delay: 110ms; }
.strip-item:nth-of-type(3) { --card-delay: 220ms; }

/* ---------- Shared section label ---------- */
.eyebrow {
  display: inline-block;
  font-family: "Inter", sans-serif;
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.24em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: 14px;
}

/* ---------- Services strip ---------- */
.strip {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 1px;
  background: var(--line);
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
}
.strip-item {
  background: var(--bg);
  padding: var(--space-3xl) var(--space-xl);
}
.strip-num {
  display: block;
  font-family: "Playfair Display", serif;
  font-size: 0.9rem;
  color: var(--accent);
  letter-spacing: 0.2em;
  margin-bottom: 18px;
}
.strip-item h3 { font-size: 1.5rem; margin-bottom: var(--space-sm); font-weight: 600; }
.strip-item p { color: var(--ink-dim); line-height: 1.6; font-size: 0.98rem; }
.strip-icon { display: block; width: 30px; height: 30px; color: var(--accent); margin-bottom: var(--space-md); }
.strip-icon svg { width: 100%; height: 100%; }

/* ---------- Our Services ---------- */
.services { padding: var(--space-6xl) var(--space-xl); text-align: center; } /* background comes from the cream-section override above */
.services h2 { font-size: clamp(2rem, 5vw, 3rem); margin-bottom: 16px; }
.services-sub { color: var(--ink-dim); max-width: 640px; margin: 0 auto var(--space-2xl); font-size: 1.05rem; line-height: 1.6; }
.services-grid {
  max-width: 1100px; margin: 0 auto;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-lg);
  text-align: left;
}
.service-card {
  position: relative;
  background: var(--bg);
  border: 1px solid var(--line);
  border-top: 2px solid var(--accent);
  border-radius: 14px;
  padding: var(--space-xl) var(--space-lg);
}
.service-icon { display: block; width: 26px; height: 26px; color: var(--accent); margin-bottom: var(--space-md); transition: color 0.3s ease; }
.service-icon svg { width: 100%; height: 100%; }
.service-card h3 { font-size: 1.1rem; margin-bottom: var(--space-sm); font-weight: 600; transition: color 0.3s ease; }
.service-card p { color: var(--ink-dim); line-height: 1.6; font-size: 0.92rem; transition: color 0.3s ease; }

/* Bold invert-on-hover — same move used on Cenovate Marketing: the card fills solid
   with the accent color and every bit of text/icon flips dark for contrast. Reserved
   for Service cards only (the primary "what we offer" section) — Process/FAQ/Work
   keep the subtler glow-only treatment, preserving the hierarchy already established
   between "primary offer" and "everything else." */
.service-card:hover {
  background: var(--accent);
  border-color: var(--accent);
}
.service-card:hover .service-icon,
.service-card:hover h3,
.service-card:hover p {
  color: #1a1408;
}

/* ---------- How We Can Help (intent router) ----------
   Rebuilt 2026-09-06 to match a reference layout Danny provided from a competitor
   site: a plain 2x2 quadrant with thin plus-shaped dividers (no card backgrounds,
   no borders-as-boxes, no icons) — a small mono-font kicker line, a serif headline
   with an italicized accent word/phrase, body copy, and an underlined text link.
   The divider cross is a pair of full-length pseudo-elements on .help-grid itself,
   not per-item borders — a per-item border-right/border-bottom approach was tried
   first and broke visibly: the border segment only covers that item's own box, so
   the row-gap between items left a real gap in the middle of the vertical line
   instead of one continuous stroke top-to-bottom. */
.help { padding: var(--space-6xl) var(--space-xl); text-align: center; background: var(--bg); } /* top hairline removed: a seam wash blends this boundary now */
.help h2 { font-size: clamp(2rem, 5vw, 3rem); margin-bottom: 16px; }
.help-sub { color: var(--ink-dim); max-width: 640px; margin: 0 auto var(--space-2xl); font-size: 1.05rem; line-height: 1.6; }
.help-grid {
  position: relative;
  max-width: 1100px; margin: 0 auto;
  display: grid;
  grid-template-columns: 1fr 1fr;
  column-gap: var(--space-4xl);
  row-gap: var(--space-4xl);
  text-align: left;
}
.help-grid::before {
  content: "";
  position: absolute;
  top: 0; bottom: 0; left: 50%;
  width: 1px;
  background: var(--line);
}
.help-grid::after {
  content: "";
  position: absolute;
  left: 0; right: 0; top: 50%;
  height: 1px;
  background: var(--line);
}
.help-item { position: relative; }
.help-kicker {
  display: block;
  font-family: "JetBrains Mono", monospace;
  font-size: 0.7rem;
  font-weight: 600;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--accent);
  margin-bottom: var(--space-md);
}
.help-item h3 { font-size: 1.6rem; font-weight: 700; line-height: 1.25; margin-bottom: var(--space-md); }
.help-item h3 em { font-style: italic; font-weight: 600; }
/* No bottom margin: the "Explore ..." link that used to sit under this was removed,
   so a trailing margin would just leave dead space in each quadrant. */
.help-item p { color: var(--ink-dim); font-size: 0.98rem; line-height: 1.7; max-width: 420px; }

/* ---------- Our Process ---------- */
.process { padding: var(--space-6xl) var(--space-xl); text-align: center; background: var(--bg); }
.process h2 { font-size: clamp(2rem, 5vw, 3rem); margin-bottom: 16px; }
.process-sub { color: var(--ink-dim); max-width: 640px; margin: 0 auto var(--space-2xl); font-size: 1.05rem; line-height: 1.6; }
/* Horizontal connected-circle timeline (i / ii / iii / iv), replacing the old
   4-card grid. The connecting line is an absolutely-positioned ::before on the
   flex container; each .process-step is given position:relative so it paints
   after (on top of) that ::before in stacking order — without that, the line
   would render over the circles instead of behind them. */
.process-timeline {
  max-width: 1000px; margin: 0 auto;
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  position: relative;
  text-align: center;
}
.process-timeline::before {
  content: "";
  position: absolute;
  top: 27px;
  left: 27px;
  right: 27px;
  height: 1px;
  background: var(--line);
}
.process-step {
  position: relative;
  flex: 1 1 0;
  padding: 0 var(--space-sm);
}
.process-circle {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 56px; height: 56px;
  margin: 0 auto var(--space-lg);
  border-radius: 50%;
  background: var(--bg-2);
  border: 1px solid var(--line);
  font-family: "Playfair Display", serif;
  font-style: italic;
  font-size: 1.25rem;
  color: var(--accent);
  transition: border-color 0.25s ease, background-color 0.25s ease;
}
.process-step:hover .process-circle {
  border-color: var(--accent);
  background: var(--accent);
  color: #1a1408;
}
.process-step h3 { font-size: 1.1rem; margin-bottom: var(--space-sm); font-weight: 600; }
.process-step p { color: var(--ink-dim); line-height: 1.6; font-size: 0.92rem; max-width: 230px; margin: 0 auto; }

/* ---------- Spotlight glow card ----------
   Originally ported from a 21st.dev React/shadcn component using a dual-mask
   `mask-composite: intersect` ring trick. That technique turned out to be
   genuinely broken in practice — confirmed via direct testing that with the
   mask applied the pseudo-element rendered fully invisible (not a ring) even
   though the underlying position/content/gradient were all correct. Replaced
   with a single, robust cursor-tracked glow (no mask) + a plain hover
   border-brighten as a guaranteed-visible floor effect. */
.glow-card {
  position: relative;
  --base: 36;      /* amber hue, matches site accent instead of the original's blue/purple */
  --spread: 10;    /* kept tight so the glow stays amber/gold across the whole card, never drifts to green */
  --spotlight-size: 260px;
  --hue: calc(var(--base) + (var(--xp, 0.5) * var(--spread)));
  background-image: radial-gradient(
    var(--spotlight-size) var(--spotlight-size) at calc(var(--x, 0) * 1px) calc(var(--y, 0) * 1px),
    hsl(var(--hue) 88% 62% / 0.28), transparent 70%
  );
  background-attachment: fixed;
  /* Full property set kept in sync with .stagger-item's transition list — see the
     comment there for why (transition shorthand isn't additive across matching rules). */
  transition: opacity 0.65s cubic-bezier(0.16, 1, 0.3, 1), transform 0.65s cubic-bezier(0.16, 1, 0.3, 1), border-color 0.25s ease, background-color 0.3s ease, color 0.3s ease;
}
.glow-card:hover {
  border-color: rgba(224, 164, 88, 0.6);
}

/* The cursor-tracked glow is desktop-only. `background-attachment: fixed` in particular
   forces the gradient to be repainted against the viewport on every scroll frame, which
   is a well-known source of scroll jank on mobile, and there is no cursor to track on a
   touch device anyway. effects.js skips the pointermove listener under the same
   condition, so on touch this costs nothing at all. */
@media (hover: none), (pointer: coarse) {
  .glow-card {
    background-image: none;
    background-attachment: scroll;
  }
}

/* ---------- Why Nightscape ---------- */
.why { padding: var(--space-6xl) var(--space-xl); } /* background comes from the cream-section override above */
.why-inner { max-width: 780px; margin: 0 auto; }
.why h2 { font-size: clamp(1.9rem, 4.5vw, 2.7rem); margin-bottom: var(--space-md); line-height: 1.2; }
.why p { color: var(--ink-dim); font-size: 1.05rem; line-height: 1.75; }
.why-note {
  margin-top: var(--space-xl);
  padding: var(--space-lg) var(--space-lg);
  border-left: 3px solid var(--accent);
  background: rgba(224,164,88,0.06);
  border-radius: 0 10px 10px 0;
}
.why-note p { color: var(--ink); font-size: 0.98rem; margin: 0; }

/* ---------- For Architects, Designers & Builders ---------- */
.trade { padding: var(--space-6xl) var(--space-xl); text-align: center; border-top: 1px solid var(--line); border-bottom: 1px solid var(--line); } /* background comes from the cream-section override above */
.trade-inner { max-width: 720px; margin: 0 auto; }
.trade h2 { font-size: clamp(1.9rem, 4.5vw, 2.7rem); margin-bottom: var(--space-md); line-height: 1.2; }
.trade p { color: var(--ink-dim); font-size: 1.05rem; line-height: 1.75; }

/* ---------- Considered — reusable two-column image+text pattern ----------
   Used for the intro philosophy section and "Built For Long Island." Add
   .considered--reverse to swap the media to the left side. */
.considered { padding: var(--space-6xl) var(--space-xl); background: var(--bg); }
.considered-grid {
  max-width: 1200px; margin: 0 auto;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-4xl);
  align-items: center;
}
.considered--reverse { } /* background comes from the cream-section override above */
.considered--reverse .considered-text { order: 2; }
.considered--reverse .considered-media { order: 1; }
.considered-text h2 { font-size: clamp(1.7rem, 3.6vw, 2.4rem); margin: var(--space-md) 0; line-height: 1.25; }
.considered-text p { color: var(--ink-dim); font-size: 1rem; line-height: 1.7; margin-bottom: var(--space-md); }
.considered-text p:last-child { margin-bottom: 0; }

/* Scene-based list for the Smart Lighting Control section (Arrival/Entertaining/
   Evening/Away) — a plain list, not cards, so it stays inline with the rest of a
   text column rather than competing with it visually. */
.scene-list {
  list-style: none;
  margin: 0 0 var(--space-lg);
  padding: 0;
  border-top: 1px solid var(--line);
}
.scene-list li {
  padding: var(--space-md) 0;
  border-bottom: 1px solid var(--line);
  color: var(--ink-dim);
  font-size: 0.98rem;
  line-height: 1.6;
}
.scene-list strong {
  color: var(--accent);
  font-family: "Playfair Display", serif;
  font-style: italic;
  font-weight: 600;
  margin-right: 6px;
}
.considered-closer { color: var(--ink) !important; font-family: "Playfair Display", serif; font-size: 1.1rem !important; }
.considered-media { position: relative; border-radius: 14px; overflow: hidden; border: 1px solid var(--line); }
.considered-media img { width: 100%; height: 100%; object-fit: cover; display: block; aspect-ratio: 4/3; }
/* Anchored bottom-left and sized to its own content rather than stretched edge to
   edge. It used to set `right` as well, which forced it full-width and, once the
   text wrapped on a phone, covered close to half the photo. */
.considered-caption {
  position: absolute; left: var(--space-lg); bottom: var(--space-lg);
  max-width: calc(100% - (var(--space-lg) * 2));
  background: rgba(7, 6, 10, 0.82);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  color: var(--ink);
  padding: 10px var(--space-md);
  border-radius: 6px;
  font-family: "Playfair Display", serif;
  font-style: italic;
  font-size: 0.88rem;
  line-height: 1.3;
}

/* ---------- Our Work ---------- */
.work { padding: var(--space-6xl) var(--space-xl); text-align: center; background: var(--bg); }
.work h2 { font-size: clamp(2rem, 5vw, 3rem); margin-bottom: var(--space-md); }
.work-sub { color: var(--ink-dim); margin-bottom: var(--space-2xl); font-size: 1.05rem; }
/* Asymmetric editorial grid instead of a flat uniform mosaic — the flagship estate
   shot (.feature-lg) and one wide establishing shot (.feature-wide) get real visual
   weight instead of being sized identically to every other tile. grid-auto-flow: dense
   lets the remaining standard tiles fill in around them without manual placement. */
.work-grid {
  max-width: 1200px; margin: 0 auto;
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  grid-auto-rows: 190px;
  grid-auto-flow: dense;
  gap: var(--space-md);
}
.work-card {
  position: relative;
  border-radius: 10px;
  overflow: hidden;
  border: 1px solid var(--line);
  background: var(--bg-2);
}
.work-card.feature-lg { grid-column: span 2; grid-row: span 2; }
.work-card.feature-wide { grid-column: span 2; grid-row: span 1; }

@media (max-width: 1100px) and (min-width: 701px) {
  .work-grid { grid-template-columns: repeat(3, 1fr); }
  .services-grid { grid-template-columns: repeat(2, 1fr); }
}
.work-card img {
  width: 100%; height: 100%;
  object-fit: cover;
  display: block;
  transition: transform 0.5s ease;
}
.work-card:hover img { transform: scale(1.06); }
.work-card figcaption {
  position: absolute;
  left: 0; right: 0; bottom: 0;
  padding: 14px 16px;
  background: linear-gradient(0deg, rgba(0,0,0,0.85), transparent);
}
.work-tag {
  font-size: 0.78rem;
  font-weight: 600;
  letter-spacing: 0.04em;
  color: var(--accent-bright);
}

/* ---------- Service Area + Care ---------- */
.area { padding: var(--space-6xl) var(--space-xl); } /* background comes from the cream-section override above */
.area-grid {
  max-width: 1100px; margin: 0 auto;
  display: grid;
  grid-template-columns: 1.3fr 1fr;
  gap: var(--space-2xl);
}
.area-towns h2 { font-size: clamp(1.8rem, 4vw, 2.4rem); margin-bottom: var(--space-md); line-height: 1.2; }
.area-list { color: var(--ink-dim); font-size: 1rem; line-height: 2; }
.area-note { color: var(--ink-dim); font-size: 0.9rem; margin-top: 18px; font-style: italic; }
.area-care {
  background: var(--bg);
  border: 1px solid var(--line);
  border-radius: 14px;
  padding: var(--space-xl) var(--space-xl);
}
.area-care h3 { font-size: 1.2rem; margin-bottom: var(--space-sm); font-weight: 600; }
.area-care p { color: var(--ink-dim); line-height: 1.7; font-size: 0.95rem; }

/* ---------- FAQ ---------- */
.faq { padding: var(--space-6xl) var(--space-xl); text-align: center; background: var(--bg); }
.faq h2 { font-size: clamp(2rem, 5vw, 3rem); margin-bottom: var(--space-2xl); }
.faq-grid {
  max-width: 1000px; margin: 0 auto;
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: var(--space-lg);
  text-align: left;
}
.faq-item {
  background: var(--bg-2);
  border: 1px solid var(--line);
  border-radius: 12px;
  padding: var(--space-lg) var(--space-xl);
  transition: border-color 0.2s, background 0.2s;
}
.faq-item:hover { border-color: rgba(224, 164, 88, 0.4); background: var(--bg); }
.faq-item h3 { font-size: 1.05rem; margin-bottom: var(--space-sm); font-weight: 600; color: var(--accent-bright); }
.faq-item p { color: var(--ink-dim); line-height: 1.65; font-size: 0.92rem; }

/* ---------- Contact ---------- */
.contact { padding: var(--space-6xl) var(--space-xl); text-align: center; }
.contact h2 { font-size: clamp(2.1rem, 5.5vw, 3.2rem); margin-bottom: var(--space-md); }
.contact-sub { color: var(--ink-dim); margin-bottom: var(--space-2xl); font-size: 1.05rem; }
.contact-grid {
  display: flex; justify-content: center; gap: 20px; flex-wrap: wrap;
  margin-bottom: 56px;
}
.contact-card {
  display: flex; flex-direction: column; gap: 6px;
  padding: var(--space-lg) var(--space-xl);
  border: 1px solid var(--line);
  border-radius: 12px;
  text-decoration: none;
  color: var(--ink);
  background: var(--bg-2);
  transition: border-color 0.2s, transform 0.2s;
}
.contact-card:hover { border-color: var(--accent); transform: translateY(-2px); }
.contact-name { font-weight: 600; font-size: 1.05rem; }
.contact-phone { color: var(--accent-bright); font-size: 1.15rem; font-weight: 600; }

.estimate-form {
  max-width: 420px; margin: 0 auto;
  display: flex; flex-direction: column; gap: 14px;
}
/* Needed because the `display: flex` above outranks the UA stylesheet's
   `[hidden] { display: none }`, so setting .hidden in JS alone would leave the form
   on screen with the confirmation stacked underneath it. */
.estimate-form[hidden] { display: none; }
.estimate-form input,
.estimate-form select,
.estimate-form textarea {
  padding: 15px 18px;
  border-radius: 8px;
  border: 1px solid var(--line);
  background: var(--bg-2);
  color: var(--ink);
  font-family: "Inter", sans-serif;
  font-size: 0.98rem;
  width: 100%;
}
.estimate-form textarea { resize: vertical; min-height: 96px; line-height: 1.5; }
/* Selects sit on an unselected placeholder option until the visitor picks something.
   Dim that state so it reads like the inputs' placeholder text rather than a real answer. */
.estimate-form select:invalid,
.estimate-form select:has(option[value=""]:checked) { color: var(--ink-dim); }
/* The native dropdown list is drawn by the OS and does not inherit the dark theme, so
   set option colours explicitly or they can render as dark-on-dark. */
.estimate-form select option { background: var(--bg-2); color: var(--ink); }
.estimate-form select:focus-visible,
.estimate-form textarea:focus-visible {
  outline: 2px solid var(--accent-bright);
  outline-offset: 2px;
  border-color: var(--accent);
}
/* Confirmation state swapped in after submit (see initEstimateForm in effects.js). */
.estimate-success {
  max-width: 420px;
  margin: 0 auto;
  padding: var(--space-xl) var(--space-lg);
  border: 1px solid var(--line);
  border-radius: 12px;
  background: var(--bg-2);
  text-align: center;
}
.estimate-success[hidden] { display: none; }
.estimate-success-icon { display: block; width: 34px; height: 34px; margin: 0 auto var(--space-md); color: var(--accent); }
.estimate-success-icon svg { width: 100%; height: 100%; }
.estimate-success h3 { font-size: 1.2rem; font-weight: 600; margin-bottom: var(--space-sm); }
.estimate-success p { color: var(--ink-dim); font-size: 0.95rem; line-height: 1.7; }
.estimate-success a { color: var(--accent); text-decoration: none; border-bottom: 1px solid rgba(224, 164, 88, 0.4); }
.estimate-success a:hover { color: var(--accent-bright); border-color: var(--accent-bright); }

.estimate-form input::placeholder,
.estimate-form textarea::placeholder { color: var(--ink-dim); }
.estimate-form input:focus { border-color: var(--accent); }
.estimate-form button {
  margin-top: 6px;
  padding: 16px;
  border-radius: 999px;
  border: none;
  background: var(--accent);
  color: #1a1408;
  font-weight: 700;
  letter-spacing: 0.04em;
  font-size: 1rem;
  cursor: pointer;
  box-shadow: 0 0 30px rgba(224, 164, 88, 0.35);
  transition: transform 0.2s;
}
.estimate-form button:hover { transform: translateY(-1px); }

/* ---------- Footer ---------- */
.footer {
  padding: var(--space-xl); text-align: center;
  color: var(--ink-dim); font-size: 0.85rem;
  border-top: 1px solid var(--line);
  display: flex; flex-direction: column; align-items: center; gap: 14px;
}
.footer-logo { width: 46px; height: 46px; border-radius: 50%; opacity: 0.85; }

/* ---------- Repeating CTA band ----------
   Everything between the hero and the contact form used to carry no ask at all.
   Deliberately kept dark in every placement, including where it follows a cream
   section, so it reads as the same recurring moment each time rather than as part
   of whichever section it happens to sit under. */
.cta-band {
  padding: var(--space-4xl) var(--space-xl);
  background: var(--bg-2);
  border-top: 1px solid var(--line);
  border-bottom: 1px solid var(--line);
  text-align: center;
  position: relative;
  overflow: hidden;
}
.cta-band::before {
  content: "";
  position: absolute; inset: 0;
  background: radial-gradient(ellipse 60% 120% at 50% 50%, rgba(224, 164, 88, 0.10), transparent 70%);
  pointer-events: none;
}
/* The band directly under the gallery. Drops the top hairline and tightens the top
   padding so it reads as part of the gallery rather than as a separate block: there
   were too many gold lines stacking up through this stretch of the page. */
.cta-band--attached {
  border-top: none;
  /* No bottom hairline: this band now runs straight into the cream Service Area, and
     every other dark-to-cream boundary on the page is a hard edge with no rule. */
  border-bottom: none;
  padding-top: var(--space-xl);
  /* Same background as the gallery above it, not the band's usual --bg-2. With the
     top border gone, a tonal step was still marking the boundary; matching --bg makes
     it read as the gallery's own closing line rather than a separate block. */
  background: var(--bg);
}
.cta-band-inner { position: relative; max-width: 720px; margin: 0 auto; }
.cta-band p {
  font-family: "Playfair Display", serif;
  font-size: clamp(1.25rem, 3vw, 1.75rem);
  line-height: 1.35;
  color: var(--ink);
  margin-bottom: var(--space-lg);
}
.cta-band-actions { display: flex; flex-wrap: wrap; justify-content: center; align-items: stretch; gap: 14px; }
/* Icon-only counterpart to .btn-primary. Square-ish so it reads as a paired action
   next to the estimate button rather than a second competing text button. */
.btn-phone {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 54px;
  border-radius: 3px;
  color: var(--accent);
  background: rgba(224, 164, 88, 0.08);
  border: 1px solid rgba(224, 164, 88, 0.45);
  text-decoration: none;
  transition: background 0.2s ease, border-color 0.2s ease, color 0.2s ease, transform 0.2s ease;
}
.btn-phone svg { width: 20px; height: 20px; }
.btn-phone:hover {
  background: var(--accent);
  border-color: var(--accent);
  color: #1a1408;
  transform: translateY(-1px);
}

/* ---------- Mobile ---------- */
@media (max-width: 700px) {
  .nav { padding: 14px 18px; font-size: 10px; }
  .nav-brand { gap: 10px; }
  /* Logo sizes are deliberately larger on mobile than the desktop-derived defaults.
     The mark is a circular badge with "NIGHTSCAPE / LIGHTING" set inside it, and below
     roughly 50px that inner text is not legible at all, so the logo stopped reading as
     a brand and became a dark dot. Desktop is untouched. */
  .nav-logo { width: 56px; height: 56px; }
  /* The footer mark closes the page directly under the estimate form (about 120px
     below it), so at mobile width this single logo is what brands that whole bottom
     stretch. Full opacity here too, rather than the 0.85 used on desktop. */
  .footer-logo { width: 84px; height: 84px; opacity: 1; }
  /* The hero subheadline crosses a brightly lit stone patio at the point in the clip
     where it peaks, and cream text over that is genuinely hard to read at mobile type
     sizes. Heavier weight plus a tight, dense shadow close to the glyphs is what
     actually restores contrast against a light backdrop. Mobile only: on desktop the
     line is far larger and spreads across darker parts of the frame. */
  .reveal-line.sub {
    font-weight: 600;
    text-shadow:
      0 1px 2px rgba(0, 0, 0, 0.95),
      0 2px 8px rgba(0, 0, 0, 0.9),
      0 8px 30px rgba(0, 0, 0, 0.75);
  }
  .nav-links, .nav-cta { display: none; }
  .nav-toggle { display: flex; }
  .nav-mobile { display: flex; }
  .strip { grid-template-columns: 1fr; }
  .help-grid { grid-template-columns: 1fr; row-gap: var(--space-2xl); }
  .help-grid::before, .help-grid::after { content: none; }
  .help-item:not(:last-child) { border-bottom: 1px solid var(--line); padding-bottom: var(--space-2xl); }
  .process-timeline { flex-direction: column; gap: var(--space-2xl); align-items: stretch; }
  .process-timeline::before { top: 0; bottom: 0; left: 27px; right: auto; width: 1px; height: auto; }
  /* 76px, not --space-2xl (48px). The circle is 56px wide and absolutely positioned
     at left: 0, so 48px of padding left it overlapping the title and copy by 8px. */
  .process-step { padding: 0 0 0 76px; text-align: left; }
  .process-circle { position: absolute; top: 0; left: 0; margin: 0; }
  .process-step h3, .process-step p { margin-left: 0; }
  .process-step p { max-width: none; margin: 0; }
  .services-grid { grid-template-columns: 1fr; }
  .cta-band { padding: var(--space-3xl) var(--space-lg); }
  .cta-band-actions .btn-primary { flex: 1 1 auto; justify-content: center; }
  .considered-grid { grid-template-columns: 1fr; gap: var(--space-xl); }
  .considered-media img { aspect-ratio: 16/10; }
  /* All three two-column sections share one frame on mobile so they read as the same
     component. Smart Lighting Control briefly kept 16/10 here because its photo is the
     only landscape one, but that rendered it at half the height of the other two
     (198px vs 395px) and looked like a mistake. Its subject sits centre-frame so the
     taller crop holds up. */
  #considered .considered-media img,
  #built-for .considered-media img,
  #smart-tech .considered-media img { aspect-ratio: 4/5; }
  .considered-caption { font-size: 0.8rem; padding: 8px 12px; left: var(--space-md); bottom: var(--space-md); }
  .work-grid { grid-template-columns: repeat(2, 1fr); grid-auto-rows: 200px; }
  .work-card.feature-lg, .work-card.feature-wide { grid-column: span 2; grid-row: span 1; }
  .area-grid { grid-template-columns: 1fr; }
  .faq-grid { grid-template-columns: 1fr; }
  .contact-grid { flex-direction: column; align-items: center; }
  .reveal-line.sub { max-width: 88vw; }
}

/* ---------- Cream section override ----------
   Danny's call 2026-09-08: the site read as too uniformly dark end-to-end (every
   section either --bg or --bg-2, both near-black). Rather than repaint each
   component individually, this re-points the semantic tokens (--ink, --ink-dim,
   --line, --accent, --accent-bright, --bg) to their cream equivalents for exactly
   the 5 sections that used to be --bg-2 ("the lighter black"), since every rule
   in this file already reads color through those tokens instead of hardcoded hex.
   --bg specifically maps to --cream-2 (not --cream) so that nested "card" pieces
   (.service-card, .area-care, etc.) that use var(--bg) for their own fill get a
   visibly different tone than the section behind them, same relationship as the
   dark-mode original, just inverted. Deliberately left OUT of this list: the small
   --bg-2 uses that are just component fills inside an otherwise-dark section
   (.work-card, .faq-item, .contact-card, .estimate-form input, .process-circle),
   not full sections, left dark on purpose.
   Placed at the very end of the file on purpose — .considered { background:
   var(--bg); } also matches the Built-For-Long-Island section (it carries both
   .considered and .considered--reverse), and for same-specificity selectors CSS
   cascade goes by source order, so this has to come after every other rule that
   touches these 5 selectors' `background`/`color`, not just after :root, or an
   earlier-but-later-in-file rule would silently win instead. */
.services, .why, .trade, .area, .considered--reverse {
  background: var(--cream);
  color: var(--cream-ink);
  --ink: var(--cream-ink);
  --ink-dim: var(--cream-ink-dim);
  --line: var(--cream-line);
  --accent: var(--cream-accent);
  --accent-bright: var(--cream-accent-bright);
  --bg: var(--cream-2);
}

/* ---------- Section seam washes ----------
   Replaces an earlier .gold-divider element that drew a hairline through the seam.
   That hairline was the exact thing it needed to get rid of: it marked the division
   instead of dissolving it. This is the technique used on cenovatemarketing.com
   instead: the section above fades an accent wash IN toward its bottom edge, the
   section below fades the same wash OUT from its top edge, and because both sides
   hit identical values at the seam they merge into one continuous glow with no
   visible boundary.

   Matched pairs, and they must stay matched. If you change an opacity on one side,
   change the other or a seam line reappears:
     #built-for  -> #why       bronze 0.22 (cream stretch)
     #faq        -> #contact   amber  0.20 (dark stretch)

   Fade distance is in px rather than % so both sides of a seam blend over the same
   physical distance regardless of how tall each section happens to be.

   ID selectors on purpose: the cream override block above sets `background` on
   .why via a class, and these have to outrank it. */
#built-for {
  background:
    linear-gradient(180deg, transparent calc(100% - 260px), rgba(156, 106, 40, 0.22) 100%),
    var(--cream);
}
#why {
  background:
    linear-gradient(180deg, rgba(156, 106, 40, 0.22) 0%, transparent 260px),
    var(--cream);
}
#faq {
  background:
    linear-gradient(180deg, transparent calc(100% - 260px), rgba(224, 164, 88, 0.20) 100%),
    var(--bg);
}
#contact {
  background:
    linear-gradient(180deg, rgba(224, 164, 88, 0.20) 0%, transparent 260px),
    var(--bg);
}

/* Three more seams, all dark-to-dark so they use the same amber 0.20 pairing as
   #faq -> #contact. Same rule as the others: these are MATCHED PAIRS, change one
   side's opacity without the other and a seam line reappears.
     #considered -> #help
     #smart-tech -> #process
   The hairline that used to sit at the first of these (.help's border-top) was removed
   above so the pair blends over one continuous tone. */
#considered {
  background:
    linear-gradient(180deg, transparent calc(100% - 260px), rgba(224, 164, 88, 0.20) 100%),
    var(--bg);
}
#help {
  background:
    linear-gradient(180deg, rgba(224, 164, 88, 0.20) 0%, transparent 260px),
    var(--bg);
}
#smart-tech {
  background:
    linear-gradient(180deg, transparent calc(100% - 260px), rgba(224, 164, 88, 0.20) 100%),
    var(--bg);
}
#process {
  background:
    linear-gradient(180deg, rgba(224, 164, 88, 0.20) 0%, transparent 260px),
    var(--bg);
}

/* Copy review 2026-09-13 (Danny): never leave a single word alone on the last line.
   balance = headings wrap evenly; pretty = paragraphs and buttons avoid one-word last lines. */
h1, h2, h3 { text-wrap: balance; }
p, figcaption, .btn-primary, .btn-secondary, li { text-wrap: pretty; }
/* Phones: the hero's forced line break leaves "disappear." alone on a 4th line at 390px.
   Dropping the <br> lets text-wrap: balance produce a clean 3-line stack instead. */
@media (max-width: 700px) { h1.reveal-line br { display: none; } }
