/* =========================================================================
 THE HARDWOOD GUYS — CT & NY — COMPONENT LIBRARY
 Ported from the Georgia design system (/Users/davidbrannan/THG Website/
 design/components.css), adapted red-forward for this site. Depends on
 tokens.css (load it first). Every color/spacing/type value below is a
 var(--semantic-token) reference — no raw hex, no raw color literal, ever.
 That is what makes a retone a one-file change.

 Class names are IDENTICAL to Georgia's — the CT build script emits
 Georgia-shaped markup, so nothing here may be renamed.

 Deltas from the Georgia file (see also header.css for header-specific
 deltas):
   - Georgia's wood accent (--color-accent-wood) does not exist in this
     token set. CT has no third accent color — navy is the sole supporting
     accent — so the one Georgia rule that used wood (.process-step) now
     uses --color-accent-navy.
   - Several Georgia rules used raw rgba(255, 255, 255, N) literals for
     translucent-white overlays on dark surfaces. Replaced with
     color-mix(in srgb, var(--white) N%, transparent) so nothing in this
     file is a bare color literal — everything traces back to a token.
   - Added .btn--inverse (not in Georgia): originally a white-filled /
     deep-red-text button for the header and footer bands, where CT's
     bright red CTA fill was invisible on the old --red-deep surface
     (2.20:1). As of the 2026-08-04 gray-glass restyle those bands are
     --gray-ink instead, red passes there (3.32:1, clears the 3:1 non-text
     minimum — see tokens.css "KNOWN CONTRAST TRAPS"), so
     --color-cta-inverse-bg / --color-cta-inverse-text are now simply
     aliases of the primary CTA tokens and .btn--inverse renders identically
     to .btn--primary. Kept as its own class (rather than removed) so the
     header/footer/footer-cta-btn markup didn't need editing.
 ========================================================================= */

/* ---------------------------------------------------------------------
 0. RESET / BASE
 --------------------------------------------------------------------- */
*, *::before, *::after { box-sizing: border-box; }

html {
 -webkit-text-size-adjust: 100%;
 scroll-behavior: smooth;
}
@media (prefers-reduced-motion: reduce) {
 html { scroll-behavior: auto; }
}

body {
 margin: 0;
 font-family: var(--font-body);
 font-size: var(--text-base);
 line-height: var(--leading-normal);
 color: var(--color-text-body);
 background: var(--color-bg-page);
 font-variant-numeric: normal;
}

img, svg { max-width: 100%; display: block; }
button, input, select, textarea { font: inherit; color: inherit; }
ul, ol { padding: 0; margin: 0; list-style: none; }
h1, h2, h3, h4, p, figure, blockquote { margin: 0; }
a { color: inherit; text-decoration: none; }

h1, h2, h3, h4 {
 font-family: var(--font-heading);
 color: var(--color-text-heading);
 line-height: var(--leading-tight);
 font-weight: var(--weight-semibold);
}

.tabular-nums { font-variant-numeric: tabular-nums; }

/* Universal focus-visible treatment — solid outline, never a glow-only
 box-shadow, so it survives on every background in the system. */
:focus-visible {
 outline: 3px solid var(--color-focus-ring);
 outline-offset: 2px;
 border-radius: var(--radius-sm);
}
.site-header :focus-visible,
.site-header__mobile-nav :focus-visible,
.mobile-cta-bar :focus-visible,
.site-footer :focus-visible,
.hero :focus-visible {
 outline-color: var(--color-focus-ring-inverse);
}

/* ---------------------------------------------------------------------
 1. LAYOUT UTILITIES
 --------------------------------------------------------------------- */
.container {
 max-width: var(--container-max);
 margin-inline: auto;
 padding-inline: var(--container-pad);
}

.section {
 padding-block: var(--space-16);
}
.section--alt { background: var(--color-bg-page-alt); }
.section--dark { background: var(--color-bg-header-solid); color: var(--color-text-inverse); }

.section-head {
 max-width: 640px;
 margin-bottom: var(--space-8);
}
.section-head p { color: var(--color-text-muted); margin-top: var(--space-3); }

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

/* Skip link — visible on keyboard focus, WCAG 2.4.1 */
.skip-link {
 position: absolute;
 top: -60px;
 left: var(--space-4);
 z-index: var(--z-skip-link);
 background: var(--color-cta-bg);
 color: var(--color-cta-text);
 padding: var(--space-3) var(--space-5);
 border-radius: 0 0 var(--radius-base) var(--radius-base);
 font-weight: var(--weight-semibold);
 transition: top var(--motion-base) var(--motion-ease);
}
.skip-link:focus {
 top: 0;
}

/* ---------------------------------------------------------------------
 2. BUTTONS
 --------------------------------------------------------------------- */
.btn {
 display: inline-flex;
 align-items: center;
 justify-content: center;
 gap: var(--space-2);
 min-height: var(--touch-target-min);
 padding: var(--space-3) var(--space-6);
 border-radius: var(--radius-base);
 font-family: var(--font-body);
 font-weight: var(--weight-semibold);
 font-size: var(--text-base);
 border: 2px solid transparent;
 cursor: pointer;
 transition: background-color var(--motion-base) var(--motion-ease),
 color var(--motion-base) var(--motion-ease),
 box-shadow var(--motion-base) var(--motion-ease),
 border-color var(--motion-base) var(--motion-ease);
 text-align: center;
}
.btn--lg { padding: var(--space-4) var(--space-8); font-size: var(--text-md); }
.btn--sm { padding: var(--space-2) var(--space-4); font-size: var(--text-sm); min-height: 36px; }
.btn--block { width: 100%; }

.btn--primary {
 background: var(--color-cta-bg);
 color: var(--color-cta-text);
}
.btn--primary:hover { background: var(--color-cta-bg-hover); box-shadow: var(--shadow-md); }
.btn--primary:disabled {
 background: var(--color-cta-bg-disabled);
 color: var(--color-cta-text-disabled);
 cursor: not-allowed;
}

.btn--secondary {
 background: var(--color-btn-secondary-bg);
 color: var(--color-btn-secondary-text);
 border-color: var(--color-btn-secondary-border);
}
.btn--secondary:hover {
 background: var(--color-btn-secondary-hover-bg);
 color: var(--color-btn-secondary-hover-text);
}

/* Outline button — used on top of the hero photo scrim (dark). Hover
 fills solid rather than swapping to red, because red-on-dark is one
 of the documented contrast traps. DARK CONTEXTS ONLY — see header.css
 for why the Georgia light-context overrides were not ported. */
.btn--outline {
 background: transparent;
 color: var(--color-btn-outline-text);
 border-color: var(--color-btn-outline-border);
}
.btn--outline:hover {
 background: var(--color-btn-outline-hover-bg);
 color: var(--color-btn-outline-hover-text);
}

