/* ==========================================================================
   IE Pro Exteriors — site stylesheet (from tools/website_starter)

   Header style: DARK by default (standards §4: match-legacy-else-dark).

   ── COLOR CONTRACT — fill this in, do not delete it ─────────────────────────
   scaffold.py writes --primary / --accent / --accent-hover from config.json's
   brand block. Every DERIVED token below (--primary-deep, --accent-ink,
   --on-dark, --muted-on-dark, --on-accent) is a claim about a contrast ratio:
   COMPUTE it for this brand and write the number beside it. Do not transcribe
   the previous client's numbers. Rules that decided the values on the last
   build, all in docs/website_build_standards.md Rule 12:
     - an accent-on-dark token is calibrated for ONE ground; name the ground
     - hover must never be worse than resting
     - white on a saturated brand color usually FAILS AA; the fix is a dark
       label (--on-accent = --ink), never darkening the brand until it is brown.
       If the operator overrides that, document it here as an ACCEPTED EXCEPTION
       with the measured ratio, so the QA gate's contrast nodes can be read.
   ========================================================================== */

:root {
  /* ── COLOR CONTRACT for IE Pro Exteriors (computed 2026-09-14, WCAG 2.x) ──
     Brand: near-black + orange, from the client's own logo (orange house
     emblem on a black ground) and their existing landing page. Every ratio
     below was measured with a luminance script, not transcribed. */
  --primary: #141414;         /* brand primary — header, footer, dark grounds (brand.primary_color). White on it 18.42:1 */
  --primary-dark: #1C1C1C;    /* hero overlay ground; white on it 17.04:1 */
  --primary-deep: #262626;    /* trust bar, stats, CTA band, dark sidebar card, work band. White 15.13:1 */
  --footer-bg: #1C1C1C;       /* one step below --primary-deep so the footer reads as its own band
                                 under the CTA banner. --muted-on-dark 9.91:1, --white 17.04:1,
                                 --on-dark 8.95:1 on it. */

  --accent: #F6AD55;          /* brand accent — FILLS, with --on-accent on top (brand.accent_color) */
  --on-accent: #23272A;       /* DARK label on orange: 7.90:1. White on this orange is 1.90:1 and
                                 fails AA, so the label is ink (Rule 12, dark-on-brand first). */
  --accent-hover: #E0952F;    /* hover fill (brand.secondary_color). --on-accent on it 6.10:1 —
                                 lower than resting (7.90) but still AA; hover never fails. */
  --accent-ink: #A85A00;      /* orange TEXT on white — links, icons: 5.09:1 */
  --accent-ink-dark: #8E4C00; /* link hover on white: 6.60:1 */
  --accent-tint: #FDF2E5;     /* pale orange ground */
  --on-dark: #F6AD55;         /* orange text/icons on --primary-deep #262626: 7.95:1 (the brand
                                 orange itself clears AA on every dark ground here — no lift needed) */
  --muted-on-dark: #C2C6C8;   /* secondary text ON dark grounds: 8.80:1 on #262626 */
  --warm: #D1D3C0;            /* warm-white */

  --ink: #23272A;             /* 15.05:1 on white */
  --body: #3F464B;            /* 9.59:1 on white */
  --muted: #5C646A;           /* 6.02:1 on white, 5.62:1 on --surface */
  --line: #E1E4E6;
  --surface: #F6F7F8;
  --surface-2: #ECEEF0;
  --white: #ffffff;

  /* DARK header (standards §4 default for a new build; the brand is black on
     the logo and the current landing page). White on #141414 is 18.42:1. */
  --header-bg: #141414;
  --header-text: #ffffff;
  --header-line: #333333;
  /* The mobile slide-in panel is --primary-deep, NOT the header colour, so it
     reads as a surface. Every dark-ground colour is restated in the mobile
     block below (the light/dark header port trap). Measured on #262626:
     --muted-on-dark 8.80:1, --white 15.13:1, --on-dark 7.95:1. */
  --panel-bg: #262626;

  --font-head: 'Plus Jakarta Sans', system-ui, -apple-system, 'Segoe UI', sans-serif;
  --font-body: 'Inter', system-ui, -apple-system, 'Segoe UI', sans-serif;

  --wrap: 1180px;
  --radius: 14px;
  --shadow: 0 1px 2px rgba(20,20,20,.05), 0 8px 24px rgba(20,20,20,.07);
  --shadow-lg: 0 2px 4px rgba(20,20,20,.05), 0 22px 50px rgba(20,20,20,.16);
}

/* ── 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; }
  *, *::before, *::after { animation-duration: .001ms !important; animation-iteration-count: 1 !important; transition-duration: .001ms !important; }
}
body {
  margin: 0;
  font-family: var(--font-body);
  font-size: 17px;
  line-height: 1.65;
  color: var(--body);
  background: var(--white);
}
img { max-width: 100%; height: auto; display: block; }
h1, h2, h3, h4 { font-family: var(--font-head); color: var(--ink); line-height: 1.2; margin: 0 0 .55em; }
h1 { font-size: clamp(2.1rem, 4.6vw, 3.35rem); font-weight: 800; letter-spacing: -.025em; }
h2 { font-size: clamp(1.65rem, 3.1vw, 2.35rem); font-weight: 700; letter-spacing: -.018em; text-wrap: balance; }
h3 { font-size: 1.2rem; font-weight: 700; }
p { margin: 0 0 1.1em; }
a { color: var(--accent-ink); }
a:focus-visible, button:focus-visible, input:focus-visible, select:focus-visible, textarea:focus-visible {
  outline: 3px solid var(--accent-ink); outline-offset: 2px; border-radius: 3px;
}
.wrap { width: min(100% - 2.5rem, var(--wrap)); margin-inline: auto; }
.section { padding: clamp(3.5rem, 7vw, 6rem) 0; }
.section-alt { background: var(--surface); }
.section-sub { max-width: 64ch; color: var(--muted); font-size: 1.06rem; margin-bottom: 2.4rem; }
.icon { flex: none; vertical-align: -.18em; }

.skip-link {
  position: absolute; left: -9999px; top: 0; z-index: 999;
  background: var(--white); color: var(--accent-ink); padding: .8rem 1.2rem; font-weight: 600;
}
.skip-link:focus { left: 0; }

/* ── buttons ──────────────────────────────────────────────────────────────
   Rule 12: base colors carry NO !important, so a container can restyle a
   button by specificity rather than by fighting it. */
.btn {
  display: inline-flex; align-items: center; justify-content: center; gap: .5rem;
  font-family: var(--font-head); font-weight: 700; font-size: 1rem;
  padding: .95rem 1.7rem; border-radius: 999px; border: 2px solid transparent;
  text-decoration: none; cursor: pointer; transition: background-color .15s, color .15s, border-color .15s;
}
.btn-accent { background: var(--accent); color: var(--on-accent); }
.btn-accent:hover, .btn-accent:focus-visible { background: var(--accent-hover); color: var(--on-accent); }
.btn-outline { background: transparent; color: var(--accent-ink); border-color: var(--accent-ink); }
.btn-outline:hover, .btn-outline:focus-visible { background: var(--accent-ink); color: var(--white); }
/* on dark grounds: a white-outlined button */
.btn-ondark { background: transparent; color: var(--white); border-color: rgba(255,255,255,.75); }
.btn-ondark:hover, .btn-ondark:focus-visible { background: var(--white); color: var(--primary); border-color: var(--white); }
.btn-block { width: 100%; }

