/* ============================================================================
   Family RV Inspection & Mobile Repair
   EXACT_MIGRATION rebuild. Structure and spacing follow the Duda source's
   measured computed styles; the improvements are semantic, accessible and
   performance-related, not visual.
   ========================================================================= */

@import url("tokens.css");

/* --- Fonts: self-hosted, subset, variable ---------------------------------
   The source shipped a 609 KB .otf for the display face and pulled Inter and
   Montserrat from Google. All three are now local woff2. Inter and Montserrat
   are variable (wght 100-900), so one file each covers every weight in use. */
@font-face {
  font-family: "RetroDream-Lines";
  src: url("../fonts/RetroDream-Lines-400.woff2") format("woff2");
  font-weight: 400;
  font-display: swap;
}
@font-face {
  font-family: "Inter";
  src: url("../fonts/Inter-variable-latin.woff2") format("woff2-variations");
  font-weight: 100 900;
  font-display: swap;
}
@font-face {
  font-family: "Montserrat";
  src: url("../fonts/Montserrat-variable-latin.woff2") format("woff2-variations");
  font-weight: 100 900;
  font-display: swap;
}

/* --- Reset ---------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }
html { -webkit-text-size-adjust: 100%; scroll-behavior: smooth; }
@media (prefers-reduced-motion: reduce) { html { scroll-behavior: auto; } }

body {
  margin: 0;
  /* Paper texture is the page surface the masthead card sits on. */
  background-color: var(--color-bg);
  background-image: url("../img/white-textured-paper-background-subtle-detail-ab-2026-01-08-02-37-28-utc-3637h.webp");
  background-size: 900px auto;
  background-repeat: repeat;
  color: var(--color-text);
  font-family: var(--font-body);
  font-size: var(--fs-body);
  line-height: var(--lh-body);
  -webkit-font-smoothing: antialiased;
}

img, picture, video { max-width: 100%; height: auto; display: block; }
svg { display: block; }

h1, h2, h3, h4 {
  font-family: var(--font-display);
  font-weight: var(--fw-regular);
  margin: 0 0 var(--space-4);
  text-wrap: balance;
}
p { margin: 0 0 var(--space-4); }
p:last-child { margin-bottom: 0; }

a { color: var(--color-accent); }
a:focus-visible,
button:focus-visible,
input:focus-visible,
select:focus-visible,
textarea:focus-visible,
summary:focus-visible {
  outline: 3px solid var(--color-accent);
  outline-offset: 2px;
  border-radius: var(--radius-sm);
}

/* Skip link. Hidden by clipping rather than by left:-9999px: an off-screen box
   escapes its parent's bounds, and the masthead card clips to rounded corners
   with overflow:hidden. On focus it becomes fixed so overflow cannot hide it. */
.skip-link {
  position: absolute;
  width: 1px;
  height: 1px;
  overflow: hidden;
  clip-path: inset(50%);
  white-space: nowrap;
  background: var(--navy);
  color: var(--cream);
  text-decoration: none;
  font-weight: var(--fw-semibold);
}
.skip-link:focus {
  position: fixed;
  top: 0;
  left: 0;
  z-index: 100;
  width: auto;
  height: auto;
  clip-path: none;
  padding: var(--space-3) var(--space-5);
  border-radius: 0 0 var(--radius-sm) 0;
}

/* --- 4.1b Container discipline -------------------------------------------
   Backgrounds go full-bleed, content stays constrained, every section shares
   one .inner. No section sets its own max-width. */
/* SITE LAYOUT RULE — see tokens.css. Every section is a rounded card inset
   from the page edge, separated from the one above by the same 20px. */
.section {
  margin-inline: var(--edge);
  margin-bottom: var(--edge);
  border-radius: var(--radius-lg);
  overflow: hidden;
  padding-inline: var(--gutter);
  padding-block: var(--section-py);
}
body > .section:first-of-type, .masthead, .row-group:first-of-type { margin-top: var(--edge); }

/* Some cards hold more than one row. Measured from the source radii: the
   masthead is hero+trust, "Our Services" is intro+cards, and the footer is
   footer+copyright — each a single rounded card with 0 gap inside it and the
   full 20px gap outside. The group owns the inset; its rows reset. */
.row-group {
  margin-inline: var(--edge);
  margin-bottom: var(--edge);
  border-radius: var(--radius-lg);
  overflow: hidden;
}
.row-group > .section {
  margin: 0;
  border-radius: 0;
  overflow: visible;
  /* Rows inside one card share its rhythm — full section padding on both sides
     of every join doubled the gap and read as separate cards with no border. */
  padding-block: var(--space-10);
}
.row-group > .section:first-child { padding-top: var(--section-py); }
.row-group > .section:last-child  { padding-bottom: var(--section-py); }
.row-group > .section--flush { padding-block: 0; }
.section > .inner { max-width: var(--container); margin-inline: auto; }
.section--wide > .inner { max-width: var(--container-wide); }
.section--bleed { padding-inline: 0; }
.section--bleed > .inner { padding-inline: var(--gutter); }
.section--flush { padding-block: 0; }
.prose { max-width: var(--measure); }

/* --- Surfaces ------------------------------------------------------------- */
.surface-brand { background: var(--color-surface-brand); color: var(--color-text-invert); }
.surface-alt   { background: var(--color-surface-alt);   color: var(--color-text-invert); }
/* The source's page surface is a subtle paper texture over the warm off-white,
   not a flat fill. Dropping it was the "texture is the brand" failure. */
.surface-page { background: var(--color-bg); color: var(--color-text); }
.surface-white { background: var(--color-bg-alt);        color: var(--color-text); }
.surface-brand h1, .surface-brand h2, .surface-brand h3,
.surface-alt h1, .surface-alt h2, .surface-alt h3 { color: var(--color-text-invert); }
.surface-brand a, .surface-alt a { color: var(--cream); }

/* --- Masthead card -------------------------------------------------------
   The source wraps header + hero + trust bar in ONE rounded card, inset 20px
   from the viewport, on the paper-texture page background. Measured live:
   hero x=20 w=1240 of 1280, border-radius 30px 30px 0 0. The header is
   transparent and overlays the hero media — it is not a navy bar. */
/* Inner pages run a shorter hero than home: measured 402-490 against home's
   681, because home carries the video and a four-line headline. */
.masthead--compact { --hero-pt: clamp(4.5rem, 9vw, 8rem); --hero-pb: clamp(1.5rem, 3.5vw, 3rem); }
/* City heroes crop low — the subject sits in the lower half of those photos,
   the opposite of the service-page images. */