/* Inverse button — CT-only, not in Georgia. Originally needed for the dark
 red header/footer bands, where a bright-red CTA fill was invisible (red on
 red-deep = 2.20:1, a documented trap in tokens.css). Since the 2026-08-04
 gray-glass restyle those bands are --gray-ink and red passes there as a
 button fill (3.32:1), so --color-cta-inverse-bg/-text are now aliases of
 the primary CTA tokens (see tokens.css) and this hover state matches
 .btn--primary's darken-and-shadow treatment instead of its old
 translucent-fill-plus-underline compromise. */
.btn--inverse {
 background: var(--color-cta-inverse-bg);
 color: var(--color-cta-inverse-text);
}
.btn--inverse:hover,
.btn--inverse:focus-visible {
 background: var(--color-cta-bg-hover);
 color: var(--color-cta-inverse-text);
 box-shadow: var(--shadow-md);
}

.btn svg { width: 1.15em; height: 1.15em; flex: none; }

/* ---------------------------------------------------------------------
 3. HEADER
 --------------------------------------------------------------------- */
/* Base layer: sticky + solid. header.css loads LAST and overrides
   position/background to fixed + translucent glass (see its "GLASS HEADER"
   section) — this solid value is what @supports fallback and any
   header.css load failure would leave visible, so it must not be a stale
   token. */
.site-header {
 position: sticky;
 top: 0;
 z-index: var(--z-header);
 background: var(--color-bg-header-solid);
 color: var(--color-text-inverse);
 box-shadow: var(--shadow-header);
}

.site-header__bar {
 display: flex;
 align-items: center;
 gap: var(--space-6);
 min-height: 72px;
 padding-block: var(--space-2);
}

.site-header__logo {
 display: flex;
 align-items: center;
 gap: var(--space-2);
 flex: none;
 max-width: 260px;
 color: var(--color-text-inverse);
}
/* The mark is a near-square badge (1391x1175), not a wide wordmark — it needs real
   height to read. David asked for it prominently displayed. */
.site-header__logo-mark { height: 92px; width: auto; display: block; flex: none; }
@media (max-width: 900px) {
  .site-header__logo-mark { height: 76px; }
}
@media (max-width: 480px) {
  .site-header__logo-mark { height: 58px; }
}

/* The bar carries logo + 6 nav items + phone + hours + CTA. Below 1400px the
   decorative tagline is the first thing to go — the crest already says who we
   are, and the footer NAP block repeats the location. */
@media (max-width: 1400px) {
  .site-header__logo-tag { display: none; }
}
/* Keep a real gutter between the last nav item and the phone block. */
.site-header__bar { column-gap: var(--space-8); }

.site-header__logo-word {
 font-family: var(--font-heading);
 font-weight: var(--weight-bold);
 font-size: 1.35rem;
 line-height: 1.1;
 letter-spacing: var(--tracking-tight);
}
.site-header__logo-tag {
 display: block;
 white-space: nowrap;
 font-family: var(--font-body);
 font-size: var(--text-xs);
 font-weight: var(--weight-medium);
 letter-spacing: var(--tracking-wide);
 text-transform: uppercase;
 color: var(--color-text-inverse);
 opacity: 0.85;
}

.site-nav { flex: 1; display: none; min-width: 0; }
.site-nav ul { display: flex; gap: var(--space-5); flex-wrap: nowrap; white-space: nowrap; }
@media (max-width: 1100px) {
  .site-nav ul { gap: var(--space-4); }
}
.site-nav a {
 display: inline-block;
 padding: var(--space-2) 0;
 font-weight: var(--weight-medium);
 color: var(--color-nav-link);
 border-bottom: 2px solid transparent;
}
.site-nav a:hover,
.site-nav a:focus-visible {
 text-decoration: underline;
 text-underline-offset: 4px;
}

.site-header__meta {
 display: none;
 flex-direction: column;
 align-items: flex-end;
 line-height: 1.3;
 flex: none;
}
.site-header__phone {
 font-weight: var(--weight-bold);
 font-size: var(--text-md);
 color: var(--color-text-inverse);
}
.site-header__phone:hover,
.site-header__phone:focus-visible { text-decoration: underline; }
.site-header__hours {
 font-size: var(--text-xs);
 color: var(--color-text-inverse);
 opacity: 0.85;
}
.site-header__cta { display: none; flex: none; }

.hamburger {
 flex: none;
 margin-left: auto;
 display: inline-flex;
 align-items: center;
 justify-content: center;
 width: var(--touch-target-min);
 height: var(--touch-target-min);
 background: transparent;
 border: 2px solid transparent;
 border-radius: var(--radius-base);
 color: var(--color-text-inverse);
 cursor: pointer;
}
.hamburger svg { width: 26px; height: 26px; }
.hamburger .icon-close { display: none; }
.hamburger[aria-expanded="true"] .icon-menu { display: none; }
.hamburger[aria-expanded="true"] .icon-close { display: block; }

.site-header__mobile-nav {
 position: fixed;
 /* Top offset matches the fixed header's real height (--header-h, set in
    header.css), not a hardcoded guess. Solid, not glass: a translucent
    blurred panel full of stacked nav text would be harder to read than
    the header bar itself, where it sits over a photo/short label only. */
 inset: var(--header-h) 0 0 0;
 background: var(--color-bg-header-solid);
 z-index: var(--z-mobile-nav);
 overflow-y: auto;
 padding: var(--space-6) var(--container-pad) var(--space-24);
}
.site-header__mobile-nav[hidden] { display: none; }

.site-header__mobile-nav ul { display: flex; flex-direction: column; }
.site-header__mobile-nav a {
 display: block;
 padding: var(--space-4) 0;
 font-family: var(--font-heading);
 font-size: var(--text-lg);
 font-weight: var(--weight-semibold);
 color: var(--color-text-inverse);
 border-bottom: 1px solid color-mix(in srgb, var(--white) 18%, transparent);
}
.site-header__mobile-nav a:hover,
.site-header__mobile-nav a:focus-visible { text-decoration: underline; }

.site-header__mobile-meta {
 margin-top: var(--space-8);
 padding-top: var(--space-8);
 border-top: 1px solid color-mix(in srgb, var(--white) 25%, transparent);
}
.site-header__mobile-meta .site-header__phone { font-size: var(--text-xl); }
.site-header__mobile-meta .site-header__hours { display: block; margin-top: var(--space-2); }

@media (min-width: 1024px) {
 .site-nav { display: block; }
 .site-header__meta { display: flex; }
 .site-header__cta { display: inline-flex; }
 .hamburger { display: none; }
}

/* ---------------------------------------------------------------------
 4. MOBILE STICKY BOTTOM CTA BAR
 The single most important conversion element on the site: it is the
 only UI guaranteed to be on-screen no matter how far a phone user has
 scrolled. Two 44px+ targets, safe-area aware, always visible.
 --------------------------------------------------------------------- */