/* ── trust bar ────────────────────────────────────────────────────────────── */
.trust-bar { background: var(--primary-deep); color: var(--muted-on-dark); font-size: .875rem; }
.trust-bar-inner { display: flex; flex-wrap: wrap; align-items: center; gap: .4rem 1.6rem; padding: .55rem 0; }
.trust-item { display: inline-flex; align-items: center; gap: .4rem; }
.trust-item .icon { color: var(--on-dark); }
.trust-call { margin-left: auto; color: var(--white); font-weight: 600; text-decoration: none; }
.trust-call:hover { text-decoration: underline; }
@media (max-width: 720px) { .trust-bar { display: none; } }

/* ── header ───────────────────────────────────────────────────────────────── */
header {
  position: sticky; top: 0; z-index: 100;
  background: var(--header-bg); border-bottom: 1px solid var(--header-line);
  box-shadow: 0 1px 3px rgba(35,39,42,.05);
}
.header-inner { display: flex; align-items: center; justify-content: space-between; gap: 1.2rem; padding: .55rem 0; min-height: 80px; }
.logo { display: block; flex: none; }
.logo img { width: auto; height: 64px; }
@media (max-width: 980px) { .logo img { height: 52px; } }

.nav-desktop { display: flex; align-items: center; gap: .25rem; list-style: none; margin: 0; padding: 0; }
/* Rule 12 again: :not(.btn) sits on BOTH the base rule and the hover rule.
   Without it on the base rule, .nav-call's resting label inherits this color.

   ── THE `> li >` IS LOAD-BEARING. DO NOT FLATTEN IT BACK TO A DESCENDANT. ───
   This rule is for TOP-LEVEL links only. Written as a descendant selector it
   also matched every link inside .sub, and it BEAT both submenu rules on
   specificity, because :not() contributes its argument's weight:

     .nav-desktop a:not(.btn):not(.nav-call):not(.nav-quote)   (0,4,1)  WON
     .nav-desktop .sub a:not(.btn)                             (0,3,1)  lost
     .nav-desktop .sub-all a                                   (0,2,1)  lost

   So every dropdown link took --header-text (white) and rendered white-on-white
   on the .sub card: both desktop dropdowns were BLANK, sitewide. Nothing caught
   it, and nothing was going to — the dropdown is visibility:hidden at rest, so
   axe never measures it, and mobile masks it because white on the slate panel
   is perfectly readable. Only hovering it on desktop shows the bug.

   The child combinator is the fix rather than more :not()s: these links are not
   in .sub, so the rule should never have reached them in the first place. */
.nav-desktop > li > a:not(.btn):not(.nav-call):not(.nav-quote) {
  display: block; padding: .6rem .8rem; border-radius: 8px;
  color: var(--header-text); text-decoration: none; font-weight: 600; font-size: .97rem;
}
.nav-desktop > li > a:not(.btn):not(.nav-call):not(.nav-quote):hover,
.nav-desktop > li > a:not(.btn):not(.nav-call):not(.nav-quote):focus-visible { background: rgba(255,255,255,.12); }
/* The call button is excluded from BOTH rules above rather than overriding them
   with !important. A hover-only exclusion would leave its RESTING label taking
   the nav link color — the failure mode that reads fine on screen and fails
   axe at the base state. */
.nav-cta { margin-left: .35rem; }
/* outlined quote button, then the filled phone button — the estate's pair */
.nav-desktop a.nav-quote { display: inline-flex; align-items: center; justify-content: center;
  background: transparent; color: var(--white); border: 1.5px solid rgba(255,255,255,.55);
  padding: .62rem 1.15rem; border-radius: 8px; text-decoration: none; font-weight: 700; font-size: .95rem; }
.nav-desktop a.nav-quote:hover, .nav-desktop a.nav-quote:focus-visible {
  background: rgba(255,255,255,.14); border-color: var(--white); color: var(--white); }
.nav-desktop a.nav-call { display: inline-flex; align-items: center; gap: .45rem;
  background: var(--accent); color: var(--on-accent); padding: .62rem 1.15rem; border-radius: 8px;
  text-decoration: none; font-weight: 700; font-size: .95rem; }
.nav-desktop a.nav-call:hover, .nav-desktop a.nav-call:focus-visible { background: var(--accent-hover); color: var(--on-accent); }

.has-sub { position: relative; }
.sub {
  position: absolute; left: 0; top: 100%; min-width: 250px;
  background: var(--white); border: 1px solid var(--line); border-radius: var(--radius);
  box-shadow: var(--shadow-lg); list-style: none; margin: 0; padding: .4rem;
  opacity: 0; visibility: hidden; transform: translateY(6px); transition: opacity .15s, transform .15s, visibility .15s;
}
.has-sub:hover > .sub, .has-sub:focus-within > .sub { opacity: 1; visibility: visible; transform: translateY(0); }
/* These now style themselves completely: the base rule above no longer
   reaches them, so display, text-decoration and radius have to be restated
   here or the dropdown renders as underlined inline text. */
.nav-desktop .sub a:not(.btn) { display: block; padding: .55rem .7rem; border-radius: 8px;
  color: var(--body); text-decoration: none; font-weight: 500; font-size: .97rem; }
.nav-desktop .sub a:not(.btn):hover,
.nav-desktop .sub a:not(.btn):focus-visible { background: var(--surface); color: var(--accent-ink); }
/* :not(.btn) here only to match the specificity of .sub a:not(.btn) above —
   at (0,3,1) they tie and this one wins on source order. Without it this rule
   is (0,2,1) and the emphasis link silently takes the ordinary link color. */
.nav-desktop .sub-all a:not(.btn) { font-weight: 700; color: var(--accent-ink); border-top: 1px solid var(--line); margin-top: .25rem; }

/* Border at .55: composited over the #141414 header, .55 white gives #959595
   = 6.6:1 against it, well over the 3:1 WCAG 1.4.11 wants for a control
   boundary, and it matches .nav-quote. */
.hamburger { display: none; flex-direction: column; justify-content: center; gap: 5px; width: 46px; height: 42px; margin-left: auto; padding: 0 10px; background: transparent; border: 1px solid rgba(255,255,255,.55); border-radius: 10px; cursor: pointer; }
.hamburger span { display: block; height: 2px; background: var(--white); border-radius: 2px; transition: transform .2s, opacity .2s; }

