/* ==========================================================================
   Surface Shield - shared stylesheet (mobile-first, no build step)

   Brand build: light warm sections, deep-navy header/footer/CTA bands,
   electric-cyan pill CTAs with ink text, chrome-silver hairlines, soft
   steel-tinted service cards. Layout rhythm follows the Bordner reference
   (pill buttons, tinted cards with a VIEW bar, numbered process timeline,
   bordered accordion, large navy footer) executed in Surface Shield's
   palette. Contrast pairs verified in NOTES.md.
   ========================================================================== */

/* ---- Tokens ---- */
:root {
  color-scheme: light;

  /* Brand palette (owner-specified; matches the logo artwork) */
  --navy:      #001B3A;  /* header, footer, CTA band, dark cards */
  --navy-mid:  #002A59;  /* raised surfaces on navy */
  --ink:       #000C25;  /* headings, text on cyan buttons */
  --cyan:      #00A9E2;  /* ALL primary CTAs + highlights (ink text, 7.2:1) */
  --cyan-deep: #0078A8;  /* text links on light bg (4.9:1 on white) */
  --silver:    #D6DADE;  /* chrome hairlines, text on navy (12.3:1) */
  --steel:     #345E82;  /* secondary text on light (6.8:1 on white) */
  --star:      #B45309;  /* review stars on a WHITE card (5.0:1) */
  --star-navy: #F0A500;  /* review stars on the NAVY band (8.3:1) */

  /* Surfaces */
  --paper: #FFFFFF;
  --warm:  #F7F8FA;      /* alternating light band */
  --tint:  #E9EEF3;      /* soft steel wash: service cards, value cards */

  /* Text */
  --body-c: #24344A;     /* body on light */
  --fog:    #B9C6D6;     /* body on navy (9:1+) */

  /* Hairlines */
  --line:      #E3E7EC;
  --line-mid:  #CDD5DD;
  --line-navy: rgba(214, 218, 222, 0.22);

  /* Spacing scale */
  --sp-1: 0.25rem;
  --sp-2: 0.5rem;
  --sp-3: 0.75rem;
  --sp-4: 1rem;
  --sp-5: 1.25rem;
  --sp-6: 1.5rem;
  --sp-8: 2rem;
  --sp-10: 2.5rem;
  --sp-12: 3rem;
  --sp-16: 4rem;
  --sp-20: 5rem;
  --sp-24: 6rem;

  /* Fluid type scale. Every step is clamp(min, rem-base + vw, max) tuned so
     text is comfortable at 1280 (small laptop) rather than hitting its ceiling
     there, and still grows a little through 1920. Reference sizes:
       h1  32px @375 · 48px @1280 · 52px @1440 · 54px @1920
       h2  24px @375 · 31px @1280 · 34px @1920
       body 16px @375 · 17px @1280+ */
  --fs-xs:   clamp(0.78rem, 0.76rem + 0.06vw, 0.8125rem);
  --fs-sm:   clamp(0.9rem, 0.88rem + 0.08vw, 0.95rem);
  --fs-base: clamp(1rem, 0.97rem + 0.12vw, 1.0625rem);
  --fs-lg:   clamp(1.05rem, 0.98rem + 0.25vw, 1.2rem);
  --fs-xl:   clamp(1.2rem, 1.02rem + 0.5vw, 1.45rem);
  --fs-2xl:  clamp(1.5rem, 1.05rem + 1.15vw, 2.1rem);
  --fs-3xl:  clamp(1.75rem, 1.1rem + 1.7vw, 2.6rem);
  --fs-4xl:  clamp(2rem, 1.1rem + 2.4vw, 3.4rem);

  /* Archivo: squared industrial grotesque matching the logo wordmark.
     IBM Plex Sans: engineered, workmanlike body face. */
  --font-display: "Archivo", "Arial Black", Arial, sans-serif;
  --font-body: "IBM Plex Sans", system-ui, "Segoe UI", Arial, sans-serif;

  /* Shape: pill buttons (reference style), softly rounded cards */
  --r-pill: 999px;
  --r-card: 14px;
  --r-media: 10px;
  --r-input: 6px;

  /* Motion */
  --ease: cubic-bezier(0.22, 1, 0.36, 1);
  --ease-soft: cubic-bezier(0.4, 0, 0.2, 1);
  --t-fast: 150ms;
  --t-mid: 260ms;

  /* Navy-tinted shadows */
  --sh-sm: 0 1px 2px rgba(0, 27, 58, 0.06), 0 2px 8px rgba(0, 27, 58, 0.05);
  --sh-md: 0 2px 6px rgba(0, 27, 58, 0.07), 0 10px 26px rgba(0, 27, 58, 0.09);

  /* Text container stays ~1216px so line length never stretches awkwardly on
     a 24" monitor. Image-led sections use --container-wide so photography
     fills more of a large screen instead of leaving dead margins. Full-bleed
     bands and background colors ignore both and run edge to edge. */
  --container: 76rem;       /* 1216px */
  --container-wide: 90rem;  /* 1440px */
  --gutter: clamp(1.25rem, 3.5vw, 3rem);
  --header-h: 4.5rem;
}

/* ---- Reset & base ---- */
*,
*::before,
*::after { box-sizing: border-box; }

html {
  scroll-behavior: smooth;
  scroll-padding-top: calc(var(--header-h) + var(--sp-6));
  -webkit-text-size-adjust: 100%;
}

@media (prefers-reduced-motion: reduce) {
  html { scroll-behavior: auto; }
}