.mobile-cta-bar {
 position: fixed;
 left: 0; right: 0; bottom: 0;
 z-index: var(--z-bottom-bar);
 display: grid;
 grid-template-columns: 1fr 1.3fr;
 gap: 1px;
 background: var(--color-border-default);
 box-shadow: var(--shadow-bottom-bar);
 padding-bottom: env(safe-area-inset-bottom, 0);
}
.mobile-cta-bar a {
 display: flex;
 align-items: center;
 justify-content: center;
 gap: var(--space-2);
 min-height: var(--touch-target-min);
 padding-block: var(--space-4);
 font-weight: var(--weight-bold);
 font-size: var(--text-base);
}
.mobile-cta-bar__call {
 background: var(--color-bg-header-solid);
 color: var(--color-text-inverse);
}
.mobile-cta-bar__call:hover,
.mobile-cta-bar__call:focus-visible { text-decoration: underline; }
.mobile-cta-bar__estimate {
 background: var(--color-cta-bg);
 color: var(--color-cta-text);
}
.mobile-cta-bar__estimate:hover,
.mobile-cta-bar__estimate:focus-visible { background: var(--color-cta-bg-hover); }
.mobile-cta-bar svg { width: 20px; height: 20px; }

/* Reserve space so the fixed bar never covers the last content/footer */
.has-mobile-cta-bar { padding-bottom: 64px; }

@media (min-width: 1024px) {
 .mobile-cta-bar { display: none; }
 .has-mobile-cta-bar { padding-bottom: 0; }
}

/* ---------------------------------------------------------------------
 5. PLACEHOLDER PHOTO BLOCK
 Every "photo" in this system is a placeholder — never a hotlinked
 live-site image, never an external request. The pattern + label make
 it obvious in review that real photography drops in later.
 --------------------------------------------------------------------- */
.photo-placeholder {
 position: relative;
 display: flex;
 align-items: flex-end;
 overflow: hidden;
 background:
 repeating-linear-gradient(135deg,
 rgba(var(--navy-rgb), 0.10) 0px, rgba(var(--navy-rgb), 0.10) 2px,
 transparent 2px, transparent 14px),
 var(--color-bg-page-alt);
 border: 1px solid var(--color-border-default);
 color: var(--color-text-muted);
 aspect-ratio: 4 / 3;
}
.photo-placeholder--wide { aspect-ratio: 16 / 9; }
.photo-placeholder--tall { aspect-ratio: 3 / 4; }
.photo-placeholder--square { aspect-ratio: 1 / 1; }
.photo-placeholder__label {
 display: flex;
 align-items: center;
 gap: var(--space-2);
 width: 100%;
 padding: var(--space-3);
 background: linear-gradient(to top, rgba(var(--near-black-rgb), 0.55), transparent);
 color: var(--white);
 font-size: var(--text-xs);
 font-weight: var(--weight-medium);
}
.photo-placeholder__label svg { width: 18px; height: 18px; flex: none; }

/* ---------------------------------------------------------------------
 6. HERO
 --------------------------------------------------------------------- */
.hero {
 position: relative;
 color: var(--color-text-inverse);
 overflow: hidden; /* required so the Ken Burns zoom below never shows a scaled edge */
}
.hero__media {
 position: absolute;
 inset: 0;
 background:
 linear-gradient(rgba(var(--near-black-rgb), 0.62), rgba(var(--near-black-rgb), 0.5)),
 repeating-linear-gradient(120deg,
 color-mix(in srgb, var(--white) 6%, transparent) 0px, color-mix(in srgb, var(--white) 6%, transparent) 2px,
 transparent 2px, transparent 18px),
 var(--color-bg-header-solid);
 z-index: 0;
}

/* ---- Ken Burns: slow drift on the homepage hero photo -----------------
   The real homepage hero photo is <img class="hero__media"> (see
   header.css "HERO PHOTO AS <img>" — no page in site/ uses the
   ".hero-media img" wrapper shape the original brief named; the actual
   built markup is a single <img class="hero__media">). Targeting
   .hero__media directly is the equivalent selector for this codebase.
   header.css's older thg-kenburns keyframe no longer touches this
   selector (see the note in header.css) so this is the only animation
   driving it. */
@keyframes hwg-kenburns {
  from { transform: scale(1.02); }
  to   { transform: scale(1.14) translate(-1.5%, -1%); }
}
.hero__media {
  animation: hwg-kenburns 24s ease-out forwards;
  transform-origin: 60% 40%;
  will-change: transform;
}
@media (prefers-reduced-motion: reduce) {
  .hero__media {
    animation: none;
  }
}
.hero__media-tag {
 position: absolute;
 bottom: var(--space-4);
 right: var(--space-4);
 z-index: 1;
 font-size: var(--text-xs);
 color: var(--white);
 opacity: 0.7;
 background: rgba(var(--near-black-rgb), 0.4);
 padding: var(--space-1) var(--space-3);
 border-radius: var(--radius-full);
}
.hero__content {
 position: relative;
 z-index: 1;
 /* The header is now fixed + translucent (header.css), so it no longer
    pushes .hero down in normal flow — the photo intentionally runs full
    bleed under it, but the readable copy must clear it. Top padding gains
    --header-h; the original --space-20 is trimmed down so the total visual
    gap stays in the same ballpark rather than doubling. */
 padding-block: calc(var(--header-h) + var(--space-10)) var(--space-16);
 max-width: 760px;
}
.hero__eyebrow {
 font-size: var(--text-sm);
 font-weight: var(--weight-semibold);
 letter-spacing: var(--tracking-wide);
 text-transform: uppercase;
 color: var(--white);
 opacity: 0.9;
 margin-bottom: var(--space-4);
}
.hero__title {
 font-size: var(--text-4xl);
 color: var(--white);
 letter-spacing: var(--tracking-tight);
 margin-bottom: var(--space-5);
}
.hero__subtitle {
 font-size: var(--text-md);
 line-height: var(--leading-relaxed);
 color: var(--white);
 max-width: 56ch;
 margin-bottom: var(--space-8);
}

.proof-chips {
 display: flex;
 flex-wrap: wrap;
 gap: var(--space-3);
 margin-bottom: var(--space-8);
}
.proof-chip {
 display: inline-flex;
 align-items: center;
 gap: var(--space-2);
 padding: var(--space-2) var(--space-4);
 border-radius: var(--radius-full);
 background: color-mix(in srgb, var(--white) 12%, transparent);
 border: 1px solid color-mix(in srgb, var(--white) 35%, transparent);
 font-size: var(--text-sm);
 font-weight: var(--weight-medium);
 color: var(--white);
}
.proof-chip svg { width: 18px; height: 18px; flex: none; }
/* Gold, sparingly: only the review-star and TV icons, per brand
 direction. Icon-only so chip text stays white for readability against
 the photo scrim (gold text on white/red both fail contrast — see
 tokens.css known traps). */
.proof-chip__icon--gold { color: var(--color-rating-star); }

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

/* ---------------------------------------------------------------------
 7. REVIEW BAND
 --------------------------------------------------------------------- */