/* ── mobile nav (Rule 25) ─────────────────────────────────────────────────── */
@media (max-width: 980px) {
  .hamburger { display: flex; }
  .nav {
    position: fixed; inset: 0 0 0 auto; width: min(86vw, 360px);
    background: var(--panel-bg); border-left: 1px solid var(--header-line);
    padding: 5.5rem 1.1rem 2rem; overflow-y: auto;
    /* the closed state */
    transform: translateX(100%); transition: transform .25s ease; z-index: 120;
  }
  /* Rule 25: EVERY state resets the transform explicitly — never rely on the
     desktop rule not having applied. */
  body.nav-open .nav { transform: translateX(0); }
  .nav-desktop { flex-direction: column; align-items: stretch; gap: .15rem; }
  .nav-desktop > li > a:not(.btn) { padding: .85rem .7rem; font-size: 1.05rem; }
  .nav-cta { margin-left: 0; }
  .nav-desktop a.nav-quote, .nav-desktop a.nav-call { width: 100%; margin-top: .6rem; padding: .8rem 1rem; }

  /* submenus fold rather than float */
  .sub {
    position: static; opacity: 1; visibility: visible; transform: none;
    box-shadow: none; border: 0; border-left: 2px solid var(--header-line);
    border-radius: 0; background: transparent; margin: 0 0 .4rem .7rem; padding: 0 0 0 .5rem;
    display: none;
  }
  .has-sub.open > .sub { display: block; }
  .has-sub:hover > .sub, .has-sub:focus-within > .sub { transform: none; }
  /* Submenu links sit on the DARK panel here, not on white — the desktop rule
     above sets them to --body, which is invisible on a dark ground. Each color
     is restated here rather than swapped at :root. Measured on --panel-bg
     #262626: --muted-on-dark 8.80:1, --white 15.13:1, --on-dark 7.95:1. */
  .nav-desktop .sub a:not(.btn) { color: var(--muted-on-dark); }
  .nav-desktop .sub a:not(.btn):hover,
  .nav-desktop .sub a:not(.btn):focus-visible { background: rgba(255,255,255,.12); color: var(--white); }
  .nav-desktop .sub-all a:not(.btn) { color: var(--on-dark); border-top-color: var(--header-line); }

  /* The panel is z-index 120 and the header only 100, so the burger was BURIED
     under the open panel — the X was unclickable and Escape was the only way
     out. Lift it above the panel while open. Rule 25 wants burger -> X, and an
     X you cannot press is not a close control. */
  body.nav-open .hamburger { position: relative; z-index: 130; border-color: rgba(255,255,255,.55); background: var(--primary); }
  body.nav-open .hamburger span:nth-child(1) { transform: translateY(7px) rotate(45deg); }
  body.nav-open .hamburger span:nth-child(2) { opacity: 0; }
  body.nav-open .hamburger span:nth-child(3) { transform: translateY(-7px) rotate(-45deg); }
  body.nav-open { overflow: hidden; }
}

/* ── hero ─────────────────────────────────────────────────────────────────── */
.hero { position: relative; background: var(--primary-deep); overflow: hidden; }
.hero-bg { position: absolute; inset: 0; }
.hero-bg img { width: 100%; height: 100%; object-fit: cover; }
/* Directional veil, in the brand near-black. The hero photo (a light gray
   two-story house under a bright sky) is the brightest image in the library:
   at .88 over pure white, white text still reads 8.9:1; at .78 it is 6.4:1.
   The veil falls to .20 on the form side, where no text sits, so the
   photograph stays visible. */
.hero-overlay { position: absolute; inset: 0; background:
  linear-gradient(100deg,
    rgba(20,20,20,.88) 0%,
    rgba(20,20,20,.78) 34%,
    rgba(20,20,20,.46) 62%,
    rgba(20,20,20,.20) 100%); }
/* bottom scrim so the trust row stays legible over a bright lower edge */
.hero-overlay::after { content: ""; position: absolute; inset: 0;
  background: linear-gradient(to top, rgba(20,20,20,.55) 0%, transparent 34%); }

.hero-inner { position: relative; z-index: 1; display: grid; grid-template-columns: 1.02fr .98fr;
  gap: clamp(2rem, 4.5vw, 4rem); align-items: center; padding: clamp(3rem, 6vw, 5.5rem) 0; }
.hero h1 { color: var(--white); line-height: 1.04; letter-spacing: -.03em;
  font-size: clamp(2.4rem, 5.2vw, 4rem); text-wrap: balance; }
