/* ==========================================================================
   STYLES.CSS — layout, components, and behavior. Reads all values from
   tokens.css. Do not hardcode a color, font, radius, or spacing value in
   this file — add or reuse a token instead. This keeps every client site
   a true reskin of the same system.
   ========================================================================== */

/* ---------------------------------------------------------------------
   RESET
   --------------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
body, h1, h2, h3, h4, p, figure, blockquote, dl, dd { margin: 0; }
ul[class], ol[class] { margin: 0; padding: 0; list-style: none; }
img, picture, svg { display: block; max-width: 100%; }
input, button, textarea, select { font: inherit; color: inherit; }
button { cursor: pointer; }
a { color: inherit; }

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
  *, *::before, *::after {
    animation-duration: 0.01ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: 0.01ms !important;
    scroll-behavior: auto !important;
  }
}

/* ---------------------------------------------------------------------
   BASE
   --------------------------------------------------------------------- */
body {
  font-family: var(--font-body);
  font-size: var(--text-base);
  line-height: var(--leading-normal);
  color: var(--color-text);
  background: var(--color-bg);
  -webkit-font-smoothing: antialiased;
}

h1, h2, h3, h4 {
  font-family: var(--font-display);
  font-weight: 400;
  line-height: var(--leading-tight);
  color: var(--color-primary);
  letter-spacing: -0.01em;
}

h1 { font-size: var(--text-4xl); }
h2 { font-size: var(--text-2xl); }
h3 { font-size: var(--text-lg); }

p { color: var(--color-text-muted); }
/* Global reset zeroes p margin (see RESET above), so consecutive prose
   paragraphs collide with no gap - this restores spacing between them
   without affecting single paragraphs or paragraphs inside flex/grid
   components that already handle their own spacing via gap. */
p + p { margin-top: var(--space-4); }

.lede {
  font-size: var(--text-md);
  color: var(--color-text-muted);
  line-height: var(--leading-relaxed);
}

a.link {
  color: var(--color-primary);
  text-decoration: underline;
  text-decoration-color: var(--color-accent);
  text-underline-offset: 3px;
}
a.link:hover { color: var(--color-accent-ink); }

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

.container--narrow { max-width: var(--container-narrow); }
/* Prose body sections (About story, legal pages, service detail copy) - h2
   has zero margin from the global reset, so it sits flush against the body
   copy below it with no breathing room. */
.container--narrow h2 { margin-bottom: var(--space-4); }

.visually-hidden {
  position: absolute;
  width: 1px; height: 1px;
  padding: 0; margin: -1px;
  overflow: hidden;
  clip: rect(0, 0, 0, 0);
  white-space: nowrap;
  border: 0;
}

.skip-link {
  position: absolute;
  left: -9999px;
  top: 0;
  background: var(--color-primary);
  color: var(--color-text-inverse);
  padding: var(--space-3) var(--space-5);
  z-index: 200;
  border-radius: 0 0 var(--radius-sm) 0;
}
.skip-link:focus { left: 0; }

:focus-visible {
  outline: 2px solid var(--color-focus);
  outline-offset: 2px;
}

/* Finding 2: fragment targets (footer service links, "Learn more" cards,
   #faq, and every service-detail id on services.html) need scroll-margin
   so the sticky header doesn't cover the heading once scrolled to. Applies
   to any section or service-detail block that carries an id. Mobile gets
   extra margin because a wrapped brand name (finding 4) can grow the
   sticky header taller than --header-height. site.js also drives the
   actual scroll (see "Fragment scroll" in js/site.js) so this works both
   on direct/cross-page load and same-page anchor clicks, not just the
   cases the browser's own scroll-into-view already handled. */
section[id],
.service-detail[id] {
  scroll-margin-top: calc(var(--header-height) + var(--space-4));
}
@media (max-width: 480px) {
  section[id],
  .service-detail[id] {
    scroll-margin-top: calc(var(--header-height) + var(--space-9));
  }
}

/* Section rhythm */
.section { padding-block: var(--space-10); }
.section--alt { background: var(--color-bg-alt); }
.section--dark {
  background: linear-gradient(160deg, var(--color-primary) 0%, var(--color-primary-700) 100%);
  color: var(--color-text-inverse);
  --color-focus: var(--color-accent);
}
.section--dark h1, .section--dark h2, .section--dark h3 { color: var(--color-text-inverse); }
.section--dark p { color: var(--color-text-inverse-muted); }

.section-head {
  max-width: 640px;
  margin-bottom: var(--space-8);
}
.section-head--center { margin-inline: auto; text-align: center; }

.eyebrow {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  font-family: var(--font-body);
  font-size: var(--text-xs);
  font-weight: 700;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: var(--color-accent-ink);
  margin-bottom: var(--space-4);
}
.eyebrow::before {
  content: '';
  width: 22px;
  height: 2px;
  background: var(--color-accent);
  display: inline-block;
}
.section--dark .eyebrow { color: var(--color-accent); }

/* ---------------------------------------------------------------------
   BUTTONS
   --------------------------------------------------------------------- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-2);
  padding: var(--space-3-5) calc(var(--space-5) + var(--space-1));
  border-radius: var(--radius-full);
  font-weight: 600;
  font-size: var(--text-sm);
  text-decoration: none;
  border: var(--border-width) solid transparent;
  transition: transform var(--transition-fast), box-shadow var(--transition-fast), background var(--transition-fast), color var(--transition-fast);
  white-space: nowrap;
}
.btn:hover { transform: translateY(-2px); }
.btn:active { transform: translateY(0); }

.btn--primary {
  background: var(--color-accent);
  color: var(--color-primary-700);
  box-shadow: var(--shadow-gold);
}
.btn--primary:hover {
  background: var(--color-accent-600);
  box-shadow: 0 14px 34px rgba(201, 168, 20, 0.34), 0 3px 8px rgba(20, 20, 16, 0.10);
}

.btn--outline {
  background: transparent;
  border-color: currentColor;
  color: var(--color-primary);
}
.section--dark .btn--outline { color: var(--color-text-inverse); }
.btn--outline:hover { background: rgba(15,15,13,0.06); }

.btn--ghost-light {
  background: rgba(255,255,255,0.08);
  color: var(--color-text-inverse);
  border-color: var(--color-border-dark);
}
.btn--ghost-light:hover { background: rgba(255,255,255,0.16); }

/* Solid black fill - the deliberate "black as accent" button, used as the
   primary action inside the gold .cta-band where a gold-filled button would
   disappear into its own background. */
.btn--dark {
  background: var(--color-primary);
  color: var(--color-text-inverse);
}
.btn--dark:hover { background: var(--color-primary-600); }

.btn--block { width: 100%; }
.btn--lg { padding: var(--space-4) var(--space-6); font-size: var(--text-md); }

.btn[disabled] { opacity: 0.6; cursor: not-allowed; transform: none; }

/* ---------------------------------------------------------------------
   HEADER / NAV
   --------------------------------------------------------------------- */
.site-header {
  position: sticky;
  top: 0;
  z-index: 100;
  background: rgba(255, 255, 255, 0.92);
  backdrop-filter: blur(10px);
  -webkit-backdrop-filter: blur(10px);
  border-bottom: var(--border-width) solid var(--color-border);
}

.site-header__bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-5);
  min-height: var(--header-height);
}

.brand {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  min-width: 0;
  flex: 1 1 auto;
  text-decoration: none;
  color: var(--color-primary);
}

