/* Pixel smiley (see part.js). A 13 x 13 pixel face on a 156-unit grid (12 units per pixel).
   Markup: <div class="pxsmiley" data-mood="happy"></div>  (or data-mood="sad"); part.js draws the face.
   Every colour, size and timing below is a knob; defaults are the measured source values. */
.pxsmiley {
  --sm-size: 128px;                         /* face box (source 128px) */
  --sm-ink: #0a0a0a;                        /* eyes + mouth */
  --sm-blush: #e0492a;                      /* sad face's cheeks when shy */
  /* body heat bands (cell value = heat x 0.9): hidden below .30 */
  --sm-c0: #1c2541;                         /* >= .30  the frayed rim while fading */
  --sm-c1: #3b5bd9;                         /* >= .46  sad body */
  --sm-c2: #f5c518;                         /* >= .62  accent flicker */
  --sm-c3: #e0492a;                         /* >= .78  first step of the fade-out */
  --sm-hot: #d8ff00;                        /* .86-1.02 happy body (the hottest band) */
  --sm-heart: #e0492a;
  --sm-heart-rise: 72px;                    /* hearts float this far up */
  --sm-heart-dur: 1s;
  --sm-jump: 18px;                          /* first hop */
  --sm-hop: 7px;                            /* second, smaller hop */
  --sm-jump-dur: .62s;
  --sm-jump-ease: cubic-bezier(.3, 1.5, .5, 1);
  --sm-shy-scale: .93;
  --sm-shy-drop: 3px;
  --sm-shy-dur: .3s;
  position: relative; display: block; width: var(--sm-size); height: var(--sm-size);
}
.pxsmiley > .pxsm-face {
  display: block; width: 100%; height: 100%; overflow: visible;
  transform-origin: 50% 58%; transition: transform var(--sm-shy-dur) ease; will-change: transform;
}
.pxsmiley.is-jump > .pxsm-face { animation: pxsm-jump var(--sm-jump-dur) var(--sm-jump-ease); }
.pxsmiley.is-shy > .pxsm-face { transform: scale(var(--sm-shy-scale)) translateY(var(--sm-shy-drop)); }
@keyframes pxsm-jump {
  0% { transform: translateY(0); }
  28% { transform: translateY(calc(var(--sm-jump) * -1)); }
  52% { transform: translateY(0); }
  68% { transform: translateY(calc(var(--sm-hop) * -1)); }
  100% { transform: translateY(0); }
}

.pxsm-ink { fill: var(--sm-ink); }
.pxsm-blush { fill: var(--sm-blush); fill-opacity: 0; }
.pxsmiley.is-shy .pxsm-blush { fill-opacity: .5; }

/* body cells: part.js swaps the class as a cell's heat crosses a band */
.pxsm-cell { display: none; }
.pxsm-cell.b0 { display: inline; fill: var(--sm-c0); }
.pxsm-cell.b1 { display: inline; fill: var(--sm-c1); }
.pxsm-cell.b2 { display: inline; fill: var(--sm-c2); }
.pxsm-cell.b3 { display: inline; fill: var(--sm-c3); }
.pxsm-cell.bh { display: inline; fill: var(--sm-hot); }

.pxsm-heart {
  position: absolute; z-index: 6; width: 24px; height: 19px; pointer-events: none; color: var(--sm-heart);
  animation: pxsm-heart var(--sm-heart-dur) ease-out forwards;
}
.pxsm-heart rect { fill: currentColor; }
@keyframes pxsm-heart {
  0% { opacity: 0; transform: translate(-50%, 0) scale(.5); }
  14% { opacity: 1; }
  100% { opacity: 0; transform: translate(-50%, calc(var(--sm-heart-rise) * -1)) scale(1.1); }
}

@media (prefers-reduced-motion: reduce) {
  .pxsmiley.is-jump > .pxsm-face { animation: none; }
  .pxsmiley > .pxsm-face { transition: none; }
  .pxsm-heart { animation-name: pxsm-heart-still; }
  @keyframes pxsm-heart-still { 0% { opacity: 0; transform: translate(-50%, 0); } 14% { opacity: 1; } 100% { opacity: 0; transform: translate(-50%, 0); } }
}