.masthead--low { --hero-pos: 50% 78%; }
/* Service pages run a shorter photo band than home: measured 250 vs 357. */
.photo-section--short { --strip-h: 250px; }
.masthead {
  margin: var(--edge) var(--edge) var(--edge);
  border-radius: var(--radius-lg);
  overflow: hidden;
  position: relative;
  isolation: isolate;
  background-color: var(--navy);
  background-image: var(--hero-img, none);
  background-size: cover;
  /* The source anchors near the top (50% -42.57px on a 402px hero). Centring a
     tall photo in a short hero lands on the bottom of the frame — the ground
     rather than the subject. 25% shows the middle-upper band. */
  background-position: var(--hero-pos, 50% 25%);
}
.masthead::before {                    /* keeps cream type legible on any frame */
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(180deg, rgba(0,0,0,.45) 0%, rgba(0,0,0,.30) 45%, rgba(0,0,0,.45) 100%);
  z-index: 0;
}
/* Stack the card's own sections above the gradient overlay. Named explicitly:
   a blanket `.masthead > *` also caught the skip link (pushing the hero down
   30px), and once :not() raised its specificity it beat .masthead__video and
   dropped an 833px video into the flow. */
.masthead > .hero,
.masthead > .trust-bar {
  position: relative;
  z-index: 1;
  margin: 0;                 /* the card owns the inset, not its children */
  border-radius: 0;
  overflow: visible;
}
.masthead__video {
  position: absolute; inset: 0; z-index: -1;
  width: 100%; height: 100%; object-fit: cover; display: block;
}

/* --- Header (transparent, over the masthead) ------------------------------
   Measured live: the header row and the hero row BOTH start at y=0 — the
   header is layered on the hero, not stacked above it. Stacking pushed the
   hero down 134px and made the card 65px too tall. */
.site-header {
  color: var(--cream);
  padding-inline: var(--space-5);
  position: absolute;
  inset: 0 0 auto 0;
  z-index: 2;
}
.site-header__inner {
  /* Shares the hero's container so the logo aligns with the headline at every
     width, not just at 1280. */
  max-width: var(--container);
  margin-inline: auto;
  padding: var(--space-5) 0 0;
  display: flex;
  align-items: flex-start;
  justify-content: space-between;
  gap: var(--space-6);
}
.site-header__logo img { width: auto; height: 62px; }
.site-header__right { display: flex; flex-direction: column; align-items: flex-end; gap: var(--space-2); }
.site-header__utility {
  margin: 0;
  font-size: var(--fs-body-sm);
  font-weight: var(--fw-semibold);
  display: flex; gap: var(--space-3); align-items: center;
}
.site-header__utility a { color: var(--cream); text-decoration: none; }
.site-header__utility a:hover { text-decoration: underline; }

.site-nav ul { list-style: none; margin: 0; padding: 0; display: flex; align-items: center; gap: var(--space-6); }
.site-nav a {
  color: var(--cream);
  text-decoration: none;
  font-family: var(--font-body);
  font-size: var(--fs-nav);
  font-weight: var(--fw-semibold);
  letter-spacing: var(--ls-nav);
  text-transform: uppercase;
  padding-block: var(--space-2);
  border-bottom: 2px solid transparent;
}
.site-nav a:hover,
.site-nav a[aria-current="page"] { border-bottom-color: var(--rust); }

.nav-toggle {
  display: none;
  background: none;
  border: 2px solid var(--cream);
  border-radius: var(--radius-sm);
  color: var(--cream);
  font: inherit;
  padding: var(--space-2) var(--space-3);
  cursor: pointer;
  align-items: center;
  gap: var(--space-2);
}
.nav-toggle__bars { display: inline-block; width: 20px; height: 2px; background: currentColor; position: relative; }
.nav-toggle__bars::before,
.nav-toggle__bars::after { content: ""; position: absolute; left: 0; width: 20px; height: 2px; background: currentColor; }
.nav-toggle__bars::before { top: -6px; }
.nav-toggle__bars::after { top: 6px; }

/* --- Buttons -------------------------------------------------------------- */
.btn {
  display: inline-block;
  font-family: var(--font-body);
  font-size: var(--fs-body);
  line-height: var(--lh-normal);
  font-weight: var(--fw-semibold);
  padding: var(--space-3) var(--space-8);
  border-radius: var(--radius-pill);
  border: var(--border-width) solid transparent;
  text-decoration: none;
  cursor: pointer;
  transition: background var(--duration-base) var(--ease-out),
              color var(--duration-base) var(--ease-out),
              border-color var(--duration-base) var(--ease-out);
}
.btn--primary { background: var(--rust); color: var(--cream); border-color: var(--rust); }
.btn--sm { padding: var(--space-2) var(--space-5); font-size: var(--fs-body-sm); }
.btn--primary:hover { background: transparent; color: var(--rust); }
.surface-brand .btn--primary:hover, .surface-alt .btn--primary:hover { color: var(--cream); border-color: var(--cream); }
.btn--ghost { background: transparent; color: var(--cream); border-color: var(--cream); }
.btn--ghost:hover { background: var(--cream); color: var(--navy); }
.btn--dark { background: var(--navy); color: var(--cream); border-color: var(--navy); }
.btn--dark:hover { background: transparent; color: var(--navy); }


/* --- Hero (inside the masthead) ------------------------------------------
   Left-aligned, not centred. The eyebrow is two tracked lines; the display
   line is the large RetroDream headline. One rust pill CTA, not two buttons. */
.hero { color: var(--cream); padding-inline: var(--space-5); }
.hero > .inner {
  /* Content is centred in the 1200 container, NOT padded from the card edge.
     At 1280 those coincide (both give x=40), which is why a 1280-only check
     could not tell them apart. At 1556 the source puts content at x=178 —
     exactly (1556-1200)/2 — so the container is what governs. */
  max-width: var(--container);
  margin-inline: auto;
  /* Measured: hero 681 tall, eyebrow top at 217. The top pad clears the
     overlaid header; the bottom pad brings the row to its measured height. */
  padding-block: var(--hero-pt, clamp(6rem, 14vw, 13.56rem)) var(--hero-pb, clamp(2.2rem, 7.2vw, 6.9rem));
  text-align: left;
}
.hero h1 { color: var(--cream); margin-bottom: var(--space-5); }
.hero__eyebrow {
  display: block;
  /* Stated rather than inherited: on the blog post this is a <p>, not a
     heading, so it does not pick up the h1-h4 display-face rule. */
  font-family: var(--font-display);
  font-size: clamp(0.875rem, 1.4vw, var(--fs-eyebrow));
  font-weight: var(--fw-bold);
  letter-spacing: var(--ls-eyebrow);
  text-transform: uppercase;
  line-height: 1.2;      /* measured: eyebrow->headline gap is 59px */
  margin-bottom: var(--space-4);
}
.hero__headline {
  display: block;
  max-width: 705px;              /* measured live */
  font-size: clamp(1.9rem, 4.2vw, var(--fs-display));
  line-height: 1;                /* measured: 52px/52px */
  text-transform: uppercase;
  margin-bottom: 0;
}
.hero__sub { max-width: 46ch; margin-bottom: 0; }
.hero__actions { display: flex; flex-wrap: wrap; gap: var(--space-4); margin-top: var(--space-8); }

/* --- Trust bar ------------------------------------------------------------ */
/* Needs to outrank `.section`'s gutter, which otherwise squeezes the band to
   1360 while the photo band sits at 1400 — reading as a third container. */