.reviews__head {
 display: flex;
 flex-wrap: wrap;
 align-items: center;
 justify-content: space-between;
 gap: var(--space-4);
 margin-bottom: var(--space-8);
}
.review-badge {
 display: inline-flex;
 align-items: center;
 gap: var(--space-3);
 padding: var(--space-3) var(--space-5);
 background: var(--color-bg-card);
 border: 1px solid var(--color-border-default);
 border-radius: var(--radius-base);
 box-shadow: var(--shadow-sm);
}
.review-badge__stars { display: flex; gap: 2px; color: var(--color-rating-star); }
.review-badge__stars svg { width: 18px; height: 18px; }
.review-badge__text { font-size: var(--text-sm); color: var(--color-text-body); font-weight: var(--weight-medium); }
.review-badge__text strong { display: block; font-size: var(--text-base); color: var(--color-text-heading); }

.reviews__list {
 display: grid;
 gap: var(--space-6);
 grid-template-columns: 1fr;
}
.review-card {
 background: var(--color-bg-card);
 border: 1px solid var(--color-border-default);
 border-radius: var(--radius-lg);
 padding: var(--space-6);
 box-shadow: var(--shadow-sm);
 display: flex;
 flex-direction: column;
 gap: var(--space-4);
}
.review-card__stars { display: flex; gap: 2px; color: var(--color-rating-star); }
.review-card__stars svg { width: 16px; height: 16px; }
.review-card blockquote {
 font-size: var(--text-base);
 line-height: var(--leading-relaxed);
 color: var(--color-text-body);
}
.review-card__author {
 font-weight: var(--weight-semibold);
 color: var(--color-text-heading);
 font-size: var(--text-sm);
}
.review-card__location { color: var(--color-text-muted); font-weight: var(--weight-regular); }

.reviews__stat {
 margin-top: var(--space-8);
 text-align: center;
 color: var(--color-text-muted);
 font-size: var(--text-sm);
}
.reviews__stat strong { color: var(--color-text-heading); font-family: var(--font-heading); font-size: var(--text-lg); }

@media (min-width: 768px) {
 .reviews__list { grid-template-columns: repeat(3, 1fr); }
}

/* ---------------------------------------------------------------------
 8. QUOTE FORM
 --------------------------------------------------------------------- */
.quote-form-wrap {
 background: var(--color-bg-card);
 border: 1px solid var(--color-border-default);
 border-radius: var(--radius-lg);
 box-shadow: var(--shadow-md);
 padding: var(--space-8);
 max-width: 720px;
 margin-inline: auto;
}

.form-error-summary {
 display: none;
 background: var(--color-bg-error);
 border: 1px solid var(--color-border-input-error);
 border-left: 4px solid var(--color-text-error);
 border-radius: var(--radius-base);
 padding: var(--space-4) var(--space-5);
 margin-bottom: var(--space-6);
 color: var(--color-text-error);
 font-weight: var(--weight-semibold);
 gap: var(--space-2);
 align-items: flex-start;
}
.form-error-summary.is-visible { display: flex; }
.form-error-summary svg { width: 22px; height: 22px; flex: none; margin-top: 2px; }
.form-error-summary a { text-decoration: underline; color: var(--color-text-error); }

.form-grid {
 display: grid;
 gap: var(--space-5);
 grid-template-columns: 1fr;
}
.form-field { display: flex; flex-direction: column; gap: var(--space-2); }
.form-field--span2 { grid-column: 1 / -1; }

.form-field label {
 font-weight: var(--weight-semibold);
 font-size: var(--text-sm);
 color: var(--color-text-heading);
}
.form-field .optional-tag {
 font-weight: var(--weight-regular);
 color: var(--color-text-muted);
 text-transform: none;
}
.form-field input[type="text"],
.form-field input[type="tel"],
.form-field input[type="email"],
.form-field input[type="number"],
.form-field select,
.form-field textarea {
 min-height: var(--touch-target-min);
 padding: var(--space-3) var(--space-4);
 border: 2px solid var(--color-border-input);
 border-radius: var(--radius-base);
 background: var(--color-bg-input);
 font-size: var(--text-base);
 color: var(--color-text-body);
}
.form-field textarea { min-height: 120px; resize: vertical; }
.form-field select {
 appearance: none;
 background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%236B6B6B' stroke-width='2.5' stroke-linecap='round' stroke-linejoin='round'%3E%3Cpolyline points='6 9 12 15 18 9'/%3E%3C/svg%3E");
 background-repeat: no-repeat;
 background-position: right var(--space-4) center;
 background-size: 18px;
 padding-right: var(--space-10);
}
.form-field input:focus-visible,
.form-field select:focus-visible,
.form-field textarea:focus-visible {
 outline: 3px solid var(--color-focus-ring);
 outline-offset: 1px;
 border-color: var(--color-focus-ring);
}
.form-field input[aria-invalid="true"],
.form-field select[aria-invalid="true"],
.form-field textarea[aria-invalid="true"] {
 border-color: var(--color-border-input-error);
}
.field-error {
 display: none;
 align-items: center;
 gap: var(--space-1);
 font-size: var(--text-sm);
 color: var(--color-text-error);
 font-weight: var(--weight-medium);
}
.field-error.is-visible { display: flex; }
.field-error svg { width: 16px; height: 16px; flex: none; }
.field-hint { font-size: var(--text-sm); color: var(--color-text-muted); }

.form-checkbox {
 display: flex;
 align-items: flex-start;
 gap: var(--space-3);
}
.form-checkbox input[type="checkbox"] {
 width: 24px; height: 24px;
 flex: none;
 margin-top: 2px;
 accent-color: var(--color-cta-bg);
}
.form-checkbox label { font-weight: var(--weight-regular); font-size: var(--text-sm); color: var(--color-text-body); }

.form-actions { margin-top: var(--space-2); }
.form-fine-print {
 font-size: var(--text-xs);
 color: var(--color-text-muted);
 margin-top: var(--space-3);
}

.form-success {
 display: none;
 text-align: center;
 padding: var(--space-10) var(--space-4);
}
.form-success.is-visible { display: block; }
.form-success__icon {
 width: 56px; height: 56px;
 margin-inline: auto var(--space-4);
 color: var(--color-text-success);
 background: var(--color-bg-success);
 border: 2px solid var(--color-text-heading);
 border-radius: var(--radius-full);
 display: flex; align-items: center; justify-content: center;
}
.form-success h3 { margin-bottom: var(--space-2); }
.form-success p { color: var(--color-text-muted); max-width: 46ch; margin-inline: auto; }
.quote-form.is-submitted .form-grid,
.quote-form.is-submitted .form-checkbox,
.quote-form.is-submitted .form-actions,
.quote-form.is-submitted .form-fine-print { display: none; }

@media (min-width: 640px) {
 .form-grid { grid-template-columns: 1fr 1fr; }
}

/* ---------------------------------------------------------------------
 9. VIDEO STRIP (YouTube facade — real iframe only injected on click)
 --------------------------------------------------------------------- */
