/* Homepage styles — Exterior Services LLC (Direction B: Zilla Slab)
   Shared components (nav, buttons, sections, mosaic, footer) are in base.css.
   This file covers homepage-specific sections only. */

/* EST. 1999 roundel retired site-wide (Brief 13) — do not reintroduce. */

/* ══════════════════════════════════════════════════════════════════════════════
   HERO — ambient crossfade under the Direction A billboard (Brief 13)
   Text zone + sill ported from docs/mockups/direction-a.html; the crossfade
   slide/scrim structure and hero-crossfade.js are the unchanged engine.
   --font-hero (Bricolage Grotesque 800) lives ONLY inside this hero.
   ══════════════════════════════════════════════════════════════════════════════ */
.hero {
  position: relative;
  /* DESKTOP BAND 3:2 (Brief 35, Bobby's ruling — Option A): the band matches the
     slides' native 1.500 so the whole photograph is the target. HONEST MATH,
     measured before wiring: a full-width 3:2 band is TALLER than every common
     landscape viewport (1440->960 vs 836 available; 1920->1280 vs 1016), so the
     100svh-minus-nav cap below binds there and retention stays 87.1% / 79.4% —
     identical to the old min-height rule. The ruling's zero-crop goal is fully
     delivered only on viewports taller than 2/3 width + nav (portrait tablets,
     vertical monitors, short windows); everywhere else this is the closest a
     full-bleed hero can get without letterboxing. The cap is NOT optional: without
     it the fold would swallow the text block and CTAs at 16:9. */
  /* height, not aspect-ratio: aspect-ratio + max-height triggers the spec's
     ratio TRANSFER and the capped height re-derives a 1254px WIDTH at 1440 —
     caught by measurement. min() keeps the band full-bleed and caps cleanly. */
  height: min(calc(100vw / 1.5), calc(100svh - var(--nav-h)));
  display: flex; flex-direction: column; justify-content: flex-end;
}
.hero__slides {
  position: absolute; inset: 0;
}
.hero__slide {
  position: absolute; inset: 0;
  opacity: 0;
  transition: opacity 1.2s ease-in-out;
}
.hero__slide--active { opacity: 1; }
.hero__slide:first-child { opacity: 1; }
.hero__slide .shot { height: 100%; border-radius: 0; }

/* Scrim — bottom wash only, sized to the caption-scale text zone (13b; was
   58% for the billboard). TUNING LEVER: the last stop is the scrim's reach —
   raise/lower it to trade legibility against photo brightness. */
.hero__scrim {
  position: absolute; inset: 0; z-index: 1; pointer-events: none;
  background: linear-gradient(to top,
    color-mix(in srgb, var(--ink) 82%, transparent) 0%,
    color-mix(in srgb, var(--ink) 44%, transparent) 24%,
    transparent 46%);
}

.hero__body {
  position: relative; z-index: 2;
  padding: var(--sp-8) var(--gutter) var(--sp-6);
  max-width: 72rem;
}
/* CONTAINED LEGIBILITY WASH (Brief 19 pt B, option 2 — shipped default).
   The global .hero__scrim is a bottom-up wash that runs out below the text, so
   on a bright frame the whole text block failed AA. Raising the scrim's reach
   (option 1) was measured and does NOT fix it — the text sits at ~61% up from
   the hero's bottom, right at the new transparent stop, so every element stayed
   at ~1:1. This wash is anchored to the TEXT COLUMN instead: it darkens the
   left of the body box where the words are and is fully transparent by 90%, so
   the right two-thirds of the photograph stay at full brightness.
   z-index:-1 keeps it inside .hero__body's stacking context — above the photo
   and the scrim, behind the words.
   It is tuned to the TEXT ZONE, not to the current photograph, so it survives a
   hero swap — Shane's replacement shot needs no re-tuning here.
   TUNING LEVER: the 68%/90% stops are the wash's reach across the frame.
   Measured after Brief 19b at 1440: H1 12.99:1, sub 6.52:1, CTAs 14.6-14.9:1. */
