/* ---------------------------------------------------------------------------
   parallax.css — scroll-linked image depth.

   Ported from the motion study of mtechnikbmw.net (Squarespace 7.0 Momentum,
   `positionIndexImages()`, drift constant h = 0.8). That template pinned each
   image into a position:fixed 100vh box and counter-translated the image by
   -0.8 x the section offset, so the on-screen image moved at 20% of scroll
   speed while content moved at 100%.

   Our sections are in normal flow, not fixed, so the same 20% is produced a
   different way: the image is overscaled by `--px-travel` top and bottom, and
   JS translates it within +/- that slack. Because |translate| never exceeds the
   slack, an edge can never be exposed. See parallax.js for the derivation.

   Everything here is scoped under `html.px-on`, a class JS adds only when the
   effect is actually allowed to run. With JS off, with reduced motion, or on
   touch/narrow screens, none of these rules apply and the page renders exactly
   as it does today.

   CONTAINER GEOMETRY
     Absolutely positioning the image takes it out of flow, so each container
     must already have its own height or it would collapse to nothing. All
     three homepage containers do, in the public stylesheet, and nothing here
     touches those declarations:

       .luxury-home-hero          min-height: min(920px, 100svh)
       .luxury-brand-panel        min-height: 520px
       .luxury-landscape-feature  min-height: clamp(680px, 80vw, 880px)

     A future container without an intrinsic height needs one added there, not
     patched in here.
   --------------------------------------------------------------------------- */

html.px-on [data-parallax] {
  position: relative;
  overflow: hidden;
}

/* <picture> generates no box, so the <img> positions against [data-parallax]. */
html.px-on [data-parallax] picture {
  display: contents;
}

html.px-on [data-parallax] [data-parallax-image] {
  position: absolute;
  left: 0;
  right: auto;
  bottom: auto;
  margin: 0;
  width: 100%;
  top: calc(-1 * var(--px-travel, 10%));
  height: calc(100% + 2 * var(--px-travel, 10%));
  /* The overscale is taller than the container by construction, so an
     inherited cap would clip it and re-expose the edge the overscale exists to
     hide. `right`/`bottom`/`margin` above are here for the same reason: a site
     rule with `inset: 0` would otherwise stretch the image back to the box. */
  max-width: none;
  max-height: none;
  object-fit: cover;
  /* object-position is deliberately not set: the site stylesheet owns each
     image's crop, including the responsive variants on the team panel. */
  transform: translate3d(0, var(--px-y, 0px), 0);
  will-change: transform;
}

/* Belt and braces. JS already refuses to add .px-on under reduced motion; this
   makes the CSS side inert too, in case the class is ever set another way. */
@media (prefers-reduced-motion: reduce) {
  html.px-on [data-parallax] [data-parallax-image] {
    top: 0;
    height: 100%;
    transform: none;
    will-change: auto;
  }
}

/* --- J. Morris Home Loans ---------------------------------------------------
   Single container: the homepage hero portrait.

   CONTAINER GEOMETRY — already satisfied by site.css, nothing added here:
     .hero-portrait  position: relative
                     min-height: 36rem  (31rem at the narrow desktop step)
     .hero-grid      align-items: stretch
   So the figure holds its own height with the image out of flow, and the
   absolute image has a positioned ancestor to resolve against. The figure's
   only border is `border-left`, so the JS border-box height and the CSS
   percentage height still agree — the coverage proof in parallax.js holds.

   STACKING — .portrait-label ("One direct point of contact") is already
   position:absolute and follows <picture> in source order, so it paints above
   the image on source order alone. The z-index below states that explicitly
   rather than leaving a caption's legibility resting on DOM order.

   No entrance animation owns `transform` on this hero, so the Velvet
   `scale`/`px-hero-settle` hand-off has no counterpart here and is omitted.
   -------------------------------------------------------------------------- */
html.px-on .hero-portrait .portrait-label {
  z-index: 1;
}
