/* ===========================================================================
   sparkle.css - the magic dust. Two things, and both of them are about a
   thing you can press:

     hover   a few motes arrive with the pointer, and one keeps coming while
             it stays - each drifts a little and fades. They sit just OUTSIDE
             the thing's outline, so they need a layer of their own: a cut
             hexagon slices anything that tries to leave its own box.
     press   five to nine small stars out of the point that was pressed, each
             thrown off on its own heading and fading on the way. A slider is
             dragged rather than pressed, so it throws none.

   The shapes are the app's own, not new ones: the mote is the four-point
   twinkle that sits on the corners of every sigil (holdhex.js), and the star
   is the six-pointed one the sigils turn on. Masks, not backgrounds, so the
   motes can wear whatever colour the thing under them wears.

   The layer is built and driven entirely by sparkle.js - this file is the look.

   Everything below is a knob. Put any of them on an element (or higher up the
   tree) to change what happens there:
     --spk-hue     the colour the dust wears. Left alone, a mote borrows the
                   card's genre colour (--gcl) and a bare button the house
                   purple, so a genre-tinted card sparkles in its genre.
     --spk         0 turns the whole thing off. Nothing is ever built.
   =========================================================================== */

:root {
  --spk: 1;                     /* 0 = no sparkle at all, anywhere           */
  --spk-size: 10px;             /* how big one mote is                       */
  --spk-travel: 26px;           /* how far a mote drifts before it fades     */
  --spk-life: 1000ms;           /* how long one mote lives                   */
  --spk-gap: 340ms;             /* one mote after another, while hovered     */
  --spk-burst: 5;               /* the few that arrive with the pointer      */
  --spk-out: 7px;               /* how far outside the outline they start    */
  --spk-max: 44;                /* cap on motes alive at once, across the page */
  --spk-pop: 560ms;             /* the press: from the point, outwards, gone */
  --spk-pop-size: 15px;         /* how big one star of the scatter is        */
  --spk-pop-min: 5;             /* fewest stars one press throws             */
  --spk-pop-max: 9;             /* most stars one press throws               */
  --spk-pop-travel: 34px;       /* how far each of them flies outwards       */
  --spk-z: 70;                  /* above every panel the site stacks (max 60) */

  /* the four-point twinkle off the corners of a sigil, and the six-pointed
     star that turns inside it. Filled white and used as a mask, so the colour
     comes from the element, never from here. */
  --spk-ink: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='-6 -6 12 12'%3E%3Cpath d='M0 -5 L1.5 -1.5 L5 0 L1.5 1.5 L0 5 L-1.5 1.5 L-5 0 L-1.5 -1.5 Z' fill='%23fff'/%3E%3C/svg%3E");
  --spk-star: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 100 100'%3E%3Cpolygon points='50,0 62.5,28.35 93.3,25 75,50 93.3,75 62.5,71.65 50,100 37.5,71.65 6.7,75 25,50 6.7,25 37.5,28.35' fill='%23fff'/%3E%3C/svg%3E");
}

/* one layer for the whole page, floating over everything. Nothing in it can be
   clicked, and it never grows a scrollbar. */
#spk-layer {
  position: fixed; inset: 0; z-index: var(--spk-z);
  overflow: hidden; pointer-events: none;
}
#spk-layer * { pointer-events: none; }

/* ---------------------------------------------------------------- a mote -- */

.spk {
  position: absolute; width: var(--spk-size); height: var(--spk-size);
  /* the mote hangs off the point it was given, not off its own top-left */
  margin: calc(var(--spk-size) / -2) 0 0 calc(var(--spk-size) / -2);
  background: var(--spk-hue, #ffe2ff);
  -webkit-mask: var(--spk-ink) center / contain no-repeat;
          mask: var(--spk-ink) center / contain no-repeat;
  filter: drop-shadow(0 0 5px var(--spk-hue, #ffe2ff));
  will-change: transform, opacity;
  animation: spk-drift var(--spk-life) ease-out forwards;
}

/* arrives, hangs about, then drifts off a little way and is gone. The twinkle
   is in the opacity: it never holds still at full strength. */
@keyframes spk-drift {
  0%   { transform: translate3d(0, 0, 0) scale(.35) rotate(0deg); opacity: 0; }
  18%  { opacity: 1; }
  45%  { opacity: .55; }
  65%  { opacity: 1; }
  100% { transform: translate3d(var(--spk-dx, 0), var(--spk-dy, -14px), 0)
                    scale(var(--spk-sc, .9)) rotate(var(--spk-r, 90deg));
         opacity: 0; }
}

/* ---------------------------------------------------------------- a pop -- */

/* The press is a scatter, not a bloom. The wrapper is a single point - the
   place the pointer actually went down - and the stars hang off it, each one
   thrown out along its own heading by --spk-dx/--spk-dy, which the script
   picks: an even spread round the circle, wobbled, so no two presses match. */
.spk-pop {
  position: absolute; width: 0; height: 0;
}

/* one small star of the scatter: the same six-pointed star the sigils turn on,
   a third of the width the old single bloom opened to, and gone on the way
   out rather than landing anywhere. */
.spk-pop .spk-pip {
  position: absolute; width: var(--spk-pop-size); height: var(--spk-pop-size);
  margin: calc(var(--spk-pop-size) / -2) 0 0 calc(var(--spk-pop-size) / -2);
  background: var(--spk-hue, #ffe2ff);
  -webkit-mask: var(--spk-star) center / contain no-repeat;
          mask: var(--spk-star) center / contain no-repeat;
  filter: drop-shadow(0 0 6px var(--spk-hue, #ffe2ff));
  will-change: transform, opacity;
  animation: spk-pip var(--spk-pop) cubic-bezier(.2, .7, .3, 1) forwards;
}
@keyframes spk-pip {
  0%   { transform: translate3d(0, 0, 0) scale(.2) rotate(0deg); opacity: 0; }
  18%  { opacity: 1; }
  62%  { opacity: .9; }
  100% { transform: translate3d(var(--spk-dx, 0), var(--spk-dy, -18px), 0)
                   scale(var(--spk-sc, .55)) rotate(var(--spk-r, 140deg));
         opacity: 0; }
}

/* --------------------------------------------------- when asked to calm -- */

/* Somebody who has asked their machine for less movement still gets to see
   that a thing was pressed - the scatter just blinks where it was pressed
   instead of flying, and no dust follows the pointer around. */
@media (prefers-reduced-motion: reduce) {
  .spk { display: none; }
  .spk-pop .spk-pip { animation: spk-blink 200ms ease-out forwards; }
}
@keyframes spk-blink {
  0%   { transform: none; opacity: .85; }
  100% { transform: none; opacity: 0; }
}
