/* ============================================================
   Pole Barn — site/style.css  ("rugged warm" skin)
   A block-palette skin of the shared vocabulary, derived from
   _easton-template. Same variable NAMES, new VALUES.
   Palette: warm charcoal + barn red, timber & oat neutrals,
   galvanized steel accents.
   Fonts: SITE OVERRIDE — Barlow Condensed (headings) + Roboto (body), self-hosted.
   (Template ships Zilla Slab + Source Sans 3; swapped for this site.)
   ============================================================ */

/* ---------- Design Tokens ---------- */
:root {
  /* --navy* = warm charcoal darks (header, dark sections, footer, form card) */
  --navy: #2B2A28;               /* dark sections, header, footer */
  --navy-2: #35332F;             /* slightly lighter charcoal panels */
  --navy-card: #3A362F;          /* quote-form card (warm dark) */
  /* --teal* = timber brown — the secondary accent (labels, h3, links, bands) */
  --teal: #6B4E3D;               /* timber — section labels, links on light */
  --teal-bright: #C9A57E;        /* warm tan — timber accent on dark bg */
  /* --orange* = barn red — the primary action color (CTA, phone) */
  --orange: #8C3A2B;             /* barn red — primary CTA, phone accents */
  --orange-bright: #D97A54;      /* warm brick — barn-red accent on dark bg */

  /* PRIMARY FILL vs PRIMARY INK — the opt-in that lets a palette choose its own
     colour structure instead of filling fixed slots.
     --orange must stay dark enough to read as TEXT on light backgrounds
     (.accent, .brand-text b, the faq "+", the button hover state), which caps how
     vivid it can be: the brightest white-safe orange is ~#D04910 at 4.5:1. A
     genuinely straight orange (#F26A1B and up) is only reachable with DARK ink, so
     fills get their own pair. Both DEFAULT to the existing behaviour, so every
     palette shipped before this change renders byte-identically unless it opts in. */
  /* KEYLINE — the offset frame peeking out behind --framed / --long figures and
     .split-media--framed. This is NOT the secondary accent doing accent work: in
     the default skin --teal is timber brown, so the frame reads as a quiet wooden
     keyline. A palette whose secondary is a saturated hue turns the same rule into
     a loud coloured rectangle, which reads as a stray element. Defaults to --teal
     so the default/harvest/walnut skins are unchanged; palettes with a saturated
     secondary point it at a neutral instead. */
  --keyline: var(--teal);
  /* CARD ACCENT — the 4px bar on .faq-item and .testi-quote. In the default skin
     --teal is timber brown, which harmonises with barn red; a palette with a
     SATURATED secondary turns the same two rules into isolated coloured bars on
     white cards that read as stray. Defaults to --teal (default/harvest/walnut
     unchanged); palettes with a saturated secondary point it at the accent. */
  --card-accent: var(--teal);
  /* ON-DARK BUTTON. A warm-led palette (navy + cream) cannot use one button
     colour on both surfaces: a cream button vanishes on a cream page, and forcing
     it dark enough to read there turns it to copper. So dark sections get their
     own pair. Defaults to the light-surface values, leaving every other palette
     byte-identical. */
  --btn-fill-dark: var(--orange-fill);
  --btn-ink-dark: var(--btn-ink);

  --orange-fill: var(--orange);   /* button / badge / node background */
  --btn-ink: #ffffff;             /* ink ON --orange-fill */

  --color-link: var(--teal);
  --color-text: #2E2B27;
  --color-text-muted: #6f6a62;
  --color-heading: #2B2A28;
  --color-bg: #ffffff;
  --color-bg-alt: #F3ECDD;       /* warm oat cream */
  --color-border: #e4ddd0;
  --color-error: #b00020;
  --color-focus: var(--orange);
  --color-fg-on-dark: #ffffff;

  /* barn-red accent used as a decorative RULE/BORDER on dark sections
     (project-card top rule on --navy-2, footer h4 underline on --navy,
     service-card-header inset on --teal). Role split from --orange so a
     palette whose primary is too dark to read on its own dark sections can
     lighten just these accents. DEFAULT aliases --orange, whose barn-red
     melts on the dark bands (1.0–1.9:1) — grandfathered as shipped; the two
     alternates re-derive it to ≥3:1 on navy/navy-2/teal. */
  --accent-frame: var(--orange);

  /* muted warm-neutral inks ON the dark charcoal chrome (top bar + footer) —
     tinted per palette so the chrome tracks the skin. */
  --on-dark-nav: #d9d3c7;        /* top-bar text + links (9.62:1 on --navy) */
  --on-dark-social: #cfc7b8;     /* top-bar social icons (8.55:1) */
  --on-dark-body: #b0a99c;       /* footer body text + legal links (6.15:1) */
  --on-dark-link: #cfc7b9;       /* footer nav + contact links (8.55:1) */
  --on-dark-faint: #8f8879;      /* legal fine print — 4.07:1 on --navy is grandfathered (pre-contract); alternates hit ≥4.5 */
  --on-teal-label: #e6dcc8;      /* pale label ON the timber/teal band (5.55:1 on --teal) */

  /* galvanized-steel corrugated ribbing (hero edge, .metal-edge, steps post
     line) — three-stop rib gradient. Retired the old unused --galvanized
     token in favour of these three consumed stops. Decorative texture (no
     text-contrast requirement); shifted per palette so the corrugation
     tracks the skin's temperature. */
  --metal-1: #767d84;            /* mid rib */
  --metal-2: #9aa2a8;            /* rib highlight */
  --metal-3: #656c73;            /* rib shadow */

  /* photo-overlay washes (tinted darkening over section bg images). The
     charcoal wash tint (30,28,26) is a hair deeper than --navy so photos
     read; re-derived per palette. Low-alpha scrims stay tinted too. */
  --overlay-dark: linear-gradient(rgba(30,28,26,0.82), rgba(30,28,26,0.88));   /* .bg-host default */
  --overlay-teal: linear-gradient(rgba(74,54,42,0.86), rgba(60,44,34,0.92));   /* .bg-host.bg-teal (timber-tinted) */
  --overlay-soft: linear-gradient(rgba(30,28,26,0.55), rgba(30,28,26,0.72));   /* .bg-host.bg-soft (banner) */
  --overlay-scrim: linear-gradient(rgba(30,28,26,0.30), rgba(30,28,26,0.30));  /* flex-media--overlay light scrim */
  --overlay-scrim-strong: linear-gradient(rgba(30,28,26,0.35), rgba(30,28,26,0.35)); /* flex-media--long-center scrim */
  --overlay-panel: rgba(30,28,26,0.78);   /* translucent .overlay-half / .overlay-center text panels */

  /* brand-tinted rings/washes (alpha too high / too saturated to read as
     neutral). NOTE: the default values carry easton's teal (46,112,119) —
     a stale clone leftover kept BYTE-IDENTICAL so the shipped default is
     unchanged; both alternates re-derive them from their own accents. */
  --focus-ring: rgba(46,112,119,0.18);    /* RESERVED — form-validation focus halo; no live rule uses it (see the utility-form note below) */
  --wash-accent: rgba(46,112,119,0.22);   /* .feature-aside-box panel wash */

  /* select placeholder ink + caret data-URI (dark quote-bar / contact form
     selects sit on the --oat field) — re-emitted per palette. */
  --select-ink: #6b7280;
  --select-caret: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%236b7280'><path d='M7 10l5 5 5-5z'/></svg>");

  /* check-bullet / tick data-URIs — a CSS var can't interpolate into a
     data-URI, so each palette re-emits the whole url() with its own fill.
     --bullet-hero rides the DARK hero panel; --bullet-badge/--bullet-snow
     ride LIGHT sections; --tick-timber is the light-bg feature tick (its
     tan 2.2:1 on white is grandfathered decorative — alternates use a
     darker secondary). The white on-dark tick stays a literal (exempt). */
  --bullet-hero: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><circle cx='12' cy='12' r='11' fill='%23B24A36'/><path d='M17 8.5L10.5 15.5 7 12' fill='none' stroke='white' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'/></svg>");
  --bullet-badge: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><circle cx='12' cy='12' r='11' fill='%238C3A2B'/><path d='M17 8.5L10.5 15.5 7 12' fill='none' stroke='white' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'/></svg>");
  --bullet-snow: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><circle cx='12' cy='12' r='11' fill='%236B4E3D'/><path d='M17 8.5L10.5 15.5 7 12' fill='none' stroke='white' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'/></svg>");
  --tick-timber: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M20 6L9 17l-5-5' fill='none' stroke='%23C9A57E' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'/></svg>");

  /* extra rugged-skin tokens */
  --oat: #E7DCC7;                /* deeper oat for cards/strips */
  --radius: 0;

  --shadow-sm: 0 1px 3px rgba(43,42,40,0.14);
  --shadow-md: 0 10px 30px rgba(43,42,40,0.18);
  --shadow-lg: 0 18px 50px rgba(43,42,40,0.30);

  --max-w: 1200px;
  --header-h: 80px;

  --font-body: "Roboto", system-ui, -apple-system, "Segoe UI", Arial, sans-serif;
  --font-head: "Barlow Condensed", "Barlow", system-ui, -apple-system, "Segoe UI", Arial, sans-serif;
}

/* ============================================================
   ASSEMBLY-TIME PALETTE VARIANTS — the standard every skin follows
   (full contract: templates/_template/CLAUDE.md "Color palettes")
   Default (no attribute) = the warm-charcoal + barn-red pole-barn skin in
   :root above. To build a site in another palette, set the attribute on
   <html>:
       <html lang="en" data-theme="denim">
   Rules of the system (hard requirements for every palette block):
   • FULL-SPECTRUM — override EVERY color role from :root (same role, new
     value), including the on-dark neutrals, metal ribbing, overlays,
     rings, select ink/caret and every check-bullet data-URI. Exemptions:
     white-on-dark inks stay white (--color-fg-on-dark; the literal #fff
     headings/copy/button-ink on .section-dark, .hero, bands and the dark
     form card; the rgba(255,255,255,…) washes; the white card/field/faq
     surfaces on light sections; the white on-dark feature-tick data-URI),
     and the low-alpha NEUTRAL shadows stay un-overridden (--shadow-sm/md/lg
     and the rgba(43,42,40,…)/rgba(0,0,0,…) box + inset shadows, alpha ≤0.30
     — at that opacity they read as neutral). Everything else — the four
     overlay washes, the two scrims + panel, the focus/error rings, the
     select caret and the bullet/tick URIs — is a role above and MUST be
     re-derived.
   • FUNCTION PRESERVED — light backgrounds stay light, dark sections stay
     dark, inks stay dark-and-readable, error stays recognizably red. The
     pole-barn identity holds: ONE loud PRIMARY action family (--orange*:
     CTAs, phone, step nodes, project tags, decorative rules), a SEPARATE
     secondary (--teal* timber: labels, h3, links, bands, keyline frames),
     warm-neutral chrome darks (--navy*) and a soft section band
     (--color-bg-alt). Nothing reorganizes which role does what.
   • PALETTE SEPARATION — palettes differ at a glance INCLUDING neutrals.
     Primary accents sit apart in hue (barn-red 9° vs denim cobalt 216° vs
     harvest goldenrod 46° vs walnut caramel 29°); the section bands are
     different hue FAMILIES or lightnesses (default warm oat-cream ~41°/91% vs
     denim cool blue-gray ~219° vs harvest olive-wheat ~57° vs walnut warm tan
     ~36°/86%); the dark chrome carries an obvious temperature/depth shift
     (warm charcoal ~40°/4% vs cool slate ~226° vs harvest warm espresso
     ~25°/25%/L13% vs walnut near-black coffee-charcoal ~26°/16%/L9%); and the
     secondaries come from different families (timber-brown 22° vs deep teal
     177° vs olive-bronze 49° vs walnut bronze-brown 33°). Where hue crowds —
     the three WARM palettes' accents (barn-red 9° / goldenrod 46° / caramel
     29°) box each other in — separation is carried by LIGHTNESS/CHROMA per the
     family standard, not hue alone: walnut's caramel is brighter than the
     barn-red, and its coffee-charcoal darks are deeper AND lower-chroma than
     harvest's warm espresso so the two never read the same.
   • CONTRAST — white on --orange/--teal/--navy* fills ≥4.5; --teal &
     --orange as ink on --color-bg AND --color-bg-alt ≥4.5; --orange-bright
     & --teal-bright on --navy AND --navy-2 ≥4.5; --on-teal-label on the
     teal band ≥4.5; every --on-dark-* ink on --navy ≥4.5; --color-text on
     --color-bg ≥7; --color-text-muted on both light bgs ≥4.5; and every
     accent-on-dark DECORATIVE consumer (--accent-frame rules, hero bullet
     circle, feature ticks, --teal-bright frames) ≥3:1. All three alternates
     below pass ALL of these with zero failures. (The DEFAULT's grandfathered
     shortfalls — --on-dark-faint 4.07:1, barn-red --accent-frame melting on
     the dark bands, the 2.7:1 hero bullet and 2.2:1 tan feature tick, and
     --orange-bright's 4.12:1 on --navy-2 — predate this contract and are
     left as shipped; see the token comments.)
   Add a palette by cloning a block below and re-deriving every role. The three
   alternates span the separation standard: denim is a cool COUNTERPOINT to the
   warm default, while harvest and walnut are both WARM — kept apart from each
   other (and the default) by lightness/chroma, not hue (harvest = goldenrod +
   visible-brown espresso darks; walnut = brighter caramel + deeper, cooler
   coffee-charcoal darks + a distinct tan band). Cloning any of them inherits
   the standard: when a new accent hue is boxed in, separate on lightness/chroma.
   ============================================================ */

/* Denim — saturated cobalt-blue primary (216°, a true blue set apart from
   the repo's muted steel 205° / icy cyan 193–195° accents by its high
   chroma) + deep-teal secondary, on a COOL family: slate-indigo darks,
   cool blue-gray band + chrome, cool paper-white page. */
[data-theme="denim"] {
  --card-accent: var(--orange-fill);   /* saturated secondary -> card bars follow the accent */
  --keyline: #4C7271;   /* muted secondary — visible like the default timber frame, without the saturated hue */
  --navy: #232838;               /* slate-indigo dark sections/header/footer (white 14.66:1) */
  --navy-2: #2C3242;             /* lighter slate panels (service/project cards) */
  --navy-card: #2E3446;          /* quote-form card (white 12.38:1) */
  --teal: #316D6A;               /* deep teal secondary — 5.96:1 white-on-fill; 5.61/4.89:1 as ink on bg/bg-alt */
  --teal-bright: #86C0BC;        /* pale teal on dark — 7.18:1 on --navy, 6.26:1 on --navy-2 */
  --orange: #2B579A;             /* cobalt PRIMARY — 7.16:1 white-on-fill; 6.74/5.88:1 as ink on bg/bg-alt */
  --orange-bright: #7CA6DD;      /* light cobalt on dark — 5.83:1 on --navy, 5.09:1 on --navy-2 */

  --color-link: var(--teal);
  --color-text: #23272E;         /* cool near-black body (14.11:1 on bg) */
  --color-text-muted: #565E6A;   /* cool slate muted (6.17/5.38:1 on bg/bg-alt) */
  --color-heading: #1E222C;      /* near-black slate headings (14.98:1) */
  --color-bg: #F7F8FB;           /* cool paper-white page */
  --color-bg-alt: #E4E9F2;       /* cool blue-gray band (hue ~219° — vs default oat-cream and harvest olive) */
  --color-border: #D3D9E4;       /* cool gray-blue border */
  --oat: #DDE3ED;                /* cool blue-gray card/field surface (deeper than --color-bg-alt; text 11.6:1, teal 4.62:1) */
  --color-error: #B0243A;        /* cool crimson, off the blue axis (6.26:1 on bg) */
  --color-focus: var(--orange);
  --color-fg-on-dark: #ffffff;   /* stays white (exempt) */

  --accent-frame: #AEC9EA;       /* pale cobalt decorative rule — ≥3 on navy/navy-2/teal (7.5/8.6/3.5:1) */
  --on-dark-nav: #D2D8E2;        /* top-bar text (10.24:1 on --navy) */
  --on-dark-social: #C8CFDB;     /* top-bar social (9.36:1) */
  --on-dark-body: #A6AEBD;       /* footer body (6.57:1) */
  --on-dark-link: #C8CFDB;       /* footer links (9.36:1) */
  --on-dark-faint: #8892A0;      /* legal fine print (4.65:1) */
  --on-teal-label: #CFE9E6;      /* pale label on the teal band (4.67:1 on --teal) */

  --metal-1: #6E7A88;            /* cool blue-steel rib */
  --metal-2: #97A3B0;            /* rib highlight */
  --metal-3: #5C6673;            /* rib shadow */

  --overlay-dark: linear-gradient(rgba(24,27,38,0.82), rgba(24,27,38,0.88));
  --overlay-teal: linear-gradient(rgba(30,58,56,0.86), rgba(24,48,46,0.92));  /* deep-teal tinted */
  --overlay-soft: linear-gradient(rgba(24,27,38,0.55), rgba(24,27,38,0.72));
  --overlay-scrim: linear-gradient(rgba(24,27,38,0.30), rgba(24,27,38,0.30));
  --overlay-scrim-strong: linear-gradient(rgba(24,27,38,0.35), rgba(24,27,38,0.35));
  --overlay-panel: rgba(24,27,38,0.78);

  --focus-ring: rgba(43,87,154,0.18);     /* from --orange #2B579A */
  --wash-accent: rgba(49,109,106,0.22);   /* from --teal #316D6A */

  --select-ink: #565E6A;
  --select-caret: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%23565E6A'><path d='M7 10l5 5 5-5z'/></svg>");

  /* light cobalt circle on the dark hero panel ⇒ dark (navy) check, not white */
  --bullet-hero: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><circle cx='12' cy='12' r='11' fill='%237CA6DD'/><path d='M17 8.5L10.5 15.5 7 12' fill='none' stroke='%23232838' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'/></svg>");
  --bullet-badge: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><circle cx='12' cy='12' r='11' fill='%232B579A'/><path d='M17 8.5L10.5 15.5 7 12' fill='none' stroke='white' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'/></svg>");
  --bullet-snow: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><circle cx='12' cy='12' r='11' fill='%23316D6A'/><path d='M17 8.5L10.5 15.5 7 12' fill='none' stroke='white' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'/></svg>");
  --tick-timber: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M20 6L9 17l-5-5' fill='none' stroke='%23316D6A' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'/></svg>");
}

/* Harvest — goldenrod primary (46°, ≥27° off easton copper 19° / orange 15°)
   + olive-bronze secondary, on a WARM but distinctly deeper family than the
   default's pale oat: espresso-brown darks, olive-wheat band, wheat chrome,
   warm ivory page. */