.brand__mark {
  width: 42px;
  height: 42px;
  border-radius: var(--radius-sm);
  background: linear-gradient(155deg, var(--color-primary), var(--color-primary-700));
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}
.brand__mark svg { width: 24px; height: 24px; }

/* Text wrapper (name + tagline) — needs min-width:0 so it can actually
   shrink inside the flex row instead of forcing brand-name/tagline to
   wrap across 2-3 lines (which used to blow out the header's real
   height past the --header-height token the mobile nav dropdown
   anchors to). No class in the markup to hook, so target structurally. */
.brand > span:not(.brand__mark) {
  min-width: 0;
}

.brand__name {
  display: block;
  font-family: var(--font-display);
  font-size: var(--text-lg);
  line-height: 1.1;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 100%;
}
.brand__tagline {
  display: block;
  font-family: var(--font-body);
  font-size: var(--text-xs);
  font-weight: 600;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--color-text-faint);
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.nav-toggle {
  display: none;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  flex-shrink: 0;
  border-radius: var(--radius-sm);
  border: var(--border-width) solid var(--color-border);
  background: var(--color-bg);
}
.nav-toggle__bar, .nav-toggle__bar::before, .nav-toggle__bar::after {
  content: '';
  display: block;
  width: 20px;
  height: 2px;
  background: var(--color-primary);
  position: relative;
  transition: all var(--transition-fast);
}
.nav-toggle__bar::before { position: absolute; top: -6px; width: 20px; }
.nav-toggle__bar::after { position: absolute; top: 6px; width: 20px; }

/* Finding 15: morph hamburger -> X when open. Pure CSS, driven off the
   aria-expanded state site.js already sets (no new JS needed). The bars
   already transition "all" var(--transition-fast), and the global
   prefers-reduced-motion block at the top of this file forces all
   transition-durations to ~0 for users who've asked for less motion, so
   this respects that automatically. */
.nav-toggle[aria-expanded="true"] .nav-toggle__bar {
  background: transparent;
}
.nav-toggle[aria-expanded="true"] .nav-toggle__bar::before {
  top: 0;
  transform: rotate(45deg);
}
.nav-toggle[aria-expanded="true"] .nav-toggle__bar::after {
  top: 0;
  transform: rotate(-45deg);
}

.main-nav__list {
  display: flex;
  align-items: center;
  gap: var(--space-6);
}
.main-nav__link {
  font-size: var(--text-sm);
  font-weight: 600;
  text-decoration: none;
  color: var(--color-text-muted);
  padding-block: var(--space-2);
  border-bottom: 2px solid transparent;
  transition: color var(--transition-fast), border-color var(--transition-fast);
}
.main-nav__link:hover,
.main-nav__link[aria-current="page"] {
  color: var(--color-primary);
  border-color: var(--color-accent);
}

/* Services dropdown: hover/focus flyout on desktop, plain nested list on
   mobile (see the max-width:900px override below). */
.main-nav__item--has-dropdown { position: relative; }
.main-nav__dropdown {
  list-style: none;
  margin: 0;
  padding: var(--space-2);
  position: absolute;
  top: 100%;
  left: 50%;
  transform: translateX(-50%) translateY(-6px);
  min-width: 240px;
  background: var(--color-bg);
  border: var(--border-width) solid var(--color-border);
  border-radius: var(--radius-md);
  box-shadow: var(--shadow-lg);
  opacity: 0;
  pointer-events: none;
  transition: opacity var(--transition-base), transform var(--transition-base);
  z-index: 20;
}
/* Scoped to desktop only (not just left as the default/unscoped rule) -
   iOS Safari applies a "sticky" :hover state after a real tap since
   touchscreens have no true hover, and this rule's specificity would
   otherwise beat the mobile .is-open override below, silently
   re-applying transform: translateX(-50%) on phones and shoving the
   whole accordion off the left edge of the screen. Wrapping it in
   min-width:901px means it cannot match at all below that width,
   regardless of any sticky-hover quirk. */
@media (min-width: 901px) {
  .main-nav__item--has-dropdown:hover .main-nav__dropdown,
  .main-nav__item--has-dropdown:focus-within .main-nav__dropdown {
    opacity: 1;
    transform: translateX(-50%) translateY(0);
    pointer-events: auto;
  }
}
.main-nav__dropdown a {
  display: block;
  padding: var(--space-2) var(--space-3);
  border-radius: var(--radius-sm);
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--color-text-muted);
  text-decoration: none;
  white-space: nowrap;
  transition: background var(--transition-fast), color var(--transition-fast);
}
.main-nav__dropdown a:hover,
.main-nav__dropdown a:focus-visible {
  background: var(--color-bg-alt);
  color: var(--color-primary);
}

.header-actions {
  display: flex;
  align-items: center;
  gap: var(--space-4);
}
.header-call {
  display: flex;
  align-items: center;
  gap: var(--space-2);
  min-height: 44px;
  flex-shrink: 0;
  padding-inline: var(--space-2);
  margin-inline: calc(var(--space-2) * -1);
  font-weight: 700;
  font-size: var(--text-sm);
  text-decoration: none;
  color: var(--color-primary);
  white-space: nowrap;
}
.header-call svg { width: 20px; height: 20px; color: var(--color-accent-ink); flex-shrink: 0; }

@media (max-width: 900px) {
  .nav-toggle { display: inline-flex; }
  .main-nav {
    /* Anchored to .site-header (position: sticky, so it's the nearest
       positioned ancestor) via top:100% instead of the old
       `inset: var(--header-height) ...`. The old fixed offset assumed
       an 84px header, but a long company name or tagline wraps the
       header taller than that on narrow phones, which left the
       dropdown floating over/under the wrong spot. top:100% always
       lands right below the header regardless of its rendered height. */
    position: absolute;
    top: 100%;
    left: var(--space-4);
    right: var(--space-4);
    margin-top: var(--space-3);
    background: var(--color-bg);
    border: var(--border-width) solid var(--color-border);
    border-radius: var(--radius-md);
    box-shadow: var(--shadow-lg);
    padding: var(--space-5);
    transform: translateY(-12px);
    opacity: 0;
    pointer-events: none;
    transition: transform var(--transition-base), opacity var(--transition-base);
  }
  .main-nav.is-open {
    transform: translateY(0);
    opacity: 1;
    pointer-events: auto;
  }
  .main-nav__list {
    flex-direction: column;
    align-items: flex-start;
    gap: var(--space-4);
    width: 100%;
  }
  .main-nav__link { width: 100%; }
  .header-actions .btn--outline { display: none; }

  /* Services dropdown on mobile: collapsed accordion under "Services",
     not a hover flyout (no hover on touch) and not always-open (that
     made the whole menu look jumbled on open - site.js toggles the
     is-open class on tap). */
  .main-nav__dropdown {
    position: static;
    opacity: 1;
    pointer-events: none;
    transform: none;
    box-shadow: none;
    border: none;
    background: transparent;
    padding: 0 0 0 var(--space-4);
    margin-top: 0;
    max-height: 0;
    overflow: hidden;
    transition: max-height var(--transition-base);
    /* Without these, the desktop flyout's min-width:240px + nowrap
       links make this box size to its widest label ("Ambulatory
       Transportation") instead of the phone's actual width, pushing
       it wider than the viewport and shifting the visible portion
       left - this is what caused labels to render cut off/offscreen. */
    width: 100%;
    min-width: 0;
  }
  .main-nav__item--has-dropdown.is-open .main-nav__dropdown {
    pointer-events: auto;
    max-height: 320px;
    padding-top: var(--space-2);
    margin-top: var(--space-2);
  }
  .main-nav__item--has-dropdown { width: 100%; }
  .main-nav__dropdown a {
    padding-block: var(--space-2);
    white-space: normal;
  }

  /* Chevron indicator on the trigger, rotates when the accordion opens. */
  .main-nav__item--has-dropdown > .main-nav__link[aria-haspopup] {
    display: flex;
    align-items: center;
    justify-content: space-between;
  }
  .main-nav__item--has-dropdown > .main-nav__link[aria-haspopup]::after {
    content: '';
    width: 8px;
    height: 8px;
    border-right: 2px solid currentColor;
    border-bottom: 2px solid currentColor;
    transform: rotate(45deg);
    transition: transform var(--transition-fast);
    flex-shrink: 0;
  }
  .main-nav__item--has-dropdown.is-open > .main-nav__link[aria-haspopup]::after {
    transform: rotate(-135deg);
  }

  /* Finding 4: stop ellipsizing the company name on mobile. Let it wrap
     to two (or a few, for very long names) lines instead of truncating
     to "Crown City Med…". min-width:0 on the parent (.brand > span) plus
     max-width:100% here keeps it from ever overflowing the flex row
     regardless of viewport width. */
  .brand__name {
    white-space: normal;
    overflow: visible;
    text-overflow: clip;
    line-height: var(--leading-snug);
  }
}

