/* ============================================================
   Delta Gates — Base styles + layout primitives
   Depends on tokens.css + typography.css
   ============================================================ */

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

html {
  -webkit-text-size-adjust: 100%;
  /* Keep horizontal scrollbars away when crop-mark frames overhang */
  overflow-x: clip;
}

body {
  margin: 0;
  background: var(--color-surface-page);
  color: var(--color-text-primary);
  font-family: var(--font-body);
  font-size: 1rem;
  line-height: 1.5;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  overflow-x: clip;
}

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

h1, h2, h3, h4, h5, h6, p, ul, ol { margin: 0; }
ul { padding: 0; list-style: none; }
a { color: inherit; text-decoration: none; }

button {
  font: inherit;
  background: none;
  border: 0;
  padding: 0;
  cursor: pointer;
}

/* ── Layout primitives ───────────────────────────────────── */
.container {
  width: 100%;
  max-width: calc(var(--container-wide) + (var(--container-gutter) * 2));
  margin-inline: auto;
  /* Fluid gutter: shrinks on phones, grows on tablets+ */
  padding-inline: clamp(1rem, 4vw, 1.5rem);
}

/* Section block-padding fluid-scales with viewport */
.section {
  padding-block: clamp(3rem, 8vw, 6rem);
}
.section--tight  { padding-block: clamp(2rem, 5vw, 3rem); }
.section--loose  { padding-block: clamp(4rem, 10vw, 8rem); }
.section--dark {
  background: var(--color-surface-page-dark);
  color: var(--color-text-inverse);
}

.stack > * + * { margin-top: var(--stack, var(--space-4)); }
.stack-1 { --stack: var(--space-1); }
.stack-2 { --stack: var(--space-2); }
.stack-3 { --stack: var(--space-3); }
.stack-4 { --stack: var(--space-4); }
.stack-5 { --stack: var(--space-5); }
.stack-6 { --stack: var(--space-6); }
.stack-7 { --stack: var(--space-7); }

.cluster { display: flex; flex-wrap: wrap; align-items: center; gap: var(--cluster, var(--space-3)); }

/* ── Button ──────────────────────────────────────────────── */
.btn {
  position: relative;
  overflow: hidden;
  isolation: isolate;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  /* Fluid padding: 12px → 24px vertical, 24px → 48px horizontal */
  padding: clamp(0.75rem, 1.5vw, 1.5rem) clamp(1.25rem, 3vw, 3rem);
  border-radius: var(--radius-sm);
  border: 1px solid transparent;
  font-family: var(--font-ui);
  font-weight: 700;
  font-size: clamp(0.875rem, 1.1vw, 1rem);
  line-height: 1;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  transition: color 180ms ease, border-color 180ms ease, transform 180ms ease, box-shadow 240ms ease;
}

/* Primary CTA — "olive oil" gradient: a warm golden-olive top edge bleeds
   into the deep brand olive at the base, with a mid-olive plateau to give
   the surface a viscous, light-catching feel rather than a flat ramp.
   The icon and text sit above the gradient layers via z-index, so the
   shine pass underneath them doesn't wash out the label. */
.btn--primary {
  background: linear-gradient(140deg, #6a8523 0%, #4e6918 50%, #2e480c 100%);
  color: #ffffff;
  text-shadow: 0 1px 1px rgba(0, 0, 0, 0.28);
  box-shadow: 0 1px 2px rgba(46, 72, 12, 0.22);
}
.btn--primary::before {
  /* Brighter olive-oil cross-fade on hover — same family, more saturation.
     z-index:-1 keeps it behind the text node (which has no own z-index),
     while isolation:isolate on .btn stops it escaping the button. */
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(140deg, #7e9c2c 0%, #5d7c20 50%, #3a5612 100%);
  opacity: 0;
  transition: opacity 220ms ease;
  z-index: -1;
}
.btn--primary::after {
  /* Diagonal light sweep on hover. */
  content: "";
  position: absolute;
  top: 0;
  left: -120%;
  width: 80%;
  height: 100%;
  background: linear-gradient(110deg, transparent 0%, rgba(255,255,255,0.28) 50%, transparent 100%);
  transform: skewX(-20deg);
  transition: left 600ms cubic-bezier(0.2, 0.7, 0.2, 1);
  z-index: -1;
  pointer-events: none;
}
.btn--primary:hover,
.btn--primary:focus-visible {
  transform: translateY(-1px);
  box-shadow: 0 8px 22px rgba(46, 72, 12, 0.32), 0 0 0 1px rgba(182, 193, 74, 0.45) inset;
}
.btn--primary:hover::before,
.btn--primary:focus-visible::before { opacity: 1; }
.btn--primary:hover::after,
.btn--primary:focus-visible::after { left: 140%; }
.btn--primary:active { transform: translateY(0); box-shadow: 0 2px 6px rgba(46, 72, 12, 0.28); }

@media (prefers-reduced-motion: reduce) {
  .btn--primary,
  .btn--primary::before,
  .btn--primary::after { transition: none; }
  .btn--primary:hover { transform: none; }
}

.btn--outline-light {
  background: transparent;
  color: var(--color-text-inverse);
  border-color: var(--color-border-inverse);
}
.btn--outline-light:hover { background: var(--color-white-15); }

.btn--outline-dark {
  background: transparent;
  color: var(--color-text-primary);
  border-color: var(--color-border-strong);
}
.btn--outline-dark:hover { background: var(--color-surface-card); }

.btn--ghost {
  background: transparent;
  color: var(--color-text-accent);
}
.btn--ghost:hover { color: var(--color-button-bg-hover); }

/* Instagram CTA — neutral-700 fill, subtle olive-tinted border, white text */
.btn--instagram {
  background: var(--color-neutral-700);
  color: var(--color-text-inverse);
  border-color: rgb(114 121 104 / 0.4);     /* neutral/600 @ 40% */
  padding: 13px 25px 13px 17px;             /* exact Figma — 13 / 25 / 13 / 17 */
  gap: var(--space-2);
  font-size: 16px;
  line-height: 1;
}
.btn--instagram:hover { background: var(--color-neutral-800); }

.btn--sm { padding: var(--space-2) var(--space-3); font-size: 0.8125rem; }
.btn--lg {
  padding: clamp(0.875rem, 1.6vw, 1.5rem) clamp(1.5rem, 3vw, 3rem);
  font-size: clamp(0.875rem, 1.1vw, 1rem);
}

.btn .icon { width: 1em; height: 1em; }

/* ── Eyebrow · bordered chip with diagonal slashes ───────── */
.eyebrow {
  --eyebrow-color: var(--color-text-secondary);
  --eyebrow-border: var(--color-text-muted);
  --eyebrow-slash: var(--color-text-muted);

  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: clamp(0.375rem, 1vw, 0.5rem);
  padding: clamp(0.5rem, 1.2vw, 0.75rem) clamp(0.75rem, 1.6vw, 1rem);
  border: 1px solid var(--eyebrow-border);
  font-family: var(--font-ui);
  font-weight: 700;
  font-size: clamp(0.75rem, 1vw, 1rem);
  line-height: 1;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--eyebrow-color);
  width: max-content;
}
/* Diagonal slash decorations on each side */
.eyebrow::before,
.eyebrow::after {
  content: "";
  display: block;
  width: clamp(8px, 0.8vw, 12px);
  height: 1px;
  background: var(--eyebrow-slash);
  transform: rotate(-60deg);
  flex-shrink: 0;
}

/* Variants */
.eyebrow--on-dark {
  --eyebrow-color: var(--color-text-inverse-muted);
  --eyebrow-border: var(--color-border-inverse);
  --eyebrow-slash: var(--color-text-inverse-muted);
}
.eyebrow--sm { font-size: 0.875rem; padding: var(--space-2) var(--space-3); }

/* ── Section header ──────────────────────────────────────── */
.section-header { max-width: 42rem; }
.section-header__title {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: 3rem;          /* display-sm */
  line-height: 1.3;
  letter-spacing: -0.015em;
  margin-top: var(--space-4);
}
.section-header__subtitle {
  font-size: 1.25rem;       /* body-lg */
  line-height: 1.5;
  color: var(--color-text-secondary);
  margin-top: var(--space-5);
}
.section--dark .section-header__subtitle { color: var(--color-text-inverse-muted); }

/* ── Hero (Relume header-76 pattern) ─────────────────────── */
.hero-wrapper {
  background:
    var(--color-surface-page-dark)
    url('../images/hero-bg.png')
    left center / 50% auto
    no-repeat;
  color: var(--color-text-inverse);
  position: relative;
  overflow: hidden;
  /* Height is driven by .hero__copy content + symmetric padding-block */
}
/* Make sure copy + media sit ABOVE the decorative bg */
/* No position:relative here — so .hero__media (absolutely positioned
   below) anchors to .hero-wrapper instead, letting it span the full
   section height INCLUDING the divider padding-bottom area. */
.hero { z-index: 1; }

.hero {
  display: grid;
  grid-template-columns: 1fr 1fr;
  align-items: stretch;
}

/* Left column: text respects site container, padded out of viewport-edge */
.hero__copy {
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding-block: clamp(2rem, 8vw, 5rem);   /* 32px → 80px (tighter than before) */
  /* Left edge matches the centred container's content edge (= logo). */
  padding-left: max(
    var(--container-gutter),
    calc((100vw - var(--container-wide)) / 2)
  );
  padding-right: var(--space-7);
  /* No max-width here — would shrink content because border-box includes padding */
  min-width: 0;
}
.hero__copy-inner {
  max-width: 36rem; /* ≈ 576px from Figma .hero__copy */
}

.hero__eyebrow { margin-bottom: var(--space-5); }
.hero__title {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(2rem, 6vw, 4rem);   /* 32 → 64px */
  line-height: 1.15;
  letter-spacing: -0.03em;
  text-wrap: balance;
}
.hero__sub {
  margin-top: var(--space-4);
  font-size: 1.125rem;
  line-height: 1.5;
  color: var(--color-body-on-dark);
}
.hero__bullets {
  margin-top: var(--space-4);
  display: grid;
  gap: var(--space-2);
}
.hero__bullet {
  display: flex;
  align-items: flex-start;       /* icon pins to first line if text wraps */
  gap: var(--space-3);
  color: var(--color-body-on-dark);
  line-height: 1.5;
}
.hero__bullet .check {
  flex-shrink: 0;
  width: 22px;
  height: 1lh;
  border-radius: 999px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  color: var(--color-status-success);
}
.hero__bullet .check svg {
  width: 22px;
  height: 22px;
  display: block;
}
.hero__ctas { margin-top: var(--space-5); display: flex; gap: var(--space-3); flex-wrap: wrap; }

/* Right column: full-bleed window. Absolutely positioned to span the
   ENTIRE .hero-wrapper height (including the bottom padding reserved
   for the divider), independent of .hero__copy's height/padding.
   Photos extend from section top to section bottom, behind the divider. */
.hero__media {
  position: absolute;
  top: 0;
  bottom: 0;
  /* Width: half the viewport up to 1728px, then frozen at 864px so the
     carousel stops growing on ultra-wide displays.
     Right offset: pinned to viewport edge until 1728px, then pulled inward
     by half the overflow so the column stays in the same position relative
     to the design — it doesn't drift toward the far-right edge. */
  width: min(50%, 864px);
  right: max(0px, (100vw - 1728px) / 2);
  overflow: hidden;
}
/* Soft fade at the bottom of the carousel — transparent at the top,
   easing to black at 70% opacity at the bottom. Creates a subtle
   vignette behind the divider so the divider's torn cream reads
   cleanly against a darker base. */
.hero__media::after {
  content: '';
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: linear-gradient(
    to bottom,
    transparent 55%,
    rgba(0, 0, 0, 0.7) 100%
  );
}
.hero__media-inner {
  position: absolute;
  inset: 0;
  display: grid;
  grid-template-columns: 1fr 1fr;
  align-items: start;
  gap: var(--space-3);
  /* No padding — photos must fill the column edge-to-edge so the
     divider's transparent rips reveal photo content, not empty bg. */
}

/* Each column has the image set duplicated to make the loop seamless */
.hero__media-col {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  will-change: transform;
}
.hero__media-col--up   { animation: hero-scroll-up   38s linear infinite; }
.hero__media-col--down { animation: hero-scroll-down 38s linear infinite; }
@media (prefers-reduced-motion: reduce) {
  .hero__media-col--up,
  .hero__media-col--down { animation: none; }
}

/* With 16 images per column (4 sets of 4 unique images), the seamless
   loop point is at -25% — translating by one set out of four brings
   the next identical set into the same visual position. Using -25%
   instead of -50% keeps the column's bottom edge at +75% of its
   height at the extreme, guaranteeing it always covers the visible
   hero area (which is at most 1× column height in practice). */
@keyframes hero-scroll-up {
  from { transform: translateY(0); }
  to   { transform: translateY(-25%); }
}
@keyframes hero-scroll-down {
  from { transform: translateY(-25%); }
  to   { transform: translateY(0); }
}

/* Caption overlay on each hero image — populated via JS from
   data-label on each .img-placeholder. Sits bottom-left, subtle. */
.hero__media .img-placeholder { position: relative; }
.hero__media .img-placeholder[data-label]::after {
  content: attr(data-label);
  position: absolute;
  left: 10px;
  bottom: 10px;
  font-family: var(--font-ui);
  font-size: 11px;
  font-weight: 600;
  letter-spacing: 0.04em;
  text-transform: uppercase;
  color: var(--color-text-inverse);
  background: rgba(14, 16, 15, 0.65);
  padding: 5px 8px;
  border-radius: 3px;
  backdrop-filter: blur(4px);
  -webkit-backdrop-filter: blur(4px);
  pointer-events: none;
  max-width: calc(100% - 20px);
}

.hero__media img,
.hero__media .img-placeholder {
  width: 100%;
  aspect-ratio: 1 / 1;
  object-fit: cover;
  background-color: var(--color-neutral-800);
  background-size: cover;
  background-position: center;
  border-radius: var(--radius-sm);
  flex-shrink: 0;
}

/* ── Topbar ──────────────────────────────────────────────── */
.topbar {
  background: var(--color-surface-page-dark);
  color: var(--color-text-inverse);
}
/* On mobile the topbar scrolls away with the hero; the .section-nav strip
   below takes over the top edge once the hero is out of view. */
.topbar__inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-5);
  padding-block: var(--space-5);
}
.topbar__logo {
  display: inline-flex;
  align-items: center;
}
.topbar__logo img {
  height: 28px;
  width: auto;
  filter: brightness(0) invert(1);   /* SVG → white on dark topbar */
}
.topbar__nav {
  display: flex;
  gap: var(--space-6);
  font-family: var(--font-ui);
  font-weight: 600;
  font-size: 1rem;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--color-text-inverse-muted);
}
.topbar__nav a:hover { color: var(--color-text-inverse); }
.topbar__cta { display: flex; gap: var(--space-2); }

/* Mobile menu — <details> hamburger, no JS */
.topbar__hamburger {
  display: none;                /* shown by media query */
  margin-left: auto;
}
.topbar__hamburger > summary {
  list-style: none;
  cursor: pointer;
  width: 44px;
  height: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 1px solid var(--color-border-inverse);
  color: var(--color-text-inverse);
  background: transparent;
}
.topbar__hamburger > summary::-webkit-details-marker { display: none; }
.topbar__hamburger[open] > summary { background: var(--color-white-15); }
.topbar__hamburger > summary .bars {
  width: 18px;
  height: 12px;
  position: relative;
}
.topbar__hamburger > summary .bars::before,
.topbar__hamburger > summary .bars::after,
.topbar__hamburger > summary .bars > span {
  content: "";
  position: absolute;
  left: 0; right: 0;
  height: 1.5px;
  background: currentColor;
}
.topbar__hamburger > summary .bars::before { top: 0; }
.topbar__hamburger > summary .bars > span  { top: 50%; transform: translateY(-50%); }
.topbar__hamburger > summary .bars::after  { bottom: 0; }

.topbar__menu {
  position: absolute;
  inset-inline: 0;
  top: 100%;
  background: var(--color-surface-page-dark);
  border-top: 1px solid var(--color-border-inverse);
  padding: var(--space-5) clamp(1rem, 4vw, 1.5rem);
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  z-index: 50;
}
.topbar__menu a {
  font-family: var(--font-ui);
  font-weight: 600;
  font-size: 1rem;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--color-text-inverse-muted);
  padding-block: var(--space-2);
  border-bottom: 1px solid var(--color-border-inverse);
}
.topbar__menu a:hover { color: var(--color-text-inverse); }
.topbar__menu-ctas {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  margin-top: var(--space-3);
}
.topbar { position: relative; }   /* anchor for absolute menu */

/* Mobile section-nav — one-row anchor strip, hidden until the hero
   scrolls past, then slides down and sticks to the top edge. Desktop
   uses the inline .topbar__nav instead, so this is mobile-only. JS
   (.is-shown) is toggled by the same hero-passed observer as .callbar. */
.section-nav { display: none; }
@media (max-width: 900px) {
  .section-nav {
    display: block;
    position: fixed;
    top: 0;
    inset-inline: 0;
    z-index: 60;
    background: var(--color-surface-page-dark);
    border-bottom: 1px solid var(--color-border-inverse);
    transform: translateY(-100%);
    visibility: hidden;
    transition: transform 300ms cubic-bezier(0.22, 1, 0.36, 1),
                visibility 0s linear 300ms;
  }
  .section-nav.is-shown {
    transform: translateY(0);
    visibility: visible;
    transition: transform 300ms cubic-bezier(0.22, 1, 0.36, 1);
  }
  .section-nav__inner {
    display: flex;
    flex-wrap: nowrap;
    gap: var(--space-5);
    overflow-x: auto;
    overscroll-behavior-x: contain;
    -webkit-overflow-scrolling: touch;
    scrollbar-width: none;
    padding: var(--space-3) clamp(1rem, 4vw, 1.5rem);
  }
  .section-nav__inner::-webkit-scrollbar { display: none; }
  .section-nav__link {
    flex: 0 0 auto;
    font-family: var(--font-ui);
    font-weight: 600;
    font-size: 0.8125rem;
    letter-spacing: 0.05em;
    text-transform: uppercase;
    white-space: nowrap;
    color: var(--color-text-inverse-muted);
  }
  .section-nav__link:hover { color: var(--color-text-inverse); }
  /* Offset anchor jumps so section tops clear the fixed strip. */
  section[id] { scroll-margin-top: 56px; }
}
@media (prefers-reduced-motion: reduce) {
  .section-nav { transition: none; }
}

/* ── Services (Section 03 — Three things. Done properly.) ─ */
.services { background: var(--color-surface-page); padding-block: clamp(3rem, 8vw, 6rem); }
.services__header { max-width: 49.5rem; /* 792px Figma */ }
.services__title {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(1.875rem, 4.5vw, 3rem);   /* 30 → 48px */
  line-height: 1.25;
  letter-spacing: -0.015em;
  margin-top: var(--space-4);
  text-wrap: balance;
}
.services__lede {
  font-size: clamp(15px, 1.3vw, 18px);
  line-height: 1.5;
  color: var(--color-body-on-light);
  margin-top: var(--space-5);
}
.services__grid {
  margin-top: var(--space-7);
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--space-7);  /* 48px — leaves room for .framed offsets + overshoot */
}
.services__footnote {
  margin-top: var(--space-7);
  font-size: clamp(14px, 1.2vw, 18px);
  line-height: 1.5;
  color: var(--color-body-on-light);
  max-width: 60rem;
}

