/* ==========================================================================
   Level Headed Construction — hero.css
   Hero slideshow ported from Brasfield & Gorrie teardown.
   ========================================================================== */

.hero {
  position: relative;
  width: 100%;
  height: 100vh;
  height: 100svh;
  min-height: 560px;
  overflow: hidden;
  background: var(--ink);
  /* Parallax stacking: hero pinned at z:0, every sibling at z:2 (rule
     below) so they paint OVER the hero as the page scrolls. The
     parallax JS in inner-page.js translates the hero downward at half
     scroll speed, and the cream divider + sections below glide up
     over it. Same pattern as services / about / gallery / contact. */
  z-index: 0;
  will-change: transform;
}
@media (min-width: 1024px) {
  .hero { height: min(100svh, 780px); }
}

/* Cream divider strip directly below the hero — same seam used on
   every inner page (.services-divider, .about-divider, etc.). */
.hero-divider {
  height: 18px;
  background: var(--cream);
}

/* Every sibling after the hero sits above it in stacking order so it
   covers the hero during the parallax scroll. The strip is transparent
   by default — give it a solid bg so the hero doesn't leak through.
   Variant sections (.section--cream, .section--ink) keep their own
   backgrounds via class specificity. */
.hero ~ * {
  position: relative;
  z-index: 2;
}
.hero ~ .strip {
  background: var(--cream-soft);
}

/* Honor reduced-motion: skip parallax. JS bails out for matching
   users; this rule resets any transform that may have been applied
   before the listener attached. */
@media (prefers-reduced-motion: reduce) {
  .hero { transform: none !important; }
}

/* ---------- Stage (holds all 5 slides) ---------- */
.hero__stage {
  position: absolute;
  inset: 0;
  overflow: hidden;
}

/* ---------- Slide ---------- */
.hero__slide {
  position: absolute;
  inset: 0;
  opacity: 0;
  transform: skewX(6deg) scale(1.25) translateX(5%);
  transition:
    opacity var(--dur-medium) var(--ease-in-out-circ),
    transform var(--dur-medium) var(--ease-in-out-circ);
  pointer-events: none;
  will-change: transform, opacity;
}
.hero__slide.is-active {
  opacity: 1;
  transform: skewX(0) scale(1) translateX(0);
  pointer-events: auto;
}
.hero__slide.is-leaving {
  opacity: 0;
  transform: skewX(-6deg) scale(1.25) translateX(-5%);
}

/* ---------- Image ---------- */
.hero__image,
.hero__image img {
  position: absolute;
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
  object-position: center;
}

/* Slide 1 (Remodels & Renovations) — image mirrored horizontally per
   client. The transform applies to the <img> only, so it doesn't
   conflict with the slide-level skew/scale used by the crossfade or
   with the boot zoom keyframe (which only runs on slide 0 at first
   paint). */
.hero__slide[data-index="1"] .hero__image img {
  transform: scaleX(-1);
}

/* Per-slide crop focus on mobile — keeps the subject in frame
   when the container goes tall. */
@media (max-width: 767px) {
  .hero__slide[data-index="1"] .hero__image img { object-position: 32% 45%; }
  .hero__slide[data-index="2"] .hero__image img { object-position: 28% 70%; }
  .hero__slide[data-index="3"] .hero__image img { object-position: 12% 50%; }
}

/* Per-slide left-edge gradient — bound to each slide so it crossfades
   and transforms with the photo during slide transitions instead of
   staying static on top of the stage. Sits between the image (default
   stacking) and the content block (z:4) inside each slide.          */
.hero__slide::after {
  content: '';
  position: absolute;
  inset: 0;
  background: linear-gradient(to right,
    rgba(0, 0, 0, 0.50) 0%,
    rgba(0, 0, 0, 0.32) 18%,
    rgba(0, 0, 0, 0.14) 45%,
    rgba(0, 0, 0, 0) 75%);
  pointer-events: none;
  z-index: 1;
}

/* Top-down brown shade — improves header/wordmark legibility on
   bright/sky slides. Fades out once the header takes its solid background. */
