/* story-reveal.css: the story's entrances (story.js section 1 drives them; see its header for the API).
   A block shows up once, as it comes on screen: opacity, and a short rise (text 6px; cards and sheets
   12px; figures 8px and a 1.5% scale; handwriting is written in from the left). How fast depends on
   how fast the reader scrolls: story.js sets --rv-dur per block, and .rv-quick (a flick, a jump) is
   opacity only. Nothing moves with the scroll, nothing hides again; every hidden state is gated on
   html.has-reveal (motion allowed, observers available) so no JS, reduced motion and print show
   the final page. The held map frame (#s3 .aemap-hold) never carries .rv. */

.rv { --rv-y: 6px; --rv-s: 1; }
.rv[data-rv-kind="card"],
.rv[data-rv-kind="sheet"] { --rv-y: 12px; }
.rv[data-rv-kind="figure"] { --rv-y: 8px; --rv-s: .985; }

/* #s2 and #s3 fade only, no rise (the owner asked for calm surroundings around the map, and the
   hero -> #s2 seam must never feel like "smart scrolling"). The rises start at #s3b. */
#s2 .rv, #s3 .rv { --rv-y: 0px; --rv-s: 1; }

/* An entrance unit must never be Chrome's scroll anchor: when one starts its entrance right after an
   instant jump (find-in-page, scrollIntoView), anchoring slid the page 144-410px on its own. */
html.has-reveal .rv { overflow-anchor: none; }

@media (prefers-reduced-motion: no-preference) {
  html.has-reveal .rv:not(.is-in) {
    opacity: 0;
    translate: 0 var(--rv-y);
    scale: var(--rv-s);
  }
  /* Handwriting is written in from the left by a soft-edged mask (never clip-path: a clipped target
     is invisible to IntersectionObserver in Chrome). */
  html.has-reveal .rv[data-rv-kind="ink"] {
    -webkit-mask-image: linear-gradient(90deg, #000 40%, transparent 60%);
            mask-image: linear-gradient(90deg, #000 40%, transparent 60%);
    -webkit-mask-size: 250% 100%;
            mask-size: 250% 100%;
    -webkit-mask-repeat: no-repeat;
            mask-repeat: no-repeat;
    -webkit-mask-position: 0 0;
            mask-position: 0 0;
  }
  html.has-reveal .rv[data-rv-kind="ink"]:not(.is-in) {
    translate: none;
    -webkit-mask-position: 100% 0;
            mask-position: 100% 0;
  }
  html.has-reveal .rv[data-rv-kind="ink"].rv-done {
    -webkit-mask-image: none;
            mask-image: none;
  }

  html.has-reveal .rv.is-in:not(.rv-done) {
    transition:
      opacity calc(var(--rv-dur, 520ms) * .8) cubic-bezier(.4, 0, .6, 1),
      translate var(--rv-dur, 520ms) cubic-bezier(.2, .7, .2, 1),
      scale var(--rv-dur, 520ms) cubic-bezier(.2, .7, .2, 1);
  }
  /* Brisk (the reader is moving): the opacity comes up front-loaded, the rise keeps its curve. */
  html.has-reveal .rv.rv-brisk.is-in:not(.rv-done) {
    transition:
      opacity calc(var(--rv-dur, 520ms) * .7) cubic-bezier(.2, .6, .35, 1),
      translate var(--rv-dur, 520ms) cubic-bezier(.2, .7, .2, 1),
      scale var(--rv-dur, 520ms) cubic-bezier(.2, .7, .2, 1);
  }
  html.has-reveal .rv[data-rv-kind="ink"].is-in:not(.rv-done) {
    transition:
      opacity calc(var(--rv-dur, 820ms) * .3) linear,
      -webkit-mask-position var(--rv-dur, 820ms) cubic-bezier(.35, .15, .3, 1),
      mask-position var(--rv-dur, 820ms) cubic-bezier(.35, .15, .3, 1);
  }
  html.has-reveal .rv.rv-quick.is-in:not(.rv-done) {
    transition: opacity var(--rv-dur, 140ms) linear;
  }
  html.has-reveal .rv.rv-now { transition: none; }
}

@media print {
  .rv { opacity: 1 !important; translate: none !important; scale: none !important; -webkit-mask-image: none !important; mask-image: none !important; }
}