.hero__body::before {
  content: "";
  position: absolute; inset: 0;
  z-index: -1; pointer-events: none;
  background: linear-gradient(to right,
    color-mix(in srgb, var(--ink) 93%, transparent) 0%,
    color-mix(in srgb, var(--ink) 90%, transparent) 46%,
    color-mix(in srgb, var(--ink) 62%, transparent) 68%,
    transparent 90%);
  /* Without this the wash's top edge cuts a hard horizontal line across the
     photograph. The mask fades it in across the body's top padding, above the
     first line of type, so the treatment has no visible boundary. */
  -webkit-mask-image: linear-gradient(to bottom, transparent 0%, #000 16%);
          mask-image: linear-gradient(to bottom, transparent 0%, #000 16%);
}
/* HERO EYEBROW REMOVED (Brief 19b, option 3). The nav lists all five trades
   40px above where it sat, so it was repeating the navigation. All four rules
   that styled it — the left-anchored flex, the green/tracking, the sand
   hairlines and the Brief 19 rule that hid those hairlines — died with the
   markup and are gone. `.eyebrow` itself is untouched in base.css; every other
   eyebrow on the site keeps its centred rules. */
/* H1 — Direction A display voice at caption scale (13b: the photo is the
   hero; the headline is a strong caption, not a billboard).
   TUNING LEVER: this clamp is the headline's size — Brief 13's billboard was
   clamp(3.25rem, 10.5vw, 8.5rem); Bobby adjusts by naming a new ceiling. */
.hero__h1 {
  /* Was margin-top: var(--sp-3) — the eyebrow-to-H1 gap. With the eyebrow gone
     (Brief 19b) the H1 is the block's first child, so that value only padded it
     against .hero__body's own padding and is dead. Zeroed rather than left to
     drift: the block is bottom-anchored on desktop, so this changes where the
     wash starts, not where the words sit. */
  margin-top: 0;
  color: var(--paper);
  font-family: var(--font-hero);
  font-weight: 800;
  text-transform: uppercase;
  line-height: 0.92;
  letter-spacing: -0.02em;
  font-size: clamp(2.4rem, 5.2vw, 4.75rem);
}
.hero__h1 .hl { color: var(--green-lt); font-style: normal; }
/* Text-block spacing tightened for caption scale (13b): the sp-4/sp-5 gaps
   were proportioned to 136px type and read hollow under ~76px */
.hero__sub {
  margin-top: var(--sp-3);
  color: var(--mut-d);
  font-size: var(--fs-4);
  max-width: 40ch;
  line-height: 1.5;
}
/* Only one of the sub pair is ever rendered — see the markup comment. */
.hero__sub--short { display: none; }

/* CTA PAIR (Brief 20 pt B). Was a flex row of two differently-sized pills, which
   read as mismatched and weak. Now a grid of two EQUAL columns so the pair is
   confident and symmetrical, each with a generous tap target and an arrow.
   A grammar retained: square corners, uppercase tracking, no hover lift. */
.hero__ctas {
  margin-top: var(--sp-5);
  display: grid;
  grid-template-columns: repeat(2, minmax(0, 15rem));
  gap: var(--sp-3);
}
.hero .btn {
  border-radius: 0;
  min-height: 3rem;                      /* 48px tap target */
  padding: var(--sp-3) var(--sp-5);
  display: flex; align-items: center; justify-content: center; gap: var(--sp-3);
  text-align: center;
  letter-spacing: 0.14em; text-transform: uppercase;
}
.hero .btn:hover { translate: 0 0; }
/* Secondary reads as a button, not a link: a full-strength paper rule rather
   than the 50%-alpha border it inherited, and it fills on hover. */
.hero .btn--ghost {
  border-width: 2px; border-color: var(--paper); color: var(--paper);
}
.hero .btn--ghost:hover { background: var(--paper); border-color: var(--paper); color: var(--ink); }
.btn__arrow { font-weight: 400; transition: translate 0.2s; }
.hero .btn:hover .btn__arrow { translate: 3px 0; }

/* Trust sill — Direction A numbered strip: flat, full-width, over the
   darkened photo bottom (replaces the floating paper card, Brief 13) */
.trust {
  position: relative; z-index: 2;
  list-style: none;
  display: grid; grid-template-columns: repeat(4, 1fr);
  border-top: 1px solid var(--hair-d);
}
.trust li {
  /* Mockup pads var(--gutter) both sides; production gutter caps 5rem (vs the
     mockup's 4.5rem) and the wider pad wrapped cell 04 — text is left-anchored,
     so keep the gutter inset on the lead side only and free the tail */
  padding: var(--sp-4) var(--sp-4) var(--sp-4) var(--gutter);
  color: var(--mut-d);
  font-size: var(--fs-1); font-weight: 700;
  letter-spacing: 0.16em; text-transform: uppercase;
}
.trust li + li { border-left: 1px solid var(--hair-d); }
.trust b { color: var(--green-lt); font-weight: 700; margin-right: var(--sp-2); }

/* ── Homepage-specific section modifier ─────────────────────────────────────── */
/* Was calc(var(--sp-8) + var(--sp-6)) to clear the floating trust card;
   the A sill sits inside the hero, so no overlap remains (Brief 13). */
.sec--tight { padding-top: var(--sp-8); }

/* ── Services 3 + 2 ─────────────────────────────────────────────────────────
   Five cards (Brief 14: Pools promoted to a full page). A six-column track
   lets every card span 2 — identical widths on both rows — and the two-card
   second row is centred by offsetting it one column. A 5-across row was
   rejected: at 72rem the cards fall to ~198px and the photo panel dies.
   ─────────────────────────────────────────────────────────────────────────── */
.svc {
  margin-top: var(--sp-7);
  width: min(72rem, 100%); margin-inline: auto;
  display: grid; grid-template-columns: repeat(6, 1fr); gap: var(--sp-6);
}
.svc__card { grid-column: span 2; }
.svc__card:nth-child(4) { grid-column: 2 / span 2; }
.svc__card:nth-child(5) { grid-column: 4 / span 2; }
.svc__card { display: flex; flex-direction: column; text-align: center; }
/* WHOLE CARD IS THE LINK (Brief 20 pt C). The photo, the name, the line and the
   CTA row all sit inside one <a>; the old sibling .textlink became a <span> so
   nothing interactive nests inside anything interactive. */
.svc__link {
  display: flex; flex-direction: column; height: 100%;
  text-decoration: none; color: inherit;
}
.svc__card .shot { aspect-ratio: 3 / 2; transition: translate 0.25s, box-shadow 0.25s; }
.svc__name { margin-top: var(--sp-5); font-size: var(--fs-5); font-weight: 600; color: var(--ink); }
.svc__line { margin-top: var(--sp-2); color: var(--mut); max-width: 44ch; margin-inline: auto; flex: 1; }
/* The CTA is a button-shaped row rather than an underlined link: it is the
   persistent tap affordance on touch, where :hover does not exist, and it
   doubles as the desktop prominence the old textlink lacked. Chosen over a
   chevron badge on the image corner so nothing is ever laid over a photograph —
   the same photo-first discipline the rest of the site keeps. */
.svc__cta {
  margin-top: var(--sp-4);
  display: inline-flex; align-items: center; justify-content: center; gap: var(--sp-2);
  align-self: center;
  min-height: 2.75rem; padding: var(--sp-2) var(--sp-5);
  border: 1px solid var(--green); border-radius: var(--r-pill);
  color: var(--green); font-size: var(--fs-2); font-weight: 700; letter-spacing: 0.06em;
  transition: background 0.2s, color 0.2s, border-color 0.2s;
}
.svc__arrow { transition: translate 0.2s; }
/* Hover/active belong to the whole card, driven from the one anchor */
.svc__link:hover .shot { translate: 0 -4px; box-shadow: var(--shadow-card); }
.svc__link:hover .svc__cta { background: var(--green); color: var(--paper); }
.svc__link:hover .svc__arrow { translate: 3px 0; }
.svc__link:active .shot { translate: 0 -1px; }
/* Focus ring outlines the entire card, not just a word of text */
.svc__link:focus-visible { outline: 2px solid var(--green); outline-offset: 6px; border-radius: var(--r); }

/* ── Before / After ─────────────────────────────────────────────────────────── */
.ba-wrap { width: min(72rem, 100%); margin: var(--sp-7) auto 0; }
/* .ba static styles removed (Brief 6b) — .ba-slider component now in base.css */

/* ── Crew band (Brief 25) ───────────────────────────────────────────────────
   REPLACES the family band. That band was a 46rem centred column carrying one
   4:3 portrait, a drop-capped paragraph and the stats — 1455px at 1440. This
   one keeps the page's standard centred .sec__head (the family band was the
   only homepage section that did NOT use it), pairs the crew with the fleet,
   and keeps the same .stats. The drop-cap paragraph is gone with the markup:
   its two load-bearing facts are in the lede and the rest lives on /about/.

   ASYMMETRY IS THE POINT. 7fr/5fr, both images 3:2, top-aligned: the lead is
   433px tall and the fleet 309px, and the 124px the fleet does not use is
   where the About link sits. Matched heights were rejected — a 5fr column at
   the lead's height forces a ~0.72 portrait crop, which cuts the truck in
   half and throws away the one frame in the archive whose livery reads.
   ─────────────────────────────────────────────────────────────────────────── */
.sec--crew { background: var(--paper-2); }
.crew {
  margin-top: var(--sp-7);
  width: min(72rem, 100%); margin-inline: auto;
  display: grid; grid-template-columns: minmax(0, 7fr) minmax(0, 5fr);
  gap: var(--sp-6);
  align-items: start;
}
/* Both frames are native 1.50 into a 3:2 box — zero crop, every breakpoint */
.crew__lead .shot,
.crew__fleet .shot { aspect-ratio: 3 / 2; }
.crew__aside { display: flex; flex-direction: column; }
/* Same outlined-pill affordance as the service cards: persistent on touch,
   where :hover does not exist, and it never sits over a photograph. */
.crew__link {
  margin-top: var(--sp-5); align-self: center;
  display: inline-flex; align-items: center; justify-content: center; gap: var(--sp-2);
  min-height: 2.75rem; padding: var(--sp-2) var(--sp-5);
  border: 1px solid var(--green); border-radius: var(--r-pill);
  color: var(--green); font-size: var(--fs-2); font-weight: 700; letter-spacing: 0.06em;
  text-decoration: none;
  transition: background 0.2s, color 0.2s, border-color 0.2s;
}
.crew__arrow { transition: translate 0.2s; }
.crew__link:hover { background: var(--green); color: var(--paper); }
.crew__link:hover .crew__arrow { translate: 3px 0; }
.crew__link:focus-visible { outline: 2px solid var(--green); outline-offset: 4px; }
/* The stats keep the full 72rem measure so the numeric band spans the pair */
.sec--crew .stats { width: min(72rem, 100%); margin-inline: auto; }

/* .stats promoted to base.css (Brief 6) */

/* ── Service area chips ─────────────────────────────────────────────────────── */
.chips__label {
  margin-top: var(--sp-6); text-align: center;
  font-size: var(--fs-2); font-weight: 600; letter-spacing: 0.08em;
  text-transform: uppercase; color: var(--mut);
}
.chips {
  margin-top: var(--sp-4);
  display: flex; flex-wrap: wrap; justify-content: center;
  gap: var(--sp-3); list-style: none;
  width: min(56rem, 100%); margin-inline: auto;
}
.chips span {
  display: inline-block;
  padding: var(--sp-2) var(--sp-5);
  border: 1px solid color-mix(in srgb, var(--ink) 28%, transparent);
  border-radius: var(--r-pill);
  background: var(--paper);
  font-size: var(--fs-2); font-weight: 600;
}
.chips .ny span { border-color: var(--green); color: var(--green); }
.chips__legend {
  margin-top: var(--sp-5); color: var(--mut);
  font-family: var(--font-display); font-style: italic;
  font-size: var(--fs-2); text-align: center;
}

/* Tablet: three-across drops the cards to ~270px and the photo panel with them.
   Fall back to 2 + 2 + 1 on a four-column track, last card centred the same way. */
@media (min-width: 881px) and (max-width: 1100px) {
  .svc { grid-template-columns: repeat(4, 1fr); }
  .svc__card:nth-child(4) { grid-column: span 2; }
  .svc__card:nth-child(5) { grid-column: 2 / span 2; }
}

/* ── Scroll-reveal homepage targets ─────────────────────────────────────────── */
@media (prefers-reduced-motion: no-preference) {
  @supports (animation-timeline: view()) {
    .svc__card, .crew__lead, .crew__fleet {
      animation: soften 1s both;
      animation-timeline: view();
      animation-range: entry 0% entry 35%;
    }
  }
}

/* ══════════════════════════════════════════════════════════════════════════════
   MOBILE — ≤880px homepage-specific
   ══════════════════════════════════════════════════════════════════════════════ */
@media (max-width: 880px) {
  /* MOBILE HERO LAW — stacked: natural-ratio image band, then text band.
     BAND RATIO 3:2 (Brief 29, Bobby's ruling). The band was 16/9 from Brief 16,
     when heroes 1-2 were natively 1.778 — but every slide in the Brief 29 trio
     (POOL-181 · CON-233 · POOL-039) is natively 1.500, so 16/9 cropped ALL
     THREE to 84.4% and 3/2 renders ALL THREE at ZERO crop, including the LCP
     slide. If a future 1.778 hero returns, IT pays the 84.4% width cost here —
     re-run the arithmetic before touching this ratio. Was 4/5 in the
     placeholder era; do not restore a portrait ratio here. */
  /* height:auto — the desktop min() height must not constrain the stacked band */
  .hero { display: block; height: auto; min-height: 0; position: relative; }
  .hero__slides {
    position: relative; aspect-ratio: 3 / 2;
    height: auto; overflow: hidden;
  }
  .hero__slide { position: absolute; inset: 0; }
  .hero__slide .shot { height: 100%; border-radius: 0; }
  .hero__scrim { display: none; }
  /* Text band tightened (Brief 20 pt A.3): H1, sub, CTAs and nothing else, with
     the top pad cut so the band stops competing with the photograph above it. */
  .hero__body {
    background: var(--char); max-width: none;
    padding: var(--sp-5) var(--gutter) var(--sp-6);
  }
  .hero__sub  { margin-top: var(--sp-2); }
  .hero__ctas { margin-top: var(--sp-4); }
  /* Billboard H1: no mobile down-clamp — the A clamp's 3.25rem floor IS the
     mockup's own mobile treatment (two lines, verified by shot at 390) */

  /* Swap the sub for the short one — the trade list is redundant against the nav */
  .hero__sub--long  { display: none; }
  .hero__sub--short { display: block; }

  /* CTAs go full-width and stack: two confident equal bars, not a wrapped pair */
  .hero__ctas { grid-template-columns: 1fr; gap: var(--sp-3); }

  /* TRUST SILL REMOVED ON MOBILE (Brief 20 pt B ruling). It repeated below the
     buttons and pushed the photograph's share of the first screen down. Removed
     with display:none rather than by restructuring the markup: the sill is a
     desktop composition element, all four facts appear elsewhere on the page
     (footer NAP carries the licence and the counties), and display:none also
     takes it out of the accessibility tree, so nothing is announced twice.
     DESKTOP KEEPS IT — this rule is inside the ≤880px block only. */
  .trust { display: none; }

  /* Single column: the span/offset placement must be cleared or the cards
     force implicit columns into the track */
  .svc { grid-template-columns: 1fr; }
  .svc__card,
  .svc__card:nth-child(4),
  .svc__card:nth-child(5) { grid-column: 1 / -1; }

  /* Crew band stacks: head, crew, fleet, link, stats. BOTH images stay 3:2 —
     they are native 1.50, so mobile re-crops nothing. The fleet frame is kept
     rather than dropped: measured stacked, it still lands under the family band
     it replaced. If that ever stops being true, this is the rule that drops it. */
  .crew { margin-top: var(--sp-6); grid-template-columns: 1fr; gap: var(--sp-5); }
  /* Stacked, two equal-width images would throw away the hierarchy the desktop
     grid establishes — the lead leads, the fleet supports. Insetting the fleet
     keeps that reading AND is what holds the stacked band under the old one at
     600px, the widest point of the stack, where full-width images peaked it
     135px OVER the family band. Also drops the fleet a srcset tier on phones. */
  .crew__fleet { width: 70%; margin-inline: auto; }
}