/* Small phones (~480px and under: iPhone SE/mini, most Android in
   portrait): brand name + tagline + nav-toggle + full phone number
   CTA cannot all fit on one row without either wrapping the header
   tall (breaks the sticky header height) or truncating the company
   name down to one letter. Collapse the always-visible header call
   link to an icon-only 44x44 tap target here — the full number is
   still shown in the hero, footer, and contact page, and this button's
   accessible name still comes from the (visually collapsed, not
   removed) phone-number text node, so it stays screen-reader-friendly. */
@media (max-width: 480px) {
  .brand__tagline { display: none; }
  .header-call {
    width: 44px;
    justify-content: center;
    gap: 0;
    padding-inline: 0;
    margin-inline: 0;
    font-size: 0;
  }
  .header-call svg { width: 20px; height: 20px; }

  /* Small phones (<=480px, 320px worst case): reclaim horizontal room so
     a long wrapped brand name (e.g. "Crown City Medical Transport")
     settles at ~2 lines instead of 3-4, and drop the display size a step
     since the header-call button is icon-only here anyway. */
  .site-header__bar { gap: var(--space-3); }
  .site-header .container { padding-inline: var(--space-4); }
  .brand__name { font-size: var(--text-base); }
}

/* ---------------------------------------------------------------------
   HERO
   --------------------------------------------------------------------- */
.hero {
  position: relative;
  overflow: hidden;
  /* Hernando de Soto Bridge at sunset (Unsplash, Terrance Raper) behind a
     charcoal wash - left side darkest, where the text sits. */
  background:
    linear-gradient(100deg, rgba(15,15,13,0.90) 0%, rgba(15,15,13,0.72) 52%, rgba(15,15,13,0.42) 100%),
    url('../images/hernando-de-soto-bridge-memphis-sunset.jpg') center 42% / cover no-repeat;
  color: var(--color-text-inverse);
  border-bottom: var(--border-width) solid var(--color-primary-700);
  padding-block: var(--space-11) var(--space-10);
}

.hero::before {
  content: '';
  position: absolute;
  inset: 0;
  background-image:
    radial-gradient(circle at 88% 12%, rgba(201,162,39,0.16), transparent 45%),
    radial-gradient(circle at 8% 92%, rgba(201,162,39,0.10), transparent 40%);
  pointer-events: none;
}

/* Single-column since 2026-09-18: the hospital photo card moved to the
   discharge page, the bridge background carries the visual weight now. */
.hero__grid {
  position: relative;
  display: grid;
  grid-template-columns: 1fr;
}

.hero__eyebrow {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  background: var(--color-accent);
  border: var(--border-width) solid transparent;
  padding: var(--space-2) var(--space-4);
  border-radius: var(--radius-full);
  font-size: var(--text-xs);
  font-weight: 700;
  letter-spacing: 0.06em;
  text-transform: uppercase;
  color: var(--color-primary-700);
  margin-bottom: var(--space-5);
}

.hero h1 {
  color: var(--color-text-inverse);
  font-size: var(--text-4xl);
  max-width: 24ch;
  margin-bottom: var(--space-5);
}
/* .hero h1 em gold highlight removed 2026-09-18 per Ray: single-color
   headline, no two-tone treatment. */

.hero__lede {
  font-size: var(--text-md);
  color: var(--color-text-inverse-muted);
  max-width: 64ch;
  margin-bottom: var(--space-7);
  line-height: var(--leading-relaxed);
}

.hero__actions {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-4);
  margin-bottom: var(--space-8);
}

.hero__stats {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-3);
}
@media (max-width: 560px) {
  .hero__stats { grid-template-columns: 1fr; }
}
.hero__stats > div {
  background: var(--color-bg);
  border: var(--border-width) solid var(--color-border);
  border-radius: var(--radius-sm);
  padding: var(--space-3) var(--space-3-5);
  transition: transform var(--transition-base), background var(--transition-base), border-color var(--transition-base);
}
.hero__stats > div:hover {
  transform: translateY(-3px);
  background: var(--color-accent-tint);
  border-color: var(--color-accent);
}
.hero__stat-num {
  display: block;
  font-family: var(--font-display);
  font-size: var(--text-md);
  color: var(--color-primary);
}
.hero__stat-label {
  font-size: var(--text-xs);
  color: var(--color-text-faint);
  letter-spacing: 0.04em;
  text-transform: uppercase;
}

/* Hero visual: CSS/SVG treatment, no photo dependency */
.hero__visual {
  position: relative;
  align-self: stretch;
  min-height: 520px;
  border-radius: var(--radius-lg);
  background: linear-gradient(155deg, var(--color-accent-tint) 0%, var(--color-bg) 100%);
  border: var(--border-width) solid var(--color-border);
  box-shadow: var(--shadow-lg);
  display: flex;
  align-items: center;
  justify-content: center;
  overflow: hidden;
}
.hero__visual svg { width: 62%; height: 62%; }
/* Deliberate black accent moment on an otherwise light/gold panel. */
.hero__visual-card {
  position: absolute;
  left: var(--space-5);
  right: var(--space-5);
  bottom: var(--space-5);
  background: var(--color-primary);
  border: var(--border-width) solid var(--color-primary-700);
  border-radius: var(--radius-md);
  padding: var(--space-4) var(--space-5);
  display: flex;
  align-items: center;
  gap: var(--space-3);
  box-shadow: var(--shadow-md);
}
.hero__visual-card svg { width: 20px; height: 20px; color: var(--color-accent); flex-shrink: 0; }
.hero__visual-card strong { display: block; font-size: var(--text-sm); color: var(--color-text-inverse); }
.hero__visual-card span { font-size: var(--text-xs); color: var(--color-text-inverse-muted); }

/* Optional image slot: if a client supplies a photo, drop it in and this
   treatment recedes to a simple frame. See comments in index.html. */
.hero__visual.has-image { background: var(--color-primary-600); }
.hero__visual.has-image img { width: 100%; height: 100%; object-fit: cover; }

