/* ==========================================================================
   Staggered blur-in reveal.

   A container marked [data-reveal] holds elements marked .rv; reveal.js adds
   .in to the container and each .rv transitions in, 120ms apart, ordered by
   its own --i.

   The hidden state is scoped to html.js-anim, which a tiny inline script in
   the head sets before first paint. Without JavaScript the class is never
   added, so the content is plain visible text rather than stuck at opacity 0.
   Only opacity, filter and transform animate, so every element occupies its
   final space from the first paint and nothing reflows.
   ========================================================================== */

.js-anim [data-reveal] .rv {
  opacity: 0;
  filter: blur(10px);
  transform: translateY(24px);
  transition:
    opacity   0.8s cubic-bezier(.2, .65, .3, 1),
    filter    0.8s cubic-bezier(.2, .65, .3, 1),
    transform 0.8s cubic-bezier(.2, .65, .3, 1);
  transition-delay: calc(var(--i, 0) * 120ms);
}

/* Headline clauses lift proportionally to their own type size, which is what
   gives the effect its weight on large display text. Blocks and images use the
   fixed 24px above instead: 35% of a 700px screenshot would be a leap. */
.js-anim [data-reveal] .rv.rv-text { transform: translateY(35%); }

/* Articles and glossary terms: the body after the title, date and lede
   (the .rv elements) blurs in too, one step after the lede, so the whole
   text has the effect and not only the heading (Guilherme, 23 Oct 2026). */
.js-anim article[data-reveal] > :not(.rv) {
  opacity: 0;
  filter: blur(10px);
  transform: translateY(24px);
  transition:
    opacity   0.8s cubic-bezier(.2, .65, .3, 1),
    filter    0.8s cubic-bezier(.2, .65, .3, 1),
    transform 0.8s cubic-bezier(.2, .65, .3, 1);
  transition-delay: 360ms;
}

/* Last, so it beats .rv-text on equal specificity. */
.js-anim [data-reveal].in .rv {
  opacity: 1;
  filter: blur(0);
  transform: translateY(0);
}
.js-anim article[data-reveal].in > :not(.rv) {
  opacity: 1;
  filter: blur(0);
  transform: translateY(0);
}

/* Screen-reader copy of a headline that has been split into animated clauses,
   so assistive technology and crawlers get one clean sentence. */
.hl-plain {
  position: absolute;
  width: 1px;
  height: 1px;
  margin: -1px;
  padding: 0;
  overflow: hidden;
  clip: rect(0 0 0 0);
  clip-path: inset(50%);
  white-space: nowrap;
  border: 0;
}

@media (prefers-reduced-motion: reduce) {
  .js-anim [data-reveal] .rv,
  .js-anim [data-reveal] .rv.rv-text,
  .js-anim [data-reveal].in .rv,
  .js-anim article[data-reveal] > :not(.rv),
  .js-anim article[data-reveal].in > :not(.rv) {
    opacity: 1;
    filter: none;
    transform: none;
    transition: none;
    transition-delay: 0s;
  }
}
