@import url('/fonts/plex.css');

/* --- Start: reset.css --- */
/* Modern CSS reset.
   Adapted from Andy Bell's https://piccalil.li/blog/a-more-modern-css-reset/
   plus the OVERHAUL-PLAN §2.12 requirement that media never overflow. */

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

/* Remove default margin */
body, h1, h2, h3, h4, h5, h6, p, figure, blockquote, dl, dd { margin: 0; }

/* Remove list styling on ul/ol that have an explicit role attribute */
ul[role='list'], ol[role='list'] { list-style: none; padding: 0; }

/* Set core body defaults */
body {
  min-height: 100vh;
  text-rendering: optimizeSpeed;
  line-height: 1.5;
}

/* A elements that don't have a class get default styles */
a:not([class]) { text-decoration-skip-ink: auto; }

/* Make images, video, svg easier to work with — never overflow their parent.
   Required by OVERHAUL-PLAN §1.9 ("no horizontal scroll ever"). */
img, video, svg, picture, canvas {
  max-width: 100%;
  height: auto;
  display: block;
}

/* SVG icons that should sit inline with text override .display = block via class. */

/* Inherit fonts for inputs and buttons */
input, button, textarea, select { font: inherit; }

/* Remove all animations and transitions for people that prefer not to see them */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* --- End: reset.css --- */

/* --- Start: tokens.css --- */
/* Generated by scripts/build-tokens.mjs - DO NOT EDIT BY HAND.
   Theme-neutral tokens plus light-theme color defaults on :root.
   Color tokens: from scripts/research/palettes.json (Direction A - Steel & Ember).
   Type tokens: from scripts/research/typography-final.md.
   Re-run `node scripts/build-tokens.mjs` to regenerate. */

:root {
  /* Type — locked in scripts/research/typography-final.md */
  --font-display: 'IBM Plex Serif', Georgia, serif;
  --font-body: 'IBM Plex Sans', -apple-system, BlinkMacSystemFont, 'Segoe UI', system-ui, sans-serif;
  --font-mono: ui-monospace, SFMono-Regular, Menlo, Consolas, monospace;

  --fw-regular: 400;
  --fw-medium: 500;
  --fw-semibold: 600;
  --fw-bold: 700;

  --fs-xs: 0.75rem;        /* 12px - chip / badge / small caption */
  --fs-sm: 0.875rem;       /* 14px - UI labels, breadcrumb */
  --fs-base: 1rem;         /* 16px - body prose, default */
  --fs-md: 1.0625rem;      /* 17px - lede paragraph */
  --fs-lg: 1.25rem;        /* 20px - h3 */
  --fs-xl: clamp(1.5rem, 1.2rem + 1.2vw, 1.875rem);   /* 24-30px - h2 */
  --fs-2xl: clamp(1.875rem, 1.4rem + 2vw, 2.5rem);    /* 30-40px - section h1 */
  --fs-hero: clamp(2.25rem, 1.6rem + 3.4vw, 3.5rem);  /* 36-56px - homepage hero */

  --lh-tight: 1.1;
  --lh-snug: 1.3;
  --lh-normal: 1.55;       /* Plex Sans-tuned, slightly looser than 1.5 */
  --lh-relaxed: 1.7;

  --ls-tight: -0.015em;
  --ls-normal: 0;
  --ls-wide: 0.06em;
  --ls-widest: 0.14em;

  /* Space — 4px ramp; section / container use clamp() for fluid mobile-first */
  --space-1: 0.25rem;      /* 4px */
  --space-2: 0.5rem;       /* 8px */
  --space-3: 0.75rem;      /* 12px */
  --space-4: 1rem;         /* 16px */
  --space-5: 1.5rem;       /* 24px */
  --space-6: 2rem;         /* 32px */
  --space-7: 3rem;         /* 48px */
  --space-8: 4rem;         /* 64px */
  --space-9: 6rem;         /* 96px */

  --space-container: clamp(1rem, 4vw, 2rem);
  --space-section: clamp(2.5rem, 1.5rem + 4vw, 5rem);

  /* Radius */
  --radius-sm: 4px;
  --radius: 6px;
  --radius-md: 8px;
  --radius-lg: 12px;
  --radius-pill: 999px;

  /* Shadow — light theme tint of warm navy. theme-dark.css overrides for dark surfaces. */
  --shadow-sm: 0 1px 2px rgba(20, 41, 58, 0.08);
  --shadow-md: 0 4px 12px rgba(20, 41, 58, 0.12);
  --shadow-lg: 0 12px 32px rgba(20, 41, 58, 0.16);
  --shadow-focus: 0 0 0 3px rgba(31, 78, 115, 0.35);  /* primary @ 35% */

  /* Motion — easing per OVERHAUL-PLAN §1.7 */
  --ease: cubic-bezier(0.22, 1, 0.36, 1);
  --dur-fast: 150ms;
  --dur-base: 250ms;
  --dur-slow: 600ms;

  /* z-index */
  --z-base: 1;
  --z-sticky: 50;
  --z-overlay: 100;
  --z-modal: 200;
  --z-toast: 300;

  /* Breakpoints — DOCUMENTARY ONLY.
     CSS custom properties cannot be used inside @media () queries. The values
     below are the canonical pixel values; @media queries elsewhere must use
     the literal numbers (e.g. @media (min-width: 768px) { ... }).
  */
  --bp-sm: 480px;
  --bp-md: 768px;
  --bp-lg: 1024px;
  --bp-xl: 1280px;

  /* Color - light theme as the :root default so a missing data-theme renders correctly. */
  --surface: #F7F2EA;
  --surface-2: #EDE5D6;
  --border: #D7CCB8;
  --text: #14293A;
  --text-muted: #5A6577;
  --primary: #1F4E73;
  --primary-fg: #FFFFFF;
  --accent: #B8761E;
  --accent-fg: #14293A;
  --danger: #B81C2A;
  --warn: #B8761E;
  --info: #1F4E73;
}

/* --- End: tokens.css --- */

/* --- Start: base.css --- */
/* Base — html, body, typography defaults, link defaults, focus rings, selection.
   Assumes tokens.css has loaded first so the var() references resolve. */


html {
  font-family: var(--font-body);
  /* Mobile-first body size, scales smoothly to desktop. 16px floor, 17px ceiling. */
  font-size: clamp(16px, 0.95rem + 0.15vw, 17px);
  line-height: var(--lh-normal);
  color: var(--text);
  background: var(--surface);
  -webkit-text-size-adjust: 100%;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

body {
  font-family: inherit;
  font-weight: var(--fw-regular);
  color: inherit;
  background: inherit;
  /* Prevent body from creating a horizontal scroll if a child overflows;
     real fix is per-component, this is the safety net. */
  overflow-x: clip;
}

/* Headings inherit display family. Component CSS sets size + weight per use case. */
h1, h2, h3 {
  font-family: var(--font-display);
  font-weight: var(--fw-bold);
  line-height: var(--lh-tight);
  letter-spacing: var(--ls-tight);
  color: var(--text);
}
h4, h5, h6 {
  font-family: var(--font-display);
  font-weight: var(--fw-semibold);
  line-height: var(--lh-snug);
  color: var(--text);
}

/* Paragraph defaults */
p { max-width: 68ch; }

/* Links */
a {
  color: var(--primary);
  text-decoration-color: color-mix(in srgb, var(--primary) 35%, transparent);
  text-underline-offset: 0.18em;
  transition: color var(--dur-fast) var(--ease),
              text-decoration-color var(--dur-fast) var(--ease);
}
a:hover { text-decoration-color: var(--primary); }

/* Visible focus ring on every focusable element using keyboard navigation. */
:focus-visible {
  outline: none;
  box-shadow: var(--shadow-focus);
  border-radius: var(--radius-sm);
}

/* Selection uses brand primary so highlighted copy reads on-brand. */
::selection {
  background: var(--primary);
  color: var(--primary-fg);
}

/* Code defaults */
code, kbd, samp, pre {
  font-family: var(--font-mono);
  font-size: 0.95em;
}

/* Horizontal rule */
hr {
  border: 0;
  border-top: 1px solid var(--border);
  margin: var(--space-7) 0;
}

/* Visually-hidden utility for screen-reader-only labels. */
.sr-only {
  position: absolute;
  width: 1px;
  height: 1px;
  padding: 0;
  margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

/* --- End: base.css --- */

/* --- Start: theme-light.css --- */
/* Generated by scripts/build-tokens.mjs - DO NOT EDIT BY HAND.
   Light-theme color tokens. Same as :root in tokens.css; provided for explicit data-theme="light" override of any future user-agent dark default.
   Color tokens: from scripts/research/palettes.json (Direction A - Steel & Ember).
   Type tokens: from scripts/research/typography-final.md.
   Re-run `node scripts/build-tokens.mjs` to regenerate. */

[data-theme="light"] {
  --surface: #F7F2EA;
  --surface-2: #EDE5D6;
  --border: #D7CCB8;
  --text: #14293A;
  --text-muted: #5A6577;
  --primary: #1F4E73;
  --primary-fg: #FFFFFF;
  --accent: #B8761E;
  --accent-fg: #14293A;
  --danger: #B81C2A;
  --warn: #B8761E;
  --info: #1F4E73;
}

/* --- End: theme-light.css --- */

/* --- Start: theme-dark.css --- */
/* Generated by scripts/build-tokens.mjs - DO NOT EDIT BY HAND.
   Dark-theme color tokens plus shadow overrides (rgba-navy shadows are invisible on the dark-navy surface in tokens.css, so we use deeper black-tinted shadows here).
   Color tokens: from scripts/research/palettes.json (Direction A - Steel & Ember).
   Type tokens: from scripts/research/typography-final.md.
   Re-run `node scripts/build-tokens.mjs` to regenerate. */

[data-theme="dark"] {
  --surface: #0F1A26;
  --surface-2: #16273A;
  --border: #2A3D55;
  --text: #EDE5D6;
  --text-muted: #9DA9B8;
  --primary: #5BA3D9;
  --primary-fg: #0F1A26;
  --accent: #E0993A;
  --accent-fg: #0F1A26;
  --danger: #E84654;
  --warn: #E0993A;
  --info: #5BA3D9;

  /* Shadow overrides for dark surfaces */
  --shadow-sm: 0 1px 2px rgba(0, 0, 0, 0.4);
  --shadow-md: 0 6px 16px rgba(0, 0, 0, 0.45);
  --shadow-lg: 0 16px 40px rgba(0, 0, 0, 0.55);
  --shadow-focus: 0 0 0 3px rgba(91, 163, 217, 0.4);  /* primary @ 40% */
}

/* --- End: theme-dark.css --- */

/* --- Start: layout.css --- */
/* Layout primitives — container, section spacing, simple grid utilities.
   No component-specific CSS in here; that lives in /assets/css/components/. */

.container {
  width: 100%;
  max-width: 1280px;
  margin-inline: auto;
  padding-inline: var(--space-container);
}

.container-narrow {
  width: 100%;
  max-width: 760px;
  margin-inline: auto;
  padding-inline: var(--space-container);
}

/* Wider container for full-bleed hero, footer, and any layout that should
   breathe on large monitors without looking awkward in the middle of a 1920px+
   viewport. Use sparingly — most content reads better at the standard 1280px. */
.container-wide {
  width: 100%;
  max-width: 1440px;
  margin-inline: auto;
  padding-inline: var(--space-container);
}

/* Section vertical rhythm. .section is the canonical wrapper for top-level
   page sections. .section-tight halves the vertical space for compact runs. */
.section {
  padding-block: var(--space-section);
}
.section-tight {
  padding-block: calc(var(--space-section) / 2);
}

/* Stack — vertical flow with a single gap token. Set --stack on the element to override. */
.stack { display: flex; flex-direction: column; gap: var(--stack, var(--space-4)); }
.stack-2 { --stack: var(--space-2); }
.stack-3 { --stack: var(--space-3); }
.stack-5 { --stack: var(--space-5); }
.stack-6 { --stack: var(--space-6); }

/* Cluster — horizontal wrap with a single gap token. Used for badge rows, button rows. */
.cluster {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--cluster, var(--space-3));
}

/* Auto-grid — responsive card grid. Items size themselves to fill the row down to a
   minimum of --grid-min before wrapping. Mobile-first: single column on narrow phones,
   multi-column when the row width allows it. */
.grid-auto {
  display: grid;
  gap: var(--grid-gap, var(--space-5));
  grid-template-columns: repeat(auto-fit, minmax(min(var(--grid-min, 18rem), 100%), 1fr));
}

/* Eyebrow / kicker text utility — used above headlines to introduce a section. */
.eyebrow {
  font-family: var(--font-body);
  font-weight: var(--fw-semibold);
  font-size: var(--fs-xs);
  letter-spacing: var(--ls-widest);
  text-transform: uppercase;
  color: var(--accent);
  margin-block-end: var(--space-2);
}

/* Visible "Last updated" line — paired with a <time datetime="..."> element
   so AI crawlers and SERP rich results pick up the freshness signal. Sits
   directly after the breadcrumb. Quiet byline styling: small muted text in
   normal case, no tracking. Reads as a corroborating date for the schema's
   dateModified, not as a banner section header. */
.last-updated {
  margin: 0;
  padding-block: var(--space-2);
  font-size: var(--fs-xs);
  color: var(--text-muted);
}
.last-updated time {
  color: var(--text-muted);
  font-weight: var(--fw-regular);
}

/* Hide an element below the named breakpoint. Mobile-first hide-until utilities.
   Pixel values match --bp-* tokens in tokens.css; CSS custom properties cannot be
   used inside @media queries so the values are repeated literally here. */
@media (max-width: 767.98px)  { .hide-md-down { display: none !important; } }
@media (max-width: 1023.98px) { .hide-lg-down { display: none !important; } }
@media (min-width: 768px)     { .hide-md-up   { display: none !important; } }
@media (min-width: 1024px)    { .hide-lg-up   { display: none !important; } }

/* Center utilities — sparingly. .text-center sets text-align; .center-flex
   centers a flex/cluster's children horizontally; .center-block centers an
   element itself within its parent block. */
.text-center  { text-align: center; }
.center-flex  { justify-content: center; }
.center-block { margin-inline: auto; }

/* Section intro block — eyebrow + h2 + lede pattern at the top of a section.
   Centered, prose-width capped, with bottom rhythm paired to --space-section. */
.section-intro {
  text-align: center;
  max-width: 720px;
  margin-inline: auto;
  margin-block-end: var(--space-7);
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

/* --- End: layout.css --- */

/* --- Start: components/badge.css --- */
/* badge.css — small chips for "IICRC Certified", "24/7", "EPA RRP", etc.
   Pill-shaped, uppercase, tracked.

   IMPORTANT — accent-fg constraint from brand-final.md note 4:
   The `--accent` fill paired with `--accent-fg` text passes WCAG AA-large only
   (4.01:1 in light theme). That's fine for chip-sized uppercase labels, which
   is the WCAG large-text definition. Do NOT reuse this pair behind body-prose
   sized text — at body size it would fail AA. If a future use case wants the
   ember as a fill behind paragraph copy, set color: var(--surface) instead.

   Variants: default (accent), primary (brand fill), outline (token-color text on
   transparent), danger (semantic, emergency-only). */

.badge {
  --badge-bg: var(--accent);
  --badge-fg: var(--accent-fg);
  --badge-border: transparent;

  display: inline-flex;
  align-items: center;
  gap: var(--space-2);

  padding: var(--space-1) var(--space-3);

  font-family: var(--font-body);
  font-size: var(--fs-xs);
  font-weight: var(--fw-semibold);
  line-height: 1.2;
  letter-spacing: var(--ls-wide);
  text-transform: uppercase;
  white-space: nowrap;

  background: var(--badge-bg);
  color: var(--badge-fg);
  border: 1px solid var(--badge-border);
  border-radius: var(--radius-pill);
}

.badge .icon {
  /* Slightly under cap-height so chip type and icon optically align. */
  width: 0.95em;
  height: 0.95em;
  flex: 0 0 auto;
}

/* Primary — brand fill. Use when the chip needs the same weight as a brand
   primary button (e.g. inline CTA in a card header). */
.badge-primary {
  --badge-bg: var(--primary);
  --badge-fg: var(--primary-fg);
  --badge-border: transparent;
}

/* Outline — transparent fill, primary-tinted text and border. Lighter weight
   than the accent fill; use for category tags inside a hero stack. */
.badge-outline {
  --badge-bg: transparent;
  --badge-fg: var(--primary);
  --badge-border: var(--primary);
}

/* Danger — emergency / Cat-3 / urgent. Use very sparingly; the red semantic
   is reserved for genuine emergency context per brand-final.md.
   Text is hard-coded white because the danger red is the same in both themes
   and white reads on red regardless. Using --primary-fg would give dark navy
   on red in dark mode. */
.badge-danger {
  --badge-bg: var(--danger);
  --badge-fg: #ffffff;
  --badge-border: transparent;
}

/* Subtle — muted surface chip. For non-emergency status (e.g. "draft",
   "archived"). Token-only colors so it stays AA in both themes. */
.badge-subtle {
  --badge-bg: var(--surface);
  --badge-fg: var(--text-muted);
  --badge-border: var(--border);
}

/* On-dark — outlined chip designed to sit on the hero scrim or any other
   dark-overlay surface. Foreground and border are fixed light values, not
   tokens, because the hero overlay is dark in both light and dark site themes. */
.badge-on-dark {
  --badge-bg: transparent;
  --badge-fg: #ffffff;
  --badge-border: rgba(255, 255, 255, 0.45);
}

/* --- End: components/badge.css --- */

/* --- Start: components/breadcrumb.css --- */
/* breadcrumb.css — page-location trail.
 *
 * Per OVERHAUL-PLAN §3.12: the full breadcrumb shows at 768px+. On smaller
 * viewports it collapses to a single "← Back" link pointing one level up.
 * The generator emits BOTH variants in the markup; CSS toggles which is shown.
 *
 * Architecture:
 *   <nav class="breadcrumb" aria-label="Breadcrumb">
 *     <a class="breadcrumb-back" href="../">
 *       <svg class="icon">…arrow-left…</svg> Back
 *     </a>
 *     <ol class="breadcrumb-trail">
 *       <li><a href="/">Home</a></li>
 *       <li><a href="/water-damage-restoration/">Water damage</a></li>
 *       <li aria-current="page">Holland, MI</li>
 *     </ol>
 *   </nav>
 *
 * Schema-org BreadcrumbList JSON-LD already lives in the page <head>; this
 * component is only the visual trail. */

.breadcrumb {
  font-family: var(--font-body);
  font-size: var(--fs-sm);
  color: var(--text-muted);
}

/* Mobile: show only the "← Back" link. */
.breadcrumb-back {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);

  min-height: 44px;            /* tap-target floor */
  padding-block: var(--space-2);

  font-weight: var(--fw-medium);
  color: var(--primary);
  text-decoration: none;
}
.breadcrumb-back .icon {
  width: 1em;
  height: 1em;
}
@media (hover: hover) and (pointer: fine) {
  .breadcrumb-back:hover { text-decoration: underline; text-underline-offset: 0.18em; }
}

.breadcrumb-trail {
  display: none;       /* hidden on mobile; .breadcrumb-back is shown instead */
  list-style: none;
  margin: 0;
  padding: 0;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-1) var(--space-2);
}
.breadcrumb-trail li {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  min-width: 0;
}
/* Generator emits a token chevron between items via ::after on each li
   except the last — keeps markup clean. */