.hero__top-shade {
  position: absolute;
  top: 0;
  left: 0;
  right: 0;
  height: 220px;
  background: linear-gradient(to bottom,
    rgba(42, 27, 16, 0.65) 0%,
    rgba(42, 27, 16, 0.35) 50%,
    rgba(42, 27, 16, 0) 100%);
  pointer-events: none;
  z-index: 2;
  transition: opacity var(--dur-base) var(--ease-in-out-quad);
}
body:has(.site-header.is-stuck) .hero__top-shade {
  opacity: 0;
}

/* ---------- Content (headline + subtext + CTAs) ---------- */
.hero__content {
  position: absolute;
  left: var(--gutter);
  right: var(--gutter);
  bottom: 120px;
  max-width: 860px;
  z-index: 4;
  opacity: 0;
  transform: translateX(16px);
  transition:
    opacity var(--dur-medium) var(--ease-in-out-quad) 75ms,
    transform var(--dur-medium) var(--ease-in-out-quad) 75ms;
  pointer-events: none;
}
.hero__slide.is-active .hero__content {
  opacity: 1;
  transform: translateX(0);
  pointer-events: auto;
}
.hero__slide.is-leaving .hero__content {
  opacity: 0;
  transform: translateX(-16px);
  transition-delay: 0ms;
}

@media (min-width: 768px) {
  .hero__content { bottom: 140px; }
}
@media (min-width: 1024px) {
  .hero__content { bottom: 160px; }
}

.hero__title {
  position: relative;
  font-family: var(--font-display);
  font-weight: 700;
  /* Min dropped 60px → 48px so the longest single-word title
     (CONSTRUCTION, RENOVATIONS) fits within the mobile content area
     (375px viewport - 48px gutters = 327px) without clipping. The mid
     range (11vw) and max (128px) are unchanged, so desktop sizing is
     identical to the design.                                         */
  font-size: clamp(48px, 11vw, 128px);
  line-height: 0.92;
  letter-spacing: -0.015em;
  text-transform: uppercase;
  /* Cream face from the brand palette (--cream = #EDDDB7) — same warm
     tan used for the wordmark and ghost-CTA labels across the site. */
  color: var(--cream);
  margin-bottom: 20px;
  /* Ink extrusion (--ink = #2A1B10) — the brand's deepest dark, used
     for body text and the dark raised section panels. Five hard offset
     steps build the 3D depth; a wider blurred cast sits behind for
     atmospheric drop. */
  text-shadow:
    1px 1px 0 var(--ink),
    2px 2px 0 var(--ink),
    3px 3px 0 var(--ink),
    4px 4px 0 var(--ink),
    5px 5px 0 var(--ink),
    7px 9px 12px rgba(0, 0, 0, 0.45);
}

/* Thin white rule above every title — same crisp white tilt as the
   subtitle / ghost CTA so the three elements read as one stack. The
   rule lives inside the title's box so it inherits the title's
   fade-in/out timing on slide transitions and the boot.            */
/* The accent above each title — a simple house silhouette in brand
   rust: long triangle roof + rectangular walls + a door cut into the
   bottom-right and a square window cut into the left wall. All drawn
   as one fill-rule:evenodd path so it composites cleanly with a single
   drop-shadow. The path is inlined as a data: URL so no extra request
   and no separate asset file. Same fade-in/out timing as the title.  */
.hero__title::before {
  content: '';
  display: block;
  width: clamp(110px, 12vw, 180px);
  /* House SVG aspect 144:56 ≈ 2.57:1 — wide & low. Roof: full 144 wide,
     32 tall. Walls: inset 16px on each side (112 wide), 24 tall — both
     slimmer and shorter than the roof, so the roof clearly overhangs.
     Window cut into the left wall, door notched out at the bottom.  */
  aspect-ratio: 144 / 56;
  background-image: url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 144 56'><path d='M0 32L72 0L144 32L128 32L128 56L84 56L84 44L62 44L62 56L16 56L16 32L0 32ZM28 36L44 36L44 48L28 48Z' fill='%239E3C0E' fill-rule='evenodd'/></svg>");
  background-repeat: no-repeat;
  background-size: 100% 100%;
  /* Matches the title's text-shadow: five chained drop-shadows at
     (1px, 1px) each stair-step the rust silhouette to the (5,5)
     corner in ink, then a wider blurred cast lands the form. */
  filter:
    drop-shadow(1px 1px 0 var(--ink))
    drop-shadow(1px 1px 0 var(--ink))
    drop-shadow(1px 1px 0 var(--ink))
    drop-shadow(1px 1px 0 var(--ink))
    drop-shadow(1px 1px 0 var(--ink))
    drop-shadow(7px 9px 12px rgba(0, 0, 0, 0.45));
  margin-bottom: 4px;
}
@media (min-width: 768px) {
  .hero__title::before { margin-bottom: 6px; }
}