.video-grid {
 display: grid;
 gap: var(--space-6);
 grid-template-columns: 1fr;
}
.video-card { display: flex; flex-direction: column; gap: var(--space-3); }
.video-thumb {
 position: relative;
 width: 100%;
 aspect-ratio: 16 / 9;
 border-radius: var(--radius-base);
 overflow: hidden;
 border: 0;
 padding: 0;
 cursor: pointer;
 background:
 linear-gradient(rgba(var(--near-black-rgb), 0.35), rgba(var(--near-black-rgb), 0.55)),
 repeating-linear-gradient(135deg,
 color-mix(in srgb, var(--white) 8%, transparent) 0px, color-mix(in srgb, var(--white) 8%, transparent) 2px,
 transparent 2px, transparent 16px),
 var(--color-bg-header-solid);
}
.video-thumb__play {
 position: absolute;
 inset: 0;
 display: flex;
 align-items: center;
 justify-content: center;
}
.video-thumb__play svg {
 width: 64px; height: 64px;
 color: var(--white);
 filter: drop-shadow(0 2px 6px rgba(var(--near-black-rgb), 0.4));
}
.video-thumb:hover .video-thumb__play svg,
.video-thumb:focus-visible .video-thumb__play svg { transform: scale(1.08); }
.video-thumb__play svg { transition: transform var(--motion-base) var(--motion-ease); }
.video-thumb__duration {
 position: absolute;
 bottom: var(--space-2);
 right: var(--space-2);
 background: rgba(var(--near-black-rgb), 0.75);
 color: var(--white);
 font-size: var(--text-xs);
 font-weight: var(--weight-semibold);
 padding: 2px var(--space-2);
 border-radius: var(--radius-sm);
}
.video-card__title {
 font-size: var(--text-sm);
 font-weight: var(--weight-medium);
 color: var(--color-text-body);
 line-height: var(--leading-snug);
}
.video-embed-frame {
 width: 100%;
 aspect-ratio: 16 / 9;
 border: 0;
 border-radius: var(--radius-base);
}

@media (min-width: 768px) {
 .video-grid { grid-template-columns: repeat(2, 1fr); }
}
@media (min-width: 1024px) {
 .video-grid { grid-template-columns: repeat(4, 1fr); }
}

/* ---------------------------------------------------------------------
 10. PROCESS STRIP
 --------------------------------------------------------------------- */
.process-grid {
 display: grid;
 gap: var(--space-8);
 grid-template-columns: 1fr;
 counter-reset: process;
}
.process-step {
 position: relative;
 padding-top: var(--space-4);
 /* Georgia used --color-accent-wood here (a third, non-CTA accent color).
    CT has no wood accent — navy is the sole supporting color on this
    red-forward site — so this uses --color-accent-navy instead. Still
    never red: red stays reserved exclusively for clickable CTAs so it
    never loses signal strength through decorative reuse. */
 border-top: 3px solid var(--color-accent-navy);
}
.process-step__icon {
 width: 48px; height: 48px;
 color: var(--color-text-heading);
 margin-bottom: var(--space-4);
}
.process-step__number {
 font-family: var(--font-heading);
 font-size: var(--text-sm);
 font-weight: var(--weight-bold);
 color: var(--color-text-muted);
 letter-spacing: var(--tracking-wide);
 margin-bottom: var(--space-2);
}
.process-step h3 { font-size: var(--text-lg); margin-bottom: var(--space-2); }
.process-step p { color: var(--color-text-muted); }

@media (min-width: 768px) {
 .process-grid { grid-template-columns: repeat(3, 1fr); }
}

/* ---------------------------------------------------------------------
 11. FINANCING STRIP
 --------------------------------------------------------------------- */
.financing-strip {
 background: var(--color-strip-bg);
 color: var(--color-strip-text);
 border-block: 1px solid var(--color-border-default);
 padding-block: var(--space-6);
}
.financing-strip__row {
 display: flex;
 flex-wrap: wrap;
 align-items: center;
 justify-content: center;
 gap: var(--space-3);
 text-align: center;
 font-size: var(--text-base);
 font-weight: var(--weight-medium);
}
.financing-strip__row svg { width: 28px; height: 28px; color: var(--color-strip-accent); flex: none; }
.financing-strip strong { color: var(--color-text-heading); }
.financing-strip small { display: block; color: var(--color-text-muted); font-size: var(--text-xs); margin-top: var(--space-1); }

/* ---------------------------------------------------------------------
 12. SERVICE CARDS
 --------------------------------------------------------------------- */
.service-grid {
 display: grid;
 gap: var(--space-6);
 grid-template-columns: 1fr;
}
.service-card {
 display: flex;
 flex-direction: column;
 background: var(--color-bg-card);
 border: 1px solid var(--color-border-default);
 border-radius: var(--radius-lg);
 overflow: hidden;
 box-shadow: var(--shadow-sm);
 transition: box-shadow var(--motion-base) var(--motion-ease), transform var(--motion-base) var(--motion-ease);
}
.service-card:hover { box-shadow: var(--shadow-lg); transform: translateY(-2px); }
.service-card__body { padding: var(--space-6); display: flex; flex-direction: column; gap: var(--space-3); flex: 1; }
.service-card h3 { font-size: var(--text-lg); }
.service-card p { color: var(--color-text-muted); flex: 1; }
.service-card__links {
 display: flex;
 flex-wrap: wrap;
 gap: var(--space-4);
 margin-top: var(--space-2);
}
.service-card__links a {
 font-weight: var(--weight-semibold);
 font-size: var(--text-sm);
 color: var(--color-text-link);
 display: inline-flex;
 align-items: center;
 gap: var(--space-1);
 min-height: var(--touch-target-min);
}
.service-card__links a:hover,
.service-card__links a:focus-visible { color: var(--color-text-link-hover); text-decoration: underline; }
.service-card__links a.is-primary { color: var(--color-cta-bg); }
.service-card__links a.is-primary:hover,
.service-card__links a.is-primary:focus-visible { color: var(--color-cta-bg-hover); }
.service-card__links svg { width: 16px; height: 16px; }

@media (min-width: 640px) {
 .service-grid { grid-template-columns: repeat(2, 1fr); }
}
@media (min-width: 1024px) {
 .service-grid { grid-template-columns: repeat(4, 1fr); }
}

/* ---------------------------------------------------------------------
 13. BEFORE / AFTER SLIDER
 Vanilla JS drag + keyboard operable (Arrow Left/Right, Home, End).
 Respects prefers-reduced-motion (no transition on drag/keys, only an
 instant position update) — see components.html script.
 --------------------------------------------------------------------- */
