/* Base layout + components. All color/typography comes from tokens
   (src/generated/tokens.css); skins override structure/feel only.

   THIS FILE IS THE ONLY EDITABLE COPY. It styles BOTH outputs: the Astro
   build imports it directly, and tools/wp_deploy.py stage_assets() copies it
   over wp-theme/oneclick/assets/base.css at every deploy. Edits made to the
   wp-theme copy are silently clobbered on the next deploy (this happened
   2026-08-15). WordPress-only chrome selectors are scoped with `--v1`
   modifier classes so they stay inert in the Astro DOM. */

*, *::before, *::after { box-sizing: border-box; }
html { scroll-behavior: smooth; }
body {
  margin: 0;
  font-family: var(--font-body);
  color: var(--color-body);
  background: var(--color-bg);
  line-height: 1.65;
  font-size: 1.0625rem;
}
h1, h2, h3, h4 {
  font-family: var(--font-heading);
  color: var(--color-heading);
  font-weight: 700;
  letter-spacing: -0.01em;
  line-height: 1.1;
  margin: 0 0 0.6em;
}
/* Measured against the live ocf-lightning reference 2026-08-31: their H1 is
   clamp(34px, 5vw, 63px) / weight 700 / line-height 1.08 (assets/global.css
   --font-h1-size + components/hero.css .ocf-hero__headline). Ours topped out
   at 3.1rem (49.6px) -- noticeably thinner/smaller at desktop widths. */
h1 { font-size: clamp(34px, 5vw, 63px); line-height: 1.08; }
h2 { font-size: clamp(1.5rem, 3.2vw, 2.1rem); }
h3 { font-size: 1.2rem; }
p { margin: 0 0 1em; }
a { color: var(--color-accent); text-decoration: none; }
a:hover { color: var(--color-accent-hover); }
img { max-width: 100%; height: auto; display: block; }
ul { padding-left: 1.2em; }

.container { max-width: 72rem; margin-inline: auto; padding-inline: 1.25rem; }
.container-narrow { max-width: 46rem; }

/* Buttons */
.btn {
  display: inline-block;
  padding: 0.65em 1.4em;
  border-radius: calc(var(--radius, 8px) + 2px);
  font-weight: 600;
  font-family: var(--font-body);
  border: 2px solid transparent;
  cursor: pointer;
  transition: background 0.15s, color 0.15s, border-color 0.15s;
}
.btn-lg { padding: 0.8em 1.7em; font-size: 1.05rem; }
.btn-primary { background: var(--color-accent); color: var(--color-on-accent); }
.btn-primary:hover { background: var(--color-accent-hover); color: var(--color-on-accent); }
.btn-inverse { background: var(--color-heading-alt); color: var(--color-bg-dark); }
.btn-inverse:hover { background: var(--color-body-alt); color: var(--color-bg-dark); }
.btn-outline { border-color: var(--color-heading-alt); color: var(--color-heading-alt); }
.btn-outline:hover { background: var(--color-heading-alt); color: var(--color-bg-dark); }

/* Shared design utilities: eyebrow section labels + icon-badge decorators
   used across section components (Services, Areas, Reviews, etc). */
.eyebrow {
  display: block;
  font-size: 0.8rem;
  font-weight: 700;
  letter-spacing: 0.08em;
  text-transform: uppercase;
  color: var(--color-accent);
  margin-bottom: 0.5em;
}
.icon-badge {
  width: 46px; height: 46px;
  display: flex; align-items: center; justify-content: center;
  border-radius: var(--button-radius);
  background: color-mix(in srgb, var(--color-accent) 12%, var(--color-bg));
  color: var(--color-accent);
  margin-bottom: 0.9rem;
}
.icon-badge svg, .icon-badge img { width: 22px; height: 22px; }

/* Header */
.site-header {
  background: var(--color-bg);
  border-bottom: 1px solid var(--color-border);
  position: sticky; top: 0; z-index: 50;
}
.header-row { display: flex; align-items: center; gap: 1.5rem; min-height: 4.25rem; }
.brand { flex-shrink: 0; }
.brand-logo { max-height: 2.6rem; width: auto; }
/* Footer logo slot (2026-09-01 logo-slot parity fix): matches
   wp-theme/oneclick/assets/components/footer.css's .footer-logo-img sizing
   (max-height: 3rem; margin-bottom: 1rem) so the two render paths agree on
   how large an uploaded logo shows in the footer. Sits above the always-
   rendered .footer-brand name text, never replacing it -- see the Base.astro
   comment at this element for the full arrangement rationale. */
.footer-logo { max-height: 3rem; width: auto; margin-bottom: 1rem; display: block; }
.wordmark {
  font-family: var(--font-heading);
  font-weight: 800; font-size: 1.35rem;
  color: var(--color-heading);
  letter-spacing: -0.01em;
}
.site-nav { display: flex; gap: 1.4rem; margin-left: auto; }
.site-nav a { color: var(--color-body); font-weight: 500; }
.site-nav a:hover, .site-nav a[aria-current="page"] { color: var(--color-accent); }
.header-actions { display: flex; align-items: center; gap: 1rem; }
.phone-link { font-weight: 600; color: var(--color-heading); white-space: nowrap; }
.nav-toggle { display: none; background: none; border: 0; padding: 0.4rem; }
/* :not(.screen-reader-text) — Astro's burger is three bare <span>s, the
   WordPress one adds a .screen-reader-text label span alongside them. An
   unscoped `.nav-toggle span` turns that label into a fourth visible bar
   (.screen-reader-text is the weaker selector and loses on width/height). */
.nav-toggle span:not(.screen-reader-text) {
  display: block; width: 22px; height: 2px; margin: 5px 0;
  background: var(--color-heading);
}

/* Hero */
.hero {
  background: var(--color-bg-alt);
  padding: clamp(3.5rem, 9vw, 6.5rem) 0;
  text-align: center;
}
.hero-compact { padding: clamp(2.25rem, 6vw, 3.75rem) 0; }
/* Measured against the live ocf-lightning reference 2026-08-31
   (wp-content/themes/ocf-lightning/assets/ocf-global.css --gradient-hero-dark
   at the reference's full-strength shade opacity of 1): a directional
   near-black scrim, fixed at #141414 -- NOT the tenant's brand-tinted
   --color-bg-dark. Using --color-bg-dark here (a dark green for a
   pest-control brand, etc.) is what produced the light, brand-tinted hero
   wash instead of their dark overlay. Percentages below are the reference's
   own color-mix stops (94/86/58/30/12 and 32/54) copied as-is -- our WP
   theme's home-hero.php previously rendered its .ocf-hero__shade at 0.72
   opacity instead of 1, which is why an earlier version of this comment
   pre-multiplied these stops by 0.72; that bug is fixed (see
   parts/home-hero.php), so this flat single-layer version now reproduces
   the reference at full strength without needing a second opacity pass. */