.hero__subtitle {
  font-family: var(--font-body);
  /* Bumped 500 -> 600 so the strokes catch more light against bright
     photo zones without feeling chunky. */
  font-weight: 600;
  font-size: clamp(16px, 1.85vw, 21px);
  line-height: 1.45;
  /* Pure white tilt for max brightness against the gradient. */
  color: #FFFCF4;
  max-width: 560px;
  margin-bottom: 36px;
  /* Tight two-step shadow: a crisp 1px drop gives every glyph a sharp
     edge against bright pixels (no blur halo, so it stays clean), then
     a wider soft cast adds ambient depth without compounding into a
     muddy plate the way the old single 8px halo did.                 */
  text-shadow:
    0 1px 2px rgba(0, 0, 0, 0.75),
    0 2px 10px rgba(0, 0, 0, 0.35);
}

/* Hero CTAs: bold solid pair. Primary is the rust brand color at full
   saturation with a chunky offset shadow (echoes the title's 3D feel);
   secondary is a solid cream block — flips the ghost to a real button
   so both buttons read with equal weight against any photo. */
.hero__ctas .btn--primary {
  /* Brand rust (--rusty = #9E3C0E) — same fill the site-wide primary
     button uses, so the hero CTA is locked to the palette and stays
     consistent with every other primary button on the site. */
  background: var(--rusty);
  color: #FFFCF4;
  border: 2px solid var(--rusty);
  padding: 16px 28px;
  font-size: 15px;
  letter-spacing: 0.04em;
  box-shadow:
    4px 4px 0 rgba(42, 27, 16, 0.85),
    0 8px 22px rgba(0, 0, 0, 0.30);
  transition:
    transform var(--dur-base) var(--ease-out-circ),
    box-shadow var(--dur-base) var(--ease-out-circ),
    background-color var(--dur-base) var(--ease-out-circ);
}
.hero__ctas .btn--primary:hover,
.hero__ctas .btn--primary:focus-visible {
  /* Site-wide hover state: darker rust + bigger offset shadow. */
  background: var(--rusty-dark);
  border-color: var(--rusty-dark);
  transform: translate(-2px, -2px);
  box-shadow:
    6px 6px 0 rgba(42, 27, 16, 0.85),
    0 12px 28px rgba(0, 0, 0, 0.35);
}

.hero__ctas .btn--ghost {
  /* Pure-white-tilt cream so the secondary button reads as bright. */
  background: #FFFCF4;
  color: var(--ink);
  border: 2px solid #FFFCF4;
  padding: 16px 28px;
  font-size: 15px;
  letter-spacing: 0.04em;
  -webkit-backdrop-filter: none;
  backdrop-filter: none;
  box-shadow:
    4px 4px 0 rgba(42, 27, 16, 0.85),
    0 8px 22px rgba(0, 0, 0, 0.25);
  transition:
    transform var(--dur-base) var(--ease-out-circ),
    box-shadow var(--dur-base) var(--ease-out-circ),
    background-color var(--dur-base) var(--ease-out-circ);
}
.hero__ctas .btn--ghost:hover,
.hero__ctas .btn--ghost:focus-visible {
  background: #FFFFFF;
  border-color: #FFFFFF;
  color: var(--ink);
  transform: translate(-2px, -2px);
  box-shadow:
    6px 6px 0 rgba(42, 27, 16, 0.85),
    0 12px 28px rgba(0, 0, 0, 0.30);
}