.service-card,
.service-card__inner {
  display: flex;
  flex-direction: column;
  background: var(--color-surface-card);
  flex: 1;
  transition: background 200ms ease;
}
/* Card is interactive — hover shifts the framed outline color to brand
   olive and lifts the card slightly. The CTA link inside is the actual
   interactive element; ::after below stretches its hit-target across
   the whole card so clicks anywhere trigger the quote modal. */
.service-card {
  position: relative;
  cursor: pointer;
  transition: transform 200ms ease, --frame-color 200ms ease;
}
.service-card:hover,
.service-card:hover .service-card__inner {
  --frame-color: var(--color-brand-olive-mid);
  background: var(--color-white);
  transform: translateY(-2px);
}
.service-card:hover .service-card__cta {
  color: var(--color-brand-olive-mid);   /* brighter green on hover */
}
/* Card-wide click is wired via a JS handler (see index.html), so the
   whole card opens the quote modal and pre-selects its service. */
.service-card__media {
  position: relative;
  aspect-ratio: 16 / 9;
  width: 100%;
  overflow: hidden;
  background: var(--color-neutral-300) center/cover no-repeat;
}
.service-card__media img { width: 100%; height: 100%; object-fit: cover; display: block; }
.service-card__chip {
  position: absolute;
  left: var(--space-5);
  bottom: 0;
  display: inline-flex;
  align-items: center;
  background: var(--color-surface-card-dark);
  color: var(--color-text-inverse-muted);
  padding: var(--space-2) var(--space-3);
  font-family: var(--font-body);
  font-size: clamp(14px, 1.4vw, 20px);
  line-height: 1.5;
  white-space: nowrap;
}
.service-card__body {
  padding: clamp(1rem, 2.5vw, 2rem) clamp(1rem, 2vw, 1.5rem) clamp(1rem, 2vw, 1.5rem);
  display: flex;
  flex-direction: column;
  gap: clamp(0.75rem, 1.6vw, 1rem);
  flex: 1;
}
.service-card__title {
  font-family: var(--font-body);
  font-weight: 600;
  font-size: clamp(18px, 2vw, 24px);
  line-height: 1.2;
  color: var(--color-text-accent);
}
.service-card__bullets {
  display: grid;
  gap: var(--space-2);   /* 8px — tighter rhythm between bullets */
}
.service-card__bullet {
  display: flex;
  align-items: flex-start;        /* icon stays at the top with first line */
  gap: var(--space-2);
  color: var(--color-body-on-light);
  font-size: clamp(14px, 1.1vw, 16px);
  line-height: 1.5;
}
.service-card__bullet .check {
  flex-shrink: 0;
  width: 22px;
  height: 1lh;                    /* one line-height of the bullet text */
  display: inline-flex;
  align-items: center;            /* centers icon within that one line */
  color: var(--color-status-success);
}
.service-card__bullet .check svg {
  width: 22px;
  height: 22px;
  display: block;
}
.service-card__footer {
  border-top: 1px solid var(--color-border-default);
  padding: var(--space-3) var(--space-5);   /* 12px top/bottom, 24px left/right */
  display: flex;
  justify-content: flex-end;
}
.service-card__cta {
  display: inline-flex;
  align-items: center;
  gap: var(--space-3);
  font-family: var(--font-ui);
  font-weight: 700;
  font-size: 1rem;
  line-height: 1;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--color-text-accent);
  padding: var(--space-1) 0;
  transition: color 200ms ease;
}
.service-card__cta .icon { width: 16px; height: 16px; }

@media (max-width: 900px) {
  .services__grid { grid-template-columns: 1fr; }
}

/* ── Recent builds (Section 04) ──────────────────────────── */
.builds { background: var(--color-surface-page); padding-block: clamp(3rem, 8vw, 6rem); }

/* Header: intro (left) + IG button & arrows (right), container-aligned. */
.builds__top {
  display: flex;
  justify-content: space-between;
  align-items: flex-end;
  gap: var(--space-6);
  margin-bottom: var(--space-7);
  flex-wrap: wrap;
}
.builds__intro { max-width: 40rem; }
.builds__title {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(1.875rem, 4.5vw, 3rem);
  line-height: 1.25;
  letter-spacing: -0.015em;
  margin-top: var(--space-4);
  text-wrap: balance;
  color: var(--color-text-accent);
}
.builds__sub {
  font-size: clamp(15px, 1.3vw, 18px);
  line-height: 1.5;
  color: var(--color-body-on-light);
  margin-top: var(--space-3);
}
.builds__controls {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  flex-shrink: 0;
}
.builds__social { display: flex; gap: var(--space-2); }
.builds__social-btn {
  width: 44px;
  height: 44px;
  display: grid;
  place-items: center;
  background: transparent;
  border: 1px solid var(--color-border-strong);
  color: var(--color-text-accent);
  transition: background 120ms ease, border-color 120ms ease, color 120ms ease;
}
.builds__social-btn svg { width: 18px; height: 18px; }
.builds__social-btn:hover {
  background: var(--color-text-accent);
  border-color: var(--color-text-accent);
  color: var(--color-text-inverse);
}
.builds__arrows { display: flex; gap: var(--space-2); }
.builds__arrow {
  width: 44px;
  height: 44px;
  display: grid;
  place-items: center;
  background: transparent;
  border: 1px solid var(--color-border-strong);
  color: var(--color-text-accent);
  cursor: pointer;
  transition: background 120ms ease, border-color 120ms ease, color 120ms ease, opacity 120ms ease;
}
.builds__arrow svg { width: 20px; height: 20px; }
.builds__arrow:hover { background: var(--color-text-accent); border-color: var(--color-text-accent); color: var(--color-text-inverse); }
.builds__arrow[disabled] { opacity: 0.3; cursor: not-allowed; }

/* Full-bleed horizontal track. First card aligns to the container's left
   edge via padding-inline = the same gutter the .container uses; cards beyond
   the wrapper peek on the right. Manual scroll + scroll-snap, no autoplay. */
.builds__gallery {
  display: flex;
  gap: var(--space-7);              /* 48px — clears each card's dashed .framed decoration */
  overflow-x: auto;
  overflow-y: hidden;
  scroll-snap-type: x mandatory;
  scroll-behavior: smooth;
  scrollbar-width: none;            /* arrows are the control */
  -webkit-overflow-scrolling: touch;
  /* First card's left edge aligns to the .container content edge:
     half the leftover viewport beyond the 1488px container + the fluid gutter. */
  --builds-edge: calc(max(0px, (100vw - (var(--container-wide) + var(--container-gutter) * 2)) / 2) + clamp(1rem, 4vw, 1.5rem));
  padding-inline: var(--builds-edge);
  /* Vertical room so each card's dashed .framed decoration (extends ~20px
     beyond the box) isn't clipped by overflow-y: hidden. */
  padding-block: var(--space-5);
  scroll-padding-left: var(--builds-edge);
}
.builds__gallery::-webkit-scrollbar { display: none; }
.builds__gallery { cursor: grab; }
.builds__gallery.is-dragging { cursor: grabbing; scroll-snap-type: none; scroll-behavior: auto; }
.builds__gallery.is-dragging .project-tile { pointer-events: none; }   /* prevent text selection / accidental link during drag */

.project-tile {
  flex: 0 0 45%;                    /* 15% smaller than the previous 53% */
  scroll-snap-align: start;
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  background: transparent;          /* dashed .framed decoration only — no solid border */
}
.project-tile__media {
  aspect-ratio: 16 / 9;            /* cinematic landscape — matches service cards + form options */
  min-height: 0;
  overflow: hidden;
  background: var(--color-neutral-300) center/cover no-repeat;
}
.project-tile__media img { width: 100%; height: 100%; object-fit: cover; display: block; }
.project-tile__caption {
  display: flex;
  align-items: center;
  flex-wrap: wrap;
  gap: var(--space-2);
  padding: var(--space-2);
  font-family: var(--font-body);
  font-size: clamp(13px, 1.3vw, 16px);
  line-height: 1.3;
}
.project-tile__title { font-weight: 700; color: var(--color-text-accent); text-transform: uppercase; }
.project-tile__dot {
  width: 4px; height: 4px; border-radius: 999px;
  background: var(--color-text-accent); opacity: 0.5; flex-shrink: 0;
}
.project-tile__loc {
  font-weight: 400; color: var(--color-text-accent); opacity: 0.5;
  text-transform: uppercase; overflow: hidden; text-overflow: ellipsis;
}

@media (max-width: 900px) {
  .builds__top { flex-direction: column; align-items: flex-start; }
  .project-tile { flex-basis: 64%; }   /* ~1.4 cards per view */
}
@media (max-width: 600px) {
  .project-tile { flex-basis: 80%; }   /* ~1.1 cards per view */
  .builds__controls { width: 100%; justify-content: space-between; }
}

/* ── Instagram (Section 07 — Layout 414) ─────────────────── */
.ig {
  background: var(--color-surface-page);
  padding-top: clamp(3rem, 8vw, 6rem);
  padding-bottom: var(--space-2);   /* matches the IG row/tile gap */
  overflow: hidden;
}
.ig__header {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: var(--space-4);
  margin-bottom: var(--space-7);
}
.ig__title {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(1.875rem, 4.5vw, 3rem);
  line-height: 1.25;
  letter-spacing: -0.015em;
  text-wrap: balance;
  max-width: 38rem;
}
.ig__sub {
  font-size: clamp(15px, 1.3vw, 18px);
  line-height: 1.5;
  color: var(--color-body-on-light);
  max-width: 38rem;
}
.ig__follow {
  margin-top: var(--space-3);
}

/* Two-row marquee, rows scroll in opposite directions */
.ig__rows {
  display: grid;
  gap: var(--space-2);     /* 8px — was 16px */
}
.ig__row {
  display: flex;
  gap: var(--space-2);     /* 8px — was 16px */
  width: max-content;
  will-change: transform;
}
.ig__row--left  { animation: ig-scroll-left  90s linear infinite; }
.ig__row--right { animation: ig-scroll-right 90s linear infinite; }
.ig__row:hover  { animation-play-state: paused; }
@media (prefers-reduced-motion: reduce) {
  .ig__row { animation: none; }
}
@keyframes ig-scroll-left {
  from { transform: translateX(0); }
  to   { transform: translateX(-50%); }
}
@keyframes ig-scroll-right {
  from { transform: translateX(-50%); }
  to   { transform: translateX(0); }
}