.ba-slider {
 position: relative;
 width: 100%;
 aspect-ratio: 4 / 3;
 border-radius: var(--radius-lg);
 overflow: hidden;
 border: 1px solid var(--color-border-default);
 box-shadow: var(--shadow-sm);
 touch-action: pan-y;
 user-select: none;
}
.ba-slider__after,
.ba-slider__before {
 position: absolute;
 inset: 0;
 aspect-ratio: auto;
 border: 0;
 border-radius: 0;
}
.ba-slider__before {
 /* clipped by JS setting inline width % — starts at 50 */
 width: 50%;
 overflow: hidden;
}
.ba-slider__before .photo-placeholder,
.ba-slider__after .photo-placeholder {
 position: absolute;
 inset: 0;
 width: var(--ba-fixed-width, 100%);
 height: 100%;
 border-radius: 0;
 border: 0;
}
.ba-slider__before .photo-placeholder { width: 100vw; max-width: none; }
.ba-slider__handle {
 position: absolute;
 top: 0;
 bottom: 0;
 left: 50%;
 width: 4px;
 background: var(--white);
 transform: translateX(-50%);
 box-shadow: 0 0 0 1px rgba(var(--near-black-rgb), 0.25);
}
.ba-slider__handle-grip {
 position: absolute;
 top: 50%;
 left: 50%;
 transform: translate(-50%, -50%);
 width: var(--touch-target-min);
 height: var(--touch-target-min);
 border-radius: var(--radius-full);
 background: var(--white);
 color: var(--color-text-heading);
 display: flex;
 align-items: center;
 justify-content: center;
 box-shadow: var(--shadow-md);
 cursor: ew-resize;
 border: 3px solid var(--color-cta-bg);
}
.ba-slider__handle-grip:focus-visible {
 outline: 3px solid var(--color-focus-ring);
 outline-offset: 3px;
}
.ba-slider__handle-grip svg { width: 22px; height: 22px; }
.ba-slider__tag {
 position: absolute;
 top: var(--space-3);
 z-index: 1;
 padding: var(--space-1) var(--space-3);
 border-radius: var(--radius-full);
 font-size: var(--text-xs);
 font-weight: var(--weight-bold);
 letter-spacing: var(--tracking-wide);
 text-transform: uppercase;
 background: rgba(var(--near-black-rgb), 0.65);
 color: var(--white);
}
.ba-slider__tag--before { left: var(--space-3); }
.ba-slider__tag--after { right: var(--space-3); }
.ba-caption {
 margin-top: var(--space-3);
 font-size: var(--text-sm);
 color: var(--color-text-muted);
 text-align: center;
}

/* ---------------------------------------------------------------------
 14. FOOTER — the only place disclaimers live (Canonical Decision #4)
 --------------------------------------------------------------------- */
.site-footer {
 background: var(--color-bg-footer);
 color: var(--color-text-inverse);
 padding-block: var(--space-16) var(--space-8);
}
.footer-grid {
 display: grid;
 gap: var(--space-10);
 grid-template-columns: 1fr;
 padding-bottom: var(--space-10);
 border-bottom: 1px solid color-mix(in srgb, var(--white) 20%, transparent);
}
/* Intentionally a styled <p>, not a heading element: footer nav groups are
 already labeled via aria-label on each <nav>, so no heading tag is
 introduced here. Keeps the document's heading outline (H1 → H2 → H3)
 uninterrupted by the footer, which sits after the last real heading. */
.footer-col-title {
 color: var(--color-text-inverse);
 font-size: var(--text-sm);
 font-weight: var(--weight-bold);
 letter-spacing: var(--tracking-wide);
 text-transform: uppercase;
 margin-bottom: var(--space-4);
}
.footer-col ul { display: flex; flex-direction: column; gap: var(--space-3); }
.footer-col a { color: var(--color-nav-link); opacity: 0.9; }
.footer-col a:hover, .footer-col a:focus-visible { text-decoration: underline; opacity: 1; }
.footer-brand p { color: var(--color-text-inverse); opacity: 0.85; max-width: 40ch; margin-top: var(--space-3); }
.footer-brand .site-header__phone { font-size: var(--text-lg); display: inline-block; margin-top: var(--space-4); }
.footer-social { display: flex; gap: var(--space-3); margin-top: var(--space-5); }
.footer-social a {
 width: 40px; height: 40px;
 display: flex; align-items: center; justify-content: center;
 border: 1px solid color-mix(in srgb, var(--white) 40%, transparent);
 border-radius: var(--radius-full);
}
.footer-social svg { width: 18px; height: 18px; }

.footer-bottom {
 margin-top: var(--space-8);
 display: flex;
 flex-direction: column;
 gap: var(--space-4);
 font-size: var(--text-xs);
 color: var(--color-text-inverse);
 opacity: 0.75;
}
.footer-disclaimer { max-width: 80ch; line-height: var(--leading-relaxed); }
.footer-legal { display: flex; flex-wrap: wrap; gap: var(--space-2) var(--space-5); }
.footer-legal a { text-decoration: underline; }

@media (min-width: 640px) {
 .footer-grid { grid-template-columns: repeat(2, 1fr); }
}
@media (min-width: 1024px) {
 .footer-grid { grid-template-columns: 1.4fr 1fr 1fr 1fr; }
 .footer-bottom { flex-direction: row; align-items: center; justify-content: space-between; }
}

/* ---------------------------------------------------------------------
 15. MISC
 --------------------------------------------------------------------- */
.badge-row {
 display: flex;
 flex-wrap: wrap;
 gap: var(--space-3);
 align-items: center;
}

.eyebrow {
 display: inline-block;
 font-size: var(--text-sm);
 font-weight: var(--weight-semibold);
 letter-spacing: var(--tracking-wide);
 text-transform: uppercase;
 color: var(--color-cta-bg);
 margin-bottom: var(--space-3);
}

.showcase-block {
 border: 1px dashed var(--color-border-default);
 border-radius: var(--radius-lg);
 padding: var(--space-6);
 margin-bottom: var(--space-16);
}
.showcase-index {
 padding-block: var(--space-4);
 border-bottom: 1px solid var(--color-border-default);
 background: var(--color-bg-page-alt);
}
.showcase-index p {
 font-size: var(--text-xs);
 font-weight: var(--weight-bold);
 letter-spacing: var(--tracking-wide);
 text-transform: uppercase;
 color: var(--color-text-muted);
 margin-bottom: var(--space-2);
}
.showcase-index ul { display: flex; flex-wrap: wrap; gap: var(--space-1) var(--space-5); }
.showcase-index a {
 display: inline-flex;
 align-items: center;
 min-height: 32px;
 font-size: var(--text-sm);
 font-weight: var(--weight-semibold);
 color: var(--color-text-link);
}
.showcase-index a:hover, .showcase-index a:focus-visible { color: var(--color-text-link-hover); text-decoration: underline; }

.showcase-block__label {
 display: inline-block;
 font-family: var(--font-body);
 font-size: var(--text-xs);
 font-weight: var(--weight-bold);
 letter-spacing: var(--tracking-wide);
 text-transform: uppercase;
 color: var(--color-text-muted);
 background: var(--color-bg-page-alt);
 padding: var(--space-1) var(--space-3);
 border-radius: var(--radius-sm);
 margin-bottom: var(--space-6);
}

