/* ==========================================================================
   Hero

   ONE hero on every page and subpage. Same height, same type, same scrim,
   same scroll behaviour. The image is the only thing that changes.

   Modelled on thechadcarrollgroup.com's homepage hero, measured off their
   live computed styles: full viewport height, full-bleed cover media, large
   uppercase display type, and a scrubbed parallax that drives the media and
   the title at different rates.

   Note their site only does this on the homepage; every inner page there
   drops straight into content. Doing it everywhere is our addition.
   ========================================================================== */

.yp-hero {
  position: relative;
  display: flex;
  align-items: center;
  justify-content: center;
  /* 89vh. Down twice then back up once by 10 percent from full viewport, so a real
     slice of the next section shows at the fold and the page reads as
     continuing rather than as a full stop. */
  height: 89vh;
  min-height: 89vh;
  /* svh, not dvh. dvh tracks the URL bar as it hides and shows, so an 89dvh
     hero resizes, and pushes the whole page under it, in the middle of a
     scroll on every phone. svh is the viewport with the bar showing: the
     same height on first paint, and it never changes afterwards. vh above
     is the fallback. */
  height: 89svh;
  min-height: 89svh;
  overflow: hidden;
  background: var(--yp-ink);
}

/* The media is deliberately taller than the frame it sits in. Chad's tween
   slides the video down 80% of its own height, which on a viewport-tall
   element would drag its top edge into view. Oversizing by 20% and travelling
   within that slack gives the identical read with no exposed edge. */
.yp-hero-media {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 120%;
  will-change: transform;
  transform: translate3d(0, 0, 0);
}

.yp-hero-media img,
.yp-hero-media video {
  display: block;
  width: 100%;
  height: 100%;
  object-fit: cover;
  /* Per page focal point. A single centre crop cannot serve every photograph:
     on About the subject sits high in the frame and centring cut her face off
     at the top edge. Pages that need a different anchor set the variable in
     their own stylesheet. */
  object-position: var(--yp-hero-focus, center);
}

/* Legibility without a flat black wash: heavier top and bottom where the
   header and the title sit, near-clear through the middle so the picture
   still reads as a picture. */
.yp-hero-scrim {
  position: absolute;
  inset: 0;
  background:
    linear-gradient(to bottom,
      rgb(var(--yp-ink-rgb) / 0.55) 0%,
      rgb(var(--yp-ink-rgb) / 0.18) 38%,
      rgb(var(--yp-ink-rgb) / 0.30) 72%,
      rgb(var(--yp-ink-rgb) / 0.62) 100%);
}

/* Centred. The 30px gutter is the same one the header logo sits on, so a long
   page name ("New Construction Condos") never runs closer to the viewport
   edge than the mark does, and text-wrap: balance on the title keeps two
   centred lines at similar widths. */
.yp-hero-inner {
  position: relative;
  z-index: 2;
  width: 100%;
  max-width: 1460px;
  padding: 0 30px;
  text-align: center;
  will-change: transform, opacity;
}

/* 103px at a 1710 viewport is Chad's measured size, which is 6.02vw. Held to
   that ratio and clamped at both ends so a long page name cannot overflow on
   a phone or grow past the display ceiling on a wide monitor. */
.yp-hero-title {
  margin: 0;
  color: var(--yp-white);
  font-family: var(--yp-hero-font, var(--yp-serif, Georgia, serif));
  font-size: clamp(2.125rem, 6vw, 6.5rem);
  font-weight: var(--yp-w-display, 560);
  line-height: 1.04;
  letter-spacing: 0.02em;
  text-transform: uppercase;
  text-wrap: balance;
}

.yp-hero-sub {
  /* auto inline margins, not just margin-top. The 46ch measure keeps the line
     readable, but a constrained box with zero side margins sits flush left no
     matter what text-align says: centring the TEXT only centres it inside its
     own 437px box. The box has to be centred too. */
  margin: 22px auto 0;
  max-width: 46ch;
  color: rgb(var(--yp-white-rgb) / 0.86);
  font-family: var(--yp-serif, Georgia, serif);
  font-size: clamp(0.875rem, 0.5vw + 0.72rem, 1.0625rem);
  line-height: 1.6;
  letter-spacing: 0.01em;
}

/* ---- letter reveal -------------------------------------------------------
   hero.js splits the title into per-character spans, the same way Chad's
   markup ships one <div> per letter. Each rests below the line and rises on
   load, staggered by index. Doing the split in JS keeps the HTML readable and
   keeps the title a single translatable string. */

/* The default is VISIBLE. Only .is-anim, which hero.js sets synchronously,
   moves the letters to their hidden resting state, and .is-in brings them
   back. This ordering matters: gating visibility on a JS class means a
   background tab, a throttled rAF, or a headless renderer ships a blank
   headline, because transitions do not run on hidden content. Written this
   way the worst case is a hero that simply appears without animating. */

.yp-hero-title .yp-ch {
  display: inline-block;
  transition: opacity 0.5s ease, transform 0.75s cubic-bezier(0.25, 0.46, 0.45, 0.94);
  transition-delay: var(--ch-delay, 0s);
}

.yp-hero-title .yp-sp { display: inline-block; width: 0.28em; }

.yp-hero.is-anim .yp-hero-title .yp-ch { opacity: 0; transform: translateY(0.5em); }
.yp-hero.is-anim.is-in .yp-hero-title .yp-ch { opacity: 1; transform: translateY(0); }

.yp-hero-sub {
  transition: opacity 0.6s ease 0.5s, transform 0.8s cubic-bezier(0.25,0.46,0.45,0.94) 0.5s;
}
.yp-hero.is-anim .yp-hero-sub { opacity: 0; transform: translateY(14px); }
.yp-hero.is-anim.is-in .yp-hero-sub { opacity: 1; transform: translateY(0); }

/* ---- responsive ---------------------------------------------------------- */

/* 540, not 640: this must match the breakpoint where .st-header-inner
   changes its own gutter, or the title stops starting on the logo's edge. */
@media (max-width: 540px) {
  .yp-hero-inner { padding: 0 16px; }
  .yp-hero-title { letter-spacing: 0.01em; }
}

/* ---- reduced motion ------------------------------------------------------
   Purely additive: nobody who has not asked their OS for less motion sees any
   difference. The parallax is also disabled in hero.js, which reads the same
   query, so the transform is never written at all. */

@media (prefers-reduced-motion: reduce) {
  .yp-hero-title .yp-ch,
  .yp-hero-sub {
    opacity: 1;
    transform: none;
    transition: none;
  }
  .yp-hero-media { transform: none !important; }
}