.ig__rows-wrap {
  mask-image: linear-gradient(to right, transparent 0, #000 5%, #000 95%, transparent 100%);
  -webkit-mask-image: linear-gradient(to right, transparent 0, #000 5%, #000 95%, transparent 100%);
}

.ig__tile {
  flex: 0 0 clamp(200px, 18vw, 304px);
  aspect-ratio: 1;
  background: var(--color-neutral-300) center/cover no-repeat;
  display: block;
}

/* ── Reviews + Hardware (Section 06) ─────────────────────── */
.reviews {
  background: var(--color-surface-page);
  padding-block: clamp(3rem, 8vw, 6rem);
}
.reviews__header {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: var(--space-4);
  margin-bottom: var(--space-7);
}
.reviews__title {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(1.875rem, 4.5vw, 3rem);
  line-height: 1.25;
  letter-spacing: -0.015em;
  text-wrap: balance;
  max-width: 38rem;
}

/* Full-bleed marquee — auto-scrolls horizontally,
   fades on the left/right edges into the page bg */
.reviews__marquee {
  overflow: hidden;
  padding-block: var(--space-5);
  mask-image: linear-gradient(to right, transparent 0, #000 6%, #000 94%, transparent 100%);
  -webkit-mask-image: linear-gradient(to right, transparent 0, #000 6%, #000 94%, transparent 100%);
}
.reviews__track {
  display: flex;
  gap: var(--space-7);
  width: max-content;
  animation: reviews-scroll 80s linear infinite;
}
.reviews__track:hover { animation-play-state: paused; }
@media (prefers-reduced-motion: reduce) {
  .reviews__track { animation: none; }
}
@keyframes reviews-scroll {
  from { transform: translateX(0); }
  to   { transform: translateX(-50%); }    /* exactly half — original set ends, duplicate continues seamlessly */
}

.review-card {
  flex: 0 0 clamp(260px, 30vw, 432px);
  background: var(--color-surface-card);
  padding: var(--space-6) var(--space-5);
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: var(--space-5);
}
.review-card__source {
  display: flex;
  align-items: center;
  gap: var(--space-4);
}
.review-card__source-icon {
  width: 20px; height: 20px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-body);
  font-weight: 700;
  font-size: 16px;
  /* Multi-colour G stand-in until real SVG */
  color: var(--color-text-accent);
}
.review-card__divider {
  width: 1px;
  height: 20px;
  background: var(--color-border-strong);
}
.review-card__stars {
  display: inline-flex;
  gap: 2px;
  color: var(--color-status-star);
  font-size: 16px;
  line-height: 1;
}
.review-card__quote {
  font-family: var(--font-body);
  font-weight: 500;
  font-size: clamp(15px, 1.3vw, 20px);
  line-height: 1.5;
  color: var(--color-body-on-light);
}
.review-card__author {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  font-family: var(--font-body);
  font-weight: 500;
  font-size: 14px;
  color: var(--color-body-on-light);
}
.review-card__dot {
  width: 4px; height: 4px;
  border-radius: 999px;
  background: currentColor;
  flex-shrink: 0;
}

/* Hardware logos */
.hardware {
  margin-top: var(--space-9);
  text-align: center;
}
.hardware__title {
  font-family: var(--font-body);
  font-weight: 500;
  font-size: clamp(14px, 1.2vw, 18px);
  color: var(--color-body-on-light);
}
.hardware__grid {
  margin-top: var(--space-5);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: var(--space-6);
}
.hardware__logo {
  width: clamp(80px, 10vw, 140px);
  height: clamp(40px, 5vw, 64px);
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 8px;
}
.hardware__logo img {
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
  display: block;
}
.hardware__note {
  margin: var(--space-5) auto 0;
  max-width: 36rem;
  font-size: clamp(14px, 1.2vw, 18px);
  line-height: 1.5;
  color: var(--color-body-on-light);
}

/* ── Modal · Same-day ballpark wizard ─────────────────────── */
.modal {
  position: fixed;
  inset: 0;
  z-index: 200;
  display: flex;
  align-items: flex-end;        /* anchor card + badges to the bottom */
  justify-content: flex-end;    /* and to the right */
  padding: 20px;
  gap: 10px;
  background: rgb(0 0 0 / 0.55);
  backdrop-filter: blur(6px);
  -webkit-backdrop-filter: blur(6px);
  opacity: 0;
  visibility: hidden;
  transition: opacity 200ms ease, visibility 200ms;
}
.modal.is-open { opacity: 1; visibility: visible; }
/* Lock background scroll when modal/lightbox is open. position:fixed
   (with top set in JS to preserve scrollY) prevents the page bleeding
   when GF AJAX-submits and tries to scroll the form into view. */
body.modal-open {
	overflow: hidden;
	position: fixed;
	width: 100%;
	left: 0;
	right: 0;
}

/* Trust badges column (left of the modal card) */
.modal__badges {
  display: flex;
  flex-direction: column;
  justify-content: flex-end;
  gap: var(--space-3);
  width: 96px;
  flex-shrink: 0;
}
.modal__avatar {
  width: 96px; height: 96px;
  border-radius: 6.4px;
  background: #5c7a36 center/cover no-repeat;
  overflow: hidden;
}
.modal__divider {
  height: 1px;
  background: var(--color-border-inverse);
}
.modal__badge {
  width: 96px;
  height: 96px;
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}
.modal__badge img {
  width: 100%;
  height: 100%;
  object-fit: contain;
  display: block;
}

/* Card */
.modal__card {
  position: relative;
  width: 640px;
  /* Was fixed 920px — Step 1's image grid overflows. Auto sizing
     to current step content; only cap by viewport so tiny screens
     still scroll if absolutely necessary. dvh (dynamic viewport height)
     respects iOS Safari's address bar so the 4th Step 1 option doesn't
     get hidden under the chrome. Falls back to vh for older browsers. */
  height: auto;
  max-width: calc(100vw - 96px - 10px - 40px);
  max-height: calc(100vh - 40px);
  max-height: calc(100dvh - 40px);
  background: var(--color-text-inverse);
  border-radius: 8px;
  overflow: hidden;
  display: flex;
  flex-direction: column;
  box-shadow: 0 16px 40px rgb(0 0 0 / 0.25);
  transform: translateY(20px) scale(0.98);
  opacity: 0;
  transition: transform 280ms cubic-bezier(.2,.7,.2,1), opacity 220ms ease;
}
.modal.is-open .modal__card { transform: none; opacity: 1; }

/* Header (olive gradient) */
.modal__header {
  position: relative;
  background: linear-gradient(to right, var(--color-brand-olive-mid), #496a30);
  padding: 34px 60px;
  color: var(--color-text-inverse);
}
.modal__title {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(1.875rem, 3.5vw, 2.5rem);
  line-height: 1.25;
  text-align: center;
  margin-bottom: var(--space-4);
}
.modal__pills {
  display: flex;
  justify-content: center;
  gap: var(--space-5);
  flex-wrap: wrap;
}
.modal__pill {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: 16px;
  color: #eaf5d9;
  white-space: nowrap;
}
.modal__pill .icon { width: 16px; height: 16px; }

.modal__close {
  position: absolute;
  top: 14px; right: 14px;
  width: 36px; height: 36px;
  border-radius: 999px;
  background: var(--color-text-inverse);
  color: var(--color-text-primary);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  z-index: 2;
}
.modal__close:hover { background: var(--color-neutral-100); }
.modal__close .icon { width: 20px; height: 20px; }

/* Body */
.modal__body {
  flex: 1;
  display: flex;
  flex-direction: column;
  padding: 26px 60px;
  background: var(--color-text-inverse);
  overflow-y: auto;
}
.modal__step {
  flex-direction: column;
  gap: var(--space-4);
  height: 100%;
}
.modal__step-title {
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 18px;
  line-height: 1.3;
  color: #557434;
  text-align: center;
  margin-top: -8px;        /* tighter coupling with the small step indicator above */
}
.modal__choices {
  flex: 1;
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-3);
  /* Center the grid + give it breathing room so it feels like the focal point */
  max-width: 480px;
  width: 100%;
  margin: var(--space-5) auto;
  padding: 0;
  align-self: center;
}
.modal__choice {
  display: flex;
  flex-direction: column;
  background: var(--color-brand-cream);
  border: 2px solid transparent;
  cursor: pointer;
  overflow: hidden;
  transition: border-color 120ms ease, transform 100ms ease;
  text-align: left;
}
.modal__choice:hover { border-color: var(--color-brand-olive-mid); }
.modal__choice.is-selected {
  border-color: var(--color-brand-olive);
}
.modal__choice-media {
  flex: 1;
  min-height: 125px;
  background: var(--color-neutral-300) center/cover no-repeat;
}
.modal__choice-label {
  padding: 13px 12px;
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 15px;
  line-height: 1.2;
  color: var(--color-text-accent);
  text-align: center;
}
.modal__continue {
  width: 100%;
  background: var(--color-neutral-200);
  color: var(--color-neutral-500);
  border: 1px solid rgb(222 222 222 / 0.4);
  padding: 17px 22px;
  font-size: 15px;
  margin-top: auto;          /* always pin to bottom of the step */
}
.modal__continue:not(:disabled) {
  background: var(--color-brand-olive);
  color: var(--color-text-inverse);
  cursor: pointer;
}
.modal__continue:not(:disabled):hover { background: var(--color-brand-olive-hover); }
.modal__continue:disabled { cursor: not-allowed; }

/* Step nav (Back + Continue/Send) — steps 2 & 3 */
.modal__nav {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: var(--space-3);
  margin-top: auto;            /* pin to bottom — same place across steps */
}
.modal__back, .modal__submit {
  padding: 17px 22px;
  font-family: var(--font-ui);
  font-weight: 700;
  font-size: 15px;
  line-height: 1;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  cursor: pointer;
}
.modal__back {
  background: var(--color-text-inverse);
  color: var(--color-text-primary);
  border: 1px solid var(--color-border-default);
}
.modal__back:hover { background: var(--color-neutral-100); }
.modal__submit {
  background: var(--color-brand-olive);
  color: var(--color-text-inverse);
  border: 1px solid transparent;
}
.modal__submit:hover { background: var(--color-brand-olive-hover); }
.modal__submit .icon, .modal__back .icon { width: 16px; height: 16px; }

/* Field group */
.modal__field {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.modal__field-label {
  font-family: var(--font-body);
  font-weight: 600;
  font-size: 15px;
  color: var(--color-text-primary);
}
.modal__field-row {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-3);
}
.modal__input, .modal__textarea {
  width: 100%;
  background: var(--color-brand-cream);
  border: 1px solid transparent;
  padding: 10px 14px;
  font-family: var(--font-body);
  font-size: 16px;
  color: var(--color-text-primary);
  transition: border-color 120ms ease;
}
.modal__input::placeholder, .modal__textarea::placeholder { color: var(--color-text-muted); }
.modal__input:focus, .modal__textarea:focus {
  outline: none;
  border-color: var(--color-brand-olive-mid);
}
.modal__textarea { min-height: 72px; resize: vertical; font-family: inherit; }

/* Phone input with flag prefix */
.modal__phone {
  display: flex;
  align-items: center;
  background: var(--color-brand-cream);
}
.modal__phone-prefix {
  padding: 0 var(--space-3) 0 16px;
  font-size: 20px;
  line-height: 1;
}
.modal__phone .modal__input { background: transparent; padding-left: 0; }

/* Pill chip group (timeline, style) */
.modal__pill-group {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
}
.modal__pill-btn {
  background: var(--color-brand-cream);
  border: 1px solid transparent;
  padding: 9px 16px;
  font-family: var(--font-body);
  font-size: 14px;
  color: var(--color-text-primary);
  cursor: pointer;
  transition: border-color 120ms ease, background 120ms ease;
}
.modal__pill-btn:hover { border-color: var(--color-brand-olive-mid); }
.modal__pill-btn.is-selected {
  border-color: var(--color-brand-olive);
  background: #eaf5d9;
  color: var(--color-brand-olive);
  font-weight: 600;
}

/* Select (native, styled to match the cream inputs) */
.modal__select {
  appearance: none;
  -webkit-appearance: none;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2362685a' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><polyline points='6 9 12 15 18 9'/></svg>");
  background-repeat: no-repeat;
  background-position: right 16px center;
  background-size: 16px 16px;
  padding-right: 44px;
  cursor: pointer;
}

/* File upload dropzone */
.modal__upload {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: 10px var(--space-3);
  background: var(--color-brand-cream);
  border: 1.5px dashed var(--color-border-strong);
  cursor: pointer;
}
.modal__upload-icon {
  width: 24px; height: 24px;
  color: var(--color-text-secondary);
  flex-shrink: 0;
}
.modal__upload-text {
  display: flex;
  flex-direction: column;
  gap: 4px;
}
.modal__upload-headline {
  font-weight: 600;
  font-size: 15px;
  color: var(--color-text-primary);
}
.modal__upload-hint {
  font-size: 13px;
  color: var(--color-text-muted);
}

/* Show only the active step */
.modal__step { display: none; }
.modal__step.is-active { display: flex; }

/* Step indicator — smaller + lower contrast inside the modal */
.modal .eyebrow {
  --eyebrow-color: var(--color-text-muted);
  --eyebrow-border: var(--color-border-default);
  --eyebrow-slash: var(--color-border-strong);
  padding: 5px 10px;
  font-size: 11px;
  letter-spacing: 0.08em;
  gap: 6px;
}
.modal .eyebrow::before,
.modal .eyebrow::after { width: 8px; }

/* Footer (legal/disclaimer) */
.modal__footer {
  background: #f1f3f0;
  padding: 18px 56px;
  text-align: center;
  font-family: var(--font-body);
}
.modal__footer-headline {
  font-size: 15px;
  line-height: 1.4;
  color: var(--color-text-secondary);
}
.modal__footer-headline strong { font-weight: 700; }
.modal__legal {
  margin-top: 4px;
  font-size: 12px;
  font-weight: 500;
  line-height: 1.4;
  color: var(--color-neutral-400);
}
.modal__legal a {
  color: var(--color-brand-olive);
  text-decoration: underline;
}
.modal__legal-links {
  margin-top: 6px;
  font-size: 12px;
  color: var(--color-neutral-400);
  display: flex;
  justify-content: center;
  gap: 8px;
}
.modal__legal-links a { color: var(--color-brand-olive); text-decoration: none; }
.modal__legal-links a:hover { text-decoration: underline; }
.modal__legal-links span { opacity: 0.5; }
/* The footer chrome (lead + legal) belongs to the form's Submit button, so it
   only shows on the step that actually has a Submit. JS toggles .quote-has-submit
   on the modal when a visible submit button is present (i.e. the final GF page). */
.modal__footer { display: none; }
.modal.quote-has-submit .modal__footer { display: block; }

/* Responsive */
@media (max-width: 900px) {
  /* Fullscreen + single scroll: the whole modal scrolls as one document, so
     the footer flows naturally after the form's submit button instead of
     being pinned to the viewport bottom. Edge-to-edge, no outer padding,
     no rounded corners. */
  .modal {
    display: block;            /* plain block scroll container (flex broke tall-step scrolling) */
    padding: 0;
    overflow-y: auto;
    -webkit-overflow-scrolling: touch;
  }
  .modal__badges { display: none; }
  .modal__card {
    width: 100%;
    height: auto;
    min-height: 100vh;
    min-height: 100dvh;
    max-width: 100%;
    max-height: none;
    border-radius: 0;
  }
  /* Body flows at natural height (no inner scroll); step doesn't force 100%. */
  .modal__body { flex: 0 0 auto; overflow: visible; padding: 20px; }
  .modal__step { height: auto; }
  /* Close stays reachable while the modal scrolls. */
  .modal__close {
    position: fixed;
    top: 10px; right: 10px;
    width: 32px; height: 32px;
    z-index: 10;
    box-shadow: 0 1px 4px rgb(0 0 0 / 0.2);
  }
  /* Compact green header — smaller heading + tighter gaps = less height. */
  .modal__header { padding: 18px 20px 14px; }
  .modal__title { font-size: 22px; margin-bottom: 10px; }
  .modal__pills { gap: 6px 14px; }
  .modal__pill { font-size: 12px; }
  .modal__footer { padding: 14px 20px; }
  .modal__footer-headline { font-size: 13px; }
  .modal__choice-media { min-height: 100px; }
  .modal__choice-label { padding: 10px 8px; font-size: 14px; }
}

/* ── Sticky callbar (Section 13) ─────────────────────────── */
.callbar {
  position: fixed;
  inset: auto 0 0 0;
  z-index: 100;
  background: var(--color-surface-page-dark);
  padding: var(--space-4) clamp(1rem, 4vw, 4rem);
  border-top: 1px solid var(--color-border-inverse);
  /* Hidden by default; JS adds .is-visible when between hero exit + CTA entry */
  transform: translateY(110%);
  opacity: 0;
  pointer-events: none;
  transition: transform 280ms cubic-bezier(.2,.7,.2,1), opacity 200ms ease;
}
.callbar.is-visible {
  transform: translateY(0);
  opacity: 1;
  pointer-events: auto;
}
.callbar__inner {
  max-width: 1080px;
  margin-inline: auto;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-5);
}
.callbar__text {
  font-family: var(--font-body);
  font-size: clamp(14px, 1.2vw, 18px);
  line-height: 1.3;
  color: var(--color-body-on-dark);
}
.callbar__text strong {
  font-weight: 700;
  color: var(--color-text-accent-soft);
  margin-right: var(--space-2);
}
.callbar__buttons {
  display: flex;
  gap: var(--space-2);
  flex-shrink: 0;
}
/* Callbar buttons share the header CTA classes (btn--outline-light btn--sm
   + btn--primary btn--sm) — same olive-oil gradient + shine sweep + lift
   as the navbar. The override below only tweaks padding so they fit the
   compact bar layout; everything else inherits from the shared .btn rules. */
.callbar__buttons .btn {
  padding: 14px 22px;
  font-size: 14px;
  line-height: 1;
}

@media (max-width: 600px) {
  .callbar { padding: var(--space-3); }
  .callbar__inner { gap: var(--space-3); flex-direction: column; align-items: stretch; text-align: center; }
  .callbar__text { font-size: 13px; }
  .callbar__buttons { justify-content: center; }
  .callbar__buttons .btn { flex: 1; padding: 10px 14px; font-size: 13px; }
}

/* ── Footer (Section 12) ─────────────────────────────────── */
.footer {
  background: var(--color-surface-page-dark);
  color: var(--color-body-on-dark);         /* every text element → one colour */
  padding-block: clamp(3rem, 6vw, 5rem) clamp(1.5rem, 3vw, 2.5rem);
  position: relative;          /* anchor for the top divider */
  overflow: hidden;
}
/* All footer content displayed at 60% opacity for a subtler tone. */
.footer__grid,
.footer__bottom { opacity: 0.6; }
/* Inherit everything to body-on-dark, then explicitly override headings to pure white */
.footer * { color: inherit; }
.footer .footer__logo,
.footer .footer__col-title { color: var(--color-text-inverse); }
.footer__grid {
  display: grid;
  grid-template-columns: 1.2fr 1fr 1fr;
  gap: clamp(2rem, 4vw, 4rem);
  padding-bottom: var(--space-7);
  border-bottom: 1px solid var(--color-border-inverse);
}
.footer__brand {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}
.footer__logo {
  display: inline-flex;
  align-items: center;
}
.footer__logo img {
  height: 32px;
  width: auto;
  filter: brightness(0) invert(1);
}
.footer__tagline {
  font-size: 14px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
.footer__col {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}
.footer__col-title {
  font-family: var(--font-ui);
  font-weight: 700;
  font-size: 14px;
  letter-spacing: 0.06em;
  text-transform: uppercase;
}
.footer__list {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  font-size: 15px;
  line-height: 1.5;
}
.footer__list-item {
  display: flex;
  align-items: center;
  gap: var(--space-3);
}
.footer__list-item a:hover { color: var(--color-text-inverse); }
.footer__list-item .icon { width: 16px; height: 16px; flex-shrink: 0; }

.footer__creds {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  font-size: 15px;
  line-height: 1.5;
}
.footer__cred {
  display: grid;
  grid-template-columns: 90px 1fr;
  gap: var(--space-3);
}
.footer__cred-label {
  font-family: var(--font-ui);
  font-weight: 700;
  font-size: 13px;
  letter-spacing: 0.05em;
  text-transform: uppercase;
}

.footer__bottom {
  display: flex;
  justify-content: space-between;
  gap: var(--space-4);
  padding-top: var(--space-5);
  font-size: 13px;
  letter-spacing: 0.05em;
  text-transform: uppercase;
}
.footer__bottom-links { display: flex; gap: var(--space-5); }
.footer__bottom-links-list {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-5);
  list-style: none;
  margin: 0;
  padding: 0;
}
.footer__bottom-links a:hover { color: var(--color-text-inverse); }

@media (max-width: 900px) {
  .footer__grid { grid-template-columns: 1fr; gap: var(--space-6); }
  .footer__bottom { flex-direction: column; gap: var(--space-3); }
}

/* ── Closing CTA (Section 11) ─────────────────────────────
   Olive gradient band — split layout: copy left, buttons right */
.cta {
  background: linear-gradient(to right, #5e7c36, #496a30);
  color: var(--color-text-inverse);
  padding-block: clamp(2rem, 5vw, 4rem);   /* tighter — reads as a banner */
  position: relative;          /* anchor for the top divider */
  overflow: hidden;
}
.cta__inner {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: var(--space-8);
  align-items: center;
}
.cta__copy {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}
.cta__title {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(2rem, 5.5vw, 4rem);
  line-height: 1.2;
  letter-spacing: -0.03em;
  color: var(--color-text-inverse);          /* white for max readability on olive */
  text-wrap: balance;
  max-width: 32rem;
}
.cta__lead {
  font-size: clamp(15px, 1.3vw, 20px);
  line-height: 1.5;
  color: var(--color-body-on-dark);
  max-width: 32rem;
}
.cta__buttons {
  display: flex;
  gap: var(--space-5);
}
/* CTA button overrides — match Figma padding exactly */
.cta__buttons .btn {
  padding: 17px 33px 17px 25px;
  gap: var(--space-5);
  font-size: 16px;
  line-height: 1;
}
/* On the green CTA banner the colour rule inverts:
   – secondary (Get a quote) → outline white text + white border at 35% (same
     opacity pattern as the callbar outline)
   – primary (Call) → white solid fill with olive text                       */
.btn--cta-outline {
  background: transparent;
  color: var(--color-text-inverse);
  border-color: color-mix(in srgb, currentColor 35%, transparent);
}
.btn--cta-outline:hover {
  color: var(--color-text-inverse);
  border-color: color-mix(in srgb, currentColor 60%, transparent);
  background: rgb(255 255 255 / 0.08);
}
.btn--cta-solid {
  background: var(--color-text-inverse);
  color: var(--color-brand-olive);
  border-color: transparent;
}
.btn--cta-solid:hover { background: var(--color-neutral-100); }

@media (max-width: 900px) {
  .cta__inner { grid-template-columns: 1fr; gap: var(--space-6); }
  .cta__buttons { flex-direction: column; gap: var(--space-3); }
  .cta__buttons .btn { width: 100%; justify-content: center; padding: 14px 20px; }
}

/* ── Service area + map (Section 10) — DARK ──────────────── */
.area {
  background: var(--color-surface-page-dark);
  color: var(--color-text-inverse);
  padding-block: clamp(3rem, 8vw, 6rem);
}
.area__top {
  display: grid;
  grid-template-columns: 452px 1fr;     /* fixed text column, map fills rest */
  gap: var(--space-7);
  align-items: start;
  margin-bottom: var(--space-7);
}
.area__copy { max-width: 28rem; }
.area__title {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(1.875rem, 4.5vw, 3rem);
  line-height: 1.3;
  letter-spacing: -0.015em;
  margin-top: var(--space-5);
  color: var(--color-text-inverse-muted);
  text-wrap: balance;
}
.area__lead {
  margin-top: var(--space-4);
  font-size: clamp(15px, 1.3vw, 20px);
  line-height: 1.5;
  color: var(--color-body-on-dark);
}
.area__map {
  position: relative;
  aspect-ratio: 848 / 480;
  background: var(--color-neutral-900) center/cover no-repeat;
}

/* 3-column area list with dashed top border (Figma rgba(75,76,72,0.4)) */
.area__grid {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: clamp(2rem, 6vw, 7rem);       /* 112px on desktop per Figma */
  padding-top: var(--space-6);
  border-top: 1px dashed rgb(75 76 72 / 0.4);
}
.area__col {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}
.area__col-title {
  font-family: var(--font-ui);
  font-weight: 700;
  font-size: 16px;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--color-text-accent-soft);
}
.area__col-body {
  font-size: 16px;
  line-height: 1.5;
  color: var(--color-body-on-dark);
}

@media (max-width: 900px) {
  .area__top { grid-template-columns: 1fr; gap: var(--space-6); }
  .area__map { aspect-ratio: 4 / 3; }
  .area__grid {
    grid-template-columns: 1fr;
    gap: var(--space-6);
    padding-top: var(--space-5);
  }
  .area__col-body { font-size: 15px; }
}

/* ── FAQ (Section 09) ────────────────────────────────────── */
.faq {
  background: var(--color-surface-page);
  padding-block: clamp(3rem, 8vw, 6rem);
}
.faq__header {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: var(--space-4);
  margin-bottom: var(--space-7);
}
.faq__title {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(1.875rem, 4.5vw, 3rem);
  line-height: 1.25;
  letter-spacing: -0.015em;
  text-wrap: balance;
}
.faq__list {
  max-width: 45rem;       /* ~724px Figma */
  margin: 0 auto;
}
.faq-item {
  border-bottom: 1px solid var(--color-border-strong);
}
.faq-item:first-of-type { border-top: 1px solid var(--color-border-strong); }

.faq-item > summary {
  list-style: none;
  cursor: pointer;
  padding: var(--space-5) 0;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  font-family: var(--font-body);
  font-weight: 600;
  font-size: clamp(16px, 1.4vw, 20px);
  line-height: 1.3;
  color: var(--color-text-primary);
  transition: color 120ms ease;
}
.faq-item > summary::-webkit-details-marker { display: none; }
.faq-item > summary:hover { color: var(--color-text-accent); }

/* + / − sign on the right */
.faq-item__sign {
  flex-shrink: 0;
  position: relative;
  width: 16px;
  height: 16px;
  color: var(--color-text-secondary);
}
.faq-item__sign::before,
.faq-item__sign::after {
  content: "";
  position: absolute;
  inset: auto 0;
  top: 50%;
  height: 1.5px;
  background: currentColor;
  transform: translateY(-50%);
}
.faq-item__sign::after { transform: translateY(-50%) rotate(90deg); transition: transform 200ms ease; }
.faq-item[open] .faq-item__sign::after { transform: translateY(-50%) rotate(0deg); }

.faq-item__answer {
  padding: 0 0 var(--space-5);
  font-size: clamp(15px, 1.3vw, 18px);
  line-height: 1.5;
  color: var(--color-body-on-light);
  max-width: 42rem;
}

/* ── Process · Four steps (Section 08) ───────────────────── */
.process {
  background: var(--color-surface-page-dark);
  color: var(--color-text-inverse);
  padding-top:    clamp(5rem, 14vw, 10rem);   /* extra room for the top bg image */
  padding-bottom: clamp(4rem, 10vw, 8rem);
  position: relative;
  overflow: hidden;
}
/* Background blueprint — covers the whole section at low opacity so the
   technical-drawing texture reads behind the title AND the step rail.
   --process-bg comes from the block's ACF field. */
.process::before {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background-image:
    var(--process-bg, linear-gradient(135deg, var(--color-neutral-600), var(--color-neutral-800)));
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  opacity: 0.18;
}
/* Soft vignette to keep step copy readable over the busiest parts of the drawing. */
.process::after {
  content: "";
  position: absolute;
  inset: 0;
  pointer-events: none;
  background: radial-gradient(ellipse at center, rgb(14 16 15 / 0) 0%, rgb(14 16 15 / 0.55) 90%);
}
.process > .container { position: relative; z-index: 1; }

.process__header {
  max-width: 42rem;                /* ~664px Figma */
  margin-bottom: clamp(3rem, 8vw, 6rem);   /* much more space below */
  display: flex;
  flex-direction: column;
  gap: var(--space-5);
}
.process__title {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(1.875rem, 4.5vw, 3rem);
  line-height: 1.3;
  letter-spacing: -0.015em;
  color: var(--color-text-inverse-muted);
  text-wrap: balance;
}
.process__sub {
  font-size: clamp(15px, 1.3vw, 20px);
  line-height: 1.5;
  color: var(--color-body-on-dark);
  padding-right: clamp(0px, 6vw, 96px);
}

/* Rail with 4 phases connected by a thin top line */
.process__rail {
  position: relative;
  display: grid;
  grid-template-columns: repeat(4, minmax(0, 1fr));
  column-gap: clamp(2rem, 5vw, 5rem);
  row-gap: var(--space-6);
}
.process__rail::before {
  content: "";
  position: absolute;
  left: 0; right: 0;
  top: 28px;                       /* matches the centre of the .process-step__num box */
  height: 1px;
  background: var(--color-surface-card-dark);
  z-index: 0;
}
.process-step {
  display: flex;
  flex-direction: column;
  gap: var(--space-6);
  position: relative;
  z-index: 1;
}
/* Bordered number box — uses section bg so the connecting line is naturally
   interrupted as it passes behind each box. */
.process-step__num {
  align-self: flex-start;
  background: var(--color-surface-page-dark);
  border: 1px solid var(--color-surface-card-dark);
  padding: var(--space-4) var(--space-3);
  font-family: var(--font-body);
  font-weight: 400;
  font-size: 20px;
  line-height: 1.5;
  color: var(--color-text-muted);
}
.process-step__copy {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}
.process-step__eyebrow {
  font-family: var(--font-ui);
  font-weight: 700;
  font-size: 16px;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--color-text-accent-soft);
}
.process-step__title {
  font-family: var(--font-body);
  font-weight: 400;
  font-size: 20px;
  line-height: 1.5;
  color: var(--color-text-inverse);
}
.process-step__body {
  font-family: var(--font-body);
  font-size: 16px;
  line-height: 1.5;
  color: var(--color-body-on-dark);
}

@media (max-width: 900px) {
  .process__rail {
    grid-template-columns: 1fr;
    row-gap: var(--space-6);
    position: relative;
    padding-left: var(--space-7);   /* room for the vertical line */
  }
  /* Replace the horizontal line with a vertical one running down the left edge */
  .process__rail::before {
    top: 0; bottom: 0;
    left: 28px;             /* matches the centre of the number box */
    right: auto;
    width: 1px;
    height: auto;
    background: var(--color-surface-card-dark);
  }
  .process-step {
    flex-direction: row;
    align-items: flex-start;
    gap: var(--space-4);
    /* number box anchored at left edge; copy fills */
    margin-left: calc(var(--space-7) * -1);
  }
  .process-step__num {
    flex: 0 0 auto;
    padding: var(--space-3);
    font-size: 16px;
    min-width: 56px;
    text-align: center;
    justify-content: center;
  }
  .process-step__copy {
    flex: 1;
    gap: var(--space-3);
    padding-top: var(--space-2);
  }
  .process-step__title { font-size: 18px; }
  .process-step__body  { font-size: 15px; }
  .process-step__eyebrow { font-size: 14px; }
  .process__header { margin-bottom: var(--space-6); gap: var(--space-4); }
  .process__sub { padding-right: 0; }
}

/* ── Owner (Section 05 — Meet Reuben) ───────────────────────
   Same full-bleed pattern as Hero: left text respects container,
   right graphic block bleeds to viewport edge. */
.owner {
  background: var(--color-surface-page-dark);
  color: var(--color-text-inverse);
  position: relative;
  overflow: hidden;
}
.owner__grid {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1fr);
  align-items: stretch;
}
.owner__copy {
  padding-block: clamp(3rem, 8vw, 6rem);
  padding-left: max(
    var(--container-gutter),
    calc((100vw - var(--container-wide)) / 2)
  );
  padding-right: var(--space-7);
  min-width: 0;
}
.owner__title {
  font-family: var(--font-display);
  font-weight: 400;
  font-size: clamp(1.875rem, 4.5vw, 3rem);
  line-height: 1.25;
  letter-spacing: -0.015em;
  margin-top: var(--space-4);
  text-wrap: balance;
  max-width: 33rem;
}
.owner__lead {
  margin-top: var(--space-5);
  font-size: clamp(16px, 1.4vw, 20px);
  line-height: 1.5;
  color: var(--color-body-on-dark);
  max-width: 33rem;
}
.owner__body {
  margin-top: var(--space-6);
  display: grid;
  gap: var(--space-3);
  color: var(--color-body-on-dark);
  font-size: clamp(15px, 1.25vw, 18px);
  line-height: 1.5;
  max-width: 33rem;
}
.owner__badges {
  margin-top: var(--space-7);
  display: flex;
  align-items: center;
  gap: var(--space-3);
}
.owner__badges img {
  height: 96px;
  width: auto;
  display: block;
}
@media (max-width: 600px) {
  .owner__badges img { height: 72px; }
}