.trust-bar.section { padding-inline: var(--space-5); }
.trust-bar {
  background: var(--navy);
  color: var(--cream);
  padding: 1.75rem var(--space-5);   /* measured: 78px tall for one 22px line */
}
/* The source's trust band is 1382px wide at weight 400 — deliberately wider
   than the 1200 body container, which is how it stays on one line. That is
   exactly what --container-wide is for, so this stays within the two permitted
   widths rather than introducing a third. */
.trust-bar .inner { max-width: var(--container-wide); margin-inline: auto; }
/* A trust band outside the masthead has the card's 20px inset available to it,
   so without matching that inset the two instances cap at different widths and
   read as two different containers. */
.trust-bar--standalone {
  margin-inline: var(--masthead-inset);
  border-radius: var(--radius-lg);
}
.trust-bar ul {
  list-style: none;
  margin: 0;
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: var(--space-1) var(--space-3);
  font-size: var(--fs-nav);          /* measured: 18px */
  font-weight: var(--fw-regular);    /* measured: 400, not 600 — 600 ran wider and wrapped */
  text-transform: uppercase;
}
.trust-bar li { display: flex; align-items: center; gap: var(--space-2); }
/* The source separates these with a pipe rather than whitespace alone. */
.trust-bar li + li::before { content: "|"; opacity: .55; margin-right: var(--space-2); }
.trust-bar .stars { color: var(--amber); letter-spacing: 2px; }

/* Measured: 470x99, 2px rust border, 30px radius, 15px padding, no fill. */
/* Measured: 18px Inter, bold ITALIC lead line, regular body, both in the
   callout's own accent colour — not body ink. */
.callout {
  border: var(--border-width) solid var(--rust);
  border-radius: var(--radius-lg);
  padding: 15px var(--space-5);
  margin-block: var(--space-5);
  color: var(--rust);
  font-size: var(--fs-body);
  line-height: 1.2;
}
.callout p { margin: 0; }
.callout p + p { margin-top: var(--space-2); }
.callout strong { font-weight: var(--fw-bold); font-style: italic; }

/* The service-area callout is olive, and its body is italic too. */
.callout--olive { border-color: var(--olive); color: var(--olive); line-height: 1.5; }
.callout--olive p { font-style: italic; }

/* Display-font inline link — measured 24px RetroDream in navy, not body text. */
.link-display {
  font-family: var(--font-display);
  font-size: var(--fs-h3);
  color: var(--navy);
  text-decoration: none;
}
.link-display:hover { text-decoration: underline; }

/* Service-page intro sidebar and the bordered "common signs" note. */
/* Measured: main column 880, sidebar 300, 20px gap — inside the 1200
   container. The home intro's 470/670 split is a different component. */
.split.split--sidebar { grid-template-columns: 880fr 300fr; gap: var(--space-5); }
.sidebar {
  border: var(--border-width) solid var(--rust);
  border-radius: var(--radius-lg);
  padding: var(--space-6);
  color: var(--rust);
  font-size: var(--fs-body-sm);
}
.sidebar__title { font-size: var(--fs-body); text-transform: uppercase; color: var(--rust); margin-bottom: var(--space-3); }
.sidebar__title + ul { margin-bottom: var(--space-6); }
.sidebar p { font-size: var(--fs-body-sm); }
/* Source has NO outer border here — the emphasis is a solid olive tile behind
   the icon, with the heading in the display face. */
.note {
  margin-top: var(--space-8);
  display: grid;
  grid-template-columns: 84px 1fr;
  gap: var(--space-5);
  align-items: start;
}
.note__tile {
  width: 84px;
  height: 84px;
  border-radius: var(--radius-md);
  background: var(--olive);
  display: grid;
  place-items: center;
}
.note__icon { width: 44px; height: 44px; color: var(--cream); }
.note > div { min-width: 0; }
.note__title { font-family: var(--font-display); font-size: var(--fs-h3); text-transform: uppercase; color: var(--ink); margin-bottom: var(--space-4); }
.tick-list { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--space-2); }
/* Measured: the source's bullet is a "➞" glyph in ink, not a tick. */
.tick-list li { padding-left: 1.45em; text-indent: -1.45em; }
.tick-list li::before { content: "\279E"; color: var(--ink); margin-right: var(--space-2); }
.sidebar .tick-list li::before { color: var(--rust); }

/* Service pages: the "difference" block is three columns of lists. */
.col-3 {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: var(--space-8);
  margin-top: var(--space-8);
}
.col-title {
  font-size: var(--fs-body);
  text-transform: uppercase;
  color: var(--olive);
  margin-bottom: var(--space-4);
}
.num-list { margin: 0; padding-left: 1.25em; display: grid; gap: var(--space-2); font-size: var(--fs-body-sm); }
.col-3 .tick-list { font-size: var(--fs-body-sm); }

/* Service-area with a map beside it, and the related-services split. */
.split.split--map { grid-template-columns: 1fr 600px; align-items: start; }
.split.split--related { grid-template-columns: 300fr 880fr; }
/* Three across in the right column — auto-fit was wrapping them 2 + 1. */
.split--related .grid--3 { grid-template-columns: repeat(3, 1fr); gap: var(--space-4); }
.split.split--faq { grid-template-columns: 380fr 800fr; }
.area-map {
  border-radius: var(--radius-md);
  overflow: hidden;
  border: var(--border-width) solid var(--gray-200);
  min-height: 460px;
}
.area-map iframe { display: block; width: 100%; height: 100%; min-height: 460px; border: 0; }
.btn-row { display: flex; flex-wrap: wrap; gap: var(--space-3); margin-top: var(--space-6); }
.btn--olive { background: var(--olive); color: var(--cream); border-color: var(--olive); }
.btn--olive:hover { background: transparent; color: var(--olive); }

/* "Need help soon?" is a solid olive banner in the source, not an outline. */
.banner {
  background: var(--olive);
  color: var(--cream);
  padding-block: var(--space-6);
  font-size: var(--fs-body-sm);
}
/* The banner closes a row-group, where two rules fought over it:
   .row-group > .section--flush (0,2,0) zeroed padding-top, while
   .row-group > .section:last-child (0,2,1) kept an 80px padding-bottom - the
   pseudo-class wins on specificity. The text ended up flush against the top
   edge with 80px of olive below it. Three classes beat both, symmetrically. */
.row-group > .section.banner { padding-block: var(--space-6); }
.banner p { margin: 0; }

@media not all and (min-width: 861px) {
  .col-3 { grid-template-columns: 1fr; gap: var(--space-6); }
  .split.split--map,
  .split.split--related,
  .split.split--faq { grid-template-columns: 1fr; }
}

/* Long-form article body. A single column at a readable measure, with the
   numbered section headings carrying the display face like every other
   heading on the site. */