[data-theme="harvest"] {
  --navy: #2A2019;               /* espresso brown-black dark sections (white 15.92:1) */
  --navy-2: #362B22;             /* lighter walnut panels */
  --navy-card: #3A2E24;          /* quote-form card (white 13.16:1) */
  --teal: #5E5320;               /* olive-bronze secondary — 7.68:1 white-on-fill; 7.24/5.98:1 as ink on bg/bg-alt */
  --teal-bright: #C9A94E;        /* gold on dark — 7.03:1 on --navy, 6.08:1 on --navy-2 */
  --orange: #725806;             /* goldenrod PRIMARY — 6.74:1 white-on-fill; 6.35/5.25:1 as ink on bg/bg-alt */
  --orange-bright: #E0A63A;      /* bright amber on dark — 7.34:1 on --navy, 6.35:1 on --navy-2 */

  --color-link: var(--teal);
  --color-text: #292219;         /* warm espresso body (14.80:1 on bg) */
  --color-text-muted: #6B6350;   /* warm taupe muted (5.61/4.64:1 on bg/bg-alt) */
  --color-heading: #241D14;      /* near-black brown headings (15.69:1) */
  --color-bg: #FBF8F0;           /* warm ivory page */
  --color-bg-alt: #E7E5BE;       /* olive-wheat band (hue ~57° — vs default oat-cream and denim blue-gray) */
  --color-border: #D9D3AE;       /* wheat-khaki border */
  --oat: #E4DDB6;                /* deeper wheat card/field surface (text 11.5:1, teal 5.60:1, select-ink 4.83:1) */
  --color-error: #B0242A;        /* warm brick-crimson, clear of the gold axis (6.32:1 on bg) */
  --color-focus: var(--orange);
  --color-fg-on-dark: #ffffff;   /* stays white (exempt) */

  --accent-frame: #E0A63A;       /* bright amber decorative rule — ≥3 on navy/navy-2/teal (7.3/6.4/3.5:1) */
  --on-dark-nav: #E0D6B8;        /* top-bar text (10.98:1 on --navy) */
  --on-dark-social: #D8CDAB;     /* top-bar social (10.04:1) */
  --on-dark-body: #B4AB8C;       /* footer body (6.93:1) */
  --on-dark-link: #D8CDAB;       /* footer links (10.04:1) */
  --on-dark-faint: #938A72;      /* legal fine print (4.64:1) */
  --on-teal-label: #EFE3B4;      /* pale label on the olive band (5.97:1 on --teal) */

  --metal-1: #7C7A72;            /* warm pewter/zinc rib */
  --metal-2: #A19E93;            /* rib highlight */
  --metal-3: #6B6960;            /* rib shadow */

  --overlay-dark: linear-gradient(rgba(30,23,17,0.82), rgba(30,23,17,0.88));
  --overlay-teal: linear-gradient(rgba(60,52,24,0.86), rgba(48,42,20,0.92));  /* olive-bronze tinted */
  --overlay-soft: linear-gradient(rgba(30,23,17,0.55), rgba(30,23,17,0.72));
  --overlay-scrim: linear-gradient(rgba(30,23,17,0.30), rgba(30,23,17,0.30));
  --overlay-scrim-strong: linear-gradient(rgba(30,23,17,0.35), rgba(30,23,17,0.35));
  --overlay-panel: rgba(30,23,17,0.78);

  --focus-ring: rgba(114,88,6,0.18);      /* from --orange #725806 */
  --wash-accent: rgba(94,83,32,0.22);     /* from --teal #5E5320 */

  --select-ink: #645C49;         /* darker so placeholder passes on the wheat --oat field (4.83:1) */
  --select-caret: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%23645C49'><path d='M7 10l5 5 5-5z'/></svg>");

  /* bright amber circle on the dark hero panel ⇒ dark (espresso) check */
  --bullet-hero: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><circle cx='12' cy='12' r='11' fill='%23E0A63A'/><path d='M17 8.5L10.5 15.5 7 12' fill='none' stroke='%232A2019' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'/></svg>");
  --bullet-badge: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><circle cx='12' cy='12' r='11' fill='%23725806'/><path d='M17 8.5L10.5 15.5 7 12' fill='none' stroke='white' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'/></svg>");
  --bullet-snow: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><circle cx='12' cy='12' r='11' fill='%235E5320'/><path d='M17 8.5L10.5 15.5 7 12' fill='none' stroke='white' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'/></svg>");
  --tick-timber: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M20 6L9 17l-5-5' fill='none' stroke='%235E5320' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'/></svg>");
}

/* Walnut — warm leather/caramel primary (29°, a burnt-caramel set apart from
   the default's barn-red 9° AND its timber secondary 22° by being a clearly
   lighter, more orange leather tone) + muted bronze-brown secondary, on warm
   tan bands + chrome and a tan oat page, over a NEAR-BLACK COFFEE-CHARCOAL dark
   family. Those darks are deliberately deeper AND lower-chroma than harvest's
   warm espresso (walnut --navy #1A1613 L9%/sat16% vs harvest #2A2019
   L13%/sat25%; R-B spread 7 vs 17) so the two warm palettes' dark chrome reads
   distinct at a glance — walnut = coffee-black charcoal, harvest = visible
   brown. Separation from the default here is lightness/chroma, not hue (the
   caramel accent is legitimately boxed between barn-red and goldenrod), per the
   family standard. The whole palette reads walnut/leather next to the default's
   red. */
[data-theme="walnut"] {
  --navy: #1A1613;               /* near-black coffee-charcoal dark sections (white 17.98:1) */
  --navy-2: #241F1B;             /* lighter coffee panels (service/project cards) */
  --navy-card: #292420;          /* quote-form card (white 15.36:1) */
  --teal: #5A4326;               /* bronze-brown secondary — 9.27:1 white-on-fill; 8.71/7.13:1 as ink on bg/bg-alt */
  --teal-bright: #D0A566;        /* warm tan on dark — 7.39:1 on --navy, 6.66:1 on --navy-2 */
  --orange: #8E5016;             /* caramel/leather PRIMARY — 6.35:1 white-on-fill; 5.96/4.88:1 as ink on bg/bg-alt */
  --orange-bright: #D08A44;      /* light caramel on dark — 5.91:1 on --navy, 5.33:1 on --navy-2 */

  --color-link: var(--teal);
  --color-text: #2B2119;         /* warm espresso body (14.78:1 on bg) */
  --color-text-muted: #6B5B49;   /* warm taupe muted (6.13/5.02:1 on bg/bg-alt) */
  --color-heading: #241B12;      /* near-black brown headings (15.90:1) */
  --color-bg: #FDF7EF;           /* warm tan-ivory page */
  --color-bg-alt: #EEE0CB;       /* warm tan band (hue ~36° — deeper & warmer than default oat-cream #F3ECDD 41°/91%; vs denim blue-gray & harvest olive-wheat) */
  --color-border: #DDCEB6;       /* warm tan border */
  --oat: #E0CDB0;                /* deeper tan card/field surface (text 12.6:1, teal 5.97:1, select-ink 4.96:1) */
  --color-error: #B0242A;        /* warm brick-crimson, clear of the caramel axis (6.30:1 on bg) */
  --color-focus: var(--orange);
  --color-fg-on-dark: #ffffff;   /* stays white (exempt) */

  --accent-frame: #D08A44;       /* light caramel decorative rule — ≥3 on navy/navy-2/teal (5.9/5.3/3.3:1) */
  --on-dark-nav: #DBCDB6;        /* top-bar text (10.72:1 on --navy) */
  --on-dark-social: #D2C3A9;     /* top-bar social (9.68:1) */
  --on-dark-body: #B2A488;       /* footer body (6.84:1) */
  --on-dark-link: #D2C3A9;       /* footer links (9.68:1) */
  --on-dark-faint: #948871;      /* legal fine print (4.81:1) */
  --on-teal-label: #E8D3AC;      /* pale label on the bronze band (6.33:1 on --teal) */

  --metal-1: #7E7264;            /* warm bronze/pewter rib */
  --metal-2: #A0937F;            /* rib highlight */
  --metal-3: #6B5F52;            /* rib shadow */

  --overlay-dark: linear-gradient(rgba(20,17,15,0.82), rgba(20,17,15,0.88));   /* a hair deeper than the coffee-charcoal --navy */
  --overlay-teal: linear-gradient(rgba(70,52,30,0.86), rgba(56,42,24,0.92));  /* bronze-brown tinted */
  --overlay-soft: linear-gradient(rgba(20,17,15,0.55), rgba(20,17,15,0.72));
  --overlay-scrim: linear-gradient(rgba(20,17,15,0.30), rgba(20,17,15,0.30));
  --overlay-scrim-strong: linear-gradient(rgba(20,17,15,0.35), rgba(20,17,15,0.35));
  --overlay-panel: rgba(20,17,15,0.78);

  --focus-ring: rgba(142,80,22,0.18);     /* from --orange #8E5016 */
  --wash-accent: rgba(90,67,38,0.22);     /* from --teal #5A4326 */

  --select-ink: #615040;         /* darker so placeholder passes on the tan --oat field (4.96:1) */
  --select-caret: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%23615040'><path d='M7 10l5 5 5-5z'/></svg>");

  /* light caramel circle on the dark hero panel ⇒ dark (espresso) check */
  --bullet-hero: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><circle cx='12' cy='12' r='11' fill='%23D08A44'/><path d='M17 8.5L10.5 15.5 7 12' fill='none' stroke='%231A1613' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'/></svg>");
  --bullet-badge: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><circle cx='12' cy='12' r='11' fill='%238E5016'/><path d='M17 8.5L10.5 15.5 7 12' fill='none' stroke='white' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'/></svg>");
  --bullet-snow: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><circle cx='12' cy='12' r='11' fill='%235A4326'/><path d='M17 8.5L10.5 15.5 7 12' fill='none' stroke='white' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'/></svg>");
  --tick-timber: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M20 6L9 17l-5-5' fill='none' stroke='%235A4326' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'/></svg>");
}

/* Evergreen — forest-green primary (156°, the empty 140–170° band; deliberately
   ≥19° off the teal 177° that denim's secondary, easton, findlay and immov2 all
   use, and pushed to high chroma so it reads GREEN not teal) + a slate-blue
   secondary, on a cool-green family: pine-black darks (146°/16%/L9%), pale sage
   band, cool green-white page. The most conventionally trade-credible of the new
   palettes — green reads as energy/efficiency without being literal. */
[data-theme="evergreen"] {
  --card-accent: var(--orange-fill);   /* saturated secondary -> card bars follow the accent */
  --keyline: #566F81;   /* muted secondary — visible like the default timber frame, without the saturated hue */
  --navy: #131A16;               /* pine near-black dark sections/header/footer (white 17.69:1) */
  --navy-2: #131915;             /* lighter pine panels (service/project cards) — white 15.56:1 */
  --navy-card: #212B24;          /* quote-form card (white 14.63:1) */
  --teal: #366485;               /* slate-blue secondary — 6.33:1 white-on-fill; 6.01/5.03:1 as ink on bg/bg-alt */
  --teal-bright: #7BA9C9;        /* pale slate-blue — 7.04:1 on --navy, 6.20:1 on --navy-2 */
  --orange: #18734F;             /* forest-green PRIMARY — 5.83:1 white-on-fill; 5.53/4.63:1 as ink on bg/bg-alt */
  --orange-bright: #1C9E6A;      /* saturated accent on dark — 5.18:1 on --navy, 4.56:1 on --navy-2 */

  --color-link: var(--teal);
  --color-text: #222925;         /* body ink (14.12:1 on bg) */
  --color-text-muted: #4F685B;   /* muted ink (5.76/4.82:1 on bg/bg-alt) */
  --color-heading: #1B211E;      /* headings (15.54:1 on bg) */
  --color-bg: #F6FAF7;           /* page */
  --color-bg-alt: #DDE8DF;       /* sage band (hue ~131°) */
  --color-border: #CBD9CD;       /* border */
  --oat: #D2E0D5;                /* card/field surface (text 10.9:1, teal 4.63:1, select-ink 4.95:1) */
  --color-error: #B8232D;        /* crimson, clear of the accent axis (6.01:1 on bg) */
  --color-focus: var(--orange);
  --color-fg-on-dark: #ffffff;   /* stays white (exempt) */

  --accent-frame: var(--orange-bright);   /* ON-DARK rules: the button colour is only 2.6-3.2:1 on the near-black sections */
  --on-dark-nav: #B1C4BA;        /* top-bar text (9.67:1 on --navy) */
  --on-dark-social: #A4BAAF;     /* top-bar social (8.61:1 on --navy) */
  --on-dark-body: #81A090;       /* footer body (6.20:1 on --navy) */
  --on-dark-link: #A4BAAF;       /* footer links (8.61:1 on --navy) */
  --on-dark-faint: #698C7A;      /* legal fine print (4.75:1 on --navy) */
  --on-teal-label: #D7E2EA;      /* pale label on the secondary band (4.81:1 on --teal) */

  --metal-1: #717F7A;            /* cool green-pewter rib */
  --metal-2: #97A5A0;            /* rib highlight */
  --metal-3: #606C68;            /* rib shadow */

  --overlay-dark: linear-gradient(rgba(17,24,20,0.82), rgba(17,24,20,0.88));
  --overlay-teal: linear-gradient(rgba(29,55,73,0.86), rgba(23,44,58,0.92));  /* secondary-tinted */
  --overlay-soft: linear-gradient(rgba(17,24,20,0.55), rgba(17,24,20,0.72));
  --overlay-scrim: linear-gradient(rgba(17,24,20,0.30), rgba(17,24,20,0.30));
  --overlay-scrim-strong: linear-gradient(rgba(17,24,20,0.35), rgba(17,24,20,0.35));
  --overlay-panel: rgba(17,24,20,0.78);

  --focus-ring: rgba(24,115,79,0.18);     /* from --orange #18734F */
  --wash-accent: rgba(54,100,133,0.22);   /* from --teal #366485 */

  --select-ink: #4B6056;         /* passes on the --oat field (4.95:1) */
  --select-caret: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%234B6056'><path d='M7 10l5 5 5-5z'/></svg>");

  /* bright green circle on the dark hero panel ⇒ dark check, not white */
  --bullet-hero: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><circle cx='12' cy='12' r='11' fill='%2318734F'/><path d='M17 8.5L10.5 15.5 7 12' fill='none' stroke='white' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'/></svg>");
  --bullet-badge: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><circle cx='12' cy='12' r='11' fill='%2318734F'/><path d='M17 8.5L10.5 15.5 7 12' fill='none' stroke='white' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'/></svg>");
  --bullet-snow: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><circle cx='12' cy='12' r='11' fill='%2318734F'/><path d='M17 8.5L10.5 15.5 7 12' fill='none' stroke='white' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'/></svg>");
  --tick-timber: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M20 6L9 17l-5-5' fill='none' stroke='%2318734F' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'/></svg>");
}

/* Harbor — deliberately reduced to SEVEN values, the operator's specified palette:
     #0F232D navy · #FFF5D0 cream · #1C3846 mid navy · #E9E7D9 greige
     #FFFFFF white (page + card surfaces) · plus #B0242A, the only exception, because the
     contract requires error to stay recognizably red.
   Every other role is reassigned to one of those rather than given its own value.
   The proposed #1B3846 turned out unnecessary — #1C3846 covers every role it would
   have filled, and the two are 0.2% apart in lightness.
   TWO DISTINCTIONS ARE DELIBERATELY GIVEN UP, and they are tradeoffs, not bugs:
     - muted body text is #1C3846 against #0F232D body, only 12.0:1 vs 15.8:1 on the
       page, so paragraph hierarchy is nearly flat;
     - the on-dark chrome collapses from four weights to two (white / greige), so the
       top bar, footer links, footer body and legal fine print no longer differ.
   Both need a mid-tone that this palette does not contain. */
[data-theme="harbor"] {
  --navy: #0F232D;                    /* navy — chrome, dark sections, footer, in-hero form, light-surface buttons */
  --navy-2: #1C3846;                  /* = mid navy — service/project card panels */
  --navy-card: #1C3846;               /* = mid navy — the .quote-bar band under the split hero */
  --teal: #1C3846;                    /* = mid navy — h3, links, labels, card headers */
  --teal-bright: #FFF5D0;             /* = cream — labels on dark */
  --orange: #1C3846;                  /* = mid navy — small accent marks on light (.accent, wordmark, faq +) */
  --orange-bright: #FFF5D0;           /* = cream — the highlight on dark */
  --orange-fill: #0F232D;             /* = navy — button fill on LIGHT surfaces */
  --btn-ink: #FFF5D0;                 /* = cream ink on it (14.80:1) */
  --btn-fill-dark: #FFF5D0;           /* = cream — button fill on DARK surfaces */
  --btn-ink-dark: #0F232D;            /* = navy ink on it (14.80:1) */
  --accent-frame: #FFF5D0;            /* = cream — decorative rules on dark */
  --keyline: #1C3846;                 /* = mid navy — offset frame behind figures */
  --card-accent: #1C3846;             /* = mid navy — faq / testimonial card bars */

  --color-link: var(--teal);
  --color-text: #0F232D;
  --color-heading: #0F232D;
  --color-text-muted: #1C3846;
  --color-bg: #FFFFFF;
  --color-bg-alt: #FFFCF2;   /* alternating band: warm white, not the cream. #FFF5D0 is 100%
                                saturation at L91% — an accent on navy, too yellow as a full section. */
  --color-border: #E9E7D9;
  --oat: #E9E7D9;            /* cards + form fields: greige. Reads on the white page and on the
                                #FFFCF2 band; the earlier objection was greige on a warm-white PAGE. */
  --color-error: #B0242A;
  --color-focus: var(--orange-fill);
  --color-fg-on-dark: #ffffff;

  --on-dark-nav: #FFFFFF;
  --on-dark-social: #FFFFFF;
  --on-dark-body: #E9E7D9;
  --on-dark-link: #FFFFFF;
  --on-dark-faint: #E9E7D9;
  --on-teal-label: #FFF5D0;
  --metal-1: #1C3846;
  --metal-2: #E9E7D9;
  --metal-3: #0F232D;
  --select-ink: #1C3846;

  --overlay-dark: linear-gradient(rgba(15,35,45,0.82), rgba(15,35,45,0.88));
  --overlay-teal: linear-gradient(rgba(28,56,70,0.86), rgba(28,56,70,0.92));
  --overlay-soft: linear-gradient(rgba(15,35,45,0.55), rgba(15,35,45,0.72));
  --overlay-scrim: linear-gradient(rgba(15,35,45,0.30), rgba(15,35,45,0.30));
  --overlay-scrim-strong: linear-gradient(rgba(15,35,45,0.35), rgba(15,35,45,0.35));
  --overlay-panel: rgba(15,35,45,0.78);

  --focus-ring: rgba(15,35,45,0.18);
  --wash-accent: rgba(28,56,70,0.22);

  --select-caret: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%231C3846'><path d='M7 10l5 5 5-5z'/></svg>");

  --bullet-hero: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><circle cx='12' cy='12' r='11' fill='%23FFF5D0'/><path d='M17 8.5L10.5 15.5 7 12' fill='none' stroke='%230F232D' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'/></svg>");
  --bullet-badge: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><circle cx='12' cy='12' r='11' fill='%230F232D'/><path d='M17 8.5L10.5 15.5 7 12' fill='none' stroke='%23FFF5D0' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'/></svg>");
  --bullet-snow: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><circle cx='12' cy='12' r='11' fill='%230F232D'/><path d='M17 8.5L10.5 15.5 7 12' fill='none' stroke='%23FFF5D0' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'/></svg>");
  --tick-timber: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M20 6L9 17l-5-5' fill='none' stroke='%231C3846' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'/></svg>");
}

