/* Sackett Electric LLC - Field Standard direction (operator-locked 2026-05-28)
   Tokens: bg #161616 · surface #242424 · ink #F2F2F2 · muted #AEB4BB · accent #FFC107
   Heading: Saira Condensed · Body: Roboto · Radius 2px · Density: comfortable */

/* ---------- Self-hosted fonts ----------
   Fonts are served from /assets/fonts (woff2, latin + latin-ext subsets) instead
   of the render-blocking Google Fonts stylesheet. font-display: swap keeps text
   visible during font load (no FOIT). The unicode-range values match Google's own
   latin / latin-ext subsetting, so the browser only fetches the subset a glyph
   needs. Roboto v51 ships a single variable file per subset, so one face covers
   the 400-700 weight range; Saira Condensed ships a discrete file per weight. */
@font-face {
  font-family: "Saira Condensed"; font-style: normal; font-weight: 500; font-display: swap;
  src: url("/assets/fonts/saira-condensed-500-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Saira Condensed"; font-style: normal; font-weight: 500; font-display: swap;
  src: url("/assets/fonts/saira-condensed-500-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Saira Condensed"; font-style: normal; font-weight: 600; font-display: swap;
  src: url("/assets/fonts/saira-condensed-600-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Saira Condensed"; font-style: normal; font-weight: 600; font-display: swap;
  src: url("/assets/fonts/saira-condensed-600-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Saira Condensed"; font-style: normal; font-weight: 700; font-display: swap;
  src: url("/assets/fonts/saira-condensed-700-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Saira Condensed"; font-style: normal; font-weight: 700; font-display: swap;
  src: url("/assets/fonts/saira-condensed-700-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Roboto"; font-style: normal; font-weight: 400 700; font-display: swap;
  src: url("/assets/fonts/roboto-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Roboto"; font-style: normal; font-weight: 400 700; font-display: swap;
  src: url("/assets/fonts/roboto-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}
@font-face {
  font-family: "Caveat"; font-style: normal; font-weight: 600; font-display: swap;
  src: url("/assets/fonts/caveat-600-latin-ext.woff2") format("woff2");
  unicode-range: U+0100-02BA, U+02BD-02C5, U+02C7-02CC, U+02CE-02D7, U+02DD-02FF, U+0304, U+0308, U+0329, U+1D00-1DBF, U+1E00-1E9F, U+1EF2-1EFF, U+2020, U+20A0-20AB, U+20AD-20C0, U+2113, U+2C60-2C7F, U+A720-A7FF;
}
@font-face {
  font-family: "Caveat"; font-style: normal; font-weight: 600; font-display: swap;
  src: url("/assets/fonts/caveat-600-latin.woff2") format("woff2");
  unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+0304, U+0308, U+0329, U+2000-206F, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
}

:root {
  --bg: #161616;
  --bg-deep: #0F0F0F;
  --surface: #242424;
  --surface-2: #2E2E2E;
  --ink: #F2F2F2;
  --ink-bright: #FFFFFF;
  --muted: #AEB4BB;
  /* Accent is driven entirely by these tokens so the whole site can be
     re-themed by overriding them on :root (see theme-lab.js). --accent-rgb is
     the channel triple so rgba(var(--accent-rgb), a) glows stay in-theme.
     hi/hi2/lo are the gradient shades; the defaults below are the exact,
     hand-tuned power-yellow values, so the default theme is pixel-identical. */
  --accent-rgb: 255, 193, 7;
  --accent: rgb(var(--accent-rgb));
  --accent-hi: #ffce3a;
  --accent-hi2: #ffd451;
  --accent-lo: #f0b400;
  --accent-on: #161616;
  --line: rgba(255, 255, 255, 0.10);
  --line-strong: rgba(255, 255, 255, 0.20);

  --font-head: "Saira Condensed", "Oswald", "Arial Narrow", sans-serif;
  --font-body: "Roboto", system-ui, -apple-system, "Segoe UI", sans-serif;

  --r: 2px;
  --container: 1200px;
  --gutter: clamp(24px, 6vw, 60px);
  --section-y: clamp(64px, 9vw, 116px);

  /* Measured layout constants used by the mobile hero height math: the sticky
     header is 75px tall (min-height 74px + border) and the trust-strip marquee
     after the hero is 63px tall. On mobile the hero min-height is sized so the
     hero + trust-strip together fill exactly one small viewport (100svh), which
     parks the trust strip at the bottom edge of the first screen on load. */
  --header-h: 75px;
  --trust-h: 63px;
}

* { box-sizing: border-box; }

html { scroll-behavior: smooth; -webkit-text-size-adjust: 100%; }
@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after { animation-duration: 0.001ms !important; transition-duration: 0.001ms !important; }
  /* Reveals must never hide content for reduced-motion users. */
  [data-reveal] { opacity: 1 !important; transform: none !important; }
  /* Power-up elements land on their finished lit state, no motion. */
  .hero-powerup::before { transform: scaleX(1) !important; animation: none !important; }
  .hero-powerup::after { opacity: 0.9 !important; transform: translate(50%, -50%) scale(0.85) !important; animation: none !important; }
  .subhero::after { transform: scaleX(1) !important; animation: none !important; box-shadow: 6px 0 12px -2px rgba(var(--accent-rgb), 0.4) !important; }
}

/* ---------- Entrance reveals ---------- */
/* JS adds .is-revealed when the section scrolls into view (forms.js,
   IntersectionObserver). Sections start translated + faded, settle on reveal.
   The .no-js fallback below keeps everything visible if JS never runs. */
[data-reveal] {
  opacity: 0; transform: translateY(22px);
  transition: opacity 0.6s cubic-bezier(0.22, 0.61, 0.36, 1), transform 0.6s cubic-bezier(0.22, 0.61, 0.36, 1);
  will-change: opacity, transform;
}
[data-reveal].is-revealed { opacity: 1; transform: none; }
[data-reveal][data-reveal-delay="1"] { transition-delay: 0.08s; }
[data-reveal][data-reveal-delay="2"] { transition-delay: 0.16s; }
.no-js [data-reveal] { opacity: 1; transform: none; }

body {
  margin: 0;
  background: var(--bg);
  color: var(--ink);
  font-family: var(--font-body);
  font-size: clamp(1rem, 0.96rem + 0.25vw, 1.125rem);
  line-height: 1.65;
  -webkit-font-smoothing: antialiased;
  text-rendering: optimizeLegibility;
}

img { max-width: 100%; display: block; }
a { color: inherit; text-decoration: none; }

h1, h2, h3, h4 {
  font-family: var(--font-head);
  font-weight: 700;
  line-height: 1.04;
  margin: 0;
  text-transform: uppercase;
  letter-spacing: 0.01em;
  text-wrap: balance;
  overflow-wrap: break-word;   /* never let a long word force horizontal overflow */
  color: var(--ink-bright);
}
h1 { font-size: clamp(2.35rem, 1.35rem + 4.6vw, 5rem); }
h2 { font-size: clamp(2rem, 1.3rem + 3vw, 3.25rem); }
h3 { font-size: clamp(1.375rem, 1.05rem + 1.5vw, 2rem); }
p { margin: 0; }
p + p { margin-top: 1em; }

/* Italic accent word inside headings: the one editorial note in an
   otherwise blunt, all-caps type system. Saira Condensed obliques cleanly. */
.accent-word { font-style: italic; color: var(--accent); }
h1 .accent-word { text-shadow: inherit; }

.container { width: 100%; max-width: var(--container); margin-inline: auto; padding-inline: var(--gutter); }
.section { padding-block: var(--section-y); }
.section--tight { padding-block: clamp(40px, 6vw, 72px); }
/* Halve the padding on one edge so two stacked sections don't double up their
   gap (e.g. the services-hub card grid sitting above "How we work"). */
.section--flush-bottom { padding-bottom: calc(var(--section-y) / 2); }
.section--flush-top { padding-top: calc(var(--section-y) / 2); }

.eyebrow {
  font-family: var(--font-head);
  text-transform: uppercase;
  letter-spacing: 0.22em;
  font-size: 0.875rem;
  font-weight: 600;
  color: var(--accent);
  margin: 0 0 14px;
}
.lede { color: var(--muted); font-size: clamp(1.05rem, 1rem + 0.4vw, 1.3rem); text-wrap: pretty; max-width: 60ch; }

/* ---------- Skip link ---------- */
.skip-link {
  position: absolute; left: 16px; top: -48px;
  background: var(--accent); color: var(--accent-on);
  padding: 10px 16px; border-radius: var(--r); font-weight: 700;
  z-index: 200; transition: top 0.18s ease;
}
.skip-link:focus { top: 12px; }

/* ---------- Universal focus ring ---------- */
/* Keyboard focus gets a 2px accent outline with a 4px offset on every
   focusable element. Mouse clicks don't trigger it (:focus-visible), so the
   ring only appears for keyboard + AT users. AA-visible on the dark ground. */
:focus-visible {
  outline: 2px solid var(--accent);
  outline-offset: 4px;
  border-radius: var(--r);
}
/* Inputs draw the ring tight to the field (offset 0) plus a soft accent glow,
   so the 4px offset doesn't collide with the adjacent field in a grid row. */
.field input:focus-visible, .field select:focus-visible, .field textarea:focus-visible {
  outline: 2px solid var(--accent); outline-offset: 0;
  border-color: var(--accent); box-shadow: 0 0 0 4px rgba(var(--accent-rgb), 0.22);
}

/* ---------- Buttons ---------- */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: 9px;
  min-height: 50px; padding: 14px 26px;
  font-family: var(--font-head); font-weight: 600; font-size: 1.02rem;
  text-transform: uppercase; letter-spacing: 0.05em; white-space: nowrap;
  border-radius: var(--r); border: 1px solid transparent;
  cursor: pointer; transition: transform 0.12s ease, background 0.18s ease, border-color 0.18s ease, color 0.18s ease;
}
.btn:active { transform: translateY(1px); }
/* Primary CTA: a tight power-yellow gradient (brighter at the top edge, like
   light catching a brushed-metal switch plate) over a deep shadow. On hover the
   shadow sharpens (blur tightens, alpha climbs) and the button rises 2px. The
   dark ink on yellow holds well above WCAG AA at every point of the gradient. */
.btn {
  transition: transform 0.14s cubic-bezier(0.22, 0.61, 0.36, 1), background 0.18s ease, border-color 0.18s ease, color 0.18s ease, box-shadow 0.18s ease, filter 0.18s ease;
}
.btn-primary {
  background: linear-gradient(180deg, var(--accent-hi) 0%, var(--accent) 52%, var(--accent-lo) 100%);
  color: var(--accent-on); border-color: var(--accent);
  box-shadow: 0 8px 22px rgba(var(--accent-rgb), 0.26), 0 2px 6px rgba(0, 0, 0, 0.35);
}
.btn-primary:hover {
  background: linear-gradient(180deg, var(--accent-hi2) 0%, var(--accent-hi) 52%, var(--accent) 100%);
  border-color: var(--accent-hi); transform: translateY(-2px);
  box-shadow: 0 14px 30px rgba(var(--accent-rgb), 0.38), 0 4px 10px rgba(0, 0, 0, 0.42);
}
.btn-primary:active { transform: translateY(0); box-shadow: 0 6px 16px rgba(var(--accent-rgb), 0.3), 0 1px 4px rgba(0, 0, 0, 0.4); }
.btn-ghost { background: transparent; color: var(--ink-bright); border-color: var(--line-strong); }
.btn-ghost:hover { border-color: var(--accent); color: var(--accent); transform: translateY(-2px); box-shadow: 0 10px 24px rgba(0, 0, 0, 0.32); }
.btn-lg { min-height: 56px; padding: 16px 32px; font-size: 1.1rem; }
.phone-ico { width: 18px; height: 18px; flex: none; }
.header-call .phone-ico { display: none; }

/* ---------- Header ---------- */
.site-header {
  position: sticky; top: 0; z-index: 100;
  background: rgba(18, 18, 18, 0.82);
  backdrop-filter: saturate(150%) blur(10px);
  -webkit-backdrop-filter: saturate(150%) blur(10px);
  border-bottom: 1px solid var(--line);
}
.header-inner { display: flex; align-items: center; gap: 20px; min-height: 74px; }
/* The logo image stays 34px, but the link itself is a >=44px-tall tap target
   (it's vertically centered in the 74px header bar, so the hit box grows up and
   down around the mark without moving it or changing the visual). */
.brand { display: inline-flex; align-items: center; min-height: 44px; }
.brand img { height: 34px; width: auto; }
.nav { display: flex; align-items: center; gap: 30px; margin-left: auto; }
.nav a {
  font-family: var(--font-head); text-transform: uppercase; letter-spacing: 0.07em;
  font-size: 0.95rem; font-weight: 500; color: var(--muted); transition: color 0.16s ease;
}
.nav a:hover { color: var(--ink-bright); }
.header-cta { display: inline-flex; align-items: center; gap: 14px; margin-left: 8px; }
.nav-toggle {
  display: none; margin-left: auto; background: transparent; border: 1px solid var(--line-strong);
  color: var(--ink); border-radius: var(--r); width: 48px; height: 48px; cursor: pointer;
  align-items: center; justify-content: center;
  transition: border-color 0.18s ease, color 0.18s ease, background 0.18s ease;
}
.nav-toggle:hover { border-color: var(--accent); color: var(--accent); background: rgba(var(--accent-rgb), 0.08); }
.nav-toggle svg { width: 22px; height: 22px; }

/* ---------- Services dropdown (desktop) ---------- */
/* The Services nav item is a hover/focus dropdown: the trigger keeps its link to
   /services and gains a chevron, and a panel of the three detail pages (plus an
   "All services" link) drops beneath it. A transparent ::before hover-bridge
   spans the gap between trigger and panel so the menu never flicker-closes when
   the cursor travels down into it. Shown on :hover AND :focus-within for
   keyboard + pointer parity. The whole dropdown is desktop-only; on touch the
   open mobile menu lists the sub-links as their own rows (see responsive block). */
.nav-item { position: relative; display: inline-flex; align-items: center; }
.nav-item--has-dropdown > .nav-trigger { display: inline-flex; align-items: center; gap: 6px; }
.nav-chevron { width: 11px; height: 11px; flex: none; transition: transform 0.2s ease; }
.nav-item--has-dropdown:hover .nav-chevron,
.nav-item--has-dropdown:focus-within .nav-chevron { transform: rotate(180deg); }

.nav-submenu {
  position: absolute; top: 100%; left: 50%; transform: translateX(-50%) translateY(-6px);
  margin-top: 14px; min-width: 312px;
  background: linear-gradient(180deg, var(--surface) 0%, var(--bg-deep) 100%);
  border: 1px solid var(--line-strong); border-top: 2px solid var(--accent);
  border-radius: var(--r); padding: 10px;
  box-shadow: 0 24px 50px rgba(0, 0, 0, 0.5);
  display: flex; flex-direction: column; gap: 2px;
  opacity: 0; visibility: hidden; pointer-events: none;
  transition: opacity 0.18s ease, transform 0.18s ease, visibility 0.18s;
  z-index: 120;
}
/* Hover-bridge: a transparent strip filling the 14px gap (plus slack) between
   the trigger and the panel, so the hoverable area is continuous and the menu
   stays open while the cursor crosses the gap. */
.nav-submenu::before {
  content: ""; position: absolute; left: 0; right: 0; top: -16px; height: 16px; background: transparent;
}
.nav-item--has-dropdown:hover .nav-submenu,
.nav-item--has-dropdown:focus-within .nav-submenu {
  opacity: 1; visibility: visible; pointer-events: auto;
  transform: translateX(-50%) translateY(0);
}
.nav-submenu a {
  display: flex; align-items: flex-start; gap: 13px;
  padding: 11px 13px; border-radius: var(--r);
  font-family: var(--font-head); text-transform: uppercase; letter-spacing: 0.05em;
  font-size: 0.95rem; font-weight: 500; color: var(--ink-bright);
  transition: background 0.15s ease, color 0.15s ease;
}
.nav-submenu a:hover, .nav-submenu a:focus-visible { background: rgba(var(--accent-rgb), 0.10); color: var(--accent); }
.nav-submenu a[aria-current="page"] { color: var(--accent); }
.nav-submenu .smi-ico {
  width: 34px; height: 34px; flex: none; margin-top: 1px; border-radius: var(--r);
  display: inline-flex; align-items: center; justify-content: center;
  background: rgba(var(--accent-rgb), 0.10); border: 1px solid rgba(var(--accent-rgb), 0.35); color: var(--accent);
  transition: background 0.15s ease, border-color 0.15s ease;
}
.nav-submenu .smi-ico svg { width: 19px; height: 19px; }
.nav-submenu a:hover .smi-ico, .nav-submenu a:focus-visible .smi-ico { background: rgba(var(--accent-rgb), 0.18); border-color: var(--accent); }
.nav-submenu .smi-text { display: flex; flex-direction: column; gap: 2px; min-width: 0; }
.nav-submenu small {
  font-family: var(--font-body); text-transform: none; letter-spacing: 0;
  font-size: 0.82rem; font-weight: 400; line-height: 1.35; color: var(--muted);
}
.nav-submenu a:hover small, .nav-submenu a:focus-visible small { color: var(--muted); }
/* The "All services" row reads as a footer link inside the panel. */
.nav-submenu .smi-all {
  margin-top: 4px; padding-top: 12px; border-top: 1px solid var(--line);
  align-items: center; gap: 9px; font-size: 0.9rem; letter-spacing: 0.06em; color: var(--accent);
}
.nav-submenu .smi-all svg { width: 14px; height: 14px; transition: transform 0.18s ease; }
.nav-submenu .smi-all:hover svg, .nav-submenu .smi-all:focus-visible svg { transform: translateX(4px); }

/* ---------- Hero ---------- */
/* Full-bleed photo + dual-gradient overlay (operator loves the "looks designed"
   effect). The inner is a wide container holding a 2-column asymmetric layout:
   a roomy left copy column and a right testimonial card. Generous vertical
   padding lets the headline breathe instead of feeling boxed at 760px. */
.hero { position: relative; isolation: isolate; overflow: hidden; }
.hero::before {
  content: ""; position: absolute; inset: 0; z-index: -2;
  background: url("/assets/images/hero-electrical-panels.webp") center/cover no-repeat;
  transform: scale(1.02);
}
.hero::after {
  content: ""; position: absolute; inset: 0; z-index: -1;
  background:
    linear-gradient(90deg, rgba(13,13,13,0.94) 0%, rgba(13,13,13,0.80) 46%, rgba(13,13,13,0.55) 100%),
    linear-gradient(0deg, rgba(13,13,13,0.92) 0%, rgba(13,13,13,0.35) 55%, rgba(13,13,13,0.55) 100%);
}
.hero-inner {
  position: relative; max-width: 1200px;
  padding-block: clamp(64px, 9vh, 140px);
  display: grid; grid-template-columns: minmax(0, 1fr) clamp(330px, 26vw, 420px);
  column-gap: clamp(28px, 3vw, 52px); row-gap: 36px;
  align-items: center;
}
.hero-copy { position: relative; }
/* Subtle radial halo pooled behind the H1. A faint warm bloom lifts the
   headline off the photo without reading as a spotlight. Sits below the type. */
.hero-copy::before {
  content: ""; position: absolute; z-index: -1; pointer-events: none;
  left: -6%; top: clamp(20px, 5vw, 70px); width: min(620px, 92%); height: 360px;
  background: radial-gradient(58% 60% at 28% 42%, rgba(var(--accent-rgb), 0.14) 0%, rgba(var(--accent-rgb), 0.05) 42%, rgba(var(--accent-rgb), 0) 72%);
  filter: blur(6px);
}
.hero h1 { position: relative; text-shadow: 0 2px 18px rgba(0,0,0,0.55); font-size: calc(clamp(2.5rem, 1.4rem + 5vw, 5.5rem) * var(--font-head-scale, 1)); overflow-wrap: normal; }
.hero .eyebrow { text-shadow: 0 1px 8px rgba(0,0,0,0.6); }
.hero-sub {
  margin-top: 22px; max-width: 52ch;
  color: #E9EAEC; font-size: clamp(1.08rem, 1rem + 0.5vw, 1.35rem); line-height: 1.55;
  text-shadow: 0 1px 10px rgba(0,0,0,0.55); text-wrap: pretty;
}
.hero-actions { display: flex; flex-wrap: wrap; gap: 14px; margin-top: 32px; }

/* Power-up rule: an accent line under the eyebrow that energizes left to right
   on load and settles into a lit glow at its leading edge, like current
   reaching the end of a run. Plays once. Reduced-motion lands on the lit state. */
.hero-powerup { position: relative; height: 3px; width: clamp(120px, 22vw, 220px); margin: 2px 0 4px; border-radius: 2px; overflow: visible; }
.hero-powerup::before {
  content: ""; position: absolute; inset: 0; border-radius: 2px; transform-origin: left;
  background: linear-gradient(90deg, rgba(var(--accent-rgb),0.35) 0%, var(--accent) 60%, var(--accent-hi2) 100%);
  transform: scaleX(0); animation: powerup-race 1.05s cubic-bezier(0.22, 0.61, 0.36, 1) 0.15s forwards;
}
/* The spark/glow at the leading edge brightens as the line completes. */
.hero-powerup::after {
  content: ""; position: absolute; right: -3px; top: 50%; width: 12px; height: 12px;
  transform: translate(50%, -50%) scale(0); border-radius: 999px; background: var(--accent-hi2);
  box-shadow: 0 0 10px 3px rgba(var(--accent-rgb), 0.9), 0 0 22px 6px rgba(var(--accent-rgb), 0.45);
  animation: powerup-spark 0.5s ease-out 1.1s forwards;
}
@keyframes powerup-race { to { transform: scaleX(1); } }
@keyframes powerup-spark {
  0% { transform: translate(50%, -50%) scale(0); opacity: 0; }
  55% { transform: translate(50%, -50%) scale(1.15); opacity: 1; }
  100% { transform: translate(50%, -50%) scale(0.85); opacity: 0.9; }
}

/* Single-column hero (<=1200px): tablets and smaller laptops get just eyebrow +
   H1 + sub + the 2 CTAs, with the background visible and room to breathe. The
   two-column layout needs desktop width to keep "Electrical problems," on one
   line and the review card uncramped, so below 1200px it collapses to one
   column and the review + breaker pills are hidden so the screen isn't crowded. */
@media (max-width: 1200px) {
  /* Single-column hero. The hero is sized so it plus the trust-strip beneath it
     fill exactly one small viewport (100svh), which lands the trust strip at the
     bottom edge of the first screen on load. svh (small viewport height) is used
     so mobile browser chrome can't push the strip off-screen. The copy is a
     vertically centered flex column inside that taller hero, so the breathing
     room is balanced above and below the content rather than dumped at one end. */
  .hero {
    min-height: calc(100svh - var(--header-h) - var(--trust-h));
    display: flex;
  }
  .hero-inner {
    grid-template-columns: 1fr; row-gap: 0;
    display: flex; flex-direction: column; justify-content: center;
    width: 100%; min-height: inherit;
    padding-block: clamp(48px, 9vw, 96px);
  }
  .hero .hero-aside { display: none; }
}

/* Mobile-first hero rhythm (<=768px): phones get an intentionally airy layout,
   not a squeezed desktop. The content is still vertically centered in the tall
   100svh hero (from the <=1200px block above); here the internal spacing opens
   up so the eyebrow, headline, body, and CTAs each get room. Larger gaps between
   the H1 and the body, and between the body and the buttons, do most of the
   work; a min top pad guarantees breathing room above the eyebrow even when the
   content is taller than the centered track. */
@media (max-width: 768px) {
  /* Slightly tighter side padding here buys width for a bigger headline; the
     vertical spacing below carries the breathing room. */
  .hero-inner { padding-block: clamp(48px, 12vw, 104px); padding-inline: 16px; gap: 0; }
  /* Headline scales with the viewport so it is as large as possible while keeping
     "Electrical, handled" (a non-breaking unit) on one line without overflowing,
     from 375px up. */
  .hero h1 { font-size: calc(clamp(2.5rem, 11vw, 3.5rem) * var(--font-head-scale, 1)); line-height: 1.04; }
  /* Mobile hero LCP: swap to a 1080px-wide encode of the same panel-wall photo so
     phones download ~100 KiB instead of the 1920px desktop master. The matching
     media-scoped <link rel="preload"> in each page head fetches this variant. */
  .hero::before { background-image: url("/assets/images/hero-electrical-panels-1080.webp"); }
  .hero .eyebrow { margin-bottom: clamp(12px, 3.5vw, 20px); }
  .hero-sub { margin-top: clamp(30px, 7.5vw, 42px); }
  .hero-actions { margin-top: clamp(38px, 9vw, 54px); }
}

/* Hero glass testimonial card: a real review, surfaced above the fold. On
   desktop it occupies the right grid column, vertically centered against the
   copy. On mobile it is hidden so the first screen is just headline + CTAs. */
/* Right hero column: the review card with the four breaker badges stacked
   beneath it as a 2x2. Balances the headline + CTAs on the left and keeps the
   hero short. Hidden as a unit on mobile. */
.hero-aside {
  justify-self: end; width: 100%; max-width: 30rem;
  display: flex; flex-direction: column; gap: 16px; justify-content: center;
}
.hero-quote {
  width: 100%; margin: 0;
  background: rgba(20, 20, 20, 0.46);
  border: 1px solid rgba(255, 255, 255, 0.16); border-left: 3px solid var(--accent);
  border-radius: var(--r); padding: 22px 24px;
  backdrop-filter: saturate(140%) blur(10px);
  -webkit-backdrop-filter: saturate(140%) blur(10px);
  box-shadow: 0 12px 30px rgba(0, 0, 0, 0.38);
}
.hero-quote .stars { color: var(--accent); letter-spacing: 2px; font-size: 0.9rem; }
.hero-quote blockquote {
  margin: 8px 0 0; color: var(--ink-bright); font-size: 1.02rem; line-height: 1.5;
  text-shadow: 0 1px 6px rgba(0, 0, 0, 0.5);
}
.hero-quote .cite {
  margin-top: 12px; display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap;
  font-family: var(--font-head); text-transform: uppercase; letter-spacing: 0.05em;
}
.hero-quote .cite .name { color: var(--ink-bright); font-weight: 600; font-size: 0.92rem; }
.hero-quote .cite .src { color: var(--muted); font-size: 0.875rem; letter-spacing: 0.04em; }

/* breaker-style badges */
.badge-row { display: grid; grid-template-columns: 1fr 1fr; gap: 10px; margin-top: 0; }
.badge {
  display: flex; align-items: center; justify-content: center;
  white-space: nowrap; min-width: 0;
  font-family: var(--font-head); text-transform: uppercase; letter-spacing: 0.03em;
  font-size: calc(0.8rem * var(--font-head-scale, 1)); font-weight: 600; color: var(--ink-bright);
  padding: 8px 10px; border: 1px solid var(--line-strong); border-left: 3px solid var(--accent);
  border-radius: var(--r); background: rgba(20,20,20,0.55); backdrop-filter: blur(2px);
}

/* ---------- Trust strip (credential marquee) ---------- */
/* A slow, continuous credential marquee at every width: the track scrolls
   left forever, pauses on hover/focus, and the duplicated half (aria-hidden
   clones in markup) makes the loop seamless. Under prefers-reduced-motion the
   row falls back to a static, centered, wrapped layout. */
.trust-strip { background: var(--surface); border-block: 1px solid var(--line); overflow: hidden; }
.trust-inner {
  display: flex; flex-wrap: nowrap; align-items: center; justify-content: flex-start;
  width: max-content; padding-block: 18px;
  animation: trust-marquee 40s linear infinite;
}
/* Spacing lives on each child's right margin (not flex gap) so the two halves of
   the track are exactly equal width and translateX(-50%) loops with no jump.
   A flex gap would add an odd inter-group gap and shift the seam by half a gap. */
.trust-inner > span { margin-right: 26px; }
.trust-strip:hover .trust-inner,
.trust-strip:focus-within .trust-inner { animation-play-state: paused; }
.trust-item {
  display: inline-flex; align-items: center; gap: 9px; white-space: nowrap;
  font-family: var(--font-head); text-transform: uppercase; letter-spacing: 0.07em;
  font-size: 0.92rem; color: var(--muted);
}
.trust-item strong { color: var(--ink-bright); font-weight: 600; }
.trust-item .stars { color: var(--accent); letter-spacing: 1px; font-size: 0.95rem; }
/* Accent-dot separator between credentials (replaces the hairline rule). */
.trust-sep { width: 7px; height: 7px; border-radius: 999px; background: var(--accent); opacity: 0.85; flex: none; }
/* The duplicated track makes the loop seamless; it's always part of the scroll. */
.marquee-clone { display: inline-flex; }
span.trust-sep.marquee-clone { display: block; }
@keyframes trust-marquee {
  from { transform: translateX(0); }
  to   { transform: translateX(-50%); }
}
/* Reduced motion: stop the scroll and show the static credentials, wrapped and
   centered so every item is visible without animation. The clone half is hidden
   so each credential reads exactly once. */
@media (prefers-reduced-motion: reduce) {
  .trust-inner { animation: none !important; flex-wrap: wrap; width: auto; justify-content: center; gap: 14px 26px; padding-inline: var(--gutter); }
  .trust-inner > span { margin-right: 0; }
  .marquee-clone { display: none !important; }
}

/* ---------- Section header ---------- */
.section-head { max-width: 64ch; margin-bottom: clamp(32px, 4vw, 52px); }
.section-head .lede { margin-top: 14px; }
/* Centered section head: used wherever the content beneath it is centered (the
   review grids justify-content:center), so the eyebrow + h2 + lede sit centered
   over the cards instead of hanging left. */
.section-head--center { margin-inline: auto; text-align: center; }
.section-head--center .lede { margin-inline: auto; }
/* Prose measure utility: caps reading line length for editorial rhythm. */
.measure { max-width: 68ch; }

/* ---------- Services ---------- */
.grid { display: grid; gap: 18px; }
.grid-3 { grid-template-columns: repeat(auto-fit, minmax(282px, 1fr)); }
.card {
  position: relative;
  background: var(--surface); border: 1px solid var(--line); border-left: 3px solid var(--accent);
  border-radius: var(--r); padding: 28px 26px;
  transition: transform 0.2s cubic-bezier(0.22, 0.61, 0.36, 1), background 0.2s ease, border-color 0.2s ease, box-shadow 0.2s ease;
}
/* Card lift: rises on hover with a deepening shadow + a sharpening accent edge.
   Precise, not bouncy. The easing settles fast, like a breaker snapping home. */
.card:hover,
.card:focus-within {
  background: var(--surface-2); transform: translateY(-6px);
  border-color: var(--line-strong); border-left-color: var(--accent);
  box-shadow: 0 18px 38px rgba(0, 0, 0, 0.45), inset 0 0 0 1px rgba(var(--accent-rgb), 0.06);
}
.visually-hidden { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border: 0; }
.card h3 { font-size: 1.4rem; letter-spacing: 0.015em; }
.card p { color: var(--muted); margin-top: 10px; font-size: 0.98rem; }
.card-link {
  display: inline-flex; align-items: center; gap: 7px; margin-top: 16px;
  font-family: var(--font-head); text-transform: uppercase; letter-spacing: 0.06em;
  font-size: 0.875rem; font-weight: 600; color: var(--accent);
}
.card-link span { transition: transform 0.18s cubic-bezier(0.22, 0.61, 0.36, 1); }
.card:hover .card-link span,
.card:focus-within .card-link span { transform: translateX(5px); }
/* Make the whole service card clickable: the card-link is stretched over the
   entire card via an absolute overlay (the card is position:relative). Only
   cards that actually have a link get the pointer + overlay, so text-only cards
   (e.g. the About commitments) are unaffected. */
.card:has(.card-link) { cursor: pointer; }
.card-link::after { content: ""; position: absolute; inset: 0; z-index: 1; }

/* Cards that carry an inner photo (gallery / media cards): the image zooms
   inside its clipped frame as the card lifts. Cards without a .card-media
   are unaffected. Sackett's service cards are type-only by design. */
.card-media { overflow: hidden; border-radius: var(--r); margin: -28px -26px 22px; border-bottom: 1px solid var(--line); }
.card-media img { width: 100%; height: 100%; object-fit: cover; transition: transform 0.45s cubic-bezier(0.22, 0.61, 0.36, 1); }
.card:hover .card-media img,
.card:focus-within .card-media img { transform: scale(1.06); }

/* Service-card icon: a refined custom line glyph inside a depth-treated disc.
   The depth is built in three layers, not a flat fill: (1) a blurred shadow
   ring set beneath the disc, (2) the accent hairline ring on the disc edge,
   (3) a drop-shadow on the glyph itself so the stroke reads slightly raised.
   On hover the disc fills with accent and the ring blooms. */
.svc-icon {
  display: grid; place-items: center;
  width: 54px; height: 54px; margin-bottom: 18px;
  border-radius: 50%;
  background: radial-gradient(circle at 32% 28%, rgba(var(--accent-rgb), 0.16), rgba(var(--accent-rgb), 0.04) 70%), var(--surface-2);
  box-shadow:
    inset 0 0 0 1.5px rgba(var(--accent-rgb), 0.55),
    inset 0 1px 0 rgba(255, 255, 255, 0.06),
    0 8px 18px rgba(0, 0, 0, 0.5),
    0 0 0 6px rgba(var(--accent-rgb), 0.05);
  transition: background 0.22s ease, box-shadow 0.22s ease, transform 0.22s cubic-bezier(0.22, 0.61, 0.36, 1);
}
.svc-icon svg {
  width: 26px; height: 26px; color: var(--accent);
  filter: drop-shadow(0 1px 2px rgba(0, 0, 0, 0.55));
  transition: color 0.22s ease, filter 0.22s ease;
}
.card:hover .svc-icon,
.card:focus-within .svc-icon {
  transform: translateY(-2px);
  background: radial-gradient(circle at 32% 28%, var(--accent-hi), var(--accent) 70%);
  box-shadow:
    inset 0 0 0 1.5px rgba(var(--accent-rgb), 0.9),
    0 12px 24px rgba(0, 0, 0, 0.55),
    0 0 0 8px rgba(var(--accent-rgb), 0.1);
}
.card:hover .svc-icon svg,
.card:focus-within .svc-icon svg { color: var(--accent-on); filter: drop-shadow(0 1px 1px rgba(0, 0, 0, 0.25)); }

/* ---------- Split layout (text column beside an art-directed photo) ---------- */
/* Two columns on desktop: the prose/list on the left and the framed photo on
   the right, both top-aligned and stretched so the image runs the full height
   of the taller column. Collapses to a single column at <=860px (the image
   reorders above the text there, see the responsive block). */
.split {
  display: grid; grid-template-columns: 1.05fr 0.95fr;
  gap: clamp(28px, 5vw, 56px); align-items: stretch;
}
/* Grid items default to min-width:auto, which lets a large intrinsic image
   shove its track wider than the container (horizontal scroll). Pin both
   tracks to min-width:0 so the columns honor the fr sizing instead. */
.split > * { min-width: 0; }
/* In a split the media stretches to the taller column's full height, so it
   drops the fixed 3:2 box and fills the row; the image covers it. A min-height
   keeps it from collapsing if the text column is unusually short. */
.split > .split-media { height: 100%; aspect-ratio: auto; min-height: 320px; }

/* ---------- Framed images (split media, any art-directed photo) ---------- */
/* Every framed photo gets the same treatment: an inset hairline ring drawn on
   the inner edge (so the dark image meets the dark page through a defined line)
   plus an outer drop-glow that lifts the frame off the ground. The aspect ratio
   is fixed so the browser reserves the box and the layout never shifts (CLS).
   The grade runs darker + lower-saturation than camera-default: this is the
   Field Standard look (technical, high-contrast, no showroom cheer), and on the
   panel-cabinet photo it also sinks the third-party vest branding into shadow. */
.framed-image,
.split-media {
  position: relative; overflow: hidden; border-radius: var(--r);
  aspect-ratio: 3 / 2;
  box-shadow:
    inset 0 0 0 1px var(--line-strong),
    0 22px 46px rgba(0, 0, 0, 0.5),
    0 0 0 1px rgba(0, 0, 0, 0.5);
}
/* Split media zooms slowly when the whole split block is hovered. The push-in
   is calm and deliberate, no bounce. The corner bracket sits above the clip. */
.framed-image img,
.split-media img {
  width: 100%; height: 100%; object-fit: cover; border-radius: var(--r);
  filter: contrast(1.1) saturate(0.88) brightness(0.92);
  transition: transform 0.5s cubic-bezier(0.22, 0.61, 0.36, 1), filter 0.3s ease;
}
.split:hover .split-media img,
.framed-image:hover img { transform: scale(1.04); filter: contrast(1.12) saturate(0.95) brightness(0.96); }
/* Bottom-fade overlay: the image grades into the page ground at its lower edge,
   anchoring the accent corner-bracket and sinking busy detail into shadow. The
   second layer is a corner vignette weighted to the lower-left, where the stock
   photo carries a third-party vest logo. It is not ours to display, so the grade
   pushes it down toward black while the panel-work focal point stays readable. */
.framed-image::before,
.split-media::before {
  content: ""; position: absolute; inset: 0; z-index: 1; pointer-events: none;
  border-radius: var(--r);
  background:
    linear-gradient(0deg, rgba(15, 15, 15, 0.78) 0%, rgba(15, 15, 15, 0.28) 38%, rgba(15, 15, 15, 0) 64%),
    radial-gradient(120% 100% at 16% 96%, rgba(15, 15, 15, 0.62) 0%, rgba(15, 15, 15, 0) 46%);
}
.framed-image::after,
.split-media::after { content: ""; position: absolute; left: 10px; bottom: 10px; width: 78px; height: 78px; border-left: 3px solid var(--accent); border-bottom: 3px solid var(--accent); z-index: 2; }
.reasons { list-style: none; margin: 22px 0 0; padding: 0; display: grid; gap: 22px; }
.reasons li { display: grid; grid-template-columns: auto 1fr; gap: 16px; }
/* Reason index chip: outlined at rest, fills with accent + flips ink color on
   hover. This is the icon-morph-to-accent move, sized for a numeric marker. */
.reasons .num {
  font-family: var(--font-head); font-weight: 700; color: var(--accent); font-size: 1.4rem; line-height: 1;
  border: 1px solid var(--line-strong); border-radius: var(--r); width: 48px; height: 48px;
  display: inline-flex; align-items: center; justify-content: center;
  transition: background 0.2s ease, color 0.2s ease, border-color 0.2s ease, box-shadow 0.2s ease;
}
.reasons li:hover .num {
  background: var(--accent); color: var(--accent-on); border-color: var(--accent);
  box-shadow: 0 8px 20px rgba(var(--accent-rgb), 0.22);
}
.reasons h3 { font-size: 1.22rem; }
.reasons p { color: var(--muted); margin-top: 5px; font-size: 0.98rem; }

/* ---------- Reviews ---------- */
/* Flexbox so a trailing partial row centers instead of orphaning to the left.
   Cards flex from a 312px basis up to ~400px. Applies on home, service-detail,
   and about review grids alike. */
.reviews-grid { display: flex; flex-wrap: wrap; justify-content: center; }
/* Flex cards from a 312px basis up to 400px, min-width:0 so long-quote cards
   can shrink to the basis. A trailing partial row now centers instead of
   orphaning to the left (the operator's reported issue on home, service-detail,
   and about review grids alike). */
.reviews-grid .review { flex: 1 1 300px; max-width: 380px; min-width: 0; margin: 0; }
.review {
  background: var(--surface); border: 1px solid var(--line); border-left: 3px solid var(--accent);
  border-radius: var(--r); padding: 26px 24px; display: flex; flex-direction: column;
  transition: transform 0.2s cubic-bezier(0.22, 0.61, 0.36, 1), background 0.2s ease, box-shadow 0.2s ease, border-color 0.2s ease;
}
.review:hover { transform: translateY(-5px); background: var(--surface-2); border-color: var(--line-strong); box-shadow: 0 16px 34px rgba(0, 0, 0, 0.42); }
.review .stars { color: var(--accent); letter-spacing: 2px; font-size: 1rem; margin-bottom: 12px; }
.review blockquote { margin: 0; color: var(--ink); font-size: 1rem; line-height: 1.6; }
.review .cite { margin-top: 16px; display: flex; align-items: baseline; gap: 8px; flex-wrap: wrap; }
.review .cite .name { font-family: var(--font-head); text-transform: uppercase; letter-spacing: 0.05em; font-weight: 600; color: var(--ink-bright); font-size: 0.95rem; }
.review .cite .src { color: var(--muted); font-size: 0.875rem; }

/* Service-detail review band: the default section padding read as cavernous
   above "What customers say" and under the cards, so this trims the vertical
   rhythm to a tighter block. */
.reviews-tight { padding-block: clamp(40px, 5vw, 64px); }
.reviews-tight .section-head { margin-bottom: clamp(24px, 3vw, 36px); }

/* ---------- FAQ ---------- */
/* The FAQ section is centered in its column: the heading block centers its text
   and the accordion sits as a centered 820px column. Rows keep their text
   left-aligned inside that centered block for readability. */
#faq .section-head { margin-inline: auto; text-align: center; }
#faq .section-head .lede { margin-inline: auto; }
.faq { max-width: 820px; margin-inline: auto; }
.faq details { border-bottom: 1px solid var(--line); }
.faq summary {
  list-style: none; cursor: pointer; padding: 22px 60px 22px 0; position: relative;
  font-family: var(--font-head); text-transform: uppercase; letter-spacing: 0.02em;
  font-size: clamp(1.1rem, 1rem + 0.5vw, 1.4rem); color: var(--ink-bright);
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary:hover { color: var(--accent); }
/* Circular accent toggle: CSS-drawn cross that morphs to a minus on open.
   No default <details> triangle, no glyph font dependency. */
.faq summary .faq-toggle {
  position: absolute; right: 4px; top: 50%; transform: translateY(-50%);
  width: 38px; height: 38px; border-radius: 999px;
  border: 1px solid var(--line-strong); background: rgba(var(--accent-rgb), 0.07);
  transition: background 0.2s ease, border-color 0.2s ease;
}
.faq summary .faq-toggle::before,
.faq summary .faq-toggle::after {
  content: ""; position: absolute; left: 50%; top: 50%; background: var(--accent);
  border-radius: 1px; transition: transform 0.22s ease, opacity 0.22s ease;
}
.faq summary .faq-toggle::before { width: 14px; height: 2px; transform: translate(-50%, -50%); }   /* horizontal bar */
.faq summary .faq-toggle::after  { width: 2px; height: 14px; transform: translate(-50%, -50%); }   /* vertical bar (the +) */
.faq summary:hover .faq-toggle { background: rgba(var(--accent-rgb), 0.16); border-color: var(--accent); }
.faq details[open] summary .faq-toggle { background: var(--accent); border-color: var(--accent); }
.faq details[open] summary .faq-toggle::before { background: var(--accent-on); }
.faq details[open] summary .faq-toggle::after { transform: translate(-50%, -50%) rotate(90deg); opacity: 0; }  /* morph + → − */
.faq details p { color: var(--muted); padding: 0 0 24px; max-width: 70ch; }

/* ---------- CTA band ---------- */
.cta-band { background: var(--surface); border-top: 4px solid var(--accent); }
.cta-band .container { text-align: center; }
.cta-band h2 { margin-bottom: 14px; }
.cta-band .lede { margin: 0 auto 28px; }
.cta-actions { display: flex; flex-wrap: wrap; gap: 14px; justify-content: center; }
/* Trust line under every CTA-band button pair: only claims Sackett actually
   carries (real-person answer, licensed/code-compliant, verified Google rating). */
.cta-trust { display: flex; flex-wrap: wrap; align-items: center; justify-content: center; gap: 10px 18px; margin-top: 22px; font-family: var(--font-head); text-transform: uppercase; letter-spacing: 0.05em; font-size: 0.875rem; color: var(--muted); }
.cta-trust .ct-item { display: inline-flex; align-items: center; gap: 7px; }
.cta-trust strong { color: var(--ink-bright); font-weight: 600; }
.cta-trust .stars { color: var(--accent); letter-spacing: 0.05em; }
.cta-trust .ct-sep { width: 5px; height: 5px; border-radius: 50%; background: var(--accent); opacity: 0.8; }
@media (max-width: 560px) { .cta-trust .ct-sep { display: none; } }

/* ---------- Footer ---------- */
.site-footer { background: var(--bg-deep); border-top: 1px solid var(--line); padding-block: clamp(48px, 6vw, 72px) 0; }
.footer-grid { display: grid; grid-template-columns: 1.4fr 1fr 1fr 1.2fr; gap: 36px; }
.footer-brand img { height: 40px; width: auto; margin-bottom: 16px; }
.footer-brand p { color: var(--muted); font-size: 0.94rem; max-width: 32ch; }
.footer-col h3 { font-size: 1rem; letter-spacing: 0.14em; color: var(--accent); margin-bottom: 16px; position: relative; padding-bottom: 12px; }
.footer-col h3::after { content: ""; position: absolute; left: 0; bottom: 0; width: 26px; height: 2px; background: var(--accent); opacity: 0.55; }
.footer-col ul { list-style: none; margin: 0; padding: 0; display: grid; gap: 10px; }
.footer-col a, .footer-col .muted { color: var(--muted); font-size: 0.95rem; transition: color 0.16s ease; }
.footer-col a:hover { color: var(--accent); }
.footer-phone { font-family: var(--font-head); font-size: 1.5rem; color: var(--ink-bright); letter-spacing: 0.01em; }
.footer-bottom {
  margin-top: clamp(36px, 5vw, 56px); border-top: 1px solid var(--line);
  padding-block: 22px; display: flex; flex-wrap: wrap; gap: 10px 24px; justify-content: space-between; align-items: center;
}
.footer-bottom { color: var(--muted); font-size: 0.875rem; }
/* The "Built by" credit is a real link, so its hit area is a >=44px-tall tap
   target. inline-flex keeps it inline with the surrounding text run. */
.footer-bottom a { display: inline-flex; align-items: center; min-height: 44px; color: var(--accent); font-size: 0.875rem; }
.footer-bottom a:hover { color: var(--accent); text-decoration: underline; }

/* ---------- Sub-hero (interior pages) ---------- */
/* Base is flat deep ground; the services hub + 3 service-detail pages get a
   dark photo background via .subhero--image (see below) so they read as
   designed rather than blank. The bottom accent rule is the power-up element:
   it races left to right on load and glows at its leading edge. */
.subhero { background: var(--bg-deep); border-bottom: 1px solid var(--line); position: relative; isolation: isolate; overflow: hidden; }
/* The animated power-up rule. Width is tuned per page below; the fill scales in
   from the left and a spark glows at the leading edge once it completes. */
.subhero::after {
  content: ""; position: absolute; left: 0; bottom: -1px; height: 3px; width: 100%;
  background: var(--accent); transform: scaleX(0); transform-origin: left;
  animation: powerup-race 1.0s cubic-bezier(0.22, 0.61, 0.36, 1) 0.2s forwards;
  box-shadow: 6px 0 12px -2px rgba(var(--accent-rgb), 0); border-radius: 0 2px 2px 0;
}
.subhero-inner { position: relative; padding-block: clamp(40px, 7vw, 84px); max-width: 820px; }
.subhero h1 { margin-top: 12px; }
.subhero .lede { margin-top: 16px; }

/* Subhero with a dark photo background, layered exactly like the home hero so
   the photo reads through (texture + depth) while the heading still holds AA
   contrast: a real photo layer on ::before (z -2) and a dual dark gradient on a
   dedicated overlay layer (.subhero__scrim, z -1). No solid base color sits over
   the photo, so the image is visibly present but clearly secondary to the text.
   The per-page background-image is set on ::before below (one image per page). */
.subhero--image { border-bottom-color: var(--line-strong); }
.subhero--image::before {
  content: ""; position: absolute; inset: 0; z-index: -2;
  background: var(--bg-deep) url("/assets/images/hero-electrical-panels.webp") center/cover no-repeat;
  transform: scale(1.02);
}
/* Dark dual-gradient scrim: a left-weighted horizontal wash keeps the copy
   column legible while the right edge of the photo stays lighter (depth), plus
   a bottom-up grade so the accent rule and any busy detail sink into shadow.
   Tuned so the eyebrow/H1/lede clear WCAG AA on every service photo. */
.subhero--image .subhero__scrim {
  content: ""; position: absolute; inset: 0; z-index: -1; pointer-events: none;
  background:
    linear-gradient(90deg, rgba(13,13,13,0.90) 0%, rgba(13,13,13,0.74) 48%, rgba(13,13,13,0.50) 100%),
    linear-gradient(0deg, rgba(13,13,13,0.86) 0%, rgba(13,13,13,0.30) 52%, rgba(13,13,13,0.48) 100%);
}
.subhero--image .eyebrow { text-shadow: 0 1px 8px rgba(0,0,0,0.8); }
.subhero--image h1 { text-shadow: 0 2px 18px rgba(0,0,0,0.72); }
.subhero--image .lede { color: #EAEBED; text-shadow: 0 1px 10px rgba(0,0,0,0.7); }
/* On narrow screens the copy column spans the full width, so the horizontal
   wash can't lean on a left bias. Deepen the overlay uniformly for mobile AA. */
@media (max-width: 700px) {
  .subhero--image .subhero__scrim {
    background:
      linear-gradient(90deg, rgba(13,13,13,0.90) 0%, rgba(13,13,13,0.82) 100%),
      linear-gradient(0deg, rgba(13,13,13,0.88) 0%, rgba(13,13,13,0.55) 60%, rgba(13,13,13,0.70) 100%);
  }
}
/* The glow lands when the rule finishes racing. Shared by hero + subhero. */
.subhero::after { animation-name: powerup-race, powerup-glow; animation-duration: 1.0s, 0.5s; animation-delay: 0.2s, 1.1s; animation-timing-function: cubic-bezier(0.22,0.61,0.36,1), ease-out; animation-fill-mode: forwards, forwards; }
@keyframes powerup-glow {
  from { box-shadow: 6px 0 12px -2px rgba(var(--accent-rgb), 0); }
  60% { box-shadow: 8px 0 16px -1px rgba(var(--accent-rgb), 0.85); }
  to { box-shadow: 6px 0 12px -2px rgba(var(--accent-rgb), 0.4); }
}

.breadcrumb { display: flex; flex-wrap: wrap; gap: 8px; align-items: center; font-size: 0.875rem; color: var(--muted); font-family: var(--font-head); text-transform: uppercase; letter-spacing: 0.08em; }
.breadcrumb a { color: var(--muted); }
.breadcrumb a:hover { color: var(--accent); }
.breadcrumb span.sep { color: var(--line-strong); }
.breadcrumb [aria-current] { color: var(--ink-bright); }

/* ---------- Prose / content ---------- */
.prose { max-width: 70ch; }
.prose > * + * { margin-top: 1.1em; }
.prose h2 { margin-top: 1.6em; }
.prose h3 { margin-top: 1.4em; font-size: 1.3rem; }
.prose p, .prose li { color: var(--muted); }
.prose strong { color: var(--ink); }
.prose ul { margin: 0; padding-left: 0; list-style: none; display: grid; gap: 12px; }
.prose ul li { position: relative; padding-left: 30px; }
.prose ul li::before { content: ""; position: absolute; left: 0; top: 0.55em; width: 12px; height: 12px; border-left: 2px solid var(--accent); border-bottom: 2px solid var(--accent); transform: rotate(-45deg) translateY(-2px); }

/* ---------- Process steps ---------- */
.steps { counter-reset: step; list-style: none; margin: 0; padding: 0; display: grid; gap: 18px; }
/* Step card carries a gradient top-bar that wipes in from the left on hover
   (the audience/feature-card "gradient top-bar reveal" move, re-grounded for a
   process list). The card also lifts a touch with a sharpening shadow. */
.steps li {
  counter-increment: step; position: relative; overflow: hidden;
  display: grid; grid-template-columns: auto 1fr; gap: 16px;
  background: var(--surface); border: 1px solid var(--line); border-left: 3px solid var(--accent);
  border-radius: var(--r); padding: 22px 24px;
  transition: transform 0.2s cubic-bezier(0.22, 0.61, 0.36, 1), box-shadow 0.2s ease, background 0.2s ease;
}
.steps li::after {
  content: ""; position: absolute; left: 0; right: 0; top: 0; height: 3px;
  background: linear-gradient(90deg, var(--accent) 0%, var(--accent-hi) 60%, transparent 100%);
  transform: scaleX(0); transform-origin: left; transition: transform 0.3s cubic-bezier(0.22, 0.61, 0.36, 1);
}
.steps li:hover { background: var(--surface-2); transform: translateY(-4px); box-shadow: 0 16px 34px rgba(0, 0, 0, 0.4); }
.steps li:hover::after { transform: scaleX(1); }
.steps li::before { content: counter(step); font-family: var(--font-head); font-weight: 700; color: var(--accent-on); background: var(--accent); width: 38px; height: 38px; border-radius: var(--r); display: inline-flex; align-items: center; justify-content: center; font-size: 1.2rem; transition: box-shadow 0.2s ease; }
.steps li:hover::before { box-shadow: 0 6px 16px rgba(var(--accent-rgb), 0.3); }
.steps h3 { font-size: 1.18rem; }
.steps p { color: var(--muted); margin-top: 4px; font-size: 0.98rem; }

/* Services-hub "How we work": constrained to a centered column rather than
   spanning the full page width, with a centered heading block. The step rows
   keep their left-aligned content inside the narrower column. */
.how-we-work .section-head { max-width: 780px; margin-inline: auto; text-align: center; }
.how-we-work .section-head .lede { margin-inline: auto; }
.how-we-work .steps { max-width: 780px; margin-inline: auto; }

/* ---------- Two-column layouts ---------- */
.two-col { display: grid; grid-template-columns: 1.3fr 0.7fr; gap: clamp(28px, 5vw, 56px); align-items: center; }

/* ---------- Contact / forms ---------- */
/* Gradient top accent bar (matches the brand button's power-yellow gradient)
   sits flush on the top edge of the form card. Reused by .form-expect below. */
.form { position: relative; background: var(--surface); border: 1px solid var(--line); border-radius: var(--r); padding: clamp(24px, 4vw, 36px); overflow: hidden; }
.form::before { content: ""; position: absolute; inset: 0 0 auto 0; height: 4px; background: linear-gradient(90deg, var(--accent-hi) 0%, var(--accent) 52%, var(--accent-lo) 100%); }
/* Expectation-setter: three short lines that tell a worried caller exactly what
   happens after they hit send. Sits above the fields. */
.form-expect { margin: 4px 0 22px; padding-bottom: 18px; border-bottom: 1px solid var(--line); }
.form-expect ul { list-style: none; display: grid; gap: 9px; }
.form-expect li { display: flex; align-items: center; gap: 11px; font-family: var(--font-head); text-transform: uppercase; letter-spacing: 0.04em; font-size: 0.98rem; color: var(--ink-bright); }
.form-expect svg { width: 18px; height: 18px; flex: none; color: var(--accent); }
.field { display: flex; flex-direction: column; gap: 7px; margin-bottom: 18px; }
.field-row { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
.field label { font-family: var(--font-head); text-transform: uppercase; letter-spacing: 0.06em; font-size: 0.875rem; color: var(--ink-bright); }
.field input, .field select, .field textarea {
  background: var(--bg); border: 1px solid var(--line-strong); border-radius: var(--r); color: var(--ink);
  font-family: var(--font-body); font-size: 1rem; padding: 13px 14px; width: 100%; min-height: 50px;
}
.field textarea { min-height: 120px; resize: vertical; }
/* Plain :focus (mouse + keyboard) replaces the default outline with an accent
   border plus a soft glow, never a bare outline removal. Keyboard users get the
   stronger 4px ring from the .field ...:focus-visible rule above. */
.field input:focus, .field select:focus, .field textarea:focus { outline: 2px solid transparent; border-color: var(--accent); box-shadow: 0 0 0 2px rgba(var(--accent-rgb),0.25); }
.field input::placeholder, .field textarea::placeholder { color: #6f7680; }
.form .btn { width: 100%; margin-top: 4px; }
.form__success { padding: 16px 18px; margin-top: 16px; border-radius: var(--r); background: rgba(var(--accent-rgb),0.12); border: 1px solid var(--accent); color: var(--ink-bright); font-weight: 500; }
.form-note { color: var(--muted); font-size: 0.875rem; margin-top: 14px; }
.hp-field { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

.contact-card { background: var(--surface); border: 1px solid var(--line); border-left: 3px solid transparent; border-radius: var(--r); padding: 26px 24px; transition: border-left-color 0.2s ease, background 0.2s ease, box-shadow 0.2s ease; }
.contact-card:hover { border-left-color: var(--accent); background: var(--surface-2); box-shadow: 0 12px 28px rgba(0, 0, 0, 0.34); }
.contact-card + .contact-card { margin-top: 18px; }
.contact-card h3 { font-size: 1.15rem; margin-bottom: 8px; }
.contact-card p, .contact-card a:not(.btn) { color: var(--muted); font-size: 0.96rem; }
.contact-card a:not(.btn):hover { color: var(--accent); }
/* The phone number is the primary CTA in these asides, so its link is a full
   >=44px-tall tap target. inline-flex keeps it hugging its text width (it stays
   left-aligned, visual size unchanged) while guaranteeing the touch height. */
.contact-phone { display: inline-flex; align-items: center; min-height: 44px; font-family: var(--font-head); font-size: 1.7rem; color: var(--ink-bright) !important; letter-spacing: 0.01em; }

/* ---------- Sticky mobile CTA bar ---------- */
/* The sticky header already carries a Call button at all times, so there is no
   desktop floating pill (it tripled the CTA on load). On mobile a bottom bar
   takes over the conversion job, but it stays hidden on load and reveals after
   a short scroll (forms.js toggles .is-visible past ~60vh / 500px). It starts
   translated below the fold and slides up; reduced-motion just toggles it on. */
.sticky-cta {
  display: none;
  position: fixed; left: 0; right: 0; bottom: 0; z-index: 95;
  gap: 10px; padding: 10px 14px calc(10px + env(safe-area-inset-bottom));
  background: rgba(15, 15, 15, 0.96); border-top: 1px solid var(--line-strong);
  backdrop-filter: blur(8px); -webkit-backdrop-filter: blur(8px);
  box-shadow: 0 -8px 22px rgba(0, 0, 0, 0.4);
  transform: translateY(110%); transition: transform 0.32s cubic-bezier(0.22, 0.61, 0.36, 1);
  will-change: transform;
}
.sticky-cta.is-visible { transform: translateY(0); }
.sticky-cta .btn { flex: 1; min-height: 50px; padding: 12px 14px; font-size: 0.98rem; }
@media (prefers-reduced-motion: reduce) {
  .sticky-cta { transition: none; transform: none; visibility: hidden; }
  .sticky-cta.is-visible { visibility: visible; }
}

/* Emergency callout */
.alert-band { background: var(--accent); color: var(--accent-on); }
.alert-band .container { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 16px; padding-block: 22px; }
.alert-band p { font-family: var(--font-head); text-transform: uppercase; letter-spacing: 0.04em; font-size: clamp(1.1rem, 1rem + 0.6vw, 1.5rem); font-weight: 700; }
.alert-band .btn { background: var(--accent-on); color: var(--accent); border-color: var(--accent-on); }
.alert-band .btn:hover { background: #000; border-color: #000; }

/* ---------- Responsive ---------- */
@media (max-width: 860px) {
  .nav, .header-cta .btn-ghost { display: none; }
  .nav-toggle { display: inline-flex; }
  /* Sticky mobile CTA takes over the conversion job at touch widths. It reveals
     on scroll (see .is-visible above), so it is not on the screen at load. */
  .sticky-cta { display: flex; }
  .site-footer { padding-bottom: 88px; }
  .site-header.open .nav {
    display: flex; flex-direction: column; align-items: flex-start; gap: 4px;
    position: absolute; left: 0; right: 0; top: 100%; margin: 0; padding: 12px var(--gutter) 22px;
    background: var(--bg-deep); border-bottom: 1px solid var(--line-strong);
    box-shadow: 0 18px 30px rgba(0,0,0,0.45);
  }
  /* Mobile nav links are full-width tap targets: ≥48px tall so a thumb lands
     cleanly on each row of the open menu. */
  .site-header.open .nav a { display: flex; align-items: center; min-height: 48px; padding: 12px 0; width: 100%; font-size: 1.1rem; }

  /* Services dropdown on mobile: the desktop floating panel is dropped and the
     three service sub-links plus "All services" render inline as their own
     indented rows under the Services trigger, each a ≥48px tap target. The
     chevron + hover-bridge + icons/descriptors are hidden so the open menu
     stays simple and thumb-friendly. */
  .site-header .nav-item, .site-header .nav-item--has-dropdown { display: block; width: 100%; }
  .site-header.open .nav .nav-chevron { display: none; }
  .site-header.open .nav .nav-submenu {
    position: static; transform: none; opacity: 1; visibility: visible; pointer-events: auto;
    min-width: 0; margin: 0 0 6px; padding: 0 0 0 16px; gap: 0;
    background: none; border: 0; border-left: 2px solid var(--line-strong); box-shadow: none;
  }
  .site-header.open .nav .nav-submenu::before { display: none; }
  .site-header.open .nav .nav-submenu .smi-ico { display: none; }
  .site-header.open .nav .nav-submenu small { display: none; }
  .site-header.open .nav .nav-submenu a { padding: 10px 0; font-size: 1rem; color: var(--muted); }
  .site-header.open .nav .nav-submenu a[aria-current="page"] { color: var(--accent); }
  .site-header.open .nav .nav-submenu .smi-all { border-top: 0; padding-top: 10px; margin-top: 0; }
  /* Right-edge control cluster: the .header-cta (now just the phone-icon call
     button, since the ghost button is hidden) gets pushed to the right with
     margin-left:auto, then the hamburger sits immediately after it as a tight
     pair. The base .nav-toggle margin-left:auto is dropped so the free space no
     longer splits between the two and opens a wide gap. The .header-inner flex
     gap is 20px between these two children; a -10px left margin on the toggle
     nets that down to a tight 10px pair gap without affecting the logo spacing. */
  .header-cta { margin-left: auto; gap: 10px; }
  .header-call { padding: 0; width: 50px; min-width: 50px; }
  .header-call .call-label { display: none; }
  .header-call .phone-ico { display: block; }
  .nav-toggle { margin-left: -10px; }
  .split { grid-template-columns: 1fr; }
  .split-media { order: -1; }
  .two-col { grid-template-columns: 1fr; }
  .footer-grid { grid-template-columns: 1fr 1fr; }
  /* On touch layouts the footer link lists open up so each link is a
     comfortable ≥48px-tall tap target instead of a cramped text row. A
     min-width floor guarantees even the shortest label (e.g. "About") clears
     44px wide; links stay left-aligned, longer labels size to their text. */
  .footer-col ul { gap: 4px; }
  .footer-col li a { display: inline-flex; align-items: center; min-height: 48px; min-width: 44px; }
  .footer-col li.muted { min-height: 32px; display: flex; align-items: center; }
}
@media (max-width: 540px) {
  .hero-actions .btn, .cta-actions .btn { width: 100%; }
  /* Keep two columns on phones so the footer is roughly half as tall; the brand
     block spans the full width above the link columns. */
  .footer-grid { grid-template-columns: 1fr 1fr; gap: 26px 20px; }
  .footer-brand { grid-column: 1 / -1; }
  .trust-sep { display: none; }
  .field-row { grid-template-columns: 1fr; }
}

/* ============================================================
   Wave 5: Cross-page distinctiveness
   Each interior page gets its own subhero rhythm so no two
   pages read as the same template with the words swapped. The
   shared .subhero stays the base; per-page body classes tune
   padding, H1 scale, sub-copy width, and the accent rule. Plus
   three signature blocks, one per service-detail page, so each
   detail page carries a distinguishing visual the others don't.
   ============================================================ */

/* --- Per-page subhero rhythm --- */
/* Services hub: widest, most open subhero (it's the index of everything). */
.page-services .subhero-inner { padding-block: clamp(48px, 8vw, 100px); max-width: 880px; }
/* Match the base H1 floor + vw at small viewports so the long word "businesses"
   can't overflow at 430px; only the upper clamp bound is raised for desktop scale. */
.page-services .subhero h1 { font-size: clamp(2.35rem, 1.35rem + 4.6vw, 5.4rem); }
.page-services .subhero .lede { max-width: 64ch; }

/* About: tighter, more editorial. Narrower measure, a calmer accent rule. The
   H1 upper bound is trimmed so the second line ("you can actually reach") fits
   on one line inside the 760px measure instead of breaking awkwardly; the floor
   and vw term match the base so it never overflows on small screens. */
.page-about .subhero-inner { padding-block: clamp(44px, 7vw, 88px); max-width: 760px; }
.page-about .subhero h1 { font-size: clamp(2.35rem, 1.35rem + 4.6vw, 4.25rem); }
.page-about .subhero .lede { max-width: 54ch; }
.page-about .subhero::after { height: 2px; }

/* Contact: compact subhero (the form is the point, get to it fast). The H1 keeps
   the base floor + vw at small viewports (so "ELECTRICAL SERVICE" never overflows
   430px) and only trims the upper bound to read tighter than the hub on desktop. */
.page-contact .subhero-inner { padding-block: clamp(36px, 5.5vw, 68px); max-width: 720px; }
.page-contact .subhero h1 { font-size: clamp(2.35rem, 1.35rem + 4.6vw, 4.2rem); }
.page-contact .subhero .lede { max-width: 52ch; }

/* Emergency: most urgent. Full-width accent rule. H1 holds the base floor + vw at
   small viewports so "AN ELECTRICAL SAFETY ISSUE?" never overflows 430px; only the
   upper bound is raised so it reads heaviest on desktop. */
.page-emergency .subhero-inner { padding-block: clamp(40px, 6vw, 76px); max-width: 800px; }
.page-emergency .subhero h1 { font-size: clamp(2.35rem, 1.35rem + 4.6vw, 5.2rem); }
.page-emergency .subhero::after { height: 4px; width: 100%; }

/* Service-detail pages share a rhythm with each other but differ from the hub:
   slightly tighter top, and each detail page leads with its own accent-rule
   width so the three details aren't pixel-identical at the top either. */
.page-detail .subhero-inner { padding-block: clamp(40px, 6.5vw, 80px); max-width: 800px; }

/* Per-page subhero photography. Each service page gets its own image so no two
   read as the same template, set on the .subhero--image photo layer (::before).
   The services hub keeps the panel-wall hero; the three detail pages each carry
   a distinct on-brand jobsite photo. */
.page-services .subhero--image::before { background-image: url("/assets/images/hero-electrical-panels.webp"); }
.page-panel .subhero--image::before { background-image: url("/assets/images/panel-diagnostic.webp"); }
.page-residential .subhero--image::before { background-image: url("/assets/images/jobsite-wiring.webp"); }
.page-commercial .subhero--image::before { background-image: url("/assets/images/commercial-electrical.webp"); }
.page-ev .subhero--image::before { background-image: url("/assets/images/ev-charger.webp"); }
.page-fixtures .subhero--image::before { background-image: url("/assets/images/light-fixtures.webp"); }
.page-code .subhero--image::before { background-image: url("/assets/images/code-compliance.webp"); }

/* Mobile: serve 1080px-wide subhero variants to cut LCP on phones (mirrors the home hero) */
@media (max-width: 768px) {
  .page-services .subhero--image::before { background-image: url("/assets/images/hero-electrical-panels-1080.webp"); }
  .page-panel .subhero--image::before { background-image: url("/assets/images/panel-diagnostic-1080.webp"); }
  .page-residential .subhero--image::before { background-image: url("/assets/images/jobsite-wiring-1080.webp"); }
  .page-commercial .subhero--image::before { background-image: url("/assets/images/commercial-electrical-1080.webp"); }
  .page-ev .subhero--image::before { background-image: url("/assets/images/ev-charger-1080.webp"); }
  .page-fixtures .subhero--image::before { background-image: url("/assets/images/light-fixtures-1080.webp"); }
  .page-code .subhero--image::before { background-image: url("/assets/images/code-compliance-1080.webp"); }
}

/* --- Signature block: Panel-repair "warning signs" flip cards --- */
/* A grid of interactive flip cards (3 cols desktop / 2 tablet / 1 mobile), each
   a symptom that flips on click to reveal why it matters + what Sackett does.
   The flipping element is a real <button> (.flip-card__inner) so it is keyboard
   operable and screen-reader announced via aria-expanded. Under reduced motion
   the 3D rotation is dropped and the back face simply replaces the front. The
   grid is centered/constrained so it never reads as an awkward full-bleed. */
.flip-grid {
  display: grid; grid-template-columns: repeat(3, 1fr); gap: 16px;
  margin: 4px 0 0; padding: 0; list-style: none;
}
.flip-card { perspective: 1400px; }
/* The card is a fixed-height button so front and back share one footprint and
   the grid rows stay even regardless of which cards are flipped. */
.flip-card__inner {
  position: relative; width: 100%; min-height: 188px;
  background: transparent; border: 0; padding: 0; margin: 0;
  font: inherit; color: inherit; text-align: left; cursor: pointer;
  transform-style: preserve-3d; will-change: transform;
  transition: transform 0.6s cubic-bezier(0.65, 0, 0.35, 1);
}
/* Flip on hover + keyboard focus (the primary, no-click interaction the operator
   wants); aria-expanded (tap) is kept so touch devices without hover can flip too. */
.flip-card__inner:focus-visible,
.flip-card__inner[aria-expanded="true"] { transform: rotateY(180deg); }
/* Hover-flip only on real pointer devices. Touch devices (hover: none) flip on
   tap via aria-expanded, so a card never sticks in a half-hovered state. */
@media (hover: hover) {
  .flip-card__inner:hover { transform: rotateY(180deg); }
  .flip-card__inner:hover .flip-card__face--front { background: var(--surface-2); border-color: var(--line-strong); box-shadow: 0 16px 34px rgba(0,0,0,0.42); }
  .flip-card__inner:hover .flip-card__hint svg { transform: rotate(180deg); }
}
.flip-card__face {
  position: absolute; inset: 0; -webkit-backface-visibility: hidden; backface-visibility: hidden;
  display: flex; flex-direction: column; gap: 12px;
  background: var(--surface); border: 1px solid var(--line); border-left: 3px solid var(--accent);
  border-radius: var(--r); padding: 22px 22px;
  transition: background 0.18s ease, box-shadow 0.18s ease, border-color 0.18s ease;
}
.flip-card__face--front { justify-content: flex-start; }
.flip-card__face--back { transform: rotateY(180deg); justify-content: center; overflow: auto; }
.flip-card__inner:focus-visible .flip-card__face { background: var(--surface-2); border-color: var(--line-strong); box-shadow: 0 16px 34px rgba(0,0,0,0.42); }
.flip-card .sig {
  width: 38px; height: 38px; flex: none; border-radius: var(--r);
  display: inline-flex; align-items: center; justify-content: center;
  background: rgba(var(--accent-rgb),0.12); border: 1px solid rgba(var(--accent-rgb),0.4); color: var(--accent);
}
.flip-card .sig svg { width: 20px; height: 20px; }
.flip-card__face--front h3 { font-size: 1.14rem; line-height: 1.15; }
/* The "flip for detail" affordance sits at the bottom of the front face. */
.flip-card__hint {
  margin-top: auto; display: inline-flex; align-items: center; gap: 7px;
  font-family: var(--font-head); text-transform: uppercase; letter-spacing: 0.06em;
  font-size: 0.875rem; font-weight: 600; color: var(--accent);
}
.flip-card__hint svg { width: 14px; height: 14px; transition: transform 0.2s ease; }
.flip-card__face--back h3 { font-size: 1rem; color: var(--accent); margin-bottom: 2px; }
.flip-card__face--back p { color: var(--ink); font-size: 0.92rem; line-height: 1.5; }
@media (max-width: 900px) { .flip-grid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 560px) { .flip-grid { grid-template-columns: 1fr; } }
/* On the narrowest phones the longest back-face copy wraps to an extra line and
   would otherwise need the back face's overflow-auto scrollbar; give the card a
   touch more height there so every flipped card shows its full text at a glance. */
@media (max-width: 360px) { .flip-card__inner { min-height: 228px; } }
/* Reduced motion: no 3D rotation. The back face is shown by simply toggling
   visibility/opacity on the two faces so the explanation still appears on click
   (or focus), just without the flip animation. */
@media (prefers-reduced-motion: reduce) {
  .flip-card__inner { transition: none; }
  .flip-card__inner:hover,
  .flip-card__inner:focus-visible,
  .flip-card__inner[aria-expanded="true"] { transform: none; }
  .flip-card__face { -webkit-backface-visibility: visible; backface-visibility: visible; transition: none; }
  .flip-card__face--back { transform: none; opacity: 0; visibility: hidden; }
  .flip-card__inner:hover .flip-card__face--front,
  .flip-card__inner:focus-visible .flip-card__face--front,
  .flip-card__inner[aria-expanded="true"] .flip-card__face--front { opacity: 0; visibility: hidden; }
  .flip-card__inner:hover .flip-card__face--back,
  .flip-card__inner:focus-visible .flip-card__face--back,
  .flip-card__inner[aria-expanded="true"] .flip-card__face--back { opacity: 1; visibility: visible; }
}

/* --- Signature block: Residential "at a glance" compare grid --- */
/* Two stacked cards contrasting the common symptom with what we actually do
   about it. A felt before/after without inventing photos. Unique to residential. */
.compare-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 16px; }
.compare-card { background: var(--surface); border: 1px solid var(--line); border-radius: var(--r); padding: 26px 24px; position: relative; overflow: hidden; }
.compare-card .tag { font-family: var(--font-head); text-transform: uppercase; letter-spacing: 0.16em; font-size: 0.875rem; font-weight: 600; }
.compare-card--symptom { border-top: 3px solid var(--line-strong); }
.compare-card--symptom .tag { color: var(--muted); }
.compare-card--fix { border-top: 3px solid var(--accent); }
.compare-card--fix .tag { color: var(--accent); }
.compare-card h3 { font-size: 1.2rem; margin: 10px 0 8px; }
.compare-card p { color: var(--muted); font-size: 0.96rem; }

/* --- Signature block: Commercial "sectors served" strip --- */
/* A horizontal band of property types we cover, each a chip with an icon. Tells
   a commercial buyer "yes, your kind of space" at a glance. Unique to commercial. */
.sector-strip { display: grid; grid-template-columns: repeat(auto-fit, minmax(150px, 1fr)); gap: 14px; }
.sector-chip {
  display: flex; flex-direction: column; align-items: center; text-align: center; gap: 12px;
  background: var(--surface); border: 1px solid var(--line); border-bottom: 3px solid var(--accent);
  border-radius: var(--r); padding: 24px 18px;
  transition: transform 0.18s cubic-bezier(0.22,0.61,0.36,1), box-shadow 0.18s ease, background 0.18s ease;
}
.sector-chip:hover { background: var(--surface-2); transform: translateY(-4px); box-shadow: 0 14px 30px rgba(0,0,0,0.4); }
.sector-chip svg { width: 30px; height: 30px; color: var(--accent); }
.sector-chip span { font-family: var(--font-head); text-transform: uppercase; letter-spacing: 0.06em; font-size: 0.96rem; font-weight: 600; color: var(--ink-bright); }

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

/* ============================================================
   Wave 8: Final blemish hunt + wow
   A handwritten founder signature (the one warm, human mark in an
   otherwise blunt industrial type system) plus one tasteful delight
   per page. Every delight is gated on the section's .is-revealed
   state and fully neutralized under prefers-reduced-motion, so a
   reduced-motion visitor lands on the finished look with no motion.
   The brand reads industrial-trade, so the delights borrow that
   language: bars that "power on," an edge that "energizes," a single
   calm pulse, never confetti.
   ============================================================ */

/* --- Signature flourish (About founder signature, 1 place) --- */
.sig-flourish {
  display: inline-block; position: relative;
  font-family: "Caveat", "Segoe Script", cursive;
  font-size: clamp(1.9rem, 1.4rem + 1.6vw, 2.6rem); line-height: 1;
  color: var(--accent); text-transform: none; letter-spacing: 0.01em;
  margin-top: 6px; padding-bottom: 10px;
}
/* The underline is a hand-weighted accent rule that draws left→right once
   the signature scrolls in (the .is-revealed hook is on the wrapping section). */
.sig-flourish::after {
  content: ""; position: absolute; left: 0; bottom: 0; height: 2px; width: 100%;
  background: linear-gradient(90deg, var(--accent) 0%, var(--accent-hi) 70%, transparent 100%);
  transform: scaleX(0); transform-origin: left;
  transition: transform 0.7s cubic-bezier(0.22, 0.61, 0.36, 1) 0.15s;
}
[data-reveal].is-revealed .sig-flourish::after { transform: scaleX(1); }
.sig-name { display: block; margin-top: 8px; font-family: var(--font-head); text-transform: uppercase; letter-spacing: 0.12em; font-size: 0.875rem; font-weight: 600; color: var(--muted); }

/* --- Services delight: process-step badges energize down the list --- */
/* Each step's number badge lights from outlined to accent-filled in sequence,
   reading like current flowing down the three steps. */
.steps.is-revealed li::before { animation: step-energize 0.5s cubic-bezier(0.22,0.61,0.36,1) both; }
.steps.is-revealed li:nth-child(2)::before { animation-delay: 0.12s; }
.steps.is-revealed li:nth-child(3)::before { animation-delay: 0.24s; }
@keyframes step-energize {
  from { box-shadow: 0 0 0 0 rgba(var(--accent-rgb),0); transform: scale(0.9); }
  60%  { box-shadow: 0 6px 18px rgba(var(--accent-rgb),0.5); transform: scale(1.04); }
  to   { box-shadow: 0 0 0 0 rgba(var(--accent-rgb),0); transform: scale(1); }
}

/* --- Panel delight: an energized hairline under the "warning signs" head --- */
/* A thin accent line beneath the section heading that fills left→right when
   the spec-list reveals, like a circuit closing. Placed via a modifier. */
.energize-rule { position: relative; height: 2px; margin: -4px 0 26px; background: var(--line); overflow: hidden; border-radius: 2px; }
.energize-rule::before {
  content: ""; position: absolute; inset: 0; transform: scaleX(0); transform-origin: left;
  background: linear-gradient(90deg, var(--accent) 0%, var(--accent-hi) 60%, transparent 100%);
  transition: transform 0.8s cubic-bezier(0.22, 0.61, 0.36, 1) 0.1s;
}
[data-reveal].is-revealed .energize-rule::before { transform: scaleX(1); }

/* --- Residential delight: the "what we do" fix card top-bar wipes in --- */
/* The fix card's accent top border draws in left→right on reveal, so the
   eye lands on the resolution side of the before/after pair. */
.compare-card--fix { position: relative; }
.compare-card--fix::after {
  content: ""; position: absolute; left: 0; right: 0; top: -3px; height: 3px;
  background: linear-gradient(90deg, var(--accent) 0%, var(--accent-hi) 70%, transparent 100%);
  transform: scaleX(0); transform-origin: left;
  transition: transform 0.7s cubic-bezier(0.22, 0.61, 0.36, 1) 0.12s;
}
[data-reveal].is-revealed .compare-card--fix::after { transform: scaleX(1); }

/* --- Commercial delight: sector-chip bottom edges draw in, staggered --- */
.sector-chip { position: relative; }
.sector-chip::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: -3px; height: 3px; background: var(--accent);
  transform: scaleX(0); transform-origin: center;
  transition: transform 0.55s cubic-bezier(0.22, 0.61, 0.36, 1);
}
[data-reveal].is-revealed .sector-chip::after { transform: scaleX(1); }
[data-reveal].is-revealed .sector-chip:nth-child(2)::after { transition-delay: 0.1s; }
[data-reveal].is-revealed .sector-chip:nth-child(3)::after { transition-delay: 0.2s; }
[data-reveal].is-revealed .sector-chip:nth-child(4)::after { transition-delay: 0.3s; }
/* The chip already carries a static border-bottom; the drawn edge sits on top
   of it so reduced-motion users still see the finished 3px accent border. */

/* --- Contact delight: expectation-setter icons stamp in one by one --- */
.form-expect li svg { transition: transform 0.4s cubic-bezier(0.34, 1.4, 0.5, 1), opacity 0.4s ease; }
[data-reveal] .form-expect li svg { opacity: 0; transform: scale(0.5); }
[data-reveal].is-revealed .form-expect li svg { opacity: 1; transform: scale(1); }
[data-reveal].is-revealed .form-expect li:nth-child(2) svg { transition-delay: 0.1s; }
[data-reveal].is-revealed .form-expect li:nth-child(3) svg { transition-delay: 0.2s; }

/* --- Emergency delight: one calm pulse on the alert band when it reveals --- */
/* A single ring pulse (not a loop, not a flash) draws attention to the call
   band the moment it enters view, then rests. */
.alert-band.is-revealed { animation: alert-pulse 1.1s ease-out 1; }
@keyframes alert-pulse {
  0%   { box-shadow: 0 0 0 0 rgba(var(--accent-rgb), 0.0), inset 0 0 0 0 rgba(0,0,0,0); }
  35%  { box-shadow: 0 0 0 10px rgba(var(--accent-rgb), 0.0), inset 0 0 40px rgba(0,0,0,0.18); }
  100% { box-shadow: 0 0 0 0 rgba(var(--accent-rgb), 0.0), inset 0 0 0 rgba(0,0,0,0); }
}

/* Reduced-motion: neutralize every Wave 8 delight to its finished state. The
   global reduced-motion rule zeroes durations; these lines also force the
   end transforms so nothing is left collapsed or invisible. */
@media (prefers-reduced-motion: reduce) {
  .sig-flourish::after,
  .energize-rule::before,
  .compare-card--fix::after,
  .sector-chip::after { transform: scaleX(1) !important; }
  [data-reveal] .form-expect li svg { opacity: 1 !important; transform: none !important; }
  .steps.is-revealed li::before,
  .alert-band.is-revealed { animation: none !important; }
}

/* --- Print stylesheet ---------------------------------------------------- */
/* The site is dark-themed; a raw print would dump ink. Flip to black-on-white,
   drop the sticky call bar, the mobile nav toggle, and the skip link, and
   reveal anything still mid-reveal so the page prints whole. */
@media print {
  html, body { background: #fff !important; color: #000 !important; }
  .sticky-cta,
  .nav-toggle,
  .skip-link,
  .header-cta { display: none !important; }
  .site-header { position: static !important; box-shadow: none !important; }
  [data-reveal] { opacity: 1 !important; transform: none !important; }
  a { color: #000 !important; text-decoration: underline; }
  .section, .subhero { background: #fff !important; }
  .stars { color: #000 !important; }
}

/* ---------- Offscreen layout containment ----------
   Below-the-fold sections are skipped during initial layout (content-visibility:
   auto) so first paint spends its main-thread budget on the hero/LCP instead of
   laying out the whole page. contain-intrinsic-size reserves a plausible height
   so the scrollbar + anchor offsets stay stable (no CLS). The browser lays each
   section out for real as it nears the viewport. */
.cv-defer { content-visibility: auto; contain-intrinsic-size: auto 600px; }

/* ============================================================
   Touch devices: no lingering hover states. On a phone a tap can leave an
   element stuck in its :hover transform until you tap elsewhere, which reads
   as a glitch. Neutralize the hover lift/scale so interaction is purely
   tap-or-don't. (Flip cards are already gated to hover: hover above.)
   ============================================================ */
@media (hover: none) {
  .btn-primary:hover, .btn-ghost:hover,
  .card:hover, .review:hover, .steps li:hover, .sector-chip:hover,
  .reasons li:hover .num, .contact-card:hover, .faq summary:hover .faq-toggle { transform: none; }
  .card:hover .card-media img, .card:hover .svc-icon, .card:hover .svc-icon svg,
  .split:hover .split-media img, .framed-image:hover img { transform: none; filter: none; }
  .steps li:hover { box-shadow: none; }
}