.breadcrumb-trail li:not(:last-child)::after {
  content: '/';
  color: var(--text-muted);
  opacity: 0.6;
  font-size: var(--fs-sm);
  /* Use a slash instead of an SVG chevron to keep the breadcrumb a single
     text-only line with no inline SVG-per-item cost. */
}
.breadcrumb-trail a {
  color: var(--text-muted);
  text-decoration: none;
  transition: color var(--dur-fast) var(--ease);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 24ch;
}
@media (hover: hover) and (pointer: fine) {
  .breadcrumb-trail a:hover {
    color: var(--primary);
    text-decoration: underline;
    text-underline-offset: 0.18em;
  }
}
.breadcrumb-trail [aria-current="page"] {
  color: var(--text);
  font-weight: var(--fw-semibold);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 32ch;
}

/* md+ : show the full trail, hide the back link. */
@media (min-width: 768px) {
  .breadcrumb-back { display: none; }
  .breadcrumb-trail { display: flex; }
}

/* --- End: components/breadcrumb.css --- */

/* --- Start: components/button.css --- */
/* button.css — variants: primary (brand), emergency (danger), secondary (outline-on-primary),
   ghost (outline-on-text). All variants share base sizing and motion.

   Tap-target rule: min-height 44px on every breakpoint. Padding stays comfortable on
   desktop; the floor is mobile, not a separate desktop override.

   Hover transforms are color/border only on touch devices (hover: none); fine-pointer
   devices also get a 1px translateY lift. Per OVERHAUL-PLAN §1.7 — no scale, no rotate. */

.btn {
  --btn-bg: var(--primary);
  --btn-fg: var(--primary-fg);
  --btn-border: transparent;
  --btn-bg-hover: color-mix(in srgb, var(--primary) 85%, var(--text));

  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);

  min-height: 44px;
  padding: var(--space-3) var(--space-5);

  font-family: var(--font-body);
  font-weight: var(--fw-semibold);
  font-size: var(--fs-sm);
  line-height: 1;
  letter-spacing: 0;
  text-decoration: none;
  white-space: nowrap;

  background: var(--btn-bg);
  color: var(--btn-fg);
  border: 1px solid var(--btn-border);
  border-radius: var(--radius);
  cursor: pointer;

  transition:
    background var(--dur-fast) var(--ease),
    color var(--dur-fast) var(--ease),
    border-color var(--dur-fast) var(--ease),
    transform var(--dur-fast) var(--ease);
  -webkit-tap-highlight-color: transparent;
}

/* Hover lift only on fine-pointer devices. Touch devices get color shift only,
   so a tap doesn't leave the button stuck in a "lifted" state. */
@media (hover: hover) and (pointer: fine) {
  .btn:hover {
    background: var(--btn-bg-hover);
    transform: translateY(-1px);
  }
}

.btn:active { transform: translateY(0); }

.btn[disabled],
.btn[aria-disabled="true"] {
  opacity: 0.55;
  cursor: not-allowed;
  transform: none;
}

.btn .icon {
  width: 1.05em;
  height: 1.05em;
  flex: 0 0 auto;
}

/* Primary — brand. Default variant if no modifier class is set. */
.btn-primary {
  --btn-bg: var(--primary);
  --btn-fg: var(--primary-fg);
  --btn-border: transparent;
  --btn-bg-hover: color-mix(in srgb, var(--primary) 85%, var(--text));
}

/* Emergency — danger red. Reserved for the call CTA and urgency banners.
   Per brand-final.md: red is semantic.danger only, never a brand fill.
   Text is hard-coded white (NOT --primary-fg) because the danger red is the
   same in both themes, so white is correct in both — using --primary-fg
   would give dark navy text in dark mode. */
.btn-emergency {
  --btn-bg: var(--danger);
  --btn-fg: #ffffff;
  --btn-border: transparent;
  --btn-bg-hover: color-mix(in srgb, var(--danger) 88%, var(--text));
}

/* Secondary — accented outline. Used next to a primary button to offer a
   second-tier action without competing visually. */
.btn-secondary {
  --btn-bg: transparent;
  --btn-fg: var(--primary);
  --btn-border: var(--primary);
  --btn-bg-hover: color-mix(in srgb, var(--primary) 12%, transparent);
}

/* Ghost — minimal chrome. Used in headers and toolbars where a full fill would
   compete with surrounding content. */
.btn-ghost {
  --btn-bg: transparent;
  --btn-fg: var(--text);
  --btn-border: var(--border);
  --btn-bg-hover: var(--surface-2);
}

/* Size modifiers. Default is "comfortable". Use sparingly. */
.btn-sm {
  min-height: 36px;
  padding: var(--space-2) var(--space-4);
  font-size: var(--fs-xs);
}
.btn-lg {
  min-height: 52px;
  padding: var(--space-4) var(--space-6);
  font-size: var(--fs-base);
}

/* Icon-only button. Used for the theme toggle and similar header-bar controls.
   Keeps the 44px tap-target floor. */
.btn-icon {
  width: 44px;
  min-height: 44px;
  padding: 0;
  border-radius: var(--radius);
}
.btn-icon .icon {
  width: 1.25em;
  height: 1.25em;
}

/* On-dark — modifier for buttons that sit on the hero scrim or other dark-overlay
   surfaces. Pairs with .btn-secondary and .btn-ghost. The hero scrim is dark in
   both light and dark site themes, so these values are fixed light, not tokens. */
.btn-on-dark.btn-secondary,
.btn-on-dark.btn-ghost {
  --btn-fg: #ffffff;
  --btn-border: rgba(255, 255, 255, 0.5);
  --btn-bg-hover: rgba(255, 255, 255, 0.12);
}

/* --- End: components/button.css --- */

/* --- Start: components/card.css --- */
/* card.css — content cards. Neutral surface, theme-aware.
   The grid that holds them is .grid-auto in layout.css; this file only styles
   the card itself, not its placement. */

.card {
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: var(--space-5);
  box-shadow: var(--shadow-sm);
  display: flex;
  flex-direction: column;
  gap: var(--space-3);

  transition:
    transform var(--dur-base) var(--ease),
    box-shadow var(--dur-base) var(--ease),
    border-color var(--dur-base) var(--ease);
}

/* Card-as-link: when the entire card is a clickable <a>, kill the default
   underline and tint. */
a.card {
  color: var(--text);
  text-decoration: none;
}

/* Hover lift, fine-pointer only — touch devices skip translate so a tap doesn't
   leave the card stuck in a "lifted" state. Opt-in via .card-hover for static
   cards; <a class="card"> gets it automatically. */
@media (hover: hover) and (pointer: fine) {
  .card-hover:hover,
  a.card:hover {
    transform: translateY(-2px);
    box-shadow: var(--shadow-md);
    border-color: color-mix(in srgb, var(--primary) 30%, var(--border));
  }
}

/* Sub-parts. Generators should compose these, not invent their own classes. */
.card-eyebrow {
  font-size: var(--fs-xs);
  font-weight: var(--fw-semibold);
  letter-spacing: var(--ls-widest);
  text-transform: uppercase;
  color: var(--accent);
}

.card-title {
  font-family: var(--font-display);
  font-size: var(--fs-lg);
  font-weight: var(--fw-bold);
  line-height: var(--lh-snug);
  letter-spacing: var(--ls-tight);
  color: var(--text);
  margin: 0;
}

.card-body {
  font-size: var(--fs-base);
  color: var(--text-muted);
  margin: 0;
}

.card-foot {
  margin-top: auto;        /* pin actions to the bottom of mixed-height cards */
  padding-top: var(--space-2);
}

/* When a <ul> appears inside a card it should sit flush — no list-marker, no
   default padding-inline, single source of truth on the gap (handled by
   .stack which the markup wraps the <ul> with). */
.card > ul {
  list-style: none;
  padding: 0;
  margin: 0;
}

/* <address> in a card body — strip browser-default italic. The element
   carries semantic meaning (it's an address, screen readers announce it)
   so we don't replace the tag, we just normalize the appearance. */
.card address {
  font-style: normal;
  line-height: var(--lh-normal);
}

/* Compact card — denser padding for grids of small chips. */
.card-compact {
  padding: var(--space-4);
  gap: var(--space-2);
}

/* Featured card — accent left border to draw the eye. Use sparingly. */
.card-featured {
  border-left: 3px solid var(--accent);
}

/* --- End: components/card.css --- */

/* --- Start: components/emergency-bar.css --- */
/* emergency-bar.css — top-of-page red strip + sticky bottom mobile CTA.
 *
 * Two related but distinct components share this file because they share the
 * same data (the phone number, the 24/7 messaging) and the same emergency-red
 * surface treatment.
 *
 * 1) Top emergency bar — short status line above the site header.
 * 2) Sticky bottom CTA — phone-call bar pinned to the bottom of mobile
 *    viewports below 768px. Per OVERHAUL-PLAN §1.9.5 ("the phone number
 *    should be a tap away from anywhere on the page").
 *
 * Architecture:
 *   <div class="emergency-bar">
 *     <div class="container emergency-bar-inner">
 *       <span class="emergency-bar-item"><svg>…</svg> 24/7/365 emergency response</span>
 *       <span class="emergency-bar-item"><svg>…</svg> Average response under 60 minutes</span>
 *     </div>
 *   </div>
 *
 *   <a class="sticky-call" href="tel:6168221978">
 *     <svg>…</svg>
 *     <span class="sticky-call-label">Call (616) 822-1978</span>
 *     <span class="sticky-call-sub">24/7 emergency · Walker, MI</span>
 *   </a>
 */

/* ── Top emergency bar ─────────────────────────────────────────────────── */

.emergency-bar {
  background: var(--danger);
  color: #ffffff;
  font-size: var(--fs-xs);
  font-weight: var(--fw-semibold);
  letter-spacing: var(--ls-wide);
  text-transform: uppercase;
}

.emergency-bar-inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--space-1);

  padding-block: var(--space-2);
  text-align: center;
}
@media (min-width: 768px) {
  .emergency-bar-inner {
    flex-direction: row;
    justify-content: center;
    gap: var(--space-5);
    text-align: left;
  }
}

.emergency-bar-item {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
}
.emergency-bar-item .icon {
  width: 1em;
  height: 1em;
  flex: 0 0 auto;
}
.emergency-bar a {
  color: inherit;
  text-decoration: underline;
  text-underline-offset: 0.18em;
}

/* ── Sticky bottom mobile CTA ──────────────────────────────────────────── */

.sticky-call {
  /* Phone-only by default; hidden at md+. */
  display: flex;
  align-items: center;
  gap: var(--space-3);

  position: fixed;
  inset: auto 0 0 0;
  z-index: var(--z-sticky);

  padding: var(--space-3) var(--space-4);
  /* iOS safe-area padding so the bar clears the home indicator. */
  padding-bottom: calc(var(--space-3) + env(safe-area-inset-bottom, 0px));

  background: var(--danger);
  color: #ffffff;
  text-decoration: none;
  box-shadow: 0 -4px 16px rgba(15, 26, 38, 0.35);

  /* The whole bar IS the tap target. Min 56px is generous on purpose; this is
     the most-used button on a mobile emergency page. */
  min-height: 56px;
  font-family: var(--font-body);
}
.sticky-call .icon {
  width: 1.4em;
  height: 1.4em;
  flex: 0 0 auto;
}
.sticky-call-label {
  font-size: var(--fs-base);
  font-weight: var(--fw-bold);
  line-height: 1.1;
}
.sticky-call-sub {
  display: block;
  font-size: var(--fs-xs);
  font-weight: var(--fw-regular);
  opacity: 0.92;
  margin-top: 2px;
}
.sticky-call-text {
  display: flex;
  flex-direction: column;
  flex: 1 1 auto;
  min-width: 0;
}
.sticky-call-arrow {
  margin-left: auto;
  width: 1.1em;
  height: 1.1em;
  flex: 0 0 auto;
  opacity: 0.85;
}

@media (hover: hover) and (pointer: fine) {
  .sticky-call:hover {
    background: color-mix(in srgb, var(--danger) 88%, var(--text));
  }
}

@media (min-width: 768px) {
  /* The desktop header CTA covers this need; the sticky bar only exists on
     small viewports. */
  .sticky-call { display: none; }
}

/* When the sticky-call is present, push body content up so the last paragraph
   isn't hidden under the bar. Generators add .has-sticky-call to <body>. */
@media (max-width: 767.98px) {
  body.has-sticky-call {
    padding-bottom: calc(72px + env(safe-area-inset-bottom, 0px));
  }
}

/* Static-preview override — used only by the components harness to render the
   sticky-call inline alongside other components. Real pages never use this. */
.sticky-call.is-static-preview {
  position: static;
  box-shadow: var(--shadow-md);
  border-radius: var(--radius);
  display: flex;
}
@media (min-width: 768px) {
  .sticky-call.is-static-preview { display: flex; }
}

/* --- End: components/emergency-bar.css --- */

/* --- Start: components/faq.css --- */
/* faq.css — accordion built on <details>/<summary> for keyboard, touch, and
 * screen-reader baseline. Same a11y rationale as the nav dropdown.
 *
 * Architecture:
 *   <div class="faq">
 *     <details class="faq-item">
 *       <summary class="faq-question">
 *         Question text
 *         <svg class="faq-chevron">…chevron-down…</svg>
 *       </summary>
 *       <div class="faq-answer">
 *         <p>Answer paragraph(s).</p>
 *       </div>
 *     </details>
 *   </div>
 *
 * No height animation on the body. Animating <details> open/close cleanly
 * requires either the new interpolate-size: allow-keywords (Chrome 129+, not
 * universal in 2026) or a JS height-measure trick. KISS: use a fade + slight
 * translate on the answer instead. The chevron rotates. That's enough motion. */

