/* Motion — the one place the site's entrance effects are defined.
   The approved visual language allows an arrival that moves no more than about
   8px and finishes quickly; nothing here scrolls by itself, loops, or hides
   content from a visitor whose browser asks for less motion.

   A template marks an element with data-reveal and assets/js/reveal.js adds
   .is-in when it arrives. Until then the element is held at its start state, so
   the effect costs no layout shift: the element keeps its box and only its
   opacity and 8px offset change. */

html.has-reveal [data-reveal]{
  opacity:0;
  transform:translateY(var(--reveal-shift));
  transition:opacity var(--transition-arrive), transform var(--transition-arrive);
  transition-delay:var(--reveal-delay,0ms);
  will-change:opacity, transform;
}

/* The revealed state has to outrank the hidden one. The hidden rules below are
   scoped to html.has-reveal, which gives them one more element selector than a
   bare [data-reveal].is-in, so the scoping is mirrored on every revealed rule:
   without it the hidden rule wins for every marked block and nothing a template
   marked ever arrives. */
html.has-reveal [data-reveal].is-in{
  opacity:1;
  transform:none;
  will-change:auto;
}

/* A row of cards, figures or icons arrives one after another rather than all at
   once. The script numbers the children, so the step is a stylesheet value. */
html.has-reveal [data-reveal-stagger] > *{
  opacity:0;
  transform:translateY(var(--reveal-shift));
  transition:opacity var(--transition-arrive), transform var(--transition-arrive);
  transition-delay:calc(var(--reveal-step,60ms) * var(--reveal-index,0));
}

html.has-reveal [data-reveal-stagger].is-in > *{
  opacity:1;
  transform:none;
}

/* The page's own first screen is never hidden: it is already in view when the
   document paints, so revealing it would only delay what the visitor came for. */
html.has-reveal [data-reveal].is-instant,
html.has-reveal [data-reveal-stagger].is-instant > *{
  opacity:1;
  transform:none;
  transition:none;
}

/* Motion the site runs on its own, without a scroll trigger: a moving highlight
   travelling along a drawn path. The path is normalised to pathLength="100", so
   one keyframe set drives a link of any length. */
@keyframes hober-flow-dash{
  from{stroke-dashoffset:100}
  to{stroke-dashoffset:-100}
}

@keyframes hober-flow-pulse{
  0%,100%{opacity:.18}
  50%{opacity:.5}
}

/* A link that is drawn when its diagram arrives: the line is revealed from its
   own start rather than fading in as a whole. */
@keyframes hober-draw{
  from{stroke-dashoffset:var(--draw-length,200)}
  to{stroke-dashoffset:0}
}

@media (prefers-reduced-motion: reduce){
  /* Scoped like the hidden rule this answers, and last in the file, so a reader
     whose browser asks for less motion is never held at the hidden state. */
  html.has-reveal [data-reveal],
  html.has-reveal [data-reveal-stagger] > *{
    opacity:1;
    transform:none;
    transition:none;
  }

  .diagram [class*="__flow"],
  .diagram [class*="__line"],
  .flow-dot,
  .flow-glow{
    animation:none !important;
  }

  *{
    scroll-behavior:auto !important;
  }
}