/* Owner media — 3 layered photos sized in % so they scale with the column.
   Z-stack:
     tertiary (top-left)  — behind primary
     primary  (portrait)  — main subject
     secondary (bottom-right) — in front of primary  */
/* .owner__media IS a <figure> element, so we need to zero out the UA
   default `margin: 1em 40px` here directly — not on a child selector. */
.owner__media {
  position: relative;
  overflow: visible;
  min-height: 600px;       /* sensible floor so photos always have room */
  height: 100%;            /* fill the grid row exactly — no slack below */
  margin: 0;               /* kill UA figure margins (was 16px top/bottom) */
}
/* Higher specificity needed — `.framed` also sets `position: relative`
   and would otherwise win the cascade and break the absolute positioning */
.owner__media .owner__photo {
  position: absolute;
  /* Placeholders use distinct shades so each layer is visible
     in this preview. Replace with real images. */
}
/* Tertiary + secondary share the same proportions, mirrored —
   tertiary anchors to top-left, secondary to bottom-right. */
.owner__photo--tertiary {
  left: 4%;    top: 6%;
  width: 32%;  height: 40%;
  z-index: 1;
  background: var(--color-neutral-600) center/cover no-repeat;
}
.owner__photo--secondary {
  right: 4%;   bottom: 2%;
  width: 32%;  height: 40%;
  z-index: 3;
  background: var(--color-neutral-500) center/cover no-repeat;
}
/* Primary photo — preserves the file's natural aspect ratio (1076:1692,
   ~0.636 portrait), anchored to the TOP of the container, with bottom
   extending downward according to aspect. With wider side gutters (8%)
   the photo box is larger AND its aspect-derived height reaches the
   section bottom in most viewports, with any overflow clipped by
   .owner's overflow:hidden. Top of the photo (Reuben's face) is
   always visible; bottom flows as far as the container allows. */
