/*
  Arolite Group — site stylesheet (from tools/website_starter)
  Asheville, NC roofing / siding / gutters. Black + gold, dark header, Montserrat
  headings, Source Sans 3 body. Derived tokens are computed, see the contract.
*/
/* ── COLOR CONTRACT (Arolite Group, black + gold) ──────────────────────────
   Read from the client's legacy stylesheet :root (gold #e6c368 / #cfaf5d, black
   grounds, #111418 text) and the truck wraps. Every ratio below was computed
   (WCAG relative luminance) on 2026-09-30, not eyeballed:
     white on --primary #111418 ............ 18.47:1
     --accent gold on --primary ............ 10.88:1   (--on-dark is the gold itself)
     --accent gold on --primary-deep ....... 9.86:1
     --accent gold on --footer-bg .......... 11.46:1
     --on-accent ink on --accent gold ...... 10.88:1   (dark label on a gold fill)
     --on-accent ink on --accent-hover ..... 8.74:1    (hover never worse than rest, Rule 12)
     --muted-on-dark on deep / footer ...... 8.86 / 10.30:1
     --accent-ink #7A5E12 on white ......... 6.11:1    (gold TEXT needs a dark gold; the fill gold is 1.5:1 on white)
     --accent-ink on --surface #F6F5F0 ..... 5.60:1
     --accent-ink-dark #5C450C on white .... 9.08:1
   Gold is a FILL colour and a colour ON DARK. It is never body text on a light
   ground: that is what --accent-ink is for. */
:root {
  --primary: #111418;         /* brand black — header, dark grounds */
  --primary-dark: #181C21;    /* hero overlay ground; white on it is 17:1 */
  --primary-deep: #1A1E24;    /* trust bar, stats, CTA band, dark cards */
  --footer-bg: #0B0D10;       /* one step below deep so the footer reads as its own band */

  --accent: #e6c368;          /* brand gold — FILLS, with --on-accent on top */
  --on-accent: #111418;       /* ink on gold, 10.88:1 */
  --accent-hover: #cfaf5d;    /* darker gold hover fill, ink on it 8.74:1 */
  --accent-ink: #7A5E12;      /* gold TEXT on white — links, icons (6.11:1) */
  --accent-ink-dark: #5C450C; /* 9.08:1 */
  --accent-tint: #FBF4DF;     /* pale gold ground; ink on it 16.8:1 */
  --on-dark: #e6c368;         /* gold text on the dark grounds (9.86:1 on deep) */
  --muted-on-dark: #B8BDC4;   /* secondary text on dark grounds */
  --warm: #F2F1EE;            /* the legacy off-white section ground */

  --ink: #111418;
  --body: #2E3338;
  --muted: #5A6169;
  --line: #E3E5E8;
  --surface: #F6F5F0;
  --surface-2: #ECEAE3;
  --white: #ffffff;

  /* DARK header: match-legacy (the Topline site is black) and the wraps. */
  --header-bg: #111418;
  --header-text: #ffffff;
  --header-line: #2A2F36;
  --panel-bg: #1A1E24;        /* the mobile slide-in panel; gold on it 9.86:1 */

  --font-head: 'Montserrat', system-ui, -apple-system, 'Segoe UI', sans-serif;
  --font-body: 'Source Sans 3', system-ui, -apple-system, 'Segoe UI', sans-serif;

  --wrap: 1180px;
  --radius: 14px;
  --shadow: 0 1px 2px rgba(17,20,24,.06), 0 8px 24px rgba(17,20,24,.08);
  --shadow-lg: 0 2px 4px rgba(17,20,24,.06), 0 22px 50px rgba(17,20,24,.18);
}