.faq {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.faq-item {
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  overflow: hidden;
  transition: border-color var(--dur-fast) var(--ease);
}
.faq-item[open] {
  border-color: color-mix(in srgb, var(--primary) 40%, var(--border));
}

.faq-question {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);

  min-height: 56px;
  padding: var(--space-4) var(--space-5);

  font-family: var(--font-display);
  font-weight: var(--fw-bold);
  font-size: var(--fs-base);
  line-height: var(--lh-snug);
  color: var(--text);
  cursor: pointer;
  list-style: none;
  user-select: none;

  transition: background var(--dur-fast) var(--ease);
}
.faq-question::-webkit-details-marker { display: none; }
.faq-question::marker { content: ''; }

@media (hover: hover) and (pointer: fine) {
  .faq-question:hover {
    background: color-mix(in srgb, var(--primary) 6%, var(--surface-2));
  }
}

.faq-chevron {
  width: 1.1em;
  height: 1.1em;
  flex: 0 0 auto;
  color: var(--accent);
  transition: transform var(--dur-base) var(--ease);
}
.faq-item[open] .faq-chevron {
  transform: rotate(180deg);
}

.faq-answer {
  padding: 0 var(--space-5) var(--space-5);
  color: var(--text-muted);
  font-size: var(--fs-base);
  line-height: var(--lh-normal);
  border-top: 1px solid var(--border);
  padding-top: var(--space-4);
  animation: faq-answer-in var(--dur-base) var(--ease);
}
.faq-answer > :first-child { margin-top: 0; }
.faq-answer > :last-child  { margin-bottom: 0; }
.faq-answer p { max-width: 70ch; }
.faq-answer a { color: var(--primary); }

@keyframes faq-answer-in {
  from { opacity: 0; transform: translateY(-2px); }
  to   { opacity: 1; transform: translateY(0); }
}

@media (prefers-reduced-motion: reduce) {
  .faq-chevron { transition: none; }
  .faq-answer { animation: none; }
}

/* --- End: components/faq.css --- */

/* --- Start: components/footer.css --- */
/* footer.css — multi-column site footer.
 *
 * The 4-item primary nav (Option B, locked in 3.1) demoted Blog and Contact
 * out of the header. The footer is where they live now, so the column layout
 * here is load-bearing for site navigation, not just visual filler.
 *
 * Architecture:
 *   <footer class="site-footer">
 *     <div class="container site-footer-inner">
 *       <div class="site-footer-brand">
 *         <a class="site-footer-logo" href="/">…logo…</a>
 *         <p class="site-footer-tagline">…</p>
 *         <div class="cluster">…badges…</div>
 *       </div>
 *
 *       <nav class="site-footer-nav" aria-label="Footer">
 *         <div class="site-footer-col">
 *           <h2 class="site-footer-heading">Services</h2>
 *           <ul>…</ul>
 *         </div>
 *         <div class="site-footer-col">
 *           <h2 class="site-footer-heading">Company</h2>
 *           <ul>…About / Contact / Service areas…</ul>
 *         </div>
 *         <div class="site-footer-col">
 *           <h2 class="site-footer-heading">Resources</h2>
 *           <ul>…Blog / Answers / Insurance guides…</ul>
 *         </div>
 *       </nav>
 *     </div>
 *
 *     <div class="container site-footer-bottom">
 *       <p>&copy; …</p>
 *       <ul>…privacy / terms / sitemap…</ul>
 *     </div>
 *   </footer>
 */

.site-footer {
  background: var(--surface-2);
  border-top: 1px solid var(--border);
  color: var(--text);
  margin-top: var(--space-9);
}

/* Top region: brand block + columns. Stacks on mobile, splits at md. */
.site-footer-inner {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-6);
  padding-block: var(--space-7);
}
@media (min-width: 768px) {
  .site-footer-inner {
    grid-template-columns: minmax(220px, 1fr) 2fr;
    gap: var(--space-8);
  }
}

.site-footer-brand {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}
.site-footer-logo {
  display: inline-flex;
  align-items: center;
  text-decoration: none;
  color: inherit;
}
.site-footer-logo img {
  height: 44px;
  width: auto;
  display: block;
}
.site-footer-tagline {
  font-size: var(--fs-sm);
  color: var(--text-muted);
  margin: 0;
  max-width: 36ch;
}

/* Column grid — 1 col on mobile, 3 cols at md+. */
.site-footer-nav {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-5);
}
@media (min-width: 480px) {
  .site-footer-nav { grid-template-columns: repeat(2, 1fr); }
}
@media (min-width: 768px) {
  .site-footer-nav { grid-template-columns: repeat(3, 1fr); }
}

.site-footer-col ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}
.site-footer-heading {
  font-family: var(--font-body);
  font-size: var(--fs-xs);
  font-weight: var(--fw-semibold);
  letter-spacing: var(--ls-widest);
  text-transform: uppercase;
  color: var(--text-muted);
  margin: 0 0 var(--space-3);
}
.site-footer-col a {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);

  font-family: var(--font-body);
  font-size: var(--fs-sm);
  font-weight: var(--fw-medium);
  color: var(--text);
  text-decoration: none;
  padding-block: var(--space-1);
  transition: color var(--dur-fast) var(--ease);
}
.site-footer-col a .icon {
  width: 0.95em;
  height: 0.95em;
  color: var(--accent);
}
@media (hover: hover) and (pointer: fine) {
  .site-footer-col a:hover { color: var(--primary); }
}

/* Bottom strip: copyright + legal links. */
.site-footer-bottom {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);

  padding-block: var(--space-5);
  border-top: 1px solid var(--border);

  font-size: var(--fs-xs);
  color: var(--text-muted);
}
@media (min-width: 768px) {
  .site-footer-bottom {
    flex-direction: row;
    align-items: center;
    justify-content: space-between;
    gap: var(--space-5);
  }
}
.site-footer-bottom p { margin: 0; }
.site-footer-bottom ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-4);
}
.site-footer-bottom a {
  color: var(--text-muted);
  text-decoration: none;
  transition: color var(--dur-fast) var(--ease);
}
@media (hover: hover) and (pointer: fine) {
  .site-footer-bottom a:hover { color: var(--text); }
}

/* --- End: components/footer.css --- */

/* --- Start: components/hero.css --- */
/* hero.css — full-bleed media hero. Replaces the broken homepage hero
 * documented in OVERHAUL-PLAN §2.2 (small video stuck bottom-right with the
 * browser "download video" badge sitting on top of it).
 *
 * Architecture:
 *   <section class="hero">
 *     <div class="hero-media">
 *       <video class="hero-video" autoplay muted loop playsinline
 *              poster="/images/hero/poster.webp"
 *              controlsList="nodownload" oncontextmenu="return false">
 *         <source src="/images/hero/vanvideo.mp4" type="video/mp4">
 *       </video>
 *     </div>
 *     <div class="hero-overlay" aria-hidden="true"></div>
 *     <div class="container hero-content">
 *       <div class="hero-badges cluster">…</div>
 *       <span class="eyebrow">…</span>
 *       <h1 class="hero-title">…</h1>
 *       <p class="hero-lede">…</p>
 *       <div class="hero-actions cluster">…</div>
 *     </div>
 *   </section>
 *
 * Mobile cellular-cost rule (OVERHAUL-PLAN §1.9.8): the <video> is HIDDEN
 * below 768px. The poster image painted by the browser is the entire mobile
 * hero. Phase 6.10 will ship the compressed video; until then the poster does
 * 100% of the work on phones, which is the correct default anyway.
 *
 * Phase 4.1 picks the actual hero asset (still vs video). This component
 * supports both via the same .hero-media slot. */

.hero {
  position: relative;
  isolation: isolate;          /* contain stacking context for ::before / overlay */

  /* Min-height tuned per breakpoint. Mobile floor is fixed; desktop uses dvh
     so address-bar collapse on iOS doesn't cause a layout jump. Caps at 720px
     so the hero never eats the entire scroll on a 4K monitor. */
  min-height: 520px;
  display: flex;
  align-items: center;
  overflow: hidden;
  color: #ffffff;              /* default content color sits on the dark scrim — hard-coded, NOT --primary-fg, since the token inverts in dark mode */
}

@media (min-width: 768px) {
  .hero { min-height: min(72dvh, 640px); }
}
@media (min-width: 1024px) {
  .hero { min-height: min(80dvh, 720px); }
}

/* ── Media layer ────────────────────────────────────────────────────────
   Sits behind everything (z-index 0). The overlay sits at z-index 1.
   Content sits at z-index 2 (the .hero-content default in the cascade).
   Video and poster image both stretch to fill via object-fit: cover. */

.hero-media {
  position: absolute;
  inset: 0;
  z-index: 0;
  background: var(--surface-2);  /* placeholder color while media loads */
}
/* Both <img> and <video> overlay the same box so swapping is a display:none
   toggle, not a flow rearrangement. Without `position: absolute` here the
   image and video stack vertically and the video gets clipped by overflow. */
.hero-media > img,
.hero-media > video {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  display: block;
}

/* Mobile (<768px): hide the video entirely so it doesn't auto-play on
   cellular per OVERHAUL-PLAN §1.9.8. The <img> poster carries the hero.
   Desktop (>=768px): hide the duplicate <img> and show the video.
   prefers-reduced-motion (handled below) hides the video at every breakpoint
   and the image takes over again. */
.hero-video { display: none; }
@media (min-width: 768px) {
  .hero-video { display: block; }
  .hero-poster-mobile { display: none; }
}
@media (prefers-reduced-motion: reduce) {
  .hero-poster-mobile { display: block !important; }
}

/* ── Overlay scrim ─────────────────────────────────────────────────────
   Dark gradient anchored at the bottom-left so headline text sits over the
   darkest area. Uses a fixed dark color (not a token) because the hero is the
   one place where text-on-media must stay light regardless of theme. */

.hero-overlay {
  position: absolute;
  inset: 0;
  z-index: 1;
  background:
    linear-gradient(135deg,
      rgba(15, 26, 38, 0.88) 0%,
      rgba(15, 26, 38, 0.72) 45%,
      rgba(15, 26, 38, 0.55) 100%);
}

/* ── Content stack ─────────────────────────────────────────────────────
   The container handles horizontal padding. Inside, content stacks with
   spacing tokens — no inline padding/margin overrides. */

.hero-content {
  position: relative;
  z-index: 2;
  padding-block: var(--space-8);
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
  max-width: 880px;
}

.hero-badges { gap: var(--space-2); }

.hero-title {
  font-family: var(--font-display);
  font-weight: var(--fw-bold);
  font-size: var(--fs-hero);
  line-height: var(--lh-tight);
  letter-spacing: var(--ls-tight);
  margin: 0;
  /* Hard-coded white — NOT --primary-fg. The token inverts meaning between
     themes (white in light, dark navy in dark) because it's the foreground for
     primary fills. The hero scrim is always dark in BOTH themes, so the text
     must always be light. */
  color: #ffffff;
  text-wrap: balance;
  max-width: 24ch;
}
.hero-title strong {
  /* The locked accent for emphasis inside the headline. Uses the lifted dark
     accent so it reads on the dark scrim regardless of light/dark site theme. */
  color: #E0993A;
  font-weight: inherit;
}

.hero-lede {
  font-family: var(--font-body);
  font-size: var(--fs-md);
  line-height: var(--lh-normal);
  margin: 0;
  max-width: 56ch;
  color: rgba(255, 255, 255, 0.88);
}

/* Defensive overrides — base.css applies dark colors to all h1/h2/h3 and
   inherits color from body. The hero sits on a dark scrim and needs light
   text regardless of site theme. These rules override the cascade. */
.hero h1,
.hero h2,
.hero h3,
.hero h4,
.hero h5,
.hero h6 {
  color: #ffffff;
}
.hero p,
.hero li {
  color: rgba(255, 255, 255, 0.92);
}

.hero-actions {
  margin-top: var(--space-2);
}

/* ── Eyebrow override for the hero ─────────────────────────────────────
   The default .eyebrow uses --accent which on light theme is the desaturated
   ember (#B8761E). On the dark scrim that hue lacks luminance. Use the dark-
   theme lifted accent unconditionally inside the hero. */
.hero .eyebrow {
  color: #E0993A;
}

/* ── Reduced motion ─────────────────────────────────────────────────────
   Stop the looping video for users who request reduced motion. The poster
   <img> (.hero-poster-mobile, restored to display:block in the rule above)
   takes over. Per OVERHAUL-PLAN §1.7.4. */
@media (prefers-reduced-motion: reduce) {
  .hero-video { display: none !important; }
}

/* --- End: components/hero.css --- */

/* --- Start: components/nav.css --- */
/* nav.css — site header, primary nav, Services dropdown, mobile overlay.
 *
 * Structure (HTML, illustrative — generator emits this in Phase 3.D):
 *
 * <header class="site-header">
 *   <div class="container site-header-inner">
 *     <a class="site-logo" href="/">…</a>
 *     <nav class="site-nav" aria-label="Primary">
 *       <ul class="site-nav-list">
 *         <li class="site-nav-item">
 *           <details class="site-nav-dropdown">
 *             <summary>Services <svg class="icon">…chevron</svg></summary>
 *             <ul class="site-nav-submenu">…service links…</ul>
 *           </details>
 *         </li>
 *         <li class="site-nav-item"><a href="/about/">About</a></li>
 *         <li class="site-nav-item"><a href="/insurance-claims/">Insurance</a></li>
 *       </ul>
 *     </nav>
 *     <div class="site-header-actions">
 *       <button class="btn btn-icon btn-ghost theme-toggle-btn" data-theme-toggle …>
 *       <a class="btn btn-emergency" href="tel:…">Call</a>
 *     </div>
 *     <button class="site-nav-toggle" aria-controls="mobile-overlay" aria-expanded="false">…burger…</button>
 *   </div>
 * </header>
 *
 * <div id="mobile-overlay" class="mobile-overlay" hidden> … </div>
 *
 * Nav model: Option B (locked 2026-05-18). Desktop primary = Services ▾ · About · Insurance · CTA.
 * Blog and Contact intentionally moved to footer; full list still appears in the mobile overlay.
 *
 * Dropdown a11y: built on <details>/<summary> so keyboard, touch, and screen readers all work
 * with zero JS. A `:hover { open }` enhancement lights up on fine-pointer devices only.
 * Full ARIA menubar / arrow-key nav is deferred to Phase 6 polish if real users need it. */

/* ── Header shell ──────────────────────────────────────────────────────── */

.site-header {
  position: sticky;
  top: 0;
  z-index: var(--z-sticky);
  background: var(--surface);
  border-bottom: 1px solid var(--border);
  /* When sticky, the header is above content; a soft shadow communicates layering
     without being a full drop shadow that competes with hero content. */
  box-shadow: 0 1px 0 0 transparent;
  transition: box-shadow var(--dur-fast) var(--ease);
}
.site-header[data-scrolled="true"] {
  box-shadow: var(--shadow-sm);
}

.site-header-inner {
  display: flex;
  align-items: center;
  gap: var(--space-5);
  min-height: 64px;
  padding-block: var(--space-2);
}

/* Logo */
.site-logo {
  display: inline-flex;
  align-items: center;
  flex: 0 0 auto;
  text-decoration: none;
  color: inherit;
}
.site-logo img {
  /* The current brand image is 220×60. Constrain it so it never blows past the
     header height regardless of intrinsic dimensions. */
  height: 40px;
  width: auto;
  display: block;
}

/* ── Primary nav (desktop) ─────────────────────────────────────────────── */

.site-nav {
  /* Hidden under the mobile overlay breakpoint; the mobile-overlay <nav>
     handles small viewports. Mobile-first: hide by default, show at md. */
  display: none;
  flex: 1 1 auto;
  justify-content: center;
}

.site-nav-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  align-items: center;
  gap: var(--space-5);
}

.site-nav-item > a,
.site-nav-dropdown > summary {
  display: inline-flex;
  align-items: center;
  gap: var(--space-1);

  /* 44px tap-target floor with vertically-centered text. */
  min-height: 44px;
  padding: var(--space-2) var(--space-3);

  font-family: var(--font-body);
  font-size: var(--fs-sm);
  font-weight: var(--fw-medium);
  color: var(--text);
  text-decoration: none;
  border-radius: var(--radius);
  cursor: pointer;
  list-style: none;            /* kill default <summary> disclosure marker */
  transition: background var(--dur-fast) var(--ease),
              color var(--dur-fast) var(--ease);
}
.site-nav-dropdown > summary::-webkit-details-marker { display: none; } /* Safari */
.site-nav-dropdown > summary::marker { content: ''; }

@media (hover: hover) and (pointer: fine) {
  .site-nav-item > a:hover,
  .site-nav-dropdown > summary:hover {
    background: var(--surface-2);
    color: var(--primary);
  }
}

/* Current-page highlight. Generator sets aria-current="page" on the active link. */
.site-nav-item > a[aria-current="page"] {
  color: var(--primary);
  background: color-mix(in srgb, var(--primary) 10%, transparent);
}