.hero__ctas {
  display: flex;
  flex-wrap: wrap;
  gap: 14px;
}

/* ---------- Initial boot animation (first paint only) ----------
   Literal 1:1 port of Brasfield & Gorrie's hero entrance choreography.
   B&G's `avalanche.delay.enter` is treated as 0.5s in our timeline; every
   delay below is computed exactly the way their x-init blocks compute it.

     image       scale 1.5 → 1     0.5s circ.out         delay 0
     image       opacity 0 → 1     0.6s circ.out         delay 0
     nav border  xPercent -101→0   0.8s circ.inOut       delay 0.3s
     title       opacity 0 → 1     0.5s circ.out         delay 0.9s   (= enter+0.4)
     subtitle    opacity 0 → 1     0.5s circ.out         delay 0.9s   (concurrent with title)
     tab #1      yPercent 20 → 0   0.5s circ.out         delay 1.0s
     tab #2..n   same                                    delay 1.0s + 0.05s × index
     pause btn   same                                    delay after last tab
     CTAs        yPercent 10 → 0   0.6s circ.out         delay 1.6s   (= enter+0.4+0.7)

   Class machinery:
     .is-booting   — set in HTML at parse. Pins every animated element in
                     its pre-entrance state so nothing flashes through while
                     the loader curtains are still on top.
     .is-entering  — added by hero.js the moment lheroReady fires (curtains
                     begin pulling apart). This triggers every animation.
     Both stripped together once the full sequence settles. */

/* ---- Pre-state: pinned by .is-booting so nothing peeks past the curtain ---- */
.hero.is-booting .hero__slide.is-active .hero__image img {
  opacity: 0;
  transform: scale(1.5);
}
.hero.is-booting .hero__slide.is-active .hero__title,
.hero.is-booting .hero__slide.is-active .hero__subtitle {
  opacity: 0;
}
.hero.is-booting .hero__slide.is-active .hero__ctas {
  opacity: 0;
  transform: translateY(10%);
}
.hero.is-booting .hero__slide.is-active .hero__content {
  /* Suppress the per-active transition rules so each child animates on its own */
  transition: none;
}
.hero.is-booting .hero__nav::before {
  transform: translateX(-101%);
}
.hero.is-booting .hero__tab,
.hero.is-booting .hero__pauseplay {
  opacity: 0;
  transform: translateY(20%);
}

/* ---- Image: scale-down + fade-up (concurrent, two timing functions) ---- */
.hero.is-entering .hero__slide.is-active .hero__image img {
  animation:
    heroBootZoom 500ms cubic-bezier(0, 0.55, 0.45, 1) both,
    heroBootFade 600ms cubic-bezier(0, 0.55, 0.45, 1) both;
}
@keyframes heroBootZoom {
  from { transform: scale(1.5); }
  to   { transform: scale(1); }
}
@keyframes heroBootFade {
  from { opacity: 0; }
  to   { opacity: 1; }
}

/* ---- Title + subtitle: simple fadeIn at delay 0.9s (matches B&G h2/p) ---- */
.hero.is-entering .hero__slide.is-active .hero__title,
.hero.is-entering .hero__slide.is-active .hero__subtitle {
  animation: heroBootFadeIn 500ms cubic-bezier(0, 0.55, 0.45, 1) 900ms both;
  transition: none;
}
@keyframes heroBootFadeIn {
  from { opacity: 0; }
  to   { opacity: 1; }
}

/* ---- CTAs: yPercent 10→0 + fade at delay 1.6s (matches B&G CTA block) ---- */
.hero.is-entering .hero__slide.is-active .hero__ctas {
  animation: heroBootRise 600ms cubic-bezier(0, 0.55, 0.45, 1) 1600ms both;
  transition: none;
}
@keyframes heroBootRise {
  from { opacity: 0; transform: translateY(10%); }
  to   { opacity: 1; transform: translateY(0); }
}

/* ---- Bottom nav: top border line sweeps in left→right ----
   New ::before establishes a continuous, full-width hairline. The per-tab
   border-top is removed below in favor of this single animated line. */