.post { max-width: 68ch; margin-inline: auto; }
.post > .breadcrumbs { margin-bottom: var(--space-8); }
.prose--post { max-width: none; }
.prose--post > p { margin-bottom: var(--space-5); }
.post__heading { font-size: var(--fs-h3); margin: var(--space-10) 0 var(--space-4); }
.prose--post > .tick-list { margin-top: var(--space-5); }

/* Bordered panels — the city "what to expect" block is two of these side by
   side, and the local-content section uses the same treatment so it reads as
   part of the system rather than a bolted-on block. */
.panel {
  border: var(--border-width) solid var(--navy);
  border-radius: var(--radius-lg);
  padding: var(--space-8);
  background: var(--color-bg-alt);
}
.panel--accent { border-color: var(--rust); }
/* Each list heading needs air above it; only the right panel's first heading,
   which already sits below the lead paragraph, is exempt. */
.panel .col-title { margin-top: var(--space-8); }
.panel__lead + div .col-title { margin-top: 0; }
.panel__lead { margin: 0 0 var(--space-5); }
.panel__note-title {
  font-size: var(--fs-body);
  text-transform: uppercase;
  color: var(--rust);
  margin: var(--space-6) 0 var(--space-2);
}
.panel__note { font-style: italic; font-size: var(--fs-body-sm); color: var(--rust); margin: 0; }
.split.split--expect { grid-template-columns: 700fr 480fr; align-items: start; }
.split.split--expect.split--even { grid-template-columns: 1fr 1fr; }

@media not all and (min-width: 861px) {
  .split.split--expect,
  .split.split--expect.split--even { grid-template-columns: 1fr; }
  .panel { padding: var(--space-6); }
}

/* --- Split intro ---------------------------------------------------------
   The source's intro is two UNEVEN columns, not a full-width heading: heading
   block ~470px left, body ~670px right, 40px gap, inside the 1200 container.
   Uneven splits read as designed; equal halves read as default. */
.split {
  display: grid;
  gap: var(--space-10);
  grid-template-columns: 470fr 670fr;
  align-items: start;
}
@media not all and (min-width: 861px) {
  .split,
  .split.split--sidebar { grid-template-columns: 1fr; gap: var(--space-6); }
  /* The icon column would not fit beside text on a phone. */
  .note { grid-template-columns: 1fr; }
  .note__icon { width: 48px; height: 48px; }
}

/* --- Section headings ----------------------------------------------------- */
.section__eyebrow {
  display: block;
  font-family: var(--font-display);
  font-size: var(--fs-eyebrow);
  font-weight: var(--fw-bold);
  letter-spacing: var(--ls-eyebrow);
  text-transform: uppercase;
  color: var(--rust);
  margin-bottom: var(--space-3);
}
.surface-brand .section__eyebrow, .surface-alt .section__eyebrow { color: var(--cream); }
.section__title { font-size: var(--fs-display-2); line-height: 1.1; }
.section__title--sm { font-size: var(--fs-h3); text-transform: uppercase; }
.section--center { text-align: center; }
.section--center .prose { margin-inline: auto; }

/* --- Cards / grids -------------------------------------------------------- */
.grid { display: grid; gap: var(--space-6); }
.grid--2 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 22rem), 1fr)); }
.grid--3 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 18rem), 1fr)); }
.grid--3.grid--fixed { grid-template-columns: repeat(3, 1fr); }
/* Measured: 4 across at 1556, cards 277x345, 24px gap. */
.grid--4 { grid-template-columns: repeat(auto-fit, minmax(min(100%, 15.5rem), 1fr)); gap: var(--space-6); }

.card {
  background: var(--color-bg);   /* matches the Our Services surface */
  border: var(--border-width) solid var(--navy);
  border-radius: var(--radius-md);   /* measured: 20px, not 30px */
  overflow: hidden;
  box-shadow: var(--shadow-card);
  display: flex;
  flex-direction: column;
}
.card__media { aspect-ratio: 3 / 2; display: block; }
/* <picture> is inline by default, so it left the image short of the box and
   opened a strip of card background above the title bar. */
.card__media > picture { display: block; height: 100%; }
.card__media img { width: 100%; height: 100%; object-fit: cover; }
/* Measured: a navy header bar (84px tall, 20px 20px 16px padding) carrying a
   24px cream uppercase title, above a white body. This is what the
   --radius-top / --radius-bottom tokens were extracted for. */
.card__icon { flex: 0 0 auto; width: 24px; height: 24px; color: var(--cream); }
.card__head {
  background: var(--navy);
  color: var(--cream);
  padding: 16px 20px;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: var(--space-3);
  /* One height across every card. Titles run one to three lines
     ("RV Slide-Out & Leveling System Repair" is the longest), which measured
     85 and 111 and left the row ragged. Sized to the tallest so the navy band
     is a constant. */
  min-height: 7rem;
  text-align: center;
}
.card__body { padding: var(--space-5); display: flex; flex-direction: column; gap: var(--space-3); flex: 1; font-size: var(--fs-body-sm); }
.card__title { font-size: var(--fs-h3); text-transform: uppercase; margin: 0; line-height: 1.1; color: var(--cream); }
.card__title a { color: var(--cream); text-decoration: none; }
.card__title a:hover { text-decoration: underline; }
.card__title a { color: inherit; text-decoration: none; }
.card__title a:hover { text-decoration: underline; }
.card__actions { margin-top: auto; padding-top: var(--space-3); }


/* Photo band. Measured: one continuous full-card strip 1516x357 with NO gaps,
   NO per-image radius and NO borders — three photos butted edge to edge. The
   earlier version rendered them as three separate bordered cards. */
/* Measured: the band spans the card width (x=20, w=1516), not the 1200
   container — it is a full-bleed strip inset only by the card margin. */
/* The band must share the trust bar's inset context, or the two cap at
   different values on narrower desktops (1360 vs 1400 at 1440) and read as
   separate containers. Card inset + the band's own 20px = 40px each side. */
/* The section already carries the 20px page-edge margin from the layout rule,
   so the band adds only its own 20px — adding the edge twice made it 1320
   against the trust bar's 1360. */
/* Photos run to the card edge; the card's own radius clips them. */
.photo-section { padding-inline: 0; }
/* Wide bands share one inset so they cap on the same value. Using the full
   gutter here put the service-area at 1272 while the trust bar and photo band
   sat at 1360 — an accidental third container. */
.section--wide-inset { padding-inline: var(--space-5); }
.photo-band { width: 100%; }
.photo-strip {
  width: 100%;
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 0;
  height: var(--strip-h, 357px);
}
.photo-strip picture { display: block; height: 100%; overflow: hidden; }
.photo-strip picture img { width: 100%; height: 100%; object-fit: cover; }
@media not all and (min-width: 641px) { .photo-strip { height: 200px; } }

/* Testimonials */
.quote {
  background: var(--color-bg-alt);
  border: var(--border-width) solid var(--navy);
  border-radius: var(--radius-lg);
  padding: var(--space-6);
  box-shadow: var(--shadow-card);
  margin: 0;
}
.quote blockquote { margin: 0 0 var(--space-4); font-size: var(--fs-body); }
.quote figcaption { font-weight: var(--fw-semibold); }
.quote__source { display: block; font-weight: var(--fw-regular); color: var(--color-text-muted); font-size: var(--fs-body-sm); }