/* ── Services dropdown ─────────────────────────────────────────────────── */

.site-nav-dropdown {
  position: relative;
}

/* Chevron rotates when open. The summary itself stays on a single baseline. */
.site-nav-dropdown > summary .icon {
  width: 0.85em;
  height: 0.85em;
  transition: transform var(--dur-fast) var(--ease);
}
.site-nav-dropdown[open] > summary .icon {
  transform: rotate(180deg);
}

.site-nav-submenu {
  position: absolute;
  top: calc(100% + 4px);
  left: 0;
  z-index: var(--z-overlay);

  list-style: none;
  margin: 0;
  padding: var(--space-2);

  min-width: 240px;
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-md);

  display: flex;
  flex-direction: column;
  gap: 2px;
}

.site-nav-submenu a {
  display: flex;
  align-items: center;
  gap: var(--space-2);

  min-height: 40px;
  padding: var(--space-2) var(--space-3);

  font-size: var(--fs-sm);
  font-weight: var(--fw-medium);
  color: var(--text);
  text-decoration: none;
  border-radius: var(--radius-sm);
  transition: background var(--dur-fast) var(--ease),
              color var(--dur-fast) var(--ease);
}
.site-nav-submenu a .icon {
  color: var(--accent);
  width: 1em;
  height: 1em;
}
@media (hover: hover) and (pointer: fine) {
  .site-nav-submenu a:hover {
    background: var(--surface-2);
    color: var(--primary);
  }
}

/* Hover-enhancement: on fine-pointer devices, hovering the dropdown opens it
   without requiring a click. Click / keyboard / touch still work via <details>. */
@media (hover: hover) and (pointer: fine) {
  .site-nav-dropdown:hover[open],     /* keep open while hovered */
  .site-nav-dropdown:hover {
    /* The :hover { open } trick: we can't *force* open via CSS, but we can
       reveal the submenu on hover even if [open] isn't set, by making the
       submenu visible when the parent is hovered. Below 'open' attribute
       still drives keyboard/touch behavior; CSS handles the mouse path. */
  }
  .site-nav-dropdown:not([open]):hover > .site-nav-submenu {
    display: flex;
    /* A tiny delay-free entrance keeps the menu from feeling janky when the
       cursor sweeps past on the way to another nav item. */
    animation: nav-submenu-in var(--dur-fast) var(--ease);
  }
  .site-nav-dropdown:not([open]):hover > summary {
    background: var(--surface-2);
    color: var(--primary);
  }
}
@keyframes nav-submenu-in {
  from { opacity: 0; transform: translateY(-4px); }
  to   { opacity: 1; transform: translateY(0); }
}
@media (prefers-reduced-motion: reduce) {
  .site-nav-dropdown:not([open]):hover > .site-nav-submenu { animation: none; }
}

/* ── Header right cluster (theme toggle + CTA) ─────────────────────────── */

.site-header-actions {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  flex: 0 0 auto;
}

/* The theme toggle uses .btn .btn-icon .btn-ghost from button.css and the icon-
   swap rules from components/theme-toggle.css. This file only owns the slot. */

/* ── Mobile burger ─────────────────────────────────────────────────────── */

.site-nav-toggle {
  /* Visible at small viewports only, hidden once the desktop nav appears. */
  display: inline-flex;
  align-items: center;
  justify-content: center;

  width: 44px;
  height: 44px;
  padding: 0;

  background: transparent;
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  cursor: pointer;

  transition: background var(--dur-fast) var(--ease),
              color var(--dur-fast) var(--ease);
}
.site-nav-toggle .icon {
  width: 1.25em;
  height: 1.25em;
}
@media (hover: hover) and (pointer: fine) {
  .site-nav-toggle:hover {
    background: var(--surface-2);
    color: var(--primary);
  }
}

/* ── Mobile overlay ────────────────────────────────────────────────────── */

.mobile-overlay {
  position: fixed;
  inset: 0;
  z-index: var(--z-modal);

  background: var(--surface);
  color: var(--text);

  display: flex;
  flex-direction: column;

  /* Animated entrance. The .is-open class is toggled by the wiring script. */
  opacity: 0;
  pointer-events: none;
  transform: translateY(-8px);
  transition:
    opacity var(--dur-base) var(--ease),
    transform var(--dur-base) var(--ease);
}
.mobile-overlay.is-open {
  opacity: 1;
  pointer-events: auto;
  transform: translateY(0);
}
@media (prefers-reduced-motion: reduce) {
  .mobile-overlay { transition: none; }
}

.mobile-overlay-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-container);
  border-bottom: 1px solid var(--border);
  min-height: 64px;
}

.mobile-overlay-close {
  width: 44px;
  height: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: transparent;
  color: var(--text);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  cursor: pointer;
}
.mobile-overlay-close .icon { width: 1.25em; height: 1.25em; }

.mobile-overlay-body {
  flex: 1 1 auto;
  overflow-y: auto;
  padding: var(--space-4) var(--space-container) var(--space-6);
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
}

.mobile-overlay-body a {
  display: flex;
  align-items: center;
  gap: var(--space-3);

  min-height: 52px;
  padding: var(--space-3) var(--space-3);

  font-family: var(--font-body);
  font-size: var(--fs-md);
  font-weight: var(--fw-medium);
  color: var(--text);
  text-decoration: none;
  border-radius: var(--radius);
  border-bottom: 1px solid var(--border);
}
.mobile-overlay-body a .icon {
  color: var(--accent);
  width: 1.1em;
  height: 1.1em;
}

.mobile-overlay-section-label {
  font-size: var(--fs-xs);
  font-weight: var(--fw-semibold);
  letter-spacing: var(--ls-widest);
  text-transform: uppercase;
  color: var(--text-muted);
  padding: var(--space-3) var(--space-3) var(--space-1);
}

.mobile-overlay-foot {
  padding: var(--space-4) var(--space-container) var(--space-5);
  border-top: 1px solid var(--border);
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}

/* When the overlay is open, lock body scroll. The wiring script adds .has-overlay
   to <html>; using <html> instead of <body> avoids the iOS Safari rubber-band
   bug where overflow:hidden on <body> still scrolls. */
html.has-overlay,
html.has-overlay body {
  overflow: hidden;
  touch-action: none;
}

/* ── Breakpoint switch ─────────────────────────────────────────────────── */

/* At md (768px+), show desktop nav and hide the burger. */
@media (min-width: 768px) {
  .site-nav { display: flex; justify-content: center; }
  .site-nav-toggle { display: none; }
  .mobile-overlay { display: none; }   /* belt + suspenders */
}

/* --- End: components/nav.css --- */

/* --- Start: components/photo-strip.css --- */
/* photo-strip.css — 3-up grid of job photos with location-specific captions.
 * Used on city pages and service hubs to show real work.
 *
 * Architecture:
 *   <div class="photo-strip">
 *     <figure class="photo-card">
 *       <img src="..." alt="…descriptive alt with city + work…"
 *            loading="lazy" width="800" height="600">
 *       <figcaption class="photo-caption">
 *         <span class="photo-location">Holland, MI</span>
 *         <span class="photo-job">Cat-2 basement extraction · Aug 2025</span>
 *       </figcaption>
 *     </figure>
 *     ... (three cards)
 *   </div>
 *
 * 1 column on phone, 2 at md, 3 at lg. Lazy-loading attribute is on the markup,
 * not the CSS — the generator emits it on every below-fold image. */

.photo-strip {
  display: grid;
  gap: var(--space-4);
  grid-template-columns: 1fr;
}
@media (min-width: 768px)  { .photo-strip { grid-template-columns: repeat(2, 1fr); } }
@media (min-width: 1024px) { .photo-strip { grid-template-columns: repeat(3, 1fr); } }

.photo-card {
  position: relative;
  margin: 0;
  border-radius: var(--radius-md);
  overflow: hidden;
  background: var(--surface-2);
  border: 1px solid var(--border);
  box-shadow: var(--shadow-sm);
  isolation: isolate;
}

.photo-card img {
  width: 100%;
  height: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  display: block;
  transition: transform var(--dur-slow) var(--ease);
}

@media (hover: hover) and (pointer: fine) {
  .photo-card:hover img {
    transform: scale(1.03);   /* OVERHAUL-PLAN §1.7.6 forbids hover scale on
                                 transforms generally; the strict reading is
                                 "no decorative card hover scale". A subtle
                                 image zoom inside an overflow-clipped frame
                                 is a different pattern (the frame is static),
                                 so it's allowed. If Matt rejects on review,
                                 swap for transform: translateY(-1px) on the
                                 .photo-card itself. */
  }
}

.photo-caption {
  position: absolute;
  inset: auto 0 0 0;
  z-index: 1;
  padding: var(--space-4);

  display: flex;
  flex-direction: column;
  gap: 2px;

  color: #ffffff;
  background: linear-gradient(to top,
    rgba(15, 26, 38, 0.85) 0%,
    rgba(15, 26, 38, 0.55) 60%,
    rgba(15, 26, 38, 0)   100%);
  pointer-events: none;
}

.photo-location {
  font-family: var(--font-body);
  font-size: var(--fs-xs);
  font-weight: var(--fw-semibold);
  letter-spacing: var(--ls-wide);
  text-transform: uppercase;
  color: #E0993A;            /* dark-theme accent — caption sits on dark scrim */
}
.photo-job {
  font-family: var(--font-body);
  font-size: var(--fs-sm);
  font-weight: var(--fw-medium);
  line-height: var(--lh-snug);
  color: rgba(255, 255, 255, 0.92);
}

@media (prefers-reduced-motion: reduce) {
  .photo-card img { transition: none; }
  .photo-card:hover img { transform: none; }
}

/* --- End: components/photo-strip.css --- */

/* --- Start: components/reveal.css --- */
/* reveal.css — scroll-driven one-shot reveal.
 *
 * The hidden state is gated on `.js-reveals` (added by animate-on-scroll.js)
 * so that content stays visible if JS fails or is disabled.
 *
 * Per OVERHAUL-PLAN §1.7:
 *   - Easing: cubic-bezier(0.22, 1, 0.36, 1)  (smooth out, no bounce)
 *   - Duration: 480ms (under the 600ms cap)
 *   - Translate + opacity only. No scale, no rotation.
 *   - prefers-reduced-motion: reduce zeroes out the animation.
 *
 * The JS already bails on reduced-motion, so the media query here is a
 * defense-in-depth fallback for the brief window between CSS load and JS
 * execution.
 */

.js-reveals .reveal {
  opacity: 0;
  transform: translateY(16px);
  transition:
    opacity 480ms cubic-bezier(0.22, 1, 0.36, 1),
    transform 480ms cubic-bezier(0.22, 1, 0.36, 1);
  will-change: opacity, transform;
}

.js-reveals .reveal.is-revealed {
  opacity: 1;
  transform: none;
}

@media (prefers-reduced-motion: reduce) {
  .js-reveals .reveal,
  .js-reveals .reveal.is-revealed {
    opacity: 1;
    transform: none;
    transition: none;
  }
}

/* --- End: components/reveal.css --- */

/* --- Start: components/review-card.css --- */
/* review-card.css — Google review embed styling.
 *
 * Pairs with assets/js/google-reviews.js (which currently lives at root and
 * gets relocated in Phase 1.6's deferred batch). The JS injects review data
 * into a grid container; this file styles the resulting card markup.
 *
 * Target architecture (Phase 3.D will rewrite google-reviews.js to emit this
 * markup with class names instead of the inline styles it ships today):
 *
 *   <article class="review-card">
 *     <header class="review-card-head">
 *       <img class="review-card-avatar" src="…" alt="" width="44" height="44">
 *       <!-- or .review-card-avatar.is-initial for initial-letter fallback -->
 *       <div class="review-card-meta">
 *         <p class="review-card-author">Jane Doe</p>
 *         <div class="review-card-stars" aria-label="5 out of 5 stars">…svg stars…</div>
 *       </div>
 *       <span class="review-card-source" aria-label="Source: Google">…G…</span>
 *     </header>
 *     <p class="review-card-text">"They documented every wet stud…"</p>
 *     <p class="review-card-time">3 weeks ago</p>
 *   </article>
 *
 * Uses surface tokens so the cards inherit theme. The current google-reviews.js
 * hard-codes `--bg-white,#1a1f2e` which is dark-only; that hardcode disappears
 * when the JS is rewritten in Phase 3.D. */

.review-card {
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: var(--space-5);
  box-shadow: var(--shadow-sm);

  display: flex;
  flex-direction: column;
  gap: var(--space-3);

  font-size: var(--fs-sm);
  color: var(--text);
}

.review-card-head {
  display: flex;
  align-items: center;
  gap: var(--space-3);
}

.review-card-avatar {
  width: 44px;
  height: 44px;
  border-radius: 50%;
  object-fit: cover;
  flex: 0 0 auto;
  background: var(--surface);   /* placeholder while img loads */
}

/* Initial-letter fallback when no profile_photo_url. The JS sets a CSS custom
   property --avatar-bg with one of an internal palette; tokens-only would tie
   us to the brand and weaken the "real people, varied avatars" cue. */
.review-card-avatar.is-initial {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  background: var(--avatar-bg, var(--primary));
  color: #ffffff;
  font-family: var(--font-body);
  font-weight: var(--fw-bold);
  font-size: 1.05rem;
  line-height: 1;
}

.review-card-meta {
  display: flex;
  flex-direction: column;
  gap: 2px;
  min-width: 0;
}

.review-card-author {
  margin: 0;
  font-family: var(--font-body);
  font-weight: var(--fw-bold);
  font-size: var(--fs-sm);
  color: var(--text);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.review-card-stars {
  display: inline-flex;
  gap: 2px;
  color: #FBBC05;       /* Google star yellow — fixed, not a token, since it's
                           a recognizable brand cue regardless of site theme.
                           Matches the canonical color emitted by
                           assets/js/google-reviews.js. */
}
.review-card-stars .icon {
  width: 0.95em;
  height: 0.95em;
}

.review-card-source {
  margin-left: auto;
  flex: 0 0 auto;
  display: inline-flex;
  align-items: center;
  width: 22px;
  height: 22px;
}
.review-card-source svg { width: 100%; height: 100%; }

.review-card-text {
  margin: 0;
  font-size: var(--fs-sm);
  line-height: var(--lh-normal);
  color: var(--text);
  flex: 1 1 auto;
  /* Quote styling: italic and a hairline left rule, sparingly used. The JS
     emits the quote characters as part of the text; this just frames it. */
}
.review-card-text::before { content: open-quote; }
.review-card-text::after  { content: close-quote; }
.review-card-text { quotes: '“' '”' '‘' '’'; }

.review-card-time {
  margin: 0;
  font-size: var(--fs-xs);
  color: var(--text-muted);
}

.review-card-readmore {
  display: inline;
  background: none;
  border: 0;
  padding: 0;
  margin-left: var(--space-1);
  font: inherit;
  font-weight: var(--fw-semibold);
  font-size: var(--fs-xs);
  color: var(--primary);
  cursor: pointer;
  text-decoration: underline;
  text-underline-offset: 0.18em;
}

/* Compact variant — used in the homepage proof bar where 4-5 cards must fit
   side by side. Trims padding and font sizes but keeps the same layout. */
.review-card-compact {
  padding: var(--space-4);
  gap: var(--space-2);
}
.review-card-compact .review-card-text { font-size: var(--fs-xs); }

/* --- End: components/review-card.css --- */

/* --- Start: components/theme-toggle.css --- */
/* theme-toggle.css — sun/moon icon-button styles + theme-aware icon swap.
 *
 * Architecture:
 *   <button class="btn btn-icon btn-ghost theme-toggle-btn"
 *           data-theme-toggle aria-label="Toggle color theme">
 *     <svg class="icon-light">…moon…</svg>
 *     <svg class="icon-dark">…sun…</svg>
 *   </button>
 *
 * The `data-theme-toggle` attribute is what assets/js/theme-toggle.js binds to —
 * any element with that attribute fires window.themeToggle.toggle() on click.
 * The icon-swap below is pure CSS driven by the [data-theme] attribute on <html>,
 * no JS needed for the visual flip.
 *
 * On desktop the toggle is icon-only (44×44 from .btn-icon). Inside the mobile
 * overlay it's used as a labeled .btn-ghost with text alongside the icons. The
 * .icon-light / .icon-dark visibility rules below cover both shapes. */

.theme-toggle-btn {
  /* Hook only. Sizing comes from .btn / .btn-icon. */
}

.theme-toggle-btn .icon-light,
.theme-toggle-btn .icon-dark {
  width: 1.25em;
  height: 1.25em;
}

[data-theme="light"] .theme-toggle-btn .icon-light { display: inline; }
[data-theme="light"] .theme-toggle-btn .icon-dark  { display: none; }
[data-theme="dark"]  .theme-toggle-btn .icon-light { display: none; }
[data-theme="dark"]  .theme-toggle-btn .icon-dark  { display: inline; }

/* View Transition tuning for theme swap.
 *
 * theme-toggle.js wraps the data-theme attribute write in
 * document.startViewTransition() when available, which gives a
 * UA-default cross-fade between the old and new viewport snapshots.
 * Default UA timing feels too long (~400ms) for a tap-driven control
 * and the easing isn't tuned. We override both inside a no-preference
 * media query so it stays inert under prefers-reduced-motion: reduce
 * (the JS also bails on reduced-motion as belt + suspenders).
 *
 * The crossfade is on the root snapshot — no per-element opt-in needed.
 * Browsers without View Transitions silently use the instant snap.
 */
@media (prefers-reduced-motion: no-preference) {
  ::view-transition-old(root),
  ::view-transition-new(root) {
    animation-duration: 260ms;
    animation-timing-function: cubic-bezier(0.22, 1, 0.36, 1);
  }
}

/* --- End: components/theme-toggle.css --- */

/* --- Start: pages/city.css --- */
/* city.css — page-level layout for the 208 city × service pages.
 * Single-source supplement to .hub-layout (in service-hub.css) — city pages
 * use .hub-layout too, plus the split hero defined here. */

/* Split hero: text left, photo right at md+, stacked single column on phone. */
.city-hero-content {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-6);
  align-items: center;
}
@media (min-width: 1024px) {
  .city-hero-content {
    grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr);
    gap: var(--space-8);
  }
}
@media (min-width: 1280px) {
  .city-hero-content {
    /* On wide desktops, give the text more horizontal space so the headline
       can breathe and the photo doesn't dominate. */
    grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr);
    gap: var(--space-9);
  }
}