@media (max-width: 900px) {
  .hero__grid { grid-template-columns: 1fr; }
  /* Finding 3: content (headline, subhead, CTAs, phone) must come first
     on mobile, illustration after, so the ask is reachable without
     scrolling. Natural DOM order already puts the content div before
     .hero__visual - no "order: -1" here, that was flipping it. */
  .hero__visual { aspect-ratio: 16 / 10; }
  .hero h1 { font-size: var(--text-3xl); max-width: 100%; }
}

@media (max-width: 480px) {
  /* Finding 3, continued: the fixed .mobile-call-bar (finding 12) covers
     the bottom ~78px of every viewport, and a wrapped 2-line brand name
     (finding 4) makes the header taller too - both eat into the "buttons
     reachable without scrolling on 375x812" budget. Tighten the hero's
     vertical rhythm on small phones only (desktop/tablet keep the
     original spacing) so the Request a Ride / Call buttons clear the
     sticky bar on load instead of landing underneath it. Placed after
     the unconditional .hero rule above on purpose - same specificity,
     source order decides, and this needs to win. */
  .hero { padding-block: var(--space-9) var(--space-6); }
  .hero__eyebrow { margin-bottom: var(--space-3); }
  .hero h1 { margin-bottom: var(--space-3); }
  .hero__lede { margin-bottom: var(--space-5); }
}

/* ---------------------------------------------------------------------
   TRUST STRIP
   --------------------------------------------------------------------- */
.trust-strip {
  border-bottom: var(--border-width) solid var(--color-border);
  background: var(--color-bg-alt);
}
.trust-strip__row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-4);
  justify-content: space-between;
  align-items: stretch;
  padding-block: var(--space-6);
}
.trust-item {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  flex: 1 1 200px;
  background: var(--color-bg);
  border: var(--border-width) solid var(--color-border);
  border-radius: var(--radius-md);
  padding: var(--space-4) var(--space-5);
  transition: transform var(--transition-base), box-shadow var(--transition-base), border-color var(--transition-base);
}
.trust-item:hover {
  transform: translateY(-3px);
  box-shadow: var(--shadow-md);
  border-color: var(--color-accent);
}
.trust-item svg {
  width: 26px;
  height: 26px;
  color: var(--color-accent-ink);
  flex-shrink: 0;
  transition: transform var(--transition-base);
}
.trust-item:hover svg { transform: scale(1.12); }
.trust-item strong {
  display: block;
  font-size: var(--text-sm);
  color: var(--color-primary);
}
.trust-item span {
  font-size: var(--text-xs);
  color: var(--color-text-faint);
}

/* ---------------------------------------------------------------------
   CARDS — services grid
   --------------------------------------------------------------------- */
.card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(260px, 1fr));
  gap: var(--space-6);
}
/* Force all 4 service cards onto one row at desktop widths rather than
   letting auto-fit wrap a 4th/5th card to its own line at in-between
   widths (e.g. 1000-1150px, where 4x260+gaps doesn't quite clear
   auto-fit's math). card-grid is reused for other N-up grids (About
   values), so this 4-up override is scoped to the homepage "What We
   Offer" grid and the services.html overview grid specifically. */
#services .card-grid,
#services-overview .card-grid {
  grid-template-columns: repeat(4, 1fr);
}
@media (max-width: 1100px) {
  #services .card-grid,
  #services-overview .card-grid { grid-template-columns: repeat(2, 1fr); }
}
@media (max-width: 620px) {
  #services .card-grid,
  #services-overview .card-grid { grid-template-columns: 1fr; }
}

.service-card {
  background: var(--color-bg);
  border: var(--border-width) solid var(--color-border);
  border-radius: var(--radius-md);
  padding: var(--space-6);
  transition: transform var(--transition-base), box-shadow var(--transition-base), border-color var(--transition-base);
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}
.service-card:hover {
  transform: translateY(-4px);
  box-shadow: var(--shadow-md);
  border-color: transparent;
}
.service-card__icon {
  width: 52px;
  height: 52px;
  border-radius: var(--radius-sm);
  background: var(--color-primary-tint);
  display: flex;
  align-items: center;
  justify-content: center;
}
.service-card__icon svg { width: 24px; height: 24px; color: var(--color-primary); }
.service-card h3 { margin-bottom: 0; }
.service-card p { font-size: var(--text-sm); }
.service-card__list {
  display: flex;
  flex-direction: column;
  gap: var(--space-2);
  font-size: var(--text-sm);
  color: var(--color-text-muted);
}
.service-card__list li { display: flex; gap: var(--space-2); align-items: flex-start; }
.service-card__list svg { width: 16px; height: 16px; color: var(--color-success); margin-top: 3px; flex-shrink: 0; }
.service-card__link {
  margin-top: auto;
  font-size: var(--text-sm);
  font-weight: 700;
  color: var(--color-primary);
  text-decoration: none;
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
}
.service-card__link svg { width: 16px; height: 16px; transition: transform var(--transition-fast); }
.service-card__link:hover svg { transform: translateX(3px); }

/* Full service page detail block */
.service-detail {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-8);
  align-items: start;
  padding-block: var(--space-9);
}
.service-detail:not(:last-child) { border-bottom: var(--border-width) solid var(--color-border); }
.service-detail__figure {
  aspect-ratio: 1 / 1;
  border-radius: var(--radius-lg);
  background: var(--color-primary-tint);
  display: flex;
  align-items: center;
  justify-content: center;
  position: relative;
  overflow: hidden;
}
.service-detail__figure svg { width: 40%; height: 40%; color: var(--color-primary); }
.service-detail__figure img { width: 100%; height: 100%; object-fit: cover; }
.service-detail__badge {
  position: absolute;
  top: var(--space-4);
  left: var(--space-4);
  background: var(--color-bg);
  border-radius: var(--radius-full);
  padding: var(--space-2) var(--space-4);
  font-size: var(--text-xs);
  font-weight: 700;
  color: var(--color-primary);
  box-shadow: var(--shadow-sm);
}
.service-detail__body ul {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  margin-block: var(--space-5);
  list-style: none;
  padding: 0;
}
.service-detail__body li {
  display: flex;
  gap: var(--space-3);
  align-items: flex-start;
  font-size: var(--text-sm);
  color: var(--color-text-muted);
}
.service-detail__body li svg { width: 20px; height: 20px; color: var(--color-success); margin-top: 2px; flex-shrink: 0; }

@media (max-width: 800px) {
  .service-detail { grid-template-columns: 1fr; }
  .service-detail__figure { order: -1; aspect-ratio: 16/9; }
}

/* ---------------------------------------------------------------------
   HOW IT WORKS — numbered steps, each its own hoverable card
   --------------------------------------------------------------------- */
.steps {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: var(--space-6);
  counter-reset: step;
}
.step {
  background: var(--color-bg);
  border: var(--border-width) solid var(--color-border);
  border-radius: var(--radius-md);
  padding: var(--space-6) var(--space-5);
  transition: transform var(--transition-base), box-shadow var(--transition-base), border-color var(--transition-base);
}
.step:hover {
  transform: translateY(-5px);
  box-shadow: var(--shadow-md);
  border-color: var(--color-accent);
}
.step::before {
  counter-increment: step;
  content: counter(step);
  width: 40px;
  height: 40px;
  border-radius: 50%;
  background: var(--color-primary);
  color: var(--color-accent);
  font-family: var(--font-display);
  font-size: var(--text-md);
  display: flex;
  align-items: center;
  justify-content: center;
  margin-bottom: var(--space-4);
  transition: transform var(--transition-base);
}
.step:hover::before { transform: scale(1.1) rotate(-6deg); }
.step h3 { margin-bottom: var(--space-2); font-size: var(--text-md); }
.step p { font-size: var(--text-sm); }