.hero-image {
  background:
    linear-gradient(90deg,
      color-mix(in srgb, #141414 94%, transparent) 0%,
      color-mix(in srgb, #141414 86%, transparent) 34%,
      color-mix(in srgb, #141414 58%, transparent) 58%,
      color-mix(in srgb, #141414 30%, transparent) 76%,
      color-mix(in srgb, #141414 12%, transparent) 100%),
    linear-gradient(180deg,
      color-mix(in srgb, #141414 32%, transparent) 0%,
      color-mix(in srgb, #141414 54%, transparent) 100%),
    var(--hero-img) center/cover no-repeat;
}
.hero-image h1, .hero-image .subhead { color: var(--color-heading-alt); }
.subhead {
  font-size: 1.25rem;
  max-width: 38rem;
  margin: 0.75rem auto 0;
  color: var(--color-body);
}
.hero-image .subhead { color: var(--color-body-alt); }
.hero-actions { margin-top: 1.75rem; display: flex; gap: 1rem; justify-content: center; flex-wrap: wrap; }

/* Split hero: copy left, calculator or lead-form card right. Base geometry
   (shared by every skin); a skin may still restyle the card itself (see
   summit.css's glass .hero-calc-card) but the grid/alignment lives here so
   the split layout isn't a summit-only feature. */
.hero-split .hero-grid { display: grid; grid-template-columns: 1.1fr 1fr; gap: 3rem; align-items: center; }
.hero-split .hero-content { text-align: left; }
.hero-split .subhead { margin-inline: 0; }
.hero-split .hero-actions { justify-content: flex-start; }
/* SAME-CARD RULING 2026-09-12 (skin/form-nav-cool, Hannah: "our hero form
   card should be the same as our other cards"): CASCADE FINDING made while
   fixing this -- functions.php enqueues assets/components/contact-form.css
   (which also declares a bare `.hero-form-card` rule) BEFORE this file, and
   both rules share the exact same specificity (one class selector), so on
   every property they both set, THIS rule was the one actually winning and
   rendering all along -- contact-form.css's version (including the earlier
   "match the nav bar" glass surface) was fighting a cascade battle it always
   lost for background/border/border-radius/box-shadow. Fixed here by moving
   this rule onto the identical shared card tokens as contact-form.css's
   .hero-form-card and every other card on the site (.ocf-svc-card /
   .ocf-testimonial-card / .ocf-faq-item): var(--card-radius),
   var(--card-shadow), var(--card-border-width)/var(--card-border-color),
   var(--ocf-bg) -- so the two rules now agree instead of one silently
   shadowing the other. */
.hero-form-card {
  background: var(--ocf-bg);
  border: var(--card-border-width) solid var(--card-border-color);
  border-radius: var(--card-radius);
  padding: 1.75rem;
  box-shadow: var(--card-shadow);
}
.hero-form-card .contact-form-heading { margin-bottom: 1rem; }
/* Reference's "Send Request" button spans the card, not just its own
   content width -- measured 2026-08-31. */
.contact-form .btn { width: 100%; text-align: center; }
@media (max-width: 900px) {
  .hero-split .hero-grid { grid-template-columns: 1fr; }
  .hero-split .hero-content { text-align: center; }
  .hero-split .subhead { margin-inline: auto; }
  .hero-split .hero-actions { justify-content: center; }
}

/* Rating badge: real aggregate rating only (never invented). Reuses the
   .hero-badge pill; adds an inline star string and an optional Google mark,
   shown only when the review data actually came from Google. */
.hero-badge-rating { gap: 0.45em; }
.hero-badge-rating .stars-inline { color: #f5b400; letter-spacing: 1px; font-size: 0.85em; }
.hero-badge-rating .google-g-icon { width: 16px; height: 16px; flex: none; }

/* Sections */
section { padding: clamp(2.5rem, 6vw, 4.25rem) 0; }
.intro-section { padding-bottom: 1rem; }
.lead { font-size: 1.15rem; }
.rich-section:nth-of-type(even) { background: var(--color-bg-alt); }
.section-intro { max-width: 44rem; margin-bottom: 2rem; }

/* Cards */
.card-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(17rem, 1fr));
  gap: 1.5rem;
  margin-top: 1.5rem;
}
.card {
  background: var(--color-bg);
  border-top: 3px solid var(--color-accent);
  border-radius: calc(var(--radius, 10px) + 6px);
  overflow: hidden;
  color: inherit;
  display: flex; flex-direction: column;
  box-shadow: 0 2px 12px rgba(15, 23, 42, 0.07);
  transition: box-shadow 0.15s, transform 0.15s;
}
.card:hover { box-shadow: 0 8px 26px rgba(15, 23, 42, 0.12); transform: translateY(-2px); }
.card-img { aspect-ratio: 3 / 2; object-fit: cover; width: 100%; }
.card-img-placeholder {
  background: linear-gradient(135deg, var(--color-accent), var(--color-secondary));
  opacity: 0.85;
}
.card-body { padding: 1.1rem 1.25rem 1.3rem; }
.card-body h3 { margin-bottom: 0.35em; }
.card-body p { color: var(--color-body); font-size: 0.97rem; }
.card-cta { font-weight: 600; color: var(--color-accent); font-size: 0.95rem; }

/* Areas */
.areas-grid-section { background: var(--color-bg-alt); }
.area-links {
  list-style: none; padding: 0;
  display: grid; grid-template-columns: repeat(auto-fill, minmax(13rem, 1fr));
  gap: 0.6rem 1.25rem; margin-top: 1.25rem;
}
.area-links a {
  display: block; padding: 0.7rem 1rem;
  background: var(--color-bg);
  border: 1px solid var(--color-border);
  border-radius: var(--radius, 8px);
  font-weight: 500; color: var(--color-heading);
  box-shadow: 0 1px 6px rgba(15, 23, 42, 0.04);
  transition: box-shadow 0.15s, border-color 0.15s, color 0.15s;
}
.area-links a:hover {
  border-color: var(--color-accent); color: var(--color-accent);
  box-shadow: 0 4px 14px rgba(15, 23, 42, 0.08);
}

/* Process */
.process-steps {
  list-style: none; counter-reset: step; padding: 0;
  display: grid; grid-template-columns: repeat(auto-fit, minmax(14rem, 1fr));
  gap: 1.75rem; margin-top: 1.5rem;
}
.step-num {
  display: inline-flex; align-items: center; justify-content: center;
  width: 2.2rem; height: 2.2rem; border-radius: 50%;
  background: var(--color-accent); color: var(--color-on-accent);
  font-weight: 700; margin-bottom: 0.6rem;
}

/* Bullets */
.bullets { list-style: none; padding: 0; }
.bullets li {
  padding: 0.55rem 0 0.55rem 1.6rem;
  position: relative;
}
.bullets li::before {
  content: "✓";
  position: absolute; left: 0; top: 0.55rem;
  color: var(--color-accent); font-weight: 700;
}

/* Reviews */
.reviews { background: var(--color-bg-alt); }
.reviews-heading { margin-bottom: 0.5rem; }
.reviews-subline { display: flex; align-items: center; gap: 0.5rem; font-weight: 600; margin-top: -0.5rem; }
.reviews-marquee { display: flex; overflow: hidden; gap: 1rem; }
.reviews-grid {
  display: grid; grid-template-columns: repeat(auto-fill, minmax(17rem, 1fr));
  gap: 1.4rem; margin-top: 1.4rem;
}
.marquee-track { display: flex; gap: 1rem; flex: none; }
.reviews-marquee .marquee-track { animation: marquee 40s linear infinite; }
.reviews-marquee:hover .marquee-track,
.reviews-marquee:focus-within .marquee-track,
.reviews-marquee:focus .marquee-track { animation-play-state: paused; }
.reviews-marquee .review-card { width: 20rem; flex: none; }
@keyframes marquee { from { transform: translateX(0); } to { transform: translateX(calc(-100% - 1rem)); } }
@media (prefers-reduced-motion: reduce) {
  .reviews-marquee { overflow-x: auto; }
  .reviews-marquee .marquee-track { animation: none; }
  .reviews-marquee .marquee-track[aria-hidden='true'] { display: none; }
}
.review-card {
  margin: 0; padding: 1.3rem 1.4rem;
  background: var(--color-bg);
  border-radius: calc(var(--radius, 10px) + 4px);
  box-shadow: 0 2px 12px rgba(15, 23, 42, 0.06);
}
.stars { color: var(--color-accent); letter-spacing: 2px; display: block; margin-bottom: 0.5rem; }
.review-card footer { display: flex; align-items: center; gap: 0.6rem; margin-top: 0.8rem; font-size: 0.92rem; color: var(--color-body); }
.review-who { display: flex; align-items: center; gap: 0.6rem; }
.review-card cite { font-style: normal; font-weight: 600; }
.avatar {
  width: 2.2rem; height: 2.2rem; border-radius: 50%; flex: none;
  display: inline-flex; align-items: center; justify-content: center;
  background: color-mix(in srgb, var(--color-accent) 14%, var(--color-bg));
  color: var(--color-accent); font-weight: 700; font-size: 0.8rem;
}
.review-source-icon { width: 18px; height: 18px; flex: none; }
.review-source { display: block; font-size: 0.78rem; color: var(--color-body-alt); }

/* FAQ */
.faq {
  border-bottom: 1px solid var(--color-border);
  padding: 0.35rem 0;
}
.faq summary {
  cursor: pointer; font-weight: 600; color: var(--color-heading);
  padding: 0.6rem 0; list-style-position: outside;
}
.faq p { padding: 0.15rem 0 0.75rem; }

/* CTA band */
.cta-band {
  background: var(--color-bg-dark);
  color: var(--color-body-alt);
  text-align: center;
}
.cta-band h2 { color: var(--color-heading-alt); }
.cta-band p { max-width: 40rem; margin-inline: auto; }
.cta-actions { margin-top: 1.6rem; display: flex; gap: 1rem; justify-content: center; flex-wrap: wrap; }

/* Contact */
.contact-grid {
  display: grid; grid-template-columns: 1.2fr 1fr; gap: 3rem; align-items: start;
}
.hours-card {
  background: var(--color-bg-alt);
  border: 1px solid var(--color-border);
  border-radius: var(--radius, 10px);
  padding: 1.5rem 1.75rem;
}
.hours-table { width: 100%; border-collapse: collapse; }
.hours-table th { text-align: left; font-weight: 600; color: var(--color-heading); padding: 0.4rem 0; }
.hours-table td { text-align: right; padding: 0.4rem 0; }
.contact-phone { margin: 1.5rem 0; }

/* Footer -- REMOVED (was: dark "ink" .site-footer/.footer-grid rules from the
 * pre-ocf-lightning V1 footer). footer.php now renders the ocf-lightning
 * footer exclusively (assets/components/footer.css), whose markup uses
 * `.footer-heading` / `.footer-brand-name` -- different names from this old
 * block's `.footer-head` / `.footer-brand`, which render nothing today.
 *
 * The two names this block DID still share with the current markup --
 * `.site-footer` and `.footer-grid` -- were the bug: base.css loads after
 * assets/components/footer.css (see functions.php's oneclick_assets()), so at
 * equal specificity this dark background silently won the cascade over
 * footer.css's light one, while footer.css's `.footer-heading` /
 * `.footer-brand-name` kept their light-background heading color -- dark text
 * on a dark ground. the reference product's own reference footer is light
 * (docs/compare-2026-08-27/the reference product/bayfront-home-1.png), matching
 * footer.css's design, so the fix is deleting this dead override rather than
 * repainting it.
 *
 * This mirrors commit 1bd8d16 (2026-08-27), which removed the identical
 * block from wp-theme/oneclick/assets/base.css but not from this shared
 * source -- tools/wp_deploy.py's stage_assets() copies THIS file over the
 * theme's copy on every push, so the removal there was silently reverted on
 * the next provision. Fixing it here is the durable fix; see
 * docs/verification-2026-08-31/t2-t3-comparison.md top finding #1/#2 class
 * of bug (root cause shared with the nav-dropdown fix below). */

/* Legal pages */
.legal p { max-width: 44rem; }

/* Mobile */
@media (max-width: 820px) {
  .site-nav {
    display: none;
    position: absolute; top: 4.25rem; left: 0; right: 0;
    background: var(--color-bg);
    border-bottom: 1px solid var(--color-border);
    flex-direction: column; gap: 0;
    padding: 0.5rem 1.25rem 1rem;
  }
  .site-nav.open { display: flex; }
  .site-nav a { padding: 0.6rem 0; }
  .nav-toggle { display: block; }
  .phone-link { display: none; }
  .header-actions .btn-primary { padding: 0.5em 0.9em; font-size: 0.92rem; white-space: nowrap; }
  .contact-grid { grid-template-columns: 1fr; gap: 2rem; }
}

/* Trust bar — stat-strip style: dark band, accent hairline, spaced caps */
.trustbar {
  background: var(--color-bg-dark);
  border-top: 2px solid var(--color-accent);
  padding: 0.85rem 0;
}
.trustbar-row { display: flex; flex-wrap: wrap; gap: 0.5rem 0; justify-content: center; }
.trustbar-item {
  color: var(--color-body-alt); font-weight: 600; font-size: 0.9rem;
  letter-spacing: 0.02em;
  display: flex; align-items: center; gap: 0.5rem;
  padding: 0 1.4rem;
}
.trustbar-item + .trustbar-item { border-left: 1px solid color-mix(in srgb, var(--color-body-alt) 25%, transparent); }
.trustbar-item::before { content: "✓"; color: var(--color-accent); font-weight: 700; }
@media (max-width: 640px) {
  .trustbar-item + .trustbar-item { border-left: 0; }
  .trustbar-row { gap: 0.4rem 0; flex-direction: column; align-items: center; }
}

/* Why us */
.whyus-grid { display: grid; grid-template-columns: 1.2fr 1fr; gap: 2.5rem; align-items: center; }
.whyus-bullets { list-style: none; padding: 0; margin-top: 1rem; }
.whyus-bullets li { padding: 0.4rem 0 0.4rem 1.6rem; position: relative; }
.whyus-bullets li::before {
  content: "✓"; position: absolute; left: 0; top: 0.4rem;
  color: var(--color-accent); font-weight: 700;
}
.whyus-img { border-radius: var(--radius, 10px); aspect-ratio: 4 / 3; object-fit: cover; width: 100%; }
.whyus-img-placeholder { background: linear-gradient(135deg, var(--color-accent), var(--color-secondary)); opacity: 0.85; }

/* Calc embed — glow-border frame (accent-to-secondary gradient ring) */
.calc-embed { background: var(--color-bg-alt); text-align: center; }
.calc-embed .section-intro { margin-inline: auto; }
.calc-frame-wrap {
  padding: 3px;
  background: linear-gradient(120deg, var(--color-accent), var(--color-secondary));
  border-radius: calc(var(--radius, 10px) + 3px);
  box-shadow: 0 10px 38px color-mix(in srgb, var(--color-accent) 22%, transparent);
  max-width: 56rem; margin-inline: auto;
}
.calc-frame-wrap iframe {
  display: block; width: 100%; height: 640px; border: 0;
  border-radius: var(--radius, 10px);
  background: var(--color-bg);
}
.calc-fallback { margin-top: 1rem; text-align: center; color: var(--color-body); }

/* Gallery — quiet hover zoom, contained */
.gallery-grid { display: grid; grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr)); gap: 0.9rem; margin-top: 1.4rem; }
.gallery-grid figure {
  margin: 0; overflow: hidden; border-radius: var(--radius, 8px);
  border: 1px solid var(--color-border);
}
.gallery-grid img {
  aspect-ratio: 4 / 3; object-fit: cover; width: 100%;
  transition: transform 0.3s ease;
}
.gallery-grid figure:hover img { transform: scale(1.04); }

/* Credentials — pill badges with quiet hover lift */
.credentials { background: var(--color-bg-alt); text-align: center; }
.credentials .section-intro { margin-inline: auto; }
.badge-row { display: flex; flex-wrap: wrap; gap: 0.7rem; margin-top: 1.4rem; justify-content: center; }
.badge {
  border: 1px solid var(--color-border); border-radius: var(--radius-full);
  padding: 0.5rem 1.25rem; font-weight: 600; font-size: 0.92rem;
  color: var(--color-heading); background: var(--color-bg);
  display: inline-flex; align-items: center; gap: 0.5rem;
  transition: border-color 0.15s, transform 0.15s, box-shadow 0.15s;
}
.badge::before { content: "✦"; color: var(--color-accent); }
.badge:hover {
  border-color: var(--color-accent);
  transform: translateY(-1px);
  box-shadow: 0 4px 14px color-mix(in srgb, var(--color-accent) 18%, transparent);
}

/* Financing — accent-edge card */
.financing .container-narrow {
  border: 1px solid var(--color-border);
  border-left: 4px solid var(--color-accent);
  border-radius: var(--radius, 10px);
  background: var(--color-bg);
  padding: 1.75rem 2rem;
}
.financing-partner { border-top: 1px solid var(--color-border); padding-top: 0.9rem; color: var(--color-body); margin-bottom: 0; }

@media (max-width: 820px) {
  .whyus-grid { grid-template-columns: 1fr; }
  .calc-frame-wrap iframe { height: 560px; }
}

/* Hero proof elements */
.hero-badge {
  display: inline-flex; align-items: center; gap: 0.5em;
  border-radius: var(--radius-full); padding: 7px 16px; font-size: 0.9rem;
  background: color-mix(in srgb, var(--color-heading) 6%, transparent);
  border: 1px solid color-mix(in srgb, var(--color-heading) 16%, transparent);
  margin-bottom: 1rem;
  color: var(--color-heading);
}
.hero-stats { display: flex; flex-wrap: wrap; gap: 1rem; margin-top: 2rem; }
.stat-tile {
  border: 1px solid color-mix(in srgb, var(--color-heading) 18%, transparent);
  border-radius: var(--radius); padding: 0.9rem 1.4rem; min-width: 7.5rem;
  color: var(--color-heading);
}
.stat-value { font-size: 1.6rem; font-weight: 800; font-family: var(--font-heading); }
.stat-suffix { font-size: 1.2rem; font-weight: 700; }
.stat-label { display: block; font-size: 0.72rem; letter-spacing: 0.08em; text-transform: uppercase; opacity: 0.75; margin-top: 0.15rem; }
.btn-glass {
  background: color-mix(in srgb, var(--color-heading) 6%, transparent);
  color: var(--color-heading);
  border: 1px solid color-mix(in srgb, var(--color-heading) 20%, transparent);
}
/* Breadcrumbs */
.breadcrumbs { font-size: 0.85rem; margin-bottom: 1rem; opacity: 0.85; }
.breadcrumbs ol { list-style: none; display: flex; flex-wrap: wrap; gap: 0.4em; padding: 0; margin: 0; }
.breadcrumbs li + li::before { content: '→'; margin-right: 0.4em; opacity: 0.6; }
.breadcrumbs a { color: inherit; text-decoration: none; }
.breadcrumbs a:hover { text-decoration: underline; }

.btn-glass:hover { background: color-mix(in srgb, var(--color-heading) 12%, transparent); }
.h1-accent { color: inherit; } /* skins recolor; base is a no-op */

/* hero-image applies a dark scrim over the photo (see above) — glass chrome
   needs the light-ground treatment there regardless of skin. */
.hero-image .hero-badge {
  background: color-mix(in srgb, var(--color-heading-alt) 8%, transparent);
  border-color: color-mix(in srgb, var(--color-heading-alt) 12%, transparent);
  color: var(--color-heading-alt);
}
.hero-image .stat-tile {
  border-color: color-mix(in srgb, var(--color-heading-alt) 14%, transparent);
  color: var(--color-heading-alt);
}
.hero-image .btn-glass {
  background: rgba(255, 255, 255, 0.08); color: var(--color-heading-alt);
  border: 1px solid rgba(255, 255, 255, 0.12);
}
.hero-image .btn-glass:hover { background: rgba(255, 255, 255, 0.14); }
/* Service-area heroes can carry both hero-compact and hero-image at once
   (see [slug].astro), so the credential line needs a photo-ground variant
   too: heading-alt, not heading, since heading reads dark on the ink scrim. */
.hero-image .hero-cred { color: var(--color-heading-alt); }

/* Hail stats + coverage card + area hero credential line */
.hail-tiles { display: flex; gap: 1rem; flex-wrap: wrap; }
.hail-source { font-size: 0.78rem; color: var(--color-body-alt); margin-top: 0.8rem; }
.storm-recent { margin-top: 1rem; font-weight: 500; }
/* Informational text (18px/600, below the large-text threshold) needs 4.5:1.
   derive_palette only guarantees --color-accent at 3:1 against bg, so it
   fails AA here in several presets. --color-heading is contract-guaranteed
   at 4.5:1 against bg_alt, which is what this text sits on when the area
   has no photo (see .hero-image override below for the photo case). */
.hero-cred { font-weight: 600; color: var(--color-heading); margin-top: 0.4rem; }
.coverage-card {
  background: var(--color-bg); border: 1px solid rgba(15, 23, 42, 0.06);
  border-radius: var(--card-radius); box-shadow: 0 2px 12px rgba(15, 23, 42, 0.05);
  padding: 2rem 2.2rem;
}
.chip-label {
  font-size: 0.78rem; font-weight: 600; color: var(--color-body-alt);
  text-transform: uppercase; letter-spacing: 0.08em; margin: 1.2rem 0 0.5rem;
}
.chip-list { display: flex; flex-wrap: wrap; gap: 0.5rem; list-style: none; padding: 0; margin: 0; }
.chip {
  border-radius: var(--radius-full); border: 1.5px solid rgba(15, 23, 42, 0.1);
  padding: 6px 14px; font-size: 0.82rem; font-weight: 500; color: var(--color-body);
}

/* Sticky bottom CTA (mobile) */
.sticky-cta {
  position: fixed; inset: auto 0 0 0; z-index: 60;
  display: flex; align-items: center; gap: 0.6rem;
  padding: 0.6rem 1rem calc(0.6rem + env(safe-area-inset-bottom));
  background: color-mix(in srgb, var(--color-bg-dark) 82%, transparent);
  -webkit-backdrop-filter: blur(24px); backdrop-filter: blur(24px);
  color: var(--color-heading-alt);
}
.sticky-cta .btn { padding: 0.55rem 1rem; font-size: 0.9rem; }
.sticky-cta-place { font-size: 0.82rem; margin-right: auto; }
@supports not (backdrop-filter: blur(1px)) { .sticky-cta { background: var(--color-bg-dark); } }
@media (min-width: 768px) { .sticky-cta { display: none; } }
@media (max-width: 767px) { .has-sticky-cta { padding-bottom: 3.6rem; } }

/* enhance.js hooks — every hiding rule REQUIRES html.js */
html.js [data-reveal] { opacity: 0; transform: translateY(10px); transition: opacity 0.5s ease, transform 0.5s ease; }
html.js [data-reveal].revealed { opacity: 1; transform: none; }
html.js .sticky-cta-armed { transform: translateY(110%); transition: transform 0.3s ease; }
html.js .sticky-cta-armed.sticky-cta-shown { transform: none; }
@media (prefers-reduced-motion: reduce) {
  html.js [data-reveal] { opacity: 1; transform: none; transition: none; }
  html.js .sticky-cta-armed { transform: none; }
}

/* Lead form — the one interactive element on the site, so it has to look
   deliberate rather than like raw browser defaults. Token-driven so every skin
   restyles it for free. Field grouping (the two-up rows) lives in
   components/ContactForm.astro; this is the shared field look. */
.lead-form-section { background: var(--color-bg-alt); }
.contact-form {
  display: grid;
  gap: 1rem;
  background: var(--color-bg);
  border: 1px solid var(--color-border);
  border-radius: var(--radius, 10px);
  padding: 1.75rem;
  box-shadow: 0 6px 24px rgba(15, 23, 42, 0.06);
}
.contact-form label {
  display: grid;
  gap: 0.35rem;
  font-weight: 600;
  font-size: 0.92rem;
  color: var(--color-heading);
}
.contact-form input,
.contact-form textarea {
  font: inherit;
  font-weight: 400;
  color: var(--color-body);
  background: var(--color-bg);
  border: 1px solid var(--color-border);
  border-radius: calc(var(--radius, 10px) * 0.6);
  padding: 0.65rem 0.8rem;
  width: 100%;
  transition: border-color 0.15s, box-shadow 0.15s;
}
.contact-form input:focus-visible,
.contact-form textarea:focus-visible {
  outline: none;
  border-color: var(--color-accent);
  box-shadow: 0 0 0 3px color-mix(in srgb, var(--color-accent) 22%, transparent);
}
.contact-form textarea { resize: vertical; min-height: 6rem; }
.contact-form button[type="submit"] { justify-self: start; }
.contact-form button[disabled] { opacity: 0.6; cursor: progress; }
.contact-form .form-status { margin: 0; font-size: 0.92rem; color: var(--color-body); }
.contact-form-intro { margin: 0; color: var(--color-body); font-weight: 400; }

/* ===================================================================
   Global chrome — the reference product V1 parity, Phase A. WORDPRESS OUTPUT ONLY.

   This stylesheet is shared byte-for-byte with the WordPress theme
   (tools/wp_deploy.py stage_assets copies this file over
   wp-theme/oneclick/assets/base.css), but the two headers and footers are
   different markup: Astro's nav is bare <a> children with the burger inside
   .header-actions and a 4-column auto-fit footer; WordPress's is ul/li with
   CPT dropdowns and a fixed 3-column footer.

   So every rule below that reuses a shared class name (.site-header,
   .header-row, .cta-band, .footer-grid, .site-footer, .nav-toggle,
   .header-actions) is scoped to a WordPress-only modifier — `--v1` on the
   header, band and footer elements. Rules whose selectors are WordPress-only
   to begin with (.nav-list, .nav-dropdown, .footer-col, .footer-map …) need no
   scope: they match nothing in the Astro DOM.

   Colour comes entirely from tokens.css (generated per site); nothing here
   hardcodes a palette value beyond neutral shadow/scrim alphas.
   =================================================================== */

.screen-reader-text {
  position: absolute; width: 1px; height: 1px;
  margin: -1px; padding: 0; overflow: hidden;
  clip: rect(0 0 0 0); clip-path: inset(50%);
  white-space: nowrap; border: 0;
}

/* ---- Header shell ---- */
.site-header--v1 {
  position: sticky; top: 0; z-index: 60;
  background: var(--color-bg);
  border-bottom: 1px solid var(--color-border);
  transition: transform 0.28s ease, box-shadow 0.2s ease;
  will-change: transform;
}
.site-header--v1.site-header--stuck { box-shadow: 0 6px 24px rgba(15, 23, 42, 0.08); }
/* Slide-away is only ever applied by chrome.js, so a no-JS visitor keeps a
   permanently visible bar rather than one that can get stuck off-screen. */
.site-header--v1.site-header--hidden { transform: translateY(-100%); }
@media (prefers-reduced-motion: reduce) {
  .site-header--v1 { transition: none; }
  .site-header--v1.site-header--hidden { transform: none; }
}

.site-header--v1 .header-row {
  display: flex; align-items: center; gap: 1.25rem;
  min-height: 4.5rem;
  border-radius: calc(var(--radius, 10px) + 6px);
}
.site-header--v1 .brand { flex-shrink: 0; display: flex; align-items: center; }
.site-header--v1 .wordmark { display: inline-flex; align-items: center; }

/* ---- Nav -- REMOVED (was: unscoped .nav-list/.nav-item/.nav-dropdown*
 * rules for the pre-ocf-lightning V1 header). This file's own header
 * comment claimed ".nav-* selectors are WP-only" and therefore needed no
 * `--v1` scope -- true when this was written, false since the ocf-lightning
 * header migration (header.php) reused the bare name `.nav-dropdown` for a
 * DIFFERENT element: the Services item's wrapper <div>, not the V1 dropdown
 * PANEL this block styled.
 *
 * base.css loads after assets/components/header.css (see functions.php's
 * oneclick_assets()), so `html.js-chrome .nav-dropdown { display: none; }`
 * above always won and hid the Services item outright -- chrome.js adds
 * `js-chrome` to <html> unconditionally, and the only rules that undid the
 * `display: none` required `.nav-item-has-dropdown`/`.nav-dropdown-toggle`,
 * classes the current header never renders. Confirmed live: the Services
 * item's HTML was always present and correct; it was invisible in any
 * JS-enabled browser. The properly `.site-header--v1`-scoped copies of this
 * same block further down (mobile breakpoint) are untouched -- they only
 * match inside the V1 header, which the current header never carries.
 *
 * This mirrors commit 1bd8d16 (2026-08-27), which removed the identical
 * block from wp-theme/oneclick/assets/base.css but not from this shared
 * source -- tools/wp_deploy.py's stage_assets() copies THIS file over the
 * theme's copy on every push, so the removal there was silently reverted on
 * the next provision (confirmed live on the T3/professional build in
 * docs/verification-2026-08-31/t2-t3-comparison.md, top finding #1). No
 * Astro component ever rendered `.nav-dropdown` / `.nav-item-has-dropdown`
 * (grepped site-template/src for both -- zero matches), so this block was
 * always dead weight on the Astro side too. */

.site-header--v1 .header-actions { gap: 0.6rem; flex-shrink: 0; }
.site-header--v1 .header-actions .btn { padding: 0.55em 1.1em; font-size: 0.95rem; white-space: nowrap; }
.btn-phone { font-variant-numeric: tabular-nums; }
/* WordPress puts the burger outside .header-actions, so it needs its own
   ordering; Astro's sits inside and is left alone. */
.site-header--v1 .nav-toggle { order: 3; cursor: pointer; }

/* ---- Header, mobile. Breakpoint matches the shared .site-nav panel rules
        above (820px), which already supply the off-canvas positioning,
        `display: none` / `.open { display: flex }` and the burger reveal —
        those stay untouched because the Astro header depends on them. ---- */
@media (max-width: 820px) {
  .site-header--v1 .header-row { gap: 0.75rem; }
  /* 4.5rem bar, not the shared rule's 4.25rem. */
  .site-header--v1 .site-nav { top: 100%; max-height: calc(100vh - 4.5rem); overflow-y: auto; }
  .site-header--v1 .nav-list { flex-direction: column; align-items: stretch; gap: 0; width: 100%; }
  .site-header--v1 .nav-item { flex-wrap: wrap; border-bottom: 1px solid var(--color-border); }
  .site-header--v1 .nav-item > a { flex: 1; padding: 0.75rem 0; }
  .site-header--v1 .nav-dropdown-toggle { padding: 0.75rem 0.5rem; }
  /* On mobile the dropdown is an in-flow disclosure, not a hover overlay. */
  html.js-chrome .site-header--v1 .nav-dropdown {
    position: static; width: 100%;
    border: 0; box-shadow: none; background: transparent;
    padding: 0 0 0.5rem 0.75rem;
  }
  html.js-chrome .site-header--v1 .nav-item-has-dropdown:hover .nav-dropdown { display: none; }
  html.js-chrome .site-header--v1 .nav-dropdown-toggle[aria-expanded="true"] + .nav-dropdown { display: block; }
  .site-header--v1 .nav-dropdown a { padding: 0.5rem 0.75rem; }
}
@media (max-width: 767px) {
  .site-header--v1 .header-actions .btn-phone { display: none; }
  .site-header--v1 .header-actions .btn { padding: 0.5em 0.9em; font-size: 0.9rem; }
}

/* ---- Sitewide CTA band (V1 bde-section-85-163) ----
   Scoped: Astro's CtaBand.astro reuses .cta-band for a centred one-column
   band with .cta-actions, which must keep the base rules above. */
.cta-band--v1 { text-align: left; position: relative; }
.cta-band-grid {
  display: grid; grid-template-columns: 1.6fr 1fr;
  gap: 2rem; align-items: center;
}
.cta-band-copy h2 { color: var(--color-heading-alt); margin-bottom: 0.4em; }
.cta-band-copy p { max-width: 46rem; margin: 0; }
.cta-band-action { justify-self: end; }
@media (max-width: 767px) {
  .cta-band--v1 { text-align: center; }
  .cta-band-grid { grid-template-columns: 1fr; gap: 1.5rem; }
  .cta-band-copy p { margin-inline: auto; }
  .cta-band-action { justify-self: center; }
}

/* ---- Footer (V1 bde-section-85-134) ----
   Scoped: Astro's footer reuses .site-footer / .footer-grid for a 4-column
   auto-fit grid (brand / Contact / Services / Service Areas). */
.site-footer--v1 { padding: clamp(2.5rem, 6vw, 4rem) 0 1.25rem; }
.footer-grid--v1 {
  grid-template-columns: 1.4fr 1fr 1.2fr;
  gap: 2.5rem;
  align-items: start;
}
.footer-col-brand .footer-brand { display: inline-flex; align-items: center; margin-bottom: 0.75rem; }
.site-footer--v1 .footer-blurb { font-size: 0.95rem; max-width: 26rem; }
.site-footer--v1 .footer-hours { margin-top: 1rem; }
.footer-hours-line { padding: 0.12rem 0; }

.site-footer--v1 .footer-head { font-size: 1.05rem; }
.footer-contact-list { list-style: none; padding: 0; margin: 0; }
.footer-contact-list li { margin: 0.35rem 0; }
.footer-contact-list a { display: flex; align-items: flex-start; gap: 0.55rem; }
.footer-icon { width: 18px; height: 18px; flex: none; margin-top: 0.2em; color: var(--color-accent); }

.footer-map {
  margin-top: 1rem;
  aspect-ratio: 4 / 3;
  border-radius: calc(var(--radius, 10px) + 2px);
  overflow: hidden;
  background: color-mix(in srgb, var(--color-heading-alt) 8%, transparent);
}
.footer-map iframe { display: block; width: 100%; height: 100%; border: 0; }

.footer-legal-links { display: flex; gap: 1.25rem; flex-wrap: wrap; }

@media (max-width: 900px) {
  .footer-grid--v1 { grid-template-columns: 1fr 1fr; }
  .footer-grid--v1 .footer-col-contact { grid-column: 1 / -1; }
  .footer-map { max-width: 26rem; }
}
@media (max-width: 767px) {
  .footer-grid--v1 { grid-template-columns: 1fr; gap: 2rem; }
  .footer-grid--v1 .footer-col-contact { grid-column: auto; }
  .site-footer--v1 .footer-legal { justify-content: flex-start; }
}

/* ===================================================================
   HOME V1 SPINE (WordPress theme only) — Phase B
   ===================================================================
   The 8-section homepage from the reference product V1 master: hero,
   icon strip, about teaser, services, testimonials, map + areas,
   promise, FAQ (v1-template-catalog-2026-08-15.md §4 HOME).

   Scope, for the same reason the chrome block above is scoped: this
   file is shared byte-for-byte with the Astro build, whose homepage is
   different markup. Everything here sits under `.home-v1` (the wrapper
   front-page.php puts around its sections) or carries a `--v1` suffix,
   so none of it can reach the Astro DOM. Colour is tokens only.
   =================================================================== */

/* Shared 2-column figure/copy layout: about teaser, map + areas,
   promise, FAQ. One geometry, four sections, so they line up. */
.split-grid--v1 {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: clamp(1.75rem, 4vw, 3.25rem);
  align-items: center;
}
.split-grid--single { grid-template-columns: 1fr; max-width: 46rem; }
.split-media--v1 {
  border-radius: calc(var(--radius, 10px) + 6px);
  overflow: hidden;
  background: var(--color-bg-alt);
}
.split-media--v1 img { width: 100%; aspect-ratio: 4 / 3; object-fit: cover; }
.split-copy--v1 > :last-child { margin-bottom: 0; }
.split-action--v1 { margin: 1.5rem 0 0; }

/* Outline buttons live on light section backgrounds throughout the
   homepage; the base .btn-outline is drawn for dark heroes. */
.home-v1 .btn-outline { border-color: var(--color-heading); color: var(--color-heading); }
.home-v1 .btn-outline:hover { background: var(--color-heading); color: var(--color-bg); }

/* Icon checklists / promise list: one tick or glyph per row. */
.tick-list--v1,
.promise-list--v1 { list-style: none; padding: 0; margin: 1.25rem 0 0; }
.tick-list--v1 li,
.promise-list--v1 li { display: flex; gap: 0.65rem; align-items: flex-start; padding: 0.3rem 0; }
.tick-list--v1 .oc-icon,
.promise-list--v1 .oc-icon { width: 20px; height: 20px; flex: none; margin-top: 0.25em; color: var(--color-accent); }
.promise-list--v1 { display: grid; grid-template-columns: 1fr 1fr; gap: 0.75rem 1.5rem; }
.promise-list--v1 strong { display: block; color: var(--color-heading); }
.promise-list-text { display: block; font-size: 0.93rem; color: var(--color-body); }

/* Text-style link with a trailing arrow (V1's FAQ "Contact Us"). */
.text-link--v1 {
  display: inline-flex; align-items: center; gap: 0.4rem;
  font-weight: 600; color: var(--color-accent);
}
.text-link--v1 .oc-icon { width: 18px; height: 18px; transition: transform 0.15s ease; }
.text-link--v1:hover .oc-icon { transform: translateX(3px); }

/* ---- 2. Icon strip (V1 global block 2966) ---- */
.icon-strip--v1 { padding-top: clamp(2rem, 4vw, 3rem); padding-bottom: clamp(2rem, 4vw, 3rem); }
.icon-strip-grid {
  display: grid; grid-template-columns: repeat(3, 1fr);
  gap: 1.25rem;
}
.icon-box--v1 {
  background: var(--color-bg);
  border: 1px solid var(--color-border);
  border-radius: calc(var(--radius, 10px) + 4px);
  padding: 1.5rem;
  box-shadow: 0 10px 30px rgba(15, 23, 42, 0.08);
}
.icon-box-badge {
  display: inline-flex; align-items: center; justify-content: center;
  width: 2.75rem; height: 2.75rem; margin-bottom: 0.9rem;
  border-radius: 50%;
  background: color-mix(in srgb, var(--color-accent) 12%, transparent);
  color: var(--color-accent);
}
.icon-box-badge .oc-icon { width: 24px; height: 24px; }
.icon-box-title { font-size: 1.1rem; margin-bottom: 0.35em; }
.icon-box--v1 p { margin: 0; color: var(--color-body); font-size: 0.97rem; }

/* ---- 3. About teaser (3018) ---- */
.about-teaser--v1 { background: var(--color-bg); }

/* ---- 4. Services teaser (3021) ---- */
.services--v1 { background: var(--color-bg-alt); text-align: center; }
.section-head--v1 { max-width: 46rem; margin: 0 auto 2rem; }
.section-head--v1 .section-intro { margin: 0 auto; }
.services--v1 .card { text-align: left; }
.section-actions--v1 {
  margin-top: 2rem; display: flex; gap: 1rem;
  justify-content: center; flex-wrap: wrap;
}

/* ---- 5. Testimonials (2964) ---- */
.testimonials--v1 { background: var(--color-bg); }
.testimonials-head--v1 {
  display: flex; align-items: center; justify-content: space-between;
  gap: 1.5rem; margin-bottom: 1.75rem;
}
.testimonials-head--v1 h2 { margin: 0; }
.testimonials-quote--v1 { color: var(--color-accent); opacity: 0.25; flex: none; }
.testimonials-quote--v1 .oc-icon { width: 56px; height: 56px; }

.tst-slider { position: relative; }
/* Without JS this is the whole component: a snapping, swipeable,
   keyboard-scrollable row of every review. home.js only adds buttons. */
.tst-track {
  display: flex; gap: 1.25rem;
  list-style: none; margin: 0; padding: 0 0 0.5rem;
  overflow-x: auto;
  scroll-snap-type: x mandatory;
  scrollbar-width: thin;
}
.tst-slide { flex: 0 0 calc((100% - 2.5rem) / 3); scroll-snap-align: start; }
.tst-card {
  height: 100%; margin: 0;
  background: var(--color-bg);
  border: 1px solid var(--color-border);
  border-radius: calc(var(--radius, 10px) + 4px);
  padding: 1.5rem;
  box-shadow: 0 10px 30px rgba(15, 23, 42, 0.07);
}
.oc-stars { display: flex; gap: 0.15rem; color: #f5b400; margin-bottom: 0.75rem; }
.oc-stars .oc-icon { width: 18px; height: 18px; }
.tst-card blockquote { margin: 0; }
.tst-card blockquote p { margin: 0; color: var(--color-body); }
.tst-card figcaption { margin-top: 0.9rem; font-weight: 600; color: var(--color-heading); }

/* Controls appear only once home.js has taken charge of the track. */
.tst-controls { display: none; gap: 0.5rem; justify-content: flex-end; margin-top: 1rem; }
.tst-slider.tst-ready .tst-controls { display: flex; }
.tst-btn {
  display: inline-flex; align-items: center; justify-content: center;
  width: 2.5rem; height: 2.5rem;
  background: var(--color-bg);
  border: 1px solid var(--color-border);
  border-radius: 50%;
  color: var(--color-heading);
  cursor: pointer;
}
.tst-btn:hover { border-color: var(--color-accent); color: var(--color-accent); }
.tst-btn .oc-icon { width: 18px; height: 18px; }

/* ---- 6. Map + areas (3097) ---- */
.map-areas--v1 { background: var(--color-bg-alt); }
.map-frame--v1 { aspect-ratio: 4 / 3; }
.map-frame--v1 iframe { display: block; width: 100%; height: 100%; border: 0; }
.map-areas--v1 .area-links { margin-top: 1.25rem; }

/* ---- 7. Promise (3027) ---- */
.promise--v1 { background: var(--color-bg); }

/* ---- 8. FAQ (3028) ---- */
.faq--v1 { background: var(--color-bg-alt); }
.faq-grid--v1 { align-items: start; grid-template-columns: 1fr 1.2fr; }
.faq-list--v1 {
  background: var(--color-bg);
  border: 1px solid var(--color-border);
  border-radius: calc(var(--radius, 10px) + 4px);
  padding: 0.35rem 1.25rem;
}
.faq-item--v1 + .faq-item--v1 { border-top: 1px solid var(--color-border); }
.faq-item--v1 summary {
  cursor: pointer; font-weight: 600; color: var(--color-heading);
  padding: 1rem 0; list-style: none;
}
.faq-item--v1 summary::-webkit-details-marker { display: none; }
.faq-item--v1 summary::after {
  content: "+"; float: right; margin-left: 1rem;
  color: var(--color-accent); font-weight: 700;
}
.faq-item--v1[open] summary::after { content: "–"; }
.faq-item--v1 p { margin: 0 0 1rem; color: var(--color-body); }

/* ---- Responsive (matches the Phase A chrome breakpoints) ---- */
@media (max-width: 900px) {
  .tst-slide { flex-basis: calc((100% - 1.25rem) / 2); }
}
@media (max-width: 820px) {
  .split-grid--v1,
  .faq-grid--v1 { grid-template-columns: 1fr; }
  .icon-strip-grid { grid-template-columns: 1fr; }
  .promise-list--v1 { grid-template-columns: 1fr; }
  .tst-slide { flex-basis: 100%; }
  .testimonials-head--v1 { align-items: flex-start; }
  .testimonials-quote--v1 .oc-icon { width: 40px; height: 40px; }
  /* Photo below copy on the about teaser, above nothing else: source
     order already puts the map and the promise photo where they belong. */
  .about-teaser--v1 .split-media--v1 { order: 2; }
}

/* ===================================================================
   INNER PAGES V1 (WordPress theme only) — Phase C
   ===================================================================
   Every fixed page past the homepage, to the reference product V1 master:
   about, both hubs, gallery, blog index, blog single, contact,
   thank-you, legal (v1-template-catalog-2026-08-15.md §4).

   Same scope discipline as the Phase A chrome and Phase B home blocks
   above, and for the same reason: this file is shared byte-for-byte
   with the Astro build (tools/wp_deploy.py stage_assets copies it over
   wp-theme/oneclick/assets/base.css), whose inner pages are different
   markup. Everything here sits under `.page-v1` — the wrapper each
   Phase C template puts around its sections — or carries a `--v1`
   suffix, so none of it can reach the Astro DOM.

   Colour is tokens only. Breakpoint is 820px, matching the chrome.
   =================================================================== */

/* ---- Shared: the inner-page hero (parts/page-hero.php) ---- */
.page-hero--v1 .hero-badge { margin-inline: auto; }
.hero-meta--v1 {
  display: inline-flex; align-items: center; gap: 0.45rem;
  margin: 0.9rem 0 0; color: var(--color-body); font-size: 0.95rem;
}
.hero-meta--v1 .oc-icon { width: 18px; height: 18px; color: var(--color-accent); }

/* Outline buttons sit on light section backgrounds throughout the inner
   pages; the base .btn-outline is drawn for dark heroes. Same override
   the .home-v1 wrapper makes. */
.page-v1 .btn-outline { border-color: var(--color-heading); color: var(--color-heading); }
.page-v1 .btn-outline:hover { background: var(--color-heading); color: var(--color-bg); }

/* Anchor targets clear the sticky header (blog single TOC jumps). */
.page-v1 [id] { scroll-margin-top: 6rem; }
@media (prefers-reduced-motion: no-preference) {
  html:has(.post-v1) { scroll-behavior: smooth; }
}

/* ---- ABOUT article (V1 bde-section-151-328) ---- */
.about-article--v1 { background: var(--color-bg); }
.about-grid--v1 {
  display: grid;
  grid-template-columns: minmax(0, 1.7fr) minmax(0, 1fr);
  gap: clamp(2rem, 5vw, 3.5rem);
  align-items: start;
}
.about-body--v1 > :first-child { margin-top: 0; }
.about-body--v1 h2 { margin-top: 2rem; }
.about-body--v1 p { max-width: 42rem; }

.about-aside--v1 { position: sticky; top: 6rem; }
.sidebar-card--v1 {
  background: var(--color-bg);
  border: 1px solid var(--color-border);
  border-radius: calc(var(--radius, 10px) + 6px);
  overflow: hidden;
  box-shadow: 0 12px 34px rgba(15, 23, 42, 0.09);
}
.sidebar-card-photo--v1 { display: block; width: 100%; aspect-ratio: 4 / 3; object-fit: cover; }
.sidebar-card-body--v1 { padding: 1.5rem; }
.sidebar-card-body--v1 h4 { margin-bottom: 0.4em; font-size: 1.15rem; }
.sidebar-card-body--v1 p { color: var(--color-body); font-size: 0.97rem; }
.sidebar-contact--v1 { list-style: none; margin: 1.1rem 0; padding: 0; }
.sidebar-contact--v1 li { display: flex; align-items: flex-start; gap: 0.55rem; padding: 0.3rem 0; }
.sidebar-icon--v1 { width: 18px; height: 18px; flex: none; margin-top: 0.2em; color: var(--color-accent); }

/* ---- SERVICE-AREAS HUB grid (V1 global block 3096) ----
   Icon, heading, then the town list. No map iframe here on purpose:
   see the note in archive-service_area.php. */
.areas-hub--v1 { background: var(--color-bg-alt); text-align: center; }
.areas-hub-icon--v1 {
  display: inline-flex; align-items: center; justify-content: center;
  width: 3.25rem; height: 3.25rem; margin-bottom: 1rem;
  border-radius: 50%;
  background: color-mix(in srgb, var(--color-accent) 12%, transparent);
  color: var(--color-accent);
}
.areas-hub-icon--v1 .oc-icon { width: 28px; height: 28px; }
.areas-hub--v1 .area-links { justify-content: center; }

/* ---- CONTACT card + form (V1 global block 2961) ---- */
/* SAME-CARD RULING 2026-09-12 (skin/form-nav-cool, Hannah: "our hero form
   card should be the same as our other cards"): this is the OTHER place a
   lead-form card renders (parts/contact-card.php wraps parts/lead-form.php
   in this exact card) -- its own pre-existing radius/shadow (calc(radius+
   10px), a hardcoded rgba shadow) were just as bespoke as the hero card's
   old glass surface, so it moves onto the identical shared card tokens too:
   var(--card-radius)/var(--card-shadow)/var(--card-border-width)/
   var(--card-border-color), same as .ocf-svc-card / .ocf-testimonial-card /
   .ocf-faq-item and now .hero-form-card (contact-form.css). --ocf-bg is the
   same value as --color-bg (header.php bridges one to the other), so this
   is a token-name change only, not a visual regression for whichever site
   still has this part in its render path. */
.contact-card-section--v1 { background: var(--color-bg-alt); }
.contact-card--v1 {
  background: var(--ocf-bg);
  border: var(--card-border-width) solid var(--card-border-color);
  border-radius: var(--card-radius);
  padding: clamp(1.5rem, 4vw, 2.75rem);
  box-shadow: var(--card-shadow);
}
.contact-card-grid--v1 {
  display: grid;
  grid-template-columns: minmax(0, 1fr) minmax(0, 1.05fr);
  gap: clamp(1.75rem, 4vw, 3rem);
  align-items: start;
}
.contact-card-brand--v1 { display: inline-flex; align-items: center; }
.contact-card-name--v1 { margin: 0.75rem 0 0; font-weight: 700; color: var(--color-heading); }
.contact-card-tagline--v1 { margin: 0.5rem 0 0; color: var(--color-body); max-width: 30rem; }

.contact-boxes--v1 { display: grid; gap: 0.85rem; margin-top: 1.5rem; }
/* The whole box is the link (V1 does this too), so the tap target on a
   phone is the card rather than eleven characters of phone number. */
.contact-box--v1 {
  display: flex; align-items: center; gap: 0.9rem;
  padding: 0.9rem 1rem;
  border: 1px solid var(--color-border);
  border-radius: calc(var(--radius, 10px) + 2px);
  color: var(--color-heading);
  transition: border-color 0.15s, box-shadow 0.15s;
}
.contact-box--v1:hover {
  border-color: var(--color-accent);
  box-shadow: 0 6px 20px rgba(15, 23, 42, 0.08);
}
.contact-box-icon--v1 {
  display: inline-flex; align-items: center; justify-content: center;
  width: 2.5rem; height: 2.5rem; flex: none;
  border-radius: 50%;
  background: color-mix(in srgb, var(--color-accent) 12%, transparent);
  color: var(--color-accent);
}
.contact-box-icon--v1 svg { width: 20px; height: 20px; }
.contact-box-body--v1 { display: grid; gap: 0.1rem; min-width: 0; }
.contact-box-label--v1 { font-size: 0.85rem; color: var(--color-body); }
.contact-box-value--v1 { font-weight: 600; overflow-wrap: anywhere; }

.contact-card-form-title--v1 { font-size: 1.35rem; margin-bottom: 0.9rem; }
/* Inside the card the form is the card, so it drops its own frame. */
.contact-card-form--v1 .contact-form {
  background: transparent; border: 0; box-shadow: none; padding: 0;
}

/* ---- CONTACT full-width map (V1 bde-section-705-176) ---- */
.contact-map--v1 { height: clamp(18rem, 42vw, 28rem); background: var(--color-bg-alt); }
.contact-map--v1 iframe { display: block; width: 100%; height: 100%; border: 0; }

/* ---- GALLERY (V1 bde-section-3272-100) ----
   Masonry as CSS columns rather than Isotope: the same visual result,
   computed by the browser, with no script and no reflow on load. */
.gallery--v1 { background: var(--color-bg); }
.gallery-masonry--v1 { columns: 3; column-gap: 1rem; }
.gallery-item--v1 {
  display: block;
  break-inside: avoid;
  margin-bottom: 1rem;
  border-radius: calc(var(--radius, 10px) + 4px);
  overflow: hidden;
  background: var(--color-bg-alt);
}
.gallery-item--v1 img {
  display: block; width: 100%; height: auto;
  transition: transform 0.25s ease;
}
.gallery-item--v1:hover img { transform: scale(1.03); }
@media (prefers-reduced-motion: reduce) {
  .gallery-item--v1 img,
  .gallery-item--v1:hover img { transition: none; transform: none; }
}

.gallery-lightbox--v1 {
  border: 0; padding: 0; background: transparent;
  max-width: min(92vw, 68rem); max-height: 92vh;
  overflow: visible;
}
.gallery-lightbox--v1::backdrop { background: rgba(15, 23, 42, 0.82); }
.gallery-lightbox--v1 img {
  display: block; max-width: 100%; max-height: 88vh;
  width: auto; height: auto;
  border-radius: calc(var(--radius, 10px) + 4px);
}
.gallery-lightbox-close--v1 {
  position: absolute; top: -0.75rem; right: -0.75rem;
  width: 2.5rem; height: 2.5rem;
  display: inline-flex; align-items: center; justify-content: center;
  background: var(--color-bg); color: var(--color-heading);
  border: 1px solid var(--color-border); border-radius: 50%;
  font-size: 1.4rem; line-height: 1; cursor: pointer;
}
.gallery-empty--v1 { text-align: center; margin-inline: auto; }

/* ---- BLOG INDEX cards (V1 loop-item template 2809) ----
   The whole card is one anchor; everything inside is inline-level, so
   the layout is set here rather than inherited from block defaults. */
.blog-index--v1 { background: var(--color-bg); }
.blog-grid--v1 {
  display: grid;
  grid-template-columns: repeat(auto-fit, minmax(17rem, 1fr));
  gap: 1.5rem;
}
.post-card--v1 {
  display: flex; flex-direction: column;
  background: var(--color-bg);
  border: 1px solid var(--color-border);
  border-radius: calc(var(--radius, 10px) + 4px);
  overflow: hidden;
  color: inherit;
  transition: box-shadow 0.18s ease, transform 0.18s ease;
}
.post-card--v1:hover { box-shadow: 0 12px 32px rgba(15, 23, 42, 0.12); transform: translateY(-2px); }
.post-card-media--v1 { position: relative; display: block; }
.post-card-media--v1 img { display: block; width: 100%; aspect-ratio: 3 / 2; object-fit: cover; }
.post-card-placeholder--v1 {
  display: block; width: 100%; aspect-ratio: 3 / 2;
  background: color-mix(in srgb, var(--color-heading) 8%, var(--color-bg-alt));
}
.post-card-chip--v1 {
  position: absolute; left: 0.75rem; bottom: 0.75rem;
  padding: 0.25rem 0.7rem; border-radius: var(--radius-full);
  background: var(--color-accent); color: var(--color-on-accent);
  font-size: 0.78rem; font-weight: 600;
}
.post-card-body--v1 { display: block; padding: 1.1rem 1.25rem 1.35rem; }
.post-card-date--v1 { display: block; font-size: 0.85rem; color: var(--color-body); }
.post-card-body--v1 h3 { margin: 0.35rem 0 0.4rem; font-size: 1.15rem; }
.post-card-excerpt--v1 { display: block; color: var(--color-body); font-size: 0.97rem; }
/* Looks like a button, is not a control: a link inside a link is invalid
   HTML and a second tab stop for one destination. */
.post-card-more--v1 {
  display: inline-block; margin-top: 1rem;
  padding: 0.5em 1.1em; border-radius: var(--radius, 8px);
  background: var(--color-accent); color: var(--color-on-accent);
  font-size: 0.92rem; font-weight: 600;
}
.blog-empty--v1 { margin-inline: auto; }

/* ---- BLOG SINGLE (V1 bde-section-195-106) ---- */
.post-article--v1 { background: var(--color-bg); }
.post-layout--v1 {
  display: grid;
  grid-template-columns: minmax(0, 0.85fr) minmax(0, 2.15fr);
  gap: clamp(2rem, 5vw, 3.5rem);
  align-items: start;
}
.post-layout--single { grid-template-columns: minmax(0, 1fr); max-width: 46rem; }
.post-toc--v1 { position: sticky; top: 6rem; }
.toc-card--v1 {
  background: var(--color-bg-alt);
  border: 1px solid var(--color-border);
  border-radius: calc(var(--radius, 10px) + 4px);
  padding: 1.25rem 1.35rem;
  max-height: calc(100vh - 8rem);
  overflow-y: auto;
}
.toc-card--v1 h3 { font-size: 1.05rem; margin-bottom: 0.75rem; }
.toc-card--v1 ol { list-style: none; margin: 0; padding: 0; }
.toc-card--v1 li { padding: 0.22rem 0; }
.toc-card--v1 .toc-level-3 { padding-left: 1rem; font-size: 0.92rem; }
.toc-card--v1 a { color: var(--color-body); }
.toc-card--v1 a:hover { color: var(--color-accent); }

.post-body--v1 > :first-child { margin-top: 0; }
.post-body--v1 h2 { margin-top: 2rem; }
.post-body--v1 h3 { margin-top: 1.5rem; }
.post-body--v1 img { max-width: 100%; height: auto; border-radius: var(--radius, 10px); }
.post-body--v1 blockquote {
  margin: 1.5rem 0; padding: 0.35rem 0 0.35rem 1.25rem;
  border-left: 3px solid var(--color-accent); color: var(--color-body);
}

.adjacent-post--v1 {
  display: flex; align-items: center; gap: 0.75rem;
  margin-top: 2.5rem; padding: 1.15rem 1.35rem;
  border: 1px solid var(--color-border);
  border-radius: calc(var(--radius, 10px) + 4px);
  background: var(--color-bg-alt);
  color: var(--color-heading);
}
.adjacent-post--v1:hover { border-color: var(--color-accent); }
.adjacent-post-label--v1 { font-size: 0.85rem; color: var(--color-body); flex: none; }
.adjacent-post-title--v1 { font-weight: 600; }
.adjacent-post-icon--v1 { width: 20px; height: 20px; margin-left: auto; flex: none; color: var(--color-accent); }

/* ---- THANK-YOU (V1 bde-section-806-102) ---- */
.thankyou--v1 { text-align: center; padding: clamp(3rem, 8vw, 5.5rem) 0; }
.thankyou--v1 h3 { font-size: clamp(1.6rem, 3.5vw, 2.25rem); }
.thankyou--v1 .lead { margin-inline: auto; }
.thankyou-action--v1 { margin-top: 1.75rem; }

/* ---- Responsive (matches the Phase A/B breakpoints) ---- */
@media (max-width: 900px) {
  .gallery-masonry--v1 { columns: 2; }
}
@media (max-width: 820px) {
  /* Sticky sidebars stop being sticky the moment they are stacked: a
     one-column page has nothing for them to stick beside. */
  .about-grid--v1,
  .post-layout--v1,
  .contact-card-grid--v1 { grid-template-columns: minmax(0, 1fr); }
  .about-aside--v1,
  .post-toc--v1 { position: static; }
  .toc-card--v1 { max-height: none; }
  .gallery-masonry--v1 { columns: 1; }
  .adjacent-post--v1 { flex-wrap: wrap; }
}
