/* HIGHPEX — scroll reveal (blur → sharp)

   Nothing is hidden until scroll-reveal.js puts .hp-reveal-on on <html>, and each
   element drops its reveal classes shortly after revealing. So a visitor with no JS,
   a failed observer, or reduced-motion enabled sees the untouched page, and a revealed
   element carries no leftover transition that could fight its own hover rules.

   Rule order matters: .hp-in must come last, since it shares specificity with the
   base and heading rules and has to win as the end state. */

.hp-reveal-on .hp-r {
  opacity: 0;
  filter: blur(15px);
  /* --hp-from is flipped by JS so content always arrives from the edge you came from */
  transform: translate3d(0, var(--hp-from, 38px), 0) scale(0.984);
  transition:
    opacity 0.5s ease-out,
    filter 0.62s ease-out,
    transform 0.62s cubic-bezier(0.22, 0.61, 0.36, 1);
  transition-delay: var(--hp-d, 0ms);
}

/* Headings land faster than body content: they are read first, so a slow sharpen on
   a headline reads as the page lagging. No letter-spacing transition on purpose —
   animated tracking makes the text visibly crawl. */
.hp-reveal-on .hp-r.hp-r-head {
  filter: blur(10px);
  transform: translate3d(0, calc(var(--hp-from, 38px) * 0.45), 0) scale(0.996);
  transition:
    opacity 0.3s ease-out,
    filter 0.36s ease-out,
    transform 0.36s cubic-bezier(0.22, 0.61, 0.36, 1);
  transition-delay: var(--hp-d, 0ms);
}

.hp-reveal-on .hp-r.hp-in {
  opacity: 1;
  filter: blur(0);
  transform: translate3d(0, 0, 0) scale(1);
}

@media (prefers-reduced-motion: reduce) {
  .hp-reveal-on .hp-r,
  .hp-reveal-on .hp-r.hp-r-head,
  .hp-reveal-on .hp-r.hp-in {
    opacity: 1;
    filter: none;
    transform: none;
    transition: none;
  }
}