/* ---------------------------------------------------------------------
   REVIEWS
   --------------------------------------------------------------------- */
.review-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(280px, 1fr));
  gap: var(--space-6);
}
.review-card {
  background: var(--color-bg);
  border: var(--border-width) solid var(--color-border);
  border-radius: var(--radius-md);
  padding: var(--space-6);
  display: flex;
  flex-direction: column;
  gap: var(--space-4);
}
.review-card__meta { display: flex; align-items: center; justify-content: space-between; gap: var(--space-3); }
.review-card__stars { display: flex; gap: 2px; }
.review-card__stars svg { width: 16px; height: 16px; color: var(--color-star); }
/* Finding 13: attribution chip so a review card doesn't read as an
   unverifiable testimonial. Reuses .badge (already token-driven). */
.review-card__source { white-space: nowrap; }
.review-card__quote {
  font-size: var(--text-sm);
  color: var(--color-text);
  line-height: var(--leading-relaxed);
}
.review-card__author {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  margin-top: auto;
}
.review-card__avatar {
  width: 38px; height: 38px;
  border-radius: 50%;
  background: var(--color-primary-tint);
  color: var(--color-primary);
  display: flex;
  align-items: center;
  justify-content: center;
  font-family: var(--font-display);
  font-size: var(--text-sm);
  flex-shrink: 0;
}
.review-card__author strong { display: block; font-size: var(--text-sm); color: var(--color-primary); }
.review-card__author span { font-size: var(--text-xs); color: var(--color-text-faint); }

.rating-banner {
  display: flex;
  align-items: center;
  gap: var(--space-4);
  flex-wrap: wrap;
}
.rating-banner__score {
  font-family: var(--font-display);
  font-size: var(--text-3xl);
  color: var(--color-primary);
}
.rating-banner__stars svg { width: 20px; height: 20px; color: var(--color-star); }
.rating-banner__stars { display: flex; gap: 2px; margin-bottom: var(--space-1); }
.rating-banner__meta { font-size: var(--text-sm); color: var(--color-text-faint); }

/* ---------------------------------------------------------------------
   SERVICE AREA
   --------------------------------------------------------------------- */
.area-layout {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-8);
  align-items: center;
}
.area-map {
  aspect-ratio: 4/3;
  border-radius: var(--radius-lg);
  background: var(--color-primary-tint);
  position: relative;
  overflow: hidden;
  display: flex;
  align-items: center;
  justify-content: center;
}
.area-map svg { width: 78%; height: 78%; }
.area-map img { width: 100%; height: 100%; object-fit: cover; display: block; }
.city-tags {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
  margin-top: var(--space-5);
}
.city-tag {
  background: var(--color-bg-alt);
  border: var(--border-width) solid var(--color-border);
  border-radius: var(--radius-full);
  padding: var(--space-2) var(--space-4);
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--color-primary);
  display: inline-block;
  transition: transform var(--transition-fast), background var(--transition-fast), border-color var(--transition-fast), color var(--transition-fast), box-shadow var(--transition-fast);
}
.city-tag:hover {
  transform: translateY(-3px) scale(1.06);
  background: var(--color-accent);
  border-color: var(--color-accent);
  color: var(--color-primary-700);
  box-shadow: var(--shadow-sm);
}
@media (max-width: 800px) {
  .area-layout { grid-template-columns: 1fr; }
  .area-map { order: -1; }
}

/* ---------------------------------------------------------------------
   FAQ (native <details>, zero JS)
   --------------------------------------------------------------------- */
.faq-list {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  max-width: var(--container-narrow);
}
.faq-item {
  border: var(--border-width) solid var(--color-border);
  border-radius: var(--radius-md);
  padding: var(--space-2) var(--space-5);
  background: var(--color-bg);
}
.faq-item summary {
  cursor: pointer;
  list-style: none;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-4);
  padding-block: var(--space-4);
  font-weight: 600;
  color: var(--color-primary);
  font-size: var(--text-md);
}
.faq-item summary::-webkit-details-marker { display: none; }
/* Finding 17: the question needs real heading semantics for screen-reader
   users navigating by heading, without breaking <summary>'s native
   expand/collapse behavior or its flex layout. A display:contents h3
   inside <summary> is announced as a heading but generates no box of its
   own, so summary's flex row (text + the +/- indicator) lays out exactly
   as if the h3 wasn't there. The h1-h4 element rule earlier in this file
   sets its own font-weight/size/color directly on the h3 tag, which would
   otherwise win over the inherited summary styling below (inheritance
   loses to any same-element declaration) - forced back to inherit here
   so the visual result is unchanged. */
.faq-item summary h3 {
  display: contents;
  font-family: inherit;
  font-weight: inherit;
  font-size: inherit;
  line-height: inherit;
  color: inherit;
  letter-spacing: inherit;
}
.faq-item summary::after {
  /* Finding 16: was a "+" rotated 45deg into a diamond/x on open, not a
     real minus. Swap the glyph itself instead of rotating it. */
  content: '+';
  font-family: var(--font-display);
  font-size: var(--text-xl);
  color: var(--color-accent-ink);
  flex-shrink: 0;
}
.faq-item[open] summary::after { content: '\2212'; }
.faq-item p {
  padding-bottom: var(--space-5);
  font-size: var(--text-sm);
  line-height: var(--leading-relaxed);
}

/* ---------------------------------------------------------------------
   CTA BAND
   --------------------------------------------------------------------- */
/* The one bold solid-gold moment on the page - deliberately loud, framed by
   light sections on either side so it reads as a happy highlight, not noise. */
.cta-band {
  border-radius: var(--radius-lg);
  padding: var(--space-9);
  background: linear-gradient(155deg, var(--color-accent) 0%, var(--color-accent-600) 100%);
  color: var(--color-primary-700);
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-6);
  position: relative;
  overflow: hidden;
}
.cta-band::before {
  content: '';
  position: absolute;
  inset: 0;
  background: radial-gradient(circle at 85% 20%, rgba(15,15,13,0.08), transparent 45%);
}
.cta-band__text { position: relative; max-width: 480px; }
.cta-band h2 { color: var(--color-primary-700); margin-bottom: var(--space-3); }
.cta-band p { color: var(--color-primary-700); opacity: 0.8; }
.cta-band__actions { position: relative; display: flex; gap: var(--space-4); flex-wrap: wrap; }

/* ---------------------------------------------------------------------
   FOOTER
   --------------------------------------------------------------------- */
.site-footer {
  background: var(--color-primary-700);
  color: var(--color-text-inverse-muted);
  padding-block: var(--space-9) var(--space-6);
  --color-focus: var(--color-accent);
}
.footer-grid {
  display: grid;
  grid-template-columns: 1.4fr 1fr 1fr 1fr;
  gap: var(--space-7);
  padding-bottom: var(--space-8);
  border-bottom: var(--border-width) solid var(--color-border-dark);
}
.footer-brand .brand__name,
.footer-brand .brand__tagline { color: var(--color-text-inverse); }
.footer-brand .brand__tagline { color: var(--color-text-inverse-muted); }
.footer-brand p { margin-top: var(--space-4); font-size: var(--text-sm); max-width: 32ch; color: var(--color-text-inverse-muted); }
/* Finding 10: was <h4>, which skipped a level (every page's last heading
   before the footer is an h2 CTA band). Markup changed h4 -> h3 to close
   the gap; selector follows, visual size/weight/case unchanged. */