/* Foreman — the operator's trio: #CD4B27 burnt orange as the loud PRIMARY and
   #225777 steel blue as the secondary, used VERBATIM for the blue, on a crisp
   white page with a cool blue-gray band and deep steel-navy darks drawn from the
   #225777 family. The orange sits at #BD4524 — the #CD4B27 family darkened just
   enough to clear 4.5:1 as ink on the band as well as on white (#CD4B27 itself is
   4.53:1 on white, fine on a button, short on the band). NOTE: the operator's
   #C24C3A is only 5° of hue and 1% of lightness from #CD4B27 — the two are the
   same colour in practice, so a single warm primary carries both. Orange + steel
   blue + white is the most standard trade scheme there is. */
[data-theme="foreman"] {
  --card-accent: var(--orange-fill);   /* saturated secondary -> card bars follow the accent */
  --keyline: #577383;   /* muted secondary — visible like the default timber frame, without the saturated hue */
  --navy: #13202B;               /* deep steel navy — white 16.55:1 */
  --navy-2: #17232D;             /* lighter panels (service/project cards) — white 14.32:1 */
  --navy-card: #20313E;          /* quote-form card (white 13.37:1) */
  --teal: #225777;               /* steel-blue secondary (operator #225777, verbatim) — 7.78:1 white-on-fill; 7.78/6.85:1 as ink on bg/bg-alt */
  --teal-bright: #7CAFCF;        /* pale steel-blue on dark — 7.00:1 on --navy, 6.06:1 on --navy-2 */
  --orange: #BD4524;             /* burnt-orange PRIMARY (from #CD4B27) — 5.20:1 white-on-fill; 5.20/4.58:1 as ink on bg/bg-alt */
  --orange-bright: #E17152;      /* saturated accent on dark — 5.27:1 on --navy, 4.56:1 on --navy-2 */

  --color-link: var(--teal);
  --color-text: #262C31;         /* body ink (14.12:1 on bg) */
  --color-text-muted: #576A78;   /* muted ink (5.62/4.95:1 on bg/bg-alt) */
  --color-heading: #1F2428;      /* headings (15.66:1 on bg) */
  --color-bg: #FFFFFF;           /* page */
  --color-bg-alt: #EDF1F4;       /* cool blue-gray band (hue ~206°) */
  --color-border: #D3DCE3;       /* border */
  --oat: #DFE6EB;                /* card/field surface (text 11.2:1, teal 6.17:1, select-ink 4.91:1) */
  --color-error: #BD2731;        /* crimson, clear of the rust axis (6.00:1 on bg) */
  --color-focus: var(--orange);
  --color-fg-on-dark: #ffffff;   /* stays white (exempt) */

  --accent-frame: var(--orange-bright);   /* ON-DARK rules: the button colour is only 2.6-3.2:1 on the near-black sections */
  --on-dark-nav: #BDC7CD;        /* top-bar text (9.62:1 on --navy) */
  --on-dark-social: #B2BDC5;     /* top-bar social (8.65:1 on --navy) */
  --on-dark-body: #91A1AC;       /* footer body (6.22:1 on --navy) */
  --on-dark-link: #B2BDC5;       /* footer links (8.65:1 on --navy) */
  --on-dark-faint: #798C9A;      /* legal fine print (4.75:1 on --navy) */
  --on-teal-label: #BBCEDA;      /* pale label on the secondary band (4.80:1 on --teal) */

  --metal-1: #697B86;            /* cool blue-steel rib */
  --metal-2: #92A1AB;            /* rib highlight */
  --metal-3: #5A6972;            /* rib shadow */

  --overlay-dark: linear-gradient(rgba(17,28,38,0.82), rgba(17,28,38,0.88));
  --overlay-teal: linear-gradient(rgba(18,47,65,0.86), rgba(14,38,52,0.92));  /* secondary-tinted */
  --overlay-soft: linear-gradient(rgba(17,28,38,0.55), rgba(17,28,38,0.72));
  --overlay-scrim: linear-gradient(rgba(17,28,38,0.30), rgba(17,28,38,0.30));
  --overlay-scrim-strong: linear-gradient(rgba(17,28,38,0.35), rgba(17,28,38,0.35));
  --overlay-panel: rgba(17,28,38,0.78);

  --focus-ring: rgba(189,69,36,0.18);     /* from --orange #BD4524 */
  --wash-accent: rgba(34,87,119,0.22);   /* from --teal #225777 */

  --select-ink: #55636D;         /* passes on the --oat field (4.91:1) */
  --select-caret: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%2355636D'><path d='M7 10l5 5 5-5z'/></svg>");

  /* light orange circle on the dark hero panel ⇒ dark check, not white */
  --bullet-hero: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><circle cx='12' cy='12' r='11' fill='%23BD4524'/><path d='M17 8.5L10.5 15.5 7 12' fill='none' stroke='white' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'/></svg>");
  --bullet-badge: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><circle cx='12' cy='12' r='11' fill='%23BD4524'/><path d='M17 8.5L10.5 15.5 7 12' fill='none' stroke='white' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'/></svg>");
  --bullet-snow: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><circle cx='12' cy='12' r='11' fill='%23BD4524'/><path d='M17 8.5L10.5 15.5 7 12' fill='none' stroke='white' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'/></svg>");
  --tick-timber: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M20 6L9 17l-5-5' fill='none' stroke='%23BD4524' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'/></svg>");
}

/* Ember — burnt orange as the loud PRIMARY on a crisp white page, with
   near-black cool-charcoal darks and a true navy-slate secondary. The primary
   sits at #BB4424, the #CD4B27 family darkened just enough to clear 4.5:1 on the
   warm-gray band as well as on white. Separated from the default barn-red (9°) by
   being brighter and more orange, and from Harbor by its neutrals: Ember is
   white + warm gray + near-black, Harbor is cream + greige + petrol navy. The
   primary-colour scheme — orange, navy, white — that most trade sites reach for. */
[data-theme="ember"] {
  --card-accent: var(--orange-fill);   /* saturated secondary -> card bars follow the accent */
  --keyline: #5C718A;   /* muted secondary — visible like the default timber frame, without the saturated hue */
  --navy: #1B2026;               /* cool near-black charcoal — white 16.39:1 */
  --navy-2: #1D2127;             /* lighter panels (service/project cards) — white 14.28:1 */
  --navy-card: #292F37;          /* quote-form card (white 13.50:1) */
  --teal: #3F6693;               /* navy-slate secondary — 5.94:1 white-on-fill; 5.94/5.14:1 as ink on bg/bg-alt */
  --teal-bright: #8BADD4;        /* pale navy-slate on dark — 7.04:1 on --navy, 6.14:1 on --navy-2 */
  --orange: #BB4424;             /* burnt-orange PRIMARY (from #CD4B27) — 5.30:1 white-on-fill; 5.30/4.58:1 as ink on bg/bg-alt */
  --orange-bright: #E17254;      /* saturated accent on dark — 5.26:1 on --navy, 4.58:1 on --navy-2 */

  --color-link: var(--teal);
  --color-text: #282C31;         /* body ink (14.05:1 on bg) */
  --color-text-muted: #5A6978;   /* muted ink (5.64/4.87:1 on bg/bg-alt) */
  --color-heading: #212428;      /* headings (15.58:1 on bg) */
  --color-bg: #FFFFFF;           /* page */
  --color-bg-alt: #F1EEE9;       /* warm light-gray band (hue ~38°) */
  --color-border: #DCD6CB;       /* border */
  --oat: #E6E1D9;                /* card/field surface (text 10.8:1, teal 4.57:1, select-ink 4.93:1) */
  --color-error: #BD2731;        /* crimson, clear of the rust axis (6.00:1 on bg) */
  --color-focus: var(--orange);
  --color-fg-on-dark: #ffffff;   /* stays white (exempt) */

  --accent-frame: var(--orange-bright);   /* ON-DARK rules: the button colour is only 2.6-3.2:1 on the near-black sections */
  --on-dark-nav: #C0C7CF;        /* top-bar text (9.61:1 on --navy) */
  --on-dark-social: #B4BDC6;     /* top-bar social (8.61:1 on --navy) */
  --on-dark-body: #93A1AE;       /* footer body (6.20:1 on --navy) */
  --on-dark-link: #B4BDC6;       /* footer links (8.61:1 on --navy) */
  --on-dark-faint: #7C8C9C;      /* legal fine print (4.75:1 on --navy) */
  --on-teal-label: #E1E8EF;      /* pale label on the secondary band (4.81:1 on --teal) */

  --metal-1: #6F7880;            /* cool steel rib */
  --metal-2: #969EA6;            /* rib highlight */
  --metal-3: #5F666D;            /* rib shadow */

  --overlay-dark: linear-gradient(rgba(24,28,33,0.82), rgba(24,28,33,0.88));
  --overlay-teal: linear-gradient(rgba(34,56,80,0.86), rgba(27,44,64,0.92));  /* secondary-tinted */
  --overlay-soft: linear-gradient(rgba(24,28,33,0.55), rgba(24,28,33,0.72));
  --overlay-scrim: linear-gradient(rgba(24,28,33,0.30), rgba(24,28,33,0.30));
  --overlay-scrim-strong: linear-gradient(rgba(24,28,33,0.35), rgba(24,28,33,0.35));
  --overlay-panel: rgba(24,28,33,0.78);

  --focus-ring: rgba(187,68,36,0.18);     /* from --orange #BB4424 */
  --wash-accent: rgba(63,102,147,0.22);   /* from --teal #3F6693 */

  --select-ink: #55606C;         /* passes on the --oat field (4.93:1) */
  --select-caret: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%2355606C'><path d='M7 10l5 5 5-5z'/></svg>");

  /* light orange circle on the dark hero panel ⇒ dark check, not white */
  --bullet-hero: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><circle cx='12' cy='12' r='11' fill='%23BB4424'/><path d='M17 8.5L10.5 15.5 7 12' fill='none' stroke='white' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'/></svg>");
  --bullet-badge: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><circle cx='12' cy='12' r='11' fill='%23BB4424'/><path d='M17 8.5L10.5 15.5 7 12' fill='none' stroke='white' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'/></svg>");
  --bullet-snow: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><circle cx='12' cy='12' r='11' fill='%23BB4424'/><path d='M17 8.5L10.5 15.5 7 12' fill='none' stroke='white' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'/></svg>");
  --tick-timber: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M20 6L9 17l-5-5' fill='none' stroke='%23BB4424' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'/></svg>");
}

/* Blaze — a CUSTOM palette, not a slot-fill. Every other palette in this skin
   fills the same four roles with distinct hues (loud primary + SEPARATE secondary
   hue + tinted darks + tinted band); that structure is what makes them read as
   "several colours" rather than one scheme. Blaze breaks it deliberately: ONE hue
   does all the colour work, and the secondary role — h3s, links, labels — is a
   NEUTRAL warm gray instead of a second hue. Black, white, gray, orange, nothing
   else.
   It is also the first palette to use the --orange-fill / --btn-ink split. White
   ink caps a usable orange at ~#D04910; the split lets the FILL people actually
   see on buttons, step nodes and tags be a genuinely straight #F26A1B carrying
   dark ink at 6.12:1, while --orange stays a legible #C4450F for the few small
   TEXT roles (the faq "+", .accent, .brand-text b, the button hover state). */
[data-theme="blaze"] {
  --navy: #121212;                /* true near-black */
  --navy-2: #1C1A18;              /* lighter panels */
  --navy-card: #201E1B;           /* quote-form card */
  --teal: #4A4441;                /* NEUTRAL warm gray secondary — deliberately not a second hue */
  --teal-bright: #C9C3BE;         /* pale warm gray on dark */
  --orange: #C4450F;              /* TEXT-role orange (must read on light) */
  --orange-bright: #F26A1B;   /* SAME single orange (6.11:1 on --navy) — a separate on-dark tint was the last stray */
  --orange-fill: #F26A1B;         /* THE straight orange — button/node/tag fills */
  --btn-ink: #1A1005;             /* dark ink ON --orange-fill (6.12:1) */

  --color-link: var(--teal);
  --color-text: #22201E;
  --color-text-muted: #635C57;
  --color-heading: #1A1817;
  --color-bg: #FFFFFF;
  --color-bg-alt: #F5F3F1;
  --color-border: #DFDAD5;
  --oat: #E8E4E0;
  --color-error: #B7232D;
  --color-focus: var(--orange-fill);
  --color-fg-on-dark: #ffffff;   /* stays white (exempt) */

  --accent-frame: #F26A1B;
  --on-dark-nav: #CFC9C4;
  --on-dark-social: #C4BDB8;
  --on-dark-body: #A29A94;
  --on-dark-link: #C4BDB8;
  --on-dark-faint: #867E78;
  --on-teal-label: #DDD7D2;
  --metal-1: #7A7570;
  --metal-2: #9E9993;
  --metal-3: #6A6560;

  --overlay-dark: linear-gradient(rgba(16,16,16,0.82), rgba(16,16,16,0.88));
  --overlay-teal: linear-gradient(rgba(41,38,36,0.86), rgba(33,30,29,0.92));  /* neutral-tinted */
  --overlay-soft: linear-gradient(rgba(16,16,16,0.55), rgba(16,16,16,0.72));
  --overlay-scrim: linear-gradient(rgba(16,16,16,0.30), rgba(16,16,16,0.30));
  --overlay-scrim-strong: linear-gradient(rgba(16,16,16,0.35), rgba(16,16,16,0.35));
  --overlay-panel: rgba(16,16,16,0.78);

  --focus-ring: rgba(242,106,27,0.18);
  --wash-accent: rgba(74,68,65,0.22);

  --select-ink: #5C5651;
  --select-caret: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='%235C5651'><path d='M7 10l5 5 5-5z'/></svg>");

  /* the vivid fills take DARK checks; the neutral secondary keeps a white one */
  --bullet-hero: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><circle cx='12' cy='12' r='11' fill='%23F26A1B'/><path d='M17 8.5L10.5 15.5 7 12' fill='none' stroke='%231A1005' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'/></svg>");
  --bullet-badge: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><circle cx='12' cy='12' r='11' fill='%23F26A1B'/><path d='M17 8.5L10.5 15.5 7 12' fill='none' stroke='%231A1005' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'/></svg>");
  --bullet-snow: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><circle cx='12' cy='12' r='11' fill='%23F26A1B'/><path d='M17 8.5L10.5 15.5 7 12' fill='none' stroke='%231A1005' stroke-width='2.4' stroke-linecap='round' stroke-linejoin='round'/></svg>");
  --tick-timber: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M20 6L9 17l-5-5' fill='none' stroke='%23F26A1B' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'/></svg>");
}

/* ---------- Self-hosted fonts ---------- */
@font-face { font-family:"Roboto"; font-style:normal; font-weight:100 900; font-display:swap; src:url("/fonts/roboto.woff2") format("woff2"); }
@font-face { font-family:"Barlow"; font-style:normal; font-weight:600; font-display:swap; src:url("/fonts/barlow-600.woff2") format("woff2"); }
@font-face { font-family:"Barlow"; font-style:normal; font-weight:700; font-display:swap; src:url("/fonts/barlow-700.woff2") format("woff2"); }
@font-face { font-family:"Barlow Condensed"; font-style:normal; font-weight:600; font-display:swap; src:url("/fonts/barlow-condensed-600.woff2") format("woff2"); }
@font-face { font-family:"Barlow Condensed"; font-style:normal; font-weight:700; font-display:swap; src:url("/fonts/barlow-condensed-700.woff2") format("woff2"); }

/* ---------- Reset ---------- */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }
html, body { overflow-x: clip; }
:target, section[id] { scroll-margin-top: calc(var(--header-h) + 1rem); }
body {
  margin: 0;
  font-family: var(--font-body);
  font-size: 16px;
  line-height: 1.7;
  color: var(--color-text);
  background: var(--color-bg);
  -webkit-font-smoothing: antialiased;
}
img, picture, svg { display: block; max-width: 100%; height: auto; }
h1, h2, h3, h4 {
  font-family: var(--font-head);
  font-weight: 700;
  line-height: 1.04;
  margin: 0 0 0.5em;
  color: var(--color-heading);
  text-transform: uppercase;
  letter-spacing: 0.01em;
}
h1 { font-size: clamp(2rem, 4vw, 2.8rem); }
h2 { font-size: clamp(1.6rem, 3vw, 2.05rem); }
h3 { font-size: clamp(1.2rem, 1.9vw, 1.35rem); color: var(--teal); }
h4 { font-size: 1.1rem; }
p { margin: 0 0 1em; }
a { color: var(--color-link); text-decoration-thickness: 1px; text-underline-offset: 2px; }
a:hover { text-decoration-thickness: 2px; }
strong { color: inherit; font-weight: 700; }

/* ---------- A11y ---------- */
:focus-visible { outline: 3px solid var(--color-focus); outline-offset: 2px; }
.skip-link {
  position: absolute; left: -10000px; top: auto; width: 1px; height: 1px; overflow: hidden;
  background: var(--navy); color: #fff; padding: 0.75rem 1rem; z-index: 1000;
}
.skip-link:focus { left: 0; top: 0; width: auto; height: auto; }
.hp-field {
  position: absolute !important; width: 1px !important; height: 1px !important; min-width: 0 !important; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap; border: 0;
}
.sr-h2, .visually-hidden {
  position: absolute !important; width: 1px; height: 1px; padding: 0; margin: -1px;
  overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap; border: 0;
}