.city-hero-text {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}
.city-hero-text .hero-title {
  /* City heroes have longer titles than hub heroes ("Fire & Smoke Damage
     Restoration in Pierson, MI — 24/7 response"). Allow more characters per
     line so the headline takes 2-3 lines on desktop instead of 5+. */
  max-width: 32ch;
}

.city-hero-media {
  border-radius: var(--radius-lg);
  overflow: hidden;
  box-shadow: var(--shadow-lg);
  /* Phone: hide the photo. The image is decorative; on small viewports it
     pushes the CTA below the fold and the hero feels long. */
  display: none;
}
@media (min-width: 1024px) { .city-hero-media { display: block; } }
.city-hero-media img {
  width: 100%;
  height: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  display: block;
}

/* Local geography card — city-specific risk callout. Theme-aware via tokens.
   Used at the top of every service-by-city page body. */
.local-geo-card {
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-left: 3px solid var(--accent);
  border-radius: var(--radius-md);
  padding: var(--space-6);
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}
.local-geo-card-head {
  display: flex;
  align-items: center;
  gap: var(--space-3);
}
.local-geo-card-head .icon {
  color: var(--accent);
  width: 1.4em;
  height: 1.4em;
}
.local-geo-card-head h2 {
  font-family: var(--font-display);
  font-size: var(--fs-xl);
  margin: 0;
  color: var(--text);
}
.local-geo-card .lead {
  font-size: var(--fs-md);
  color: var(--text);
  line-height: var(--lh-normal);
  margin: 0;
}
.local-geo-card-constraint {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: var(--space-4) var(--space-5);
}
.local-geo-card-constraint h3 {
  font-family: var(--font-body);
  font-size: var(--fs-xs);
  font-weight: var(--fw-semibold);
  letter-spacing: var(--ls-widest);
  text-transform: uppercase;
  color: var(--text-muted);
  margin: 0 0 var(--space-2);
}
.local-geo-card-constraint p {
  margin: 0;
  font-weight: var(--fw-semibold);
  color: var(--text);
  display: flex;
  align-items: flex-start;
  gap: var(--space-2);
  line-height: var(--lh-normal);
}
.local-geo-card-constraint .icon {
  color: var(--accent);
  flex-shrink: 0;
  margin-top: 0.15em;
}
.local-geo-card-foot {
  font-size: var(--fs-base);
  color: var(--text-muted);
  line-height: var(--lh-normal);
  margin: 0;
  padding-top: var(--space-3);
  border-top: 1px solid var(--border);
}

/* City-page reviews section: keep the dynamic grid in the content cascade
   without inline gap or grid-template overrides. The container fills with
   .review-card markup (from review-card.css) once google-reviews.js loads. */
#gr-reviews-grid:empty::before {
  content: 'Loading verified reviews from Google\2026';
  display: block;
  text-align: center;
  color: var(--text-muted);
  font-size: var(--fs-sm);
  padding: var(--space-7);
  grid-column: 1 / -1;
}

/* Sewage biohazard warning banner — Cat 3 sewage city pages display a small
   red strip at the top of the body. Tokens-only color so it adapts to dark
   theme cleanly. */
.biohazard-warning {
  background: color-mix(in srgb, var(--danger) 14%, var(--surface));
  border: 1px solid color-mix(in srgb, var(--danger) 40%, transparent);
  border-left: 3px solid var(--danger);
  border-radius: var(--radius-md);
  padding: var(--space-4) var(--space-5);
  color: var(--text);
  font-weight: var(--fw-semibold);
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
}
.biohazard-warning .icon {
  color: var(--danger);
  flex-shrink: 0;
  width: 1.4em;
  height: 1.4em;
  margin-top: 0.1em;
}

/* Nearby-cities link strip at the bottom of city body. */
.nearby-cities {
  margin-top: var(--space-7);
  padding-top: var(--space-5);
  border-top: 1px solid var(--border);
}
.nearby-cities h3 {
  font-family: var(--font-display);
  font-size: var(--fs-lg);
  margin: 0 0 var(--space-4);
  color: var(--text);
}
.nearby-cities-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
  gap: var(--space-2);
}
.nearby-cities-grid a {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-3);
  font-size: var(--fs-sm);
  font-weight: var(--fw-medium);
  color: var(--text-muted);
  text-decoration: none;
  border-radius: var(--radius);
  transition: color var(--dur-fast) var(--ease),
              background var(--dur-fast) var(--ease);
}
.nearby-cities-grid a .icon {
  color: var(--accent);
  width: 0.8em;
  height: 0.8em;
}
@media (hover: hover) and (pointer: fine) {
  .nearby-cities-grid a:hover {
    color: var(--primary);
    background: var(--surface-2);
  }
}


/* ZIP-codes line below the local-context grid on hub city pages. Single
   utility class to keep the inline-style rule out of the generator. */
.zip-list {
  margin-top: var(--space-4);
}

/* Per-service review callout used in the city page body. Inherits the
   .card / .card-featured tokens so it respects theme. */
.review-callout {
  margin: var(--space-6) 0;
}
.review-callout p {
  margin: 0 0 var(--space-3);
  font-weight: var(--fw-semibold);
}
.review-callout .card-eyebrow {
  margin: 0;
}

/* --- End: pages/city.css --- */

/* --- Start: pages/home.css --- */
/* home.css — page-specific layout for the homepage.
 *
 * Five patterns the components don't carry:
 *   1. .trust-strip      — narrow row of credential mini-cards under the hero
 *   2. .why-ryan         — asymmetric 2-col text/photo at lg+
 *   3. .home-area        — split city-list + Google map at lg+
 *   4. .home-cta-split   — left contact info card + right form iframe at lg+
 *   5. .map-frame        — wrapper for the Google Maps iframe (aspect ratio + radius)
 *
 * Anything reusable on hubs or city pages stays in /components/. These five are
 * homepage-only so they live here.
 */

/* ── 1. Trust strip ────────────────────────────────────────────────────── */
.trust-strip {
  background: var(--surface);
  border-block: 1px solid var(--border);
}
.trust-strip-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-4);
  padding-block: var(--space-6);
}
@media (min-width: 768px) {
  .trust-strip-grid { grid-template-columns: repeat(4, 1fr); }
}
.trust-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: var(--space-2);
  padding-inline: var(--space-3);
}
.trust-item .icon {
  width: 1.5em;
  height: 1.5em;
  color: var(--accent);
}
.trust-item-label {
  font-family: var(--font-display);
  font-weight: var(--fw-bold);
  font-size: var(--fs-base);
  line-height: var(--lh-snug);
  color: var(--text);
}
.trust-item-sub {
  font-size: var(--fs-xs);
  color: var(--text-muted);
  letter-spacing: var(--ls-wide);
  text-transform: uppercase;
}

/* ── 2. Why Ryan — asymmetric 2-col at lg+ ──────────────────────────────── */
.why-ryan {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-6);
  align-items: center;
}
@media (min-width: 1024px) {
  .why-ryan { grid-template-columns: 1.4fr 1fr; gap: var(--space-8); }
}
.why-ryan-photo {
  position: relative;
  border-radius: var(--radius-lg);
  overflow: hidden;
  box-shadow: var(--shadow-md);
}
.why-ryan-photo img {
  width: 100%;
  aspect-ratio: 4 / 5;
  object-fit: cover;
}
.why-ryan-badge {
  position: absolute;
  bottom: var(--space-4);
  left: var(--space-4);
  background: var(--text);
  color: #ffffff;
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-md);
  display: flex;
  align-items: baseline;
  gap: var(--space-2);
  box-shadow: var(--shadow-md);
}
.why-ryan-badge-num {
  font-family: var(--font-display);
  font-weight: var(--fw-bold);
  font-size: 2rem;
  line-height: 1;
  color: #E0993A;
}
.why-ryan-badge-text {
  font-size: var(--fs-xs);
  letter-spacing: var(--ls-wide);
  text-transform: uppercase;
  max-width: 14ch;
}

/* ── 3. Service area — city list + map ──────────────────────────────────── */
.home-area {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-6);
  align-items: start;
}
@media (min-width: 1024px) {
  .home-area { grid-template-columns: 1fr 1.2fr; gap: var(--space-7); }
}
.home-area-cities {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-2) var(--space-5);
  margin: 0;
  padding: 0;
  list-style: none;
}
.home-area-cities a {
  color: var(--text);
  text-decoration: none;
  font-weight: var(--fw-medium);
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding-block: var(--space-2);
  border-bottom: 1px solid var(--border);
}
.home-area-cities a:hover { color: var(--primary); }
.home-area-cities .icon { color: var(--accent); }

.map-frame {
  border-radius: var(--radius-lg);
  overflow: hidden;
  border: 1px solid var(--border);
  box-shadow: var(--shadow-sm);
  aspect-ratio: 4 / 3;
}
.map-frame iframe {
  width: 100%;
  height: 100%;
  border: 0;
  display: block;
}

/* ── 4. Bottom CTA split ────────────────────────────────────────────────
   Note: also re-used on /contact/ for the same call-card + form pattern.
   Class names start with `home-` because the homepage was the first user,
   but the pattern is page-agnostic. If a third user appears, rename to
   `.cta-split` / `.cta-card` / `.cta-pill` and migrate. */
.home-cta-split {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-6);
  align-items: start;
}
@media (min-width: 1024px) {
  .home-cta-split { grid-template-columns: 1fr 1.4fr; gap: var(--space-7); }
}
.home-cta-form {
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: var(--space-5);
}
.home-cta-form iframe {
  width: 100%;
  min-height: 540px;
  border: 0;
  border-radius: var(--radius);
  display: block;
}
/* Form card heading + intro spacing — used by both the homepage and /contact/. */
.home-cta-form > .card-title { margin: 0 0 var(--space-2); }
.home-cta-form > .card-body  { margin: 0 0 var(--space-4); }

/* Big call card — emergency surface, sits in the left column of the split. */
.home-cta-call {
  background: var(--danger);
  color: #ffffff;
  border-radius: var(--radius-lg);
  padding: var(--space-6);
  text-align: center;
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}
.home-cta-call .home-cta-call-label {
  font-size: var(--fs-xs);
  letter-spacing: var(--ls-widest);
  text-transform: uppercase;
  font-weight: var(--fw-semibold);
  color: rgba(255, 255, 255, 0.85);
}
.home-cta-call a.home-cta-call-num {
  font-family: var(--font-display);
  font-weight: var(--fw-bold);
  font-size: clamp(1.75rem, 1.4rem + 1.4vw, 2.25rem);
  color: #ffffff;
  text-decoration: none;
  line-height: 1.05;
  letter-spacing: var(--ls-tight);
}
.home-cta-call .home-cta-call-sub {
  font-size: var(--fs-sm);
  color: rgba(255, 255, 255, 0.9);
  margin-bottom: var(--space-2);
}

/* Trust pill list under the call card. */
.home-cta-pills {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  margin-top: var(--space-4);
}
.home-cta-pill {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  font-size: var(--fs-sm);
  color: var(--text);
}
.home-cta-pill .icon { color: var(--primary); flex: 0 0 auto; }

/* ── 5. Carrier strip — small wordmark row above the photo strip ────────── */
.carriers {
  background: var(--surface);
  border-block: 1px solid var(--border);
  padding-block: var(--space-5);
}
.carriers-label {
  text-align: center;
  font-size: var(--fs-xs);
  font-weight: var(--fw-semibold);
  letter-spacing: var(--ls-widest);
  text-transform: uppercase;
  color: var(--text-muted);
  margin-bottom: var(--space-4);
}
.carriers-list {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
  gap: var(--space-3) var(--space-5);
  list-style: none;
  margin: 0;
  padding: 0;
}
.carriers-list li {
  font-family: var(--font-display);
  font-weight: var(--fw-bold);
  font-size: var(--fs-sm);
  color: var(--text);
  letter-spacing: var(--ls-tight);
}
.carriers-list li + li::before {
  content: "·";
  color: var(--accent);
  margin-right: var(--space-5);
  margin-left: calc(var(--space-5) * -1);
}

/* ── Section heading defaults for the homepage (tighter spacing than .stack
       defaults so two short paragraphs don't feel adrift). ──────────────── */
.home-section h2 {
  font-family: var(--font-display);
  font-size: var(--fs-2xl);
  line-height: var(--lh-tight);
  letter-spacing: var(--ls-tight);
  margin: 0;
}
.home-section p.lede {
  font-size: var(--fs-md);
  color: var(--text-muted);
  max-width: 60ch;
  margin: 0;
}

/* --- End: pages/home.css --- */

/* --- Start: pages/city.css --- */
/* city.css — page-level layout for the 208 city × service pages.
 * Single-source supplement to .hub-layout (in service-hub.css) — city pages
 * use .hub-layout too, plus the split hero defined here. */

/* Split hero: text left, photo right at md+, stacked single column on phone. */
.city-hero-content {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-6);
  align-items: center;
}
@media (min-width: 1024px) {
  .city-hero-content {
    grid-template-columns: minmax(0, 1.4fr) minmax(0, 1fr);
    gap: var(--space-8);
  }
}
@media (min-width: 1280px) {
  .city-hero-content {
    /* On wide desktops, give the text more horizontal space so the headline
       can breathe and the photo doesn't dominate. */
    grid-template-columns: minmax(0, 1.6fr) minmax(0, 1fr);
    gap: var(--space-9);
  }
}

.city-hero-text {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}
.city-hero-text .hero-title {
  /* City heroes have longer titles than hub heroes ("Fire & Smoke Damage
     Restoration in Pierson, MI — 24/7 response"). Allow more characters per
     line so the headline takes 2-3 lines on desktop instead of 5+. */
  max-width: 32ch;
}

.city-hero-media {
  border-radius: var(--radius-lg);
  overflow: hidden;
  box-shadow: var(--shadow-lg);
  /* Phone: hide the photo. The image is decorative; on small viewports it
     pushes the CTA below the fold and the hero feels long. */
  display: none;
}
@media (min-width: 1024px) { .city-hero-media { display: block; } }
.city-hero-media img {
  width: 100%;
  height: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  display: block;
}

/* Local geography card — city-specific risk callout. Theme-aware via tokens.
   Used at the top of every service-by-city page body. */