.owner__photo--primary {
  left: 8%;    right: 8%;
  top: 0;      bottom: auto;
  width: auto; height: auto;
  max-width: 640px;
  margin-inline: auto;
  aspect-ratio: 1076 / 1692;
  z-index: 2;
  background: transparent center top / 100% 100% no-repeat;
  /* Fade the bottom 20% of the photo to transparent so whatever is
     behind it (the owner section's bg) shows through naturally —
     creates a soft diffusion at the bottom instead of painting black. */
  -webkit-mask-image: linear-gradient(to bottom, #000 80%, transparent 100%);
          mask-image: linear-gradient(to bottom, #000 80%, transparent 100%);
}

@media (max-width: 900px) {
  .owner__grid {
    grid-template-columns: 1fr;
  }
  .owner__copy {
    padding-inline: clamp(1rem, 4vw, 1.5rem);
    padding-block: clamp(2.5rem, 8vw, 4rem);
  }
  .owner__grid { gap: clamp(1rem, 4vw, 2rem); }

  /* Media moves to the top as a 4:3 landscape block,
     with the same horizontal gutter as the copy below */
  .owner__media {
    order: -1;
    aspect-ratio: 4 / 3;
    min-height: 0;
    margin-inline: clamp(1rem, 4vw, 1.5rem);
  }

  /* Re-orient the 3 photos for the wider landscape container.
     Each photo tighter to its anchor edge. */
  .owner__media .owner__photo--tertiary {
    left: 2%;  top: 6%;
    width: 30%; height: 60%;
    /* Mobile: preserve aspect ratio, no crop. */
    background-size: contain;
    background-position: left top;
  }
  .owner__media .owner__photo--primary {
    /* Same top-anchored, aspect-preserving model as desktop — width
       slightly larger (62.5% vs 18% gutter) for the mobile landscape
       block. Height derives from aspect; container's overflow handles
       any bleed past the bottom. */
    left: 18.75%;  top: 0;   bottom: auto;
    right: auto;   width: 62.5%;  height: auto;
    aspect-ratio: 1076 / 1692;
  }
  .owner__media .owner__photo--secondary {
    right: 2%; bottom: 4%;
    width: 30%; height: 60%;
    left: auto; top: auto;
    /* Mobile: preserve aspect ratio, no crop. */
    background-size: contain;
    background-position: right bottom;
  }
}

/* ── Torn-paper section divider ──────────────────────────────
   Lives as the FIRST CHILD of a section. Absolutely positioned at the
   top, full viewport width, height = the PNG's natural aspect ratio.
   The section it lives inside gets `padding-top: var(--divider-height)`
   so its own content starts BELOW the divider zone — but anything
   absolutely-positioned inside the section (photos, decorative
   backgrounds) can extend INTO the divider zone if desired and will
   show through the transparent mask rips. The OTHER (previous) section
   is completely untouched.

   The PNG mask is solid at the top and tapers into torn fragments at
   the bottom — rendering reads as:
     • Top region: solid mass in UPPER section's color = seamless
       extension of the upper section reaching down into this section.
     • Bottom region: torn fragments. Where mask is opaque the upper
       color paints; where transparent, this section's own bg/content
       shows through (the divider is layered on top of it).

   Change --divider-color (set per-boundary by the pair classes below)
   to recolor. Both solid colors and gradients work. */
.divider-torn {
  --divider-height: clamp(60px, 7vw, 120px);     /* fallback; variants override */
  --divider-color: var(--color-brand-cream);     /* upper section's color */
  --divider-lower-bg: var(--color-brand-cream);  /* lower section's color */

  position: absolute;
  top: 0;                                        /* default: at TOP of section */
  left: 0;
  right: 0;
  height: var(--divider-height);
  z-index: 5;
  pointer-events: none;

  /* Mask applied directly to the element. Where mask is OPAQUE the
     element renders (showing its background = the painted color);
     where mask is TRANSPARENT the element doesn't render at all —
     truly see-through, with nothing from the divider visible. No
     pseudo-element, no background "fill" rectangle behind the mask. */
  background: var(--divider-color);
  -webkit-mask-image: var(--divider-mask);
          mask-image: var(--divider-mask);
  -webkit-mask-position: center;
          mask-position: center;
  -webkit-mask-repeat: no-repeat;
          mask-repeat: no-repeat;
  -webkit-mask-size: 100% 100%;
          mask-size: 100% 100%;
}
/* Modifier — flips position to BOTTOM of the containing section and
   vertically flips the PNG (so the solid mass is at the section's
   bottom edge and the torn fragments point UP into this section).
   Paint color also swaps to --divider-lower-bg, so the solid mass
   reads as the NEXT section reaching up into this one. */
.divider-torn.divider-torn--at-bottom {
  top: auto;
  /* Negative bottom pushes the divider's outer edge 2px past the
     section's bottom — the PNG mask's top edge (now at the element
     bottom after scaleY flip) often has 1–2px of anti-aliased alpha,
     and shifting it past the boundary hides the resulting hairline
     via the section's overflow:hidden. */
  bottom: -2px;
  /* scaleY(-1) flips vertically so torn fragments point UP into the
     section; scaleX(-1) mirrors horizontally so the visual pattern
     reads in the opposite direction from the same PNG. */
  transform: scaleY(-1) scaleX(-1);
  background: var(--divider-lower-bg);
}

/* Pattern variants — height tracks each PNG's true natural aspect
   ratio. All PNGs are 2432px wide; the middle clamp value equals
   exactly (PNG_height / 2432) × 100vw so the divider renders at its
   intrinsic proportions at every viewport (no vertical stretch, no
   horizontal squash). Min floors keep mobile visible; max caps at
   the PNG's actual pixel height (never upscaled). */
.divider-torn--v1 { --divider-mask: url('../images/divider-sections-01.png'); --divider-height: clamp(50px,  5.02vw, 122px); }
.divider-torn--v2 { --divider-mask: url('../images/divider-sections-02.png'); --divider-height: clamp(58px,  6vw,    146px); }
.divider-torn--v3 { --divider-mask: url('../images/divider-sections-03.png'); --divider-height: clamp(136px,14.23vw, 346px); }
.divider-torn--v4 { --divider-mask: url('../images/divider-sections-04.png'); --divider-height: clamp(44px,  4.48vw, 109px); }
.divider-torn--v5 { --divider-mask: url('../images/divider-sections-05.png'); --divider-height: clamp(46px,  4.61vw, 112px); }
.divider-torn--v6 { --divider-mask: url('../images/divider-sections-06.png'); --divider-height: clamp(52px,  5.26vw, 128px); }
.divider-torn--v7 { --divider-mask: url('../images/divider-sections-07.png'); --divider-height: clamp(88px,  9.25vw, 225px); }
.divider-torn--v8 { --divider-mask: url('../images/divider-sections-08.png'); --divider-height: clamp(46px,  4.65vw, 113px); }

/* Boundary color pairs — name describes [upper section] → [lower section].
   Both colors are set explicitly so the divider works at either top or
   bottom of any section. CTA boundaries use the same horizontal olive
   gradient as the .cta section itself, so colors match across the join. */
.divider-torn--dark-cream  {
  --divider-color: var(--color-brand-charcoal);
  --divider-lower-bg: var(--color-brand-cream);
}
.divider-torn--cream-dark  {
  --divider-color: var(--color-brand-cream);
  --divider-lower-bg: var(--color-brand-charcoal);
}
.divider-torn--dark-olive  {
  --divider-color: var(--color-brand-charcoal);
  --divider-lower-bg: linear-gradient(to right, #5e7c36, #496a30);
}
.divider-torn--olive-dark  {
  --divider-color: linear-gradient(to right, #5e7c36, #496a30);
  --divider-lower-bg: var(--color-brand-charcoal);
}

/* Any section/footer that CONTAINS a divider must be position: relative
   so the absolutely-positioned divider anchors to it (and not to some
   further-up ancestor). */
section:has(> .divider-torn),
footer:has(> .divider-torn) { position: relative; }

/* Per-variant padding-TOP rules — apply when the divider is at the
   default (top) position. The :not() selector skips dividers that
   carry the --at-bottom modifier (those are handled below). */
section:has(> .divider-torn--v1:not(.divider-torn--at-bottom)), footer:has(> .divider-torn--v1:not(.divider-torn--at-bottom)) { padding-top: calc(clamp(3rem, 8vw, 6rem) + clamp(50px,  5.02vw, 122px)); }
section:has(> .divider-torn--v2:not(.divider-torn--at-bottom)), footer:has(> .divider-torn--v2:not(.divider-torn--at-bottom)) { padding-top: calc(clamp(3rem, 8vw, 6rem) + clamp(58px,  6vw,    146px)); }
section:has(> .divider-torn--v3:not(.divider-torn--at-bottom)), footer:has(> .divider-torn--v3:not(.divider-torn--at-bottom)) { padding-top: calc(clamp(3rem, 8vw, 6rem) + clamp(136px,14.23vw, 346px)); }
section:has(> .divider-torn--v4:not(.divider-torn--at-bottom)), footer:has(> .divider-torn--v4:not(.divider-torn--at-bottom)) { padding-top: calc(clamp(3rem, 8vw, 6rem) + clamp(44px,  4.48vw, 109px)); }
section:has(> .divider-torn--v5:not(.divider-torn--at-bottom)), footer:has(> .divider-torn--v5:not(.divider-torn--at-bottom)) { padding-top: calc(clamp(3rem, 8vw, 6rem) + clamp(46px,  4.61vw, 112px)); }
section:has(> .divider-torn--v6:not(.divider-torn--at-bottom)), footer:has(> .divider-torn--v6:not(.divider-torn--at-bottom)) { padding-top: calc(clamp(3rem, 8vw, 6rem) + clamp(52px,  5.26vw, 128px)); }
section:has(> .divider-torn--v7:not(.divider-torn--at-bottom)), footer:has(> .divider-torn--v7:not(.divider-torn--at-bottom)) { padding-top: calc(clamp(3rem, 8vw, 6rem) + clamp(88px,  9.25vw, 225px)); }
section:has(> .divider-torn--v8:not(.divider-torn--at-bottom)), footer:has(> .divider-torn--v8:not(.divider-torn--at-bottom)) { padding-top: calc(clamp(3rem, 8vw, 6rem) + clamp(46px,  4.65vw, 113px)); }

/* Per-variant padding-BOTTOM rules — apply when the divider carries
   the --at-bottom modifier (sits at the bottom edge of its section). */
section:has(> .divider-torn--v1.divider-torn--at-bottom), footer:has(> .divider-torn--v1.divider-torn--at-bottom) { padding-bottom: calc(clamp(3rem, 8vw, 6rem) + clamp(50px,  5.02vw, 122px)); }
section:has(> .divider-torn--v2.divider-torn--at-bottom), footer:has(> .divider-torn--v2.divider-torn--at-bottom) { padding-bottom: calc(clamp(3rem, 8vw, 6rem) + clamp(58px,  6vw,    146px)); }
section:has(> .divider-torn--v3.divider-torn--at-bottom), footer:has(> .divider-torn--v3.divider-torn--at-bottom) { padding-bottom: calc(clamp(3rem, 8vw, 6rem) + clamp(136px,14.23vw, 346px)); }
section:has(> .divider-torn--v4.divider-torn--at-bottom), footer:has(> .divider-torn--v4.divider-torn--at-bottom) { padding-bottom: calc(clamp(3rem, 8vw, 6rem) + clamp(44px,  4.48vw, 109px)); }
section:has(> .divider-torn--v5.divider-torn--at-bottom), footer:has(> .divider-torn--v5.divider-torn--at-bottom) { padding-bottom: calc(clamp(3rem, 8vw, 6rem) + clamp(46px,  4.61vw, 112px)); }
section:has(> .divider-torn--v6.divider-torn--at-bottom), footer:has(> .divider-torn--v6.divider-torn--at-bottom) { padding-bottom: calc(clamp(3rem, 8vw, 6rem) + clamp(52px,  5.26vw, 128px)); }
section:has(> .divider-torn--v7.divider-torn--at-bottom), footer:has(> .divider-torn--v7.divider-torn--at-bottom) { padding-bottom: calc(clamp(3rem, 8vw, 6rem) + clamp(88px,  9.25vw, 225px)); }
section:has(> .divider-torn--v8.divider-torn--at-bottom), footer:has(> .divider-torn--v8.divider-torn--at-bottom) { padding-bottom: calc(clamp(3rem, 8vw, 6rem) + clamp(46px,  4.65vw, 113px)); }

/* Full-bleed exceptions — sections whose content (photos, gallery)
   should run flush to the bottom edge instead of being pushed up by
   the auto padding-bottom from the :has rules. The bottom divider
   sits OVER the content, with its rips revealing what's behind. */
/* Owner bottom tightening — same pattern as the top + hero: half the
   generic v2 at-bottom rule's padding-bottom. Bumped selector with
   `section` to beat the generic rule's specificity, source order wins. */
section.owner:has(> .divider-torn--at-bottom) {
  padding-bottom: calc((clamp(3rem, 8vw, 6rem) + clamp(58px, 6vw, 146px)) / 2);
}

/* Hero-specific tightening — half of what the generic per-variant
   rule applies (~200px → ~100px on desktop). `section` in the selector
   matches the generic rule's specificity so source order wins. */
section.hero-wrapper:has(> .divider-torn--at-bottom) {
  padding-bottom: calc((clamp(3rem, 8vw, 6rem) + clamp(58px, 6vw, 146px)) / 2);
}

/* Owner-specific tightening — same pattern as hero: half of the
   generic v7 rule's padding-top, since the owner's top divider zone
   is large by default. */
section.owner:has(> .divider-torn--v7) {
  padding-top: calc((clamp(3rem, 8vw, 6rem) + clamp(88px, 9.25vw, 225px)) / 2);
}

/* ── Framed · crop-mark ornament ────────────────────────────
   Two crossed rectangles offset OUTSIDE the element:
     ::before = horizontal pair (top + bottom)   — extends sideways past corners
     ::after  = vertical pair   (left + right)   — extends up/down past corners
   At each corner the lines cross with a small overshoot.

   Usage:  <article class="card framed">…</article>
   Tweak:  --frame-offset (distance from edge)
           --frame-overshoot (how far each line extends past the corner)
           --frame-color · --frame-style · --frame-width
   ─────────────────────────────────────────────────────────── */
.framed {
  --frame-offset: var(--space-3);            /* 12px out from edge */
  --frame-overshoot: var(--space-2);         /*  8px past each corner */
  --frame-color: var(--color-border-strong); /* neutral/300 */
  --frame-style: dashed;
  --frame-width: 1px;
  position: relative;
}
/* Horizontal lines (top + bottom), wider than the box */
.framed::before {
  content: "";
  position: absolute;
  top:    calc(var(--frame-offset) * -1);
  bottom: calc(var(--frame-offset) * -1);
  left:   calc((var(--frame-offset) + var(--frame-overshoot)) * -1);
  right:  calc((var(--frame-offset) + var(--frame-overshoot)) * -1);
  border-top:    var(--frame-width) var(--frame-style) var(--frame-color);
  border-bottom: var(--frame-width) var(--frame-style) var(--frame-color);
  pointer-events: none;
}
/* Vertical lines (left + right), taller than the box */
.framed::after {
  content: "";
  position: absolute;
  top:    calc((var(--frame-offset) + var(--frame-overshoot)) * -1);
  bottom: calc((var(--frame-offset) + var(--frame-overshoot)) * -1);
  left:   calc(var(--frame-offset) * -1);
  right:  calc(var(--frame-offset) * -1);
  border-left:  var(--frame-width) var(--frame-style) var(--frame-color);
  border-right: var(--frame-width) var(--frame-style) var(--frame-color);
  pointer-events: none;
}
/* Variants */
.framed--tight  { --frame-offset: var(--space-2); --frame-overshoot: var(--space-1); }
.framed--loose  { --frame-offset: var(--space-5); --frame-overshoot: var(--space-3); }
.framed--dotted { --frame-style: dotted; }
.framed--solid  { --frame-style: solid; }

/* On dark sections the dashed lines should sit at 20% so they read as subtle */
.hero-wrapper .framed,
.owner .framed,
.process .framed,
.area .framed,
.footer .framed {
  --frame-color: color-mix(in srgb, var(--color-border-strong) 20%, transparent);
}

/* Grids using .framed children need gap ≥ 2 × (offset + overshoot)
   so adjacent frames don't overlap. Default = 2 × (12 + 8) = 40px. */

/* ── Visually-hidden ─────────────────────────────────────── */
.vh {
  position: absolute; width: 1px; height: 1px;
  padding: 0; margin: -1px; overflow: hidden;
  clip: rect(0,0,0,0); white-space: nowrap; border: 0;
}

/* ── Responsive — Tablet & below (≤900px) ────────────────── */
@media (max-width: 900px) {
  /* Hero stacks; copy gets standard container padding */
  .hero { grid-template-columns: 1fr; position: relative; }
  .hero__copy {
    padding-inline: clamp(1rem, 4vw, 1.5rem);
    padding-block: clamp(2rem, 6vw, 3rem);
    max-width: none;
  }
  /* Media goes ABOVE copy on mobile as a 4:3 block. Revert from the
     desktop's absolute positioning to relative so it sits as a normal
     grid item — but still keep position:relative so its inner stays
     anchored to it (not to .hero-wrapper). */
  .hero__media {
    position: relative;
    top: auto;
    right: auto;
    bottom: auto;
    width: auto;
    order: -1;
    aspect-ratio: 16 / 9;
    min-height: 0;
  }
  /* (Removed) Mobile hero wrapper padding-bottom — was pushing the torn
     divider 48px away from the marquee, leaving dead black space. The
     divider already sits at the wrapper bottom; no extra space needed. */

  /* Tighter internal hero spacing on small screens — case-by-case, not a formula */
  .hero__eyebrow { margin-bottom: 20px; }
  .hero__sub     { margin-top: 16px; font-size: 15px; }
  .hero__bullets { margin-top: 20px; gap: 8px; }
  .hero__bullet  { font-size: 14px; gap: 8px; }
  .hero__bullet .check,
  .hero__bullet .check svg,
  .service-card__bullet .check { width: 16px; height: 16px; }
  .hero__ctas    { margin-top: 24px; gap: 8px; }

  /* Topbar: hide inline nav (replaced by hamburger details) */
  .topbar__inner > .topbar__nav,
  .topbar__inner > .topbar__cta { display: none; }
  .topbar__hamburger { display: block; }

  /* Mobile topbar — more compact, more elegant. */
  .topbar__inner { padding-block: var(--space-4); }
  .topbar__logo img { height: 20px; }
  /* Hamburger: drop the boxed border + fixed 44px square. Become a
     borderless icon that hugs its content, with a subtle hover ring. */
  .topbar__hamburger > summary {
    width: auto;
    height: auto;
    padding: 6px;
    border: 0;
    background: transparent;
    border-radius: 6px;
    transition: background 120ms ease;
  }
  .topbar__hamburger > summary:hover { background: var(--color-white-15); }
  .topbar__hamburger[open] > summary { background: var(--color-white-15); }
  /* Slightly thinner, more refined bars. */
  .topbar__hamburger > summary .bars { width: 22px; height: 14px; }
  .topbar__hamburger > summary .bars::before,
  .topbar__hamburger > summary .bars::after,
  .topbar__hamburger > summary .bars > span { height: 1px; }

  /* Mobile callbar — drop the text label, keep just the buttons. */
  .callbar__text { display: none; }
  .callbar__inner { justify-content: center; }
  .callbar__buttons { flex: 1; }
  .callbar__buttons .btn { flex: 1; justify-content: center; }

  /* Mobile footer — slightly smaller scale + tighter layout. */
  .footer {
    padding-block: clamp(2rem, 5vw, 3rem) clamp(1rem, 2vw, 1.5rem);
    font-size: 13px;
  }
  .footer__grid { gap: var(--space-5); }
  .footer__col-title { font-size: 13px; }
  .footer__logo img { height: 22px; }

  /* About-us top divider on mobile — lower min height so v7 doesn't
     get vertically stretched ~2.4× on narrow screens. */
  section:has(> .divider-torn--v7:not(.divider-torn--at-bottom)) {
    padding-top: calc(clamp(3rem, 8vw, 6rem) + clamp(40px, 9.25vw, 225px));
  }
  .divider-torn--v7 { --divider-height: clamp(40px, 9.25vw, 225px); }
}

/* ── Responsive — Phone (≤600px) ─────────────────────────── */
@media (max-width: 600px) {
  /* Shrink the root so every rem-based size scales down (16 → 14px) */
  html { font-size: 87.5%; }

  /* Section grids collapse */
  .services__grid { grid-template-columns: 1fr; gap: var(--space-5); }

  /* Tighter section headers on mobile */
  .services__header,
  .reviews__header,
  .ig__header,
  .process__header,
  .faq__header,
  .area__top { margin-bottom: var(--space-5); }
  .services__title,
  .builds__title,
  .reviews__title,
  .ig__title,
  .faq__title,
  .area__title,
  .process__title { margin-top: var(--space-3); }
  .services__lede,
  .builds__sub,
  .ig__sub,
  .area__lead,
  .process__sub { margin-top: var(--space-3); }

  /* Hero CTAs stack to full-width on phones */
  .hero__ctas .btn,
  .builds__sub-ctas .btn { flex: 1 1 100%; }

  /* Service card image stays 16:9 on phones — let aspect-ratio drive height. */
  .service-card__media { height: auto; }
  .service-card__bullet .check { width: 16px; height: 16px; }

  /* Shrink the framed ornament so it doesn't crowd the viewport edge */
  .framed {
    --frame-offset: var(--space-2);     /* 8px */
    --frame-overshoot: var(--space-1);  /* 4px */
  }

  /* Recent builds carousel tightens its caption on phones (layout handled
     by the carousel rules earlier — flex-basis 80%, scroll-snap). */
  .project-tile { border-width: 4px; }
  .project-tile__caption { padding: 4px 6px; font-size: 12px; line-height: 1.25; }

  /* ── Reviews compact on mobile — show 1 + 0.5 cards visible ── */
  .reviews__header { margin-bottom: var(--space-5); gap: var(--space-3); }
  .reviews__track  { gap: var(--space-4); }                   /* 16px between cards */
  .review-card     {
    flex-basis: 70vw;                                          /* ~1.4 cards in view at 375px */
    padding: var(--space-5) var(--space-4);                    /* 24/16 tighter */
    gap: var(--space-4);                                       /* 16 internal */
  }
  .review-card__quote  { font-size: 15px; line-height: 1.45; }
  .review-card__author { font-size: 13px; }

  /* ── Hardware logos compact ── */
  .hardware       { margin-top: var(--space-7); }              /* 48 → was 96 */
  .hardware__grid { gap: var(--space-4); margin-top: var(--space-4); }
  .hardware__logo { width: 96px; height: 44px; font-size: 12px; }
  .hardware__note { margin-top: var(--space-4); font-size: 13px; }
}

/* ── Gallery lightbox ─────────────────────────────────────────
   Fullscreen image viewer. Restrained palette — neutral darks,
   cream text. No brand olive/green (kept exclusively for the
   primary call CTA). */
.lightbox {
  position: fixed;
  inset: 0;
  z-index: 200;
  background: rgba(14, 16, 15, 0.92);
  display: none;
  align-items: center;
  justify-content: center;
  padding: clamp(16px, 4vw, 48px);
}
.lightbox.is-open { display: flex; }

.lightbox__figure {
  margin: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-3);
  max-width: 100%;
  max-height: 100%;
}
.lightbox__image {
  display: block;
  max-width: 100%;
  max-height: calc(100vh - clamp(120px, 16vw, 200px));
  width: auto;
  height: auto;
  object-fit: contain;
  background: var(--color-neutral-800);
  border: 1px solid var(--color-border-inverse);
}
.lightbox__caption {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  font-family: var(--font-ui);
  font-size: 13px;
  letter-spacing: 0.05em;
  text-transform: uppercase;
  color: var(--color-text-inverse);
}
.lightbox__title { font-weight: 600; }
.lightbox__counter {
  font-weight: 500;
  color: var(--color-text-inverse-muted);
  padding-left: var(--space-4);
  border-left: 1px solid var(--color-border-inverse);
}

.lightbox__close,
.lightbox__nav {
  position: absolute;
  background: transparent;
  border: 1px solid var(--color-border-inverse);
  color: var(--color-text-inverse);
  width: 48px;
  height: 48px;
  border-radius: 999px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  transition: background 160ms ease, border-color 160ms ease;
}
.lightbox__close:hover,
.lightbox__nav:hover {
  background: var(--color-white-15);
  border-color: var(--color-text-inverse);
}
.lightbox__close svg,
.lightbox__nav svg { width: 20px; height: 20px; }
.lightbox__close { top: clamp(12px, 2vw, 24px); right: clamp(12px, 2vw, 24px); }
.lightbox__nav--prev { left: clamp(12px, 2vw, 24px); top: 50%; transform: translateY(-50%); }
.lightbox__nav--next { right: clamp(12px, 2vw, 24px); top: 50%; transform: translateY(-50%); }

@media (max-width: 900px) {
  .lightbox__close, .lightbox__nav { width: 40px; height: 40px; }
  .lightbox__caption { font-size: 12px; flex-direction: column; gap: var(--space-2); }
  .lightbox__counter { padding-left: 0; border-left: 0; }
}

/* Gallery tiles — show a subtle hover state so the click affordance is clear. */
.builds__gallery .project-tile {
  transition: transform 200ms ease, --frame-color 200ms ease;
}
.builds__gallery .project-tile:hover {
  --frame-color: var(--color-text-secondary);   /* neutral, no brand green */
  transform: translateY(-2px);
}

/* ============================================================
   Mobile compaction — single-column rhythm
   Audit pass: tighten section padding, hero block, builds gaps,
   service-grid, ig + workshop, area columns. Two breakpoints only
   (per agency convention): 900px tablet+, 600px phones.
   ============================================================ */

@media (max-width: 900px) {
	/* Topbar: minimise bottom padding so the hero carousel sits flush
	   beneath the logo (no dead black band). Keep top padding for breathing. */
	.topbar__inner { padding-top: var(--space-4); padding-bottom: var(--space-3); }

	/* HERO: zero top padding on every nesting level on mobile. Generic
	   `:has(> .divider-torn--v5)` rules and per-variant fallbacks were
	   pushing the carousel down. Carousel must sit flush below topbar. */
	section.hero-wrapper,
	.hero-wrapper,
	.hero,
	.hero__media,
	.hero__media-inner { padding-top: 0 !important; margin-top: 0 !important; }

	/* Generic mobile section padding. Sections WITHOUT a top torn divider
	   get full padding-block tightening. Sections WITH a top divider keep
	   their auto padding-top (the :has() rules) and only get padding-bottom
	   reduced — otherwise the divider crashes into the content below it. */
	.services,
	.builds,
	.reviews,
	.ig,
	.process,
	.area { padding-block: clamp(2.5rem, 7vw, 4rem) !important; }

	.owner,
	.faq,
	.cta { padding-bottom: clamp(2.5rem, 7vw, 4rem) !important; }

	/* Hero copy on mobile sits BELOW the carousel (media has order:-1).
	   Add a gentle top spacer so the copy isn't flush against the carousel. */
	.hero__copy {
		padding-top: clamp(1.5rem, 5vw, 2.5rem);
		padding-bottom: clamp(1.5rem, 5vw, 2.5rem);
	}

	/* Recent builds: collapse the staggered offset; equal-column gap */
	.builds { padding-bottom: clamp(3rem, 8vw, 5rem) !important; }
	.builds__col--offset { padding-top: 0; }
	.builds__col { gap: var(--space-5); }
	.builds__gallery { margin-top: var(--space-5); gap: var(--space-5); }
	/* Sub copy sits directly under heading on mobile, not pushed down */
	.builds__top { gap: var(--space-3); }
	.builds__top > :last-child { padding-top: var(--space-2); }
	.builds__sub { margin-top: 0; }

	/* Services grid: stack with consistent gap */
	.services__grid { gap: var(--space-5); }
	.services__header { margin-bottom: var(--space-6); }

	/* IG rows: tighter */
	.ig__header { margin-bottom: var(--space-5); }

	/* Process steps: tighter rail */
	.process__rail { gap: var(--space-5); }

	/* FAQ + Area: tighter list spacing */
	.faq__list { gap: var(--space-3); }
	.area__grid { gap: var(--space-5); }
}

@media (max-width: 600px) {
	/* Phones — same split as 900px: sections without top divider get
	   full padding-block tightening; with-divider sections keep auto top. */
	.services,
	.builds,
	.reviews,
	.ig,
	.process,
	.area { padding-block: clamp(2rem, 6vw, 3rem) !important; }

	.owner,
	.faq,
	.cta { padding-bottom: clamp(2rem, 6vw, 3rem) !important; }

	.topbar__inner { padding-top: var(--space-3); padding-bottom: var(--space-2); }
	.hero__copy { padding-top: clamp(1.25rem, 4vw, 2rem); padding-bottom: clamp(1.25rem, 4vw, 2rem); }
	.hero__title { font-size: clamp(1.75rem, 8vw, 2.5rem); }
	.hero__sub { margin-top: var(--space-3); }
	.hero__ctas { margin-top: var(--space-5); flex-wrap: wrap; gap: var(--space-3); }

	.builds__col { gap: var(--space-4); }
	.builds__gallery { gap: var(--space-4); margin-top: var(--space-4); }

	.services__grid { gap: var(--space-4); }

	.owner__grid { gap: var(--space-6); }
	.owner__copy { padding-inline: var(--container-gutter); }

	.process-step { gap: var(--space-3); }

	.cta__inner { gap: var(--space-4); }
	.cta__buttons { flex-direction: column; align-items: stretch; gap: var(--space-3); }
	.cta__buttons .btn { justify-content: center; }
}

/* ============================================================
   Gravity Forms → Prototype Modal mapping
   Maps GF default classes to the exact values used by the
   prototype's .modal__* styles (lines 1095–1280 above).
   Scoped to .mg-gform so it only applies inside the quote modal.
   Per-field CSS Class additions needed in GF UI are listed in
   KNOWN_ISSUES.md and at the bottom of this block.
   ============================================================ */

.mg-gform { font-family: var(--font-body); color: var(--color-text-primary); }
.mg-gform .gform_fields {
	list-style: none;
	padding: 0;
	margin: 0;
	display: flex;
	flex-direction: column;
	gap: var(--space-4);
}

/* ── .gfield  →  .modal__field ──────────────────────────── */
.mg-gform .gfield {
	display: flex;
	flex-direction: column;
	gap: 6px;
}
.mg-gform .gfield_label,
.mg-gform .gform-field-label {
	font-family: var(--font-body);
	font-weight: 500;
	font-size: 13px;
	color: var(--color-text-secondary);
}
.mg-gform .gfield_required {
	color: var(--color-brand-olive);
	font-weight: 500;
	margin-left: 4px;
}
.mg-gform .gfield_description,
.mg-gform .gform-field-label--type-sub { font-size: 13px; color: var(--color-text-muted); margin-top: 4px; }

/* ── Text / email / tel / number / textarea  →  .modal__input ── */
.mg-gform input[type="text"],
.mg-gform input[type="email"],
.mg-gform input[type="tel"],
.mg-gform input[type="number"],
.mg-gform input[type="url"],
.mg-gform textarea {
	width: 100%;
	background: var(--color-brand-cream);
	border: 1px solid transparent;
	padding: 10px 14px;
	font-family: var(--font-body);
	font-size: 16px;
	color: var(--color-text-primary);
	transition: border-color 120ms ease;
}
.mg-gform input::placeholder,
.mg-gform textarea::placeholder { color: var(--color-text-muted); }
.mg-gform input:focus,
.mg-gform textarea:focus {
	outline: none;
	border-color: var(--color-text-primary);
}
.mg-gform textarea { min-height: 72px; resize: vertical; font-family: inherit; }

/* ── Select  →  .modal__select ──────────────────────────── */
.mg-gform select {
	width: 100%;
	background: var(--color-brand-cream);
	border: 1px solid transparent;
	padding: 10px 44px 10px 14px;
	font-family: var(--font-body);
	font-size: 16px;
	color: var(--color-text-primary);
	transition: border-color 120ms ease;
	appearance: none;
	-webkit-appearance: none;
	background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%2362685a' stroke-width='2' stroke-linecap='round' stroke-linejoin='round'><polyline points='6 9 12 15 18 9'/></svg>");
	background-repeat: no-repeat;
	background-position: right 16px center;
	background-size: 16px 16px;
	cursor: pointer;
}
.mg-gform select:focus { outline: none; border-color: var(--color-text-primary); }

/* ── First/Last name complex  →  .modal__field-row ───────── */
.mg-gform .ginput_complex {
	display: grid;
	grid-template-columns: 1fr 1fr;
	gap: var(--space-3);
}
.mg-gform .ginput_complex .ginput_left,
.mg-gform .ginput_complex .ginput_right,
.mg-gform .ginput_complex .ginput_full { width: 100%; }

/* Name field: drop the parent "Name" label and promote First/Last sublabels
   to look like regular field labels (sit above each input). */
.mg-gform .gfield--type-name > .gfield_label { display: none; }
.mg-gform .gfield--type-name .ginput_complex .gform-field-label--type-sub {
	font-family: var(--font-body);
	font-weight: 500;
	font-size: 13px;
	color: var(--color-text-secondary);
	margin-top: 0;
	margin-bottom: 6px;
	display: block;
}

/* ── Image-choice radio  →  .modal__choices + .modal__choice ── */
.mg-gform .gfield--type-radio .gfield_radio,
.mg-gform .gfield--type-image_choice .gfield_radio {
	display: grid;
	grid-template-columns: 1fr 1fr;
	gap: var(--space-3);
	padding: 0;
	margin: var(--space-3) 0 0;
	list-style: none;
	width: 100%;
}
/* The image_choice field's question is already shown as the page step
   header (see inc/gravity-forms-headers.php). The field's own legend
   would repeat it. Hide it visually but keep accessible to screen readers
   — clip technique, not display:none, so the <fieldset>'s accessible name
   isn't lost. Mirrors GF's default hidden_label behavior which doesn't
   load here because the parent theme disables all GF default CSS. */
.mg-gform .gfield--type-image_choice > .gfield_label,
.mg-gform .gfield--type-image_choice > legend.gfield_label {
	position: absolute !important;
	width: 1px;
	height: 1px;
	padding: 0;
	margin: -1px;
	overflow: hidden;
	clip: rect(0, 0, 0, 0);
	white-space: nowrap;
	border: 0;
}

.mg-gform .gfield--type-image_choice .gchoice {
	display: flex;
	flex-direction: column;
	background: var(--color-brand-cream);
	border: 2px solid transparent;
	cursor: pointer;
	overflow: hidden;
	transition: border-color 120ms ease;
	text-align: left;
	margin: 0;
}
.mg-gform .gfield--type-image_choice .gchoice:hover { border-color: var(--color-text-secondary); }
.mg-gform .gfield--type-image_choice .gchoice:has(input:checked) {
	border-color: var(--color-text-primary);
}
.mg-gform .gfield--type-image_choice .gchoice input[type="radio"],
.mg-gform .gfield--type-image_choice .gchoice input[type="checkbox"] {
	position: absolute;
	opacity: 0;
	pointer-events: none;
}
.mg-gform .gfield--type-image_choice .gchoice label {
	display: flex;
	flex-direction: column;
	cursor: pointer;
	width: 100%;
}
.mg-gform .gfield--type-image_choice .gchoice img {
	display: block;
	width: 100%;
	min-height: 0;
	aspect-ratio: 16 / 9;
	object-fit: cover;
	object-position: center;
}
.mg-gform .gfield--type-image_choice .gchoice .gform-field-label--type-inline,
.mg-gform .gfield--type-image_choice .gchoice label > span {
	padding: 13px 12px;
	font-family: var(--font-body);
	font-weight: 600;
	font-size: 15px;
	line-height: 1.2;
	color: var(--color-text-accent);
	text-align: center;
}

/* ── Regular radio + checkbox  →  basic .modal__field look ── */
.mg-gform .gfield--type-radio:not(.pills) .gchoice,
.mg-gform .gfield--type-checkbox:not(.pills) .gchoice {
	display: flex;
	align-items: center;
	gap: var(--space-3);
	background: transparent;
	border: 0;
	padding: 0;
}
.mg-gform .gfield--type-radio:not(.pills) .gfield_radio,
.mg-gform .gfield--type-checkbox:not(.pills) .gfield_checkbox {
	display: grid;
	grid-template-columns: 1fr;
	gap: var(--space-3);
}
.mg-gform input[type="radio"],
.mg-gform input[type="checkbox"] {
	appearance: none;
	width: 18px; height: 18px;
	border: 1.5px solid var(--color-border-strong);
	background: var(--color-brand-cream);
	cursor: pointer;
	margin: 0;
	flex-shrink: 0;
}
.mg-gform input[type="radio"] { border-radius: 50%; }
.mg-gform input[type="radio"]:checked {
	border-color: var(--color-text-primary);
	background: var(--color-text-primary);
	box-shadow: inset 0 0 0 3px var(--color-brand-cream);
}
.mg-gform input[type="checkbox"]:checked {
	border-color: var(--color-text-primary);
	background: var(--color-text-primary)
		url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16' fill='none' stroke='white' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'><polyline points='13 4 6 12 3 9'/></svg>")
		center / 14px no-repeat;
}

/* ── Pill-group radios & checkboxes  →  .modal__pill-group + .modal__pill-btn
   ENABLE: in GF, add CSS Class `pills` to a Radio or Checkbox field. */
.mg-gform .gfield.pills .gfield_radio,
.mg-gform .gfield.pills .gfield_checkbox {
	display: flex;
	flex-wrap: wrap;
	gap: var(--space-3);
	padding: 0;
	margin: 0;
	list-style: none;
}
.mg-gform .gfield.pills .gchoice {
	/* Expand to share the row equally: 1 → 100%, 2 → 50/50, 3 → 33%.
	   flex-grow fills the row; the ~33% basis caps it at 3 per row (mobile),
	   and a lone wrapped item grows to full width. Desktop bumps to 4. */
	flex: 1 1 calc(33.333% - var(--space-3));
	background: var(--color-brand-cream);
	border: 1px solid transparent;
	padding: 0;
	transition: border-color 120ms ease, background 120ms ease;
	margin: 0;
}
.mg-gform .gfield.pills .gchoice input[type="radio"],
.mg-gform .gfield.pills .gchoice input[type="checkbox"] {
	position: absolute; opacity: 0; pointer-events: none;
}
.mg-gform .gfield.pills .gchoice label {
	display: block;
	text-align: center;
	padding: 9px 12px;
	font-family: var(--font-body);
	font-size: 14px;
	color: var(--color-text-primary);
	cursor: pointer;
}
/* Desktop: up to 4 pills per row */
@media (min-width: 901px) {
	.mg-gform .gfield.pills .gchoice { flex-basis: calc(25% - var(--space-3)); }
}
.mg-gform .gfield.pills .gchoice:hover { border-color: var(--color-text-secondary); }
.mg-gform .gfield.pills .gchoice:has(input:checked) {
	border-color: var(--color-text-primary);
	background: color-mix(in srgb, var(--color-text-primary) 8%, var(--color-brand-cream));
}
.mg-gform .gfield.pills .gchoice:has(input:checked) label {
	color: var(--color-text-primary);
	font-weight: 600;
}

/* ── File upload  →  outer transparent, single dashed border on the
   inner drop area, full width. Brand olive is reserved for Call CTAs;
   form's "Select files" is a stroke/outline button on white. ── */
.mg-gform .gform_fileupload_multifile {
	background: transparent;
	border: 0;
	padding: 0;
	width: 100%;
}
.mg-gform .gform_drop_area {
	background: transparent;
	border: 1px dashed var(--color-border-strong);
	padding: var(--space-6) var(--space-5);
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: var(--space-4);
	width: 100%;
	text-align: center;
	color: var(--color-text-secondary);
}
.mg-gform .gform_drop_area .gform_drop_instructions {
	margin: 0;
	font-size: 14px;
}
.mg-gform .gform_button_select_files {
	display: inline-flex;
	align-items: center;
	gap: var(--space-2);
	background: transparent;
	color: var(--color-text-primary);
	border: 1px solid var(--color-text-primary);
	padding: 10px 18px;
	font-family: var(--font-ui);
	font-weight: 700;
	font-size: 14px;
	letter-spacing: 0.05em;
	text-transform: uppercase;
	cursor: pointer;
	border-radius: 0;
}
.mg-gform .gform_button_select_files:hover {
	background: var(--color-text-primary);
	color: var(--color-text-inverse);
}
/* Make the whole dashed area one big tap target: overlay the native file
   input transparently across it so a tap anywhere opens the picker. The raw
   input is invisible (opacity 0) so it no longer overlaps the instructions.
   (An earlier sr-only hide broke tapping on mobile — the input IS the picker.) */
.mg-gform .gform_fileupload_multifile,
.mg-gform .ginput_container_fileupload { position: relative; }
.mg-gform .gform_fileupload_multifile input[type="file"],
.mg-gform .ginput_container_fileupload > input[type="file"] {
	position: absolute !important;
	inset: 0 !important;
	width: 100% !important;
	height: 100% !important;
	margin: 0 !important;
	padding: 0 !important;
	opacity: 0 !important;
	cursor: pointer;
	z-index: 3;
	font-size: 0;
	color: transparent;
}
.mg-gform .gform_drop_area { position: relative; z-index: 1; }
.mg-gform .gform_drop_instructions { display: block; width: 100%; }

/* ── Page footer (Back/Next) + final Submit footer
   .gform_page_footer  →  .modal__nav (grid: auto + 1fr)
   .gform_footer       →  same                              */
.mg-gform .gform_page_footer,
.mg-gform .gform_footer {
	display: grid;
	grid-template-columns: auto 1fr;
	gap: var(--space-3);
	margin-top: auto;
	padding-top: var(--space-5);
}
/* First page (no Previous button) — fall back to single column */
.mg-gform .gform_page_footer:not(:has(.gform_previous_button)),
.mg-gform .gform_footer:not(:has(.gform_previous_button)) {
	grid-template-columns: 1fr;
}

/* Next + Submit — CHARCOAL, not olive. Olive (green) is reserved
   for Call CTAs site-wide; form action buttons use the dark brand colour. */
.mg-gform .gform_next_button,
.mg-gform .gform_button,
.mg-gform input[type="submit"].button {
	padding: 17px 22px;
	font-family: var(--font-ui);
	font-weight: 700;
	font-size: 15px;
	line-height: 1;
	letter-spacing: 0.05em;
	text-transform: uppercase;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: var(--space-2);
	cursor: pointer;
	background: var(--color-text-primary);
	color: var(--color-text-inverse);
	border: 1px solid transparent;
	border-radius: 0;
	width: 100%;
}
.mg-gform .gform_next_button:hover,
.mg-gform .gform_button:hover,
.mg-gform input[type="submit"].button:hover {
	background: color-mix(in srgb, var(--color-text-primary) 85%, var(--color-brand-cream));
}

/* Previous  →  .modal__back */
.mg-gform .gform_previous_button {
	padding: 17px 22px;
	font-family: var(--font-ui);
	font-weight: 700;
	font-size: 15px;
	line-height: 1;
	letter-spacing: 0.05em;
	text-transform: uppercase;
	display: inline-flex;
	align-items: center;
	justify-content: center;
	gap: var(--space-2);
	cursor: pointer;
	background: var(--color-text-inverse);
	color: var(--color-text-primary);
	border: 1px solid var(--color-border-default);
}
.mg-gform .gform_previous_button:hover { background: var(--color-neutral-100); }

/* ── Progress bar / step indicator
   We use whichever GF outputs based on Form Settings.       */
.mg-gform .gf_progressbar_wrapper,
.mg-gform .gform-progress-bars { margin-bottom: var(--space-5); }
.mg-gform .gf_progressbar,
.mg-gform .gform-progress-bar {
	background: var(--color-neutral-200);
	border-radius: 999px;
	height: 6px;
	overflow: hidden;
	border: 0;
}
.mg-gform .gf_progressbar_percentage,
.mg-gform .gform-progress-bar--percentage {
	background: var(--color-brand-olive);
	height: 100%;
	color: transparent;
	text-align: left;
}
.mg-gform .gf_progressbar_title,
.mg-gform .gform-progress-bar--title { display: none; }
.mg-gform .gf_page_steps,
.mg-gform .gform-page-steps {
	display: flex; gap: var(--space-4);
	margin-bottom: var(--space-5);
	list-style: none; padding: 0;
}
.mg-gform .gf_step,
.mg-gform .gform-page-step {
	flex: 1;
	font-family: var(--font-ui);
	font-size: 12px;
	font-weight: 700;
	letter-spacing: 0.06em;
	text-transform: uppercase;
	color: var(--color-text-muted);
	padding-top: var(--space-2);
	border-top: 2px solid var(--color-border-default);
}
.mg-gform .gf_step_active,
.mg-gform .gform-page-step--active {
	color: var(--color-brand-olive);
	border-top-color: var(--color-brand-olive);
}

/* ── Validation banner ──────────────────────────────────── */
.mg-gform .gform_validation_errors,
.mg-gform .validation_error {
	background: color-mix(in srgb, var(--color-status-error) 8%, var(--color-brand-cream));
	border: 1px solid color-mix(in srgb, var(--color-status-error) 30%, transparent);
	color: var(--color-status-error);
	padding: var(--space-3) var(--space-4);
	margin-bottom: var(--space-5);
	font-size: 14px;
}
.mg-gform .validation_message {
	color: var(--color-status-error);
	font-size: 13px;
	margin-top: 4px;
	background: transparent;
	border: 0;
	padding: 0;
}

/* ── Mobile form tuning ──────────────────────────────────── */
@media (max-width: 900px) {
	/* Step 1 image choices stay 2-col (→ 2×2 for four options), tighter gap */
	.mg-gform .gfield--type-image_choice .gfield_radio { gap: var(--space-2); }
	.mg-gform .gfield--type-image_choice .gchoice img { min-height: 0; }
	/* aspect-ratio: 16/9 already applied above — kept regardless of viewport */

	/* Pills: keep clear gaps (expanding grid), compact vertical padding */
	.mg-gform .gfield.pills .gchoice label { padding: 7px 12px; font-size: 13px; }
	.mg-gform .gfield--type-radio:not(.pills) .gfield_radio,
	.mg-gform .gfield--type-checkbox:not(.pills) .gfield_checkbox { gap: var(--space-2); }

	/* File upload: simplify to just the Select Files button (drop the icon,
	   the "Drag photos…" copy, and the dashed wrapper). */
	.mg-gform .gform_drop_area {
		border: 0;
		padding: 0;
		min-height: 0;
		justify-content: center;
	}
	.mg-gform .gform_drop_area .gform_drop_instructions { display: none; }
	.mg-gform .gform_button_select_files { width: 100%; justify-content: center; }

	/* Prev / Next / Submit: smaller text + tighter padding */
	.mg-gform .gform_next_button,
	.mg-gform .gform_previous_button,
	.mg-gform .gform_button,
	.mg-gform input[type="submit"].button {
		padding: 12px 16px;
		font-size: 13px;
	}
}

/* ── Phone: first/last name stacks ───────────────────────── */
@media (max-width: 600px) {
	.mg-gform .ginput_complex { grid-template-columns: 1fr; }
}

/* ── Thank-you state (custom HTML from gform_confirmation) ─ */
.mg-thank-you {
	padding: var(--space-7) 0;
	display: grid;
	gap: var(--space-4);
}
.mg-thank-you__icon {
	width: 48px; height: 48px;
	border-radius: 50%;
	background: var(--color-text-primary);
	color: var(--color-text-inverse);
	display: grid; place-items: center;
}
.mg-thank-you__heading {
	font-family: var(--font-display);
	font-size: clamp(1.5rem, 3vw, 2rem);
	font-weight: 500;
	color: var(--color-text-primary);
	margin: 0;
}
.mg-thank-you__subhead {
	color: var(--color-body-on-light);
	font-size: 1rem;
	margin: 0;
}
.mg-thank-you__id { font-size: 14px; color: var(--color-text-secondary); margin: 0; }
.mg-thank-you__id code {
	background: var(--color-brand-cream);
	padding: 2px 8px;
	font-family: var(--font-ui);
}
.mg-thank-you__ctas { display: flex; gap: var(--space-3); flex-wrap: wrap; margin-top: var(--space-3); }

/* ── Delta Gates thank-you state (overrides .mg-thank-you for quote form) ── */
.dg-ty {
	padding: var(--space-6) 0 var(--space-4);
	display: grid;
	gap: var(--space-5);
	text-align: center;
	justify-items: center;
}
.dg-ty__head { display: grid; gap: var(--space-2); justify-items: center; max-width: 520px; }
.dg-ty__icon {
	width: 48px; height: 48px;
	background: #22c55e;
	color: #fff;
	border-radius: 50%;
	display: grid; place-items: center;
}
/* Pure-CSS checkmark — survives TinyMCE Visual mode (SVGs get stripped). */
.dg-ty__check {
	display: inline-block;
	width: 10px; height: 18px;
	border: solid #fff;
	border-width: 0 3px 3px 0;
	transform: rotate(45deg);
	margin-bottom: 4px;
}
.dg-ty__heading {
	font-family: var(--font-display);
	font-size: clamp(1.5rem, 3vw, 1.875rem);
	font-weight: 500;
	color: var(--color-text-primary);
	line-height: 1.2;
	margin: 0;
}
.dg-ty__subhead {
	color: var(--color-body-on-light);
	font-size: 1rem;
	margin: 0;
}

/* Horizontal step timeline: 3 columns with connector line behind the circles. */
.dg-ty__steps {
	list-style: none;
	margin: 0; padding: 0;
	width: 100%;
	display: grid;
	grid-template-columns: 1fr 1fr 1fr;
	gap: var(--space-3);
	position: relative;
}
.dg-ty__steps::before {
	content: "";
	position: absolute;
	top: 18px;
	left: 16.66%;
	right: 16.66%;
	height: 2px;
	background: var(--color-brand-cream);
	z-index: 0;
}
.dg-ty__step {
	display: grid;
	justify-items: center;
	gap: 6px;
	text-align: center;
	position: relative;
	z-index: 1;
}
.dg-ty__step-num {
	width: 36px; height: 36px;
	background: var(--color-brand-cream);
	color: #3a2a14;
	font-family: var(--font-ui);
	font-weight: 700;
	font-size: 14px;
	display: grid; place-items: center;
	border-radius: 50%;
	box-shadow: 0 0 0 4px #fff;
}
.dg-ty__step-when {
	font-family: var(--font-body);
	font-weight: 600;
	font-size: 14px;
	color: var(--color-text-primary);
	margin-top: 4px;
}
.dg-ty__step-body { font-size: 13px; color: var(--color-body-on-light); line-height: 1.45; }

/* Echoed selections card */
.dg-ty__echo {
	background: var(--color-brand-cream);
	padding: var(--space-3) var(--space-4);
	display: grid;
	justify-items: center;
	gap: 4px;
	text-align: center;
	width: 100%;
}
.dg-ty__echo-label {
	font-family: var(--font-ui);
	font-size: 11px;
	font-weight: 700;
	letter-spacing: 0.08em;
	text-transform: uppercase;
	color: var(--color-text-secondary);
}
.dg-ty__echo-bits {
	margin: 0;
	font-size: 15px;
	color: var(--color-text-primary);
	line-height: 1.5;
}
.dg-ty__echo-bits strong { font-weight: 600; }
.dg-ty__echo-bits span { color: var(--color-text-muted); margin: 0 4px; }
.dg-ty__echo-ref { margin: 0; font-size: 13px; color: var(--color-text-secondary); }
.dg-ty__echo-ref code {
	background: #fff;
	padding: 1px 6px;
	font-family: var(--font-ui);
	font-size: 12px;
}

/* Owner note — centered single column */
.dg-ty__note {
	display: grid;
	justify-items: center;
	text-align: center;
	gap: var(--space-3);
	padding: var(--space-4) 0;
	border-top: 1px solid var(--color-border);
	border-bottom: 1px solid var(--color-border);
}
.dg-ty__note-avatar {
	width: 64px; height: 64px;
	border-radius: 50%;
	background-size: cover;
	background-position: center;
}
.dg-ty__note-body { margin: 0; max-width: 460px; display: grid; gap: 8px; }
.dg-ty__note-body p {
	margin: 0;
	font-family: var(--font-display);
	font-size: 17px;
	line-height: 1.5;
	color: var(--color-text-primary);
	font-style: italic;
}
.dg-ty__note-body cite {
	font-style: normal;
	font-family: var(--font-ui);
	font-size: 12px;
	letter-spacing: 0.04em;
	text-transform: uppercase;
	color: var(--color-text-secondary);
}

/* CTA stack — primary call button + subtle back link below */
.dg-ty__cta {
	display: grid;
	justify-items: center;
	gap: var(--space-2);
	margin-top: var(--space-2);
}
.dg-ty__back {
	font-size: 13px;
	color: var(--color-text-secondary);
	text-decoration: none;
}
.dg-ty__back:hover { color: var(--color-brand-olive); text-decoration: underline; }

@media (max-width: 600px) {
	.dg-ty__note-avatar { width: 56px; height: 56px; }
}


/* ============================================================
   Gravity Forms — patch pass (post-default-CSS-disable)
   - Kill the <fieldset> border around radio/checkbox groups
   - Tighten file upload + textarea inner padding
   - Hide GF's progress bar; style GF "Steps" as a single eyebrow chip
     matching the prototype's STEP X OF 3 design.
   ============================================================ */

/* Kill fieldset default border around radio/checkbox groups */
.mg-gform fieldset,
.mg-gform .gfield fieldset {
	border: 0;
	padding: 0;
	margin: 0;
	min-width: 0;
}
.mg-gform legend.gfield_label {
	padding: 0;
	margin-bottom: var(--space-2);
}

/* Image-choice cards: no border on the wrapper, only on the cards */
.mg-gform .gfield--type-image_choice .ginput_container_radio,
.mg-gform .gfield--type-image_choice .gfield_radio {
	border: 0 !important;
	padding: 0;
	background: transparent;
}

/* File upload: cream block w/ tighter padding (was 48px → 24px) */
.mg-gform .gform_fileupload_multifile,
.mg-gform .gform_drop_area {
	padding: var(--space-5);  /* 24px */
	display: flex;
	flex-direction: column;
	align-items: flex-start;
	gap: var(--space-3);
}
.mg-gform .gform_drop_area .gform_drop_instructions,
.mg-gform .gform_fileupload_multifile .gform_drop_instructions {
	margin: 0;
	font-size: 14px;
	color: var(--color-text-secondary);
}

/* Textarea: tighter padding + min-height to match modal__textarea */
.mg-gform textarea {
	padding: 10px 14px;
	min-height: 72px;
}

/* ── Pagination ──────────────────────────────────────────── */

/* Hide GF's progress bar variant entirely (we use Steps mode) */
.mg-gform .gf_progressbar_wrapper,
.mg-gform .gform-progress-bars {
	display: none !important;
}

/* GF "Steps" mode: show as a SINGLE current-step eyebrow chip,
   matching the prototype's "/ STEP X OF 3 /" eyebrow style. */
.mg-gform .gf_page_steps,
.mg-gform .gform-page-steps,
.mg-gform .gf_step_steps_visible_active {
	display: block !important;
	border: 0;
	background: transparent;
	padding: 0;
	margin: 0 auto var(--space-5);
	text-align: center;
	width: max-content;
}
/* Hide all non-active steps */
.mg-gform .gf_step,
.mg-gform .gform-page-step {
	display: none !important;
}
/* Show only the active step, as an eyebrow chip */
.mg-gform .gf_step_active,
.mg-gform .gform-page-step--active {
	display: inline-block !important;
	font-family: var(--font-ui);
	font-size: 11px;
	font-weight: 700;
	letter-spacing: 0.12em;
	text-transform: uppercase;
	color: var(--color-text-secondary);
	padding: 6px 14px;
	border: 1px solid var(--color-border-default);
	border-radius: 0;
	background: transparent;
}
/* Eyebrow's "/ … /" slashes */
.mg-gform .gf_step_active::before,
.mg-gform .gform-page-step--active::before { content: "/ "; color: var(--color-brand-olive); }
.mg-gform .gf_step_active::after,
.mg-gform .gform-page-step--active::after  { content: " /"; color: var(--color-brand-olive); }
/* Strip GF's internal numbering text (we want just "STEP X OF N") */
.mg-gform .gf_step_number,
.mg-gform .gform-page-step__number,
.mg-gform .gf_step_label,
.mg-gform .gform-page-step__label {
	all: unset;
	font: inherit;
	letter-spacing: inherit;
}

/* ============================================================
   GF refinements — round 3
   - Smaller, simpler upload zone (one line of copy, smaller btn)
   - Slimmer validation banner, absolutely positioned at top of card
     so it doesn't push form content down
   - Per-step heading styling (.step-heading)
   ============================================================ */

/* Upload zone — flush dashed border, no padding on wrappers, icon + single
   line of copy + small outline button. Hide GF's duplicate description below. */
.mg-gform .gform_fileupload_multifile { padding: 0; background: transparent; border: 0; }
.mg-gform .gform_drop_area {
	padding: 0;
	gap: var(--space-3);
	flex-direction: row;
	align-items: center;
	flex-wrap: wrap;
	border: 1px dashed var(--color-border-strong);
	min-height: 56px;
	padding-inline: var(--space-4);
}
/* Replace GF's "Drop files here or" with our icon + copy. */
.mg-gform .gform_drop_area .gform_drop_instructions {
	font-size: 14px;
	margin: 0;
	flex: 1;
	min-width: 0;
	color: var(--color-text-secondary);
	font-size: 0;        /* hide original text */
	display: inline-flex;
	align-items: center;
	gap: 10px;
}
.mg-gform .gform_drop_area .gform_drop_instructions::before {
	content: '';
	width: 18px;
	height: 18px;
	flex-shrink: 0;
	background: currentColor;
	-webkit-mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'><path d='M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4'/><polyline points='17 8 12 3 7 8'/><line x1='12' y1='3' x2='12' y2='15'/></svg>") no-repeat center / contain;
	        mask: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='1.8' stroke-linecap='round' stroke-linejoin='round'><path d='M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4'/><polyline points='17 8 12 3 7 8'/><line x1='12' y1='3' x2='12' y2='15'/></svg>") no-repeat center / contain;
}
.mg-gform .gform_drop_area .gform_drop_instructions::after {
	content: 'Drag photos or click to upload';
	font-size: 14px;
	color: var(--color-text-secondary);
	white-space: nowrap;
}
/* Hide the duplicate descriptions GF prints below the drop area. */
.mg-gform .gform_fileupload_rules,
.mg-gform .gfield--type-fileupload .gfield_description { display: none !important; }

.mg-gform .gform_button_select_files {
	padding: 6px 12px;
	font-size: 12px;
	letter-spacing: 0.06em;
}

/* Validation banner — slim, absolutely positioned at top of modal__card
   so it doesn't reflow the form layout. */
.modal__card { position: relative; }
.mg-gform .gform_validation_errors,
.mg-gform .validation_error {
	position: absolute;
	top: 0;
	left: 0;
	right: 0;
	z-index: 5;
	margin: 0;
	padding: 10px 16px;
	font-size: 13px;
	background: color-mix(in srgb, var(--color-status-error) 12%, var(--color-paper, var(--color-brand-cream-soft)));
	border: 0;
	border-bottom: 1px solid color-mix(in srgb, var(--color-status-error) 30%, transparent);
	color: var(--color-status-error);
	text-align: center;
	border-radius: 0;
	animation: dgErrorSlide 240ms cubic-bezier(.2,.7,.2,1);
}
@keyframes dgErrorSlide {
	from { transform: translateY(-100%); opacity: 0; }
	to   { transform: translateY(0); opacity: 1; }
}
.mg-gform .gform_validation_errors h2,
.mg-gform .gform_validation_errors .gform-icon,
.mg-gform .gform_validation_errors .gform_submission_error { font-size: inherit; margin: 0; display: inline; }
.mg-gform .gform_validation_errors ol,
.mg-gform .gform_validation_errors ul,
.mg-gform .gform_validation_errors a { display: none !important; } /* hide GF's auto-listed jump links */

/* Per-page heading. For each Page in GF, add an HTML field at the top of
   the page with: <h2 class="step-heading">What are you after?</h2>
   (no label on the HTML field). */
.mg-gform .step-heading,
.mg-gform h2.step-heading {
	font-family: var(--font-display);
	font-weight: 500;
	font-size: clamp(1.5rem, 3vw, 2rem);
	line-height: 1.15;
	color: var(--color-text-primary);
	margin: 0 0 var(--space-5);
	letter-spacing: -0.01em;
}

/* GF AJAX loading spinner — kill EVERY variant GF emits. The spinner
   is injected by JS at click time so we can't catch it server-side;
   broad selector covers gform_ajax_spinner (img), gform-loader (span),
   and the [data-js-spinner] attribute the modern Orbital uses. */
.mg-gform [data-js-spinner],
.mg-gform .gform_ajax_spinner,
.mg-gform img.gform_ajax_spinner,
.mg-gform .gform-loader,
.mg-gform .gform_ajax_loader,
.mg-gform span.gform-loader,
.mg-gform .ginput_quantity_container .gform-loader {
	display: none !important;
	width: 0 !important;
	height: 0 !important;
	margin: 0 !important;
	padding: 0 !important;
	visibility: hidden !important;
	position: absolute !important;
	opacity: 0 !important;
}

/* When form is mid-AJAX, GF sets data-active-form="true" — neutralise
   any GF default that would reserve space for the loader. */
.mg-gform .gform_wrapper[data-active-form="true"] .gform_page_footer,
.mg-gform .gform_wrapper[data-active-form="true"] .gform_footer,
.mg-gform [data-active-form] .gform_page_footer,
.mg-gform [data-active-form] .gform_footer { min-height: 0 !important; }
.mg-gform .gform_page_footer,
.mg-gform .gform_footer { position: relative; }

/* ============================================================
   Per-step header (injected by inc/gravity-forms-headers.php)
   Eyebrow chip + serif heading at the top of each GF page.
   ============================================================ */
.mg-gform .dg-step-header,
.mg-gform .step-header {
	text-align: center;
	margin: 0 auto;
	display: flex;
	flex-direction: column;
	align-items: center;
	gap: var(--space-4);
}
.mg-gform .step-label {
	display: inline-block;
	font-family: var(--font-ui);
	font-size: 11px;
	font-weight: 700;
	letter-spacing: 0.14em;
	text-transform: uppercase;
	color: var(--color-text-secondary);
	padding: 6px 14px;
	border: 1px solid var(--color-border-default);
	background: transparent;
}
.mg-gform .step-label::before { content: "/ "; color: var(--color-brand-olive); }
.mg-gform .step-label::after  { content: " /"; color: var(--color-brand-olive); }

/* Per Figma spec: Sofia Sans 20px semibold, #557434, 150% line-height */
.mg-gform h2.step-heading,
.mg-gform .step-heading {
	font-family: var(--font-body);   /* Sofia Sans */
	font-weight: 600;
	font-size: 1.25rem;              /* 20px */
	line-height: 1.5;                /* 150% */
	letter-spacing: 0;
	color: #557434;                  /* exact Figma swatch */
	margin: 0;
	text-align: center;
}

/* The eyebrow chip we previously rendered from GF Steps mode is redundant
   now — hide it (we inject our own per-page header). */
.mg-gform .gf_page_steps,
.mg-gform .gform-page-steps { display: none !important; }

/* Disabled Next / Submit (driven by site.js validity gate) */
.mg-gform .gform_next_button:disabled,
.mg-gform .gform_button:disabled,
.mg-gform [type="submit"]:disabled,
.mg-gform .gform_next_button.is-disabled,
.mg-gform .gform_button.is-disabled,
.mg-gform [type="submit"].is-disabled {
	background: var(--color-neutral-200) !important;
	color: var(--color-neutral-500) !important;
	border-color: transparent !important;
	cursor: not-allowed !important;
	pointer-events: none;
}

/* Loading state on Next / Submit during GF AJAX page transition. JS adds
   .is-loading on click; hook above clears it on gform_page_loaded /
   gform_confirmation_loaded.
   Note: GF renders these as <input type="button"> which cannot host
   ::before/::after pseudo-elements. The spinner is therefore an inline SVG
   with SMIL <animateTransform> served via background-image. SMIL animations
   inside an SVG continue rotating even when the SVG is used as a CSS
   background, in all modern browsers. */
/* Selector list deliberately includes specific input[type="submit"].button
   variants — the base button rule scopes by element + attribute + class
   (0,0,3,1), so the loading state must match or exceed it to win the
   background cascade on the final-page Submit button. */
.mg-gform .gform_next_button.is-loading,
.mg-gform .gform_button.is-loading,
.mg-gform input[type="submit"].button.is-loading,
.mg-gform input[type="submit"].gform_button.is-loading,
.mg-gform [type="submit"].is-loading {
	color: transparent !important;
	pointer-events: none;
	cursor: progress;
	background: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 32 32'><circle cx='16' cy='16' r='12' fill='none' stroke='rgba(255,255,255,0.35)' stroke-width='3'/><path d='M16 4a12 12 0 0 1 12 12' fill='none' stroke='%23ffffff' stroke-width='3' stroke-linecap='round'><animateTransform attributeName='transform' attributeType='XML' type='rotate' from='0 16 16' to='360 16 16' dur='0.6s' repeatCount='indefinite'/></path></svg>") center / 20px 20px no-repeat var(--color-text-primary) !important;
}

/* ============================================================
   iOS Safari fixes (Sequoia/iPhone-specific)
   - Modal body inner scroll via -webkit-overflow-scrolling
   - Hero on mobile: min-height fallback for aspect-ratio rendering bugs
   - Mobile 100dvh for viewport height
   ============================================================ */

.modal__body {
	-webkit-overflow-scrolling: touch;
	overscroll-behavior: contain;
}

@media (max-width: 900px) {
	/* Hero media on mobile: explicit min-height so the carousel renders even
	   when aspect-ratio fails. Older iOS Safari + some inner-grid combos
	   compute aspect-ratio:16/9 + inset:0 inner as 0px height. */
	.hero__media {
		aspect-ratio: 16 / 9;
		min-height: 56vw;     /* 16/9 ≈ 56% of viewport width — same as aspect-ratio */
		max-height: 80vh;
		max-height: 80dvh;
	}
	.hero__media-inner { min-height: inherit; }
}

/* Image-choice on phones: keep 2 columns (→ 2×2 for four options), with a
   shorter image so all four cards fit without excessive scrolling. */
@media (max-width: 600px) {
	.mg-gform .gfield--type-image_choice .gfield_radio { grid-template-columns: 1fr 1fr; }
	.mg-gform .gfield--type-image_choice .gchoice img {
		min-height: 0;
		aspect-ratio: 16 / 9;
	}
}


/* ============================================================
   Legal pages (Terms, Privacy Policy) — page-legal.php template
   ============================================================ */
.legal { padding: clamp(3rem, 8vw, 6rem) 0 clamp(4rem, 10vw, 8rem); background: #fff; }
.legal .container--narrow { max-width: 760px; margin: 0 auto; padding-left: 1.25rem; padding-right: 1.25rem; }

/* ============================================================
   Quote page — page-quote.php template
   Centres quote-enquiry-form in a white card so .mg-gform pills
   and inputs read correctly (cream chrome needs a non-cream bg).
   ============================================================ */
.quote-page { padding: clamp(3rem, 8vw, 6rem) 0 clamp(4rem, 10vw, 8rem); background: var(--color-brand-cream); }
.quote-page .container--narrow { max-width: 680px; margin: 0 auto; padding-left: 1.25rem; padding-right: 1.25rem; }
.quote-page__head { text-align: center; margin-bottom: clamp(1.5rem, 4vw, 2.5rem); }
.quote-page__title {
	font-family: var(--font-display, var(--font-heading));
	font-size: clamp(1.75rem, 4vw, 2.5rem);
	line-height: 1.1;
	color: var(--color-text-primary);
	margin: 0;
}
.quote-page__card {
	--dg-error: #a01919;         /* deep brick red — quote-page-only override */
	background: #fff;
	border: 1px solid color-mix(in srgb, var(--color-text-primary) 8%, transparent);
	border-radius: var(--radius-lg, 14px);
	padding: clamp(1.5rem, 5vw, 2.75rem);
	box-shadow: 0 1px 2px rgba(0,0,0,.04), 0 12px 32px -12px rgba(0,0,0,.12);
	overflow: hidden;            /* clip the bottom badge strip to the rounded corners */
}

/* ── Field colours (quote page only) ─────────────────────────────────
   Text inputs: bg #f4f3f0, border #d5d5d5.
   Choices (checkbox rows + select dropdown): bg #fbfaf9, border #d5d5d5. */

/* text inputs + textarea */
.quote-page__card input[type="text"],
.quote-page__card input[type="email"],
.quote-page__card input[type="tel"],
.quote-page__card input[type="number"],
.quote-page__card input[type="url"],
.quote-page__card textarea {
	background: #f4f3f0;
	border: 1px solid #d5d5d5;
}
/* the intl-tel phone wrapper mirrors the input shell */
.quote-page__card .gfield--type-phone .iti,
.quote-page__card .gfield--type-phone input[type="tel"] {
	background: #f4f3f0;
	border-color: #d5d5d5;
}

/* select dropdown → choice colours */
.quote-page__card .gfield--type-select select {
	background-color: #fbfaf9;
	border: 1px solid #d5d5d5;
}
/* NB: checkbox option rows (.gfield.pills .gchoice) get their #fbfaf9 fill +
   #d5d5d5 border from the stacked-choices rule further down (single source). */

/* ── Validation (quote page only) ─────────────────────────────────────
   Dark-red in-input messages, a red top-of-form banner, and a short note
   under the submit button so a failed submit reads clearly as validation. */

/* 1. In-input / per-field error text → deep brick red (was soft #b94a4a). */
.quote-page__card .gfield_validation_message,
.quote-page__card .validation_message,
.quote-page__card .gfield_error .gfield_description {
	color: var(--dg-error) !important;
	font-weight: 500;
}
/* the errored field label + input outline pick up the red too */
.quote-page__card .gfield_error .gfield_label,
.quote-page__card .gfield_error .gform-field-label { color: var(--dg-error); }
.quote-page__card .gfield_error input,
.quote-page__card .gfield_error select,
.quote-page__card .gfield_error textarea,
.quote-page__card .gfield_error .iti { box-shadow: inset 0 0 0 1px var(--dg-error); }

/* 2. Top-of-form banner → red bar at the top of the form (normal flow, so it
   pushes content down instead of overlapping — no modal absolute trick here). */
.quote-page__card .gform_validation_errors,
.quote-page__card .validation_error {
	position: static;
	margin: 0 0 var(--space-5);
	padding: 12px 16px;
	background: color-mix(in srgb, var(--dg-error) 10%, #fff);
	border: 1px solid color-mix(in srgb, var(--dg-error) 35%, transparent);
	border-left: 4px solid var(--dg-error);
	border-radius: 6px;
	color: var(--dg-error);
	font-size: 14px;
	font-weight: 600;
	text-align: left;
	animation: dgErrorSlide 240ms cubic-bezier(.2,.7,.2,1);
}
.quote-page__card .gform_validation_errors h2,
.quote-page__card .gform_validation_errors .gform_submission_error { font-size: inherit; margin: 0; display: inline; color: var(--dg-error); }
.quote-page__card .gform_validation_errors ol,
.quote-page__card .gform_validation_errors ul,
.quote-page__card .gform_validation_errors a { display: none !important; }

/* 3. Short note under the submit button — only shows when the form has errors
   (detected via :has() on the validation banner). Same deep red. */
.quote-page__card .gform_wrapper:has(.gform_validation_errors) .gform_footer::after,
.quote-page__card .gform_wrapper:has(.validation_error) .gform_footer::after {
	content: "Something's missing — please check the highlighted fields above.";
	display: block;
	width: 100%;
	margin-top: 10px;
	text-align: center;
	font-size: 13px;
	font-weight: 500;
	color: var(--dg-error);
}

/* Consent / legal footer under the submit button — mirrors the modal footer
   (bold lead, muted legal, olive Privacy/Terms links), centred. */
.quote-page__card .quote-page__footer {
	margin-top: clamp(1.25rem, 4vw, 2rem);
	text-align: center;
	font-family: var(--font-body);
}
.quote-page__card .quote-page__footer-headline {
	font-size: 15px;
	line-height: 1.4;
	color: var(--color-text-secondary);
	margin: 0;
}
.quote-page__card .quote-page__footer-headline strong { font-weight: 700; }
.quote-page__card .quote-page__legal {
	margin: 6px 0 0;
	font-size: 12px;
	font-weight: 500;
	line-height: 1.5;
	color: var(--color-neutral-400, #9aa0a6);
	max-width: 48ch;
	margin-inline: auto;
}
.quote-page__card .quote-page__legal-links {
	margin: 8px 0 0;
	font-size: 12px;
	display: flex;
	justify-content: center;
	gap: 8px;
	color: var(--color-neutral-400, #9aa0a6);
}
.quote-page__card .quote-page__legal-links a { color: var(--color-brand-olive); text-decoration: none; }
.quote-page__card .quote-page__legal-links a:hover { text-decoration: underline; }
.quote-page__card .quote-page__legal-links span { opacity: 0.5; }

/* Trust-badge strip flush to the card's bottom edge. Negative margins cancel
   the card padding so the band spans corner-to-corner; overflow:hidden on the
   card rounds its bottom corners. */
.quote-page__card .quote-page__badges {
	display: flex;
	align-items: center;
	justify-content: center;
	gap: clamp(1rem, 4vw, 2.5rem);
	margin: clamp(1.5rem, 5vw, 2.75rem) calc(-1 * clamp(1.5rem, 5vw, 2.75rem)) calc(-1 * clamp(1.5rem, 5vw, 2.75rem));
	padding: clamp(1rem, 3vw, 1.5rem) clamp(1.5rem, 5vw, 2.75rem);
	background: var(--color-brand-cream);
	border-top: 1px solid color-mix(in srgb, var(--color-text-primary) 8%, transparent);
}
.quote-page__card .quote-page__badges img {
	height: clamp(48px, 9vw, 64px);
	width: auto;
	display: block;
	opacity: .9;
}

/* ── Quote-page-only refinements (scoped to .quote-page__card so the
   quote modal keeps its own tighter styling) ─────────────────────── */

/* 1. File Upload Pro drop area → full row width (Pro wrapper defaults narrow) */
.quote-page__card .gpfup,
.quote-page__card .gpfup__droparea { width: 100%; max-width: none; }

/* 1b. File-type / size limit → small, centred, tucked at the bottom INSIDE
   the drop box. File Upload Pro hides GF's default rules span, so re-show it
   (display:block !important) and absolutely place it at the drop-box bottom. */
.quote-page__card .gfield--type-fileupload .gpfup { position: relative; }
.quote-page__card .gfield--type-fileupload .gpfup__droparea { padding-bottom: 2.5rem; }
/* Specificity 0-3-0 to beat theme's `.mg-gform .gfield--type-fileupload
   .gfield_description { display:none !important }` (also 0-3-0, but later in
   source) — add .ginput_container_fileupload to push ours to 0-3-0 and place
   it after that rule so source order wins. */
.quote-page__card .gfield--type-fileupload .ginput_container_fileupload .gform_fileupload_rules {
	display: block !important;
	position: absolute;
	left: 0;
	right: 0;
	bottom: 10px;
	margin: 0;
	padding: 0 12px;
	text-align: center;
	font-size: 11px;
	line-height: 1.3;
	color: #9aa0a6;
}

/* 2. Drop section descriptions — keep only the section heading */
.quote-page__card .gsection_description { display: none; }

/* 3. Field labels — one step bigger, darker, stronger contrast */
.quote-page__card .gfield_label,
.quote-page__card .gform-field-label {
	font-size: 15px;
	font-weight: 600;
	color: var(--color-text-primary);
}
/* First / Last name sublabels — match the main field-label style
   (e.g. "Mobile number") per request: bigger, dark, semibold.
   Specificity must beat `.mg-gform .gfield--type-name .ginput_complex
   .gform-field-label--type-sub` (0-3-0), so mirror that chain here. */
.quote-page__card .gfield--type-name .ginput_complex .gform-field-label--type-sub {
	font-size: 15px;
	font-weight: 600;
	color: var(--color-text-primary);
}

/* 4. Helper / description text — light neutral gray, desaturated */
.quote-page__card .gfield_description,
.quote-page__card .gform-field-label--type-sub + .gfield_description {
	color: #8a8f96;
	font-size: 13px;
}

/* 4b. Frontage "XXX m" — persistent metre suffix inside the input.
   Number field enforces numeric + decimal input; the "m" is a visual
   unit appended via the container, not part of the stored value. */
.quote-page__card .gfield.dg-unit-m .ginput_container_number { position: relative; }
.quote-page__card .gfield.dg-unit-m .ginput_container_number::after {
	content: "m";
	position: absolute;
	top: 50%;
	right: 14px;
	transform: translateY(-50%);
	font-size: 15px;
	color: var(--color-text-secondary);
	pointer-events: none;
}
/* leave room so typed digits don't run under the "m" */
.quote-page__card .gfield.dg-unit-m input[type="number"],
.quote-page__card .gfield.dg-unit-m .ginput_container_number input { padding-right: 34px; }

/* 5. Breathing room between the form's sections (compact) */
.quote-page__card .gfield--type-section {
	margin-top: clamp(1.25rem, 3vw, 1.75rem);
	padding-top: clamp(1rem, 2.5vw, 1.25rem);
	border-top: 1px solid color-mix(in srgb, var(--color-text-primary) 8%, transparent);
}
/* first section needs no top divider/space */
.quote-page__card .gform_fields > .gfield--type-section:first-child {
	margin-top: 0;
	padding-top: 0;
	border-top: 0;
}

/* 6. Quote-page choice fields (Service type, Extras) — override the compact
   pills grid into a single-column stacked list: one option per row, native
   checkbox visible on the LEFT, vertically centred with the label. Scoped
   to .quote-page__card so the modal keeps its pill grid. Specificity mirrors
   the .mg-gform .gfield.pills chain so these win. */
.quote-page__card .gfield.pills .gfield_radio,
.quote-page__card .gfield.pills .gfield_checkbox {
	flex-direction: column;      /* 1 column, N rows */
	flex-wrap: nowrap;
	gap: var(--space-2);
}
/* .gchoice IS the flex row: [checkbox] [label text], vertically centred.
   (In GF markup the input and label are siblings inside .gchoice.)
   position:relative so the label can overlay the whole row for clicking. */
.quote-page__card .gfield.pills .gchoice {
	position: relative;
	flex: 1 1 auto;              /* full row, no 33% cap */
	width: 100%;
	display: flex;
	align-items: center;        /* vertical centre */
	gap: var(--space-3);
	background: #fbfaf9;         /* choice fill */
	border: 1px solid #d5d5d5;   /* choice border */
	padding: 11px 14px;
	cursor: pointer;            /* whole block reads as clickable */
}
/* bring the native checkbox/radio back, on the left; keep it above the
   full-row label overlay so its own tick target still works. */
.quote-page__card .gfield.pills .gchoice input[type="radio"],
.quote-page__card .gfield.pills .gchoice input[type="checkbox"] {
	position: relative;
	z-index: 2;
	opacity: 1;
	pointer-events: auto;
	flex: 0 0 auto;
	width: 18px;
	height: 18px;
	margin: 0;
	accent-color: var(--color-text-primary);
	cursor: pointer;
}
/* label overlays the ENTIRE row so a click anywhere on the block toggles the
   option (label[for] forwards the click to the input). Text is inset-left so
   it clears the checkbox; the label sits under the checkbox (z-index) so the
   native tick still works directly too. */
.quote-page__card .gfield.pills .gchoice label {
	position: absolute;
	inset: 0;
	z-index: 1;
	display: flex;
	align-items: center;
	text-align: left;
	padding: 0 14px 0 46px;     /* left room for the 18px box + gap */
	margin: 0;
	cursor: pointer;
}
.quote-page__card .gfield.pills .gchoice:has(input:checked) label { font-weight: 600; }
/* Checked row → border only, no fill (softer than base cream fill). Specificity
   raised (extra :has qualifier) to beat the base .mg-gform checked rule.
   Solid mid-tone border (mixing with transparent computed to 0 alpha in some
   engines, so mix against the cream bg instead). */
.quote-page__card .gfield.pills .gchoice:has(input:checked):has(label) {
	background: #fbfaf9;         /* same choice fill, no darker fill on check */
	border-color: color-mix(in srgb, var(--color-text-primary) 40%, #fbfaf9);
}

.legal__back {
	display: inline-block;
	font-family: var(--font-ui);
	font-size: 13px;
	color: var(--color-text-secondary);
	text-decoration: none;
	margin-bottom: var(--space-4);
}
.legal__back:hover { color: var(--color-brand-olive); }

.legal__head { margin-bottom: clamp(2rem, 5vw, 3rem); }
.legal__title {
	font-family: var(--font-display);
	font-size: clamp(1.875rem, 5vw, 2.75rem);
	font-weight: 500;
	line-height: 1.15;
	color: var(--color-text-primary);
	margin: 0 0 var(--space-2);
}
.legal__meta {
	font-family: var(--font-ui);
	font-size: 13px;
	color: var(--color-text-secondary);
	margin: 0;
}

/* ---------- Prose styling inside the editor-rendered body ---------- */
.legal__body {
	font-family: var(--font-body);
	font-size: 16px;
	line-height: 1.7;
	color: var(--color-body-on-light);
	hanging-punctuation: first last;
}
/* Default vertical rhythm between adjacent block elements. Specific
   element pairings below override where a tighter or looser rhythm is
   needed (heading → first child, list inside paragraph, etc.). */
.legal__body > * + * { margin-top: var(--space-3); }

/* ── Headings ────────────────────────────────────────────────
   H2 is the only heading inside the long-form prose that uses the
   serif display font — everything else uses the body family with
   varied weight to create a calm in-page hierarchy. */
.legal__body h2 {
	font-family: var(--font-display);
	font-size: clamp(1.375rem, 3vw, 1.625rem);
	font-weight: 500;
	line-height: 1.25;
	letter-spacing: -0.01em;
	color: var(--color-text-primary);
	margin-top: var(--space-7);
	margin-bottom: var(--space-2);
	text-wrap: balance;
}
.legal__body h2:first-child { margin-top: 0; }

.legal__body h3,
.legal__body h4,
.legal__body h5,
.legal__body h6 {
	font-family: var(--font-body);
	color: var(--color-text-primary);
	line-height: 1.35;
	margin-bottom: var(--space-1);
}
.legal__body h3 { font-size: 1.0625rem; font-weight: 700; margin-top: var(--space-5); }
.legal__body h4 { font-size: 1rem;      font-weight: 600; margin-top: var(--space-4); }
.legal__body h5 {
	font-size: 0.8125rem;
	font-weight: 700;
	font-family: var(--font-ui);
	text-transform: uppercase;
	letter-spacing: 0.08em;
	color: var(--color-text-secondary);
	margin-top: var(--space-4);
}
.legal__body h6 {
	font-size: 0.75rem;
	font-weight: 700;
	font-family: var(--font-ui);
	text-transform: uppercase;
	letter-spacing: 0.1em;
	color: var(--color-text-secondary);
	margin-top: var(--space-3);
}
/* Tighten the gap when a heading is followed directly by prose. */
.legal__body h2 + p,
.legal__body h3 + p,
.legal__body h4 + p,
.legal__body h5 + p,
.legal__body h6 + p,
.legal__body h2 + ul, .legal__body h2 + ol,
.legal__body h3 + ul, .legal__body h3 + ol,
.legal__body h4 + ul, .legal__body h4 + ol { margin-top: var(--space-2); }

/* ── Paragraphs / inline text ────────────────────────────── */
.legal__body p { margin: 0; }
.legal__body strong, .legal__body b { color: var(--color-text-primary); font-weight: 600; }
.legal__body em, .legal__body i { font-style: italic; }
.legal__body small { font-size: 0.8125rem; color: var(--color-text-secondary); }
.legal__body sub, .legal__body sup { font-size: 0.7em; line-height: 0; }
.legal__body sub { vertical-align: sub; }
.legal__body sup { vertical-align: super; }
.legal__body mark {
	background: var(--color-brand-cream);
	color: var(--color-text-primary);
	padding: 0 4px;
	border-radius: 2px;
}
.legal__body abbr[title] {
	text-decoration: underline dotted;
	cursor: help;
}

/* ── Links ───────────────────────────────────────────────── */
.legal__body a {
	color: var(--color-brand-olive);
	text-decoration: underline;
	text-decoration-thickness: 1px;
	text-underline-offset: 3px;
	transition: color 120ms ease;
}
.legal__body a:hover { color: var(--color-brand-olive-hover); text-decoration-thickness: 2px; }
.legal__body a:visited { color: var(--color-brand-olive); }

/* ── Lists ───────────────────────────────────────────────── */
.legal__body ul,
.legal__body ol {
	padding-left: 1.5rem;
	margin: 0;
}
.legal__body ul { list-style: disc; }
.legal__body ol { list-style: decimal; }
.legal__body ul ul,
.legal__body ol ol,
.legal__body ul ol,
.legal__body ol ul {
	margin-top: 6px;
	margin-bottom: 0;
	padding-left: 1.25rem;
}
.legal__body ul ul { list-style: circle; }
.legal__body ul ul ul { list-style: square; }
.legal__body li { margin: 0; }
.legal__body li + li { margin-top: 6px; }
.legal__body li::marker { color: var(--color-brand-olive); }
.legal__body li > p { margin: 0; }
.legal__body li > p + p { margin-top: 6px; }

/* ── Definition lists (dl/dt/dd) ─────────────────────────── */
.legal__body dl {
	display: grid;
	grid-template-columns: minmax(8rem, max-content) 1fr;
	gap: var(--space-2) var(--space-4);
	margin: 0;
}
.legal__body dt { font-weight: 700; color: var(--color-text-primary); }
.legal__body dd { margin: 0; }

/* ── Blockquote ─────────────────────────────────────────── */
.legal__body blockquote {
	margin: var(--space-4) 0;
	padding: var(--space-3) var(--space-5);
	border-left: 4px solid var(--color-brand-olive);
	background: var(--color-brand-cream);
	color: var(--color-text-primary);
	font-family: var(--font-display);
	font-style: italic;
	font-size: 1.0625rem;
	line-height: 1.55;
}
.legal__body blockquote p { color: inherit; }
.legal__body blockquote p + p { margin-top: var(--space-2); }
.legal__body blockquote cite {
	display: block;
	margin-top: var(--space-2);
	font-family: var(--font-ui);
	font-style: normal;
	font-size: 0.8125rem;
	letter-spacing: 0.04em;
	text-transform: uppercase;
	color: var(--color-text-secondary);
}

/* ── Horizontal rule ─────────────────────────────────────── */
.legal__body hr {
	border: 0;
	height: 1px;
	background: var(--color-border);
	margin: var(--space-6) 0;
}

/* ── Images & figures ────────────────────────────────────── */
.legal__body img,
.legal__body figure { display: block; max-width: 100%; height: auto; }
.legal__body figure {
	margin: var(--space-5) 0;
}
.legal__body figure img { width: 100%; }
.legal__body figcaption {
	margin-top: var(--space-2);
	font-family: var(--font-ui);
	font-size: 0.8125rem;
	color: var(--color-text-secondary);
	text-align: center;
}
/* Single image in flow gets some breathing room */
.legal__body > img,
.legal__body p > img { margin: var(--space-3) 0; }

/* ── Tables ──────────────────────────────────────────────── */
.legal__body table {
	width: 100%;
	border-collapse: collapse;
	margin: var(--space-4) 0;
	font-size: 0.9375rem;
}
.legal__body th,
.legal__body td {
	padding: var(--space-2) var(--space-3);
	text-align: left;
	vertical-align: top;
	border-bottom: 1px solid var(--color-border);
}
.legal__body thead th {
	font-family: var(--font-ui);
	font-weight: 700;
	font-size: 0.75rem;
	text-transform: uppercase;
	letter-spacing: 0.06em;
	color: var(--color-text-secondary);
	background: var(--color-brand-cream);
	border-bottom: 2px solid var(--color-brand-olive);
}
.legal__body tbody tr:last-child td { border-bottom: 0; }
.legal__body tbody tr:nth-child(2n) td { background: color-mix(in srgb, var(--color-brand-cream) 40%, transparent); }

/* ── Code & preformatted ─────────────────────────────────── */
.legal__body code,
.legal__body kbd,
.legal__body samp {
	font-family: var(--font-ui);
	font-size: 0.875em;
	background: var(--color-brand-cream);
	color: var(--color-text-primary);
	padding: 2px 6px;
	border-radius: 3px;
}
.legal__body kbd {
	border: 1px solid var(--color-border);
	box-shadow: 0 1px 0 var(--color-border);
}
.legal__body pre {
	background: var(--color-brand-cream);
	color: var(--color-text-primary);
	padding: var(--space-3) var(--space-4);
	border-radius: 4px;
	overflow-x: auto;
	font-family: var(--font-ui);
	font-size: 0.875rem;
	line-height: 1.55;
}
.legal__body pre code {
	background: transparent;
	padding: 0;
	border-radius: 0;
	font-size: inherit;
}

/* ── Details / summary (accordions in editor) ─────────── */
.legal__body details {
	border: 1px solid var(--color-border);
	border-radius: 4px;
	padding: var(--space-2) var(--space-3);
}
.legal__body summary {
	cursor: pointer;
	font-weight: 600;
	color: var(--color-text-primary);
}
.legal__body details[open] summary { margin-bottom: var(--space-2); }


/* ============================================================
   Accessibility — focus-visible
   Keyboard users need a visible ring on interactive elements.
   :focus-visible only triggers on keyboard focus, not mouse clicks,
   so it doesn't add visual noise for sighted mouse users.
   ============================================================ */
.btn:focus-visible,
.topbar__nav a:focus-visible,
.topbar__cta a:focus-visible,
.section-nav__link:focus-visible,
.footer a:focus-visible,
.footer__bottom-links a:focus-visible,
.legal__back:focus-visible,
.legal__body a:focus-visible,
.dg-ty__back:focus-visible,
.modal__close:focus-visible,
[data-modal-close]:focus-visible {
	outline: 2px solid var(--color-focus-ring, var(--color-brand-olive));
	outline-offset: 2px;
	border-radius: 2px;
}
.mg-gform input:focus-visible,
.mg-gform select:focus-visible,
.mg-gform textarea:focus-visible,
.modal__input:focus-visible {
	outline: 2px solid var(--color-brand-olive);
	outline-offset: 2px;
}
.mg-gform .gchoice label:focus-within,
.mg-gform .gchoice input:focus-visible + label {
	outline: 2px solid var(--color-brand-olive);
	outline-offset: 2px;
}
