/* ==========================================================================
   Motion — the page coming up to meet the reader
   --------------------------------------------------------------------------
   One effect: a heading or a tile arrives faded and a few pixels low, and
   settles as it comes up the page. Nothing else here, and the file is meant
   to stay that small. The site's other movement belongs to the components
   that own it: the disclosure chevron and the jump-link arrow in
   components.css, the press on a button beside .btn, the phone menu in
   chrome.css.

   Loaded last, because it adds motion to what the files above have already
   drawn and changes no layout, colour or size of its own.

   It is worth saying what this is not. components.css deliberately holds
   the rule that a card does not move under the cursor, because a surface
   that shifts takes the line somebody is halfway through reading with it.
   That still stands. This moves a block once, before it is read, and then
   never again.

   Driven by reveal.js, which is loaded from <head> without defer so that
   .js-reveal is on <html> before the first paint. The header of that file
   says why this is JavaScript and not the pure-CSS scroll timeline it
   started as.
   ========================================================================== */

/* --------------------------------------------------------------------------
   Blocks arrive
   --------------------------------------------------------------------------
   Two gates, and they cover different moments:

     @media screen              keeps it off paper. A sheet of blocks that
                                were never scrolled past would otherwise
                                print at opacity 0.
     prefers-reduced-motion     the reader asked for stillness. Not
                                shortened to .01ms like the rest of the
                                site's motion (base.css) but never declared,
                                so nothing is hidden in the first place.
                                reveal.js checks the same thing before it
                                adds the class; this half is what covers the
                                setting being turned on partway through a
                                visit, when the class is already there.

   The .js-reveal class is the third gate and the load-bearing one. No
   script, no class, no hiding: a blocked file, a Content-Security-Policy
   change or JavaScript switched off all land on the page exactly as it is
   without this file.
   -------------------------------------------------------------------------- */

@media screen and (prefers-reduced-motion: no-preference) {
  /* Kept in step with SELECTOR in reveal.js by test_motion.py. */
  .js-reveal .section-head,
  .js-reveal .card,
  .js-reveal .service-tile,
  .js-reveal .person,
  .js-reveal .quote {
    opacity: 0;
  }

  /* An animation rather than a transition, because .card, .person and
     .quote already carry a transition for their hover state and anything
     declared here would replace it: .is-revealed never comes off, so the
     hover would lose its easing for good. An animation sits beside a
     transition instead of on top of it.

     `both`, so the block stays on the opening frame through its stagger
     delay and holds the closing one afterwards. That closing frame is what
     overrides the opacity: 0 above, which is why the fill mode is not
     optional. */
  .js-reveal .is-revealed {
    animation: reveal-rise .5s ease-out both;
    animation-delay: var(--reveal-delay, 0s);
  }
}

/* The end frame is `transform: none` rather than `translateY(0)` on
   purpose. The animation is filled forwards for ever, and a held
   translateY(0) is still a transform, which makes the element a containing
   block for any `position: fixed` descendant. Nothing inside these blocks
   is fixed today (the cookie banner and the lightbox are both appended to
   <body>), and `none` means nothing has to stay true for this to keep
   working.

   Only opacity and transform, because those are the two a browser can
   animate off the main thread. A page of these animating anything else
   would stutter on the phones this site is mostly read on. */
@keyframes reveal-rise {
  from {
    opacity: 0;
    transform: translateY(10px);
  }
  to {
    opacity: 1;
    transform: none;
  }
}