.local-geo-card {
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-left: 3px solid var(--accent);
  border-radius: var(--radius-md);
  padding: var(--space-6);
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}
.local-geo-card-head {
  display: flex;
  align-items: center;
  gap: var(--space-3);
}
.local-geo-card-head .icon {
  color: var(--accent);
  width: 1.4em;
  height: 1.4em;
}
.local-geo-card-head h2 {
  font-family: var(--font-display);
  font-size: var(--fs-xl);
  margin: 0;
  color: var(--text);
}
.local-geo-card .lead {
  font-size: var(--fs-md);
  color: var(--text);
  line-height: var(--lh-normal);
  margin: 0;
}
.local-geo-card-constraint {
  background: var(--surface);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  padding: var(--space-4) var(--space-5);
}
.local-geo-card-constraint h3 {
  font-family: var(--font-body);
  font-size: var(--fs-xs);
  font-weight: var(--fw-semibold);
  letter-spacing: var(--ls-widest);
  text-transform: uppercase;
  color: var(--text-muted);
  margin: 0 0 var(--space-2);
}
.local-geo-card-constraint p {
  margin: 0;
  font-weight: var(--fw-semibold);
  color: var(--text);
  display: flex;
  align-items: flex-start;
  gap: var(--space-2);
  line-height: var(--lh-normal);
}
.local-geo-card-constraint .icon {
  color: var(--accent);
  flex-shrink: 0;
  margin-top: 0.15em;
}
.local-geo-card-foot {
  font-size: var(--fs-base);
  color: var(--text-muted);
  line-height: var(--lh-normal);
  margin: 0;
  padding-top: var(--space-3);
  border-top: 1px solid var(--border);
}

/* City-page reviews section: keep the dynamic grid in the content cascade
   without inline gap or grid-template overrides. The container fills with
   .review-card markup (from review-card.css) once google-reviews.js loads. */
#gr-reviews-grid:empty::before {
  content: 'Loading verified reviews from Google\2026';
  display: block;
  text-align: center;
  color: var(--text-muted);
  font-size: var(--fs-sm);
  padding: var(--space-7);
  grid-column: 1 / -1;
}

/* Sewage biohazard warning banner — Cat 3 sewage city pages display a small
   red strip at the top of the body. Tokens-only color so it adapts to dark
   theme cleanly. */
.biohazard-warning {
  background: color-mix(in srgb, var(--danger) 14%, var(--surface));
  border: 1px solid color-mix(in srgb, var(--danger) 40%, transparent);
  border-left: 3px solid var(--danger);
  border-radius: var(--radius-md);
  padding: var(--space-4) var(--space-5);
  color: var(--text);
  font-weight: var(--fw-semibold);
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
}
.biohazard-warning .icon {
  color: var(--danger);
  flex-shrink: 0;
  width: 1.4em;
  height: 1.4em;
  margin-top: 0.1em;
}

/* Nearby-cities link strip at the bottom of city body. */
.nearby-cities {
  margin-top: var(--space-7);
  padding-top: var(--space-5);
  border-top: 1px solid var(--border);
}
.nearby-cities h3 {
  font-family: var(--font-display);
  font-size: var(--fs-lg);
  margin: 0 0 var(--space-4);
  color: var(--text);
}
.nearby-cities-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(180px, 1fr));
  gap: var(--space-2);
}
.nearby-cities-grid a {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding: var(--space-2) var(--space-3);
  font-size: var(--fs-sm);
  font-weight: var(--fw-medium);
  color: var(--text-muted);
  text-decoration: none;
  border-radius: var(--radius);
  transition: color var(--dur-fast) var(--ease),
              background var(--dur-fast) var(--ease);
}
.nearby-cities-grid a .icon {
  color: var(--accent);
  width: 0.8em;
  height: 0.8em;
}
@media (hover: hover) and (pointer: fine) {
  .nearby-cities-grid a:hover {
    color: var(--primary);
    background: var(--surface-2);
  }
}


/* ZIP-codes line below the local-context grid on hub city pages. Single
   utility class to keep the inline-style rule out of the generator. */
.zip-list {
  margin-top: var(--space-4);
}

/* Per-service review callout used in the city page body. Inherits the
   .card / .card-featured tokens so it respects theme. */
.review-callout {
  margin: var(--space-6) 0;
}
.review-callout p {
  margin: 0 0 var(--space-3);
  font-weight: var(--fw-semibold);
}
.review-callout .card-eyebrow {
  margin: 0;
}

/* --- End: pages/city.css --- */

/* --- Start: pages/service-hub.css --- */
/* service-hub.css — page-level layout for the 4 service hub pages
 * (water, fire, mold, sewage). Sets the body+sidebar 2-column pattern that
 * those pages share but no other page type uses, so it lives here rather
 * than in /components/. */

.hub-layout {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-7);
}

@media (min-width: 1024px) {
  .hub-layout {
    grid-template-columns: minmax(0, 1fr) 320px;
    gap: var(--space-8);
    align-items: start;
  }
  .hub-sidebar {
    position: sticky;
    top: calc(64px + var(--space-4));   /* clear the sticky header */
  }
}

/* Body prose inside the hub: section spacing + readable line length. The
   .stack utility handles vertical rhythm; this just keeps prose comfortable. */
.hub-body p,
.hub-body li {
  max-width: 68ch;
}
.hub-body h2 {
  font-size: var(--fs-xl);
  margin-block: var(--space-7) var(--space-4);
}
.hub-body h3 {
  font-size: var(--fs-lg);
  margin-block: var(--space-5) var(--space-3);
}

/* Two-column sub-grid for "common causes" / "types we handle" cards inside
   the hub body. Mobile: single column. md+: two columns. */
.hub-2col {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-4);
  margin-block: var(--space-5);
}
@media (min-width: 768px) {
  .hub-2col { grid-template-columns: 1fr 1fr; }
}

/* --- End: pages/service-hub.css --- */

/* --- Start: pages/home.css --- */
/* home.css — page-specific layout for the homepage.
 *
 * Five patterns the components don't carry:
 *   1. .trust-strip      — narrow row of credential mini-cards under the hero
 *   2. .why-ryan         — asymmetric 2-col text/photo at lg+
 *   3. .home-area        — split city-list + Google map at lg+
 *   4. .home-cta-split   — left contact info card + right form iframe at lg+
 *   5. .map-frame        — wrapper for the Google Maps iframe (aspect ratio + radius)
 *
 * Anything reusable on hubs or city pages stays in /components/. These five are
 * homepage-only so they live here.
 */

/* ── 1. Trust strip ────────────────────────────────────────────────────── */
.trust-strip {
  background: var(--surface);
  border-block: 1px solid var(--border);
}
.trust-strip-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-4);
  padding-block: var(--space-6);
}
@media (min-width: 768px) {
  .trust-strip-grid { grid-template-columns: repeat(4, 1fr); }
}
.trust-item {
  display: flex;
  flex-direction: column;
  align-items: center;
  text-align: center;
  gap: var(--space-2);
  padding-inline: var(--space-3);
}
.trust-item .icon {
  width: 1.5em;
  height: 1.5em;
  color: var(--accent);
}
.trust-item-label {
  font-family: var(--font-display);
  font-weight: var(--fw-bold);
  font-size: var(--fs-base);
  line-height: var(--lh-snug);
  color: var(--text);
}
.trust-item-sub {
  font-size: var(--fs-xs);
  color: var(--text-muted);
  letter-spacing: var(--ls-wide);
  text-transform: uppercase;
}

/* ── 2. Why Ryan — asymmetric 2-col at lg+ ──────────────────────────────── */
.why-ryan {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-6);
  align-items: center;
}
@media (min-width: 1024px) {
  .why-ryan { grid-template-columns: 1.4fr 1fr; gap: var(--space-8); }
}
.why-ryan-photo {
  position: relative;
  border-radius: var(--radius-lg);
  overflow: hidden;
  box-shadow: var(--shadow-md);
}
.why-ryan-photo img {
  width: 100%;
  aspect-ratio: 4 / 5;
  object-fit: cover;
}
.why-ryan-badge {
  position: absolute;
  bottom: var(--space-4);
  left: var(--space-4);
  background: var(--text);
  color: #ffffff;
  padding: var(--space-3) var(--space-4);
  border-radius: var(--radius-md);
  display: flex;
  align-items: baseline;
  gap: var(--space-2);
  box-shadow: var(--shadow-md);
}
.why-ryan-badge-num {
  font-family: var(--font-display);
  font-weight: var(--fw-bold);
  font-size: 2rem;
  line-height: 1;
  color: #E0993A;
}
.why-ryan-badge-text {
  font-size: var(--fs-xs);
  letter-spacing: var(--ls-wide);
  text-transform: uppercase;
  max-width: 14ch;
}

/* ── 3. Service area — city list + map ──────────────────────────────────── */
.home-area {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-6);
  align-items: start;
}
@media (min-width: 1024px) {
  .home-area { grid-template-columns: 1fr 1.2fr; gap: var(--space-7); }
}
.home-area-cities {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-2) var(--space-5);
  margin: 0;
  padding: 0;
  list-style: none;
}
.home-area-cities a {
  color: var(--text);
  text-decoration: none;
  font-weight: var(--fw-medium);
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  padding-block: var(--space-2);
  border-bottom: 1px solid var(--border);
}
.home-area-cities a:hover { color: var(--primary); }
.home-area-cities .icon { color: var(--accent); }

.map-frame {
  border-radius: var(--radius-lg);
  overflow: hidden;
  border: 1px solid var(--border);
  box-shadow: var(--shadow-sm);
  aspect-ratio: 4 / 3;
}
.map-frame iframe {
  width: 100%;
  height: 100%;
  border: 0;
  display: block;
}

/* ── 4. Bottom CTA split ────────────────────────────────────────────────
   Note: also re-used on /contact/ for the same call-card + form pattern.
   Class names start with `home-` because the homepage was the first user,
   but the pattern is page-agnostic. If a third user appears, rename to
   `.cta-split` / `.cta-card` / `.cta-pill` and migrate. */
.home-cta-split {
  display: grid;
  grid-template-columns: 1fr;
  gap: var(--space-6);
  align-items: start;
}
@media (min-width: 1024px) {
  .home-cta-split { grid-template-columns: 1fr 1.4fr; gap: var(--space-7); }
}
.home-cta-form {
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-lg);
  padding: var(--space-5);
}
.home-cta-form iframe {
  width: 100%;
  min-height: 540px;
  border: 0;
  border-radius: var(--radius);
  display: block;
}
/* Form card heading + intro spacing — used by both the homepage and /contact/. */
.home-cta-form > .card-title { margin: 0 0 var(--space-2); }
.home-cta-form > .card-body  { margin: 0 0 var(--space-4); }

/* Big call card — emergency surface, sits in the left column of the split. */
.home-cta-call {
  background: var(--danger);
  color: #ffffff;
  border-radius: var(--radius-lg);
  padding: var(--space-6);
  text-align: center;
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}
.home-cta-call .home-cta-call-label {
  font-size: var(--fs-xs);
  letter-spacing: var(--ls-widest);
  text-transform: uppercase;
  font-weight: var(--fw-semibold);
  color: rgba(255, 255, 255, 0.85);
}
.home-cta-call a.home-cta-call-num {
  font-family: var(--font-display);
  font-weight: var(--fw-bold);
  font-size: clamp(1.75rem, 1.4rem + 1.4vw, 2.25rem);
  color: #ffffff;
  text-decoration: none;
  line-height: 1.05;
  letter-spacing: var(--ls-tight);
}
.home-cta-call .home-cta-call-sub {
  font-size: var(--fs-sm);
  color: rgba(255, 255, 255, 0.9);
  margin-bottom: var(--space-2);
}

/* Trust pill list under the call card. */
.home-cta-pills {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  margin-top: var(--space-4);
}
.home-cta-pill {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  padding: var(--space-3) var(--space-4);
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius);
  font-size: var(--fs-sm);
  color: var(--text);
}
.home-cta-pill .icon { color: var(--primary); flex: 0 0 auto; }

/* ── 5. Carrier strip — small wordmark row above the photo strip ────────── */
.carriers {
  background: var(--surface);
  border-block: 1px solid var(--border);
  padding-block: var(--space-5);
}
.carriers-label {
  text-align: center;
  font-size: var(--fs-xs);
  font-weight: var(--fw-semibold);
  letter-spacing: var(--ls-widest);
  text-transform: uppercase;
  color: var(--text-muted);
  margin-bottom: var(--space-4);
}
.carriers-list {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  align-items: center;
  gap: var(--space-3) var(--space-5);
  list-style: none;
  margin: 0;
  padding: 0;
}
.carriers-list li {
  font-family: var(--font-display);
  font-weight: var(--fw-bold);
  font-size: var(--fs-sm);
  color: var(--text);
  letter-spacing: var(--ls-tight);
}
.carriers-list li + li::before {
  content: "·";
  color: var(--accent);
  margin-right: var(--space-5);
  margin-left: calc(var(--space-5) * -1);
}

/* ── Section heading defaults for the homepage (tighter spacing than .stack
       defaults so two short paragraphs don't feel adrift). ──────────────── */
.home-section h2 {
  font-family: var(--font-display);
  font-size: var(--fs-2xl);
  line-height: var(--lh-tight);
  letter-spacing: var(--ls-tight);
  margin: 0;
}
.home-section p.lede {
  font-size: var(--fs-md);
  color: var(--text-muted);
  max-width: 60ch;
  margin: 0;
}

/* --- End: pages/home.css --- */

/* --- Start: pages/about.css --- */
/* about.css — page-specific layout for /about/.
 *
 * Two patterns the components don't carry:
 *   1. .about-timeline       — vertical timeline (year pill + body) for "Our story"
 *   2. .about-crew-avatar    — 64px circular initial avatar for crew cards
 *   3. .about-crew-role      — quiet sub-title beneath crew name (not eyebrow)
 *
 * Anything reusable on other pages stays in /components/.
 */

/* ── 1. Timeline ────────────────────────────────────────────────────── */
.about-timeline {
  list-style: none;
  padding: 0;
  margin: 0;
  display: flex;
  flex-direction: column;
  gap: var(--space-5);
}
.about-timeline-item {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: var(--space-4);
  align-items: start;
}
.about-timeline-year {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  min-width: 5rem;
  padding: var(--space-2) var(--space-3);
  background: var(--accent);
  color: var(--accent-fg);
  font-family: var(--font-display);
  font-weight: var(--fw-bold);
  font-size: var(--fs-base);
  border-radius: var(--radius);
  letter-spacing: var(--ls-tight);
}
.about-timeline-body {
  padding-top: var(--space-1);
}
.about-timeline-body h3 {
  font-family: var(--font-display);
  font-size: var(--fs-lg);
  margin: 0 0 var(--space-2);
  line-height: var(--lh-snug);
}
.about-timeline-body p {
  margin: 0;
  color: var(--text-muted);
}

/* ── 2. Crew avatar — bigger than the review-card avatar ───────────── */
.about-crew-avatar {
  width: 72px;
  height: 72px;
  font-size: var(--fs-lg);
  margin-inline: auto;
}

/* ── 3. Crew role — quiet sub-title beneath the name ───────────────── */
.about-crew-role {
  color: var(--text-muted);
  font-size: var(--fs-sm);
  margin: calc(var(--space-2) * -1) 0 0;  /* tighten to the name above */
}

/* --- End: pages/about.css --- */

/* --- Start: pages/service-areas.css --- */
/* service-areas.css — page-specific layout for /service-areas/.
 *
 * Patterns the shared components don't carry:
 *   1. .sa-county / .sa-county-head — county group with name + city count
 *   2. .sa-city-grid                — auto-fit grid of city cards (denser
 *                                     than the default .grid-auto)
 *   3. .sa-city-card                — compact city card with name link,
 *                                     tier badge, minutes-away meta,
 *                                     and a 4-service jump row
 *
 * Anything reusable on other pages stays in /components/.
 */

/* ── 1. County section ─────────────────────────────────────────────── */
.sa-county-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-3);
  flex-wrap: wrap;
  margin-block-end: var(--space-4);
  padding-block-end: var(--space-2);
  border-block-end: 1px solid var(--border);
}
.sa-county-head h2 {
  font-family: var(--font-display);
  font-size: var(--fs-xl);
  margin: 0;
}
.sa-county-count {
  margin: 0;
  color: var(--text-muted);
  font-size: var(--fs-sm);
  letter-spacing: var(--ls-wide);
  text-transform: uppercase;
}

/* ── 2. City grid — denser than .grid-auto ───────────────────────── */
.sa-city-grid {
  display: grid;
  gap: var(--space-3);
  grid-template-columns: repeat(auto-fit, minmax(min(15rem, 100%), 1fr));
}

/* ── 3. City card ────────────────────────────────────────────────── */
.sa-city-card {
  padding: var(--space-4);
  gap: var(--space-3);
}
.sa-city-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-2);
}
.sa-city-name {
  font-family: var(--font-display);
  font-size: var(--fs-lg);
  font-weight: var(--fw-bold);
  margin: 0;
  line-height: var(--lh-snug);
}
.sa-city-name a {
  color: var(--text);
  text-decoration: none;
}
.sa-city-name a:hover {
  color: var(--primary);
}
.sa-tier-badge {
  display: inline-flex;
  align-items: center;
  padding: 2px var(--space-2);
  background: var(--primary);
  color: var(--primary-fg);
  font-size: var(--fs-xs);
  font-weight: var(--fw-semibold);
  letter-spacing: var(--ls-wide);
  text-transform: uppercase;
  border-radius: var(--radius-pill);
  flex-shrink: 0;
}
.sa-city-meta {
  margin: 0;
  font-size: var(--fs-sm);
  color: var(--text-muted);
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
}
.sa-city-meta .icon {
  color: var(--accent);
}

