/* The paper pages' motion (DS2 "Motion", the Lively level; this file is DS2-1, ds2-1-paper-and-motion.md).
   The page is paper, so nothing floats, bounces, glows or slides up as you scroll. Things are SET, DRAWN, TYPED and
   COUNTED: a headline rises from behind a mask, hairlines draw, mono text types on, numbers tick, reading text
   inks in. Loaded after design/paper.css by the reading pages only.

   Two halves.
   - The feedback needs no script: an arrow leans, a button gives, a live dot breathes.
   - The arrival needs design/motion-boot.js in the page's <head>, which sets data-motion on <html> before the first
     draw, and design/motion.js at the page's end, which switches each part on as it comes into view (.mv-in) and
     then puts it back to an ordinary part of the page.
   A device that asks for less motion gets neither.

   A page says what moves in its own markup:
     data-mv-group        a part of the page that arrives together, when it comes into view
     data-mv="lines"      a headline, set a line at a time from behind a mask (its <br>s make the lines)
     data-mv="fade"       reading text, inked in. It fades; it never moves
     data-mv="type"       mono text with nothing inside it, typed on a character a step
     data-mv="lead"       a row of dots, run from its label to its value
     data-mv="count"      a number, counted up to its value by motion.js, which holds its width
     data-mv="bars"       a chart's bars (an <svg>'s <rect>s), risen from the baseline, left to right
     data-mv="draw"       a chart's line (its <svg>), drawn from the left
     data-mv-rule         a hairline of the thing's own: "top" or "bottom" (a 1px border, drawn from the left),
                          "inset" (one already drawn as a background, as the footer's), "fade" (borders inked in)
     data-mv-delay="320"  milliseconds this thing waits, on top of its turn in the group

   Only what sits in a group that hasn't arrived is ever hidden: PENDING below is "such a group, or anything in it".
   So a thing outside a group, or written into the page after its group arrived, can't be left unseen.

   The hidden states weigh as four attributes or classes and one element. A page's own rule for the same property
   must weigh less: no #id rule on a marked thing's opacity, visibility, transform, scale, clip-path, border colour
   or background.

   Three rules, each of which was a bug once:
   - A thing is hidden with NO transition and no animation; only its arrival is animated. A hidden state is a
     selector holding :not(.mv-in), and src/web/test/motion.test.js reads this file for it.
   - A headline split into masked lines becomes a column, or the masks' margins collapse and it grows.
   - A hairline drawn as a background starts at the border box, or it sits one pixel below the border it replaces. */
:root{--mv-ease:cubic-bezier(.2,.7,.2,1);--mv-set:cubic-bezier(.16,.84,.24,1)}

/* ================= the feedback ================= */
@media (prefers-reduced-motion:no-preference){
  /* an arrow leans the way it points */
  .arrow{transition:transform .16s var(--mv-ease)}
  a:hover .arrow,.btn:hover .arrow{transform:translate(2px,-2px)}
  /* a button gives under the finger */
  .btn{transition:background .12s ease,color .12s ease,border-color .12s ease,transform .08s ease}
  .btn:active{transform:translateY(1px) scale(.985)}
  .link{transition:text-decoration-thickness .12s ease}
  /* a live dot breathes (a planned one, or a page's in-development one, doesn't) */
  .st:not(.plan):not(.dev)::before{animation:mv-breathe 2.8s ease-in-out infinite}
  @keyframes mv-breathe{0%,100%{box-shadow:0 0 0 0 transparent}50%{box-shadow:0 0 0 4px color-mix(in srgb,currentColor 16%,transparent)}}
}