.hero__nav::before {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  top: 0;
  height: 1px;
  background: rgba(237, 221, 183, 0.2);
  transform: translateX(0);
  transform-origin: left center;
  z-index: 1;
}
.hero.is-entering .hero__nav::before {
  animation: heroBootSweep 800ms cubic-bezier(0.85, 0, 0.15, 1) 300ms both;
}
@keyframes heroBootSweep {
  from { transform: translateX(-101%); }
  to   { transform: translateX(0); }
}

/* ---- Tab buttons: rise in with 50ms stagger starting at delay 1.0s ----
   B&G: stagger = 0.05, delay = enter + 1.0. We use the same. */
.hero.is-entering .hero__tab,
.hero.is-entering .hero__pauseplay {
  animation: heroBootTabIn 500ms cubic-bezier(0, 0.55, 0.45, 1) 1000ms both;
}
.hero.is-entering .hero__tab:nth-child(1) { animation-delay: 1000ms; }
.hero.is-entering .hero__tab:nth-child(2) { animation-delay: 1050ms; }
.hero.is-entering .hero__tab:nth-child(3) { animation-delay: 1100ms; }
.hero.is-entering .hero__tab:nth-child(4) { animation-delay: 1150ms; }
.hero.is-entering .hero__tab:nth-child(5) { animation-delay: 1200ms; }
.hero.is-entering .hero__pauseplay        { animation-delay: 1250ms; }
@keyframes heroBootTabIn {
  from { opacity: 0; transform: translateY(20%); }
  to   { opacity: 1; transform: translateY(0); }
}

/* ---------- Nav (tabs + pause) ---------- */
.hero__nav {
  position: absolute;
  left: 0;
  right: 0;
  bottom: 0;
  z-index: 5;
  display: flex;
  /* stretch so every tab fills the full nav height identically — prevents
     single-line labels from floating above wrapped ones at narrow widths */
  align-items: stretch;
  gap: 4px;
  padding: 16px var(--gutter);
  padding-bottom: calc(16px + env(safe-area-inset-bottom, 0px));
}

/* Desktop: horizontal text tabs. Labels never wrap — we shrink font size and
   letter-spacing fluidly so the longest label ("Remodels & Renovations")
   still fits in its flex column across the full desktop range. */
.hero__tab {
  position: relative;
  flex: 1 1 0;
  min-width: 0;
  /* Pad equally on top so the label baseline is identical across all tabs,
     regardless of length. */
  padding: 20px 8px;
  display: flex;
  align-items: flex-start;
  font-family: var(--font-display);
  font-weight: 500;
  font-size: clamp(10.5px, 0.95vw, 13px);
  letter-spacing: 0.1em;
  text-transform: uppercase;
  color: rgba(237, 221, 183, 0.65);
  text-align: left;
  overflow: hidden;
  transition: color var(--dur-base) var(--ease-in-out-quad);
  /* Top hairline now lives on .hero__nav::before so it can sweep in as a
     single continuous line during the boot animation. */
}
.hero__tab-label {
  display: block;
  width: 100%;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}
.hero__tab:hover { color: var(--cream); }
.hero__tab.is-active { color: var(--cream); }

/* Active-tab underline (sweeps left→right on enter, exits right on leave) */
.hero__tab::after {
  content: '';
  position: absolute;
  left: 0;
  right: 0;
  /* 4px thick (was 2px). top: -2px so the bar sits centered on the
     nav's top edge — half above, half below — instead of riding low. */
  top: -2px;
  height: 4px;
  background: var(--rusty);
  transform: translateX(-100%);
}
.hero__tab.is-active::after {
  transform: translateX(0);
  transition: transform var(--dur-base) var(--ease-in-out-circ);
}
.hero__tab.is-leaving::after {
  transform: translateX(100%);
  transition: transform var(--dur-base) var(--ease-in-out-circ);
}

