/* ==========================================================================
   KOTA — how the data arrives.

   A chart that is simply there on the first paint asks the reader to take the
   whole card in at once. Drawn instead, it hands over one thing at a time:
   the axis, then the shape, then the number. It is also the only moment in a
   dashboard where motion carries meaning rather than decoration, because the
   direction a bar grows is the direction the value is measured in.

   Three rules hold the whole file together:

   1. Everything animates from the baseline it is measured from. Bars grow up
      from zero, progress grows out from the left, an arc sweeps from where it
      starts. Nothing fades in from nowhere, because that would say the value
      appeared rather than accumulated.

   2. It plays once, on arrival, and never again. These are not loading states.
      A card that re-animates on every re-render is a card that cannot be read
      while it is being used.

   3. It is transform and opacity only, so it stays on the compositor and a
      twelve-bar chart costs the same as one.

   Reduced motion turns all of it off rather than shortening it: the point of
   the setting is that nothing moves, not that it moves quickly.
   ========================================================================== */

/* ---- when it plays ----
   Nothing animates on load. A chart eight screens down has finished drawing
   itself long before anyone reaches it, which is the same as not animating at
   all, so each card waits until it is actually on screen.

   Two classes do it, and the order matters. motion.js arms a card first, which
   is what puts its marks in the "before" state; the card only gets .m-on when
   it intersects. If the script never runs, nothing is ever armed and every
   chart renders finished, which is the state it should fail to.
   ========================================================================== */
@media (prefers-reduced-motion: no-preference){

  .m-armed .m-bar{transform:scaleY(0)}
  .m-armed .m-fill{transform:scaleX(0)}
  .m-armed .m-draw{stroke-dashoffset:100}
  /* An arc hides behind its own dash length, not behind 100: with a dash of
     --arc and a gap of 100 the path only clears the visible run once the
     offset equals --arc. At 100 the tail of the pattern wraps back into
     view and the gauge starts part drawn. */
  .m-armed .m-arc{stroke-dashoffset:var(--arc,100)}
  .m-armed .m-area,.m-armed .m-dot,.m-armed .m-cell,.m-armed .m-val{opacity:0}

  /* ---- bars ----
     scaleY rather than height: the value is already in the inline style, and
     a transform does not need to know it. */
  .m-on .m-bar{transform-origin:bottom center;animation:m-rise .62s cubic-bezier(.2,.7,.3,1) both}
  @keyframes m-rise{from{transform:scaleY(0)}to{transform:scaleY(1)}}

  /* ---- a fill that runs left to right ----
     Progress is read in the direction it is filled, so it is drawn that way:
     the bar, the meter under a rail, a share of a total. */
  .m-on .m-fill{transform-origin:left center;animation:m-run .7s cubic-bezier(.2,.7,.3,1) both}
  @keyframes m-run{from{transform:scaleX(0)}to{transform:scaleX(1)}}

  /* ---- a line drawing itself ----
     pathLength is set on the element so one dash value works for any path. */
  .m-on .m-draw{animation:m-stroke 1.1s cubic-bezier(.3,.6,.2,1) both}
  @keyframes m-stroke{from{stroke-dashoffset:100}to{stroke-dashoffset:0}}

  /* The area under a line cannot draw itself, so it arrives just behind the
     line that defines it. */
  .m-on .m-area{animation:m-soft .8s ease .35s both}
  @keyframes m-soft{from{opacity:0}to{opacity:1}}

  /* The end dot lands when the line reaches it. */
  .m-on .m-dot{animation:m-pop .4s cubic-bezier(.2,1.3,.4,1) .85s both}
  @keyframes m-pop{from{opacity:0;transform:scale(.4)}to{opacity:1;transform:scale(1)}}

  /* ---- discrete marks ----
     One consignment is one block, so they land one after another rather than
     as a wall. The delay comes from --i, set where the block is written. */
  .m-on .m-cell{animation:m-drop .34s cubic-bezier(.2,.8,.3,1) both;
    animation-delay:calc(var(--i, 0) * 22ms)}
  @keyframes m-drop{from{opacity:0;transform:translateY(5px) scale(.86)}
                    to{opacity:1;transform:none}}

  /* ---- the gauge ----
     Sweeps from the start of the arc to the value, which is the direction the
     score is counted in. */
  .m-on .m-arc{animation:m-sweep 1s cubic-bezier(.25,.65,.25,1) both}
  @keyframes m-sweep{from{stroke-dashoffset:var(--arc,100)}to{stroke-dashoffset:0}}

  /* ---- the number a chart resolves to ----
     Arrives last, because it is the conclusion of everything above it. */
  .m-on .m-val{animation:m-soft .5s ease .55s both}
}

/* SVG needs the property even when nothing is animating it, or the dash never
   applies once the class is added.

   The two are split because they mean different things. A .m-draw draws its
   whole path, so 100 is right. A .m-arc stops at a value, and that value is
   the whole point of a gauge: written flat here it overrode the per element
   dasharray, a stylesheet rule beating a presentation attribute, and every
   gauge rendered full whatever score it was showing. The value lives in
   --arc on the element now, which is also what the armed state and the sweep
   read, so there is one number and three uses of it. */
.m-draw{stroke-dasharray:100;stroke-dashoffset:0}
.m-arc{stroke-dasharray:var(--arc,100) 100;stroke-dashoffset:0}