/* ---------- Layout ---------- */
.container { width: 100%; max-width: var(--max-w); margin: 0 auto; padding: 0 1.25rem; }
main { display: block; }
section { padding: clamp(2.75rem, 6vw, 4.75rem) 0; }
.section-dark { background: var(--navy); color: var(--color-fg-on-dark); }
.section-dark h2, .section-dark h3, .section-dark h4 { color: #fff; }
.section-dark p { color: rgba(255,255,255,0.82); }
.section-dark a:not(.btn) { color: var(--orange-bright); }
.section-intro { max-width: 78ch; margin: 0 0 2rem; }
.section-cta { display: flex; justify-content: center; margin-top: 2rem; }
.section-label {
  font-family: var(--font-head); font-weight: 700; text-transform: uppercase;
  letter-spacing: 0.08em; color: var(--teal); font-size: 1.05rem; margin: 0 0 0.4rem;
}
.section-dark .section-label, .lf-banner .section-label { color: var(--teal-bright); }
.lf-banner.b-teal .section-label { color: var(--on-teal-label); }
.accent { color: var(--orange); }
.section-dark .accent { color: var(--orange-bright); }

/* ---------- Gable roofline top edge (post-frame profile) ----------
   Carves a center roof-peak into the section's top edge; the section
   behind (usually white/oat) shows through the notches. Add extra
   top padding so content clears the peak. */
.gable-top {
  --gable: clamp(1.25rem, 3.2vw, 2.75rem);
  clip-path: polygon(0 var(--gable), 50% 0, 100% var(--gable), 100% 100%, 0 100%);
  padding-top: calc(clamp(2.75rem, 6vw, 4.75rem) + var(--gable));
}

/* ---------- Buttons ---------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 0.55rem;
  font: inherit; font-family: var(--font-head); font-weight: 700; font-size: 1.1rem;
  text-transform: uppercase; letter-spacing: 0.04em;
  padding: 0.7rem 1.6rem; border: 2px solid transparent; border-radius: var(--radius);
  text-decoration: none; cursor: pointer; min-height: 50px; line-height: 1.1;
  transition: background-color .15s ease, color .15s ease, border-color .15s ease, transform .08s ease;
}
.btn:active { transform: translateY(1px); }
/* All .btn variants are SOLID by default and go OUTLINE on hover (inverse
   fill). The .btn 2px border is reserved transparent above, so the swap
   never changes the button's size. (.btn-tel, the header call button, is
   the sole exception — see its own rule below.) */
.btn-call, .btn-primary { background: var(--orange-fill); color: var(--btn-ink); border-color: var(--orange-fill); }
.btn-call:hover, .btn-primary:hover { background: transparent; color: var(--orange); border-color: var(--orange-fill); }
.btn-teal { background: var(--teal); color: #fff; border-color: var(--teal); }
.btn-teal:hover { background: transparent; color: var(--teal); border-color: var(--teal); }
/* white solid — sits on dark backgrounds */
.btn-services, .btn-outline-light { background: #fff; color: var(--navy); border-color: #fff; }
.btn-services:hover, .btn-outline-light:hover { background: transparent; color: #fff; border-color: #fff; }
/* Harbor's on-dark primary IS the cream, so a solid-white secondary next to it reads
   as two light buttons. Outline it there — same reasoning as .btn-outline-dark on the
   light surfaces, where harbor's primary is the navy. */
[data-theme="harbor"] .btn-outline-light { background: transparent; color: #fff; border-color: #fff; }
[data-theme="harbor"] .btn-outline-light:hover { background: #fff; color: var(--navy); border-color: #fff; }
/* In the HERO the secondary takes the mid navy as a solid fill instead of an outline:
   the cream primary is already the loud element, and a filled --navy-card sits quietly
   beside it while still reading against the hero photo (white ink at 12.33:1). */
[data-theme="harbor"] .hero .btn-outline-light {
  background: var(--navy-card); color: #fff; border-color: var(--navy-card);
}
[data-theme="harbor"] .hero .btn-outline-light:hover {
  background: transparent; color: #fff; border-color: #fff;
}
/* dark solid — sits on light backgrounds */
.btn-outline-dark, .btn-outline-navy { background: var(--color-heading); color: #fff; border-color: var(--color-heading); }
.btn-outline-dark:hover, .btn-outline-navy:hover { background: transparent; color: var(--color-heading); border-color: var(--color-heading); }
/* The .btn-*outline* classes are legacy aliases that render SOLID (see CLAUDE.md), which
   works while the PRIMARY is a saturated accent. Harbor's light-surface primary is the navy
   itself, so a solid near-black secondary next to it produced two buttons 3% apart in
   lightness and no hierarchy. Render the secondary as a true outline in that palette only —
   scoped rather than tokenized, because the skin already has more colour slots than it needs. */
[data-theme="harbor"] .btn-outline-dark,
[data-theme="harbor"] .btn-outline-navy { background: transparent; color: var(--color-heading); border-color: var(--color-heading); }
[data-theme="harbor"] .btn-outline-dark:hover,
[data-theme="harbor"] .btn-outline-navy:hover { background: var(--color-heading); color: #fff; border-color: var(--color-heading); }
/* on dark sections the barn-red outline needs the brighter brick to stay legible.
   `background: transparent` is load-bearing: `.section-dark .btn-call` below sets an
   on-dark FILL (--btn-fill-dark) at equal specificity but LATER in the file, so it beats
   the base `.btn-call:hover` transparent. Without restating it here the fill survives the
   hover and the button paints its hover ink on its own fill — invisible in harbor, where
   both resolve to the same cream. */
.hero .btn-call:hover, .section-dark .btn-call:hover, .section-dark .btn-primary:hover,
.section-dark .btn-teal:hover { background: transparent; color: var(--orange-bright); border-color: var(--orange-bright); }
.btn-block { display: flex; width: 100%; }

/* ============================================================
   img-as-background helper (real <img>, positioned to fill)
   ============================================================ */
.bg-host { position: relative; isolation: isolate; }
.bg-img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; z-index: 0; }
.bg-host::before {
  content: ""; position: absolute; inset: 0; z-index: 1;
  background: var(--overlay-dark);
}
.bg-host.bg-teal::before { background: var(--overlay-teal); }
.bg-host.bg-soft::before { background: var(--overlay-soft); }
.bg-host > .container { position: relative; z-index: 2; }
/* Fixed (parallax) backgrounds — disabled on small/touch screens where iOS renders them badly.
   The hero's parallax uses its CSS background (attachment: fixed, clips to the section);
   its .bg-img is hidden on desktop so the fixed background shows through. */
@media (max-width: 900px) {
  .bg-fixed { background-attachment: scroll !important; }
}

/* ============================================================
   Top bar (navy, scrolls away) + Header (white, sticky)
   ============================================================ */
.top-bar { background: var(--navy); color: var(--on-dark-nav); font-size: 0.9rem; }
.top-bar .container {
  padding-top: 0.5rem; padding-bottom: 0.5rem;
  display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 0.35rem 1.5rem;
}
.top-bar-list { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; align-items: center; gap: 0.35rem 1.75rem; }
.top-bar-list li { display: inline-flex; align-items: center; gap: 0.5rem; color: var(--on-dark-nav); }
.top-bar-list a { color: var(--on-dark-nav); text-decoration: none; display: inline-flex; align-items: center; gap: 0.5rem; }
.top-bar-list a:hover { color: #fff; }
.top-bar-list svg { color: var(--orange-bright); flex-shrink: 0; }
.top-bar-social { display: inline-flex; align-items: center; gap: 0.9rem; }
.top-bar-social a { color: var(--on-dark-social); display: inline-flex; }
.top-bar-social a:hover { color: #fff; }

.site-header {
  position: sticky; top: 0; z-index: 50;
  background: #fff;
  box-shadow: 0 2px 14px rgba(43,42,40,0.12);
}
.site-header .container {
  display: flex; align-items: center; justify-content: space-between; gap: 1rem;
  min-height: var(--header-h);
}
.brand { display: inline-flex; align-items: center; gap: 0.6rem; text-decoration: none; padding: 0.4rem 0; }
.brand-logo { height: 56px; width: auto; display: block; }
.brand-text { font-family: var(--font-head); font-weight: 700; text-transform: uppercase; letter-spacing: 0.01em; line-height: 1; font-size: 1.7rem; color: var(--navy); }
.brand-text b { color: var(--orange); font-weight: 700; }
@media (max-width: 600px) { .brand-logo { height: 44px; } .brand-text { font-size: 1.35rem; } }

.site-nav { display: flex; align-items: center; }
.nav-list { display: flex; align-items: center; gap: 0.25rem 2rem; flex-wrap: wrap; list-style: none; margin: 0; padding: 0; }
.nav-item { position: relative; }
.nav-item > a {
  display: inline-flex; align-items: center; gap: 0.3rem; color: var(--navy); text-decoration: none;
  font-family: var(--font-head); font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em;
  font-size: 1.15rem; padding: 1.4rem 0.1rem;
}
.nav-item > a:hover { color: var(--teal); }
.nav-caret { transition: transform .15s ease; flex-shrink: 0; }
.has-dropdown:hover > a .nav-caret, .has-dropdown:focus-within > a .nav-caret { transform: rotate(180deg); }
.dropdown {
  position: absolute; top: 100%; left: 0; min-width: 250px; background: #fff;
  box-shadow: 0 16px 36px rgba(43,42,40,0.22); list-style: none; margin: 0; padding: 0.5rem 0;
  z-index: 100; opacity: 0; visibility: hidden; transform: translateY(6px);
  transition: opacity .15s ease, visibility .15s ease, transform .15s ease;
  border-top: 3px solid var(--orange-fill);
}
.has-dropdown:hover > .dropdown, .has-dropdown:focus-within > .dropdown { opacity: 1; visibility: visible; transform: translateY(0); }
.dropdown li { margin: 0; }
.dropdown a { display: block; padding: 0.55rem 1.1rem; font-size: 0.95rem; font-weight: 500; color: var(--color-text); text-decoration: none; white-space: nowrap; }
.dropdown a:hover, .dropdown a:focus-visible { background: var(--color-bg-alt); color: var(--teal); }
.dropdown-2col, .dropdown-3col { display: grid; }
.dropdown-2col { grid-template-columns: 1fr 1fr; min-width: 440px; }
.dropdown-3col { grid-template-columns: 1fr 1fr 1fr; min-width: 560px; }
@media (max-width: 1100px) { .dropdown-3col { grid-template-columns: 1fr 1fr; min-width: 400px; } }

.nav-cta { margin-left: 0.5rem; }
.btn-tel {
  background: var(--navy); color: #fff; border-radius: var(--radius);
  /* 4px bottom border reserved transparent (bottom padding shortened to
     match) so the hover accent adds NO height — only its color changes */
  padding: 0.7rem 1.5rem calc(0.7rem - 4px); border-bottom: 4px solid transparent;
  font-family: var(--font-head); font-weight: 700; font-size: 1.3rem; letter-spacing: 0.02em;
  text-transform: none; display: inline-flex;
  align-items: center; gap: 0.5rem; min-height: 50px; text-decoration: none;
  white-space: nowrap; flex-shrink: 0;
  transition: border-color .15s ease;
}
/* Narrow-desktop squeeze (nav can wrap to two rows): tighten the rows */
@media (min-width: 901px) and (max-width: 980px) {
  .nav-item > a { padding-top: 0.45rem; padding-bottom: 0.45rem; }
}
.btn-tel:hover { border-bottom-color: var(--orange-bright); }

.menu-toggle { display: none; background: transparent; border: 0; padding: 0; width: 44px; height: 44px; align-items: center; justify-content: center; cursor: pointer; }
.menu-toggle span, .menu-toggle span::before, .menu-toggle span::after { display: block; width: 26px; height: 3px; background: var(--navy); border-radius: var(--radius); transition: transform .25s ease, top .25s ease; }
.menu-toggle span { position: relative; }
.menu-toggle span::before, .menu-toggle span::after { content: ""; position: absolute; left: 0; }
.menu-toggle span::before { top: -8px; } .menu-toggle span::after { top: 8px; }
.menu-toggle.is-open span { background: transparent; }
.menu-toggle.is-open span::before { top: 0; transform: rotate(45deg); }
.menu-toggle.is-open span::after { top: 0; transform: rotate(-45deg); }

/* SITE-LOCAL DIVERGENCE from _polebarn-template: breakpoint raised 900 -> 1150.
   The brand is now the real image logo (~245px wide at 56px tall), so brand +
   4-item nav + phone button cannot fit on one row until ~1150px; below that the
   nav wrapped to a second row (header 151px vs --header-h 80px). Hand the
   hamburger over before the nav wraps instead. Re-measured 2026-07-29 when the
   image logo replaced the temporary text wordmark (which had allowed 1020px). */
@media (max-width: 1150px) {
  .top-bar .container { justify-content: center; }
  .top-bar-list { justify-content: center; font-size: 0.82rem; gap: 0.25rem 1.25rem; }
  .site-header .container { flex-wrap: wrap; align-content: center; row-gap: 0; }
  .site-header .brand { min-height: var(--header-h); }
  .site-nav { display: none; }
  .menu-toggle { display: inline-flex; order: 3; }
  .nav-cta { order: 2; }
  .site-nav.is-open {
    display: block; order: 4; flex: 1 1 100%; margin: 0 -1.25rem 0;
    padding: 0.25rem 1.25rem 1rem; background: var(--navy);
    /* The header is sticky, so a menu taller than the viewport is otherwise
       unreachable — cap it at the space below the header row and scroll
       internally. vh fallback first, dvh corrects for mobile browser chrome. */
    max-height: calc(100vh - var(--header-h));
    max-height: calc(100dvh - var(--header-h));
    overflow-y: auto;
    overscroll-behavior: contain;
  }
  .site-nav.is-open .nav-list { flex-direction: column; align-items: stretch; gap: 0; }
  .site-nav.is-open .nav-item { width: 100%; position: static; }
  .site-nav.is-open .nav-item + .nav-item { border-top: 1px solid rgba(255,255,255,0.15); }
  .site-nav.is-open .nav-item > a { justify-content: space-between; padding: 0.85rem 0; font-size: 1.15rem; color: #fff; }
  .site-nav.is-open .nav-item > a:hover { color: var(--orange-bright); }
  .site-nav.is-open .dropdown { display: none; position: static; opacity: 1; visibility: visible; transform: none; background: transparent; box-shadow: none; border-top: 0; min-width: 0; padding: 0 0 0.5rem 1rem; }
  .site-nav.is-open .has-dropdown.expanded > .dropdown { display: block; }
  .site-nav.is-open .has-dropdown.expanded > a .nav-caret { transform: rotate(180deg); }
  .site-nav.is-open .dropdown a { color: rgba(255,255,255,0.85); padding: 0.4rem 0; white-space: normal; }
  .site-nav.is-open .dropdown a:hover { background: transparent; color: #fff; }
}

/* Smallest screens: logo + hamburger on top, phone button centered below */
@media (max-width: 480px) {
  .menu-toggle { order: 1; }
  .nav-cta { order: 2; flex: 0 0 100%; max-width: max-content; margin: 0 auto 0.75rem; }
}

/* ============================================================
   Hero (full-bleed photo + checklist left, quote card right)
   ============================================================ */
/* ---------- HERO: 50/50 split (Gable layout) ----------
   Solid charcoal type panel left | full-bleed photo right.
   No overlay, no floating form card — the lead form lives in the
   .quote-bar band directly beneath the hero. */
.hero { position: relative; color: #fff; background: var(--navy); padding: 0; }
/* Upward gable triangle rising from the hero's base — full width, apex at
   center. Same charcoal as the type panel, so its left half blends in and
   you only SEE it against the photo half. Sits behind the corrugated edge.
   Scoped OFF .hero--form: over a full-width photo the triangle has no panel
   to blend into, and that variant needs ::before for the .bg-host scrim. */
.hero:not(.hero--form)::before {
  content: ""; position: absolute; left: 0; right: 0; bottom: 0; z-index: 2;
  height: clamp(2.5rem, 6vw, 5rem);
  background: var(--navy);
  clip-path: polygon(0 100%, 50% 0, 100% 100%);
  pointer-events: none;
}
/* Signature corrugated-metal edge — galvanized ribbing along the hero base + a barn-red line. */
.hero::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 12px; z-index: 3;
  background:
    linear-gradient(var(--accent-frame), var(--accent-frame)) bottom / 100% 3px no-repeat,
    repeating-linear-gradient(90deg, var(--metal-1) 0 7px, var(--metal-2) 7px 9px, var(--metal-3) 9px 14px);
  box-shadow: inset 0 2px 3px rgba(0,0,0,0.28);
}
/* reusable corrugated divider for other bands (e.g. banner) */
.metal-edge { position: relative; }
.metal-edge::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: 0; height: 11px; z-index: 3;
  background: repeating-linear-gradient(90deg, var(--metal-1) 0 7px, var(--metal-2) 7px 9px, var(--metal-3) 9px 14px);
  box-shadow: inset 0 2px 3px rgba(0,0,0,0.28);
}
.hero-split { display: grid; grid-template-columns: 1fr; }
@media (min-width: 900px) { .hero-split { grid-template-columns: 1.05fr 0.95fr; min-height: min(72vh, 680px); } }
.hero-panel {
  position: relative; z-index: 2;
  display: flex; flex-direction: column; justify-content: center;
  padding: clamp(2.5rem, 6vw, 4.25rem) clamp(1.25rem, 4vw, 3.5rem) clamp(3.25rem, 6vw, 4.5rem);
}
.hero-media { position: relative; min-height: 300px; }
.hero-media img { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: cover; }
.hero-kicker {
  font-family: var(--font-head); font-weight: 600; text-transform: uppercase;
  letter-spacing: 0.14em; font-size: 1.05rem; color: var(--teal-bright); margin: 0 0 0.75rem;
}
.hero-title { color: #fff; margin: 0 0 clamp(1.25rem, 2.5vw, 1.75rem); font-size: clamp(1.75rem, 2.7vw, 2.4rem); line-height: 1.06; }
.hero-checklist { list-style: none; margin: 0 0 1.75rem; padding: 0; display: grid; gap: 0.55rem 1.5rem; grid-template-columns: 1fr; }
@media (min-width: 560px) { .hero-checklist { grid-template-columns: 1fr 1fr; } }
.hero-checklist li { position: relative; padding-left: 30px; font-weight: 500; line-height: 1.4; }
.hero-checklist li::before {
  content: ""; position: absolute; left: 0; top: 0.05em; width: 20px; height: 20px;
  background-repeat: no-repeat; background-size: contain;
  background-image: var(--bullet-hero);
}
.hero-intro { color: rgba(255,255,255,0.9); margin-bottom: 1.75rem; }
.hero-title + .hero-intro { margin-bottom: 1em; }  /* tighter gap after the first hero paragraph */
.hero-cta-row { display: flex; flex-wrap: wrap; align-items: center; gap: 0.85rem; }

/* ---------- HERO--FORM: full-width photo, intro LEFT, quote card RIGHT ----------
   The sibling skins' hero shape in polebarn dress, for sites that want the lead
   form above the fold instead of in the .quote-bar band. Standard .bg-host +
   <img class="bg-img"> scrim (which is why the gable ::before is scoped off this
   variant above); the corrugated ::after edge is kept as the skin marker.
   Overrides .hero's padding:0 — same specificity, later in the file wins. */
.hero--form { padding: clamp(2.75rem, 6vw, 4.5rem) 0 clamp(3.5rem, 7vw, 5.5rem); }
.hero-grid { display: grid; gap: clamp(1.75rem, 4vw, 3rem); grid-template-columns: 1fr; }
@media (min-width: 900px) { .hero-grid { grid-template-columns: 1.05fr 0.95fr; align-items: center; } }
/* the split hero's h1 is sized for a narrow panel; over the full container it can run larger */
.hero--form .hero-title { font-size: clamp(1.85rem, 3.2vw, 2.75rem); }
.hero--form .hero-intro:last-of-type { margin-bottom: 1.5rem; }

/* ---------- Estimate / quote form card (kept for contact page + card-variant assemblies) ---------- */
.estimate-card { background: var(--navy-card); color: #fff; padding: clamp(1.5rem, 3vw, 2.25rem); border-radius: var(--radius); box-shadow: var(--shadow-lg); }
/* The hero--form treatment puts the quote form INSIDE the hero, where a separate
   card tone is a third dark for no gain — it reads as a panel on the hero rather
   than part of it. The standalone .quote-bar band under the split hero keeps
   --navy-card, since there it genuinely separates two stacked sections. */
.hero .estimate-card { background: var(--navy); }
.estimate-card .quote-mark { color: var(--orange-bright); margin-bottom: 0.25rem; }
.estimate-title { font-family: var(--font-head); font-weight: 700; text-transform: uppercase; font-size: clamp(1.7rem, 3vw, 2.2rem); color: #fff; margin: 0 0 1.25rem; letter-spacing: 0.01em; }
.estimate-head { display: flex; align-items: center; gap: 0.65rem; margin: 0 0 1.25rem; }
.estimate-head .quote-mark { margin: 0; display: inline-flex; }
.estimate-head .estimate-title { margin: 0; }
.estimate-form { display: grid; gap: 0.7rem; grid-template-columns: 1fr 1fr; }
.estimate-form > .full, .estimate-form textarea, .estimate-form select, .estimate-form button, .estimate-form .cf-turnstile { grid-column: 1 / -1; }
.estimate-form input, .estimate-form select, .estimate-form textarea {
  font: inherit; width: 100%; min-height: 48px; padding: 0.7rem 0.9rem;
  border: 0; border-radius: var(--radius); background: var(--oat); color: var(--color-text);
}
.estimate-form select { color: var(--select-ink); appearance: none; background-image: var(--select-caret); background-repeat: no-repeat; background-position: right 0.7rem center; padding-right: 2.2rem; }
.estimate-form textarea { min-height: 96px; resize: vertical; }
.estimate-form input:focus, .estimate-form select:focus, .estimate-form textarea:focus { outline: 3px solid var(--color-focus); outline-offset: 1px; }
.estimate-form button[type="submit"] {
  background: var(--btn-fill-dark); color: var(--btn-ink-dark); font: inherit; font-family: var(--font-head);
  font-weight: 700; font-size: 1.25rem; text-transform: uppercase; letter-spacing: 0.06em; padding: calc(0.85rem - 2px); border: 2px solid var(--btn-fill-dark);
  border-radius: var(--radius); cursor: pointer; min-height: 52px; display: inline-flex; align-items: center; justify-content: center; gap: 0.5rem;
  transition: background-color .15s ease, color .15s ease, border-color .15s ease;
}
.estimate-form button[type="submit"]:hover { background: transparent; color: var(--orange-bright); border-color: var(--orange-bright); }

/* Buttons on DARK surfaces (hero panel, .section-dark, the quote-bar / estimate
   card, feature-aside boxes). Same values as the light button unless a palette
   overrides the pair — see --btn-fill-dark. */
.section-dark .btn-call, .section-dark .btn-primary,
.hero .btn-call, .hero .btn-primary {
  background: var(--btn-fill-dark); color: var(--btn-ink-dark); border-color: var(--btn-fill-dark);
}

/* ---------- QUOTE-BAR: the lead form as a horizontal band under the hero ----------
   (Overrides live AFTER the base .estimate-form rules — same specificity, later wins.) */
.quote-bar { background: var(--navy-card); color: #fff; padding: clamp(1.75rem, 3.5vw, 2.75rem) 0; border-bottom: 4px solid var(--accent-frame); }
.quote-bar .estimate-head { margin-bottom: 1rem; }
.estimate-form--bar { grid-template-columns: repeat(4, 1fr); align-items: start; }
.estimate-form--bar > .full { grid-column: auto; }        /* name/address become normal row cells */
.estimate-form--bar textarea { grid-column: 1 / -1; min-height: 72px; }
.estimate-form--bar .cf-turnstile { grid-column: 1 / 3; }
.estimate-form--bar button[type="submit"] { grid-column: 3 / -1; align-self: stretch; }
@media (max-width: 880px) {
  .estimate-form--bar { grid-template-columns: 1fr 1fr; }
  .estimate-form--bar > .full, .estimate-form--bar .cf-turnstile, .estimate-form--bar button[type="submit"] { grid-column: 1 / -1; }
}

/* ============================================================
   Feature bands (navy + teal): icon + heading + text triplets
   ============================================================ */
.feature-band { background: var(--navy); color: #fff; padding: clamp(2.25rem, 4vw, 3rem) 0; }
.feature-band.band-teal { background: var(--teal); }
.feature-grid { display: grid; gap: clamp(1.5rem, 3vw, 2.5rem); grid-template-columns: 1fr; }
@media (min-width: 760px) { .feature-grid { grid-template-columns: repeat(3, 1fr); } }
.feature-item { display: grid; grid-template-columns: auto 1fr; gap: 0 1rem; align-items: start; }
.feature-item .feature-ico { grid-row: span 2; color: #fff; }
.feature-band.band-navy .feature-item .feature-ico { color: var(--teal-bright); }
.feature-item h3 { color: #fff; margin: 0 0 0.35rem; font-size: 1.4rem; }
.feature-item p { color: rgba(255,255,255,0.82); margin: 0; font-size: 0.95rem; line-height: 1.55; }

/* ============================================================
   Split content (About / Story): media + text + check badges
   ============================================================ */
.split { background: var(--color-bg); }
.split-alt { background: var(--color-bg-alt); }
.split-grid { display: grid; grid-template-columns: 1fr; gap: clamp(1.75rem, 4vw, 3.25rem); align-items: center; }
@media (min-width: 900px) { .split-grid { grid-template-columns: 1fr 1fr; } }
.split-grid.media-right .split-media { order: -1; }
@media (min-width: 900px) { .split-grid.media-right .split-media { order: 2; } }
.split-media img { width: 100%; aspect-ratio: 4 / 3; object-fit: cover; border-radius: var(--radius); box-shadow: var(--shadow-md); }
.split h2 { color: var(--color-heading); }
.badge-grid { list-style: none; margin: 1.5rem 0 1.75rem; padding: 0; display: grid; gap: 0.55rem 1.5rem; grid-template-columns: 1fr; }
@media (min-width: 520px) { .badge-grid { grid-template-columns: 1fr 1fr; } }
.badge-grid li { position: relative; padding-left: 28px; font-weight: 600; color: var(--navy); line-height: 1.4; }
.badge-grid li::before {
  content: ""; position: absolute; left: 0; top: 0.1em; width: 18px; height: 18px;
  background-repeat: no-repeat; background-size: contain;
  background-image: var(--bullet-badge);
}
.split-cta-row { display: flex; flex-wrap: wrap; gap: 0.85rem; align-items: center; }
/* optional offset keyline box behind the split's image — the same treatment
   the --framed / --long flex-media family wears. Frame hangs off the corner
   AWAY from the copy (bottom-right when the image sits right, bottom-left
   when it sits left), and the grid reserves that 14px so it never clips. */
.split-media--framed { position: relative; }
.split-media--framed::after {
  content: ""; position: absolute; inset: 14px -14px -14px 14px;
  border: 3px solid var(--keyline); border-radius: var(--radius); z-index: 0; pointer-events: none;
}
.split-media--framed img { position: relative; z-index: 1; }
.split-grid.media-right:has(> .split-media--framed) { padding: 0 14px 14px 0; }
.split-grid:not(.media-right) > .split-media--framed::after { inset: 14px 14px -14px -14px; }
.split-grid:not(.media-right):has(> .split-media--framed) { padding: 0 0 14px 14px; }
@media (max-width: 899px) {
  .split-media--framed::after { inset: 10px -8px -8px 10px; }
  .split-grid:not(.media-right) > .split-media--framed::after { inset: 10px 10px -8px -8px; }
}

/* ============================================================
   How it works strip (teal)
   ============================================================ */
.howitworks { background: var(--teal); color: #fff; padding: clamp(1.75rem, 3.5vw, 2.5rem) 0; }
.hiw-grid { display: grid; grid-template-columns: 1fr; gap: 1.25rem 2rem; align-items: center; text-align: center; }
@media (min-width: 760px) { .hiw-grid { grid-template-columns: auto repeat(3, 1fr); text-align: left; } }
.hiw-title { font-family: var(--font-head); font-weight: 700; text-transform: uppercase; font-size: 1.7rem; color: #fff; margin: 0; }
.hiw-step { display: inline-flex; align-items: center; gap: 0.6rem; justify-content: center; font-family: var(--font-head); font-weight: 700; text-transform: uppercase; letter-spacing: 0.02em; font-size: 1.25rem; color: #fff; }
@media (min-width: 760px) { .hiw-step { justify-content: flex-start; } }
.hiw-step svg { color: #fff; flex-shrink: 0; }
.hiw-step a { color: #fff; text-decoration: none; }
.hiw-step a:hover { text-decoration: underline; }

/* ============================================================
   Services grid (shared vocab: header + image + description)
   Dark section.
   ============================================================ */
.services-head { text-align: center; max-width: 64ch; margin: 0 auto 2.25rem; }
.services-head .section-label, .services-head h2 { text-align: center; }
.services-head .section-label { color: var(--orange-bright); }
.section-dark .services-head h2 { color: #fff; margin-bottom: 0.5rem; }
/* Mosaic rows: the FIRST TWO cards form a row of 2 (wider, taller images);
   every card after flows into rows of 3. Works for any card count. */
.services-grid { display: grid; gap: 1.25rem; grid-template-columns: 1fr; margin-top: 0.5rem; }
@media (min-width: 600px) {
  .services-grid { grid-template-columns: 1fr 1fr; }
}
@media (min-width: 940px) {
  .services-grid { grid-template-columns: repeat(6, 1fr); }
  .service-card { grid-column: span 2; }
  .service-card:nth-child(-n+2) { grid-column: span 3; }
}
.service-card {
  display: flex; flex-direction: column; background: var(--navy-2);
  border: 1px solid rgba(255,255,255,0.10); border-radius: var(--radius); overflow: hidden;
  transition: transform .12s ease, border-color .15s ease, box-shadow .15s ease;
}
.service-card:hover { transform: translateY(-3px); border-color: var(--teal-bright); box-shadow: 0 12px 28px rgba(0,0,0,0.35); }
.service-card-header {
  background: var(--teal); color: #fff; padding: 0.75rem 1.25rem; margin: 0; text-align: left;
  font-family: var(--font-head); font-size: 1.4rem; font-weight: 700; letter-spacing: 0.01em;
  text-transform: uppercase; line-height: 1.15;
  /* This header sits on --teal, the ONLY surface --accent-frame ever touched that
     is not the navy family. Requiring one accent to contrast against BOTH the
     near-black darks and a mid-dark secondary is what forced every palette's
     accent to a washed-out pastel. The rule belongs to this surface's own family. */
  box-shadow: inset 0 -3px 0 var(--on-teal-label);
}
.service-card-body { padding: 1.25rem; display: flex; flex-direction: column; flex: 1; gap: 0.9rem; }
.service-card-body img {
  width: calc(100% + 2.5rem); max-width: none; margin: -1.25rem -1.25rem 0;
  aspect-ratio: 16 / 9; object-fit: cover; border-radius: 0;
}
.service-card-body p { color: rgba(255,255,255,0.80); margin: 0; font-size: 0.95rem; }
/* first-row (of 2) cards: bigger type; their wider span makes the 16/9 images taller naturally */
@media (min-width: 940px) {
  .service-card:nth-child(-n+2) .service-card-header { font-size: clamp(1.5rem, 2vw, 1.9rem); }
  .service-card:nth-child(-n+2) .service-card-body p { font-size: 1.05rem; }
}

/* ============================================================
   Long-form banner sections (installation / repair / demolition / decorative)
   ============================================================ */
.lf-banner { color: #fff; padding: clamp(2.5rem, 5vw, 4rem) 0; }
.lf-banner.b-navy { background: var(--navy); }
.lf-banner.b-teal { background: var(--teal); }
.lf-banner-grid { display: grid; grid-template-columns: 1fr; gap: clamp(1.75rem, 4vw, 3rem); align-items: center; }
@media (min-width: 900px) { .lf-banner-grid { grid-template-columns: 1.05fr 0.95fr; } }
.lf-banner-grid.media-right .lf-media { order: -1; }
@media (min-width: 900px) { .lf-banner-grid.media-right .lf-media { order: 2; } }
.lf-media img { width: 100%; aspect-ratio: 4 / 3; object-fit: cover; border-radius: var(--radius); box-shadow: var(--shadow-lg); }
.lf-banner h2 { color: #fff; }
.lf-banner p { color: rgba(255,255,255,0.85); }
.lf-sub-h { font-family: var(--font-head); font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; color: #fff; font-size: 1.2rem; margin: 1.5rem 0 0.75rem; }
.lf-body { background: var(--color-bg); }
.lf-body.body-alt { background: var(--color-bg-alt); }
.lf-body h2 { color: var(--color-heading); }
.lf-body h3 { color: var(--teal); margin-top: 1.75rem; }
.lf-prose { max-width: 82ch; }
.lf-prose.center { margin: 0 auto; }

/* ============================================================
   Check / feature lists
   ============================================================ */
.feature-list { list-style: none; margin: 0.75rem 0 0; padding: 0; font-size: 0.97rem; }
.feature-list li { position: relative; padding-left: 28px; margin-bottom: 0.65rem; line-height: 1.5; }
.feature-list li strong { color: var(--color-heading); }
.feature-list li::before {
  content: ""; position: absolute; left: 0; top: 0.2em; width: 16px; height: 16px;
  background-repeat: no-repeat; background-size: contain;
  background-image: var(--tick-timber);
}
.lf-banner .feature-list li, .section-dark .feature-list li { color: rgba(255,255,255,0.9); }
.lf-banner .feature-list li strong, .section-dark .feature-list li strong { color: #fff; }
.lf-banner .feature-list li::before, .section-dark .feature-list li::before { background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24'><path d='M20 6L9 17l-5-5' fill='none' stroke='%23ffffff' stroke-width='3' stroke-linecap='round' stroke-linejoin='round'/></svg>"); }
.feature-list-2col, .feature-list-3col { display: grid; gap: 0 1.75rem; grid-template-columns: 1fr; }
@media (min-width: 600px) { .feature-list-2col, .feature-list-3col { grid-template-columns: 1fr 1fr; } }
@media (min-width: 1000px) { .feature-list-3col { grid-template-columns: 1fr 1fr 1fr; } }
.inline-cta { margin-top: 1.5rem; display: inline-flex; }

/* ============================================================
   FAQ (navy panel with accordion)
   ============================================================ */
/* FAQ: LIGHT two-column — intro column (sticky on desktop) left,
   accordion of white cards right, on the oat section bg. */
.faq { background: var(--color-bg-alt); }
.faq-grid { display: grid; grid-template-columns: 1fr; gap: clamp(1.75rem, 4vw, 3.5rem); align-items: start; }
@media (min-width: 880px) {
  .faq-grid { grid-template-columns: 0.85fr 1.4fr; }
  .faq-intro { position: sticky; top: calc(var(--header-h) + 1.5rem); }
}
.faq-intro h2 { margin-bottom: 0.75rem; }
.faq-intro p { color: var(--color-text); max-width: 45ch; }
.faq-intro .btn { margin-top: 0.75rem; }
.faq-list { display: flex; flex-direction: column; gap: 0.75rem; }
.faq-item { background: #fff; border: 1px solid var(--color-border); border-left: 4px solid var(--card-accent); border-radius: var(--radius); box-shadow: var(--shadow-sm); }
.faq-item > summary { list-style: none; cursor: pointer; padding: 1rem 1.15rem; font-family: var(--font-head); font-weight: 700; text-transform: uppercase; letter-spacing: 0.01em; color: var(--color-heading); font-size: 1.2rem; display: flex; align-items: center; justify-content: space-between; gap: 1rem; }
.faq-item > summary::-webkit-details-marker { display: none; }
.faq-item > summary::after { content: "+"; font-size: 1.7rem; color: var(--orange); flex-shrink: 0; line-height: 1; }
.faq-item[open] > summary::after { content: "\2212"; }
.faq-item > .faq-body { padding: 0 1.15rem 1.1rem; color: var(--color-text); }
.faq-item > .faq-body ul { margin: 0.5rem 0; padding-left: 1.1rem; }
.faq-item > .faq-body a { color: var(--teal); }

/* ============================================================
   Final CTA (photo bg + centered quote card)
   ============================================================ */
.final-cta { color: #fff; padding: clamp(3rem, 6vw, 5rem) 0; }
.final-cta .estimate-card { max-width: 560px; margin: 0 auto; }

/* ============================================================
   Footer (navy + wood strip)
   ============================================================ */
.site-footer { background: var(--navy); color: var(--on-dark-body); padding: 3.25rem 0 1.5rem; border-top: 4px solid var(--accent-frame); }
.footer-grid { display: grid; gap: 2rem; grid-template-columns: 1fr; align-items: start; }
@media (min-width: 700px) { .footer-grid { grid-template-columns: 1fr 1fr; } }
@media (min-width: 1000px) { .footer-grid { grid-template-columns: 1.05fr 1.5fr 1.35fr 1.15fr; } }
.footer-brand-logo { display: inline-block; text-decoration: none; }
.footer-brand-logo img { width: 100%; height: auto; display: block; }
/* text wordmark fallback in the footer (dark bg): knockout white + brick accent */
.footer-brand-logo .brand-text { color: #fff; font-size: 1.9rem; }
.footer-brand-logo .brand-text b { color: var(--orange-bright); }
/* --boxed: for dark/color logos that need a white plate (no knockout version available) */
.footer-brand-logo--boxed { background: #fff; padding: 0.9rem 1rem; border-radius: var(--radius); display: inline-block; }
.footer-brand-logo--boxed img { height: 70px; width: auto; }
.footer-col h4 { color: #fff; margin: 0 0 1rem; padding-bottom: 0.5rem; position: relative; font-size: 1.3rem; }
.footer-col h4::after { content: ""; position: absolute; left: 0; bottom: 0; width: 38px; height: 3px; background: var(--accent-frame); }
.footer-col ul { list-style: none; padding: 0; margin: 0; }
.footer-col li { margin-bottom: 0.6rem; }
.footer-links a { color: var(--on-dark-link); text-decoration: none; display: inline-flex; align-items: center; gap: 0.6rem; }
.footer-links a:hover { color: #fff; }
.footer-links svg { color: var(--orange-bright); flex-shrink: 0; }
.footer-col ul.footer-col-links { margin-top: 2.25rem; }
.footer-list-plain { list-style: none; padding: 0; margin: 0; }
.footer-list-plain li { color: var(--on-dark-body); margin-bottom: 0.4rem; font-size: 0.88rem; line-height: 1.35; }
.footer-areas-list { columns: 2; column-gap: 1.5rem; }
.footer-areas-list li { break-inside: avoid; }
.footer-contact-list li { display: flex; align-items: flex-start; gap: 0.6rem; line-height: 1.5; }
.footer-contact-list a, .footer-contact-list span { color: var(--on-dark-link); text-decoration: none; display: inline-flex; align-items: flex-start; gap: 0.6rem; }
.footer-contact-list a:hover { color: #fff; }
.footer-contact-list svg { color: var(--orange-bright); flex-shrink: 0; margin-top: 0.18em; }
.footer-phone { font-family: var(--font-head); font-weight: 700; font-size: 1.7rem; color: var(--orange-bright); text-decoration: none; }
.footer-phone:hover { color: #fff; }
.legal { margin-top: 2.5rem; padding-top: 1.25rem; border-top: 1px solid rgba(255,255,255,0.1); font-size: 0.85rem; color: var(--on-dark-faint); display: flex; flex-wrap: wrap; gap: 0.75rem 1.5rem; justify-content: space-between; }
.legal a { color: var(--on-dark-body); text-decoration: none; margin-right: 1rem; }
.legal a:hover { color: #fff; }

/* ============================================================
   Contact / utility forms (contact.html etc.)
   ============================================================ */
.page-narrow { max-width: 820px; margin: 0 auto; }
.page-hero { background: var(--navy); color: #fff; padding: clamp(2.5rem, 5vw, 3.75rem) 0; border-bottom: 4px solid var(--accent-frame); }
.page-hero h1 { color: #fff; }
.page-hero p { color: rgba(255,255,255,0.85); margin: 0; }
.breadcrumb { font-size: 0.9rem; color: rgba(255,255,255,0.7); margin-bottom: 0.5rem; }
.breadcrumb a { color: rgba(255,255,255,0.85); text-decoration: none; }
.breadcrumb a:hover { color: #fff; }
/* NOTE: the label/fieldset "utility-form" styles (.form-card / .form-grid /
   .field / .req / .help / .error / .form-footnote) were removed — this skin's
   contact page uses the .estimate-card + .estimate-form pattern, so they were
   dead in every page. They were inherited from a sibling skin. If a utility
   form is ever added here, style it as .estimate-form rather than reviving
   them. The --color-error / --focus-ring tokens are deliberately KEPT (see
   :root) — they are part of the 4-palette token contract and are the values a
   form-validation state would use. */
.contact-info { list-style: none; margin: 1.5rem 0 0; padding: 0; display: grid; gap: 0.85rem; }
.contact-info li { display: flex; align-items: flex-start; gap: 0.7rem; line-height: 1.4; }
.contact-info svg { color: var(--teal); flex-shrink: 0; margin-top: 0.12em; }
.contact-info a { color: var(--color-text); text-decoration: none; }
.contact-info a:hover { color: var(--teal); }
.nap address { font-style: normal; line-height: 1.7; }
.prose h2 { margin-top: 2rem; }
.prose h3 { margin-top: 1.5rem; color: var(--teal); }

/* ---------- Utility page simple nav ---------- */
.site-nav.simple { gap: 2rem; }
.site-nav.simple a { color: var(--navy); font-family: var(--font-head); font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; text-decoration: none; font-size: 1.15rem; }
.site-nav.simple a:hover { color: var(--teal); }
@media (max-width: 900px) { .site-nav.simple { display: none; } }

/* ============================================================
   SHARED BLOCK VOCABULARY (Gable / rugged-warm skin)
   The global blocks the assembler fills. Extras (feature-band,
   lf-banner) keep their own sections above.
   ============================================================ */

/* ---------- Flex-media (workhorse: overlapping offset card) ----------
   Desktop: the image bleeds wide on its side and the TEXT sits in an
   offset card that overlaps it by one grid column. Default = card left /
   image right; --reverse mirrors. Mobile stacks normally. */
/* The light-surface backgrounds of the flex-media family are declared AFTER
   .section-dark at the same specificity, so a plain `.flex-media.section-dark`
   would silently render on the light bg with dark headings. Every dark variant
   in the palette also carries .bg-host, whose ::before paints over it, which is
   why it never showed — but an image-less dark flex-media (e.g. --long-center
   with no photo) composites its translucent panel over white. :not(.section-dark)
   makes the dark modifier win without changing relative order inside the family. */
.flex-media:not(.section-dark) { background: var(--color-bg); }
.flex-media--reverse:not(.section-dark), .flex-media--long-reverse:not(.section-dark) { background: var(--color-bg-alt); }
.flex-media h2, .flex-media--long h2, .flex-media--long-reverse h2 { color: var(--color-heading); }
/* barn-red rule spans the FULL block width — above both the text card and
   the image; ONE box-shadow wraps the whole card+image unit (not per column) */
/* NOTE — decorative rules on LIGHT surfaces follow --orange-fill so they match
   the button colour in the same section. In blaze that is #F26A1B, which sits at
   3.06:1 on the white page and 2.77:1 on the band. That is deliberate and is NOT a
   contrast failure: WCAG 1.4.11 covers UI components and meaningful graphics, and
   these are purely decorative 4px keylines carrying no information. The luminance
   ratio also understates a saturated orange's visibility against an off-white —
   the alternative (the darker --orange #C4450F) is crisper but renders a visibly
   different orange directly beneath a --orange-fill button, which is the exact
   mismatch this whole pass set out to remove. */
.flex-media-grid { display: grid; gap: clamp(1.5rem, 3vw, 2rem); grid-template-columns: 1fr; align-items: center; border-top: 4px solid var(--orange-fill); box-shadow: var(--shadow-md); }
.flex-media-text {
  /* The offset card must read against its own section. The shadow lives on
     .flex-media-grid, not here, so when --oat matches the section background (a
     palette whose card surface is white on a white page) the card had no edge at
     all. A hairline restores it without needing a tinted fill. */
  border: 1px solid var(--color-border);
  background: var(--oat);
  border-radius: var(--radius);
  padding: clamp(1.5rem, 3vw, 2.5rem);
}
.flex-media--reverse .flex-media-text { background: #fff; }  /* card flips to white on the oat section bg */
.flex-media-text > :first-child { margin-top: 0; }
.flex-media-figure { margin: 0; }   /* no per-column shadow — the unit shadow lives on .flex-media-grid */
.flex-media-figure img { width: 100%; border-radius: var(--radius); aspect-ratio: 4 / 3; object-fit: cover; }
@media (min-width: 880px) {
  .flex-media-grid { grid-template-columns: repeat(12, 1fr); align-items: stretch; }
  .flex-media-text { grid-column: 1 / 7; grid-row: 1; position: relative; z-index: 2; }
  /* the TEXT card drives the row height; the image absolute-fills its
     figure and crops (object-fit) to always match the text's height */
  .flex-media-figure { grid-column: 6 / -1; grid-row: 1; position: relative; min-height: 300px; }
  .flex-media-figure img {
    position: absolute; inset: 0; width: 100%; height: 100%;
    object-fit: cover; aspect-ratio: auto;
  }
  /* --reverse mirrors the overlap */
  .flex-media--reverse .flex-media-text { grid-column: 7 / -1; }
  .flex-media--reverse .flex-media-figure { grid-column: 1 / 8; }
}
.flex-media-cta-row { display: flex; flex-wrap: wrap; gap: 0.85rem; margin-top: 2rem; align-items: center; }

/* --long / --long-reverse: two columns of long copy, image cornered.
   --long = image at TOP of the first column; --long-reverse = image at
   the BOTTOM of the first column (columns are equal height). Images get
   an offset timber keyline frame. */
.flex-media-long-grid { display: grid; grid-template-columns: 1fr; gap: clamp(1.5rem, 3vw, 2.5rem); align-items: stretch; margin-top: 1.5rem; }
@media (min-width: 768px) { .flex-media-long-grid { grid-template-columns: 1fr 1fr; } }
.flex-media-long-col { display: flex; flex-direction: column; }
.flex-media-long-col > :first-child { margin-top: 0; }
.flex-media-long-col h3 { margin-top: 1.5rem; }
.flex-media-long-figure { margin: 0; position: relative; }
/* offset keyline frame — peeks BOTTOM-RIGHT on --long */
.flex-media-long-figure::after {
  content: ""; position: absolute; inset: 14px -14px -14px 14px;
  border: 3px solid var(--keyline); border-radius: var(--radius); z-index: 0; pointer-events: none;
}
/* --long-reverse: same 14px offset, hangs off the BOTTOM-LEFT */
.flex-media--long-reverse .flex-media-long-figure::after { inset: 14px 14px -14px -14px; }
/* the bottom-cornered figure carries 1.25rem padding-top (its gap from the
   text above) — offset the frame from the IMAGE, not the padded figure box */
.flex-media--long-reverse .flex-media-long-figure:last-child::after { top: calc(1.25rem + 14px); }
.flex-media-long-figure img { position: relative; z-index: 1; width: 100%; border-radius: var(--radius); aspect-ratio: 4 / 3; object-fit: cover; box-shadow: var(--shadow-md); }
.flex-media-long-col > .flex-media-long-figure:first-child { margin-bottom: 1.75rem; }
/* ---- column balance: the IMAGE is the shock absorber ----
   Uneven columns are the #1 defect in this block, because a 4/3 image is a
   fixed ~360px slab and the copy split has to be guessed against it. Instead,
   let the figure GROW to swallow whatever height the other column dictates and
   crop via object-fit — the same mechanism the short .flex-media already uses
   ("the TEXT drives the row height, the image matches it"). Authoring rule
   collapses to: put LESS copy in the image column than in the other one.
   (Residual case: if the image column's own text already exceeds the other
   column, the other one still runs ragged — no CSS can fix that, move copy.) */
@media (min-width: 768px) {
  /* flex-basis 0 is the load-bearing part: the figure contributes only its
     min-height to the column's natural height, so the image column can never
     be the one that inflates the grid row. The row is then set by the copy,
     and the figure grows into whatever is left. (flex-basis auto would let a
     4/3 image push the row taller than the other column — which is exactly
     how this block used to end up ragged.) */
  /* 200px floor, not 240 — every extra px of floor is a px the figure cannot
     give back when the image column's own copy runs long. Below ~200 a
     full-width figure letterboxes badly, so this is the practical limit. */
  .flex-media-long-figure { flex: 1 1 0; min-height: 200px; }
  /* the image is taken out of flow entirely so it adds NO intrinsic height —
     same proven mechanism as the short .flex-media figure */
  .flex-media-long-figure img { position: absolute; inset: 0; width: 100%; height: 100%; aspect-ratio: auto; }
  /* the bottom-anchored figure fills the slack itself now, so drop the auto
     margin that used to push it down past a gap of whitespace */
  .flex-media-long-col > .flex-media-long-figure:last-child { margin-top: 0; }
}
.flex-media-long-col > .flex-media-long-figure:last-child { margin-top: auto; padding-top: 1.25rem; }
@media (max-width: 767px) {
  .flex-media-long-figure::after { inset: 10px -8px -8px 10px; }
  .flex-media--long-reverse .flex-media-long-figure::after { inset: 10px 10px -8px -8px; }
  .flex-media--long-reverse .flex-media-long-figure:last-child::after { top: calc(1.25rem + 10px); }
}

/* --overlay / --overlay-right: FULL-BLEED bg photo; the text lives on a
   TRANSLUCENT dark panel covering one half (photo fully visible on the
   other). Copy length is content-driven — works as a short OR long block.
   Section also carries .bg-host + .section-dark (white text).
   Default = panel LEFT; add --overlay-right for panel RIGHT. */
.flex-media--overlay { padding: 0; }
.flex-media--overlay.bg-host::before { background: var(--overlay-scrim); } /* light scrim only */
.flex-media--overlay .overlay-half {
  --panel-pad: clamp(1.25rem, 4vw, 3rem);
  position: relative; z-index: 2;
  background: var(--overlay-panel); border-top: 4px solid var(--accent-frame);  /* translucent — photo reads through */
  padding: clamp(2.75rem, 6vw, 4.5rem) var(--panel-pad);
}
.flex-media--overlay h2 { color: #fff; }
@media (min-width: 880px) {
  .flex-media--overlay .overlay-half {
    width: 50%; min-height: 480px; border-top: none; border-right: 4px solid var(--accent-frame);
    display: flex; flex-direction: column; justify-content: center;
  }
  /* align the panel's text with the global container's edge. The panel is
     exactly HALF the layout width, so 100% − max-w/2 is the gutter+padding
     distance — %-based, immune to the 100vw scrollbar error. */
  .flex-media--overlay .overlay-half-inner {
    max-width: 34rem;
    margin-left: max(0px, calc(100% + var(--panel-pad) + 4px - var(--max-w) / 2 + 1.25rem));
  }
  /* --overlay-right: mirror — panel covers the RIGHT half */
  .flex-media--overlay-right .overlay-half {
    margin-left: 50%; border-right: none; border-left: 4px solid var(--accent-frame);
  }
  .flex-media--overlay-right .overlay-half-inner {
    margin-left: auto; margin-right: max(0px, calc(100% + var(--panel-pad) + 4px - var(--max-w) / 2 + 1.25rem));
  }
}

/* --long-center: FULL-BLEED bg photo; the overlay is a CENTERED content
   panel holding the heading + the 2-col long grid.
   Section also carries .bg-host + .section-dark (white text). */
.flex-media--long-center { padding: 0; }  /* panel runs flush to the section's top + bottom */
.flex-media--long-center.bg-host::before { background: var(--overlay-scrim-strong); } /* light scrim only */
.flex-media--long-center h2 { color: #fff; }
.flex-media--long-center .overlay-center {
  /* SYMMETRIC rule: this panel is centered, so a lone border-right read as a
     mistake once the palettes gave --accent-frame real contrast. */
  background: var(--overlay-panel); border-inline: 4px solid var(--accent-frame);  /* translucent — photo reads through */
  padding: clamp(1.75rem, 4vw, 3rem);
}

/* ============================================================
   FLEX-MEDIA MATRIX — 4 families x short/long, mirrored.
   Each family is a distinct GEOMETRY; --long/short is how much
   copy it carries. Long copy may run as TWO columns (the default
   .flex-media-long-grid) or ONE taller column (add --single, or
   just put a single .flex-media-long-col in — :has() collapses it).

   | family                          | short              | long               |
   |---------------------------------|--------------------|--------------------|
   | matched-height image beside text| .flex-media        | --stack            |
   | image w/ offset keyline box     | --framed           | --long             |
   | side overlay on full-bleed photo| --overlay          | --overlay-long     |
   | center overlay on full-bleed    | --center           | --long-center      |
   ...each + its mirror (--reverse / --overlay-right; --center has no sides).
   ============================================================ */

/* long copy as ONE taller column instead of two */
.flex-media-long-grid--single { grid-template-columns: 1fr !important; }
.flex-media-long-grid:has(> .flex-media-long-col:only-child) { grid-template-columns: 1fr; }

/* ---------- --stack: matched-height family, LONG form ----------
   Same overlapping-card geometry as .flex-media, but the text card
   takes 7 of 12 columns (long copy needs the measure) and the figure
   holds TWO images stacked, split 50/50 down the column height with a
   barn-red rule between them. The TEXT still drives the row height;
   both images crop to fill their half. Mirror = --stack-reverse. */
.flex-media--stack:not(.section-dark) { background: var(--color-bg); }
.flex-media--stack-reverse:not(.section-dark) { background: var(--color-bg-alt); }
.flex-media--stack:not(.section-dark) h2, .flex-media--stack-reverse:not(.section-dark) h2 { color: var(--color-heading); }
.flex-media--stack-reverse .flex-media-text { background: #fff; }
/* grid rows (not flex) — 1fr/1fr splits the height deterministically;
   flex-basis sizing fights the images' intrinsic aspect ratios. */
.flex-media-figure--stack { display: grid; grid-template-rows: auto auto; gap: 0; min-height: 300px; }
.flex-media-figure--stack img {
  width: 100%; height: auto; min-height: 0;
  object-fit: cover; border-radius: var(--radius); aspect-ratio: 4 / 3;
}
.flex-media-figure--stack img + img { border-top: 4px solid var(--accent-frame); }
@media (min-width: 880px) {
  .flex-media--stack .flex-media-text, .flex-media--stack-reverse .flex-media-text { grid-column: 1 / 8; }
  .flex-media--stack .flex-media-figure, .flex-media--stack-reverse .flex-media-figure { grid-column: 7 / -1; }
  .flex-media--stack-reverse .flex-media-text { grid-column: 6 / -1; }
  .flex-media--stack-reverse .flex-media-figure { grid-column: 1 / 7; }
  /* The TEXT must drive the row height, so the images cannot contribute any
     intrinsic height — same absolute-fill trick the base single-image rule
     uses, just split into halves. (Leaving them in flow made the images'
     own height set the row and left the text card with dead space.) */
  .flex-media-figure--stack { min-height: 0; display: block; }
  .flex-media-figure--stack img {
    position: absolute; left: 0; right: 0; width: 100%; height: 50%;
    aspect-ratio: auto; object-fit: cover; box-sizing: border-box;
  }
  .flex-media-figure--stack img:first-child { top: 0; }
  .flex-media-figure--stack img:last-child  { top: 50%; }
  .flex-media--stack .flex-media-figure, .flex-media--stack-reverse .flex-media-figure { position: relative; }
}

/* the text card is 8 of 12 cols — only split the copy once that's genuinely wide */
@media (max-width: 1023px) {
  .flex-media--stack .flex-media-long-grid, .flex-media--stack-reverse .flex-media-long-grid { grid-template-columns: 1fr; }
}

/* ---------- --framed: keyline-box family, SHORT form ----------
   Plain two-column block (no overlapping card): text one side, a single
   image the other wearing the offset timber keyline frame that --long
   uses. The frame hangs 14px past the image, so the grid reserves that
   room. Mirror = --framed-reverse. */
.flex-media--framed:not(.section-dark) { background: var(--color-bg); }
.flex-media--framed-reverse:not(.section-dark) { background: var(--color-bg-alt); }
.flex-media--framed:not(.section-dark) h2, .flex-media--framed-reverse:not(.section-dark) h2 { color: var(--color-heading); }
/* plain copy column — no oat card, unlike .flex-media-text */
.flex-media-text-plain > :first-child { margin-top: 0; }
.flex-media-text-plain > :last-child { margin-bottom: 0; }
.flex-media-framed-grid { display: grid; grid-template-columns: 1fr; gap: clamp(1.75rem, 4vw, 3rem); align-items: center; }
@media (min-width: 880px) {
  .flex-media-framed-grid { grid-template-columns: 1fr 1fr; }
  .flex-media--framed-reverse .flex-media-framed-grid > .flex-media-long-figure { order: -1; }
}
/* room for the frame's 14px bottom-right (bottom-left when mirrored) overhang */
.flex-media--framed .flex-media-framed-grid { padding: 0 14px 14px 0; }
.flex-media--framed-reverse .flex-media-framed-grid { padding: 0 0 14px 14px; }
.flex-media--framed-reverse .flex-media-long-figure::after { inset: 14px 14px -14px -14px; }
@media (max-width: 879px) {
  .flex-media--framed-reverse .flex-media-long-figure::after { inset: 10px 10px -8px -8px; }
}

/* ---------- --overlay-long: side-overlay family, LONG form ----------
   Same full-bleed photo + translucent side panel as --overlay, but the
   panel widens (50% -> 62%) so long copy gets a workable measure, and it
   carries the 2-col long grid. Compose with --overlay-right to mirror. */
/* The panel stays EXACTLY half — it must never cross the midline, so the
   photo always keeps a clean, full half of the section. That caps the copy
   measure: the panel's right edge is the midpoint and the copy starts at the
   global container's left gutter, so the content column is always
   (--max-w / 2 − panel padding) ≈ 550px no matter how wide the viewport gets.
   Two columns of ~250px in that space are unreadable, so this family's long
   form is ALWAYS a single taller column — width inherits from --overlay and
   the long grid is forced to 1fr at every breakpoint. */
.flex-media--overlay-long .flex-media-long-grid { grid-template-columns: 1fr; }
.flex-media--overlay-long .flex-media-long-col h3 { color: #fff; }

/* ---------- --center: center-overlay family, SHORT form ----------
   The --long-center panel, sized for short copy: the section keeps its
   normal vertical padding (panel does NOT run flush to the edges) and the
   panel is a narrower centered column. No mirror — it has no sides. */
.flex-media--center.bg-host::before { background: var(--overlay-scrim-strong); }
.flex-media--center h2 { color: #fff; }
.flex-media--center .overlay-center {
  /* SYMMETRIC rule — see the --long-center note above. */
  background: var(--overlay-panel); border-inline: 4px solid var(--accent-frame);
  padding: clamp(1.75rem, 4vw, 3rem);
  max-width: 46rem; margin-inline: auto;
}

/* ---------- snow-list (check-bullet feature list) ---------- */
.snow-list { list-style: none; margin: 1.25rem 0 0; padding: 0; font-size: 0.97rem; }
.snow-list li { position: relative; padding-left: 30px; margin-bottom: 0.7rem; line-height: 1.5; color: var(--color-text); }
.snow-list li strong { color: var(--color-heading); }
.snow-list li::before {
  content: ""; position: absolute; left: 0; top: 0.15em; width: 20px; height: 20px;
  background-repeat: no-repeat; background-size: contain;
  background-image: var(--bullet-snow);
}
.flex-media .snow-list { display: grid; grid-template-columns: 1fr; gap: 0.4rem 1.5rem; }
@media (min-width: 560px) { .flex-media .snow-list { grid-template-columns: 1fr 1fr; } }
.snow-list--single { grid-template-columns: 1fr !important; }
.section-dark .snow-list li, .spotlight .snow-list li { color: rgba(255,255,255,0.9); }
.section-dark .snow-list li strong, .spotlight .snow-list li strong { color: #fff; }

/* ---------- subhead (h3 lead-in inside text blocks) ---------- */
.subhead { font-family: var(--font-head); font-weight: 700; text-transform: uppercase; letter-spacing: 0.03em; color: var(--teal); font-size: 1.2rem; margin: 1.5rem 0 0.5rem; }
.section-dark .subhead, .feature-aside .subhead { color: var(--teal-bright); }

/* ---------- Feature-aside (dark text column + nav aside boxes) ---------- */
.feature-aside-grid { display: grid; gap: clamp(1.5rem, 3vw, 2.5rem); grid-template-columns: 1fr; align-items: center; }
@media (min-width: 960px) { .feature-aside-grid { grid-template-columns: 1.5fr 1fr; } }
.feature-aside-side { display: flex; flex-direction: column; gap: 1rem; justify-content: center; }
.feature-aside-box { background: var(--wash-accent); border: 1px solid var(--teal-bright); padding: 1.75rem; border-radius: var(--radius); text-align: center; }
.feature-aside-box-title { color: #fff; margin: 0 0 1rem; font-family: var(--font-head); font-size: clamp(1.3rem, 2vw, 1.6rem); font-weight: 700; text-transform: uppercase; line-height: 1.05; }
.feature-aside-box .btn { width: 100%; background: var(--btn-fill-dark); color: var(--btn-ink-dark); border-color: var(--btn-fill-dark); }
.feature-aside-box .btn:hover { background: transparent; color: var(--btn-fill-dark); border-color: var(--btn-fill-dark); }

/* ---------- Spotlight (service areas + city narrative) ---------- */
.spotlight { color: #fff; }
.spotlight .container { display: grid; grid-template-columns: 1fr; gap: clamp(1.5rem, 4vw, 3rem); align-items: start; }
@media (min-width: 880px) {
  .spotlight .container { grid-template-columns: 1fr 1.3fr; }
  /* --reverse: narrative in the WIDE left column, areas chips narrow right */
  .spotlight--reverse .container { grid-template-columns: 1.3fr 1fr; }
}
.spotlight h2 { color: #fff; }
.spotlight p { color: rgba(255,255,255,0.85); }
.spotlight-side-title { font-family: var(--font-head); font-size: clamp(1.6rem, 3.5vw, 2.2rem); font-weight: 700; text-transform: uppercase; line-height: 1.05; color: #fff; margin: 0 0 1rem; }
/* areas render as stamped TAG CHIPS (not a bulleted list) */
.spotlight-areas { display: flex; flex-wrap: wrap; gap: 0.6rem; margin-top: 0; font-size: 0.95rem; }
.spotlight-areas li {
  padding: 0.4rem 0.9rem; margin: 0; line-height: 1.4;
  background: rgba(0,0,0,0.35); border: 1px solid rgba(255,255,255,0.30);
  border-left: 3px solid var(--accent-frame); border-radius: var(--radius);
  color: #fff; font-weight: 600;
}
.spotlight-areas li::before { display: none; }
.spotlight--light .spotlight-areas li {
  background: var(--oat); border-color: var(--color-border);
  border-left-color: var(--orange-fill); color: var(--color-heading);
}
.spotlight--light { color: var(--color-text); background: var(--color-bg); }
.spotlight--light h2 { color: var(--color-heading); }
.spotlight--light .spotlight-side-title { color: var(--teal); }
.spotlight--light p, .spotlight--light .snow-list li { color: var(--color-text); }
.spotlight--light .snow-list li strong { color: var(--color-heading); }

/* ---------- Steps (vertical timeline on a galvanized post line) ----------
   Markup per step: <li><span class="step-num">N</span> <div class="process-step-body">
   h3 + p</div> <img|.process-step-icon></li>. Handles any step count. */
.steps h2 { color: #fff; }
.process-intro { max-width: 70ch; margin: 0 auto 2.5rem; text-align: center; color: rgba(255,255,255,0.85); }
.process-grid {
  position: relative; display: flex; flex-direction: column;
  gap: clamp(2rem, 4vw, 3rem); max-width: 820px; margin: 0 auto; padding: 0; list-style: none;
}
/* the "post": a ribbed galvanized line running down the number column */
.process-grid::before {
  content: ""; position: absolute; left: 26px; top: 10px; bottom: 10px; width: 4px;
  background: repeating-linear-gradient(180deg, var(--metal-1) 0 10px, var(--metal-2) 10px 14px);
  border-radius: var(--radius);
}
.process-step { display: grid; grid-template-columns: 56px 1fr auto; gap: 1.1rem 1.4rem; align-items: start; position: relative; }
.process-step .step-num {
  grid-column: 1; grid-row: 1 / span 2; position: relative; z-index: 1;
  width: 56px; height: 56px; display: flex; align-items: center; justify-content: center;
  background: var(--orange-fill); color: var(--btn-ink); font-family: var(--font-head); font-size: 1.7rem;
  font-weight: 700; line-height: 1; border-radius: var(--radius);
  box-shadow: 0 0 0 6px var(--navy);
}
.process-step-body { grid-column: 2; }
.process-step-body > :first-child { margin-top: 0; }
.process-step > img, .process-step > .process-step-icon {
  grid-column: 3; grid-row: 1 / span 2; width: 150px; height: 104px;
  border-radius: var(--radius); object-fit: cover; margin: 0;
  display: flex; align-items: center; justify-content: center; flex-shrink: 0;
}
.process-step > .process-step-icon { background: var(--teal); color: #fff; }
.process-step h3 { color: #fff; margin-bottom: 0.4rem; }
.process-step p { color: rgba(255,255,255,0.80); font-size: 0.95rem; margin: 0; }
/* small screens: drop the side thumb below the text, keep the post line */
@media (max-width: 640px) {
  .process-step { grid-template-columns: 48px 1fr; }
  .process-grid::before { left: 22px; }
  .process-step .step-num { width: 48px; height: 48px; font-size: 1.4rem; grid-row: 1; }
  .process-step > img, .process-step > .process-step-icon { grid-column: 2; grid-row: 3; width: 100%; max-width: 320px; height: 140px; }
}
/* The closing box of the steps block. Was a 4%-white wash, which is barely visible;
   a real palette tone reads as a deliberate panel on the dark section. */
.mini-cta { margin-top: 3rem; text-align: center; padding: 1.75rem; background: var(--navy-card); border-radius: var(--radius); }
.mini-cta p { color: var(--orange-bright); font-family: var(--font-head); font-weight: 700; text-transform: uppercase; margin: 0 0 0.35rem; font-size: 1.15rem; }
.mini-cta p + p { color: rgba(255,255,255,0.80); font-weight: 400; text-transform: none; margin-bottom: 1rem; font-family: var(--font-body); }
.mini-cta .btn { margin-top: 0.5rem; }

/* ---------- Banner (centered emphasis over image) ---------- */
.banner { color: #fff; display: flex; align-items: center; min-height: 420px; padding: clamp(3.5rem, 7vw, 6rem) 0; text-align: center; }
.banner-inner { max-width: 760px; margin: 0 auto; }
.banner h2 { color: #fff; }
.banner p { color: rgba(255,255,255,0.9); }
.banner-kicker { font-family: var(--font-head); text-transform: uppercase; letter-spacing: 0.08em; font-weight: 700; font-size: 1.05rem; color: var(--teal-bright); margin: 0 0 0.5rem; }
.banner-cta-row { display: flex; flex-wrap: wrap; gap: 0.75rem 1rem; justify-content: center; margin-top: 1.75rem; }

/* ---------- Testimonials carousel (JS in /testimonials.js) ---------- */
.testimonials { background: var(--color-bg-alt); }
.testi-carousel { display: flex; align-items: center; gap: clamp(0.5rem, 2vw, 1rem); margin-top: 2rem; }
.testi-viewport { overflow: hidden; flex: 1 1 auto; min-width: 0; }
.testi-track { display: flex; margin: 0; padding: 0; list-style: none; will-change: transform; }
.testi-slide { flex: 0 0 100%; width: 100%; padding: 0.5rem clamp(0.25rem, 2vw, 1.5rem); }
.testi-quote { margin: 0 auto; max-width: 760px; background: #fff; border: 1px solid var(--color-border); border-top: 4px solid var(--card-accent); border-radius: var(--radius); padding: clamp(1.5rem, 4vw, 2.75rem); text-align: center; box-shadow: var(--shadow-md); }
.testi-quote > p { font-size: clamp(1.05rem, 2vw, 1.3rem); line-height: 1.6; font-style: italic; color: var(--color-text); margin: 0 0 1.5rem; }
.testi-quote > p::before { content: "\201C"; }
.testi-quote > p::after  { content: "\201D"; }
.testi-cite { display: flex; flex-direction: column; gap: 0.1rem; }
.testi-name { font-family: var(--font-head); font-weight: 700; text-transform: uppercase; letter-spacing: 0.02em; color: var(--color-heading); font-size: 1.2rem; }
.testi-meta { font-size: 0.9rem; color: var(--color-text-muted); }
.testi-arrow { flex: 0 0 auto; width: 48px; height: 48px; display: inline-flex; align-items: center; justify-content: center; background: var(--navy); color: #fff; border: 0; border-radius: 50%; cursor: pointer; transition: background-color .15s ease, transform .08s ease; }
.testi-arrow:hover { background: var(--orange-fill); color: var(--btn-ink); }
.testi-arrow:active { transform: scale(0.94); }
.testi-arrow svg { width: 24px; height: 24px; }
.testi-dots { display: flex; justify-content: center; gap: 0.5rem; margin-top: 1.5rem; }
.testi-dot { width: 10px; height: 10px; border-radius: 50%; background: var(--color-border); transition: background-color .15s ease; }
.testi-dot.is-active { background: var(--teal); }
@media (prefers-reduced-motion: reduce) { .testi-track { transition: none !important; } }

/* ---------- Recent-projects carousel (scroll-snap gallery) ---------- */
.projects { background: var(--navy); color: var(--color-fg-on-dark); }
.projects h2 { color: #fff; }
.projects-head { margin-bottom: clamp(1.5rem, 3vw, 2.25rem); }
.projects-carousel { position: relative; }
.projects-track {
  display: flex; gap: 1.25rem; margin: 0; padding: 0 0 0.5rem; list-style: none;
  overflow-x: auto; scroll-snap-type: x mandatory; scroll-behavior: smooth;
  -webkit-overflow-scrolling: touch; scrollbar-width: none;
}
.projects-track::-webkit-scrollbar { display: none; }
.projects-track:focus-visible { outline: 3px solid var(--color-focus); outline-offset: 4px; }
.project-card {
  flex: 0 0 auto; width: min(85%, 380px); scroll-snap-align: start;
  background: var(--navy-2); border-top: 4px solid var(--accent-frame);
  box-shadow: var(--shadow-md); overflow: hidden;
}
@media (min-width: 700px) { .project-card { width: calc((100% - 2.5rem) / 3); } }
@media (min-width: 1040px) { .project-card { width: calc((100% - 3.75rem) / 4); } }
.project-card img { width: 100%; aspect-ratio: 4 / 3; object-fit: cover; display: block; }
.project-cap { padding: 0.9rem 1.1rem 1.1rem; }
.project-tag {
  display: inline-block; font-family: var(--font-head); font-weight: 700;
  text-transform: uppercase; letter-spacing: 0.04em; font-size: 0.72rem;
  color: var(--btn-ink); background: var(--orange-fill); padding: 0.15rem 0.55rem; margin-bottom: 0.5rem;
}
.project-cap p { margin: 0; font-family: var(--font-head); font-weight: 700; text-transform: uppercase; color: #fff; font-size: 1.05rem; line-height: 1.15; }
.proj-arrows { display: flex; justify-content: center; gap: 0.6rem; margin-top: 1.5rem; }
.proj-btn {
  width: 48px; height: 48px; display: inline-flex; align-items: center; justify-content: center;
  background: var(--navy-2); color: #fff; border: 2px solid rgba(255,255,255,0.25); cursor: pointer;
  transition: background-color .15s ease, border-color .15s ease, opacity .15s ease, transform .08s ease;
}
.proj-btn:hover { background: var(--orange-fill); border-color: var(--orange-fill); color: var(--btn-ink); }
.proj-btn:active { transform: scale(0.94); }
.proj-btn:disabled { opacity: 0.35; cursor: default; }
.proj-btn svg { width: 24px; height: 24px; }
@media (prefers-reduced-motion: reduce) { .projects-track { scroll-behavior: auto; } }

/* ---------- CTA (closing call to action) ---------- */
.cta-split { display: grid; gap: clamp(1.5rem, 3vw, 2.5rem); grid-template-columns: 1fr; align-items: start; }
@media (min-width: 880px) { .cta-split { grid-template-columns: 1fr 1fr; } }
.cta-split .btn-row { display: flex; flex-wrap: wrap; gap: 0.75rem; margin-top: 1.5rem; }
.cta > .container > .btn-row { display: flex; flex-wrap: wrap; gap: 0.75rem; justify-content: center; margin-top: clamp(1.5rem, 3vw, 2.5rem); }

/* ---------- Print ---------- */
@media print {
  .top-bar, .site-header, .site-footer, .nav-cta, .howitworks, .feature-band { display: none; }
  body { font-size: 12pt; color: #000; background: #fff; }
}

/* ============================================================
   SITE-LOCAL — columbia-spray-foam-works
   Additions the shared polebarn skin does not ship. All values
   come from existing Harbor tokens; no new colours introduced.
   ============================================================ */

/* ---------- services-grid on LIGHT surfaces ----------
   The shared block is dark-only (.section-dark). Sections 03 and 04
   render the same cards on the white page and on the tinted band. */
.services-light { background: var(--color-bg); }
.services-band  { background: var(--color-bg-alt); }
.services-light .services-head h2,
.services-band  .services-head h2 { color: var(--color-heading); margin-bottom: 0.5rem; }
.services-light .process-intro,
.services-band  .process-intro { color: var(--color-text); }
.services-light .service-card,
.services-band  .service-card { background: #fff; border-color: var(--color-border); box-shadow: var(--shadow-sm); }
/* --teal-bright is the on-dark hover ink; it disappears on white */
.services-light .service-card:hover,
.services-band  .service-card:hover { border-color: var(--orange-fill); box-shadow: var(--shadow-md); }
.services-light .service-card-body p,
.services-band  .service-card-body p { color: var(--color-text); }

/* --3up: cancel the 2-then-3 mosaic so a three-card section renders
   as one even row of three instead of 2 wide + 1 orphan. */
@media (min-width: 940px) {
  .services-grid--3up .service-card:nth-child(-n+2) { grid-column: span 2; }
}

/* ---------- .compare-table (new component) ----------
   Section 07's 8-row open-cell/closed-cell comparison. Lives inside the
   --long-center dark panel, so it is styled for an on-dark surface. */
.compare-table-wrap { overflow-x: auto; margin: clamp(1.5rem, 3vw, 2.25rem) 0 0; }
.compare-table {
  width: 100%; min-width: 34rem; border-collapse: collapse;
  font-size: 0.97rem; line-height: 1.45; text-align: left;
}
.compare-table th,
.compare-table td { padding: 0.65rem 0.9rem; vertical-align: top; border-bottom: 1px solid rgba(255,255,255,0.16); }
.compare-table thead th {
  font-family: var(--font-head); font-weight: 700; text-transform: uppercase;
  letter-spacing: 0.03em; font-size: 1.02rem; color: var(--teal-bright);
  border-bottom: 3px solid var(--accent-frame);
}
.compare-table tbody th[scope="row"] { color: #fff; font-weight: 700; white-space: nowrap; }
.compare-table tbody td { color: rgba(255,255,255,0.85); }
.compare-table tbody tr:nth-child(even) { background: rgba(255,255,255,0.05); }
.compare-table tbody tr:last-child th,
.compare-table tbody tr:last-child td { border-bottom: none; }
@media (max-width: 560px) {
  .compare-table tbody th[scope="row"] { white-space: normal; }
}

/* --framed keeps the template's CENTRED figure. An earlier `align-items:
   stretch` override here made the figure fill the full copy height, which is
   what produced the 549x787 portrait; the figure is pinned to 3:2 below with
   the other keyline figures instead. */

/* ---------- .cta-center (shared modifier the skin lacks) ---------- */
.cta-center { max-width: 62rem; margin: 0 auto; text-align: center; }
.cta-center .btn-row { display: flex; flex-wrap: wrap; gap: 0.75rem; justify-content: center; margin-top: clamp(1.5rem, 3vw, 2.5rem); }

/* ---------- FAQ trailing CTA line (below the accordion) ---------- */
.faq-outro { margin: 1.5rem 0 0; color: var(--color-text); }

/* ---------- uniform service-card headings ----------
   The polebarn mosaic gives the first TWO cards of every grid a larger heading
   (clamp(1.5rem, 2vw, 1.9rem)) and larger body text, because they span 3 of 6
   columns instead of 2. Operator asked for one size across the grid, so both
   are pulled back: headings to the global h3 scale, body text to the card
   default. The 2-then-3 mosaic GEOMETRY is unchanged — only the type. */
@media (min-width: 940px) {
  .service-card:nth-child(-n+2) .service-card-header { font-size: clamp(1.2rem, 1.9vw, 1.35rem); }
  .service-card:nth-child(-n+2) .service-card-body p { font-size: 0.95rem; }
}
.service-card-header { font-size: clamp(1.2rem, 1.9vw, 1.35rem); }

/* ---------- header: one-line wordmark ----------
   "Columbia Spray Foam Works" is a 25-character wordmark. At the template's
   1.7rem it needs 416px on one line but only ~325px is free, so it wrapped to
   two lines and pushed the sticky header to 156px against a --header-h of 80px.
   Lock it to one line and let it scale with the viewport; tighten the desktop
   nav (which was also wrapping) so the whole row fits on one line. */
.brand-text { white-space: nowrap; }   /* TEMPORARY wordmark "Spray Foam" — real logo pending */
@media (min-width: 901px) {
  .nav-item > a { font-size: 1.05rem; }
  .nav-list { column-gap: 1.5rem; }
}

/* ---------- §07 open-cell/closed-cell column balance ----------
   HISTORY: while §07 was image-less this was 1.06fr / 0.94fr. --long-center has
   no figure to absorb slack, so the columns had to be authored to match, and the
   open-cell paragraph runs ~10 words longer than the closed-cell one — it pushed
   the left column a line proud (27px > the 24px tolerance) once Barlow/Roboto
   rewrapped it. Copy is fixed, so the column ratio was used as the variable.

   2026-07-28: §07 gained a MATCHED PAIR of foam-texture figures (see the pin
   below). An uneven ratio now costs more than it buys — at this grid width
   1.06/0.94 renders the two swatches ~64px different in width, and a comparison
   pair that is visibly not the same size reads as a bug. Equal columns were
   expected to bring the old 27px rag back; measured, they do not — the figures
   changed where the paragraphs wrap and the block now sits at **0px** at 1440
   and 1024. Re-measure if this copy is ever edited.

   NOTE the media query — the 1.06/0.94 version did NOT have one, so it also beat
   the template's single-column mobile default (.flex-media-long-grid is 1fr and
   only becomes two columns at 768px). §07 was therefore rendering as two ~131px
   columns on a 390px phone, unreadable, since before this change. Column ratios
   belong inside the breakpoint that creates the columns. */
@media (min-width: 768px) {
  .flex-media--long-center .flex-media-long-grid { grid-template-columns: 1fr 1fr; }
}

/* ---------- §07 figures: a matched pair, NOT a slack absorber ----------
   These two images exist to be compared, so they must render identically. The
   template default (flex: 1 1 0) makes a figure swallow whatever slack its
   column has left — with §07's uneven paragraphs that would render the pair at
   two different heights. Pin both to a fixed ratio and let the copy split carry
   the balance, the same trade the --long figures make above.
   Both sources are cut to exactly 4:3 (756x567 and 640x480), so object-fit has
   nothing to crop — keep it that way when re-sourcing and the framing you cut is
   the framing that ships. */
@media (min-width: 768px) {
  #foam-types-h2 ~ .flex-media-long-grid .flex-media-long-figure { flex: 0 0 auto; aspect-ratio: 4 / 3; min-height: 0; }
}

/* NEVER UPSCALE — a guard rail, not an active constraint. Both images now exceed
   the grid column (which runs 508px at 1440), so nothing is being stretched at
   any normal width; the cap only bites on an ultra-wide viewport. 756 is the
   SMALLER of the two files (open-cell 756x567, closed-cell 800x600) and the pair
   must render identically, so it sets the ceiling for both.
   Earlier revisions capped at 488 then 462 then 459, each time because the images
   of the day were crops off a small comparison graphic. Re-measure on any
   re-source: the cap is the smaller FILE width. */
#foam-types-h2 ~ .flex-media-long-grid .flex-media-long-figure { max-width: 756px; }

/* §07 figures drop the offset keyline frame (operator, 2026-07-28). Elsewhere the
   frame marks a photo as a feature figure; these two are reference swatches read
   against each other, and two frames sitting side by side fought the comparison.
   Dropping it also releases the 14px the site-local rhythm rule reserves below a
   first-child figure for the frame's overhang — no frame, no reservation. */
#foam-types-h2 ~ .flex-media-long-grid .flex-media-long-figure::after { content: none; }
#foam-types-h2 ~ .flex-media-long-grid .flex-media-long-col > .flex-media-long-figure:first-child { margin-bottom: 1.75rem; }

/* ---------- hero: tighter paragraph rhythm ----------
   The three intro paragraphs moved into the hero on 2026-07-28. The template's
   1.75rem gap was tuned for a single hero paragraph and reads as three
   disconnected blocks at this length. The last one keeps its larger gap so the
   CTA row still separates cleanly (.hero--form .hero-intro:last-of-type). */
.hero--form .hero-text .hero-intro { margin-bottom: 0.7rem; line-height: 1.55; }
/* restate the CTA gap — this selector outranks the template's
   .hero--form .hero-intro:last-of-type at equal specificity */
.hero--form .hero-text .hero-intro:last-of-type { margin-bottom: 1.5rem; }

/* ---------- header phone button: cream label, white on hover ----------
   Keeps the template's zero-shift border-bottom hover (the 4px border is
   reserved transparent and the bottom padding pre-shortened), and adds a
   colour swap on top. Cream #FFF5D0 on navy is 14.6:1; white is 15.8:1. */
.btn-tel { color: var(--orange-bright); transition: border-color .15s ease, color .15s ease; }
.btn-tel:hover { color: #fff; }

/* ---------- --long figures keep a normal landscape ratio ----------
   The template makes the figure the column-balance shock absorber
   (flex: 1 1 0), so it takes whatever slack is left — which rendered §01 at
   560x236 (2.37:1), a letterbox against every other figure on the page
   (0.70-0.88). Pin a normal 3:2 instead and let the copy split carry the
   balance. Verified per block with the block-vocabulary balance check. */
@media (min-width: 768px) {
  .flex-media--long .flex-media-long-figure,
  .flex-media--long-reverse .flex-media-long-figure,
  .flex-media--framed .flex-media-long-figure { flex: 0 0 auto; aspect-ratio: 5 / 3; min-height: 0; }
}

/* ---------- spotlight: image under the service-area chips ----------
   Wears the same offset keyline frame as the --framed / --long figures. It hangs
   bottom-RIGHT, matching the default --framed / --long treatment. The figure
   reserves the 14px internally, so the frame never overflows the container. */
.spotlight-figure { margin: clamp(1.5rem, 3vw, 2rem) 0 0; position: relative; padding: 0 14px 14px 0; }
.spotlight-figure img { width: 100%; height: auto; aspect-ratio: 3 / 2; object-fit: cover; border-radius: var(--radius); box-shadow: var(--shadow-md); position: relative; z-index: 1; display: block; }
.spotlight-figure::after {
  content: ""; position: absolute; inset: 14px 0 0 14px;
  border: 3px solid var(--keyline); border-radius: var(--radius); z-index: 0; pointer-events: none;
}
@media (max-width: 767px) {
  .spotlight-figure { padding: 0 10px 10px 0; }
  .spotlight-figure::after { inset: 10px 0 0 10px; }
}


/* ---------- §07: breathing room under the comparison table ---------- */
.compare-table-wrap + p { margin-top: clamp(1.5rem, 3vw, 2.25rem); }

/* §12 puts ALL the copy in one column and only the image + button in the other,
   so its figure goes back to absorbing the column slack (the template default)
   rather than holding a fixed ratio — with a whole column of copy opposite it,
   the slack it takes is a normal portrait, not the letterbox §01 produced. */
@media (min-width: 768px) {
  #rvalue-h2 ~ .flex-media-long-grid .flex-media-long-figure,
  #benefits-h2 ~ .flex-media-long-grid .flex-media-long-figure { flex: 1 1 0; aspect-ratio: auto; min-height: 200px; }
}

/* ---------- hero base: plain navy rule instead of the corrugated edge ----------
   The skin's signature .hero::after is a galvanized-rib strip with a cream
   baseline. Replaced here with a simple flat border. */
.hero::after { content: none; }
.hero { border-bottom: 4px solid #0F232D; }

/* ---------- hero: tighter gap above the h1 ----------
   The template's top padding (up to 4.5rem) was sized for a hero whose h1 sits
   inside a column beside the form. Here the h1 spans the full width directly
   under the sticky header, so the same gap reads as dead space. Bottom padding
   is untouched. */
.hero--form { padding-top: clamp(1.75rem, 3.5vw, 2.75rem); }

/* ---------- §01 Why Choose: bullets are prose, size them like prose ----------
   .snow-list is 0.97rem (15.52px) in the template — right for a compact feature
   list of short fragments, which is what §07's "we select by checking" list is.
   §01's nine bullets are full sentences and are that section's ONLY body copy,
   so they sat a half-step below every other paragraph on the page. */
#why-h2 ~ .flex-media-long-grid .snow-list li { font-size: 1rem; }

/* ---------- hero: top-align the copy with the quote card ----------
   The template centres .hero-grid's two columns, which was right when the copy
   column was the taller one. Now that it is shorter than the form, centring
   pushed it down by half the difference and opened a gap above the first
   paragraph. Top-align so the copy starts level with the card's top edge. */
@media (min-width: 900px) {
  .hero--form .hero-grid { align-items: start; }
}



@media (min-width: 768px) {
  .flex-media-long-figure--banner { flex: 0 0 auto; aspect-ratio: 3 / 2; }
}


/* ---------- uniform vertical rhythm inside .flex-media-long-col ----------
   That container is display:flex, so margins do NOT collapse: a paragraph's
   16px bottom margin and an h3's 24px top margin ADD to 40px, against 16px
   between paragraphs. Normalise every gap in the column to one 16px step. */
.flex-media-long-col > h3 { margin-top: 0; margin-bottom: 1rem; }
.flex-media-long-col > p, .flex-media-long-col > ul { margin-bottom: 1rem; }
.flex-media-long-col > .flex-media-cta-row { margin-top: 0; }
/* The keyline frame overhangs the figure 14px on the right and bottom, so the
   step below it has to clear the FRAME, not the image: 1.75rem + the overhang.
   The grid also reserves 14px on the right so the frame is not crowding the
   container edge (it was sitting 6px off it). */
.flex-media-long-col > .flex-media-long-figure:first-child { margin-bottom: calc(1.75rem + 14px); }
.flex-media--long .flex-media-long-grid { padding-right: 14px; }
.flex-media-long-col > .flex-media-long-figure:last-child { padding-top: 0; }  /* the preceding element's 1rem margin already supplies the step */
.flex-media-long-col > :last-child { margin-bottom: 0; }

/* ---------- hero: slightly deeper scrim over the install photo ----------
   bg-soft ships at 0.55 -> 0.72; the new hero photo is brighter than the one
   the template tuned against. Same harbor navy, just more of it — scoped to
   the hero so any other .bg-soft band is untouched. */
.hero--form.bg-host::before {
  background: linear-gradient(rgba(15,35,45,0.64), rgba(15,35,45,0.80));
}

/* ---------- hero: fixed (parallax) background ----------
   The skin's hero paints its photo with an <img class="bg-img">, which cannot
   be attachment-fixed. Use the documented pattern instead: a CSS background on
   the section with attachment:fixed, and hide the <img> so the fixed layer
   shows through. The ::before scrim still sits above it (z-index 1).
   Dropped below 901px — iOS renders fixed attachment badly — where the <img>
   returns automatically.
   NOTE: the photo now lives in TWO places. Swapping it means changing this
   url() AND the <img> src/srcset in index.html. */
@media (min-width: 901px) {
  .hero--form {
    background-image: url("/images/hero-foam-applicator-1600.webp");
    background-position: center;
    background-size: cover;
    background-attachment: fixed;
  }
  .hero--form > .bg-img { display: none; }
}

/* ---------- §10 step numbers: same tile colour as the phone icon ----------
   The template fills `.step-num` with `--orange-fill`, which is the "button fill
   on LIGHT surfaces" token. In harbor that resolves to #0F232D — the exact
   colour of `.section-dark`, which is the surface §10 sits on. So the badge had
   no visible shape at all: 1.00:1 against its own background, leaving the cream
   numeral floating with only the 6px ring punching it out of the galvanized post
   line. Its sibling `.process-step-icon` (the phone tile on step 1) uses
   `--teal` = #1C3846 and does read as a tile, which is the inconsistency the
   operator spotted.

   Using --teal here matches that sibling exactly and is the semantically correct
   token for a panel on dark — --orange-fill is by its own definition a
   light-surface token and should not have been carrying a badge on a dark
   section. The 6px --navy ring is kept: it still separates the badge from the
   post line behind it.

   Cream numeral on #1C3846 is 11.28:1 (was 14.80:1 on the navy). Both clear 4.5
   comfortably; the badge now also reads as a shape, which it did not before. */
[data-theme="harbor"] .process-step .step-num { background: var(--teal); }

/* ---------- testimonial card: greige, with a 5-star row ----------
   Same reasoning as the §06/§11 cards below — `.testi-quote` shipped white on
   the `--color-bg-alt` band (1.03:1, no visible edge); greige gives it 1.21:1.
   It keeps its hairline and its 4px --card-accent top bar.

   Stars use `--orange`, matching the pattern already in tiffin-concrete-co. In
   harbor that token resolves to mid navy #1C3846, which is 9.92:1 on the greige
   card — far past the 3:1 non-text floor. NOTE they are NOT gold: harbor has no
   warm accent that survives on a light surface (cream #FFF5D0 on greige is
   ~1.2:1, invisible). Navy stars are the honest read of a locked palette; if the
   testimonial card ever goes dark, cream becomes available and is the better
   colour there.

   The `#star-filled` symbol was ported into icons.svg from tiffin's sprite —
   the Lucide `#star` this site shipped is an outline, wrong for a rating. */
[data-theme="harbor"] .testi-quote { background: var(--oat); }
.testi-stars { display: flex; justify-content: center; gap: 0.2rem; color: var(--orange); margin: 0 0 1.1rem; }

/* ---------- §06 + §11: greige text card, matching §05 ----------
   `.flex-media-text` is an --oat (greige #E9E7D9) card by default. The template
   flips it to white for `--stack-reverse` (style.css:1567) because that variant
   sits on the `--color-bg-alt` band, and in most palettes oat is close enough to
   that band that the card would vanish into it.

   Harbor is the exception. Its band is #FFFCF2 and its oat is #E9E7D9, so the
   greige card actually separates BETTER than the white one does:
     greige card on #FFFCF2 band : 1.21:1
     white  card on #FFFCF2 band : 1.03:1  (all but invisible)
   §05 uses plain `--stack`, so it kept the greige card and is the reference the
   operator was matching.

   Ink checked against greige, all well clear: --color-text / --color-heading
   #0F232D 13.01:1, --color-text-muted #1C3846 9.92:1, and both button hover
   states that expose the panel (btn-call 9.92:1, btn-outline-dark 13.01:1).
   Neither panel contains a form field or a nested --oat card, so there is no
   greige-on-greige collision.

   Scoped to [data-theme="harbor"] (0,3,0) so it outranks the template rule
   without editing the template-derived region, which still serves the other
   palettes correctly. */
[data-theme="harbor"] .flex-media--stack-reverse .flex-media-text { background: var(--oat); }

/* ---------- hero "Call Now": cream outline + cream label ----------
   The template gives harbor's hero secondary a solid --navy-card fill with white
   ink and a border the same colour as the fill, so it reads as a flat navy slab
   with no edge against the hero photo. Operator asked for an outline in the
   cream, with the label to match.

   Kept as a site-local override at the identical selector rather than an edit to
   the template block at ~828 — same specificity (0,3,0), later in the file, so
   this wins without diverging the template-derived region.

   Contrast: cream #FFF5D0 on --navy-card #1C3846 is 11.06:1 for the label, and
   the cream border against the scrimmed photo clears the 3:1 non-text floor
   comfortably. Hover inverts to a cream fill with navy ink (14.80:1, the
   --btn-fill-dark / --btn-ink-dark pair), which keeps the skin's
   solid-goes-inverse-on-hover behaviour instead of fading to transparent.
   The phone <svg> inherits currentColor, so the icon turns cream with the label. */
[data-theme="harbor"] .hero .btn-outline-light {
  background: var(--navy-card); color: var(--orange-bright); border-color: var(--orange-bright);
}
[data-theme="harbor"] .hero .btn-outline-light:hover {
  background: var(--orange-bright); color: var(--navy); border-color: var(--orange-bright);
}

/* ---------- §09 safety: fixed (parallax) background ----------
   Same construction as the hero above, applied to the one --center section on
   the page. `.section-dark` sets `background: var(--navy)` as a shorthand at
   equal specificity (0,1,0); this block is later in the file, so the
   background-image lands and the navy survives underneath as the fallback
   colour — which is what shows in the gap while the image loads.

   Text safety is unaffected: §09's copy sits on `.overlay-center`
   (`--overlay-panel`, 78% navy) over the section's 35% scrim, so the panel
   carries the contrast, not the photo. Same as §07.

   Dropped below 901px — iOS renders fixed attachment badly — where the
   <img class="bg-img"> takes over automatically.

   ⚠ THE PHOTO IS NOW NAMED IN TWO PLACES, exactly like the hero: this url()
   AND the <img> src/srcset in index.html. Change one without the other and the
   section serves two different photos either side of 901px. Before swapping:
     grep -rn "safety-ppe-applicator" site/{index.html,style.css} */
@media (min-width: 901px) {
  .flex-media--center {
    background-image: url("/images/safety-ppe-applicator-bg-1600.webp");
    background-position: center;
    background-size: cover;
    background-attachment: fixed;
  }
  .flex-media--center > .bg-img { display: none; }
}

/* §15 Moisture, Humidity and Indoor Air — same fixed (parallax) treatment as the
   hero and §09. Scoped by id, NOT by `.flex-media--overlay`, because that
   variant is used by more than one section and a class selector would repaint
   all of them with this photo.

   ⚠ THIRD PLACE THE TWO-FILE RULE APPLIES. The photo is named here AND as the
   <img class="bg-img"> src/srcset in index.html. Change one without the other
   and the section serves two different photos either side of 901px — and you
   will not notice, because editing the <img> and reloading at desktop width
   still shows the CSS one, which reads as a caching problem. Before swapping:
     grep -rn "moisture-foam-texture-bg" site/{index.html,style.css}

   Contrast is safe here for the same reason as §07 and §09: the copy sits on
   `.overlay-half`, so the panel carries the contrast rather than the photo.

   Dropped below 901px — iOS renders fixed attachment badly — where the <img>
   takes over. Note the ?v=2 on the <img> is a cache-bust and must NOT be copied
   into this url(): a query string in CSS defeats nothing and just makes the two
   references look different when they should read as identical. */
@media (min-width: 901px) {
  #moisture-bg {
    background-image: url("/images/moisture-foam-texture-bg-1600.webp");
    background-position: center;
    background-size: cover;
    background-attachment: fixed;
  }
  #moisture-bg > .bg-img { display: none; }
}

/* Mobile hero: bias the cover crop toward the foam wall + spray gun, which sit
   left-of-center in hero-foam-applicator (default 50% centers on the wood
   framing). This <img> only renders ≤900px — desktop paints the same photo as
   a fixed CSS background and is unaffected. */
.hero--form > .bg-img { object-position: 38% 50%; }

/* Grouped ("mega") Services dropdown — the three category groups (Spray Foam
   Applications / Related Services / Other Insulation Services) flowed into TWO
   balanced columns via CSS multicol: Applications (11) fills one column,
   Related (8) + Other (3) stack in the other. Two columns (not three) keeps the
   menu narrow enough to clear the right edge at the 1151px desktop floor, since
   the Services item sits mid-header. .dropdown a already styles the links. */
.dropdown-mega { display: block; column-count: 2; column-gap: 0; column-rule: 1px solid var(--color-border); padding: 0.6rem 0; min-width: 0; }
.dropdown-mega > .mega-group { break-inside: avoid; padding: 0.4rem 0; }
.mega-head { display: block; padding: 0.3rem 1.1rem 0.5rem; font-family: var(--font-head); font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; font-size: 0.78rem; color: var(--color-text-muted); white-space: nowrap; }
.mega-list { list-style: none; margin: 0; padding: 0; }
.mega-list li { margin: 0; }

/* Footer brand is now the reversed image logo; cap its width so it doesn't
   stretch to the full column. */
.footer-brand-logo img { max-width: 230px; }

/* Mobile (hamburger) view: the mega dropdown stacks — category headings become
   light labels on the navy panel, column dividers become row dividers.

   ⚠ THE FIRST RULE IS LOAD-BEARING. Without `column-count: 1` the desktop
   multicol above stays active inside the hamburger panel, which squeezes the
   three groups into two ~45vw columns and drags the `column-rule` straight
   through the "RELATED SERVICES" heading. Styling `.mega-group` for stacking is
   not enough on its own — multicol has to be switched off, or the group rules
   below are laying row dividers over a column layout. */
@media (max-width: 1150px) {
  .site-nav.is-open .dropdown-mega { column-count: 1; column-rule: none; column-gap: 0; }
  .site-nav.is-open .dropdown-mega > .mega-group { padding: 0.35rem 0; }
  .site-nav.is-open .dropdown-mega > .mega-group + .mega-group { border-left: 0; border-top: 1px solid rgba(255,255,255,0.15); }
  .site-nav.is-open .mega-head { padding: 0.5rem 0 0.25rem; color: rgba(255,255,255,0.55); }
  .site-nav.is-open .mega-list { padding-left: 0.75rem; }
}