.footer-col h3 {
  color: var(--color-text-inverse);
  font-family: var(--font-body);
  font-size: var(--text-xs);
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  margin-bottom: var(--space-4);
}
.footer-col ul { display: flex; flex-direction: column; gap: var(--space-3); list-style: none; margin: 0; padding: 0; }
.footer-col a {
  font-size: var(--text-sm);
  text-decoration: none;
  color: var(--color-text-inverse-muted);
  transition: color var(--transition-fast);
}
.footer-col a:hover { color: var(--color-accent); }
.footer-bottom {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-between;
  gap: var(--space-4);
  padding-top: var(--space-6);
  font-size: var(--text-xs);
}
.footer-bottom a { color: var(--color-text-inverse-muted); text-decoration: underline; }

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

/* ---------------------------------------------------------------------
   FORMS (quote / contact)
   --------------------------------------------------------------------- */
.form-card {
  background: var(--color-bg);
  border: var(--border-width) solid var(--color-border);
  border-radius: var(--radius-lg);
  padding: var(--space-7);
  box-shadow: var(--shadow-md);
}
.form-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-5);
}
.form-field { display: flex; flex-direction: column; gap: var(--space-2); }
.form-field--full { grid-column: 1 / -1; }
.form-field label {
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--color-primary);
}
.form-field .hint { font-size: var(--text-xs); color: var(--color-text-faint); }
/* Finding 6: asterisk marker for required fields + the "* required"
   legend at the top of each form. aria-hidden because the native
   `required` attribute already carries the semantics for AT; this is a
   sighted-user visual cue only. */
.required-mark { color: var(--color-danger); font-weight: 700; }
.form-required-legend {
  font-size: var(--text-sm);
  color: var(--color-text-faint);
  margin-bottom: var(--space-5);
}
.form-field input[type="text"],
.form-field input[type="tel"],
.form-field input[type="email"],
.form-field input[type="date"],
.form-field input[type="time"],
.form-field select,
.form-field textarea {
  border: var(--border-width) solid var(--color-border);
  border-radius: var(--radius-sm);
  padding: var(--space-3) var(--space-4);
  font-size: var(--text-base);
  background: var(--color-bg);
  color: var(--color-text);
  transition: border-color var(--transition-fast), box-shadow var(--transition-fast);
  width: 100%;
}
.form-field input:focus,
.form-field select:focus,
.form-field textarea:focus {
  outline: none;
  border-color: var(--color-accent-ink);
  box-shadow: 0 0 0 3px var(--color-accent-tint);
}
.form-field textarea { resize: vertical; min-height: 100px; }

/* Finding 1: invalid-state styling, visually distinct from the normal
   accent focus ring above (danger red instead of accent terracotta), so
   a field that's both focused and invalid still reads as "wrong", not
   just "focused". Driven off aria-invalid, which form-handler.js sets/
   clears on submit and on live re-validation after a fix. */
.form-field input[aria-invalid="true"],
.form-field select[aria-invalid="true"],
.form-field textarea[aria-invalid="true"] {
  border-color: var(--color-danger);
}
.form-field input[aria-invalid="true"]:focus,
.form-field select[aria-invalid="true"]:focus,
.form-field textarea[aria-invalid="true"]:focus {
  border-color: var(--color-danger);
  box-shadow: 0 0 0 3px var(--color-danger-tint);
}
.radio-group[aria-invalid="true"] .radio-option span {
  border-color: var(--color-danger);
}
.field-error {
  display: none;
  font-size: var(--text-sm);
  color: var(--color-danger);
  font-weight: 600;
}
.field-error:not(:empty) { display: block; }

.form-error-summary {
  border: var(--border-width) solid var(--color-danger);
  background: var(--color-danger-tint);
  color: var(--color-danger);
  border-radius: var(--radius-sm);
  padding: var(--space-4) var(--space-5);
  margin-bottom: var(--space-5);
}
.form-error-summary[hidden] { display: none; }
.form-error-summary h3 {
  color: var(--color-danger);
  font-size: var(--text-md);
  margin-bottom: var(--space-2);
}
.form-error-summary ul { display: flex; flex-direction: column; gap: var(--space-1); }
.form-error-summary a {
  color: var(--color-danger);
  font-size: var(--text-sm);
  font-weight: 600;
  text-decoration: underline;
}
/* Focusable without a visible browser outline mismatch - still gets the
   standard :focus-visible ring from earlier in this file since it's a
   real element in the tab order via tabindex="-1" + .focus(). */
.form-error-summary:focus { outline: 2px solid var(--color-focus); outline-offset: 2px; }

.radio-group, .checkbox-row {
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-3);
}
.radio-option {
  flex: 1 1 140px;
  position: relative;
}
.radio-option input {
  position: absolute;
  opacity: 0;
  inset: 0;
  width: 100%;
  height: 100%;
  cursor: pointer;
}
.radio-option span {
  display: flex;
  align-items: center;
  justify-content: center;
  text-align: center;
  border: var(--border-width) solid var(--color-border);
  border-radius: var(--radius-sm);
  padding: var(--space-3);
  font-size: var(--text-sm);
  font-weight: 600;
  color: var(--color-text-muted);
  transition: all var(--transition-fast);
  height: 100%;
}
.radio-option input:checked + span {
  border-color: var(--color-accent-ink);
  background: var(--color-accent-tint);
  color: var(--color-primary);
}
.radio-option input:focus-visible + span {
  outline: 2px solid var(--color-focus);
  outline-offset: 2px;
}

.consent-row {
  display: flex;
  align-items: flex-start;
  gap: var(--space-3);
}
/* Finding 8: SMS consent legal text and tap target were both undersized
   for a 60+ audience. Checkbox itself is 22px now (was 18px); .consent-
   row__hit wraps it in an invisible 44px tap box (negative margin pulls
   the extra box back out of the layout so it doesn't push the label over
   or add visual whitespace) so the actual touch target meets the 44px
   minimum even though the visible checkbox stays a normal 22px size.
   Clicking the label text still toggles it too (native <label for>
   behavior), which is the other half of a comfortably tappable row. */
.consent-row__hit {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  width: 44px;
  height: 44px;
  margin: -11px -11px -11px 0;
  flex-shrink: 0;
}
.consent-row input { width: 22px; height: 22px; accent-color: var(--color-accent); flex-shrink: 0; }
.consent-row label { font-size: var(--text-sm); color: var(--color-text-faint); line-height: var(--leading-normal); padding-top: var(--space-1); }

.form-status {
  border-radius: var(--radius-sm);
  padding: var(--space-4) var(--space-5);
  font-size: var(--text-sm);
  margin-top: var(--space-5);
  display: none;
}
.form-status.is-visible { display: block; }
.form-status--success { background: var(--color-success-tint); color: var(--color-success); }
.form-status--error { background: var(--color-danger-tint); color: var(--color-danger); }

.form-fallback {
  margin-top: var(--space-5);
  padding-top: var(--space-5);
  border-top: var(--border-width) solid var(--color-border);
  font-size: var(--text-sm);
  color: var(--color-text-faint);
  display: none;
}
.form-fallback.is-visible { display: block; }
.form-fallback a { color: var(--color-primary); font-weight: 700; text-decoration: none; }