/* Pause / play button */
.hero__pauseplay {
  flex-shrink: 0;
  width: 44px;
  height: 44px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  color: var(--cream);
  margin-left: 8px;
  opacity: 0.7;
  transition: opacity var(--dur-fast) var(--ease-in-out-quad),
              background var(--dur-fast) var(--ease-in-out-quad);
}
.hero__pauseplay:hover,
.hero__pauseplay:focus-visible {
  opacity: 1;
  background: rgba(237, 221, 183, 0.15);
}
.hero__pauseplay svg { width: 16px; height: 16px; }
.hero__pauseplay .icon-play { display: none; }
.hero.is-paused .hero__pauseplay .icon-play { display: block; }
.hero.is-paused .hero__pauseplay .icon-pause { display: none; }

/* ---------- Prev / next arrows ---------- */
.hero__arrow {
  position: absolute;
  top: 50%;
  transform: translateY(-50%);
  width: 48px;
  height: 48px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border-radius: 50%;
  background: transparent;
  color: var(--cream-soft);
  z-index: 6;
  opacity: 0.7;
  transition: opacity var(--dur-fast) var(--ease-in-out-quad),
              background var(--dur-fast) var(--ease-in-out-quad),
              transform var(--dur-fast) var(--ease-in-out-quad);
}
.hero__arrow svg {
  width: 28px;
  height: 28px;
  filter: drop-shadow(0 1px 3px rgba(0, 0, 0, 0.55));
}
.hero__arrow:hover,
.hero__arrow:focus-visible {
  opacity: 1;
  background: rgba(237, 221, 183, 0.15);
}
.hero__arrow--prev { left: 12px; }
.hero__arrow--next { right: 12px; }
.hero__arrow--prev:hover { transform: translateY(-50%) translateX(-2px); }
.hero__arrow--next:hover { transform: translateY(-50%) translateX(2px); }

@media (min-width: 768px) {
  .hero__arrow { width: 56px; height: 56px; }
  .hero__arrow svg { width: 32px; height: 32px; }
  .hero__arrow--prev { left: 20px; }
  .hero__arrow--next { right: 20px; }
}

/* ---------- Mobile & narrow-desktop nav: dots instead of tab labels ----------
   "Remodels & Renovations" is long enough that under ~900px it would truncate
   with ellipsis even at the smallest comfortable font size, so we fall back to
   dots at tablet-and-narrow-laptop widths to keep the nav clean. */
@media (max-width: 899px) {
  .hero__nav {
    justify-content: center;
    gap: 10px;
    padding: 20px var(--gutter);
  }
  .hero__tab {
    flex: 0 0 auto;
    width: 10px;
    height: 10px;
    padding: 0;
    border: 2px solid rgba(237, 221, 183, 0.6);
    border-radius: 50%;
    background: transparent;
    border-top: 2px solid rgba(237, 221, 183, 0.6);
    transition: background var(--dur-base) var(--ease-in-out-circ),
                border-color var(--dur-base) var(--ease-in-out-circ),
                transform var(--dur-base) var(--ease-in-out-circ);
  }
  .hero__tab::after { display: none; }
  .hero__tab.is-active {
    background: var(--rusty);
    border-color: var(--rusty);
    transform: scale(1.2);
  }
  .hero__tab-label {
    position: absolute;
    width: 1px; height: 1px;
    padding: 0; margin: -1px;
    overflow: hidden;
    clip: rect(0, 0, 0, 0);
    white-space: nowrap;
    border: 0;
  }
  .hero__pauseplay {
    position: absolute;
    right: var(--gutter);
    top: 50%;
    transform: translateY(-50%);
    margin: 0;
  }
}

/* ---------- Reduced motion ---------- */
@media (prefers-reduced-motion: reduce) {
  .hero__slide,
  .hero__slide.is-active,
  .hero__slide.is-leaving {
    transform: none !important;
    transition: opacity var(--dur-base) linear !important;
  }
  .hero__content,
  .hero__slide.is-active .hero__content,
  .hero__slide.is-leaving .hero__content {
    transform: none !important;
    transition: opacity var(--dur-base) linear !important;
  }
  .hero.is-booting .hero__slide.is-active .hero__image img,
  .hero.is-booting .hero__slide.is-active .hero__content,
  .hero.is-entering .hero__slide.is-active .hero__image img,
  .hero.is-entering .hero__slide.is-active .hero__content {
    animation: none !important;
    opacity: 1 !important;
    transform: none !important;
  }
}