/* =========================================================================
 16. PAGE-LEVEL COMPONENTS
 Added after the initial Georgia port: these classes style the CT build
 script's page-level markup (page headers, card grids, prose/article
 bodies, galleries, the navy CTA band, blog list/tag/pager furniture, the
 404 template, and a text-only header logo fallback). Georgia kept the
 equivalent rules in per-page inline <style> blocks, so nothing to port
 existed in components.css or header-final.css; these are modeled on
 /Users/davidbrannan/Flooring Guys Website/design/components.css (Florida),
 with every token translated from Florida's naming (--sp-N / --fs-* /
 --lh-* / --radius / --shadow-card / --color-bg-alt / --color-bg-band /
 --color-text-accent / --color-error) to this system's Georgia-style
 semantic names (--space-N / --text-* / --leading-* / --radius-base /
 --shadow-sm+--shadow-md / --color-bg-page-alt / --color-bg-accent-navy /
 --color-text-heading+--color-text-muted / --color-text-error).

 Two classes were intentionally NOT re-added here because they already
 exist, unchanged, earlier in this file and already match the request
 exactly:
   - .site-header__logo-tag (section 3, HEADER) is already --text-xs,
     opacity .85, color: var(--color-text-inverse).
   - .cta-band's mobile width-fix (.cta-band__inner, .cta-band
     .hero__actions) already lives in header.css. The band styled below
     reuses the existing .hero__actions button-row class rather than
     inventing a second button-row class, so there is exactly one
     definition of "the CTA band's button row" across both files.
 ========================================================================= */

/* ---- page header band ---------------------------------------------- */
/* Dark --gray-ink surface, its own dedicated token (--color-bg-page-hero)
   rather than reusing --color-bg-header — the header is now translucent
   glass and this band is not, so they need to be independently swappable.
   --color-text-inverse on --color-bg-page-hero is 16.64:1 AAA (see
   tokens.css). This band is also the first element under the now-fixed
   header on 39 of the site's 40 pages, so its top padding gains
   --header-h — see the .hero__content comment above for why. */
.page-hero {
 background: var(--color-bg-page-hero);
 color: var(--color-text-inverse);
 padding-block: calc(var(--header-h) + var(--space-8)) var(--space-8);
}
/* h1's global rule (section 0) sets color: var(--color-text-heading),
   which is --navy — near-invisible on this band's own --gray-ink
   background, so it must be overridden here or the title would be
   unreadable. */
.page-hero h1 {
 color: var(--color-text-inverse);
 margin-bottom: var(--space-2);
}

.breadcrumbs {
 margin: 0;
 font-size: var(--text-sm);
 color: var(--color-text-inverse);
 opacity: 0.85;
}
.breadcrumbs a {
 color: var(--color-text-inverse);
 text-decoration: underline;
 opacity: 0.85;
}
.breadcrumbs a:hover,
.breadcrumbs a:focus-visible { opacity: 1; }

/* Small uppercase eyebrow for LIGHT sections (unlike .hero__eyebrow, which
   is white-on-dark-scrim). Deliberately not colored --color-cta-bg like
   the existing .eyebrow utility (section 15): the brief for this class
   named only --color-text-muted or --color-text-heading as options, to
   keep bright red reserved for clickable CTAs. --color-text-heading
   (--navy as of the 2026-08-04 gray-glass restyle — 13.60:1 AAA on white,
   12.58:1 AAA on off-white) is used here, without spending the brand's one
   "this is clickable" color on a label. */
.section-kicker {
 display: block;
 font-size: var(--text-sm);
 font-weight: var(--weight-bold);
 letter-spacing: var(--tracking-wide);
 text-transform: uppercase;
 color: var(--color-text-heading);
 margin-bottom: var(--space-3);
}

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

.card {
 display: flex;
 flex-direction: column;
 background: var(--color-bg-card);
 border-radius: var(--radius-base);
 box-shadow: var(--shadow-sm);
 overflow: hidden;
 transition: box-shadow var(--motion-base) var(--motion-ease);
}
.card:hover { box-shadow: var(--shadow-md); }
.card img {
 width: 100%;
 aspect-ratio: 3 / 2;
 object-fit: cover;
 display: block;
}
.card-body {
 display: flex;
 flex-direction: column;
 gap: var(--space-2);
 flex: 1;
 padding: var(--space-5);
}
.card-body h3 { font-size: var(--text-lg); }
.card-body p { color: var(--color-text-muted); flex: 1; }
.card-link {
 display: inline-flex;
 align-items: center;
 gap: var(--space-1);
 font-weight: var(--weight-semibold);
 font-size: var(--text-sm);
 color: var(--color-text-link);
}
.card-link:hover,
.card-link:focus-visible { color: var(--color-text-link-hover); text-decoration: underline; }
/* Arrow glyph is decorative-only text, not an icon font or image, so no
   token is needed for it. */
.card-link::after { content: "\2192"; }

/* ---- prose (generated article / service-page bodies) ------------------ */
.prose {
 max-width: 70ch;
 line-height: var(--leading-normal);
}
.prose h2,
.prose h3 {
 color: var(--color-text-heading);
 margin-top: var(--space-8);
 margin-bottom: var(--space-4);
}
.prose h2:first-child,
.prose h3:first-child { margin-top: 0; }
.prose p { margin: 0 0 var(--space-4); }
.prose ul,
.prose ol {
 margin: 0 0 var(--space-4);
 padding-left: var(--space-6);
}
.prose ul { list-style: disc; }
.prose ol { list-style: decimal; }
.prose li { margin-bottom: var(--space-2); }
.prose a {
 color: var(--color-text-link);
 text-decoration: underline;
}
.prose a:hover,
.prose a:focus-visible { color: var(--color-text-link-hover); }
.prose img {
 max-width: 100%;
 border-radius: var(--radius-base);
 margin: var(--space-5) 0;
}

/* Two-column body + photo rail, ≥1024px; stacks to a single column below
   that (the rail simply falls after the prose column in source order). */
.prose-layout {
 display: grid;
 gap: var(--space-8);
 grid-template-columns: 1fr;
}
@media (min-width: 1024px) {
 .prose-layout { grid-template-columns: 1fr 320px; align-items: start; }
}
.photo-rail {
 display: grid;
 gap: var(--space-4);
}
.photo-rail img {
 width: 100%;
 display: block;
 border-radius: var(--radius-base);
 box-shadow: var(--shadow-sm);
}

/* ---- gallery ------------------------------------------------------- */
.gallery-grid {
 display: grid;
 gap: var(--space-4);
 grid-template-columns: repeat(auto-fill, minmax(260px, 1fr));
}
.gallery-grid img {
 width: 100%;
 display: block;
 aspect-ratio: 4 / 3;
 object-fit: cover;
 border-radius: var(--radius-sm);
}

/* ---- CTA band -------------------------------------------------------- */
/* 2026-08-04 gray-glass restyle: moved off --color-bg-accent-navy onto the
   same --color-bg-header-solid (--gray-ink) dark surface as the header,
   footer and page-hero bands, so there is one consistent "dark band" color
   across the site instead of two (navy kept its own role elsewhere —
   .process-step border, badge text — just not as a full-bleed CTA band
   fill any more). --color-text-inverse on --gray-ink is 16.64:1 AAA.
   Reuses .hero__actions (section 6) for the button row — see the
   file-header note above on why a second button-row class was not
   created. */