/* --- Service area ---------------------------------------------------------
   Measured: a bordered cream card 873 wide on the left (2px OLIVE, 30px
   radius) and the "wherever parked" cutout on the right — not a navy band. */
/* Needs to outrank `.section > .inner` (0,2,0), which otherwise caps this at
   the 1200 body container. Source spans the full card (873 + 60 + 583 = 1516);
   --container-wide keeps those proportions without a third container width. */
.section > .inner.service-area-split { max-width: var(--container-wide); }
.service-area-split {
  display: grid;
  grid-template-columns: 873fr 583fr;
  gap: var(--space-10);
  align-items: center;
}
.service-area-card {
  background: var(--cream);
  border: var(--border-width) solid var(--olive);
  border-radius: var(--radius-lg);
  padding: var(--space-10);
}
.service-area-card h2 { font-size: var(--fs-display-2); line-height: 1.05; }
.service-area-media {
  position: relative;
  border-radius: var(--radius-lg);
  overflow: hidden;
  min-height: 100%;
}
/* Scoped to the media itself. A bare `> img` also matched the overlay cutout
   and stretched it to cover the whole panel, cropping the lettering. */
.service-area-media > picture,
.service-area-media > picture > img,
.service-area-media > .service-area-video {
  width: 100%; height: 100%; object-fit: cover; display: block;
}
/* Measured 623x876 — a tall column, not a letterbox. */
.service-area-media { min-height: 30rem; }
.service-area-split { align-items: stretch; }
.service-area-media__overlay {
  position: absolute;
  top: 60px;                 /* graphic sits at the top of the column */
  left: 50%;
  transform: translateX(-50%);
  width: 78%;
  height: auto;
  max-width: 22rem;
  object-fit: contain;
  z-index: 1;
}
.service-area-media > .service-area-video { object-position: center; }
.hub-heading {
  font-family: var(--font-display);
  font-size: 1.875rem;        /* measured 30px */
  line-height: 1.5;           /* measured 45px */
  color: var(--rust);
  text-transform: none;
  margin-bottom: var(--space-3);
}
.hub-list { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--space-2); font-size: var(--fs-body-sm); }
.hub-list li::before { content: "\2192"; color: var(--rust); margin-right: var(--space-2); }
.hub-list strong { color: var(--navy); }
@media not all and (min-width: 861px) {
  .service-area-split { grid-template-columns: 1fr; gap: var(--space-6); }
}

.quote .stars { color: var(--amber); letter-spacing: 2px; margin: 0 0 var(--space-3); }

/* --- Reviews mosaic -------------------------------------------------------
   Measured: 4 columns ~342 wide, varying heights, photographs interleaved
   with the quotes. A masonry column flow reproduces that; an equal-height
   grid does not. */
.mosaic { columns: 4 342px; column-gap: var(--space-5); }
.mosaic > * { break-inside: avoid; margin-bottom: var(--space-5); display: block; }
.mosaic img { border-radius: var(--radius-md); width: 100%; }
.section__cta { margin-top: var(--space-10); text-align: center; }
.btn--lg { padding: var(--space-4) var(--space-12); font-size: var(--fs-nav); }
@media not all and (min-width: 861px) { .mosaic { columns: 2 260px; } }
@media not all and (min-width: 541px) { .mosaic { columns: 1; } }

/* --- CTA band ------------------------------------------------------------- */
/* Fixed attachment: the photo stays put while the page scrolls, matching the
   source. iOS Safari ignores background-attachment:fixed and falls back to
   scroll, so the image is set on the element itself rather than a child <img>
   — that degrades to a normal cover image instead of breaking. */
.cta-band {
  position: relative;
  overflow: hidden;
  color: var(--cream);
  background-image: var(--cta-img);
  background-size: cover;
  background-position: center;
  background-attachment: fixed;
}
.cta-band::after { content: ""; position: absolute; inset: 0; background: var(--overlay-darker); z-index: 0; }
.cta-band > .inner { position: relative; z-index: 2; }
.cta-band::after { content: ""; position: absolute; inset: 0; background: var(--overlay-darker); z-index: 0; }
.cta-band > .inner {
  position: relative;
  z-index: 1;
  display: grid;
  grid-template-columns: 1fr auto;
  gap: var(--space-10);
  align-items: center;
  text-align: left;
}
.cta-band h2 { color: var(--cream); font-size: var(--fs-display-2); margin: 0; }
.cta-band .prose { margin: var(--space-3) 0 0; max-width: 52ch; }
.cta-band__actions { display: flex; flex-direction: column; gap: var(--space-3); }
.cta-band__actions .btn { text-align: center; white-space: nowrap; }
@media not all and (min-width: 861px) {
  .cta-band::after { content: ""; position: absolute; inset: 0; background: var(--overlay-darker); z-index: 0; }
.cta-band > .inner { grid-template-columns: 1fr; }
  .cta-band__actions { flex-direction: row; flex-wrap: wrap; }
}
.cta-band .hero__actions { margin-top: var(--space-6); }

/* --- City / service page local block -------------------------------------- */
.local { border-left: 4px solid var(--rust); padding-left: var(--space-6); }
.local h2 { font-size: var(--fs-h3); text-transform: uppercase; }

/* --- FAQ ------------------------------------------------------------------ */
.faq details {
  border-bottom: 1px solid var(--color-border-subtle);
  padding-block: var(--space-4);
}
.faq summary {
  cursor: pointer;
  font-family: var(--font-display);
  font-size: var(--fs-h3);
  /* Sentence case, not caps: these questions are quoted verbatim in FAQ rich
     results and AI answers, where shouting reads badly. */
  list-style: none;
  display: flex;
  justify-content: space-between;
  gap: var(--space-4);
}
.faq summary::-webkit-details-marker { display: none; }
.faq summary::after { content: "+"; color: var(--rust); font-weight: var(--fw-bold); }
.faq details[open] summary::after { content: "\2212"; }

/* --- Contact details ------------------------------------------------------ */
/* Contact details. <dd> carries a 40px browser indent by default, which left
   every value floating away from its label. Rows are label-over-value with a
   hairline between them, matching how the footer presents the same facts. */
.contact-list { margin: 0 0 var(--space-6); padding: 0; display: grid; gap: 0; }
.contact-list > div {
  padding: var(--space-4) 0;
  border-bottom: 1px solid rgba(27, 42, 51, 0.16);
}
.contact-list > div:first-child { padding-top: 0; }
.contact-list > div:last-child { border-bottom: 0; padding-bottom: 0; }
.contact-list dt {
  font-family: var(--font-display);
  font-size: var(--fs-body-sm);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--olive);
  margin-bottom: var(--space-1);
}
.contact-list dd {
  margin: 0;                      /* kills the default indent */
  font-size: var(--fs-body);
  line-height: var(--lh-body);
}
.contact-list a { color: var(--rust); text-underline-offset: 3px; }