/* ── 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: 17.5px;
  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; text-wrap: balance; }
h3 { text-wrap: balance; }
p, li, dd, .faq-a { text-wrap: pretty; }   /* no lone last word ("PM", "reviews.") */
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 black grounds: a white-outlined button, since gold fails there */
.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(17,20,24,.05);
}
.header-inner { display: flex; align-items: center; justify-content: space-between; gap: 1.2rem; padding: .6rem 0; min-height: 76px; }
.logo { display: block; flex: none; }
.logo img { width: auto; height: 56px; }
@media (min-width: 981px) { .logo img { height: 68px; } }   /* full-width tagline (10/05 logo) needs the height to read */

.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 black 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); }
.nav-desktop a.nav-quote, .nav-desktop a.nav-call { white-space: nowrap; }
/* Seven links + two buttons (Careers added 2026-10-06): tighten between the
   hamburger breakpoint and the width where everything fits at full size. */
@media (min-width: 981px) and (max-width: 1240px) {
  .nav-desktop > li > a:not(.btn):not(.nav-call):not(.nav-quote) { padding: .55rem .45rem; font-size: .9rem; }
  .nav-cta { margin-left: .2rem; }
  .nav-desktop a.nav-quote, .nav-desktop a.nav-call { padding: .55rem .75rem; font-size: .88rem; }
  .logo img { height: 54px; }
  .header-inner { gap: .8rem; }
}

.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 not .40: composited over the #111418 header, .40 gives
   #959799 = 2.69:1 against it, under the 3:1 that WCAG 1.4.11 wants for a
   control boundary. .55 gives #AFB1B2 = 3.66:1, and 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 SLATE panel here, not on white — the desktop rule
     above sets them to --body, which is invisible on black. This is the exact
     bug a light-to-dark header port leaves behind. */
  /* The desktop submenu rule sets these links to --body, which is invisible
     on a dark panel, so each color is restated here for the dark ground rather
     than swapped at :root. Measured on --panel-bg #1A1E24: --muted-on-dark
     7.50:1, --white on the hover ground 8.80:1, --on-dark 5.52:1.
     (The previous note here claimed --on-dark was 4.51:1 on #111418. It is
     3.37:1. That number was never true, and it was the reason the panel ground
     looked safe.) */
  .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. Stops chosen from measurement, not taste: at 0.72 over the
   photo's BRIGHTEST pixel white still reads 6.16:1, and over the roof itself
   11.5:1. It then falls to 0.18 on the form side, where no text sits, so the
   photograph is actually visible. A flat 0.9 wash — the first attempt here —
   makes the hero a gray box and wastes the only asset a competitor cannot copy. */