.cta-band {
 background: var(--color-bg-header-solid);
 color: var(--color-text-inverse);
 text-align: center;
 padding-block: var(--space-16);
}
.cta-band__inner {
 max-width: 640px;
 margin-inline: auto;
}
.cta-band h2 {
 color: var(--color-text-inverse);
 margin-bottom: var(--space-6);
}
.cta-band p {
 color: var(--color-text-inverse);
 opacity: 0.9;
 margin-bottom: var(--space-6);
}
.cta-band .hero__actions { justify-content: center; }
/* .btn--primary and .btn--outline are unmodified here on purpose: the
   button color is only ever the FILL behind the button, never a
   text/background pair being measured against the band itself.
   .btn--primary keeps its documented white-on-red (5.01:1 AA) pairing —
   and red as a button fill is legal directly on --gray-ink too (3.32:1,
   clears the 3:1 non-text minimum; see tokens.css). .btn--outline keeps
   its dark-context white border/text, which reads as a white-outline
   button on any dark fill, gray-ink included. */

/* ---- blog: post list, pager, tags -------------------------------------- */
.post-list {
 display: grid;
 gap: var(--space-6);
 grid-template-columns: 1fr;
}
@media (min-width: 768px) {
 .post-list { grid-template-columns: repeat(2, 1fr); }
}
@media (min-width: 1024px) {
 .post-list { grid-template-columns: repeat(3, 1fr); }
}
/* .post-list reuses .card / .card-grid's card component; the only
   post-list-specific override is a smaller heading size than the
   default .card-body h3. */
.post-list .card h3 { font-size: var(--text-md); }

.blog-pager {
 display: flex;
 flex-wrap: wrap;
 align-items: center;
 justify-content: center;
 gap: var(--space-3);
 margin-top: var(--space-6);
}

.tag-cloud {
 display: flex;
 flex-wrap: wrap;
 gap: var(--space-2);
}
.tag-cloud li { display: inline-flex; }
.tag-cloud a {
 display: inline-flex;
 align-items: center;
 padding: var(--space-1) var(--space-3);
 border-radius: var(--radius-full);
 background: var(--color-badge-bg);
 color: var(--color-badge-text);
 border: 1px solid var(--color-badge-border);
 font-size: var(--text-xs);
 font-weight: var(--weight-medium);
}
/* Hover fills navy (13.60:1 AAA), not red: red stays reserved for
   clickable CTA buttons only (see the .process-step and .eyebrow
   comments elsewhere in this file) — a tag chip is a filter/label
   control, not a primary call to action, so it does not spend the
   brand's one "this is the action" color. */
.tag-cloud a:hover,
.tag-cloud a:focus-visible {
 background: var(--color-bg-accent-navy);
 color: var(--color-text-inverse);
 border-color: var(--color-bg-accent-navy);
}

/* ---- 404 -------------------------------------------------------------- */
.error-page {
 text-align: center;
 padding-block: var(--space-16);
 /* 404 is the first element under the now-fixed header — margin, not
    padding: this band is on the page (light) surface, not a dark band that
    needs the header height baked into its own visible padding. */
 margin-top: var(--header-h);
}
.error-page h1 { margin-bottom: var(--space-4); }
.error-page p {
 color: var(--color-text-muted);
 margin-bottom: var(--space-6);
}

/* ---- hero button row (Florida-shaped alternative to .hero__actions) --- */
/* Distinct from .hero__actions (section 6): the CT build's hero__copy
   markup emits this class name for its button row. Both classes are
   kept — neither replaces the other — since Georgia-shaped markup uses
   .hero__actions and Florida-shaped markup uses .hero-ctas. */
.hero-ctas {
 display: flex;
 flex-wrap: wrap;
 gap: var(--space-3);
 margin-top: var(--space-6);
}

/* ---- forms: Florida-named helper text ---------------------------------- */
/* Equivalent to .field-hint (section 8) under the Florida-shaped class
   name the CT build script emits for the same role. */
.form-hint {
 font-size: var(--text-sm);
 color: var(--color-text-muted);
 margin-top: var(--space-1);
}

/* ---- header: text-only logo fallback ----------------------------------- */
/* No CT logo file has been supplied yet (see tokens.css "OPEN" note). This
   is the visible text lockup used until real logo art lands — distinct
   from .site-header__logo-word (header.css), which is a visually-hidden
   duplicate wordmark kept only for the accessibility tree once a crest
   image exists. .site-header__logo-tag already existed in section 3 with
   exactly the requested styling (--text-xs, opacity .85,
   --color-text-inverse) and is not redefined here. */
.site-header__logo-text {
 font-family: var(--font-heading);
 font-size: var(--text-lg);
 font-weight: var(--weight-bold);
 color: var(--color-text-inverse);
 line-height: 1.1;
}

/* =========================================================================
   MOBILE CLEANUP — 2026-08-04 gray-glass restyle, narrow phones (≤640px)

   Complements header.css's own ≤560px block (proof-chip/hero__actions
   stacking, Ken Burns) with the remaining owner-requested narrow-screen
   fixes: a headline that actually fits, one fewer competing hero button,
   tighter chips, and less dead vertical space above the fold.
   ========================================================================= */
@media (max-width: 640px) {
  /* --text-4xl's floor (2.25rem) still doesn't shrink enough for a 320-375px
     phone with this serif display face. Lower floor only here — the token
     itself is left alone since it's shared with any future desktop use. */
  .hero__title {
    font-size: clamp(1.9rem, 5vw + 0.9rem, 2.25rem);
  }

  /* The sticky bottom bar already has a Call button on every screen size;
     the hero's second CTA is redundant weight competing with "Get a Free
     Estimate" on a screen where every pixel of vertical space matters. */
  .hero-ctas .btn--outline {
    display: none;
  }

  .proof-chip {
    font-size: var(--text-xs);
    padding: var(--space-1) var(--space-3);
  }
  .proof-chips {
    gap: var(--space-2);
  }

  /* Tighter than the base (header-aware) padding — the goal on a phone is
     hero + eyebrow/title/subtitle + chips + one CTA fitting close to one
     viewport, not full desktop breathing room stacked on top of the fixed
     header's own offset. */
  .hero__content {
    padding-block: calc(var(--header-h) + var(--space-6)) var(--space-10);
  }
  .page-hero {
    padding-block: calc(var(--header-h) + var(--space-5)) var(--space-6);
  }
}

/* Belt-and-suspenders global reduced-motion guard, in addition to the
 token-level override in tokens.css (covers any literal duration a
 future component author forgets to tokenize). */
@media (prefers-reduced-motion: reduce) {
 *, *::before, *::after {
 animation-duration: 0.01ms !important;
 animation-iteration-count: 1 !important;
 transition-duration: 0.01ms !important;
 }
}