/* Service jump row — small, dense, separated from the meta line */
.sa-svc-row {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: var(--space-1);
  padding-top: var(--space-2);
  border-top: 1px solid var(--border);
}
.sa-svc-link {
  display: inline-flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  padding: var(--space-2) var(--space-1);
  font-size: var(--fs-xs);
  font-weight: var(--fw-medium);
  color: var(--text-muted);
  text-decoration: none;
  border-radius: var(--radius-sm);
  transition: background var(--dur-fast) var(--ease), color var(--dur-fast) var(--ease);
}
.sa-svc-link .icon {
  font-size: 1rem;
  color: var(--accent);
}
@media (hover: hover) and (pointer: fine) {
  .sa-svc-link:hover {
    background: var(--surface-2);
    color: var(--text);
  }
}

/* --- End: pages/service-areas.css --- */

/* --- Start: pages/pricing.css --- */
/* pricing.css — page-specific styles for /pricing/.
 *
 * Tables are not a shared component (only the pricing page has them today),
 * so the table styling lives here. Plus a `.callout` modifier for the
 * AI-overview summary block at the top of the page.
 */

/* ── Pricing summary callout — AI overview bait ─────────────────────── */
.pricing-summary {
  border-left: 4px solid var(--accent);
}

/* ── Disclaimer block (yellow) ──────────────────────────────────────── */
.pricing-disclaimer {
  background: color-mix(in srgb, var(--accent) 15%, var(--surface));
  border: 1px solid color-mix(in srgb, var(--accent) 35%, var(--border));
  color: var(--text);
  padding: var(--space-4) var(--space-5);
  border-radius: var(--radius-md);
  margin-block-end: var(--space-7);
}
.pricing-disclaimer p { margin: 0; font-size: var(--fs-sm); }
.pricing-disclaimer .icon {
  color: var(--accent);
  margin-right: var(--space-2);
  vertical-align: -3px;
}

/* ── Pricing tables ─────────────────────────────────────────────────── */
.pricing-table {
  width: 100%;
  border-collapse: collapse;
  margin-block: var(--space-5);
  font-size: var(--fs-sm);
}
.pricing-table thead th {
  background: var(--primary);
  color: var(--primary-fg);
  text-align: left;
  padding: var(--space-3) var(--space-4);
  font-weight: var(--fw-semibold);
  letter-spacing: var(--ls-wide);
  text-transform: uppercase;
  font-size: var(--fs-xs);
}
.pricing-table thead th:first-child { border-top-left-radius: var(--radius-sm); }
.pricing-table thead th:last-child  { border-top-right-radius: var(--radius-sm); }

.pricing-table tbody td {
  padding: var(--space-3) var(--space-4);
  border-bottom: 1px solid var(--border);
  vertical-align: top;
}
.pricing-table tbody tr:last-child td { border-bottom: none; }
.pricing-table tbody td:last-child {
  white-space: nowrap;
  font-variant-numeric: tabular-nums;
}
.pricing-table tbody td em {
  color: var(--text-muted);
  font-weight: var(--fw-regular);
  font-style: normal;
  font-size: var(--fs-xs);
  display: block;
  margin-top: 2px;
}

/* Mobile: tables get a horizontal scroll wrapper. The .pricing-table-wrap
   carries `overflow-x: auto` so the table itself doesn't break the layout
   on narrow phones. */
.pricing-table-wrap {
  overflow-x: auto;
  -webkit-overflow-scrolling: touch;
  border-radius: var(--radius-sm);
}

/* ── "What you actually pay" check list ─────────────────────────────── */
.pricing-coverage {
  list-style: none;
  padding: 0;
  margin: var(--space-4) 0;
  display: grid;
  gap: var(--space-3);
}
.pricing-coverage li {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
}
.pricing-coverage .icon {
  color: var(--accent);
  flex-shrink: 0;
  margin-top: 2px;
}

/* Section title icon spacing — h2 with a leading svg sits inline. */
.pricing-section-title {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  margin-block-end: var(--space-4);
}
.pricing-section-title .icon { color: var(--accent); flex-shrink: 0; }

/* --- End: pages/pricing.css --- */

/* --- Start: pages/blog.css --- */
/* blog.css — page-specific layout for /blog/ and individual blog posts.
 *
 * Strategy: keep the existing `.ed-*` class vocabulary (the body markup uses
 * 41 of them across 18 posts and the names are content-meaningful — TL;DR,
 * pullquote, field-note, etc.). Restyle them through design-system tokens so
 * posts inherit theme support and visual consistency with the rest of the
 * site. Drop the magazine chrome at the markup layer (masthead, vol/issue,
 * "Field Journal" kicker line) — those are removed during the migration.
 *
 * Two layout primitives exposed to the migration script:
 *   .blog-post       — wrapper around the whole post body, sets prose width
 *   .blog-index-grid — index page card grid (replaces the hand-rolled .fj-*
 *                      classes used in the legacy blog index)
 */

/* ── Post wrapper ──────────────────────────────────────────────────── */

.blog-post {
  width: 100%;
  max-width: 760px;
  margin-inline: auto;
  padding-inline: var(--space-container);
  padding-block: var(--space-7);
}
.blog-post > * + * { margin-block-start: var(--space-5); }

/* ── Post hero (eyebrow + h1 + dek + dateline) ────────────────────── */

.ed-kicker {
  display: inline-block;
  font-family: var(--font-body);
  font-weight: var(--fw-semibold);
  font-size: var(--fs-xs);
  letter-spacing: var(--ls-widest);
  text-transform: uppercase;
  color: var(--accent);
  background: color-mix(in srgb, var(--accent) 12%, transparent);
  padding: var(--space-1) var(--space-3);
  border-radius: var(--radius-pill);
  margin: 0 0 var(--space-3);
}

.ed-headline {
  font-family: var(--font-display);
  font-weight: var(--fw-bold);
  font-size: clamp(2rem, 1.4rem + 2.4vw, 2.75rem);
  line-height: var(--lh-tight);
  letter-spacing: var(--ls-tight);
  color: var(--text);
  margin: 0 0 var(--space-4);
  text-wrap: balance;
}
.ed-headline em {
  font-style: italic;
  color: var(--accent);
}

.ed-dek {
  font-family: var(--font-body);
  font-size: var(--fs-md);
  line-height: var(--lh-normal);
  color: var(--text-muted);
  max-width: 60ch;
  margin: 0 0 var(--space-5);
}

.ed-dateline {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--space-2) var(--space-4);
  font-size: var(--fs-sm);
  color: var(--text-muted);
  padding-block: var(--space-3);
  border-block: 1px solid var(--border);
  margin-block: var(--space-5) var(--space-6);
}
.ed-dateline > span { display: inline-flex; align-items: center; gap: var(--space-2); }
.ed-dateline .ed-by strong { color: var(--text); font-weight: var(--fw-semibold); }
.ed-dateline .ed-iicrc {
  font-size: var(--fs-xs);
  letter-spacing: var(--ls-wide);
  color: var(--accent);
  font-weight: var(--fw-semibold);
}

/* "Last updated" — added by the migration script, surfaces freshness signal
   per the Sona audit (was 68/100, target 90+). */
.ed-updated {
  font-style: italic;
}

/* ── Hero image and caption ───────────────────────────────────────── */

.ed-hero-img {
  width: 100%;
  height: auto;
  border-radius: var(--radius-md);
  display: block;
  margin-block: var(--space-5);
}
.ed-hero-img-cap {
  display: block;
  font-size: var(--fs-sm);
  font-style: italic;
  color: var(--text-muted);
  text-align: center;
  margin-block-start: calc(var(--space-5) * -1 + var(--space-3));
  margin-block-end: var(--space-6);
}

/* ── Post body prose defaults ─────────────────────────────────────── */

.ed-article > * + * { margin-block-start: var(--space-4); }

.ed-article p {
  font-family: var(--font-body);
  font-size: var(--fs-base);
  line-height: var(--lh-relaxed);
  color: var(--text);
  max-width: 68ch;
}

.ed-article h2 {
  font-family: var(--font-display);
  font-weight: var(--fw-bold);
  font-size: var(--fs-xl);
  line-height: var(--lh-snug);
  letter-spacing: var(--ls-tight);
  color: var(--text);
  margin-block-start: var(--space-7);
  margin-block-end: var(--space-3);
}

.ed-article h3 {
  font-family: var(--font-display);
  font-weight: var(--fw-semibold);
  font-size: var(--fs-lg);
  line-height: var(--lh-snug);
  color: var(--text);
  margin-block-start: var(--space-5);
  margin-block-end: var(--space-2);
}

.ed-article ul,
.ed-article ol {
  padding-inline-start: var(--space-5);
  margin-block: var(--space-3);
}
.ed-article li {
  margin-block: var(--space-2);
  line-height: var(--lh-relaxed);
}
.ed-article li > p:first-child { margin: 0; }

.ed-article a {
  color: var(--primary);
  text-decoration-color: color-mix(in srgb, var(--primary) 35%, transparent);
}
.ed-article a:hover { text-decoration-color: var(--primary); }

.ed-article strong { font-weight: var(--fw-semibold); color: var(--text); }
.ed-article em { font-style: italic; }

/* ── TL;DR / Quick Answer callout ─────────────────────────────────── */

.ed-tldr {
  background: color-mix(in srgb, var(--accent) 8%, var(--surface));
  border-left: 4px solid var(--accent);
  padding: var(--space-4) var(--space-5);
  border-radius: 0 var(--radius-md) var(--radius-md) 0;
  margin-block: var(--space-5);
}
.ed-tldr-label {
  display: block;
  font-size: var(--fs-xs);
  font-weight: var(--fw-semibold);
  letter-spacing: var(--ls-widest);
  text-transform: uppercase;
  color: var(--accent);
  margin-block-end: var(--space-2);
}
.ed-tldr p { margin: 0; }

/* ── Field note callout (sidebar-style aside) ─────────────────────── */

.ed-field-note {
  background: var(--surface-2);
  border: 1px solid var(--border);
  padding: var(--space-4);
  border-radius: var(--radius-md);
  margin-block: var(--space-5);
}
.ed-field-note > strong:first-child {
  display: block;
  font-family: var(--font-display);
  font-size: var(--fs-base);
  margin-block-end: var(--space-2);
  color: var(--text);
}

/* ── Job meta (job-site stat badges) ──────────────────────────────── */

.ed-job-meta {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(8rem, 1fr));
  gap: var(--space-3);
  background: var(--surface-2);
  padding: var(--space-4);
  border-radius: var(--radius-md);
  border: 1px solid var(--border);
  margin-block: var(--space-5);
}
.ed-job-meta > div {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
}
.ed-job-meta strong {
  font-family: var(--font-display);
  font-size: var(--fs-base);
  color: var(--text);
}
.ed-job-meta span {
  font-size: var(--fs-xs);
  letter-spacing: var(--ls-wide);
  text-transform: uppercase;
  color: var(--text-muted);
}

/* ── Pullquote ────────────────────────────────────────────────────── */

.ed-pullquote {
  font-family: var(--font-display);
  font-size: clamp(1.4rem, 1.1rem + 1.2vw, 1.75rem);
  line-height: var(--lh-snug);
  font-style: italic;
  color: var(--text);
  border-left: 4px solid var(--accent);
  padding-inline-start: var(--space-5);
  margin-block: var(--space-6);
  max-width: 50ch;
}

/* ── Tables ───────────────────────────────────────────────────────── */

.ed-table {
  width: 100%;
  border-collapse: collapse;
  margin-block: var(--space-5);
  font-size: var(--fs-sm);
}
.ed-table thead th {
  background: var(--primary);
  color: var(--primary-fg);
  text-align: left;
  padding: var(--space-3) var(--space-4);
  font-weight: var(--fw-semibold);
  letter-spacing: var(--ls-wide);
  font-size: var(--fs-xs);
  text-transform: uppercase;
}
.ed-table tbody td {
  padding: var(--space-3) var(--space-4);
  border-bottom: 1px solid var(--border);
  vertical-align: top;
}
.ed-table tbody tr:nth-child(even) td {
  background: color-mix(in srgb, var(--surface-2) 60%, transparent);
}
.ed-table tbody tr:last-child td { border-bottom: none; }

/* ── Stat row (3 large numeric stats inline) ──────────────────────── */

.ed-stat-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(8rem, 1fr));
  gap: var(--space-4);
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: var(--space-5);
  margin-block: var(--space-6);
}
.ed-stat { text-align: center; display: flex; flex-direction: column; gap: var(--space-1); }
.ed-stat-num {
  font-family: var(--font-display);
  font-weight: var(--fw-bold);
  font-size: clamp(1.75rem, 1.4rem + 1.2vw, 2.25rem);
  line-height: 1;
  color: var(--accent);
}
.ed-stat-label {
  font-size: var(--fs-xs);
  letter-spacing: var(--ls-wide);
  text-transform: uppercase;
  color: var(--text-muted);
}

/* ── Inline mid-post CTA ──────────────────────────────────────────── */

.ed-cta-inline {
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: var(--space-5);
  text-align: center;
  margin-block: var(--space-6);
}
.ed-cta-inline > * + * { margin-block-start: var(--space-3); }
.ed-cta-inline p {
  margin: 0 auto;
  max-width: 50ch;
  color: var(--text-muted);
}
.ed-cta-btn {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  background: var(--danger);
  color: #ffffff;
  text-decoration: none;
  padding: var(--space-3) var(--space-5);
  border-radius: var(--radius);
  font-weight: var(--fw-semibold);
  min-height: 44px;
  transition: background var(--dur-fast) var(--ease);
}
.ed-cta-btn:hover { background: color-mix(in srgb, var(--danger) 88%, var(--text)); }

/* ── FAQ block (within posts) ─────────────────────────────────────── */

.ed-faq { margin-block: var(--space-6); }
.ed-faq-heading {
  font-family: var(--font-display);
  font-weight: var(--fw-bold);
  font-size: var(--fs-xl);
  margin-block-end: var(--space-3);
}
.ed-faq details {
  border-block-end: 1px solid var(--border);
  padding-block: var(--space-3);
}
.ed-faq summary {
  cursor: pointer;
  font-family: var(--font-display);
  font-weight: var(--fw-semibold);
  font-size: var(--fs-base);
  color: var(--text);
  list-style: none;
  display: flex;
  justify-content: space-between;
  gap: var(--space-3);
}
.ed-faq summary::after {
  content: "+";
  font-family: var(--font-mono);
  color: var(--accent);
  font-size: 1.4em;
  line-height: 1;
}
.ed-faq details[open] summary::after { content: "−"; }
.ed-faq details p { margin-block-start: var(--space-2); }

/* ── Author block (post footer) ───────────────────────────────────── */

.ed-author {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: var(--space-4);
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: var(--space-5);
  margin-block: var(--space-7);
  align-items: center;
}
.ed-author-avatar {
  width: 64px;
  height: 64px;
  border-radius: 50%;
  background: var(--primary);
  color: var(--primary-fg);
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-display);
  font-weight: var(--fw-bold);
  font-size: var(--fs-lg);
}
.ed-author-meta strong {
  display: block;
  font-family: var(--font-display);
  font-size: var(--fs-base);
  color: var(--text);
}
.ed-author-meta p { margin: var(--space-2) 0 0; font-size: var(--fs-sm); color: var(--text-muted); }
.ed-credentials {
  font-size: var(--fs-xs);
  color: var(--accent);
  letter-spacing: var(--ls-wide);
  font-weight: var(--fw-semibold);
}

/* ── Related posts grid (post footer) ─────────────────────────────── */

.ed-related-grid,
.ed-related-list {
  display: grid;
  gap: var(--space-4);
  grid-template-columns: repeat(auto-fit, minmax(min(15rem, 100%), 1fr));
  margin-block: var(--space-6);
  padding: 0;
  list-style: none;
}
.ed-related-card {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: var(--space-4);
  text-decoration: none;
  color: var(--text);
  transition: transform var(--dur-base) var(--ease), border-color var(--dur-base) var(--ease);
}
@media (hover: hover) and (pointer: fine) {
  .ed-related-card:hover {
    transform: translateY(-2px);
    border-color: color-mix(in srgb, var(--primary) 30%, var(--border));
  }
}
.ed-related-tag {
  font-size: var(--fs-xs);
  letter-spacing: var(--ls-widest);
  text-transform: uppercase;
  color: var(--accent);
  font-weight: var(--fw-semibold);
}
.ed-related-card h4,
.ed-related-card strong {
  font-family: var(--font-display);
  font-weight: var(--fw-semibold);
  font-size: var(--fs-base);
  line-height: var(--lh-snug);
  color: var(--text);
  margin: 0;
}