/* --- Forms ---------------------------------------------------------------- */
.form { display: grid; gap: var(--space-5); max-width: 40rem; }
.field { display: grid; gap: var(--space-2); }
.field label { font-weight: var(--fw-semibold); }
.field input, .field textarea, .field select {
  font: inherit;
  color: var(--color-text);
  background: var(--color-bg-alt);
  border: var(--border-width) solid var(--navy);
  border-radius: var(--radius-sm);
  padding: var(--space-3) var(--space-4);
  min-height: 44px;
}
.field textarea { min-height: 8rem; resize: vertical; }
.field__hint { font-size: var(--fs-body-sm); color: var(--color-text-muted); }
.checkbox-group { display: flex; flex-wrap: wrap; gap: var(--space-4); }
.checkbox { display: flex; align-items: center; gap: var(--space-2); min-height: 44px; }
.checkbox input { width: 1.25rem; height: 1.25rem; min-height: 0; accent-color: var(--rust); }
.form__status { padding: var(--space-4); border-radius: var(--radius-sm); }
.form__status[data-state="error"] { background: #FDECEA; border: 2px solid #B3261E; color: #7A1912; }
.form__status[data-state="success"] { background: #E8F3EC; border: 2px solid var(--olive); color: #2C4527; }
.hp { position: absolute; left: -9999px; width: 1px; height: 1px; overflow: hidden; }

/* --- Footer --------------------------------------------------------------- */
.site-footer {
  background: var(--olive);
  color: var(--cream);
  /* 2px down across the footer: the four columns are narrow and the email
     address was breaking across two lines at the inherited body size. */
  font-size: calc(var(--fs-body) - 2px);
}
.site-footer a { color: var(--cream); }
.site-footer h2, .site-footer h3 { color: var(--cream); }
/* Footer layout. Deliberately NOT .grid: that class is this codebase's card-grid
   utility and verify-design audits it for mixed card variants. Footer columns
   legitimately differ (one holds links, two do not), so a card rule does not
   apply. Columns still stretch to a shared height — at align-items:start they
   came out 123/174/161px and read as ragged. */
.footer-grid {
  display: grid;
  gap: var(--space-6);
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 18rem), 1fr));
  align-items: stretch;
}
.site-footer__col { display: flex; flex-direction: column; gap: var(--space-3); }
.site-footer__col h3 {
  font-size: calc(var(--fs-h3) - 2px);
  text-transform: uppercase;
  margin-bottom: var(--space-4);
  padding-bottom: var(--space-3);
  border-bottom: 1px solid rgba(247, 244, 243, 0.28);
}
/* Four columns at 18rem min plus 40px gaps exceed the 1200 container, so the
   fourth wrapped onto its own row and read as a stray block. */
.site-footer .footer-grid {
  gap: var(--space-6);
  /* 18rem, not 15rem: below ~288px the column is narrower than the email
     address and it breaks across two lines. Fewer, wider columns beats four
     cramped ones. */
  grid-template-columns: repeat(auto-fit, minmax(min(100%, 18rem), 1fr));
}
/* Four equal columns left the contact column 276px against a 281px email
   address, so it broke across two lines. The map column needs the least room,
   so the difference comes from there. */
@media (min-width: 1240px) {
  .site-footer .footer-grid { grid-template-columns: 1.2fr 1fr 1fr 0.8fr; }
}

.site-footer a { text-underline-offset: 3px; }
.site-footer__map {
  border-radius: var(--radius-md);
  overflow: hidden;
  border: var(--border-width) solid rgba(247, 244, 243, 0.28);
  min-height: 220px;
}
.site-footer__map iframe { display: block; width: 100%; height: 100%; min-height: 220px; border: 0; }
.site-footer ul { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--space-2); }
/* jason@familyinspectionservices.com is longer than the column. */
.site-footer a, .site-footer p, .site-footer li { overflow-wrap: anywhere; }
.colophon {
  background: var(--olive);
  color: var(--cream);
  border-top: 1px solid rgba(247, 244, 243, 0.25);
  padding-block: var(--space-5);
  font-size: var(--fs-body-sm);
}
.colophon .inner { display: flex; flex-wrap: wrap; gap: var(--space-3) var(--space-6); align-items: baseline; justify-content: space-between; }

/* --- Breadcrumbs ---------------------------------------------------------- */
.breadcrumbs { font-size: var(--fs-body-sm); }
.breadcrumbs ol { list-style: none; margin: 0; padding: 0; display: flex; flex-wrap: wrap; gap: var(--space-2); }
.breadcrumbs li + li::before { content: "/"; margin-right: var(--space-2); opacity: 0.6; }

/* --- Responsive ----------------------------------------------------------- */
/* Tablet-and-below breakpoint. Written as a negated min-width so it reads
   unambiguously as a breakpoint rather than a container width. */
@media not all and (min-width: 1025px) {
  .site-nav ul { gap: var(--space-4); }
  .site-nav a { font-size: var(--fs-body-sm); }
}

@media (max-width: 768px) {

  /* 1. The utility line wrapped the phone number across three lines in 174px.
     Drop the review link on mobile and give the number the full width — it is
     the one thing a phone visitor is most likely to want. */
  .site-header__review,
  .site-header__sep { display: none; }
  .site-header__utility { white-space: nowrap; justify-content: flex-end; }
  .site-header__tel { font-size: var(--fs-nav); }

  /* 2. The tray opened transparent over the hero video and was unreadable. */
  .site-nav[data-open="true"] {
    background: var(--navy);
    border-radius: var(--radius-md);
    padding: var(--space-2) var(--space-5);
    margin-top: var(--space-3);
    box-shadow: 0 12px 32px rgba(0, 0, 0, 0.35);
  }
  .site-nav[data-open="true"] a:last-child { border-bottom: 0; }

  /* 2. The header is absolutely positioned over the hero, and on a phone it
     stacks logo + phone + Menu to 102px. A 72px hero pad put the eyebrow at
     y=92 — 30px UNDER the Menu button. Clear the header, then breathe. */
  .masthead--compact { --hero-pt: 9rem; }
  .masthead { --hero-pt: 10rem; }

  /* 3. Related-service cards stack one per row on a phone. */
  .split--related .grid--3,
  .grid--3.grid--fixed { grid-template-columns: 1fr; }

  /* 3. Trust bar: separators between wrapped rows landed in odd places and the
     block ran to 216px. Stack it centred, ruled instead of piped. */
  .trust-bar { padding-block: var(--space-4); }
  .trust-bar ul {
    display: grid;                       /* 2x2 — a single stack ran to 245px */
    grid-template-columns: 1fr 1fr;
    gap: var(--space-3) var(--space-4);
    font-size: 0.8125rem;
    line-height: 1.25;
    letter-spacing: 0.02em;
  }
  .trust-bar li {
    justify-content: center;
    text-align: center;
    flex-direction: column;
    gap: var(--space-1);
  }
  .trust-bar li + li::before { content: none; margin: 0; }
  .trust-bar .stars { font-size: 1rem; }

  .nav-toggle { display: inline-flex; }
  .site-nav {
    display: none;
    width: 100%;
    order: 3;
  }
  .site-nav[data-open="true"] { display: block; }
  .site-nav ul {
    flex-direction: column;
    align-items: stretch;
    gap: 0;
    padding-block: var(--space-4);
  }
  .site-nav a {
    display: block;
    font-family: var(--font-util);
    font-weight: var(--fw-bold);
    padding: var(--space-4) 0;
    border-bottom: 1px solid rgba(247, 244, 243, 0.2);
  }
  .site-header .inner { flex-wrap: wrap; }
  .site-header__logo img { height: 48px; }
  .hero { text-align: left; }
  .hero__actions { justify-content: flex-start; }
  .utility-bar .inner { justify-content: center; }
  .colophon .inner { justify-content: flex-start; }
}