.form-side {
  display: flex;
  flex-direction: column;
  gap: var(--space-5);
}
.info-card {
  background: var(--color-bg-alt);
  border-radius: var(--radius-md);
  padding: var(--space-6);
  display: flex;
  gap: var(--space-4);
  align-items: flex-start;
}
.info-card svg { width: 24px; height: 24px; color: var(--color-accent-ink); flex-shrink: 0; margin-top: 2px; }
.info-card h3 { font-size: var(--text-md); margin-bottom: var(--space-1); }
.info-card p { font-size: var(--text-sm); margin: 0; }

.quote-layout {
  display: grid;
  grid-template-columns: 1.4fr 1fr;
  gap: var(--space-8);
  align-items: start;
}
@media (max-width: 900px) {
  .quote-layout { grid-template-columns: 1fr; }
  .form-grid { grid-template-columns: 1fr; }
  .area-layout, .service-detail { grid-template-columns: 1fr; }
}

/* ---------------------------------------------------------------------
   PAGE HEADER (interior pages)
   --------------------------------------------------------------------- */
.page-header {
  padding-block: var(--space-9) var(--space-8);
  background: linear-gradient(160deg, var(--color-bg) 0%, var(--color-accent-tint) 100%);
  color: var(--color-text);
  border-bottom: var(--border-width) solid var(--color-border);
  position: relative;
  overflow: hidden;
}
.page-header::before {
  content: '';
  position: absolute;
  inset: 0;
  background-image: radial-gradient(circle at 90% 10%, rgba(201,162,39,0.14), transparent 45%);
}
.page-header__inner { position: relative; max-width: 720px; }
.breadcrumb {
  display: flex;
  gap: var(--space-2);
  font-size: var(--text-xs);
  color: var(--color-text-faint);
  margin-bottom: var(--space-4);
  text-transform: uppercase;
  letter-spacing: 0.05em;
}
.breadcrumb a { color: var(--color-text-faint); text-decoration: none; }
.breadcrumb a:hover { color: var(--color-accent-ink); }
/* Finding 5: interior h1s inherit the same --text-4xl size as the homepage
   hero h1, which is oversized on a 375px page header with no room to
   spare. clamp() scales it down smoothly instead of a hard breakpoint
   jump; floor is --text-2xl (matches h2 size, still reads as a page
   title), ceiling is the original --text-4xl on desktop. */
.page-header h1 {
  color: var(--color-primary);
  font-size: clamp(var(--text-2xl), 5vw + 1rem, var(--text-4xl));
  margin-bottom: var(--space-4);
}
.page-header p { color: var(--color-text-muted); font-size: var(--text-md); max-width: 60ch; }

/* ---------------------------------------------------------------------
   ABOUT PAGE EXTRAS
   --------------------------------------------------------------------- */
.value-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  gap: var(--space-6);
}
.value-item {
  display: flex;
  flex-direction: column;
  gap: var(--space-3);
  background: var(--color-bg);
  border: var(--border-width) solid var(--color-border);
  border-radius: var(--radius-md);
  padding: var(--space-6);
  transition: transform var(--transition-base), box-shadow var(--transition-base), border-color var(--transition-base);
}
.value-item:hover {
  transform: translateY(-5px);
  box-shadow: var(--shadow-md);
  border-color: var(--color-accent);
}
.value-item svg {
  width: 26px;
  height: 26px;
  color: var(--color-primary);
  transition: transform var(--transition-base);
}
.value-item:hover svg { transform: scale(1.15) rotate(-6deg); }
.value-item h3 { font-size: var(--text-md); }
.value-item p { font-size: var(--text-sm); }

.stat-row {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(160px, 1fr));
  gap: var(--space-5);
  text-align: center;
}
.stat-item {
  background: var(--color-bg);
  border: var(--border-width) solid var(--color-border);
  border-radius: var(--radius-md);
  padding: var(--space-5) var(--space-4);
  transition: transform var(--transition-base), box-shadow var(--transition-base), border-color var(--transition-base);
}
.stat-item:hover {
  transform: translateY(-4px);
  box-shadow: var(--shadow-md);
  border-color: var(--color-accent);
}
.stat-item strong {
  display: block;
  font-family: var(--font-display);
  font-size: var(--text-2xl);
  color: var(--color-primary);
}
.stat-item span { font-size: var(--text-xs); color: var(--color-text-faint); text-transform: uppercase; letter-spacing: 0.05em; }

.team-grid {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(240px, 1fr));
  gap: var(--space-6);
}
.team-card { text-align: center; }
/* Sized generously for real staff photos once supplied - see BUILD-NOTES
   chase list. Renders as a bordered circle placeholder until then. */
.team-card__photo {
  aspect-ratio: 1/1;
  border-radius: 50%;
  background: var(--color-primary-tint);
  border: 3px solid var(--color-bg-alt);
  box-shadow: var(--shadow-sm);
  display: flex;
  align-items: center;
  justify-content: center;
  margin: 0 auto var(--space-4);
  width: 220px;
  overflow: hidden;
}
@media (max-width: 480px) {
  .team-card__photo { width: 170px; }
}
.team-card__photo svg { width: 46%; height: 46%; color: var(--color-primary); }
.team-card__photo img { width: 100%; height: 100%; object-fit: cover; }
.team-card h3 { font-size: var(--text-md); margin-bottom: var(--space-1); }
.team-card span { font-size: var(--text-xs); color: var(--color-accent-ink); font-weight: 700; text-transform: uppercase; letter-spacing: 0.04em; }

/* ---------------------------------------------------------------------
   CONTACT PAGE EXTRAS
   --------------------------------------------------------------------- */
.contact-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-8);
}
.contact-methods { display: flex; flex-direction: column; gap: var(--space-4); }
.hours-table { width: 100%; border-collapse: collapse; font-size: var(--text-sm); }
.hours-table td { padding: var(--space-2) 0; border-bottom: var(--border-width) solid var(--color-border); }
.hours-table td:last-child { text-align: right; font-weight: 600; color: var(--color-primary); }

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

/* ---------------------------------------------------------------------
   MOBILE CALL BAR (finding 12) — fixed bottom bar, phones/small tablets
   only. Present on every page except quote.html (the form itself is
   already the primary action there, a second competing CTA bar would
   fight it). Pages that include the markup also set
   <body class="has-mobile-call-bar">, which is what reserves the bottom
   padding below - quote.html has neither the bar nor the class, so it
   never gets padding it doesn't need.
   --------------------------------------------------------------------- */
.mobile-call-bar { display: none; }
@media (max-width: 768px) {
  .has-mobile-call-bar { padding-bottom: calc(78px + env(safe-area-inset-bottom)); }
  .mobile-call-bar {
    display: flex;
    position: fixed;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 150;
    gap: var(--space-3);
    background: var(--color-bg);
    border-top: var(--border-width) solid var(--color-border);
    box-shadow: var(--shadow-lg);
    padding: var(--space-3) var(--space-4);
    padding-bottom: calc(var(--space-3) + env(safe-area-inset-bottom));
  }
  .mobile-call-bar__call,
  .mobile-call-bar__quote {
    flex: 1 1 50%;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: var(--space-2);
    min-height: 44px;
    border-radius: var(--radius-full);
    font-weight: 700;
    font-size: var(--text-sm);
    text-decoration: none;
  }
  .mobile-call-bar__call {
    border: var(--border-width) solid var(--color-border);
    color: var(--color-primary);
  }
  .mobile-call-bar__call svg { width: 20px; height: 20px; color: var(--color-accent-ink); flex-shrink: 0; }
}