/* ── Article footer wrapper ───────────────────────────────────────── */

.ed-article-footer {
  margin-block-start: var(--space-7);
  padding-block-start: var(--space-5);
  border-block-start: 1px solid var(--border);
}

/* ── Sidebar (rare, used in some longer posts) ───────────────────── */

.ed-grid {
  /* Mobile: collapse the body+sidebar into a single column. */
  display: block;
}
@media (min-width: 1024px) {
  .ed-grid {
    display: grid;
    grid-template-columns: minmax(0, 1fr) 280px;
    gap: var(--space-7);
    align-items: start;
  }
}
.ed-sidebar {
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}
.ed-side-card {
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: var(--space-4);
}
.ed-side-label {
  font-size: var(--fs-xs);
  letter-spacing: var(--ls-widest);
  text-transform: uppercase;
  color: var(--accent);
  font-weight: var(--fw-semibold);
  margin-block-end: var(--space-2);
}
.ed-side-cta {
  background: var(--danger);
  color: #ffffff;
  text-align: center;
  padding: var(--space-4);
  border-radius: var(--radius-md);
}
.ed-side-cta a { color: #ffffff; text-decoration: none; }
.ed-side-phone {
  font-family: var(--font-display);
  font-weight: var(--fw-bold);
  font-size: var(--fs-lg);
  display: block;
  color: #ffffff;
  margin-block: var(--space-2);
}

/* ── Container override — old .ed-container becomes a no-op since
       .blog-post handles width / padding. Strip its old margins. ── */
.ed-container { max-width: none; padding: 0; margin: 0; }

/* ── Removed in migration but present in old markup (defensive hide) ── */
.ed-masthead,
.ed-title-mark { display: none; }

/* ── Blog index ──────────────────────────────────────────────────── */

.blog-index-section { padding-block: var(--space-6); }

.blog-index-section + .blog-index-section { padding-block-start: var(--space-3); }

.blog-section-title {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-3);
  flex-wrap: wrap;
  padding-block-end: var(--space-3);
  margin-block-end: var(--space-5);
  border-block-end: 2px solid var(--accent);
}
.blog-section-title h2 {
  font-family: var(--font-display);
  font-size: var(--fs-xl);
  margin: 0;
  color: var(--text);
}
.blog-section-title-count {
  font-size: var(--fs-xs);
  letter-spacing: var(--ls-widest);
  text-transform: uppercase;
  color: var(--text-muted);
  font-weight: var(--fw-semibold);
}

.blog-index-grid {
  display: grid;
  gap: var(--space-4);
  grid-template-columns: repeat(auto-fit, minmax(min(20rem, 100%), 1fr));
}

.blog-index-card {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-radius: var(--radius-md);
  padding: var(--space-5);
  text-decoration: none;
  color: var(--text);
  transition: transform var(--dur-base) var(--ease),
              border-color var(--dur-base) var(--ease),
              box-shadow var(--dur-base) var(--ease);
}
@media (hover: hover) and (pointer: fine) {
  .blog-index-card:hover {
    transform: translateY(-3px);
    border-color: color-mix(in srgb, var(--primary) 30%, var(--border));
    box-shadow: var(--shadow-md);
  }
}
.blog-index-card .fj-tag {
  font-size: var(--fs-xs);
  font-weight: var(--fw-semibold);
  letter-spacing: var(--ls-widest);
  text-transform: uppercase;
  color: var(--accent);
}
.blog-index-card h3 {
  font-family: var(--font-display);
  font-weight: var(--fw-bold);
  font-size: var(--fs-lg);
  line-height: var(--lh-snug);
  color: var(--text);
  margin: 0;
}
.blog-index-card p {
  margin: 0;
  color: var(--text-muted);
  font-size: var(--fs-sm);
  line-height: var(--lh-normal);
}
.blog-index-card .fj-meta {
  margin-block-start: auto;
  padding-block-start: var(--space-3);
  border-block-start: 1px dashed var(--border);
  display: flex;
  justify-content: space-between;
  font-size: var(--fs-xs);
  text-transform: uppercase;
  letter-spacing: var(--ls-wide);
  color: var(--text-muted);
}

/* ── Featured intro pair on the blog index ──────────────────────── */

.blog-feature {
  display: grid;
  gap: var(--space-5);
  grid-template-columns: 1fr;
  margin-block-end: var(--space-7);
}
@media (min-width: 768px) { .blog-feature { grid-template-columns: 1fr 1fr; } }

.blog-feature-card {
  background: color-mix(in srgb, var(--primary) 8%, var(--surface));
  border: 1px solid color-mix(in srgb, var(--primary) 25%, var(--border));
  border-radius: var(--radius-md);
  padding: var(--space-5);
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
}
.blog-feature-card h2 {
  font-family: var(--font-display);
  font-size: var(--fs-lg);
  margin: 0;
  color: var(--text);
}
.blog-feature-card p { margin: 0; color: var(--text-muted); font-size: var(--fs-sm); }
.blog-feature-card a {
  margin-block-start: auto;
  align-self: flex-start;
  font-weight: var(--fw-semibold);
  color: var(--primary);
}

/* --- End: pages/blog.css --- */

/* --- Start: pages/answers.css --- */
/* answers.css — page-specific layout for /answers/, generated by
 * scripts/build-answers.js. Three page types:
 *
 *   1. Hub landing  (/answers/)              — eyebrow + h1 + 8 category blocks
 *   2. Category page (/answers/{cat}/)       — h1 + lede + list of all entries inline
 *   3. Entry page    (/answers/{cat}/{slug}/) — h1 + answer callout + meta + author
 *                                                + related + bottom CTA
 *
 * Class vocabulary preserved from the legacy generator so the JSON-LD and
 * any external link-anchor patterns continue to work. Styling rebuilt against
 * design tokens so dark mode works automatically.
 */

/* ── Shared: hub landing eyebrow + intro ────────────────────────────── */
.ans-hero {
  text-align: center;
  padding-block: var(--space-7) var(--space-6);
  border-block-end: 1px solid var(--border);
}
.ans-hero .container {
  max-width: 760px;
  margin-inline: auto;
}
.ans-hero .kicker {
  display: inline-block;
  background: color-mix(in srgb, var(--accent) 12%, transparent);
  color: var(--accent);
  padding: var(--space-1) var(--space-3);
  font-size: var(--fs-xs);
  font-weight: var(--fw-semibold);
  letter-spacing: var(--ls-widest);
  text-transform: uppercase;
  border-radius: var(--radius-pill);
  margin-block-end: var(--space-3);
}
.ans-hero h1 {
  font-family: var(--font-display);
  font-size: clamp(2rem, 1.4rem + 2.4vw, 2.75rem);
  line-height: var(--lh-tight);
  letter-spacing: var(--ls-tight);
  color: var(--text);
  font-weight: var(--fw-bold);
  margin: 0 0 var(--space-3);
  max-width: 22ch;
  margin-inline: auto;
  text-wrap: balance;
}
.ans-hero h1 em { font-style: italic; color: var(--accent); }
.ans-hero p {
  font-size: var(--fs-md);
  color: var(--text-muted);
  max-width: 60ch;
  margin: 0 auto;
  line-height: var(--lh-normal);
}

/* ── Hub landing body ──────────────────────────────────────────────── */
.ans-body {
  max-width: 1200px;
  margin-inline: auto;
  padding: var(--space-7) var(--space-container) var(--space-9);
}
.ans-cat-block { margin-block-end: var(--space-7); }
.ans-cat-head {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--space-3);
  flex-wrap: wrap;
  border-block-end: 2px solid var(--accent);
  padding-block-end: var(--space-2);
  margin-block-end: var(--space-4);
}
.ans-cat-head h2 {
  font-family: var(--font-display);
  font-size: var(--fs-xl);
  color: var(--text);
  margin: 0;
  font-weight: var(--fw-bold);
}
.ans-cat-head span {
  font-size: var(--fs-xs);
  letter-spacing: var(--ls-widest);
  text-transform: uppercase;
  color: var(--text-muted);
  font-weight: var(--fw-semibold);
}
.ans-list {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(min(20rem, 100%), 1fr));
  gap: var(--space-1) var(--space-5);
}
.ans-list li {
  padding-block: var(--space-2);
  border-block-end: 1px dashed var(--border);
}
.ans-list a {
  color: var(--text);
  text-decoration: none;
  font-size: var(--fs-base);
  line-height: var(--lh-normal);
}
.ans-list a:hover { color: var(--primary); }
.ans-cat-link {
  display: inline-block;
  margin-block-start: var(--space-3);
  color: var(--primary);
  font-weight: var(--fw-semibold);
  text-decoration-color: color-mix(in srgb, var(--primary) 35%, transparent);
}

/* ── Category page header ──────────────────────────────────────────── */
.cat-hero {
  max-width: 1000px;
  margin-inline: auto;
  padding: var(--space-6) var(--space-container) var(--space-5);
  border-block-end: 1px solid var(--border);
}
.cat-hero .breadcrumb {
  font-size: var(--fs-xs);
  letter-spacing: var(--ls-widest);
  text-transform: uppercase;
  color: var(--text-muted);
  margin-block-end: var(--space-3);
}
.cat-hero .breadcrumb a { color: var(--accent); text-decoration: none; }
.cat-hero .breadcrumb a:hover { text-decoration: underline; }
.cat-hero .kicker {
  display: inline-block;
  background: color-mix(in srgb, var(--accent) 12%, transparent);
  color: var(--accent);
  padding: var(--space-1) var(--space-3);
  font-size: var(--fs-xs);
  font-weight: var(--fw-semibold);
  letter-spacing: var(--ls-widest);
  text-transform: uppercase;
  border-radius: var(--radius-pill);
  margin-block-end: var(--space-3);
}
.cat-hero h1 {
  font-family: var(--font-display);
  font-size: clamp(1.875rem, 1.4rem + 2vw, 2.5rem);
  color: var(--text);
  font-weight: var(--fw-bold);
  line-height: var(--lh-tight);
  letter-spacing: var(--ls-tight);
  margin: 0 0 var(--space-3);
}
.cat-hero p {
  font-size: var(--fs-md);
  color: var(--text-muted);
  max-width: 60ch;
  margin: 0;
  line-height: var(--lh-normal);
}

.cat-body {
  max-width: 1000px;
  margin-inline: auto;
  padding: var(--space-7) var(--space-container) var(--space-9);
}

/* Per-entry card on category page */
.ans-item {
  background: var(--surface-2);
  border: 1px solid var(--border);
  border-left: 3px solid var(--accent);
  padding: var(--space-5);
  margin-block-end: var(--space-4);
  border-radius: 0 var(--radius-md) var(--radius-md) 0;
}
.ans-item h2 {
  font-family: var(--font-display);
  font-size: var(--fs-lg);
  font-weight: var(--fw-bold);
  color: var(--text);
  margin: 0 0 var(--space-3);
  line-height: var(--lh-snug);
}
.ans-item h2 a { color: inherit; text-decoration: none; }
.ans-item h2 a:hover { color: var(--primary); }
.ans-item p {
  color: var(--text);
  font-size: var(--fs-base);
  line-height: var(--lh-relaxed);
  margin: 0 0 var(--space-3);
}
.ans-item-meta {
  display: flex;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: var(--space-2);
  padding-block-start: var(--space-3);
  border-block-start: 1px dashed var(--border);
}
.ans-cite {
  font-family: var(--font-mono);
  font-size: var(--fs-sm);
  color: var(--text-muted);
}
.ans-permalink {
  font-size: var(--fs-sm);
  color: var(--primary);
  font-weight: var(--fw-semibold);
}

/* ── Entry page (single-question detail) ───────────────────────────── */
.entry-wrap {
  max-width: 760px;
  margin-inline: auto;
  padding: var(--space-7) var(--space-container) var(--space-9);
}
.entry-wrap .breadcrumb {
  font-size: var(--fs-xs);
  letter-spacing: var(--ls-widest);
  text-transform: uppercase;
  color: var(--text-muted);
  margin-block-end: var(--space-4);
}
.entry-wrap .breadcrumb a { color: var(--accent); text-decoration: none; }
.entry-wrap .breadcrumb a:hover { text-decoration: underline; }
.entry-wrap h1 {
  font-family: var(--font-display);
  font-size: clamp(1.875rem, 1.4rem + 2vw, 2.5rem);
  color: var(--text);
  font-weight: var(--fw-bold);
  line-height: var(--lh-tight);
  letter-spacing: var(--ls-tight);
  margin: 0 0 var(--space-5);
}

/* The answer block — visually the centerpiece of the page */
.entry-answer {
  font-family: var(--font-display);
  font-size: var(--fs-lg);
  line-height: var(--lh-normal);
  color: var(--text);
  background: color-mix(in srgb, var(--accent) 8%, var(--surface));
  border: 1px solid color-mix(in srgb, var(--accent) 25%, var(--border));
  border-left: 6px solid var(--accent);
  padding: var(--space-5);
  border-radius: 0 var(--radius-md) var(--radius-md) 0;
  margin-block-end: var(--space-5);
}

.entry-meta {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2) var(--space-5);
  padding-block: var(--space-3);
  border-block: 1px solid var(--border);
  margin-block-end: var(--space-5);
  font-size: var(--fs-sm);
  letter-spacing: var(--ls-wide);
  color: var(--text-muted);
}
.entry-meta .cite {
  color: var(--text);
  font-family: var(--font-mono);
  letter-spacing: 0;
  text-transform: none;
}

.entry-author {
  display: grid;
  grid-template-columns: auto 1fr;
  gap: var(--space-4);
  align-items: center;
  background: var(--surface-2);
  border: 1px solid var(--border);
  padding: var(--space-4);
  border-radius: var(--radius-md);
  margin-block-end: var(--space-6);
}
.entry-author .avatar {
  width: 56px;
  height: 56px;
  border-radius: 50%;
  background: var(--primary);
  color: var(--primary-fg);
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-display);
  font-size: var(--fs-lg);
  font-weight: var(--fw-bold);
  flex-shrink: 0;
}
.entry-author .meta strong {
  display: block;
  color: var(--text);
  font-family: var(--font-display);
  font-size: var(--fs-base);
  font-weight: var(--fw-bold);
  margin-block-end: var(--space-1);
}
.entry-author .meta span {
  display: block;
  color: var(--text-muted);
  font-size: var(--fs-sm);
  line-height: var(--lh-normal);
}

/* Related answers list */
.ans-related {
  margin-block-start: var(--space-6);
  padding-block-start: var(--space-5);
  border-block-start: 1px solid var(--border);
}
.ans-related h2 {
  font-family: var(--font-display);
  color: var(--text);
  font-size: var(--fs-lg);
  font-weight: var(--fw-bold);
  margin: 0 0 var(--space-3);
}
.ans-related ul { list-style: none; margin: 0; padding: 0; }
.ans-related li {
  padding-block: var(--space-2);
  border-block-end: 1px dashed var(--border);
}
.ans-related a {
  color: var(--text);
  text-decoration: none;
  font-size: var(--fs-base);
}
.ans-related a:hover { color: var(--primary); }

.cat-tag {
  display: inline-block;
  background: color-mix(in srgb, var(--accent) 12%, transparent);
  color: var(--accent);
  padding: 2px var(--space-2);
  border-radius: var(--radius-sm);
  font-size: var(--fs-xs);
  font-weight: var(--fw-semibold);
  letter-spacing: var(--ls-wide);
  text-transform: uppercase;
  margin-inline-end: var(--space-2);
}

/* Bottom CTA */
.cta-bar {
  margin-block-start: var(--space-6);
  background: var(--danger);
  color: #ffffff;
  padding: var(--space-5);
  border-radius: var(--radius-md);
  text-align: center;
}
.cta-bar h2 {
  font-family: var(--font-display);
  color: #ffffff;
  font-size: var(--fs-lg);
  font-weight: var(--fw-bold);
  margin: 0 0 var(--space-2);
}
.cta-bar p {
  color: rgba(255, 255, 255, 0.9);
  margin: 0 0 var(--space-3);
  font-size: var(--fs-base);
}
.cta-bar a.btn {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  background: #ffffff;
  color: var(--danger);
  padding: var(--space-3) var(--space-5);
  border-radius: var(--radius);
  text-decoration: none;
  font-weight: var(--fw-semibold);
  min-height: 44px;
  transition: background var(--dur-fast) var(--ease);
}
.cta-bar a.btn:hover { background: rgba(255, 255, 255, 0.92); }

/* --- End: pages/answers.css --- */
