/* The companion on the web: the .av rules, ported from prototype/companion.css (lines 40 to 140)
   for the landing page. One figure, one SVG, drawn every frame by companion.js; this file
   carries the moods (whole-figure motion), the paper bubble and the still pose.

   Every value is a token from styles.css. Link styles.css first; this file adds only .av. */

.av {
  --size: 200px;
  position: relative;
  width: var(--size);
  height: var(--size);
  flex: none;
}

.av svg {
  display: block;
  width: 100%;
  height: 100%;
  overflow: visible;
}

/* the rig carries the whole-figure motion of a mood; the body inside it is drawn per frame */
.av__rig { transform-origin: 100px 172px; transform-box: view-box; }
.av__eyes { transform-box: fill-box; transform-origin: center; }

.av[data-state="idle"] .av__rig     { animation: av-breathe 3.4s ease-in-out infinite; }
.av[data-state="happy"] .av__rig    { animation: av-hop .62s var(--ease-out) 2; }
.av[data-state="excited"] .av__rig  { animation: av-jitter .32s ease-in-out infinite; }
.av[data-state="coach"] .av__rig    { animation: av-lean 2.2s ease-in-out infinite; }
.av[data-state="proud"] .av__rig    { animation: av-chest 2.6s ease-in-out infinite; }
.av[data-state="sleepy"] .av__rig   { animation: av-sag 4.2s ease-in-out infinite; }
.av[data-state="worried"] .av__rig  { animation: av-shiver .18s ease-in-out infinite; }
.av[data-state="super"] .av__rig    { animation: av-blaze 1.1s ease-in-out infinite; }
.av.is-charging .av__rig            { animation: av-charge .52s ease-in forwards !important; }
.av.is-released .av__rig            { animation: av-release var(--t-rubber) var(--ease-rubber) forwards !important; }

/* Reduce Motion: the figure is still: no breathe, no shake, no charge, no release. */
.av.is-still .av__rig,
.av.is-still.is-charging .av__rig,
.av.is-still.is-released .av__rig { animation: none !important; }

@keyframes av-breathe { 0%, 100% { transform: scale(1, 1); } 50% { transform: scale(1.02, .98); } }
@keyframes av-hop {
  0%   { transform: scale(1, 1) translateY(0); }
  18%  { transform: scale(1.14, .84) translateY(0); }
  46%  { transform: scale(.92, 1.1) translateY(-26px); }
  70%  { transform: scale(1, 1) translateY(-6px); }
  84%  { transform: scale(1.08, .9) translateY(0); }
  100% { transform: scale(1, 1) translateY(0); }
}
@keyframes av-jitter {
  0%, 100% { transform: translateY(0) rotate(-4deg) scale(1.02, .98); }
  50%      { transform: translateY(-14px) rotate(4deg) scale(.96, 1.06); }
}
@keyframes av-lean { 0%, 100% { transform: rotate(7deg) translateX(6px); } 50% { transform: rotate(9deg) translateX(8px) translateY(-3px); } }
@keyframes av-chest { 0%, 100% { transform: scale(1.02, 1.06) translateY(-3px); } 50% { transform: scale(1.04, 1.09) translateY(-6px); } }
@keyframes av-sag { 0%, 100% { transform: scale(1.06, .9) translateY(2px) rotate(-3deg); } 50% { transform: scale(1.08, .88) translateY(3px) rotate(-4deg); } }
@keyframes av-shiver { 0%, 100% { transform: translateX(-1.5px) scale(.98, 1.02); } 50% { transform: translateX(1.5px) scale(.98, 1.02); } }
@keyframes av-blaze {
  0%, 100% { transform: translateY(-5px) scale(1.03, 1.05) rotate(-1deg); }
  50%      { transform: translateY(-8px) scale(1.04, 1.07) rotate(1deg); }
}
@keyframes av-charge {
  0%   { transform: scale(1, 1) translate(0, 0); }
  20%  { transform: scale(.96, 1) translate(-2px, 1px); }
  40%  { transform: scale(.92, .98) translate(3px, 2px); }
  60%  { transform: scale(.9, .95) translate(-4px, 3px); }
  80%  { transform: scale(.88, .9) translate(4px, 4px); }
  100% { transform: scale(.86, .86) translate(0, 6px); }
}
@keyframes av-release { 0% { transform: scale(.86, .86) translate(0, 6px); } 100% { transform: scale(1.03, 1.05) translate(0, -6px); } }

/* the speech line: a paper bubble that pops in from its bottom-left corner.
   It speaks beside itself, never on a section head, where its line is the subtitle. */
.av__say {
  position: absolute;
  /* beside the figure, and never off the screen: --say-dx is the shift the page measured */
  left: calc(100% - var(--size) * .12 + var(--say-dx, 0px));
  bottom: calc(100% - var(--size) * .34);
  z-index: 2;
  width: max-content;
  max-width: min(calc(var(--size) * 1.5), 62vw);
  padding: 10px 14px 11px;
  border-radius: 18px 18px 18px 6px;
  background: var(--paper);
  color: var(--ink);
  font-family: var(--font-display);
  font-size: clamp(12px, calc(var(--size) * .085), 17px);
  font-weight: 800;
  line-height: 1.15;
  letter-spacing: -.01em;
  text-wrap: balance;
  box-shadow: 0 2px 4px rgba(var(--shadow-rgb), .08), 0 10px 22px -8px rgba(var(--shadow-rgb), .35);
  transform-origin: 0% 100%;
  animation: av-say-in .3s var(--ease-pop) both;
  pointer-events: none;
}

/* when the bubble ends up on the figure's other side, its tail turns to face it */
.av--say-left .av__say {
  border-radius: 18px 18px 6px 18px;
  transform-origin: 100% 100%;
}

.av__say.is-super { background: var(--ink-fixed); color: var(--yellow); }
.av.is-still .av__say { animation: none; }

@keyframes av-say-in { from { transform: scale(.3); opacity: 0; } to { transform: scale(1); opacity: 1; } }

/* ---------- the travelling stage ----------
   One fixed layer holds the one figure that rides the scroll; the docks are empty seats in
   the flow, and the figure lands in whichever is nearest the reading line. */

.co-stage {
  position: fixed;
  inset: 0;
  z-index: 30;
  pointer-events: none;
  contain: layout style;
}

.co-stage .av {
  position: absolute;
  top: 0;
  left: 0;
  /* the body's centre inside the 200 box: the figure turns about itself, never about a corner */
  transform-origin: 50% 60%;
  will-change: transform;
}

/* a dock is an empty seat: it reserves the figure's box in the layout and is never painted */
.co-dock { display: block; flex: none; }