.hero-overlay { position: absolute; inset: 0; background:
  linear-gradient(100deg,
    rgba(26,30,36,.88) 0%,
    rgba(26,30,36,.78) 34%,
    rgba(26,30,36,.46) 62%,
    rgba(26,30,36,.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(11,13,16,.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(17,20,24,.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(17,20,24,.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-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 blockquote p + p { margin-top: .6rem; }
.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; }
.review-src { font-weight: 500; color: var(--muted); font-size: .85rem; }
.reviews-photo .rev-card figcaption { color: var(--ink); }

/* ── 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: .6rem; }
.cta-banner p { color: var(--muted-on-dark); margin: 0; max-width: 52ch; }
.cta-banner-actions { display: flex; flex-wrap: wrap; gap: .8rem; }
@media (max-width: 560px) { .cta-banner-actions { width: 100%; } .cta-banner-actions .btn { flex: 1 1 100%; justify-content: center; } }

/* ── 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(--footer-bg); }
}

/* ── 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 (not plain black)
   gradient via the inline multi-background shorthand. No ::before image layer,
   no var() on a pseudo-element. --primary-deep #1A1E24 is rgb(26,30,36). */
.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); }

/* ── 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
   gold, so on light grounds the eyebrow becomes an gold CHIP (fill + dark
   label, 5.62:1) to match the hero's, instead of dark-gold text nobody reads
   as gold. On dark grounds it stays text in --on-dark, which is genuinely
   gold 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 drone job photos exist and the page was using one. This puts
   the rest 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); }
@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 gold 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: #D3D6DA; }
.svc-card:hover::before { opacity: 1; }
@media (prefers-reduced-motion: reduce) { .svc-card, .svc-card:hover { transform: none; transition: none; } }

/* stat unit sits smaller and gold beside the numeral */

/* ── 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 gold 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, recovered from the legacy site) ─────────── */
.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 gold 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: #D3D6DA; }
.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. It replaces the legacy eleven-service grid, which was identical on
   all eleven city pages and hardcoded to Sarasota.
   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:"],
a[href^="tel:"], .nowrap { white-space: nowrap; }   /* a phone number never splits */


/* ── photo band variants (Arolite) ───────────────────────────────────────────
   Jeff's one explicit ask from the demo: a big background photograph with the
   reviews sitting over it. The section keeps the white review cards; only the
   ground changes. The veil is measured for white heading text over the
   brightest photo in the library (sky in the underlayment shot): 0.74 floor. */
.reviews.reviews-photo { background-color: var(--primary-deep); background-size: cover; background-position: center; color: var(--muted-on-dark); }
.reviews-photo h2 { color: var(--white); }
.reviews-photo .section-sub { color: var(--muted-on-dark); }
.reviews-photo .btn-outline { color: var(--white); border-color: rgba(255,255,255,.7); }
.reviews-photo .btn-outline:hover, .reviews-photo .btn-outline:focus-visible { background: var(--white); color: var(--primary-deep); border-color: var(--white); }

/* Financing / offer band: gold-tinted light ground with an ink heading. */
.band-tint { background: var(--accent-tint); }
.band-tint h2 { color: var(--ink); }

/* Photo grid for the gallery page: 3-up, 4/3, honest alt from the catalog. */
.gallery-grid { display: grid; grid-template-columns: repeat(3, 1fr); gap: 1rem; }
.gallery-grid figure { margin: 0; border-radius: var(--radius); overflow: hidden; background: var(--surface-2); }
.gallery-grid img { width: 100%; aspect-ratio: 4 / 3; object-fit: cover; }
@media (max-width: 900px) { .gallery-grid { grid-template-columns: repeat(2, 1fr); } }
@media (max-width: 520px) { .gallery-grid { grid-template-columns: 1fr; } }

/* Simple numbered list for careers / how-to-apply. */
.num-list { list-style: none; margin: 1.2rem 0; padding: 0; counter-reset: n; }
.num-list li { position: relative; padding-left: 3rem; margin-bottom: 1rem; }
.num-list li::before { counter-increment: n; content: counter(n); position: absolute; left: 0; top: .05rem;
  width: 2.1rem; height: 2.1rem; border-radius: 10px; background: var(--accent); color: var(--on-accent);
  font-family: var(--font-head); font-weight: 800; display: inline-flex; align-items: center; justify-content: center; }

/* ── homepage service carousel (Pisgah-style photo tiles, asked for 2026-10-01) ──
   Native scroll-snap, three tiles per view on desktop, two on tablet, a peek of
   the next one on phones. Arrows scroll by one tile; a gentle auto-advance runs
   until the visitor touches it, and never under reduced motion. Tiles with no
   honest photo keep the branded icon panel (Rule 27/32), same shape as a photo.
   Title sits on a scrim that reaches rgba(17,20,24,.88) at the baseline, so
   white on it is >= 12:1 over the brightest photo in the library. */
.svc-head { text-align: center; max-width: 64ch; margin: 0 auto 2rem; }
.svc-head p { color: var(--muted); font-size: 1.06rem; margin: 0; }
/* .svc-head p (0,1,1) outranks .eyebrow (0,1,0): restate the chip label colour or it
   paints gray on gold (axe caught it on staging 2026-10-01, 2 nodes). */
.svc-head .eyebrow { color: var(--on-accent); font-size: .76rem; margin-bottom: .9rem; }
.car { position: relative; }
.car-track { display: flex; gap: 1.1rem; list-style: none; margin: 0; padding: .25rem .25rem 1rem;
  overflow-x: auto; scroll-snap-type: x mandatory; scroll-behavior: smooth; scrollbar-width: none; -webkit-overflow-scrolling: touch; }
.car-track::-webkit-scrollbar { display: none; }
.car-item { flex: 0 0 calc((100% - 2.2rem) / 3); scroll-snap-align: start; }
@media (max-width: 980px) { .car-item { flex-basis: calc((100% - 1.1rem) / 2); } }
@media (max-width: 600px) { .car-item { flex-basis: 84%; } }
.tile { position: relative; display: block; aspect-ratio: 4 / 3; border-radius: var(--radius); overflow: hidden;
  background: var(--primary-deep); text-decoration: none; color: var(--white); box-shadow: var(--shadow); }
.tile img { width: 100%; height: 100%; object-fit: cover; display: block; transition: transform .5s ease; }
.tile:hover img, .tile:focus-visible img { transform: scale(1.05); }
.tile-panel { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center;
  background: linear-gradient(135deg, var(--primary) 0%, var(--primary-deep) 100%); color: var(--on-dark); }
.tile-cap { position: absolute; left: 0; right: 0; bottom: 0; padding: 3.2rem 1.3rem 1.2rem;
  background: linear-gradient(to top, rgba(17,20,24,.92) 0%, rgba(17,20,24,.72) 45%, rgba(17,20,24,0) 100%); }
.tile-title { display: block; font-family: var(--font-head); font-weight: 800; font-size: 1.35rem; line-height: 1.15; color: var(--white); letter-spacing: -.01em; }
.tile-more { display: inline-flex; align-items: center; gap: .35rem; margin-top: .45rem; font-family: var(--font-head);
  font-weight: 700; font-size: .9rem; color: var(--on-dark); opacity: 0; transform: translateY(4px); transition: opacity .2s, transform .2s; }
.tile:hover .tile-more, .tile:focus-visible .tile-more { opacity: 1; transform: none; }
@media (hover: none) { .tile-more { opacity: 1; transform: none; } }
.tile:focus-visible { outline: 3px solid var(--accent); outline-offset: 3px; }
.car-btn { position: absolute; top: 50%; transform: translateY(-50%); z-index: 2; width: 46px; height: 46px; border-radius: 50%;
  border: 0; background: var(--accent); color: var(--on-accent); cursor: pointer; display: inline-flex; align-items: center; justify-content: center;
  box-shadow: var(--shadow-lg); }
.car-btn:hover, .car-btn:focus-visible { background: var(--accent-hover); color: var(--on-accent); }
.car-btn.prev { left: -23px; } .car-btn.next { right: -23px; }
@media (max-width: 1240px) { .car-btn.prev { left: 6px; } .car-btn.next { right: 6px; } }
.car-dots { display: flex; justify-content: center; gap: .45rem; margin: .4rem 0 1.6rem; }
.car-dots span { width: 8px; height: 8px; border-radius: 50%; background: var(--line); }
.car-dots span.on { background: var(--accent-ink); }
.svc-cta { display: flex; flex-wrap: wrap; justify-content: center; gap: .8rem; }
/* Any row of side-by-side buttons: same .8rem gap as .hero-actions, so they never touch when they wrap. */
.btn-row { display: flex; flex-wrap: wrap; gap: .8rem; }
@media (prefers-reduced-motion: reduce) { .car-track { scroll-behavior: auto; } .tile img, .tile:hover img { transform: none; transition: none; } }

/* ── "Areas We Serve" band (Pisgah-style county list + highlighted map) ─────
   Dark ground; every colour restated for it (the light/dark trap). County cards
   on --primary, pins and the served counties in gold, the rest of the state in a
   quiet outline so the three counties read at a glance. */
.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-band > .wrap > div > p, .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); }
.county-card h3 a { color: var(--white); text-decoration: none; }
.county-card h3 a:hover, .county-card h3 a:focus-visible { color: var(--on-dark); text-decoration: underline; }
.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-also { display: flex; align-items: flex-start; gap: .45rem; margin: .2rem 0 0; color: var(--white); font-weight: 600; }
.areas-also .icon { color: var(--on-dark); flex: none; margin-top: .3em; }
.areas-actions { margin-top: 1.2rem; display: flex; flex-wrap: wrap; gap: .8rem; }
.areas-map { display: block; }
.nc-map { width: 100%; height: auto; display: block; }
.nc-map .c { fill: #161B21; stroke: #3A424B; stroke-width: .9; vector-effect: non-scaling-stroke; }
.nc-map .c.served { fill: var(--accent); stroke: var(--white); stroke-width: 1.4; }
/* Region mode (zoomed WNC + the SC / TN neighbours, 2026-10-05): the other states'
   counties sit back, state lines read as one quiet rule, regions are labelled not tinted. */
.region-map { overflow: hidden; border-radius: var(--radius); }
.nc-map .c.out { fill: #12161B; stroke: #2A3038; }
.nc-map .st { fill: none; stroke: #6B7480; stroke-width: 1.6; stroke-dasharray: 6 4; vector-effect: non-scaling-stroke; }
.nc-map .rg-label { fill: var(--muted-on-dark); font: 600 24px/1 Montserrat, sans-serif; letter-spacing: .14em; text-transform: uppercase; }
.nc-map .office { fill: var(--white); stroke: var(--primary-deep); stroke-width: 3; }
.nc-map .office-label { fill: var(--white); font: 700 26px/1 Montserrat, sans-serif; paint-order: stroke; stroke: var(--primary-deep); stroke-width: 5px; }
.nc-map .town { fill: none; stroke: var(--accent); stroke-width: 3; }
.nc-map .town-label { fill: var(--on-dark); font: 600 22px/1 Montserrat, sans-serif; paint-order: stroke; stroke: var(--primary-deep); stroke-width: 5px; }
.map-note { font-size: .85rem; color: var(--muted-on-dark); margin: .8rem auto 0; text-align: center; max-width: none !important; }

/* ── hero badge strip (Pisgah-style rotating seals, asked for 2026-10-01) ──────
   A white card that overlaps the hero's bottom edge and scrolls a row of badges
   continuously (CSS marquee, duplicated list, pauses on hover, static under
   reduced motion). Pisgah fills theirs with manufacturer and BBB logos; this one
   carries only CHECKABLE facts until the client proves a certification (Rule 27),
   and each badge is drawn as an inline SVG seal so nothing is a fake logo. */
/* The wrap straddles the seam: its top 2.6rem is transparent (the hero photo shows
   through), the rest is the stats bar's dark ground, so the white card reads as a
   card and the stats bar continues beneath it with no white gap. */
.hero-badges-wrap { position: relative; z-index: 2; margin-top: -2.6rem; width: 100%; max-width: none; padding: 0 1.25rem 1.6rem;
  background: linear-gradient(to bottom, transparent 2.6rem, var(--primary-deep) 2.6rem); }
.badge-set { display: contents; }
/* the strip overlaps the dark stats bar below it, so the bar opens with room for it */
.hero-badges { background: var(--white); border-radius: 18px; box-shadow: var(--shadow-lg); overflow: hidden;
  padding: .55rem 0; max-width: 980px; margin: 0 auto;
  -webkit-mask-image: linear-gradient(to right, transparent, #000 6%, #000 94%, transparent);
          mask-image: linear-gradient(to right, transparent, #000 6%, #000 94%, transparent); }
.badge-track { display: flex; gap: 2.2rem; width: max-content; padding: 0 1.1rem;
  animation: badge-scroll 34s linear infinite; }
.hero-badges:hover .badge-track, .hero-badges:focus-within .badge-track { animation-play-state: paused; }
@keyframes badge-scroll { from { transform: translateX(0); } to { transform: translateX(-50%); } }
.badge { display: inline-flex; align-items: center; gap: .7rem; padding: .55rem .4rem; white-space: nowrap; color: var(--ink); text-decoration: none; }
.badge-seal { flex: none; width: 52px; height: 52px; border-radius: 50%; display: inline-flex; align-items: center; justify-content: center;
  background: var(--primary); color: var(--on-dark); border: 3px solid var(--accent); }
.badge-seal.gold { background: var(--accent); color: var(--on-accent); border-color: var(--accent-hover); }
.badge-big { display: block; font-family: var(--font-head); font-weight: 800; font-size: 1.05rem; line-height: 1.1; color: var(--ink); }
.badge-small { display: block; font-size: .8rem; color: var(--muted); line-height: 1.2; margin-top: .15rem; }
a.badge:hover .badge-big, a.badge:focus-visible .badge-big { color: var(--accent-ink); text-decoration: underline; }
@media (prefers-reduced-motion: reduce) {
  .badge-track { animation: none; width: auto; flex-wrap: wrap; justify-content: center; gap: 1rem 1.6rem; padding: .3rem .8rem; }
  .badge-track > .badge-set[aria-hidden="true"] { display: none; }   /* the duplicate set only: icons are aria-hidden too */
  .hero-badges { -webkit-mask-image: none; mask-image: none; }
}
@media (max-width: 780px) { .hero-badges-wrap { margin-top: -1.6rem; background: linear-gradient(to bottom, transparent 1.6rem, var(--primary-deep) 1.6rem); } .badge-track { animation-duration: 26s; } }

/* ── process timeline (shape of the client's previous site, asked for 2026-10-01) ─
   Five steps in a row: an outlined gold circle holding the icon, a big faint
   number beside it, a thin rule linking the circles, title and one line under.
   On phones the steps stack and the rule goes away. Colours: the faint number is
   decorative (aria-hidden) and deliberately low-contrast, like the original; the
   title and copy carry the content at full contrast. */
.timeline { display: grid; grid-template-columns: repeat(5, 1fr); gap: 1.4rem; list-style: none; margin: 2.6rem 0 0; padding: 0; counter-reset: tl; }
.tl-step { position: relative; text-align: center; padding: 0 .4rem; }
.tl-mark { position: relative; display: flex; align-items: center; justify-content: center; gap: .6rem; height: 64px; margin-bottom: 1.1rem; }
.tl-icon { position: relative; z-index: 1; display: inline-flex; align-items: center; justify-content: center; width: 60px; height: 60px; border-radius: 50%;
  background: var(--white); border: 2px solid var(--accent); color: var(--accent-ink); }
/* The faint number is pure decoration, so it is drawn by CSS from a data attribute
   rather than placed in the DOM as text: screen readers never meet it and the
   contrast rules (which it fails on purpose, like the original) do not apply. */
.tl-num::before { content: attr(data-num); font-family: var(--font-head); font-weight: 800; font-size: 2.4rem; line-height: 1; color: var(--accent); opacity: .55; letter-spacing: -.02em; }
/* the connecting rule: drawn on each step from its circle to the next step's circle */
.tl-step::before { content: ""; position: absolute; top: 31px; left: 50%; width: 100%; height: 2px; background: var(--line); }
.tl-step:last-child::before { display: none; }
.tl-step h3 { font-size: 1.06rem; margin: 0 0 .45rem; color: var(--ink); }
.tl-step p { color: var(--muted); font-size: .95rem; line-height: 1.55; margin: 0; }
@media (max-width: 1080px) { .timeline { grid-template-columns: repeat(3, 1fr); row-gap: 2.4rem; } .tl-step:nth-child(3n)::before { display: none; } }
@media (max-width: 680px) {
  .timeline { grid-template-columns: 1fr; row-gap: 2.2rem; }
  .tl-step::before { display: none; }
}

/* ── financing block (shape of the reference site's three-step cards, 2026-10-01) ─
   Three light cards on the gold-tint band, each with a square icon badge hanging
   off its top-left corner, a title and one line; one button beneath. The badge
   sits half outside the card, so the list gets top room for it. */
.fin-steps { display: grid; grid-template-columns: repeat(3, 1fr); gap: 2rem; list-style: none; margin: 2.8rem 0 0; padding: 1.6rem 0 0; }
.fin-card { position: relative; background: var(--white); border: 1px solid var(--line); border-radius: var(--radius); padding: 3.2rem 1.6rem 1.6rem; box-shadow: var(--shadow); }
.fin-badge { position: absolute; top: -1.6rem; left: 1.6rem; width: 64px; height: 64px; border-radius: 14px; display: inline-flex; align-items: center; justify-content: center;
  background: var(--primary); color: var(--on-dark); border: 2px solid var(--accent); box-shadow: var(--shadow); }
.fin-card h3 { font-size: 1.12rem; margin: 0 0 .5rem; color: var(--ink); }
.fin-card p { color: var(--muted); font-size: .97rem; line-height: 1.55; margin: 0; }
.fin-section .svc-cta { margin-top: 2rem; }
.fin-note { text-align: center; color: var(--muted); font-size: .85rem; margin: 1rem auto 0; max-width: 60ch; }
.content-main .fin-note { text-align: left; margin-left: 0; }
.faq-q { text-wrap: balance; }
@media (max-width: 560px) { .content-main .area-list { display: grid; grid-template-columns: 1fr 1fr; gap: .2rem .8rem; } }
.btn-row { display: flex; flex-wrap: wrap; gap: .8rem; }
@media (max-width: 980px) { .fin-steps { grid-template-columns: 1fr; gap: 2.6rem; } }

/* Emergency storm-damage band (homepage, 2026-10-10) */
.storm-band { background: var(--primary-deep); color: var(--muted-on-dark); border-top: 3px solid var(--accent); }
.storm-grid { display: grid; grid-template-columns: auto minmax(0, 1fr) auto; gap: clamp(1.2rem, 3vw, 2.5rem); align-items: center; }
.storm-icon { width: 76px; height: 76px; border-radius: 50%; border: 2px solid var(--accent); display: grid; place-items: center; color: var(--on-dark); }
.storm-band .eyebrow { background: transparent; color: var(--on-dark); padding: 0; font-size: .9rem; margin-bottom: .4rem; }
.storm-band h2 { color: var(--white); margin: 0 0 .5rem; }
.storm-band p:not(.eyebrow) { margin: 0; max-width: 60ch; }
.storm-actions { display: flex; flex-direction: column; gap: .8rem; }
.storm-actions .btn { white-space: nowrap; justify-content: center; }
@media (max-width: 860px) {
  .storm-grid { grid-template-columns: 1fr; }
  .storm-actions { flex-direction: row; flex-wrap: wrap; }
}

/* Footer slogan, "Let's Go Roofing!" (Jeff's packaging, 2026-10-10) */
.footer-slogan { position: relative; display: inline-block; margin: 1.4rem 0 0; color: var(--accent); font: 400 clamp(1.7rem, 3vw, 2.1rem)/1.1 "Kaushan Script", cursive; transform: rotate(-4deg); transform-origin: left center; }
.footer-slogan span { text-transform: uppercase; font-size: 1.12em; letter-spacing: .02em; }
.footer-slogan svg { display: block; width: 88%; height: 10px; margin: .1rem 0 0 6%; }

/* Hero slogan, same script as the footer slogan (Jeff, 2026-10-10) */
.hero-slogan { margin: -.2rem 0 1rem; color: var(--accent); font: 400 clamp(1.45rem, 2.6vw, 2rem)/1.15 "Kaushan Script", cursive; transform: rotate(-2deg); transform-origin: left center; text-shadow: 0 2px 12px rgba(0,0,0,.55); }