@media print {
  .utility-bar, .site-nav, .nav-toggle, .cta-band, .hero__media { display: none; }
  body { color: #000; background: #fff; }
}


/* --- Viral Growth Marketing footer credit -------------------------------
   Moved out of templates/partials/vgm_credit.html: <style> is metadata
   content and is not conforming inside <div>, and the block was being
   duplicated into all 28 pages. Markup and rules are otherwise untouched. */
.vgm-credit{--vgm-footer-color:#F7F4F3;--vgm-weight-hover:800;--vgm-row-gap:.35em;--vgm-ease:cubic-bezier(.23,1,.32,1);font-size:inherit;font-family:inherit;font-weight:inherit;letter-spacing:inherit;text-transform:inherit;color:var(--vgm-footer-color);margin:0;display:flex;align-items:baseline;gap:.4em;flex-wrap:wrap}
.vgm-bsr{position:relative;display:inline-block;cursor:default}
.vgm-bsr-brand,.vgm-bsr-rated,.vgm-bsr-label{font:inherit;letter-spacing:inherit;text-transform:inherit;color:var(--vgm-footer-color)}
.vgm-bsr-brand,.vgm-bsr-label{white-space:nowrap}
.vgm-bsr-brand{text-decoration:none;line-height:1.1;transition:font-weight .22s var(--vgm-ease),letter-spacing .22s var(--vgm-ease)}
.vgm-bsr-brand:focus-visible{outline:2px solid #FBBC04;outline-offset:3px;border-radius:2px}
.vgm-bsr-top{position:absolute;bottom:100%;left:0;margin-bottom:var(--vgm-row-gap);line-height:1;display:flex;align-items:center;gap:.45em;white-space:nowrap;opacity:0;transform:translateY(-10px);pointer-events:none;transition:opacity .32s var(--vgm-ease),transform .32s var(--vgm-ease)}
.vgm-bsr-star{font-size:1em;line-height:1;display:inline-block;font-family:"Segoe UI Symbol","Apple Color Emoji","Noto Color Emoji",sans-serif;color:#FBBC04!important;opacity:0;transform:translateY(-8px) scale(.6);transition:opacity .28s var(--vgm-ease),transform .28s var(--vgm-ease),filter .28s}
.vgm-bsr-bottom{position:absolute;top:100%;left:0;margin-top:var(--vgm-row-gap);line-height:1;display:flex;align-items:center;gap:.4em;white-space:nowrap;opacity:0;transform:translateY(6px);pointer-events:none;transition:opacity .35s var(--vgm-ease),transform .35s var(--vgm-ease)}
.vgm-bsr-dot{width:.7em;height:.7em;border-radius:50%;display:inline-block;flex-shrink:0;background:linear-gradient(135deg,#4285F4 0%,#34A853 33%,#FBBC05 66%,#EA4335 100%)!important}

/* Reveal — keyboard and touch always; pointer only where hover really exists. */
.vgm-bsr:focus-within .vgm-bsr-brand,.vgm-bsr.is-active .vgm-bsr-brand{font-weight:var(--vgm-weight-hover);letter-spacing:var(--vgm-hover-track,inherit)}
.vgm-bsr:focus-within .vgm-bsr-top,.vgm-bsr.is-active .vgm-bsr-top,.vgm-bsr:focus-within .vgm-bsr-bottom,.vgm-bsr.is-active .vgm-bsr-bottom{opacity:1;transform:translateY(0)}
.vgm-bsr:focus-within .vgm-bsr-bottom,.vgm-bsr.is-active .vgm-bsr-bottom{transition-delay:.38s}
.vgm-bsr:focus-within .vgm-bsr-star,.vgm-bsr.is-active .vgm-bsr-star{opacity:1;transform:translateY(0) scale(1);filter:drop-shadow(0 0 3px rgba(251,188,4,.6));transition-delay:calc(var(--i) * 70ms)}
@media (hover:hover){
.vgm-bsr:hover .vgm-bsr-brand{font-weight:var(--vgm-weight-hover);letter-spacing:var(--vgm-hover-track,inherit)}
.vgm-bsr:hover .vgm-bsr-top,.vgm-bsr:hover .vgm-bsr-bottom{opacity:1;transform:translateY(0)}
.vgm-bsr:hover .vgm-bsr-bottom{transition-delay:.38s}
.vgm-bsr:hover .vgm-bsr-star{opacity:1;transform:translateY(0) scale(1);filter:drop-shadow(0 0 3px rgba(251,188,4,.6));transition-delay:calc(var(--i) * 70ms)}
}
.vgm-credit[data-vgm-align="right"] .vgm-bsr-top,.vgm-credit[data-vgm-align="right"] .vgm-bsr-bottom{left:auto;right:0}
@media (max-width:480px){.vgm-bsr-top,.vgm-bsr-bottom,.vgm-bsr-label{white-space:normal}.vgm-bsr-top,.vgm-bsr-bottom{max-width:14em}}
@media (prefers-reduced-motion:reduce){.vgm-bsr-top,.vgm-bsr-bottom,.vgm-bsr-star{transform:none!important}.vgm-bsr-star,.vgm-bsr-bottom{transition-delay:0s!important}.vgm-bsr-brand{transition:none}}
@media (forced-colors:active){.vgm-bsr-star{color:CanvasText!important}.vgm-bsr-dot{background:CanvasText!important;forced-color-adjust:none}}

.fieldset--bare { border: 0; padding: 0; margin: 0; }
.fieldset__legend { font-weight: var(--fw-semibold); padding: 0; }

/* Contact form sits beside the service-area map rather than leaving half the
   card empty. Same map embed the service pages use. */
.split.split--form { grid-template-columns: 620fr 520fr; align-items: start; }
@media not all and (min-width: 861px) {
  .split.split--form { grid-template-columns: 1fr; }
}

/* City tiles on the service-area hub. The list was bare links with a county
   caption underneath, which read as an unstyled sitemap rather than part of
   the card system. */
.city-grid {
  list-style: none;
  margin: 0;
  padding: 0;
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr));
  gap: var(--space-4);
}
.city-tile {
  display: flex;
  flex-direction: column;
  gap: var(--space-1);
  padding: var(--space-5) var(--space-6);
  border: var(--border-width) solid var(--navy);
  border-radius: var(--radius-md);
  background: var(--color-bg);
  text-decoration: none;
  color: inherit;
  transition: background 0.18s ease, transform 0.18s ease;
}
.city-tile:hover, .city-tile:focus-visible { background: var(--color-bg-alt); transform: translateY(-2px); }
@media (prefers-reduced-motion: reduce) { .city-tile { transition: none; } .city-tile:hover { transform: none; } }
.city-tile__name {
  font-family: var(--font-display);
  font-size: var(--fs-h3);
  text-transform: uppercase;
  line-height: 1.1;
}
.city-tile__county { font-size: var(--fs-body-sm); color: var(--olive); }

/* The post title carries its parenthetical on a second line, as the source
   sets it, without making it a separate heading. */
.hero__headline-sub { display: block; }

/* --- Article list ---------------------------------------------------------
   Text-led cards. Without a thumbnail the title has to carry the card, so it
   runs large with the meta line above it and an excerpt doing the selling. */
.post-list { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--space-5); }
.post-card {
  position: relative;
  border: var(--border-width) solid var(--navy);
  border-radius: var(--radius-md);
  background: var(--color-bg);
  padding: var(--space-8);
  transition: background 0.18s ease, transform 0.18s ease;
}
.post-card:hover, .post-card:focus-within { background: var(--color-bg-alt); transform: translateY(-2px); }
@media (prefers-reduced-motion: reduce) { .post-card { transition: none; } .post-card:hover { transform: none; } }
.post-card__meta {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-3);
  margin: 0 0 var(--space-3);
  font-size: var(--fs-body-sm);
}
.post-card__tag {
  font-family: var(--font-display);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--rust);
}
.post-card__time { color: var(--olive); }
.post-card__time::before { content: "\00b7"; margin-right: var(--space-3); color: var(--olive); }
.post-card__title { font-size: clamp(1.5rem, 2.4vw, 2rem); text-transform: uppercase; margin: 0 0 var(--space-4); line-height: 1.05; }
.post-card__title a { color: inherit; text-decoration: none; }
/* The whole card is the target; the title keeps the accessible name. */
.post-card__title a::after { content: ""; position: absolute; inset: 0; }
.post-card__title a:focus-visible { outline: none; }
.post-card:focus-within { outline: 3px solid var(--color-accent); outline-offset: 2px; }
.post-card__excerpt { max-width: var(--measure); margin-bottom: var(--space-5); }
.post-card__more { margin: 0; }

@media (min-width: 861px) {
  /* A second post will sit beside the first; one on its own stays readable
     rather than stretching a lone card across the full row. */
  .post-list { grid-template-columns: repeat(auto-fill, minmax(28rem, 1fr)); }
}

/* --- Long-form article ----------------------------------------------------
   Scannability comes from three things: a jump list so a reader can go
   straight to the symptom they have, numbered section markers so position is
   obvious mid-scroll, and generous space between sections. */
.post__meta {
  display: flex; flex-wrap: wrap; align-items: center; gap: var(--space-3);
  font-size: var(--fs-body-sm);
  margin-bottom: var(--space-6);
}
.post__tag {
  font-family: var(--font-display);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--rust);
}
.post__time { color: var(--olive); }
.post__time::before { content: "\00b7"; margin-right: var(--space-3); }
.post__intro { font-size: 1.2em; }