body {
  margin: 0;
  font-family: var(--font-body);
  font-size: var(--fs-base);
  line-height: 1.7;
  color: var(--body-c);
  background: var(--paper);
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

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

h1, h2, h3, h4 {
  font-family: var(--font-display);
  color: var(--ink);
  margin: 0 0 var(--sp-5);
  letter-spacing: -0.02em;
  text-wrap: balance;
}

h1, h2 { font-weight: 700; line-height: 1.1; }
h1 { font-size: var(--fs-3xl); }
h2 { font-size: var(--fs-2xl); }

h3 { font-size: var(--fs-xl); font-weight: 600; line-height: 1.25; }
h4 { font-size: var(--fs-lg); font-weight: 600; line-height: 1.3; }

p, ul, ol { margin: 0 0 var(--sp-5); }

a {
  color: var(--cyan-deep);
  text-decoration: none;
  text-underline-offset: 0.2em;
  transition: color var(--t-fast) var(--ease-soft);
}

a:hover { color: var(--navy); text-decoration: underline; }

strong { font-weight: 600; color: var(--ink); }

::selection { background: var(--cyan); color: var(--ink); }

:focus-visible {
  outline: 3px solid var(--cyan);
  outline-offset: 2px;
  border-radius: 4px;
}

.hidden { display: none !important; }

.skip-link {
  position: absolute;
  left: -999px;
  top: 0;
  z-index: 300;
  padding: var(--sp-3) var(--sp-5);
  background: var(--cyan);
  color: var(--ink);
  font-weight: 600;
  border-radius: var(--r-pill);
}

.skip-link:focus { left: var(--sp-4); top: var(--sp-4); }

/* ---- Layout ---- */
.container {
  max-width: var(--container);
  margin-inline: auto;
  padding-inline: var(--gutter);
}

/* Wider track for image-led sections (galleries, photo strips) */
.container--wide { max-width: var(--container-wide); }

/* Fluid vertical rhythm: grows with the viewport instead of leaving a fixed
   gap that reads as dead space on a large monitor. */
.section { padding-block: clamp(3.25rem, 5.5vw, 7rem); }
.section--tight { padding-block: clamp(2.5rem, 4vw, 5rem); }
.section--warm { background: var(--warm); }
.section--bone { background: var(--warm); } /* legacy alias, inner pages */

/* Navy band (contact blocks on inner pages, final CTA) */
.slab {
  background: var(--navy);
  color: var(--fog);
}

.slab h1, .slab h2, .slab h3, .slab h4 { color: #FFFFFF; }
.slab a:not(.btn) { color: var(--cyan); }
.slab a:not(.btn):hover { color: #FFFFFF; }

/* ---- Section headings ---- */
.head { max-width: 46rem; margin-bottom: clamp(var(--sp-10), 4vw, var(--sp-12)); }
.head--center { margin-inline: auto; text-align: center; }

.head p { font-size: var(--fs-lg); color: var(--steel); margin: 0; max-width: 50ch; }
.head--center p { margin-inline: auto; }
.slab .head p { color: var(--fog); }

.head-note { color: var(--steel); max-width: 38ch; margin-bottom: var(--sp-8); }
.slab .head-note { color: var(--fog); max-width: 44ch; }

.card-note { color: var(--steel); margin-bottom: var(--sp-6); }

/* Heading block that carries its own CTA, so it needs no trailing gap */
.head--flush { margin-bottom: 0; }

/* Kicker: small cyan-deep label above a heading (used sparingly) */
.kicker {
  display: block;
  margin: 0 0 var(--sp-3);
  font-size: var(--fs-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.12em;
  color: var(--cyan-deep);
}

.slab .kicker { color: var(--cyan); }

/* Legacy status pill (kept for inner-page compatibility) */
.pill {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  margin: 0 0 var(--sp-5);
  padding: 0.42rem 0.85rem;
  background: transparent;
  color: var(--ink);
  border: 1px solid var(--line-mid);
  border-radius: var(--r-pill);
  font-size: var(--fs-xs);
  font-weight: 600;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  line-height: 1;
}

.slab .pill, .hero .pill { color: #FFFFFF; border-color: rgba(255, 255, 255, 0.3); }

.pill-dot { width: 0.45rem; height: 0.45rem; border-radius: 50%; background: var(--cyan); }

/* ---- Buttons (pill-shaped, per reference) ---- */
.btn {
  display: inline-flex;
  align-items: center;
  justify-content: center;
  gap: var(--sp-2);
  padding: 0.85rem 1.7rem;
  border: 2px solid transparent;
  border-radius: var(--r-pill);
  font-family: var(--font-body);
  font-size: var(--fs-sm);
  font-weight: 700;
  line-height: 1.2;
  white-space: nowrap;
  cursor: pointer;
  transition: background-color var(--t-fast) var(--ease-soft),
    border-color var(--t-fast) var(--ease-soft), color var(--t-fast) var(--ease-soft),
    transform var(--t-fast) var(--ease), box-shadow var(--t-mid) var(--ease);
}

.btn:hover { text-decoration: none; transform: translateY(-1px); }
.btn:active { transform: translateY(0); }

/* Primary: cyan bg + ink text (7.2:1). Never white text on cyan. */
.btn-primary {
  background: var(--cyan);
  border-color: var(--cyan);
  color: var(--ink);
  box-shadow: 0 2px 10px rgba(0, 169, 226, 0.25);
}

.btn-primary:hover {
  background: #33BBEA;
  border-color: #33BBEA;
  color: var(--ink);
}

.btn-outline {
  background: transparent;
  border-color: var(--navy);
  color: var(--navy);
}

.btn-outline:hover { background: var(--navy); color: #FFFFFF; }

.slab .btn-outline,
.hero-navy .btn-outline {
  border-color: rgba(255, 255, 255, 0.55);
  color: #FFFFFF;
}

.slab .btn-outline:hover,
.hero-navy .btn-outline:hover { background: #FFFFFF; border-color: #FFFFFF; color: var(--navy); }

.btn-light {
  background: #FFFFFF;
  border-color: #FFFFFF;
  color: var(--navy);
}

.btn-light:hover { background: var(--tint); border-color: var(--tint); color: var(--navy); }

.btn-lg { padding: 1rem 2rem; font-size: var(--fs-base); }
.btn-block { display: flex; width: 100%; }

.btn-arrow {
  display: inline-flex;
  width: 0.9rem;
  height: 0.9rem;
  color: currentColor;
  flex: none;
  transition: transform var(--t-mid) var(--ease);
}

.btn-arrow svg { width: 100%; height: 100%; }
.btn:hover .btn-arrow { transform: translateX(3px); }

/* Phone button in the header */
.btn-phone {
  background: transparent;
  border-color: var(--line-mid);
  color: var(--navy);
  padding: 0.6rem;
  /* 44px floor: the icon-only state must still be a comfortable tap target */
  min-width: 2.75rem;
  min-height: 2.75rem;
}

/* The only phone link in the header, so it is never hidden. Below 48em the
   number is dropped and the button becomes an icon-only tap target; the
   aria-label carries the number for screen readers. */
.btn-phone-num { display: none; }

.btn-phone:hover { border-color: var(--cyan-deep); color: var(--cyan-deep); }
.btn-phone svg { width: 1rem; height: 1rem; flex: none; }

/* ---- Header (sticky navy) ---- */
.site-header {
  position: sticky;
  top: 0;
  z-index: 1002;
  background: #FFFFFF;
  border-bottom: 1px solid var(--line);
}

.site-header.is-scrolled { box-shadow: 0 2px 16px rgba(0, 27, 58, 0.12); }

.header-row {
  display: flex;
  align-items: center;
  gap: var(--sp-4);
  min-height: var(--header-h);
  padding-block: var(--sp-2);
}

/* Brand lockup: shield mark + text styled to mirror the logo wordmark
   (SURFACE heavy, SHIELD chrome-silver with wide tracking). The full logo
   artwork has navy lettering, which would vanish on the navy bar - that is
   why the header uses the mark + styled text rather than logo-full.png. */
.brand {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-3);
  flex: none;
  text-decoration: none;
}

.brand:hover { text-decoration: none; }

/* Full transparent logo lockup (Main Logo No BG). Its wordmark text is dark
   navy, so it sits on the WHITE header. 36px mobile, 48px desktop, width auto
   so the ~2.16:1 lockup never distorts. */
.brand-logo {
  height: 36px;
  width: auto;
}

@media (min-width: 48em) {
  .brand-logo { height: 48px; }
}

.header-actions {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  margin-left: auto;
}

.btn-header { display: none; }

/* Mobile nav toggle */
.nav-toggle {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  padding: var(--sp-2);
  background: none;
  border: 0;
  color: var(--navy);
  font-family: var(--font-body);
  font-size: var(--fs-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  cursor: pointer;
}

.nav-toggle-bars {
  position: relative;
  width: 1.3rem;
  height: 2px;
  background: currentColor;
  transition: background-color var(--t-fast);
}

.nav-toggle-bars::before,
.nav-toggle-bars::after {
  content: "";
  position: absolute;
  left: 0;
  width: 100%;
  height: 2px;
  background: currentColor;
  transition: transform var(--t-mid) var(--ease);
}

.nav-toggle-bars::before { top: -6px; }
.nav-toggle-bars::after { top: 6px; }
.nav-toggle[aria-expanded="true"] .nav-toggle-bars { background: transparent; }
.nav-toggle[aria-expanded="true"] .nav-toggle-bars::before { transform: translateY(6px) rotate(45deg); }
.nav-toggle[aria-expanded="true"] .nav-toggle-bars::after { transform: translateY(-6px) rotate(-45deg); }

.nav-menu { list-style: none; margin: 0; padding: 0; }

/* This is the header's own copy, used for the desktop inline nav. On mobile,
   main.js clones it into #mobile-nav-menu (a body-level sibling of <header>,
   see below) and hides this original - so it must stay visible here if JS
   never runs (no-JS fallback: the links are simply in normal flow, unstyled
   as a panel, same as before). */
@media (max-width: 63.99em) {
  .js .site-nav > .nav-menu { display: none; }
}

.nav-menu > li > a {
  display: block;
  padding: var(--sp-3) 0;
  color: #FFFFFF;
  font-weight: 600;
  font-size: var(--fs-lg);
  border-bottom: 1px solid var(--line-navy);
}

.nav-menu a:hover { color: var(--cyan); text-decoration: none; }
.nav-menu a[aria-current="page"] { color: var(--cyan); }

/* Services dropdown: hover/focus-within on desktop; expanded inline in the
   mobile panel. Pure CSS, keyboard-operable, works without JS. */
.nav-drop { position: relative; }

.nav-drop-menu {
  list-style: none;
  margin: 0;
  padding: 0 0 var(--sp-2) var(--sp-4);
}

.nav-drop-menu .nav-group {
  display: block;
  padding: var(--sp-2) 0 var(--sp-1);
  font-size: var(--fs-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  color: var(--fog);
}

.nav-drop-menu a {
  display: block;
  padding: var(--sp-2) 0;
  color: #FFFFFF;
  font-size: var(--fs-sm);
  font-weight: 500;
}

.nav-menu-cta { margin-top: var(--sp-6); }
.nav-menu-cta a { border-bottom: 0 !important; }

/* The panel CTA is a button, not a nav link: keep ink-on-cyan (7.2:1).
   Without this, .nav-menu > li > a outranks .btn-primary on specificity, which
   also strips the button's flex-centering and side padding (label goes left). */
.nav-menu .btn-primary,
.nav-menu .btn-primary:hover { color: var(--ink); font-size: var(--fs-sm); }

.nav-menu .btn-block {
  display: flex;
  align-items: center;
  justify-content: center;
  padding: 0.85rem 1.7rem;
}

/* ---- Mobile nav: overlay + panel ----
   Rebuilt from scratch after diagnosing the previous version: the old panel
   lived inside <header>, and .site-header's position:sticky + z-index gives
   it its own stacking context, which trapped the panel's z-index inside it -
   so a sibling overlay could out-rank the entire header (including the
   panel nested in it) even though the panel's own z-index was nominally
   higher. Fix: both elements are appended as direct children of <body> by
   main.js (true siblings of <header>, not descendants of it), so no
   ancestor's stacking context can trap them again. Deliberately simple:
   plain display:none/block toggled by a single class on <body>, no
   transform, no opacity transition, no backdrop-filter. */
body.menu-open { overflow: hidden; }

.mobile-nav-overlay {
  display: none;
  position: fixed;
  inset: 0;
  z-index: 1000;
  background: rgba(0, 12, 37, 0.6);
}

body.menu-open .mobile-nav-overlay { display: block; }

.mobile-nav-panel {
  display: none;
  position: fixed;
  inset: 0;
  z-index: 1001;
  width: min(21rem, 84vw);
  margin-left: auto;
  height: 100vh;
  height: 100dvh;
  padding: calc(var(--header-h) + var(--sp-6)) var(--sp-6) var(--sp-12);
  background: var(--navy);
  border-left: 1px solid var(--line-navy);
  overflow-y: auto;
}

body.menu-open .mobile-nav-panel { display: block; }

@media (min-width: 64em) {
  .mobile-nav-overlay,
  .mobile-nav-panel { display: none !important; }
}

/* ---- Hero (light, photo right, per reference) ---- */
.hero {
  background: linear-gradient(180deg, var(--warm) 0%, var(--paper) 100%);
  padding-block: clamp(var(--sp-12), 6vw, var(--sp-20)) clamp(var(--sp-12), 5vw, var(--sp-16));
}

/* Parallax hero: drops the light gradient, flips to white text over the
   navy-tinted photo. The white trust cards below scroll across the fixed
   background, which is where the depth effect actually reads. */
.hero--parallax {
  background-color: var(--navy);
  color: #FFFFFF;
  padding-block: clamp(3.5rem, 6vw, 7rem);
}

.hero--parallax h1 { color: #FFFFFF; }
.hero--parallax .hero-lede { color: var(--fog); }

.hero-grid { display: grid; gap: clamp(var(--sp-8), 4vw, var(--sp-12)); align-items: center; }

.hero h1 { font-size: var(--fs-4xl); margin-bottom: var(--sp-5); }

.hero-lede {
  font-size: var(--fs-lg);
  color: var(--steel);
  max-width: 34rem;
  margin-bottom: var(--sp-8);
}

.hero-actions { display: flex; flex-wrap: wrap; gap: var(--sp-3); }
.hero-actions--center { justify-content: center; }
.hero-lede--center { margin-inline: auto; }

.hero-media { position: relative; }

.hero-media img {
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  border-radius: var(--r-card);
  box-shadow: var(--sh-md);
}

/* Trust badge row under the hero */
.trust-row {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--sp-3);
  margin: clamp(var(--sp-8), 4vw, var(--sp-12)) 0 0;
  padding: 0;
}

.trust-row li {
  flex: 1 1 calc(50% - var(--sp-3));  /* 2-up, centered on mobile */
  min-width: 0;
  min-height: 7.25rem;                /* all badges equal, even 2-line labels across wrap rows */
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: var(--sp-2);
  padding: var(--sp-5) var(--sp-3);
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--r-card);
  box-shadow: var(--sh-sm);
  text-align: center;
  font-size: var(--fs-sm);
  font-weight: 600;
  color: var(--ink);
  line-height: 1.35;
}

.trust-row svg { width: 1.6rem; height: 1.6rem; color: var(--cyan-deep); }

/* ---- Hero: full-bleed background photo, text overlaid left ----
   Same technique as .page-header (CSS background + scrim), but taller and
   left-aligned/left-weighted instead of centered, since this is the
   homepage's primary hero rather than an inner-page title band. */
.hero-bg {
  position: relative;
  isolation: isolate;
  display: flex;
  align-items: center;
  min-height: 420px;
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  background-attachment: scroll;
  color: #FFFFFF;
}

.hero-bg::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(90deg,
    rgba(0, 12, 37, 0.9) 0%,
    rgba(0, 12, 37, 0.78) 35%,
    rgba(0, 12, 37, 0.4) 70%,
    rgba(0, 12, 37, 0.15) 100%);
}

.hero-bg-text { max-width: 600px; padding-block: clamp(2.5rem, 8vw, 3.5rem); }
.hero-bg-text h1 { color: #FFFFFF; font-size: var(--fs-4xl); margin-bottom: var(--sp-5); }
.hero-bg-text .hero-lede { color: var(--fog); margin-bottom: var(--sp-8); }

.hero-bg-text .btn-outline { border-color: rgba(255, 255, 255, 0.55); color: #FFFFFF; }
.hero-bg-text .btn-outline:hover { background: #FFFFFF; border-color: #FFFFFF; color: var(--navy); }

/* Buttons stack full-width on mobile, sit side by side from 48em up */
.hero-bg .hero-actions { flex-direction: column; }
.hero-bg .hero-actions .btn { width: 100%; min-height: 2.75rem; }

@media (min-width: 48em) {
  .hero-bg { min-height: 560px; }
  .hero-bg .hero-actions { flex-direction: row; flex-wrap: wrap; }
  .hero-bg .hero-actions .btn { width: auto; }
}

/* Trust badge strip below the hero. Grey (steel wash) so the white cards
   read clearly against it. */
.trust-strip {
  background: var(--tint);
  padding-block: clamp(2rem, 4vw, 3rem);
}

.trust-strip .trust-row { margin: 0; }

/* ---- Page header band (every page except home) ----
   Background photo set inline per page, navy scrim over it, white title,
   chrome divider at the bottom. Consistent height sitewide. Scroll attachment
   (fixed breaks on iOS). Form/info content stays readable: form cards carry
   their own white background. */
.page-header {
  position: relative;
  isolation: isolate;
  display: flex;
  align-items: center;
  min-height: clamp(15rem, 12rem + 18vw, 25rem);  /* pins to 400px on desktop so title-page headers match */
  padding-block: clamp(2.5rem, 5vw, 4rem);
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  background-attachment: scroll;
  border-bottom: 1px solid var(--silver);
  color: #FFFFFF;
}

/* .page-header is a flex container, so its .container child would size to its
   content (shrink-to-fit) and then get centred by its own margin-inline:auto.
   That pushed every inner-page hero inward, so the heading did not line up
   with the .container of the plain .section blocks below it. width:100% makes
   the track resolve to the same max-width + gutter as everywhere else. */
.page-header > .container { width: 100%; }

.page-header::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(160deg, rgba(0, 12, 37, 0.82), rgba(0, 42, 89, 0.72));
}

.page-header h1, .page-header h2, .page-header h3 { color: #FFFFFF; }
.page-header p, .page-header .head-note { color: var(--fog); }
.page-header .kicker { color: var(--cyan); }
.page-header .contact-row dt { color: #FFFFFF; }
.page-header .contact-row a { color: var(--fog); }
.page-header .contact-row a:hover { color: #FFFFFF; }
.page-header .hero-trust li { color: #FFFFFF; }
.page-header .btn-outline { border-color: rgba(255, 255, 255, 0.55); color: #FFFFFF; }

/* RFP page only (the only page-header with .section--tight): the form is
   the page's single most important element, so the photo behind the left
   column reads as texture, not a competing subject, and the heading carries
   less visual weight than the form card next to it. */
.page-header.section--tight::before {
  background: linear-gradient(160deg, rgba(0, 12, 37, 0.85), rgba(0, 42, 89, 0.8));
}

.page-header.section--tight h1 { font-size: var(--fs-2xl); }
.page-header.section--tight .head-note { line-height: 1.5; }
.page-header .btn-outline:hover { background: #FFFFFF; border-color: #FFFFFF; color: var(--navy); }

/* Invisible scroll-target for renamed section anchors (old #floor, #epoxy,
   #commercial, #basement) so inbound links still land on the right section.
   Zero-height; html scroll-padding-top handles the sticky-header offset. */
.anchor-alias { display: block; height: 0; }

/* ---- How It Works over the roof photo ----
   Roof reads as texture, not a photo. A strong navy scrim (0.86-0.90) keeps
   all text readable; readability wins over the image. background-attachment
   stays scroll (fixed is broken on iOS). Chrome hairline separates the top. */
.how-bg {
  position: relative;
  border-top: 1px solid var(--silver);
  background-image: url("../images/Protective%20coating/Residential%20Roof/roof-hero-bg.jpg");
  background-size: cover;
  background-position: center;
  background-repeat: no-repeat;
  background-attachment: scroll;
  color: #FFFFFF;
}

.how-bg::before {
  content: "";
  position: absolute;
  inset: 0;
  background: linear-gradient(160deg, rgba(0, 12, 37, 0.9), rgba(0, 42, 89, 0.86));
}

.how-bg > .container { position: relative; z-index: 1; }

/* Text flips to white / light steel-gray; cyan stays the accent */
.how-bg h2 { color: #FFFFFF; }
.how-bg .kicker { color: var(--cyan); }
.how-bg .head p { color: var(--fog); }
.how-bg .timeline h3 { color: #FFFFFF; }
.how-bg .timeline p { color: var(--fog); }
.how-bg .timeline li::after { background: rgba(214, 218, 222, 0.45); }

/* ---- Most Requested Services: tinted tiles with a VIEW bar ---- */
.svc-split { display: grid; gap: clamp(var(--sp-8), 4vw, var(--sp-12)); align-items: start; }

.svc-groups { display: grid; gap: var(--sp-8); }

.svc-group-label {
  margin: 0 0 var(--sp-4);
  font-family: var(--font-display);
  font-size: var(--fs-base);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.06em;
  color: var(--steel);
  display: flex;
  align-items: center;
  gap: var(--sp-3);
}

.svc-group-label::after {
  content: "";
  flex: 1;
  height: 1px;
  background: var(--line-mid);
}

.svc-tiles {
  display: grid;
  grid-template-columns: 1fr;      /* single column on mobile */
  align-items: stretch;            /* every card in a row is equal height */
  gap: var(--sp-4);
}

@media (min-width: 40em) {
  .svc-tiles { grid-template-columns: repeat(3, 1fr); }
}

.svc-tile {
  display: flex;
  flex-direction: column;
  border-radius: var(--r-card);
  overflow: hidden;
  background: var(--tint);
  border: 1px solid var(--line);
  text-decoration: none;
  transition: transform var(--t-mid) var(--ease), box-shadow var(--t-mid) var(--ease);
}

.svc-tile:hover { transform: translateY(-3px); box-shadow: var(--sh-md); text-decoration: none; }

/* Photo at the top of each tile. 4:3, object-fit cover so mismatched sources
   never stretch. Top corners inherit the card radius via the card's
   overflow:hidden. Hover: 1.04 zoom + a light navy wash. */
.svc-tile-media {
  position: relative;
  display: block;
  aspect-ratio: 4 / 3;
  flex-shrink: 0;                  /* image height never squeezed */
  overflow: hidden;
  background: var(--navy);
}

.svc-tile-media img {
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
  display: block;
  transition: transform 300ms var(--ease-soft);
}

.svc-tile-media::after {
  content: "";
  position: absolute;
  inset: 0;
  background: rgba(0, 27, 58, 0);
  transition: background 300ms var(--ease-soft);
}

.svc-tile:hover .svc-tile-media img { transform: scale(1.04); }
.svc-tile:hover .svc-tile-media::after { background: rgba(0, 27, 58, 0.14); }

.svc-tile-name {
  flex: 1;                         /* absorbs leftover height so all cards match */
  display: flex;
  align-items: center;
  justify-content: center;
  min-height: 4rem;               /* comfortably fits a two-line title */
  padding: var(--sp-4) var(--sp-4);
  font-family: var(--font-display);
  font-weight: 600;
  font-size: var(--fs-base);
  color: var(--ink);
  text-align: center;
  line-height: 1.3;
}

.svc-tile-view {
  margin-top: auto;               /* pinned to the card's bottom edge */
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: var(--sp-3) var(--sp-5);
  background: var(--cyan);
  color: var(--ink);
  font-size: var(--fs-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.1em;
  transition: background-color var(--t-fast) var(--ease-soft);
}

.svc-tile:hover .svc-tile-view { background: #33BBEA; }
.svc-tile-view svg { width: 0.9rem; height: 0.9rem; }

/* Optional: faint shield-mark watermark, bottom-right, bleeding off the edge,
   4% opacity, behind all content. Decorative only (no a11y role), and far too
   faint to affect text contrast. */
#services { position: relative; overflow: hidden; }

#services::after {
  content: "";
  position: absolute;
  right: -3%;
  bottom: -7%;
  width: min(28rem, 42%);
  aspect-ratio: 279 / 378;
  background: url("../images/Logo/logo-shield.png") right bottom / contain no-repeat;
  opacity: 0.04;
  pointer-events: none;
  z-index: 0;
}

#services > .container { position: relative; z-index: 1; }

/* ---- How It Works: numbered horizontal timeline ---- */
.steps-head {
  display: flex;
  flex-wrap: wrap;
  align-items: flex-end;
  justify-content: space-between;
  gap: var(--sp-4);
  margin-bottom: clamp(var(--sp-8), 4vw, var(--sp-12));
}

.steps-head .head { margin-bottom: 0; }

.timeline {
  list-style: none;
  counter-reset: step;
  display: grid;
  gap: var(--sp-8);
  margin: 0;
  padding: 0;
}

.timeline li { counter-increment: step; position: relative; padding-left: 4rem; }

.timeline li::before {
  content: counter(step);
  position: absolute;
  left: 0;
  top: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  width: 2.9rem;
  height: 2.9rem;
  border: 2px solid var(--cyan);
  border-radius: 50%;
  background: var(--paper);
  font-family: var(--font-display);
  font-weight: 700;
  font-size: var(--fs-lg);
  color: var(--navy);
}

/* connecting line */
.timeline li:not(:last-child)::after {
  content: "";
  position: absolute;
  left: 1.45rem;
  top: 3.1rem;
  bottom: calc(var(--sp-8) * -1);
  width: 2px;
  background: var(--line-mid);
}

.timeline h3 { font-size: var(--fs-lg); margin-bottom: var(--sp-1); }
.timeline p { margin: 0; color: var(--steel); font-size: var(--fs-sm); max-width: 30ch; }

/* ---- Value cards ---- */
.value-grid { display: grid; gap: var(--sp-4); }

.value-card {
  padding: var(--sp-6);
  background: var(--tint);
  border: 1px solid var(--line);
  border-radius: var(--r-card);
}

.value-card svg { width: 1.9rem; height: 1.9rem; color: var(--cyan-deep); margin-bottom: var(--sp-4); }
.value-card h3 { font-size: var(--fs-lg); margin-bottom: var(--sp-2); }
.value-card p { margin: 0; color: var(--steel); font-size: var(--fs-sm); }

/* ---- Mission statement band (Why Us page) ----
   Generous padding + a wide statement column read as an intentional section;
   the previous version was a narrow bold block that wrapped into six ragged
   lines. Width does the work here, not font weight. */
.mission-band {
  position: relative;
  isolation: isolate;
  overflow: hidden;
  padding-block: 3.75rem;
}

@media (min-width: 48em) {
  .mission-band { padding-block: 6.25rem; }
}

.mission-band .container { max-width: 56rem; text-align: center; }

.mission-band .kicker { text-align: center; }

.mission-statement {
  font-family: var(--font-display);
  font-weight: 500;
  font-size: clamp(1.375rem, 1.05rem + 1.4vw, 1.875rem);
  line-height: 1.5;
  color: #FFFFFF;
  margin: 0;
}

.mission-accent {
  display: block;
  width: 60px;
  height: 3px;
  margin: var(--sp-8) auto 0;
  background: var(--cyan);
  border-radius: 2px;
}

/* Shield watermark: decorative only, kept faint enough it never competes
   with the statement's contrast. Drop it if a future brand pass finds it
   busy - it was optional by design. */
.mission-watermark {
  position: absolute;
  z-index: -1;
  top: 50%;
  left: 50%;
  transform: translate(-50%, -50%);
  width: clamp(18rem, 34vw, 30rem);
  height: auto;
  opacity: 0.05;
  pointer-events: none;
}

/* ---- Core values (Why Us page): pinned to 2 columns at every desktop
   width, unlike .value-grid which promotes to 4-across on large screens. */
.values-grid { display: grid; gap: var(--sp-4); }

@media (min-width: 48em) {
  .values-grid { grid-template-columns: repeat(2, 1fr); }
}

.core-value-card {
  padding: var(--sp-6);
  background: var(--paper);
  border: 1px solid var(--silver);
  border-radius: var(--r-card);
}

.core-value-card svg { width: 1.8rem; height: 1.8rem; color: var(--cyan); margin-bottom: var(--sp-3); }

.core-value-tag {
  display: block;
  margin-bottom: var(--sp-1);
  font-size: var(--fs-xs);
  font-weight: 700;
  text-transform: uppercase;
  letter-spacing: 0.08em;
  color: var(--cyan);
}

.core-value-card h3 { font-size: var(--fs-lg); margin-bottom: var(--sp-2); color: var(--ink); }
.core-value-card p { margin: 0; color: var(--steel); font-size: var(--fs-sm); }

/* ---- Gallery strip / masonry (inner gallery page + home strip) ---- */
.masonry { columns: 1; column-gap: var(--sp-4); }

.masonry figure {
  break-inside: avoid;
  margin: 0 0 var(--sp-4);
  border-radius: var(--r-media);
  overflow: hidden;
  background: var(--tint);
  border: 1px solid var(--line);
  transition: border-color var(--t-fast) var(--ease-soft);
}

.masonry figure:hover { border-color: var(--steel); }
.masonry img { width: 100%; height: auto; transition: transform 500ms var(--ease); }
.masonry figure:hover img { transform: scale(1.03); }

.masonry figcaption {
  padding: var(--sp-3) var(--sp-4);
  font-size: var(--fs-sm);
  line-height: 1.5;
  color: var(--steel);
  background: var(--paper);
}

/* Asymmetric work strip: a tall feature tile plus stacked smaller ones, so it
   reads as a composed layout rather than a row of identical clones. */
.work-strip {
  display: grid;
  grid-template-columns: 1fr;   /* single column on mobile: 5 tiles, no orphan */
  gap: var(--sp-4);
}

.work-strip figure {
  margin: 0;
  border-radius: var(--r-media);
  overflow: hidden;
  border: 1px solid var(--line);
  background: var(--tint);
}

.work-strip img {
  width: 100%;
  height: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  transition: transform 500ms var(--ease);
}

/* First tile spans two rows and runs portrait; the rest stay landscape */
.work-strip figure:first-child img { aspect-ratio: 3 / 4; }

.work-strip figure:hover img { transform: scale(1.04); }

.work-strip figcaption {
  padding: var(--sp-3) var(--sp-4);
  font-size: var(--fs-sm);
  color: var(--steel);
  background: var(--paper);
}

/* ---- Testimonials ----
   The sitewide review sections live in the namespaced .rv-* block at the very
   bottom of this file. Nothing here styles them.

   .quote-card / .quote-lead / .quote-foot / .attrib survive only for the
   single inline Orrick card embedded in the "Other surfaces" (#other) section
   of services.html, which is proof inside a service description rather than a
   review section. Do not build a new review layout on them. */
.quote-card {
  padding: clamp(var(--sp-6), 3vw, var(--sp-8));
  background: var(--paper);
  border: 1px solid var(--line-mid);
  border-radius: var(--r-card);
  transition: border-color var(--t-fast) var(--ease-soft);
}

.quote-card:hover { border-color: var(--steel); }

.quote-card .stars { margin-bottom: var(--sp-4); }

.stars { display: flex; gap: 0.15rem; }

/* Stars sit on .quote-card, which is white on EVERY page regardless of whether
   the section band behind it is navy or light - so the star colour only ever
   has to work against white, and one value serves the whole site.
   The old #E0A227 gold measured 2.24:1 on that card and the cyan override
   2.7:1; both failed. --star is 5.0:1. Do not restore either. */
.stars svg { width: 0.95rem; height: 0.95rem; color: var(--star); }

.quote-lead {
  font-family: var(--font-display);
  font-size: var(--fs-lg);
  font-weight: 500;
  line-height: 1.45;
  color: var(--ink);
  margin-bottom: var(--sp-4);
}

.quote-card p:last-of-type { color: var(--steel); }

.quote-foot {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  margin-top: var(--sp-5);
  padding-top: var(--sp-5);
  border-top: 1px solid var(--line);
}


.attrib { font-size: var(--fs-sm); font-weight: 600; color: var(--ink); }
.attrib span { display: block; }
.attrib .attrib-sub { font-weight: 400; font-size: var(--fs-xs); color: var(--steel); }

.review-cta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: var(--sp-4);
  max-width: 52rem;
  margin: var(--sp-8) auto 0;
  padding-top: var(--sp-8);
  border-top: 1px solid var(--line-mid);
  text-align: center;
}

.review-cta p { margin: 0; color: var(--steel); }

/* On a navy testimonials slab: lift the divider and prompt text off navy.
   --steel is a light-bg color (2.5:1 on navy) and fails there. */
.slab .review-cta { border-top-color: var(--line-navy); }
.slab .review-cta p { color: var(--fog); }

/* ---- FAQ accordion (bordered rows, cyan +/-) ---- */
.faq-grid { display: grid; gap: clamp(var(--sp-8), 4vw, var(--sp-12)); align-items: start; }

.faq-list { display: grid; gap: var(--sp-3); }

.faq-item {
  border: 1px solid var(--line-mid);
  border-radius: var(--r-media);
  background: var(--paper);
  transition: border-color var(--t-fast) var(--ease-soft);
}

.faq-item[open], .faq-item:hover { border-color: var(--steel); }

.faq-item summary {
  display: flex;
  align-items: center;
  gap: var(--sp-4);
  padding: var(--sp-4) var(--sp-5);
  cursor: pointer;
  list-style: none;
  font-weight: 600;
  color: var(--navy);
  line-height: 1.4;
}

.faq-item summary::-webkit-details-marker { display: none; }

.svc-sign {
  position: relative;
  flex: none;
  width: 1rem;
  height: 1rem;
  margin-left: auto;
  color: var(--cyan-deep);
}

.svc-sign::before,
.svc-sign::after {
  content: "";
  position: absolute;
  inset: 50% 0 auto 0;
  height: 2px;
  background: currentColor;
  transition: transform var(--t-mid) var(--ease);
}

.svc-sign::after { transform: rotate(90deg); }
.faq-item[open] .svc-sign::after,
.svc-item[open] .svc-sign::after { transform: rotate(0deg); }

.faq-body { padding: 0 var(--sp-5) var(--sp-5); }
.faq-body p { margin: 0; color: var(--steel); max-width: 62ch; }

/* ---- Brands strip ---- */
.brand-strip {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: var(--sp-6);
}

.brand-strip figure {
  margin: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  min-width: 9rem;
  min-height: 5rem;
  padding: var(--sp-4);
  background: var(--paper);
  border: 1px solid var(--line);
  border-radius: var(--r-media);
}

.brand-strip img { max-height: 4.5rem; width: auto; }

/* Wider tile for the product lineup photo beside the logo */
.brand-wide { min-width: 16rem; }
.brand-wide img { max-height: 6rem; }

.brand-note {
  max-width: 60ch;
  margin: var(--sp-6) auto 0;
  text-align: center;
  font-size: var(--fs-sm);
  color: var(--steel);
}

/* ---- Our Work page: labeled groups above each photo set ---- */
.work-group { margin-bottom: var(--sp-6); }
.work-group .svc-group-label { margin-bottom: var(--sp-2); }

.work-blurb {
  margin: 0;
  max-width: 62ch;
  color: var(--steel);
  font-size: var(--fs-sm);
}

/* Space between one photo set and the next group heading */
.masonry + .work-group { margin-top: clamp(var(--sp-10), 4vw, var(--sp-16)); }

.work-more { margin-top: var(--sp-8); }

.why-more { margin-top: var(--sp-8); text-align: center; }
.why-more a { display: inline-flex; align-items: center; gap: var(--sp-2); font-weight: 600; }
.why-more a:hover .btn-arrow { transform: translateX(3px); }

/* ---- Full-bleed photo bands ----
   Big edge-to-edge imagery to break up the page. The scrim never drops below
   0.80 alpha anywhere text sits: even if the photo underneath were pure white
   that still gives white 9.3:1 and fog 5.4:1, so these stay AA on any image. */
.photo-band {
  position: relative;
  isolation: isolate;
  display: flex;
  align-items: center;
  min-height: clamp(23rem, 56vh, 33rem);
  padding-block: clamp(var(--sp-12), 6vw, var(--sp-20));
  background: var(--navy);
  color: #FFFFFF;
  overflow: hidden;
}

/* 56vh reads as an unpredictably tall, narrow box on a portrait phone (vh
   grows with screen height, not width), forcing background photos to scale
   way up and crop in tight to cover it - the "zoomed in" look. Below 48em,
   drop the viewport-height dependency entirely for a fixed, predictable box. */
@media (max-width: 47.99em) {
  .photo-band { min-height: 22rem; }
}

.photo-band > img {
  position: absolute;
  inset: 0;
  z-index: -2;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

.photo-band::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(100deg,
    rgba(0, 27, 58, 0.93) 0%,
    rgba(0, 27, 58, 0.85) 44%,
    rgba(0, 27, 58, 0.62) 100%);
}

/* Centered variant needs an even scrim, since text reaches both edges */
.photo-band--center { text-align: center; }
.photo-band--center::before { background: rgba(0, 27, 58, 0.85); }
.photo-band--center .head { margin-inline: auto; }

.photo-band h2 { color: #FFFFFF; font-size: var(--fs-3xl); }
.photo-band .head { max-width: 40rem; margin-bottom: var(--sp-8); }
.photo-band .head p { color: var(--fog); }
.photo-band .kicker { color: var(--cyan); }

.photo-band .btn-outline { border-color: rgba(255, 255, 255, 0.55); color: #FFFFFF; }
.photo-band .btn-outline:hover { background: #FFFFFF; border-color: #FFFFFF; color: var(--navy); }

/* Focal point tuning per band, so the subject is not cropped out */
.photo-band--top > img { object-position: center 28%; }

/* ---- Parallax bands ----
   Background stays put while content scrolls over it. Uses a background-image
   rather than an <img>, so the band needs no child element.

   background-attachment: fixed is unreliable on mobile (iOS Safari in
   particular repaints badly or ignores it), so below 64em it falls back to
   scroll. It is also disabled under prefers-reduced-motion, where the
   parallax effect is the whole point and therefore the thing to remove. */
.parallax {
  position: relative;
  isolation: isolate;
  background-attachment: scroll;
  background-position: center;
  background-repeat: no-repeat;
  background-size: cover;
}

@media (min-width: 64em) and (prefers-reduced-motion: no-preference) {
  .parallax { background-attachment: fixed; }
}

/* Navy overlay keeps white text and cyan CTAs readable over any photo.
   Same 0.80 floor as .photo-band: white 9.3:1, fog 5.4:1 worst case. */
.parallax::before {
  content: "";
  position: absolute;
  inset: 0;
  z-index: -1;
  background: linear-gradient(100deg,
    rgba(0, 27, 58, 0.93) 0%,
    rgba(0, 27, 58, 0.86) 46%,
    rgba(0, 27, 58, 0.68) 100%);
}

.parallax--even::before { background: rgba(0, 27, 58, 0.86); }

.parallax h1, .parallax h2, .parallax h3 { color: #FFFFFF; }
.parallax p { color: var(--fog); }
.parallax .kicker { color: var(--cyan); }
.parallax .head p { color: var(--fog); }

.parallax .btn-outline { border-color: rgba(255, 255, 255, 0.55); color: #FFFFFF; }
.parallax .btn-outline:hover { background: #FFFFFF; border-color: #FFFFFF; color: var(--navy); }

/* Divider band: shorter than a hero, used to break up long stretches */
.parallax-divider {
  display: flex;
  align-items: center;
  min-height: clamp(18rem, 34vw, 26rem);
  padding-block: clamp(3rem, 5vw, 5rem);
  color: #FFFFFF;
}

@media (prefers-reduced-motion: no-preference) {
  .photo-band > img { transition: transform 8s var(--ease-soft); }
}

/* A photo band running straight into a flat navy block (contact.html and
   services.html contact blocks, rfp.html reviews) is dark-on-dark with no
   seam, so the two read as one tall mass. Those navy blocks deliberately stay
   navy - each holds a white form card or the approved review block, which need
   the dark backdrop - so a chrome hairline restores the boundary instead.
   The hairline sits on the photo band, not on the block below it, so the
   approved review section keeps its own styling completely untouched.
   The footer supplies its own border-top, so it is not included here. */
.photo-band:has(+ .slab),
.photo-band:has(+ .rv-section) {
  border-bottom: 1px solid var(--line-navy);
}

/* ---- Final CTA band ---- */
.cta-band { text-align: center; }

.cta-band .head { margin-inline: auto; margin-bottom: var(--sp-8); }

.cta-actions {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
  gap: var(--sp-4);
}

/* A CTA sitting straight under a review block has no preceding .head to
   supply its top gap, so it would butt against the Google review links.
   .rv-cta is the current namespaced review block (gallery.html stacks a
   Get a Free Quote button under it); .review-cta is the older one. Both
   need the gap - matching only .review-cta left the gallery pair touching. */
.review-cta + .cta-actions,
.rv-cta + .cta-actions { margin-top: var(--sp-8); }

/* ---- Forms ----
   The RFP form is the single most important element on the site, so the
   card gets elevated treatment (shadow + cyan top edge) to read as the
   page's focal point rather than one column among two. */
.form-card {
  position: relative;
  padding: 1.25rem; /* ~20px mobile */
  background: var(--paper);
  border-radius: 12px;
  border: 1px solid var(--line-mid);
  border-top: 2px solid var(--cyan);
  box-shadow: var(--sh-md);
  /* Grid items default to min-width:auto, which lets a native <select>'s
     intrinsic content width hold this card (and the whole .contact-grid
     row) wider than its column - the exact cause of the card clipping off
     the right edge. min-width:0 here is the fix. */
  min-width: 0;
}

@media (min-width: 64em) {
  .form-card { padding: 2.5rem; } /* ~40px desktop */
}

/* Specificity note: .page-header h2 sets white text for headings in the
   dark left column - beat it explicitly here or this heading goes invisible
   on the white card the same way the checkbox labels did. */
.form-card .form-card-heading { color: var(--ink); font-size: var(--fs-xl); margin-bottom: var(--sp-2); }

.form-grid { display: grid; gap: var(--sp-5); }
.form-row { display: grid; gap: var(--sp-5); }
.field { display: grid; gap: var(--sp-2); min-width: 0; }

.field > label,
.field legend { font-size: 0.9375rem; font-weight: 500; color: var(--ink); }

.hint { font-weight: 400; font-size: 0.8125rem; color: var(--steel); }

input[type="text"],
input[type="email"],
input[type="tel"],
select,
textarea {
  width: 100%;
  min-width: 0;
  min-height: 48px;
  padding: 0.7rem 1rem;
  font-family: var(--font-body);
  font-size: 1rem; /* 16px fixed: anything smaller triggers iOS Safari's auto-zoom on focus */
  color: var(--body-c);
  background: var(--paper);
  border: 1px solid var(--silver);
  border-radius: var(--r-input);
  transition: border-color var(--t-fast) var(--ease-soft), box-shadow var(--t-fast) var(--ease-soft);
}

input::placeholder, textarea::placeholder { color: #7A8698; }

input:focus, select:focus, textarea:focus {
  outline: none;
  border-color: var(--cyan);
  border-width: 2px;
  box-shadow: 0 0 0 4px rgba(0, 169, 226, 0.16);
}

textarea { min-height: 9rem; resize: vertical; }

fieldset { margin: 0; padding: 0; border: 0; min-width: 0; }
legend { padding: 0; margin-bottom: var(--sp-3); }

/* 1 column mobile, 2 columns desktop (not auto-fit: a fixed count is what
   keeps every row a compact checkbox + label instead of stretching into
   oversized empty containers when a row only partly fills). */
.checks { display: grid; grid-template-columns: 1fr; gap: var(--sp-3); min-width: 0; }

@media (min-width: 48em) {
  .checks { grid-template-columns: repeat(2, 1fr); }
}

.check {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  min-height: 48px;
  padding: var(--sp-2) var(--sp-4);
  border: 1px solid var(--silver);
  border-radius: var(--r-input);
  font-size: 1rem;
  font-weight: 400;
  color: var(--ink);
  cursor: pointer;
  transition: border-color var(--t-fast) var(--ease-soft), background-color var(--t-fast) var(--ease-soft);
}

.check:hover { border-color: var(--cyan-deep); background: var(--warm); }
.check input { width: 1.1rem; height: 1.1rem; accent-color: var(--cyan-deep); flex: none; }
.check:has(input:checked) { border-color: var(--cyan-deep); background: rgba(0, 169, 226, 0.07); }

.form-footnote { margin: var(--sp-4) 0 0; font-size: var(--fs-sm); color: var(--steel); text-align: center; }

.form-card .btn-lg { min-height: 56px; }

/* ---- Inner-page components (services, contact, thank-you, rfp) ---- */
.detail-grid { display: grid; gap: clamp(var(--sp-8), 4vw, var(--sp-12)); align-items: center; }

.detail-media { border-radius: var(--r-card); overflow: hidden; border: 1px solid var(--line); }

.detail-media img {
  width: 100%;
  aspect-ratio: 4 / 3;
  object-fit: cover;
  transition: transform 500ms var(--ease);
}

.detail-media:hover img { transform: scale(1.03); }

.benefits { list-style: none; margin: 0 0 var(--sp-6); padding: 0; display: grid; gap: var(--sp-4); max-width: 54ch; }

.benefits li { position: relative; padding-left: var(--sp-8); color: var(--body-c); }

.benefits li::before {
  content: "";
  position: absolute;
  left: 0;
  top: 0.5em;
  width: 1rem;
  height: 0.55rem;
  border-left: 2.5px solid var(--cyan-deep);
  border-bottom: 2.5px solid var(--cyan-deep);
  transform: rotate(-45deg);
}

.where { font-size: var(--fs-sm); color: var(--steel); }

.owner-grid { display: grid; gap: var(--sp-6); }

.owner-card {
  padding: clamp(var(--sp-6), 3vw, var(--sp-8));
  border: 1px solid var(--line-mid);
  border-radius: var(--r-card);
  background: var(--paper);
  transition: border-color var(--t-fast) var(--ease-soft);
}

.owner-card:hover { border-color: var(--steel); }
.owner-card h3 { margin-bottom: var(--sp-1); }

.owner-role { margin: 0 0 var(--sp-5); font-size: var(--fs-sm); font-weight: 500; color: var(--steel); }

.contact-links { list-style: none; margin: 0; padding: 0; }
.contact-links li + li { border-top: 1px solid var(--line); }

.contact-links a {
  display: flex;
  align-items: center;
  gap: var(--sp-3);
  padding: var(--sp-4) 0;
  color: var(--body-c);
  font-weight: 500;
}

.contact-links a:hover { color: var(--cyan-deep); text-decoration: none; }
.contact-links svg { flex: none; width: 1.1rem; height: 1.1rem; color: var(--cyan-deep); }

.contact-grid { display: grid; gap: clamp(var(--sp-10), 5vw, var(--sp-16)); align-items: start; }

/* Flex/grid items default to min-width:auto, which lets a child's intrinsic
   content (a native <select>, an unbreakable email string) hold its column
   wider than the space actually assigned to it - the root cause of the RFP
   form card clipping off the right edge. min-width:0 on every level of the
   chain is the fix; box-sizing:border-box was already global and didn't
   touch this on its own. */
.contact-grid > * { min-width: 0; }

/* RFP page only (its .contact-grid is the one nested in .page-header;
   contact.html's own contact-grid lives in a separate section and is
   untouched). The form is the single most important element on the site,
   so it gets the larger ~60% share instead of the near-even split, and a
   guaranteed minimum right-edge clearance on desktop. */
@media (min-width: 64em) {
  .page-header .contact-grid {
    grid-template-columns: 0.8fr 1.2fr;
    padding-right: max(var(--gutter), 2.5rem);
  }
}

/* Mobile: form first, contact info below it - people came here to submit
   the form, not to read a block of text before reaching it. */
@media (max-width: 63.99em) {
  #proposal-form { order: -1; }
}

.contact-rows { margin: var(--sp-8) 0 0; }
.contact-rows dl { margin: 0; }

.contact-row {
  display: flex;
  align-items: baseline;
  justify-content: space-between;
  gap: var(--sp-4);
  padding: var(--sp-4) 0;
  border-bottom: 1px solid var(--line-navy);
  min-width: 0;
}

.contact-row dt,
.contact-row dd { min-width: 0; }

.contact-row dd { overflow-wrap: break-word; }

.contact-row dt { font-weight: 600; color: #FFFFFF; font-size: var(--fs-sm); }
.contact-row dd { margin: 0; text-align: right; }
.contact-row a { color: var(--fog); }
.contact-row a:hover { color: #FFFFFF; text-decoration: none; }

.hero-trust {
  list-style: none;
  display: flex;
  flex-wrap: wrap;
  gap: var(--sp-3) var(--sp-8);
  margin: 0;
  padding: var(--sp-6) 0 0;
  border-top: 1px solid var(--line-navy);
}

.hero-trust li {
  display: flex;
  align-items: center;
  gap: var(--sp-2);
  font-size: var(--fs-sm);
  font-weight: 500;
  color: #FFFFFF;
}

.hero-trust svg { width: 1rem; height: 1rem; flex: none; color: var(--cyan); }

.confirm { max-width: 44rem; margin-inline: auto; text-align: center; }

.confirm-mark {
  width: 4rem;
  height: 4rem;
  margin: 0 auto var(--sp-8);
  padding: 1.1rem;
  border-radius: 50%;
  background: var(--cyan);
  color: var(--ink);
}

.stats {
  list-style: none;
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: clamp(var(--sp-8), 4vw, var(--sp-12)) var(--sp-8);
  margin: 0;
  padding: 0;
}

.stat-value {
  display: block;
  font-family: var(--font-display);
  font-size: var(--fs-3xl);
  font-weight: 700;
  line-height: 1;
  letter-spacing: -0.03em;
  color: var(--navy);
  margin-bottom: var(--sp-3);
  font-variant-numeric: tabular-nums;
}

.stat-label { display: block; font-weight: 600; color: var(--ink); margin-bottom: var(--sp-1); }
.stat-note { display: block; font-size: var(--fs-sm); color: var(--steel); line-height: 1.5; }

/* Legacy service accordion (kept: harmless if unused) */
.svc-grid { display: grid; gap: clamp(var(--sp-8), 4vw, var(--sp-12)); align-items: start; }
.svc-media { border-radius: var(--r-card); overflow: hidden; border: 1px solid var(--line); }
.svc-media img { width: 100%; aspect-ratio: 1 / 1; object-fit: cover; }
.svc-list { border-top: 1px solid var(--line); }
.svc-item { border-bottom: 1px solid var(--line); }
.svc-item summary {
  display: flex;
  align-items: center;
  gap: var(--sp-4);
  padding: var(--sp-5) 0;
  cursor: pointer;
  list-style: none;
  font-family: var(--font-display);
  font-size: var(--fs-lg);
  font-weight: 600;
  color: var(--navy);
}
.svc-item summary::-webkit-details-marker { display: none; }
.svc-item summary:hover { color: var(--cyan-deep); }
.svc-icon { flex: none; width: 1.6rem; height: 1.6rem; color: var(--steel); stroke-width: 1.5; }
.svc-item[open] .svc-icon { color: var(--cyan-deep); }
.svc-panel { padding-bottom: var(--sp-5); }
.svc-panel p { margin: 0 0 var(--sp-4); color: var(--steel); max-width: 54ch; }
.svc-panel a { font-weight: 600; }

/* ---- Footer (clean navy block: nav row, review row, quiet base) ----
   Divider hairlines use chrome silver at low alpha so they read as a thin
   line on navy without glowing. */
.site-footer {
  background: var(--navy);
  color: var(--silver);
  border-top: 1px solid rgba(214, 218, 222, 0.4);   /* chrome divider above footer */
  padding-block: clamp(2.5rem, 5vw, 4rem);
}

.footer-inner {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: clamp(1.5rem, 3vw, 2.25rem);
  text-align: center;
}

/* Row 1: primary nav. Stacks vertically on mobile with 44px tap targets,
   becomes a single centered horizontal line at 40em and up. */
.footer-nav {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--sp-2);
  width: 100%;
}

.footer-nav > a:not(.btn) {
  display: inline-flex;
  align-items: center;
  min-height: 2.75rem;             /* 44px tap target on mobile */
  color: var(--silver);
  font-weight: 600;
  font-size: var(--fs-base);
}

@media (min-width: 40em) {
  .footer-nav {
    flex-direction: row;
    flex-wrap: wrap;
    justify-content: center;
    gap: clamp(1.25rem, 3vw, 2.5rem);
  }
  .footer-nav > a:not(.btn) { min-height: 0; padding: 0.5rem 0; }
}

.footer-nav > a:not(.btn):hover { color: #FFFFFF; text-decoration: none; }

/* Request a Proposal reads as the primary action */
.footer-nav .btn-primary { color: var(--ink); }

/* Row 2: Google review on its own line, separated by a chrome hairline */
.footer-review {
  width: 100%;
  padding-top: clamp(1.5rem, 3vw, 2.25rem);
  border-top: 1px solid rgba(214, 218, 222, 0.28);  /* divider between nav and review */
}

.footer-review-link {
  display: inline-flex;
  align-items: center;
  gap: var(--sp-2);
  padding: 0.7rem 1.6rem;
  border: 2px solid var(--cyan);
  border-radius: var(--r-pill);
  color: var(--cyan);
  font-weight: 700;
  font-size: var(--fs-sm);
  transition: background-color var(--t-fast) var(--ease-soft),
    color var(--t-fast) var(--ease-soft);
}

.footer-review-link:hover { background: var(--cyan); color: var(--ink); text-decoration: none; }
.footer-review-link svg { width: 1.05rem; height: 1.05rem; flex: none; }

/* Base: small, quiet identity block, must not compete with the links */
.footer-base {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: var(--sp-3);
  padding-top: clamp(1.25rem, 2.5vw, 1.75rem);
}

.footer-logo { width: auto; height: 40px; }

/* Quiet block uses --fog (navy-body tone, 9.9:1) not --steel: steel blue is a
   light-background color and drops to 2.5:1 on navy, which fails AA. Fog reads
   dimmer than the silver nav links above it while staying legible. */
.footer-meta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 0.4rem 1.25rem;
  margin: 0;
  font-size: var(--fs-sm);
  color: var(--fog);
}

.footer-meta a { color: var(--fog); font-weight: 600; }
.footer-meta a:hover { color: #FFFFFF; text-decoration: none; }
.footer-meta .footer-copy { color: var(--fog); }

/* ---- Motion ---- */
.reveal {
  opacity: 0;
  transform: translateY(20px);
  transition: opacity 600ms var(--ease), transform 600ms var(--ease);
}

.reveal.is-visible { opacity: 1; transform: none; }

@media (prefers-reduced-motion: reduce) {
  .reveal { opacity: 1; transform: none; transition: none; }
  *, *::before, *::after {
    animation-duration: 0.001ms !important;
    transition-duration: 0.001ms !important;
    scroll-behavior: auto !important;
  }
  .btn:hover, .svc-tile:hover { transform: none; }
}

/* ==========================================================================
   Breakpoints
   ========================================================================== */

@media (min-width: 48em) {
  /* Room for the full pill: icon + number */
  .btn-phone { padding: 0.85rem 1.7rem; }
  .btn-phone-num { display: inline; }

  .trust-row li { flex: 1 1 0; }   /* 5 equal badges across, centered */
  .form-row { grid-template-columns: repeat(2, 1fr); }
  .owner-grid { grid-template-columns: repeat(2, 1fr); }
  .masonry { columns: 2; }

  /* 3 columns, feature tile occupies the full-height left column */
  .work-strip { grid-template-columns: repeat(3, 1fr); grid-auto-rows: 1fr; }
  .work-strip figure:first-child { grid-row: span 2; }
  .value-grid { grid-template-columns: repeat(2, 1fr); }
  .stats { grid-template-columns: repeat(4, 1fr); }

  /* One equal column per step, whatever the count. This was repeat(5, 1fr),
     which suited the homepage's five steps but squeezed the financing page's
     three into the left 60% of the container, wrapping the copy and leaving
     the block visibly out of line with the heading above it. */
  .timeline {
    grid-auto-flow: column;
    grid-auto-columns: 1fr;
    gap: var(--sp-4);
  }

  .timeline li { padding-left: 0; padding-top: 4rem; }

  .timeline li::before { top: 0; left: 0; }

  .timeline li:not(:last-child)::after {
    left: 3.2rem;
    right: calc(var(--sp-4) * -1);
    top: 1.45rem;
    bottom: auto;
    width: auto;
    height: 2px;
  }
}

@media (min-width: 64em) {
  .nav-toggle { display: none; }
  .btn-header { display: inline-flex; }
  .site-nav { display: contents; }

  /* Full nav (5 tabs) + two header buttons is tight in the 1024-1280 band.
     Collapse the phone button to icon-only here to make room; the number
     returns at 80em where the wider viewport has space. */
  .btn-phone { padding: 0.6rem; min-width: 2.75rem; min-height: 2.75rem; }
  .btn-phone-num { display: none; }

  .nav-menu {
    position: static;
    display: flex;
    align-items: center;
    gap: var(--sp-6);
    width: auto;
    height: auto;
    padding: 0;
    margin-left: var(--sp-8);
    background: none;
    border: 0;
    overflow: visible;
    transform: none;
    visibility: visible;
  }

  .nav-menu > li { margin: 0; }

  .nav-menu > li > a {
    position: relative;
    padding: var(--sp-2) 0;
    font-size: var(--fs-sm);
    font-weight: 600;
    border-bottom: 0;
    color: var(--steel);
  }

  .nav-menu > li > a:hover { color: var(--navy); }
  .nav-menu > li > a[aria-current="page"] { color: var(--navy); }

  .nav-menu > li > a::after {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    bottom: -2px;
    height: 2px;
    background: var(--cyan);
    transform: scaleX(0);
    transform-origin: left;
    transition: transform var(--t-mid) var(--ease);
  }

  .nav-menu > li > a:hover::after,
  .nav-menu > li > a[aria-current="page"]::after { transform: scaleX(1); }

  /* Desktop dropdown panel */
  .nav-drop-menu {
    position: absolute;
    top: calc(100% + 0.75rem);
    left: 50%;
    transform: translateX(-50%) translateY(6px);
    z-index: 120;
    min-width: 15rem;
    padding: var(--sp-4) var(--sp-5);
    background: var(--paper);
    border: 1px solid var(--line);
    border-radius: var(--r-media);
    box-shadow: var(--sh-md);
    opacity: 0;
    visibility: hidden;
    transition: opacity var(--t-fast) var(--ease-soft),
      transform var(--t-fast) var(--ease), visibility var(--t-fast);
  }

  /* Hover bridge so the pointer can travel to the panel */
  .nav-drop::after {
    content: "";
    position: absolute;
    left: 0;
    right: 0;
    top: 100%;
    height: 0.9rem;
  }

  .nav-drop:hover .nav-drop-menu,
  .nav-drop:focus-within .nav-drop-menu {
    opacity: 1;
    visibility: visible;
    transform: translateX(-50%) translateY(0);
  }

  .nav-drop-menu .nav-group { color: var(--steel); }
  .nav-drop-menu .nav-group:not(:first-child) { margin-top: var(--sp-3); }
  .nav-drop-menu a { color: var(--body-c); }
  .nav-drop-menu a:hover { color: var(--cyan-deep); }

  .nav-menu-cta { display: none; }

  .hero-grid { grid-template-columns: 1.05fr 1fr; }
  .svc-split { grid-template-columns: 0.8fr 1.2fr; }
  .faq-grid { grid-template-columns: 0.85fr 1.15fr; }
  .contact-grid { grid-template-columns: 1fr 1.05fr; }
  .detail-grid { grid-template-columns: 1fr 1fr; }
  .detail-grid--flip .detail-media { order: 2; }
  .masonry { columns: 3; }
  .value-grid { grid-template-columns: repeat(4, 1fr); }
  .svc-grid { grid-template-columns: 1fr 1.1fr; }
}


/* ---- 80em / 1280px+ ----
   On a large monitor the extra width goes to imagery, not to empty margin:
   the gallery gains a fourth column and the work strip promotes its feature
   tile to a 2x2 block. Text stays in the 1216px track for line length. */
@media (min-width: 80em) {
  .masonry { columns: 4; }
  /* Groups with only 3 photos stay at 3 columns even on a wide monitor, so a
     4th empty column never leaves the group looking sparse/unbalanced. */
  .masonry--cols3 { columns: 3; }

  .work-strip { grid-template-columns: repeat(4, 1fr); }
  .work-strip figure:first-child { grid-column: span 2; grid-row: span 2; }
  .work-strip figure:first-child img { aspect-ratio: 1 / 1; }

  /* Room returns: restore the full phone pill with its number */
  .btn-phone { padding: 0.85rem 1.7rem; min-width: 0; }
  .btn-phone-num { display: inline; }
}


/* ==========================================================================
   Sticky mobile conversion bar
   --------------------------------------------------------------------------
   Two actions only, pinned to the bottom of the viewport below 48em/768px:
   "Get a Free Quote" (primary, cyan) and tap-to-call Jake. Deliberately NOT
   the same element as the sticky header, and deliberately never a third
   action - every item added here dilutes the two that book work.

   CSS-only. No JavaScript touches this element at all, so it works with JS
   disabled and cannot be broken by a script error.

   Stacking: z-index 900 sits BELOW the mobile nav overlay (1000) and panel
   (1001) on purpose, so opening the menu covers the bar instead of leaving
   two cyan buttons competing on screen at once.

   Content clearance: .has-cta-bar puts matching padding on the body so the
   bar never hides the end of a page - notably the footer phone number and
   the submit button on rfp.html/contact.html. The class is on <body> rather
   than on body{} globally so a page could opt out if one ever needs to.
   ========================================================================== */
.mobile-cta-bar {
  position: fixed;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 900;
  display: grid;
  grid-template-columns: 1.4fr 1fr;
  gap: var(--sp-3);
  padding: var(--sp-3) var(--sp-4);
  /* Home-indicator clearance on iPhone; resolves to 0 everywhere else */
  padding-bottom: calc(var(--sp-3) + env(safe-area-inset-bottom, 0px));
  background: var(--navy);
  border-top: 1px solid var(--silver);
}

.mobile-cta-bar .btn {
  padding: 0.8rem 1rem;
  /* 44px floor: both actions stay comfortable one-thumb tap targets */
  min-height: 2.75rem;
}

/* Secondary action: outlined against the navy bar. Silver border + white
   text (12.3:1 on navy). Never cyan - cyan is the quote button's alone. */
.mobile-cta-bar .btn-outline {
  background: transparent;
  border-color: var(--silver);
  color: #FFFFFF;
}

.mobile-cta-bar .btn-outline:hover {
  background: #FFFFFF;
  border-color: #FFFFFF;
  color: var(--navy);
}

.mobile-cta-bar .btn svg { width: 1rem; height: 1rem; flex: none; }

/* The bar's own height, reserved at the foot of every page that carries it.
   Measured, not guessed: 47px button + 24px padding-block + 1px border = 72px.
   Reserved at 4.75rem/76px to keep ~4px of slack, because the button's height
   moves by a pixel or two once Archivo and IBM Plex swap in over the fallback
   stacks - and an under-reserve means the bar sits on top of the last line of
   the footer. If the bar's padding or button size ever changes, re-measure
   this: getComputedStyle on .mobile-cta-bar vs. on body's padding-bottom. */
.has-cta-bar {
  padding-bottom: calc(4.75rem + env(safe-area-inset-bottom, 0px));
}

/* Above 48em the header CTA and phone link are both permanently visible, so
   the bar is redundant and its padding reservation is dropped with it. */
@media (min-width: 48em) {
  .mobile-cta-bar { display: none; }
  .has-cta-bar { padding-bottom: 0; }
}


/* ==========================================================================
   Financing (Hearth) — always the secondary action
   --------------------------------------------------------------------------
   HARD RULE: cyan is reserved for primary quote CTAs. No financing element is
   ever cyan, ever a filled button, and never sits above or beside a cyan CTA
   in a way that competes for the click. Financing removes a scheduling
   obstacle; it does not compete with the proposal form.

   Colour by background, because one colour cannot serve both:
     - light sections -> steel blue (6.8:1 on white, 5.9:1 on tint) PASS
     - navy .slab / .photo-band -> silver (12.3:1 on navy) PASS
   Steel blue on navy computes to roughly 2.1:1, so it is never used there.
   Silver is the correct dark-background substitute: it is the established
   secondary colour on navy sitewide and, unlike cyan, carries no primary-CTA
   meaning.

   The dark-background rules use a:not(.btn) so they outrank the sitewide
   `.slab a:not(.btn) { color: var(--cyan) }` on specificity rather than on
   source order alone - otherwise a financing link on navy would inherit the
   cyan that is supposed to be reserved.
   ========================================================================== */

/* Outlined steel button: thank-you page, financing.html hero */
.btn-steel {
  background: transparent;
  border-color: var(--steel);
  color: var(--steel);
}

.btn-steel:hover {
  background: var(--steel);
  border-color: var(--steel);
  color: #FFFFFF;
}

/* Dark contexts: the navy .slab, the photo bands, and the .page-header hero
   scrim (a linear-gradient of rgba(0,12,37,.82) -> rgba(0,42,89,.72) over a
   photo). Steel blue on that composites to roughly 2.2:1 and is genuinely
   unreadable, so the button switches to a silver outline with white text
   (12:1+). It stays visually secondary because it is outlined, not filled -
   the filled cyan pill remains unmistakably the primary action. */
.slab .btn-steel,
.photo-band .btn-steel,
.page-header .btn-steel {
  border-color: var(--silver);
  color: #FFFFFF;
}

.slab .btn-steel:hover,
.photo-band .btn-steel:hover,
.page-header .btn-steel:hover {
  background: #FFFFFF;
  border-color: #FFFFFF;
  color: var(--navy);
}

/* One-line secondary note: under the RFP/contact submit buttons, and under
   the closing CTA button pairs on the homepage and gallery. Text only. */
.finance-note {
  margin: var(--sp-4) 0 0;
  font-size: var(--fs-sm);
  line-height: 1.5;
  color: var(--steel);
  text-align: center;
}

.finance-note a { color: var(--steel); text-decoration: underline; }
.finance-note a:hover { color: var(--navy); }

/* Dark bands: homepage final CTA (.photo-band) and gallery closing (.slab) */
.slab .finance-note,
.photo-band .finance-note { color: var(--fog); }

.slab .finance-note a:not(.btn),
.photo-band .finance-note a:not(.btn) { color: var(--silver); }

.slab .finance-note a:not(.btn):hover,
.photo-band .finance-note a:not(.btn):hover { color: #FFFFFF; }

/* Left-aligned variant for the form cards, where centred text would fight
   the left-aligned labels directly above it. */
.finance-note--start { text-align: left; }

/* The RFP and contact forms are WHITE .form-card islands sitting inside dark
   sections (rfp.html in a .page-header, contact.html in a .slab). Both the
   dark-band rules above and the pre-existing `.page-header p { color: fog }`
   reach inside that card and would render this note light-on-white - 1.7:1,
   and the link 1.4:1. Same trap the checkbox labels and the form heading hit
   before (see the specificity note beside .form-card-heading).
   Beaten explicitly on specificity rather than on source order. */
.form-card p.finance-note { color: var(--steel); }
.form-card p.finance-note a:not(.btn) { color: var(--steel); }
.form-card p.finance-note a:not(.btn):hover { color: var(--navy); }

/* Services page strip: sits below the value stats, inside the same section.
   A quiet bordered band, not a card that competes with the stats above it. */
.finance-strip {
  max-width: 46rem;
  margin: clamp(var(--sp-10), 4vw, var(--sp-12)) auto 0;
  padding: clamp(var(--sp-5), 2.5vw, var(--sp-6));
  border: 1px solid var(--line-mid);
  border-left: 3px solid var(--steel);
  border-radius: var(--r-media);
  background: var(--warm);
}

.finance-strip p { margin: 0 0 var(--sp-3); color: var(--steel); font-size: var(--fs-sm); }
.finance-strip p:last-child { margin-bottom: 0; }
.finance-strip strong { color: var(--ink); }
.finance-strip a { color: var(--steel); text-decoration: underline; font-weight: 600; }
.finance-strip a:hover { color: var(--navy); }

/* Financing page: intro copy above the How It Works timeline */
.finance-lede { max-width: 44rem; }
.finance-lede p { color: var(--body-c); font-size: var(--fs-lg); }

/* Availability line naming the metro suburbs. Left-aligned to match the
   heading and the steps above it - centred, it was the only centred text in
   an otherwise left-aligned section and read as a stray block. */
.finance-area {
  max-width: 46rem;
  margin-top: var(--sp-10);
  color: var(--steel);
  font-size: var(--fs-sm);
}


/* ==========================================================================
   Reviews (.rv-*) — ONE block, identical on every page that shows reviews
   --------------------------------------------------------------------------
   Deliberately namespaced and self-contained. This section does NOT use
   .section / .slab / .head / .container / .btn, because those carry inherited
   colours that have repeatedly leaked into white cards on this site and made
   text invisible (.slab sets color:var(--fog); .page-header p sets fog too).
   Every text element below therefore declares its own colour explicitly, and
   nothing here depends on a parent's inherited value.

   Do not restyle this by adding page-specific overrides. One block, one look.
   ========================================================================== */
.rv-section {
  background: #001B3A;
  padding-block: 48px;
}

/* Mobile/tablet: one centred column, badge stacked under the subhead with a
   24px gap. Becomes a heading-left / badge-right row at 64em (see below). */
.rv-head {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 24px;
  max-width: 720px;
  margin: 0 auto 48px;
  padding-inline: 24px;
  text-align: center;
}

.rv-head-text { min-width: 0; }

.rv-eyebrow {
  display: block;
  margin: 0 0 12px;
  font-family: var(--font-body);
  font-size: 13px;
  font-weight: 700;
  letter-spacing: 0.18em;
  text-transform: uppercase;
  color: #00A9E2;                    /* 6.38:1 on the navy band */
}

.rv-title {
  margin: 0 0 12px;
  font-family: var(--font-display);
  font-size: 28px;
  font-weight: 700;
  line-height: 1.15;
  color: #FFFFFF;
}

.rv-sub {
  margin: 0;
  font-family: var(--font-body);
  font-size: 15px;
  font-weight: 400;
  line-height: 1.5;
  color: #D6DADE;
}

/* ---- Google rating badge ----
   A credential, not a CTA: outlined, transparent, never cyan-filled, and
   never styled like the .rv-btn beside the cards. Hover moves the border
   only. The visible 5.0 is deliberately NOT mirrored into JSON-LD -
   self-serving aggregateRating markup can trigger a manual penalty
   (facts.md > Google rating). */
.rv-badge {
  display: inline-flex;
  align-items: center;
  gap: 16px;
  flex: none;
  padding: 16px 22px;
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid rgba(214, 218, 222, 0.22);
  border-radius: 12px;
  text-decoration: none;
  white-space: nowrap;
  transition: border-color 150ms ease, background-color 150ms ease;
}

/* Hover changes colour only - no movement, no scale. */
.rv-badge:hover,
.rv-badge:focus-visible {
  border-color: rgba(0, 169, 226, 0.6);
  background: rgba(255, 255, 255, 0.07);
  text-decoration: none;
}

/* Google mark. Trademark use: never recoloured, cropped, rotated, or given
   effects. object-fit: contain guarantees it is never stretched whatever box
   it lands in. The badge's 16px gap plus 16px padding keeps clear space on
   every side well above the required quarter of its height (34/4 = 8.5px). */
.rv-badge-logo {
  display: block;
  width: 34px;
  height: 34px;
  flex: none;
  object-fit: contain;
}

/* Divider sits between the mark and the text, matching the text block's
   height via align-self: stretch rather than a hard-coded value. */
.rv-badge-rule {
  align-self: stretch;
  width: 1px;
  flex: none;
  background: rgba(214, 218, 222, 0.3);
}

.rv-badge-text { display: flex; flex-direction: column; min-width: 0; }

/* baseline, not center: the stars sit on the 5.0's baseline so their bottoms
   line up with the bottom of the digits. */
.rv-badge-top { display: flex; align-items: baseline; gap: 10px; }

.rv-badge-stars { display: flex; gap: 2px; }

/* Brighter gold than the card stars: these sit on navy, where --star reads
   3.4:1. --star-navy is 8.3:1 there. Two backgrounds, two values. */
.rv-badge-stars svg { width: 14px; height: 14px; flex: none; color: var(--star-navy); }

/* The hero of the badge - largest, boldest thing in it. */
.rv-badge-score {
  font-family: var(--font-body);
  font-size: 38px;
  font-weight: 800;
  line-height: 1;
  color: #FFFFFF;
}

.rv-badge-label {
  margin-top: 5px;
  font-family: var(--font-body);
  font-size: 11px;
  font-weight: 400;
  letter-spacing: 0.12em;
  text-transform: uppercase;
  color: #D6DADE;
}

/* Below 1024px the badge drops under the subhead and scales down, but keeps
   the same horizontal logo | divider | text arrangement. */
@media (max-width: 63.99em) {
  .rv-badge-logo { width: 28px; height: 28px; }
  .rv-badge-score { font-size: 30px; }
  .rv-badge-stars svg { width: 13px; height: 13px; }
}

.rv-cards {
  display: grid;
  gap: 24px;
  max-width: 1100px;
  margin: 0 auto;
  padding-inline: 24px;              /* keeps cards off the screen edge */
}

.rv-card {
  display: grid;
  grid-template-columns: 1fr;        /* mobile: single column */
  min-height: 320px;
  background: #FFFFFF;
  border-radius: 10px;
  overflow: hidden;                  /* clips the photo to the card corners */
  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.18);
}

.rv-media { position: relative; }

/* Mobile: fixed 220px so both cards' photos match and nothing jumps. */
.rv-media img {
  display: block;
  width: 100%;
  height: 220px;
  margin: 0;
  padding: 0;
  border: 0;
  border-radius: 0;
  object-fit: cover;
}

.rv-body {
  display: flex;
  flex-direction: column;
  justify-content: center;
  padding: 24px;
  min-width: 0;
}

.rv-stars { display: flex; gap: 2px; margin: 0 0 16px; }
.rv-stars svg { width: 16px; height: 16px; flex: none; color: var(--star); }

/* max-width in ch caps the line length so the wider content column becomes
   white space rather than longer, harder-to-read lines. */
.rv-quote {
  max-width: 52ch;
  margin: 0 0 14px;
  font-family: var(--font-display);
  font-size: 17px;
  font-weight: 700;
  line-height: 1.35;
  color: #000C25;
}

.rv-text {
  max-width: 52ch;
  margin: 0 0 20px;
  font-family: var(--font-body);
  font-size: 15px;
  font-weight: 400;
  line-height: 1.6;
  color: #345E82;
}

.rv-divider {
  height: 1px;
  margin: 0 0 20px;
  border: 0;
  background: #D6DADE;
}

.rv-foot { display: flex; align-items: center; gap: 12px; }
.rv-foot svg { width: 20px; height: 20px; flex: none; color: #345E82; }

.rv-name {
  display: block;
  font-family: var(--font-body);
  font-size: 15px;
  font-weight: 700;
  color: #000C25;
}

.rv-source {
  display: block;
  font-family: var(--font-body);
  font-size: 12px;
  font-weight: 400;
  color: #345E82;
}

.rv-cta {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  justify-content: center;
  gap: 24px;
  margin-top: 40px;
  padding-inline: 24px;
}

.rv-btn {
  display: inline-flex;
  align-items: center;
  gap: 8px;
  padding: 14px 28px;
  border: 2px solid #FFFFFF;
  border-radius: 999px;
  background: transparent;
  font-family: var(--font-body);
  font-size: 15px;
  font-weight: 700;
  color: #FFFFFF;
  text-decoration: none;
  transition: background-color 150ms ease, color 150ms ease;
}

.rv-btn:hover { background: #FFFFFF; color: #001B3A; text-decoration: none; }
.rv-btn svg { width: 14px; height: 14px; flex: none; }

.rv-link {
  font-family: var(--font-body);
  font-size: 15px;
  color: #00A9E2;
  text-decoration: none;
}

.rv-link:hover { color: #FFFFFF; text-decoration: underline; }

/* Below 600px the two CTAs stack instead of wrapping unevenly. */
@media (max-width: 37.49em) {
  .rv-cta { flex-direction: column; gap: 16px; }
}

/* --- 768px and up: side-by-side --- */
@media (min-width: 48em) {
  .rv-section { padding-block: 80px; }
  .rv-title { font-size: 40px; }
  .rv-sub { font-size: 17px; }

  /* Both cards take the height of the taller one, so the two photos line up
     as a pair instead of stepping. The shorter card's content stays centred
     via .rv-body's justify-content. Desktop only - on mobile this would just
     add dead space under the shorter quote. */
  .rv-cards { grid-auto-rows: 1fr; }

  .rv-card { grid-template-columns: 1fr 1fr; }
  .rv-body { padding: 36px; }

  /* The photo fills its half WITHOUT setting the card's height. A normal-flow
     <img> carries its intrinsic aspect ratio into the grid row, which let the
     tall portrait photo drive the card and overflow past the content beside
     it. Absolutely positioned, the row height comes from the content and the
     photo simply covers its cell - so the photo can never exceed the card. */
  .rv-media img {
    position: absolute;
    inset: 0;
    height: 100%;
  }

  /* Card 2 only: photo moves to the right half. Source order stays
     photo-first, so the mobile stack needs no reordering at all. */
  .rv-card--flip .rv-media { order: 2; }
}

/* --- 1024px and up: give the quote more room ---
   Photo ~42%, content ~58%. minmax(0, …fr) rather than a bare fr so a long
   unbroken word can never blow the column past its share and push the card
   wider than its container.
   The flip card's ratio is mirrored because .rv-media is ordered into the
   SECOND column there - grid-template-columns describes column positions,
   not source order, so the photo's share is the second value on that card. */
@media (min-width: 64em) {
  .rv-card { grid-template-columns: minmax(0, 0.85fr) minmax(0, 1.15fr); }
  .rv-card--flip { grid-template-columns: minmax(0, 1.15fr) minmax(0, 0.85fr); }

  /* The extra column width becomes padding, not longer lines. */
  .rv-body { padding: 44px; }

  /* Heading left, badge right. The header widens to match .rv-cards exactly
     (same 1100px max-width, same 24px inline padding), so the badge's right
     edge lands on the cards' right edge below it. align-items: flex-start
     pins the badge to the top of the heading block rather than centring it
     against three lines of text. */
  .rv-head {
    flex-direction: row;
    align-items: flex-start;
    justify-content: space-between;
    gap: 32px;
    max-width: 1100px;
    text-align: left;
  }

  .rv-head-text { max-width: 720px; }
}