/* ---------------------------------------------------------------------
   MAP EMBED SLOT (finding 14) — contact.html optional Google Maps iframe.
   Demo has no real Google Business Profile, so it keeps the decorative
   CSS/SVG placeholder treatment (matches .area-map's look).
   --------------------------------------------------------------------- */
.map-embed { border-radius: var(--radius-lg); overflow: hidden; margin-top: var(--space-7); }
.map-embed iframe { display: block; width: 100%; border: 0; }
.map-embed img { display: block; width: 100%; aspect-ratio: 16 / 10; object-fit: cover; }
.map-embed--placeholder {
  aspect-ratio: 16 / 9;
  background: var(--color-primary-tint);
  display: flex;
  align-items: center;
  justify-content: center;
}
.map-embed--placeholder svg { width: 55%; height: 55%; }

/* ---------------------------------------------------------------------
   UTILS
   --------------------------------------------------------------------- */
.mt-0 { margin-top: 0; }
.text-center { text-align: center; }
.badge {
  display: inline-flex;
  align-items: center;
  gap: var(--space-2);
  background: var(--color-accent-tint);
  color: var(--color-accent-ink);
  border-radius: var(--radius-full);
  padding: var(--space-1) var(--space-3);
  font-size: var(--text-xs);
  font-weight: 700;
}

/* ---------------------------------------------------------------------
   MOTION PASS (7/19) — entrances, scroll reveals, idle loop.
   Three hard gates, all honored here:
   1. Everything below that HIDES content is scoped under html.js-motion,
      a class stamped by the first statement of site.js. No JS (or JS
      failure) means no class, and the site renders fully visible,
      identical to the pre-motion build.
   2. prefers-reduced-motion: the global block at the top of this file
      zeroes every animation/transition, site.js additionally never
      stamps js-motion (and removes it live if the preference flips),
      and the explicit reduce block at the bottom of this section
      force-shows everything. Triple-gated.
   3. opacity/transform only — nothing here triggers layout or paint.
   Tuning knobs live in tokens.css: --motion-duration (0ms kills it),
   --motion-ease, --motion-stagger (the taste knob).
   --------------------------------------------------------------------- */

@keyframes motion-rise {
  from { opacity: 0; transform: translateY(var(--_rise, 16px)); }
  to   { opacity: 1; transform: none; }
}
@keyframes motion-pop {
  from { opacity: 0; transform: scale(0.96); }
  to   { opacity: 1; transform: none; }
}
@keyframes motion-orbit {
  to { transform: rotate(360deg); }
}

/* Hero entrance choreography (index.html only — these classes exist
   nowhere else). Beats ~90ms apart: eyebrow badge, headline (longer
   24px rise), lede, CTAs, stats, then the illustration panel scaling
   in from 0.96 as its own closing moment. */
html.js-motion .hero__eyebrow,
html.js-motion .hero h1,
html.js-motion .hero__lede,
html.js-motion .hero__actions,
html.js-motion .hero__stats {
  animation: motion-rise var(--motion-duration) var(--motion-ease) both;
}
html.js-motion .hero__eyebrow { animation-delay: 0ms; }
html.js-motion .hero h1 {
  --_rise: 24px;
  animation-duration: calc(var(--motion-duration) + 150ms);
  animation-delay: var(--motion-stagger);
}
html.js-motion .hero__lede    { animation-delay: calc(var(--motion-stagger) * 2); }
html.js-motion .hero__actions { animation-delay: calc(var(--motion-stagger) * 3); }
html.js-motion .hero__stats   { animation-delay: calc(var(--motion-stagger) * 4); }
html.js-motion .hero__visual {
  animation: motion-pop calc(var(--motion-duration) + 200ms) var(--motion-ease) both;
  animation-delay: calc(var(--motion-stagger) * 5);
}

/* Idle loop: the dashed orbit ring in the hero illustration drifts one
   full revolution per minute — barely perceptible, gives the panel a
   pulse. Not gated on js-motion (it hides nothing); the global
   reduced-motion block already kills it. */
.hero__visual > svg > circle:first-of-type {
  transform-box: fill-box;
  transform-origin: center;
  animation: motion-orbit 60s linear infinite;
}

/* Scroll reveals: site.js stamps data-reveal + a per-sibling
   --reveal-index on section heads, service details, review/team cards,
   and FAQ items, then flips is-revealed via IntersectionObserver (once,
   then unobserves — reveals never re-fire on scroll-up). The hidden
   state only exists when BOTH js-motion and data-reveal are present,
   and both are JS-stamped, so a no-JS render never hides a thing. */
html.js-motion [data-reveal] {
  opacity: 0;
  transform: translateY(16px);
}
html.js-motion [data-reveal].is-revealed {
  opacity: 1;
  transform: none;
  transition:
    opacity calc(var(--motion-duration) - 50ms) var(--motion-ease),
    transform calc(var(--motion-duration) - 50ms) var(--motion-ease);
  transition-delay: calc(var(--reveal-index, 0) * var(--motion-stagger));
}

/* Quieter micro-lift on content cards (service cards already lift). */
.review-card, .team-card {
  transition: transform var(--transition-base), box-shadow var(--transition-base);
}
.review-card:hover, .team-card:hover {
  transform: translateY(-2px);
  box-shadow: var(--shadow-md);
}

@media (prefers-reduced-motion: reduce) {
  html.js-motion .hero__eyebrow,
  html.js-motion .hero h1,
  html.js-motion .hero__lede,
  html.js-motion .hero__actions,
  html.js-motion .hero__stats,
  html.js-motion .hero__visual,
  html.js-motion [data-reveal] {
    animation: none;
    transition: none;
    opacity: 1;
    transform: none;
  }
  .hero__visual > svg > circle:first-of-type { animation: none; }
}

/* Payment methods band (Site2Site custom, homepage #why-us) */
.payment-band {
  margin-top: var(--space-8);
  padding-top: var(--space-6);
  border-top: var(--border-width) solid var(--color-border);
  text-align: center;
}
.payment-band__label {
  font-size: var(--text-sm);
  color: var(--color-text-muted);
  font-weight: 600;
  margin-bottom: var(--space-4);
}
.payment-band__tags { justify-content: center; }

/* ---------------------------------------------------------------------
   ANNOUNCEMENT BAR (homepage relaunch notice, added 2026-09-18)
--------------------------------------------------------------------- */
.announce-bar {
  background: var(--color-primary);
  color: var(--color-text-inverse-muted);
  font-size: var(--text-sm);
  text-align: center;
  padding: var(--space-2) var(--space-4);
}
.announce-bar strong { color: var(--color-accent); }

/* ---------------------------------------------------------------------
   LEGAL PROSE (terms/privacy) - section rhythm between h2 blocks,
   added 2026-09-18 after Ray flagged the cramped spacing
--------------------------------------------------------------------- */
.legal-prose h2 { margin-top: var(--space-8); }

/* Service-page content photo (first used on services-discharge) */
.service-photo { margin: 0 0 var(--space-7); border-radius: var(--radius-lg); overflow: hidden; box-shadow: var(--shadow-md); }
.service-photo img { display: block; width: 100%; aspect-ratio: 16 / 9; object-fit: cover; }