.toc {
  border: var(--border-width) solid var(--navy);
  border-radius: var(--radius-md);
  background: var(--color-bg-alt);
  padding: var(--space-6) var(--space-8);
  margin: var(--space-10) 0;
}
.toc__title {
  font-size: var(--fs-body);
  text-transform: uppercase;
  letter-spacing: 0.04em;
  color: var(--olive);
  margin-bottom: var(--space-4);
}
.toc__list { list-style: none; margin: 0; padding: 0; display: grid; gap: var(--space-2); }
.toc__list a {
  display: flex; align-items: baseline; gap: var(--space-3);
  color: inherit; text-decoration: none;
}
.toc__list a:hover, .toc__list a:focus-visible { text-decoration: underline; text-underline-offset: 3px; }
.toc__num {
  flex: 0 0 auto;
  font-family: var(--font-display);
  color: var(--rust);
  min-width: 1.2em;
}

.post__section + .post__section { margin-top: var(--space-12); }
.post__section { scroll-margin-top: var(--space-12); }
.post__heading { display: flex; align-items: baseline; gap: var(--space-4); }
.post__num {
  flex: 0 0 auto;
  color: var(--rust);
  font-size: 0.85em;
}

.post__cta {
  margin-top: var(--space-12);
  border: var(--border-width) solid var(--rust);
  border-radius: var(--radius-md);
  background: var(--color-bg-alt);
  padding: var(--space-8);
}
.post__cta p { margin-bottom: var(--space-3); }
.post__cta .btn-row { margin-top: var(--space-6); margin-bottom: 0; display: flex; flex-wrap: wrap; gap: var(--space-3); }

@media not all and (min-width: 861px) {
  .toc { padding: var(--space-5) var(--space-6); }
  .post__cta { padding: var(--space-6); }
}

.post__lead { margin: 0 0 var(--space-8); }
.post__lead img { width: 100%; height: auto; border-radius: var(--radius-md); }

/* --- Touch target size ----------------------------------------------------
   WCAG 2.5.8 (AA) wants 24x24 CSS px for anything that is not inline in a
   sentence. Standalone links sat at 16-21px on phones: footer links, the
   breadcrumb trail, the ">>" display links and card titles. Padding is added
   at mobile widths only, so desktop spacing is untouched. Links genuinely
   inline in prose are exempt and deliberately not caught here. */
@media not all and (min-width: 861px) {
  .site-footer a,
  .breadcrumbs a,
  .link-display,
  .card__title a,
  .toc__list a,
  .contact-list a,
  .not-found__links a,
  .ndrsl-widget a {
    display: inline-block;
    padding-block: 5px;
  }
  /* The padding would otherwise push the columns apart twice over. */
  .site-footer__col { gap: var(--space-1); }
  .breadcrumbs ol { gap: var(--space-1) var(--space-2); }
}

.not-found__links { list-style: none; padding: 0; }

/* Town links on the service pages. A compact inline run, not a second list of
   bullets — the hub list above it already carries that weight. */
.city-links {
  list-style: none;
  margin: 0 0 var(--space-6);
  padding: 0;
  display: flex;
  flex-wrap: wrap;
  gap: var(--space-2);
  font-size: var(--fs-body-sm);
}
/* No separator characters: a "·" before every item but the first lands at the
   start of any wrapped line. The gap does the separating. */
.city-links a {
  display: inline-block;
  padding: 4px 10px;
  border: 1px solid var(--color-border-subtle);
  border-radius: 999px;
  color: var(--rust);
  text-decoration: none;
}
.city-links a:hover, .city-links a:focus-visible { border-color: var(--rust); text-decoration: underline; }