/* ================= the arrival ================= */
/* On a screen only: a printed page shows everything. */
@media screen{
  /* a headline is set, a line at a time, from behind a mask */
  html[data-motion] :is([data-mv-group]:not(.mv-in) *,[data-mv-group]:not(.mv-in))[data-mv="lines"]:not(.mv-split){visibility:hidden}
  html[data-motion] :is([data-mv-group]:not(.mv-in) *,[data-mv-group]:not(.mv-in))[data-mv="lines"] .mv-l{transform:translateY(118%)}
  html[data-motion] [data-mv="lines"].mv-split{display:flex;flex-direction:column}
  html[data-motion] .mv-line{display:block;overflow:hidden;padding:.1em .08em .16em;margin:-.1em -.08em -.16em}
  html[data-motion] .mv-l{display:block}
  html[data-motion] [data-mv="lines"].mv-in .mv-l{transition:transform .7s var(--mv-set);transition-delay:calc(var(--d,0ms) + var(--i,0) * var(--step,45ms) + var(--k,0) * 90ms)}

  /* reading text inks in; it never slides */
  html[data-motion] :is([data-mv-group]:not(.mv-in) *,[data-mv-group]:not(.mv-in))[data-mv="fade"]{opacity:0}
  html[data-motion] [data-mv="fade"].mv-in{transition:opacity .45s ease;transition-delay:calc(var(--d,0ms) + var(--i,0) * var(--step,45ms))}

  /* mono text types on, a character a step */
  html[data-motion] :is([data-mv-group]:not(.mv-in) *,[data-mv-group]:not(.mv-in))[data-mv="type"]{visibility:hidden}
  html[data-motion] .mv-t{display:inline-block}
  html[data-motion] [data-mv="type"].mv-in > .mv-t{animation:mv-type calc(var(--n,1) * var(--cps,14ms)) steps(var(--n,1),end) both;animation-delay:calc(var(--d,0ms) + var(--i,0) * var(--step,45ms))}
  @keyframes mv-type{from{clip-path:inset(0 100% 0 0)}to{clip-path:inset(0 0 0 0)}}

  /* a row of dots runs from its label to its value */
  html[data-motion] :is([data-mv-group]:not(.mv-in) *,[data-mv-group]:not(.mv-in))[data-mv="lead"]{scale:0 1;transform-origin:0 50%}
  html[data-motion] [data-mv="lead"].mv-in{scale:1 1;transform-origin:0 50%;transition:scale .5s var(--mv-ease);transition-delay:calc(var(--d,0ms) + var(--i,0) * var(--step,45ms))}

  /* a number counts up to its value: unseen until its turn, then motion.js runs it inside a box of its full width */
  html[data-motion] :is([data-mv-group]:not(.mv-in) *,[data-mv-group]:not(.mv-in))[data-mv="count"]{visibility:hidden}
  html[data-motion] .mv-n{display:inline-block;text-align:right}

  /* a chart: its bars rise from the baseline, left to right (--b is a bar's place, from motion.js); its line draws */
  html[data-motion] :is([data-mv-group]:not(.mv-in) *,[data-mv-group]:not(.mv-in))[data-mv="bars"] rect{transform-box:fill-box;transform-origin:50% 100%;transform:scaleY(0)}
  html[data-motion] [data-mv="bars"].mv-in rect{transform-box:fill-box;transform-origin:50% 100%;transition:transform .6s var(--mv-ease);transition-delay:calc(var(--d,0ms) + var(--i,0) * var(--step,45ms) + var(--b,0) * 9ms)}
  html[data-motion] :is([data-mv-group]:not(.mv-in) *,[data-mv-group]:not(.mv-in))[data-mv="draw"]{clip-path:inset(0 100% 0 0)}
  html[data-motion] [data-mv="draw"].mv-in{clip-path:inset(0 0 0 0);transition:clip-path 1.1s var(--mv-ease);transition-delay:calc(var(--d,0ms) + var(--i,0) * var(--step,45ms))}

  /* hairlines draw from the left. --mv-rule is the hairline's colour where it isn't --line. */
  html[data-motion] :is([data-mv-group]:not(.mv-in) *,[data-mv-group]:not(.mv-in))[data-mv-rule="top"]{border-top-color:transparent;background:linear-gradient(var(--mv-rule,var(--line)),var(--mv-rule,var(--line))) no-repeat border-box 0 0 / 0 1px}
  html[data-motion] [data-mv-rule="top"].mv-in{border-top-color:transparent;background:linear-gradient(var(--mv-rule,var(--line)),var(--mv-rule,var(--line))) no-repeat border-box 0 0 / 100% 1px;transition:background-size 1s var(--mv-ease) var(--d,0ms)}
  html[data-motion] :is([data-mv-group]:not(.mv-in) *,[data-mv-group]:not(.mv-in))[data-mv-rule="bottom"]{border-bottom-color:transparent;background:linear-gradient(var(--mv-rule,var(--line)),var(--mv-rule,var(--line))) no-repeat border-box 0 100% / 0 1px}
  html[data-motion] [data-mv-rule="bottom"].mv-in{border-bottom-color:transparent;background:linear-gradient(var(--mv-rule,var(--line)),var(--mv-rule,var(--line))) no-repeat border-box 0 100% / 100% 1px;transition:background-size .8s var(--mv-ease) var(--d,0ms)}
  /* one that is a background already: it grows to its own width */
  html[data-motion] :is([data-mv-group]:not(.mv-in) *,[data-mv-group]:not(.mv-in))[data-mv-rule="inset"]{background-size:0 1px}
  html[data-motion] [data-mv-rule="inset"].mv-in{transition:background-size 1s var(--mv-ease) var(--d,0ms)}
  /* one that can't be drawn from the left (a line between columns) inks in */
  html[data-motion] :is([data-mv-group]:not(.mv-in) *,[data-mv-group]:not(.mv-in))[data-mv-rule="fade"]{border-color:transparent}
  html[data-motion] [data-mv-rule="fade"].mv-in{transition:border-color .6s ease var(--d,0ms)}
}