.hero-sub { color: #EDEFF0; font-size: 1.16rem; line-height: 1.62; max-width: 48ch; }

/* pill eyebrow badge on a white chip, like the rest of the estate */
.eyebrow-chip { display: inline-flex; align-items: center; gap: .5rem; background: var(--white);
  border: 1px solid var(--line); border-radius: 999px; padding: .5rem 1rem; margin-bottom: 1.4rem;
  font-family: var(--font-head); font-weight: 700; font-size: .8rem; letter-spacing: .07em;
  text-transform: uppercase; color: var(--accent-ink); box-shadow: 0 1px 3px rgba(35,39,42,.06); }
.eyebrow-chip .icon { color: var(--accent-ink); }

.hero-actions { display: flex; flex-wrap: wrap; gap: .8rem; margin-top: 1.8rem; }
.hero .btn-outline { color: var(--white); border-color: rgba(255,255,255,.7); background: transparent; }
.hero .btn-outline:hover, .hero .btn-outline:focus-visible { background: var(--white); color: var(--primary-deep); border-color: var(--white); }
/* trust row reads as checked facts, not as a list of badges */
.hero-checks { display: flex; flex-wrap: wrap; gap: .6rem 1.8rem; list-style: none; margin: 1.8rem 0 0; padding: 0;
  color: #EDEFF0; font-size: .95rem; font-weight: 500; }
.hero-checks li { display: inline-flex; align-items: center; gap: .5rem; }
.hero-checks .icon { color: var(--on-dark); }

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

/* ── forms ────────────────────────────────────────────────────────────────── */
.form-card { background: var(--white); border: 1px solid var(--line); border-radius: 18px; padding: 1.6rem; box-shadow: var(--shadow-lg); color: var(--body); }
.hero .form-card { border: 1px solid rgba(35,39,42,.07); }
.form-card h2 { font-size: 1.3rem; margin-bottom: .4rem; }
.form-row { display: grid; grid-template-columns: 1fr 1fr; gap: .8rem; }
.form-stack { display: grid; gap: .8rem; }
@media (max-width: 560px) { .form-row { grid-template-columns: 1fr; } }
.field { display: flex; flex-direction: column; gap: .3rem; margin-bottom: .8rem; }
.field label { font-size: .88rem; font-weight: 600; color: var(--ink); }
.field input, .field select, .field textarea {
  font-family: inherit; font-size: 1rem; color: var(--ink);
  padding: .7rem .8rem; border: 1px solid #C9CED2; border-radius: 8px; background: var(--white);
}
.field textarea { resize: vertical; }
.field-check { flex-direction: row; align-items: center; gap: .5rem; }
.field-check label { font-weight: 500; }
.form-note { font-size: .87rem; color: var(--muted); margin: .4rem 0 0; font-weight: 400; }
.form-error { background: #FDECEC; border-left: 3px solid #B3261E; color: #8C1D18; padding: .7rem .9rem; border-radius: 6px; font-size: .92rem; }
.form-consent { display: flex; gap: .55rem; align-items: flex-start; font-size: .8rem; color: var(--muted); margin: .9rem 0 0; line-height: 1.5; }
.form-consent input { margin-top: .25rem; flex: none; }
/* Rule 8 honeypot — display:none, neutral name. Never rename to a
   profile-shaped field (website/url/company/address): Chrome autofills those
   regardless of autocomplete=off and a filled honeypot silently drops a REAL
   lead, with the visitor still seeing the thank-you page. */
.hp-field { display: none !important; }
.form-compact .form-note:first-of-type { display: none; }

/* ── cards, grids ─────────────────────────────────────────────────────────── */
.grid-2 { display: grid; grid-template-columns: repeat(auto-fit, minmax(280px, 1fr)); gap: 1.4rem; }
/* Explicit counts, because auto-fit strands an orphan row whenever the item
   count does not divide by the column count — 8 cards in 3 columns leaves 2
   marooned, which reads as broken layout rather than as a grid. */
.grid-4 { display: grid; grid-template-columns: repeat(4, 1fr); gap: 1.3rem; }
.grid-svc { display: grid; grid-template-columns: repeat(6, 1fr); gap: 1.3rem; }
.grid-svc > * { grid-column: span 2; }
.grid-svc > :nth-child(-n+2) { grid-column: span 3; }   /* windows + siding, the core, run wide */
@media (max-width: 1080px) { .grid-svc { grid-template-columns: repeat(2, 1fr); } .grid-svc > *, .grid-svc > :nth-child(-n+2) { grid-column: auto; } .grid-svc > :last-child:nth-child(odd) { grid-column: 1 / -1; } }
@media (max-width: 620px)  { .grid-svc { grid-template-columns: 1fr; } .grid-svc > :last-child:nth-child(odd) { grid-column: auto; } }
.grid-2-up { display: grid; grid-template-columns: repeat(2, 1fr); gap: 1.6rem; }
@media (max-width: 1080px) { .grid-4 { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 620px)  { .grid-4, .grid-2-up { grid-template-columns: 1fr; } }
.card { background: var(--white); border: 1px solid var(--line); border-radius: var(--radius); padding: 1.5rem; box-shadow: var(--shadow); }
.card h3 { margin-bottom: .4rem; }
.card p { color: var(--muted); font-size: .96rem; margin-bottom: .8rem; }
.card-link { font-weight: 700; text-decoration: none; }
.card-link:hover { text-decoration: underline; }
.card-media { border-radius: var(--radius) var(--radius) 0 0; margin: -1.5rem -1.5rem 1.1rem; overflow: hidden; }
.icon-badge { display: inline-flex; align-items: center; justify-content: center; width: 46px; height: 46px; border-radius: 12px; background: var(--accent); color: var(--on-accent); margin-bottom: 1rem; }

/* Rule 14: the stat bar stays ONE row at every viewport — it shrinks rather
   than wrapping, because a wrapped stat bar reads as broken layout. */
.stats-bar { background: var(--primary-deep); color: var(--white); }
/* Rule 14: repeat(4,1fr) at EVERY breakpoint. Fonts shrink; the row never wraps.
   Cells separate with a hairline rather than by whitespace, which is what keeps
   four narrow columns legible on a phone. Every colour restated: this sits on
   --primary-deep, and the number, label and sub each choose their own. */
.stats-bar-inner { display: grid; grid-template-columns: repeat(4, 1fr); gap: 0; padding: clamp(1.6rem, 3.5vw, 2.6rem) 0; text-align: center; }
.stat { min-width: 0; padding: .2rem clamp(.35rem, 1.5vw, 1.2rem); border-left: 1px solid var(--header-line); }
.stat:first-child { border-left: 0; }
.stat-num { display: block; font-family: var(--font-head); font-weight: 800; letter-spacing: -.03em; line-height: 1; font-size: clamp(1.6rem, 4.6vw, 3rem); color: var(--white); }
.stat-label { display: block; margin-top: .45rem; font-family: var(--font-head); font-weight: 700; font-size: clamp(.72rem, 1.5vw, .98rem); line-height: 1.25; color: var(--white); }
.stat-sub { display: block; margin-top: .3rem; font-size: clamp(.72rem, 1.3vw, .88rem); line-height: 1.35; color: var(--muted-on-dark); }
@media (max-width: 480px) { .stat-sub { display: none; } }

/* ── two-column body + sticky sidebar ─────────────────────────────────────── */
.content-wrap { display: grid; grid-template-columns: minmax(0, 1fr) 380px; gap: clamp(2rem, 4vw, 3.5rem); }
/* Rule 13: a sticky child in a CSS grid needs align-self:start, or the stretched
   grid item is already full-height and `position:sticky` can never engage. */
.sidebar-cta { align-self: start; position: sticky; top: 96px; }
@media (max-width: 980px) { .content-wrap { grid-template-columns: 1fr; } .sidebar-cta { position: static; } }

/* ── reviews ──────────────────────────────────────────────────────────────── */
.review-grid { display: grid; grid-template-columns: repeat(auto-fit, minmax(290px, 1fr)); gap: 1.4rem; }
.rev-card { background: var(--white); border: 1px solid var(--line); border-radius: var(--radius); padding: 1.4rem; margin: 0; box-shadow: var(--shadow); }
.rev-card blockquote { margin: .6rem 0 .9rem; }
.rev-card p { color: var(--body); font-size: .96rem; margin: 0; }
.rev-card figcaption { font-weight: 700; color: var(--ink); font-family: var(--font-head); font-size: .95rem; }
/* Stars are inline SVG (Rule 22) — never the character U+2605, which renders as
   a yellow color-emoji on iOS and ignores `color`. */
.stars { display: inline-flex; gap: 2px; color: var(--accent-ink); }
.stars .icon { fill: currentColor; }
.reviews-cta { margin-top: 1.8rem; }

/* ── FAQ ──────────────────────────────────────────────────────────────────── */
.faq { border-top: 1px solid var(--line); }
.faq details { border-bottom: 1px solid var(--line); padding: .3rem 0; }
.faq summary { cursor: pointer; font-family: var(--font-head); font-weight: 700; color: var(--ink); padding: 1rem 2rem 1rem 0; position: relative; list-style: none; }
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after { content: ""; position: absolute; right: .4rem; top: 1.5rem; width: 9px; height: 9px; border-right: 2px solid var(--accent-ink); border-bottom: 2px solid var(--accent-ink); transform: rotate(45deg); transition: transform .18s; }
.faq details[open] summary::after { transform: rotate(-135deg); }
.faq details p { color: var(--muted); margin: 0 0 1rem; }

/* ── CTA band ─────────────────────────────────────────────────────────────── */
.cta-banner { background: var(--primary-deep); color: var(--white); }
.cta-banner-inner { display: flex; flex-wrap: wrap; align-items: center; justify-content: space-between; gap: 1.5rem; padding: clamp(2rem, 4vw, 3rem) 0; }
.cta-banner h2 { color: var(--white); margin-bottom: .3rem; }
.cta-banner p { color: var(--muted-on-dark); margin: 0; max-width: 52ch; }
.cta-banner-actions { display: flex; flex-wrap: wrap; gap: .8rem; }

/* ── footer ───────────────────────────────────────────────────────────────── */
.site-footer { background: var(--footer-bg); color: var(--muted-on-dark); font-size: .95rem; }
.footer-grid { display: grid; grid-template-columns: 1.5fr 1fr 1fr 1.2fr; gap: 2.5rem; padding: clamp(2.5rem, 5vw, 4rem) 0 2rem; }
@media (max-width: 900px) { .footer-grid { grid-template-columns: 1fr 1fr; gap: 2rem; } }
@media (max-width: 560px) { .footer-grid { grid-template-columns: 1fr; } }
.footer-brand img { width: auto; height: 52px; margin-bottom: 1.1rem; }
.footer-brand p { max-width: 42ch; }
.footer-license { display: flex; align-items: center; gap: .45rem; color: var(--white); font-weight: 600; }
.footer-license .icon { color: var(--on-dark); }
.footer-h { font-size: 1rem; color: var(--white); margin-bottom: .9rem; }
.footer-links, .footer-contact, .footer-social, .footer-legal { list-style: none; margin: 0; padding: 0; }
.footer-links li, .footer-contact li { margin-bottom: .55rem; }
.footer-contact li { display: flex; gap: .6rem; align-items: flex-start; }
.footer-contact .icon { color: var(--on-dark); margin-top: .28rem; }
.footer-office { display: block; font-size: .78rem; text-transform: uppercase; letter-spacing: .06em; color: var(--muted-on-dark); }
/* :not(.btn) on BOTH rules — see the color contract, trap 2. */
.site-footer a:not(.btn) { color: var(--muted-on-dark); text-decoration: none; }
.site-footer a:not(.btn):hover, .site-footer a:not(.btn):focus-visible { color: var(--white); text-decoration: underline; }
.footer-social { display: flex; gap: .6rem; margin-top: 1.1rem; }
.footer-social a { display: inline-flex; align-items: center; justify-content: center; width: 40px; height: 40px; border: 1px solid var(--header-line); border-radius: 8px; color: var(--muted-on-dark); }
.footer-social a:hover { background: var(--white); color: var(--primary-deep); border-color: var(--white); }
.footer-bottom { display: flex; flex-wrap: wrap; justify-content: space-between; gap: .8rem; padding: 1.3rem 0 1.6rem; border-top: 1px solid var(--header-line); font-size: .88rem; }
.footer-bottom p { margin: 0; }
.footer-legal { display: flex; flex-wrap: wrap; gap: 1.2rem; }

/* ── mobile sticky bar (Rules 10 + 24) ────────────────────────────────────── */
.sticky-bar { display: none; }
.sticky-clearance { display: none; }
@media (max-width: 780px) {
  /* EXACTLY two elements: quote + phone (Rule 10). */
  .sticky-bar {
    display: grid; grid-template-columns: 1fr 1fr;
    position: fixed; left: 0; right: 0; bottom: 0; z-index: 110;
    background: var(--primary-deep); border-top: 1px solid var(--header-line);
    padding-bottom: env(safe-area-inset-bottom);
  }
  .sticky-bar a { display: inline-flex; align-items: center; justify-content: center; gap: .45rem; padding: .95rem .5rem; font-family: var(--font-head); font-weight: 700; font-size: 1rem; text-decoration: none; }
  .sticky-quote { background: var(--accent); color: var(--on-accent); }
  .sticky-call { color: var(--white); }
  .sticky-call:hover { background: rgba(255,255,255,.12); }
  /* Rule 24: clearance is its own element in the SAME color as the footer, plus
     the safe-area inset — padding on the footer alone leaves a white strip under
     the bar on a notched device. */
  .sticky-clearance { display: block; height: calc(58px + env(safe-area-inset-bottom)); background: var(--primary-deep); }
}

/* ── utilities ────────────────────────────────────────────────────────────── */
.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; }
.breadcrumb { font-size: .87rem; color: var(--muted); padding: 1rem 0 0; }
.breadcrumb ol { display: flex; flex-wrap: wrap; gap: .4rem; list-style: none; margin: 0; padding: 0; }
.breadcrumb li::after { content: "/"; margin-left: .4rem; color: var(--line); }
.breadcrumb li:last-child::after { content: ""; }
.prose > h2 { margin-top: 2.2rem; }
.prose > h3 { margin-top: 1.6rem; }
.prose ul { padding-left: 1.2rem; }
.prose li { margin-bottom: .45rem; }
/* Rule 2: .page-hero carries NO background-image here — layout only. Each page
   supplies its own contextual image plus a brand-tinted gradient via the inline
   longhands in site_page_hero(). --primary-deep #262626 is rgb(38,38,38). */
.page-hero { position: relative; overflow: hidden; color: var(--white); padding: clamp(2.5rem, 5vw, 4rem) 0 clamp(2.5rem, 5vw, 3.5rem); }
.page-hero h1 { color: var(--white); margin-top: .6rem; }
.page-hero p { max-width: 62ch; color: #E8EAEB; margin: 0; font-size: 1.06rem; }
.page-hero .breadcrumb { color: var(--muted-on-dark); padding-top: 0; }
.page-hero .breadcrumb a { color: var(--muted-on-dark); }
.page-hero .breadcrumb a:hover { color: var(--white); }
.page-hero .breadcrumb li::after { color: rgba(255,255,255,.35); }

/* ── homepage: service link row + service-area list ───────────────────────── */
.more-services { margin-top: 1.6rem; color: var(--muted); font-size: .97rem; }
.more-services a { font-weight: 600; }
.area-list { display: grid; grid-template-columns: repeat(auto-fit, minmax(180px, 1fr)); gap: .6rem 1.2rem; list-style: none; margin: 0; padding: 0; }
.area-list a { display: inline-flex; align-items: center; gap: .45rem; padding: .55rem .2rem; text-decoration: none; font-weight: 600; }
.area-list a:hover { text-decoration: underline; }
.area-list .icon { color: var(--accent-ink); }

/* ── home "Areas We Serve" band (Arolite's layout, 2026-10-02) ───────────────
   Dark band: the eight city pages grouped into three cards on the left, a WA
   county map on the right with Clark in the brand orange and the rest of the
   state in a quiet outline. Text ratios are the ones in the color contract on
   --primary-deep / --primary. */
.areas-band { background: var(--primary-deep); color: var(--muted-on-dark); }
.areas-grid { display: grid; grid-template-columns: minmax(0, 1fr) minmax(0, 1.15fr); gap: clamp(2rem, 5vw, 4.5rem); align-items: center; }
@media (max-width: 980px) { .areas-grid { grid-template-columns: 1fr; } }
.areas-band .eyebrow { background: transparent; color: var(--on-dark); padding: 0; font-size: .9rem; margin-bottom: .4rem; }
.areas-band h2 { color: var(--white); margin-bottom: .6rem; }
.areas-lead { color: var(--muted-on-dark); max-width: 52ch; }
.county-card { background: var(--primary); border: 1px solid var(--header-line); border-radius: var(--radius); padding: 1rem 1.2rem; margin-bottom: .8rem; }
.county-card h3 { color: var(--white); font-size: 1rem; margin: 0 0 .5rem; display: flex; align-items: center; gap: .45rem; }
.county-card h3 .icon { color: var(--on-dark); }
.pin-list { display: grid; grid-template-columns: repeat(2, 1fr); gap: .3rem 1rem; list-style: none; margin: 0; padding: 0; font-size: .95rem; }
@media (max-width: 480px) { .pin-list { grid-template-columns: 1fr; } }
.pin-list li { display: flex; align-items: center; gap: .4rem; color: var(--muted-on-dark); }
.pin-list .icon { color: var(--on-dark); flex: none; }
.pin-list a { color: var(--white); text-decoration: none; font-weight: 600; padding: .25rem 0; display: inline-block; }
.pin-list a:hover, .pin-list a:focus-visible { text-decoration: underline; color: var(--on-dark); }
.areas-actions { margin-top: 1.2rem; display: flex; flex-wrap: wrap; gap: .8rem; }
.areas-map { display: block; }
.area-map-svg { width: 100%; height: auto; display: block; }
.area-map-svg .c { fill: #1A1A1A; stroke: #4A4A4A; stroke-width: .9; vector-effect: non-scaling-stroke; }
.area-map-svg .c.served { fill: var(--accent); stroke: var(--white); stroke-width: 1.4; }
.map-note { font-size: .85rem; color: var(--muted-on-dark); margin: .8rem 0 0; text-align: center; }

/* ── contact list ─────────────────────────────────────────────────────────── */
.contact-list { list-style: none; margin: 0; padding: 0; }
.contact-list li { display: flex; gap: .8rem; align-items: flex-start; padding: .9rem 0; border-bottom: 1px solid var(--line); }
.contact-list li:last-child { border-bottom: 0; }
.contact-list .icon { color: var(--accent-ink); margin-top: .3rem; }
.contact-list strong { display: block; font-family: var(--font-head); color: var(--ink); font-size: .95rem; }
.contact-phone { display: inline-block; font-family: var(--font-head); font-weight: 700; font-size: 1.2rem; text-decoration: none; margin: .15rem 0; }
.contact-phone:hover { text-decoration: underline; }
.contact-note { display: block; font-size: .89rem; color: var(--muted); }

/* ── thank-you / 404 ──────────────────────────────────────────────────────── */
.thanks { max-width: 62ch; }
.thanks-mark { display: inline-flex; align-items: center; justify-content: center; width: 76px; height: 76px; border-radius: 50%; background: var(--accent); color: var(--on-accent); margin-bottom: 1.3rem; }
.thanks-lead { font-size: 1.12rem; color: var(--body); }
.thanks-actions { display: flex; flex-wrap: wrap; gap: .8rem; margin: 1.6rem 0 2.4rem; }
.thanks-next { border-top: 1px solid var(--line); padding-top: 1.8rem; }
.thanks-next ol, .thanks-next ul { padding-left: 1.2rem; }
.thanks-next li { margin-bottom: .6rem; }

/* ── sidebar three-card pattern (§6) ──────────────────────────────────────────
   Every sub-page carries the same three cards: a dark phone CTA, a form CTA to
   /contact/, and a related-page card that ROTATES BY PAGE TYPE to spread
   internal-link equity rather than pointing every page at the same target. */
.sidebar-card { background: var(--white); border: 1px solid var(--line); border-radius: var(--radius); padding: 1.4rem; margin-bottom: 1.1rem; box-shadow: var(--shadow); }
.sidebar-card h3 { font-size: 1.08rem; margin-bottom: .5rem; }
.sidebar-card p { color: var(--muted); font-size: .94rem; margin-bottom: 1rem; }
.sidebar-card .btn { width: 100%; }
.sidebar-card.dark { background: var(--primary-deep); border-color: var(--primary-deep); color: var(--muted-on-dark); }
.sidebar-card.dark h3 { color: var(--white); }
.sidebar-card.dark p { color: var(--muted-on-dark); }
.phone-big { display: block; font-family: var(--font-head); font-weight: 800; font-size: 1.6rem; color: var(--on-dark); text-decoration: none; margin: .2rem 0 .6rem; }
.phone-big:hover { text-decoration: underline; }

/* ── service / why cards (capture.py clips on these selectors) ────────────── */
.svc-card, .why-card { background: var(--white); border: 1px solid var(--line); border-radius: var(--radius); padding: 1.5rem; box-shadow: var(--shadow); }
.svc-card h3, .why-card h3 { margin-bottom: .4rem; }
.svc-card p, .why-card p { color: var(--muted); font-size: .96rem; margin-bottom: .8rem; }
.why-card p:last-child { margin-bottom: 0; }

/* ── feature list ─────────────────────────────────────────────────────────── */
.feature-list { list-style: none; margin: 1.2rem 0; padding: 0; }
.feature-list li { display: flex; gap: .6rem; align-items: flex-start; margin-bottom: .7rem; }
.feature-list .icon { color: var(--accent-ink); margin-top: .28rem; flex: none; }

/* ── FAQ (documented markup: .faq-item / .faq-q / .faq-a) ─────────────────── */
.faq-item { border-bottom: 1px solid var(--line); padding: .3rem 0; }
.faq-item:first-child { border-top: 1px solid var(--line); }
.faq-q { cursor: pointer; font-family: var(--font-head); font-weight: 700; color: var(--ink); padding: 1rem 2rem 1rem 0; position: relative; list-style: none; }
.faq-q::-webkit-details-marker { display: none; }
.faq-q::after { content: ""; position: absolute; right: .4rem; top: 1.5rem; width: 9px; height: 9px; border-right: 2px solid var(--accent-ink); border-bottom: 2px solid var(--accent-ink); transform: rotate(45deg); transition: transform .18s; }
.faq-item[open] .faq-q::after { transform: rotate(-135deg); }
.faq-a { color: var(--muted); margin: 0 0 1rem; }

/* ── in-body photo (Rule 32) ──────────────────────────────────────────────── */
.photo-frame { border-radius: var(--radius); overflow: hidden; box-shadow: var(--shadow); margin: 1.8rem 0; }
.photo-frame img { width: 100%; }
.photo-frame figcaption { background: var(--surface); color: var(--muted); font-size: .87rem; padding: .7rem 1rem; }
.photo-inline { border-radius: var(--radius); overflow: hidden; margin: 1.6rem 0; }

/* ── section heading helper ───────────────────────────────────────────────── */
.section-h { margin-bottom: .5rem; }
/* Section eyebrow. --accent-ink at 12px uppercase reads near-black rather than
   orange, so on light grounds the eyebrow becomes an orange CHIP (fill + dark
   label, 5.62:1) to match the hero's, instead of dark-orange text nobody reads
   as orange. On dark grounds it stays text in --on-dark, which is genuinely
   orange there. */
.eyebrow { display: inline-flex; align-items: center; gap: .4rem;
  background: var(--accent); color: var(--on-accent); border-radius: 999px;
  padding: .38rem .8rem; font-family: var(--font-head); font-weight: 700;
  font-size: .76rem; letter-spacing: .09em; text-transform: uppercase; margin-bottom: .9rem; }
.hero .eyebrow, .cta-banner .eyebrow, .work .eyebrow {
  background: transparent; color: var(--on-dark); padding: 0; font-size: .9rem; }
.review-featured { background: var(--white); border: 1px solid var(--line); border-left: 4px solid var(--accent); border-radius: var(--radius); padding: 1.6rem; margin-bottom: 1.4rem; box-shadow: var(--shadow); }
.review-by { font-weight: 700; color: var(--ink); font-family: var(--font-head); font-size: .95rem; margin: .6rem 0 0; }
.review-by span { font-weight: 500; color: var(--muted); }
.reviews-note { color: var(--muted); margin-bottom: 1.8rem; }

/* ── .content-wrap = .content-main + aside.sidebar-cta (§6) ───────────────── */
.content-main > h2:first-child { margin-top: 0; }
.content-main > h2 { margin-top: 2.2rem; }
.content-main > h3 { margin-top: 1.6rem; }
.content-main ul:not(.feature-list):not(.area-list) { padding-left: 1.2rem; }
.content-main li { margin-bottom: .45rem; }

/* ── footer column + reviews band ─────────────────────────────────────────── */
.footer-col { min-width: 0; }
.reviews { background: var(--surface); }

/* ── recent-work photo band (Rule 32) ─────────────────────────────────────────
   Nine authentic job photos from the client's Google listing. This puts them
   to work: it is the only thing on the page a competitor cannot copy, and it
   is the reason to trust the copy above it. */
.work { background: var(--primary-deep); color: var(--muted-on-dark); }
.work h2 { color: var(--white); }
.work .section-sub, .work .section-head p { color: var(--muted-on-dark); }
/* The work band is a DARK ground dropped into a page of light sections, so every
   color set for the light ground has to be restated here. .section-head p and
   .eyebrow both inherited --muted (2.14:1 on this ground) — the same light/dark
   trap as the header port, this time inside my own new section. */
.work .eyebrow .icon { color: var(--on-dark); }
.work-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 1rem; }
.work-item { position: relative; margin: 0; border-radius: var(--radius); overflow: hidden; background: var(--primary); }
.work-item img { width: 100%; height: 100%; aspect-ratio: 4 / 3; object-fit: cover; transition: transform .4s ease; }
.work-item:hover img { transform: scale(1.04); }
.work-grid-3 { grid-template-columns: repeat(3, 1fr); }
@media (max-width: 900px) { .work-grid { grid-template-columns: repeat(2, 1fr); } }
@media (prefers-reduced-motion: reduce) { .work-item:hover img { transform: none; } }

/* ── section eyebrow label, used to lead a section rather than a bare H2 ───── */
.section-head { max-width: 64ch; margin-bottom: 2.4rem; }
.section-head .eyebrow { margin-bottom: .5rem; }
.section-head h2 { margin-bottom: .5rem; }
.section-head p { color: var(--muted); font-size: 1.06rem; margin: 0; }

/* ── svc-card: give the orange somewhere real to live ─────────────────────── */
.svc-card { position: relative; transition: transform .18s ease, box-shadow .18s ease, border-color .18s ease; }
.svc-card::before { content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 4px; background: var(--accent); border-radius: var(--radius) 0 0 var(--radius); opacity: 0; transition: opacity .18s ease; }
.svc-card:hover { transform: translateY(-2px); box-shadow: var(--shadow-lg); border-color: #D6D9DB; }
.svc-card:hover::before { opacity: 1; }
@media (prefers-reduced-motion: reduce) { .svc-card, .svc-card:hover { transform: none; transition: none; } }


/* ── photo-led service cards (Rule 32) ────────────────────────────────────────
   The whole card is one <a>, so the inner "heading" and copy are spans styled
   to look like a heading rather than real h3/p — nesting block elements or a
   heading inside an anchor is invalid and axe flags the heading-order. */
.svc-card { display: flex; flex-direction: column; padding: 0; overflow: hidden; text-decoration: none; color: inherit; }
.svc-card .pic { display: block; overflow: hidden; background: var(--surface-2); }
.svc-card .pic img { width: 100%; aspect-ratio: 16 / 10; object-fit: cover; transition: transform .45s ease; }
.svc-card:hover .pic img { transform: scale(1.05); }
.svc-card .icon-badge { margin: 1.5rem 1.5rem 0; }
.svc-card .body { display: flex; flex-direction: column; gap: .45rem; padding: 1.25rem 1.5rem 1.5rem; }
.svc-card .h3 { font-family: var(--font-head); font-weight: 700; font-size: 1.15rem; color: var(--ink); line-height: 1.25; }
.svc-card .blurb { color: var(--muted); font-size: .95rem; line-height: 1.55; }
.svc-card .more { display: inline-flex; align-items: center; gap: .35rem; margin-top: .35rem;
  font-family: var(--font-head); font-weight: 700; font-size: .93rem; color: var(--accent-ink); }
.svc-card:hover .more { color: var(--accent-ink-dark); }
.svc-card:hover .more .icon { transform: translateX(3px); }
.svc-card .more .icon { transition: transform .18s ease; }
/* the orange edge only makes sense on the icon variant; a photo card already
   has its own top-edge weight */
.svc-card.has-pic::before { display: none; }
@media (prefers-reduced-motion: reduce) {
  .svc-card:hover .pic img, .svc-card:hover .more .icon { transform: none; }
}

/* Fallback panel for a service with no honest photo yet. Same 16/10 block as a
   real photo so a mixed grid keeps its rhythm, but visibly not a photograph. */
.svc-card .pic-placeholder { display: flex; align-items: center; justify-content: center;
  aspect-ratio: 16 / 10; background:
    linear-gradient(135deg, var(--primary) 0%, var(--primary-deep) 100%);
  color: var(--on-dark); }
.svc-card:hover .pic-placeholder { color: var(--accent); }

/* ── owner portraits (real photos only — none yet on this build) ──────────── */
.owner { float: left; margin: .4rem 1.4rem .8rem 0; text-align: center; }
.owner img { width: 132px; height: 132px; border-radius: 50%; object-fit: cover; border: 3px solid var(--accent); }
.owner figcaption { font-family: var(--font-head); font-weight: 700; font-size: .92rem; color: var(--ink); margin-top: .55rem; }
.owner figcaption span { display: block; font-weight: 500; font-size: .8rem; color: var(--muted); }
.content-main h3 { clear: none; }
@media (max-width: 560px) { .owner { float: none; margin: 0 auto 1rem; } }



/* ── process steps ────────────────────────────────────────────────────────────
   An ordered sequence, not a card grid. Own component because .svc-card now
   carries padding:0 for the photo layout — anything reusing it without a .body
   wrapper loses its inset entirely, which is exactly what happened here. */
.step-grid { display: grid; grid-template-columns: repeat(4, 1fr); gap: 1.3rem; list-style: none; margin: 0; padding: 0; counter-reset: step; }
.step-card { position: relative; background: var(--white); border: 1px solid var(--line);
  border-radius: var(--radius); padding: 2.4rem 1.5rem 1.6rem; box-shadow: var(--shadow); }
.step-num { position: absolute; top: -18px; left: 1.5rem;
  display: inline-flex; align-items: center; justify-content: center; width: 44px; height: 44px;
  border-radius: 12px; background: var(--accent); color: var(--on-accent);
  font-family: var(--font-head); font-weight: 800; font-size: 1.15rem; box-shadow: var(--shadow); }
.step-card h3 { font-size: 1.08rem; margin: .35rem 0 .45rem; }
.step-card p { color: var(--muted); font-size: .95rem; line-height: 1.55; margin: 0; }
/* the connecting rule between steps, desktop only */
.step-card::after { content: ""; position: absolute; top: 4px; right: -1.3rem; width: 1.3rem; height: 1px; background: var(--line); }
.step-card:last-child::after { display: none; }
@media (max-width: 1080px) { .step-grid { grid-template-columns: repeat(2, 1fr); row-gap: 2.4rem; } .step-card::after { display: none; } }
@media (max-width: 620px)  { .step-grid { grid-template-columns: 1fr; row-gap: 2.4rem; } }

/* The eyebrow is a <p> inside .section-head, and `.section-head p` (0,1,1) is
   declared later than `.eyebrow` (0,1,0), so it silently won and painted the
   chip label --muted — gray on orange at 2.25:1. Restated at (0,2,0) so the
   eyebrow's own color holds regardless of the container it sits in. */
.section-head .eyebrow { color: var(--on-accent); }
.work .section-head .eyebrow,
.hero .section-head .eyebrow,
.cta-banner .section-head .eyebrow { color: var(--on-dark); }

/* ── location cards (/locations/) ───────────────────────────────────────────
   A TEXT card, not a photo card, and that is a content-integrity decision
   rather than a design one — see the comment above site_city_card().

   Every color is restated on the card's own children rather than inherited.
   This build has already had four incidents where a rule on a CONTAINER
   silently repainted a component that had chosen its own color, and these
   cards sit on BOTH grounds: .section (white) in one block and .section-alt
   (--surface) in the other. Inheriting would make them diverge the first time
   either ground changes. */
.loc-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1.2rem; }
@media (max-width: 900px) { .loc-grid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 560px) { .loc-grid { grid-template-columns: 1fr; } }

.loc-card {
  display: flex; flex-direction: column; position: relative;
  background: var(--white); border: 1px solid var(--line); border-radius: var(--radius);
  padding: 1.35rem; box-shadow: var(--shadow); text-decoration: none;
  transition: transform .18s ease, box-shadow .18s ease, border-color .18s ease;
}
.loc-card::before { content: ""; position: absolute; left: 0; top: 0; bottom: 0; width: 4px;
  background: var(--accent); border-radius: var(--radius) 0 0 var(--radius);
  opacity: 0; transition: opacity .18s ease; }
.loc-card:hover, .loc-card:focus-visible { transform: translateY(-2px); box-shadow: var(--shadow-lg); border-color: #D6D9DB; }
.loc-card:hover::before, .loc-card:focus-visible::before { opacity: 1; }
@media (prefers-reduced-motion: reduce) { .loc-card, .loc-card:hover { transform: none; transition: none; } }

.loc-card .county { display: inline-flex; align-items: center; gap: .35rem;
  font-size: .73rem; font-weight: 700; text-transform: uppercase; letter-spacing: .07em;
  color: var(--accent-ink); margin-bottom: .55rem; }
.loc-card .county .icon { color: var(--accent-ink); }
.loc-card .h3 { display: block; font-family: var(--font-head); font-weight: 700;
  font-size: 1.14rem; line-height: 1.25; color: var(--ink); margin-bottom: .45rem; }
.loc-card .blurb { display: block; color: var(--muted); font-size: .94rem; line-height: 1.55;
  margin-bottom: 1rem; }
.loc-card .more { display: inline-flex; align-items: center; gap: .35rem; margin-top: auto;
  font-weight: 700; font-size: .92rem; color: var(--accent-ink); }
.loc-card .more .icon { color: var(--accent-ink); }
.loc-card:hover .more { text-decoration: underline; }

/* ── city-page service block (includes/city_render.php) ─────────────────────
   Three or four services chosen FOR that city, each with copy written for that
   market — never a full service grid repeated identically on every city page.
   Every color restated rather than inherited — this block sits inside
   .content-main on a white ground, and .content-main sets its own p color. */
.city-svc { display: grid; grid-template-columns: repeat(2, 1fr); gap: 1.1rem; margin: 1.4rem 0 .4rem; }
@media (max-width: 640px) { .city-svc { grid-template-columns: 1fr; } }
.city-svc-item { background: var(--surface); border: 1px solid var(--line); border-radius: var(--radius); padding: 1.15rem 1.25rem; }
.city-svc-item h3 { margin: 0 0 .4rem; font-size: 1.06rem; color: var(--ink); }
.city-svc-item h3 a { color: var(--accent-ink); text-decoration: none; }
.city-svc-item h3 a:hover, .city-svc-item h3 a:focus-visible { text-decoration: underline; }
.city-svc-item p { margin: 0; color: var(--muted); font-size: .95rem; line-height: 1.6; }

/* A phone number is one token. Inside running prose the inline tel link was
   wrapping mid-number at 390px on /locations/ and /privacy-policy/. */
.content-main a[href^="tel:"], .prose a[href^="tel:"], .contact-list a[href^="tel:"],
.sidebar-card a[href^="tel:"], .cta-banner a[href^="tel:"] { white-space: nowrap; }

/* ── gallery (/gallery/) ─────────────────────────────────────────────────────
   Reuses the work-grid tiles on a LIGHT ground with a visible caption that
   does not repeat the alt. Colors restated: .work-item was designed for the
   dark band and its ground is --primary, which would show through as a black
   frame around a portrait photo here. */
.gallery-grid { margin: 1rem 0 2.6rem; }
.gallery-item { background: var(--surface-2); }
.gallery-item img { aspect-ratio: 4 / 5; }
.gallery-item figcaption { padding: .6rem .8rem; font-size: .88rem; color: var(--muted); background: var(--white); border: 1px solid var(--line); border-top: 0; border-radius: 0 0 var(--radius) var(--radius); }
.section .gallery-grid + h2 { margin-top: .5rem; }

/* Links inside the dark work band inherited --accent-ink (#A85A00), which is
   2.0:1 on #262626 and was the one axe color-contrast node on the homepage.
   Restated for the dark ground: --on-dark is 7.95:1 there. */
.work a:not(.btn) { color: var(--on-dark); }
.work a:not(.btn):hover, .work a:not(.btn):focus-visible { color: var(--white); }

/* ── owner family portraits on /about/ ──────────────────────────────────────
   Two real photos of the owners with their families (from the client's own
   Facebook page, previously used in their ads). Portrait 3:4 tiles, one
   shared caption underneath so neither photo is labelled with a name until
   Eric confirms which family is which. */
.owners-grid { display: grid; grid-template-columns: 1fr 1fr; gap: 1rem; margin: 1.6rem 0 .4rem; }
.owners-grid figure { margin: 0; border-radius: var(--radius); overflow: hidden; background: var(--surface-2); }
.owners-grid img { width: 100%; aspect-ratio: 3 / 4; object-fit: cover; }
.owners-caption { color: var(--muted); font-size: .92rem; margin: 0 0 1.6rem; }
@media (max-width: 560px) { .owners-grid { grid-template-columns: 1fr; } }
