/* Pixel Kirill (js/buddy.js, art in js/buddy-art.js): a 26 × 32 sprite scaled up with hard pixel
   edges. He shows in one of two spots, peeking over the prescription or standing above the
   question, and moves with eased transforms only. */

.rx__stage,
.buddy-slot,
.receipt-stage { --px: 3; }

@media (min-width: 734px) {
  .rx__stage,
  .buddy-slot,
  .receipt-stage { --px: 4; }
}

.buddy {
  position: absolute;
  width: calc(26px * var(--px));
  height: calc(32px * var(--px));
  pointer-events: none;
  visibility: hidden;
  transition: visibility 0s linear 300ms;   /* stays visible while he ducks away */
}

.buddy.is-on {
  visibility: visible;
  transition-delay: 0s;
}

.buddy__body,
.buddy__sprite {
  position: absolute;
  inset: 0;
}

/* Away: quick and accelerating. Back: decelerating with a hair of overshoot, like a head popping up. */
.buddy__body { transition: transform 280ms cubic-bezier(0.5, 0, 0.75, 0); }

.buddy.is-on .buddy__body {
  transform: none;
  transition: transform 680ms cubic-bezier(0.2, 1.12, 0.36, 1);
}

.buddy__sprite {
  background: no-repeat center / 100% 100%;
  image-rendering: pixelated;
}

/* He breathes while he waits and shudders while he sobs. */
.buddy.is-on .buddy__sprite { animation: buddy-breathe 2.8s ease-in-out infinite; }

.buddy.is-on:is([data-mode="cry"], [data-mode="sitcry"]) .buddy__sprite {
  animation: buddy-sob 0.95s ease-in-out infinite;
}

@keyframes buddy-breathe {
  0%, 100% { translate: 0 0; }
  50% { translate: 0 calc(var(--breath, 0.6) * var(--px) * -1px); }
}

@keyframes buddy-sob {
  0%, 100% { translate: 0 0; }
  35% { translate: 0 calc(var(--px) * 0.8px); }
  65% { translate: 0 calc(var(--px) * -0.3px); }
}

/* On the prescription: behind the card, only head and hands come over its top edge. */
.buddy--card {
  --breath: 0.35;
  z-index: 0;
  top: calc(var(--px) * -16px);
  right: 9%;
}

.buddy--card .buddy__body { transform: translateY(calc(var(--px) * 17px)); }

/* Above the question: he rises out of an invisible floor. */
.buddy-slot {
  position: relative;
  width: calc(26px * var(--px));
  height: calc(32px * var(--px) + 8px);
  margin: 0 auto 4px;
  clip-path: inset(-100vh -100vw 0 -100vw);
}

.buddy--ask {
  left: 0;
  bottom: 8px;
}

.buddy--ask .buddy__body { transform: translateY(calc(100% + 12px)); }

/* His shadow on the floor; a puddle once he sits down and cries. */
.buddy--ask::after {
  content: "";
  position: absolute;
  left: 20%;
  right: 20%;
  bottom: -6px;
  height: 6px;
  border-radius: 50%;
  background: rgba(29, 29, 31, 0.16);
  opacity: 0;
  transition: opacity 300ms ease, left 500ms var(--ease-out), right 500ms var(--ease-out), background-color 500ms ease;
}

.buddy--ask.is-on::after { opacity: 1; }

.buddy--ask[data-mode="sitcry"]::after {
  left: -8%;
  right: -8%;
  background: rgba(124, 198, 255, 0.5);
}

/* Next to the receipt at the end, on the dark finale: a light rim keeps his dark hair and jacket
   apart from the night. */
.buddy--finale {
  left: calc(50% - 180px - 26px * var(--px) - 8px);
  bottom: 0;
}

.buddy--finale .buddy__body { transform: translateY(16px); }

.buddy--finale .buddy__sprite {
  filter:
    drop-shadow(calc(var(--px) * 1px) 0 0 rgba(245, 245, 247, 0.85))
    drop-shadow(calc(var(--px) * -1px) 0 0 rgba(245, 245, 247, 0.85))
    drop-shadow(0 calc(var(--px) * 1px) 0 rgba(245, 245, 247, 0.85))
    drop-shadow(0 calc(var(--px) * -1px) 0 rgba(245, 245, 247, 0.85));
}

/* No room beside the receipt on a phone: he stands in front of its torn-off corner. */
@media (max-width: 560px) {
  .buddy--finale {
    z-index: 2;
    left: 0;
    bottom: -2px;
  }
}

/* Comic speech bubble beside his head: left of him on the prescription, right of him at the question. */
.buddy-say {
  position: absolute;
  z-index: 2;
  bottom: 64%;
  max-width: 46vw;
  padding: 5px 10px 6px;
  border: 2px solid #1d1d1f;
  border-radius: 10px;
  background: #ffffff;
  color: #1d1d1f;
  font: 700 14px/1.15 var(--font-sans);
  letter-spacing: 0;
  white-space: nowrap;
  opacity: 0;
  scale: 0.8;
  transition: opacity 160ms ease, scale 160ms ease;
}

.buddy-say.is-on {
  opacity: 1;
  scale: 1;
  transition: opacity 200ms ease, scale 380ms cubic-bezier(0.2, 1.3, 0.4, 1);
}

.buddy-say::after {
  content: "";
  position: absolute;
  bottom: -7px;
  width: 10px;
  height: 10px;
  background: #ffffff;
  border-bottom: 2px solid #1d1d1f;
  transform: rotate(45deg) skew(8deg, 8deg);
}

.buddy--card .buddy-say {
  right: 80%;
  transform-origin: 100% 100%;
}

.buddy--card .buddy-say::after {
  right: 10px;
  border-right: 2px solid #1d1d1f;
}

.buddy:is(.buddy--ask, .buddy--finale) .buddy-say {
  left: 78%;
  transform-origin: 0 100%;
}

.buddy:is(.buddy--ask, .buddy--finale) .buddy-say::after {
  left: 10px;
  border-left: 2px solid #1d1d1f;
  transform: rotate(-45deg) skew(-8deg, -8deg);
}

/* Tears: a drop now and then when he is sad, both eyes running when he cries. */
.buddy:is([data-mode="sad"], [data-mode="cry"], [data-mode="sitcry"]) .buddy__body::before {
  content: "";
  position: absolute;
  left: calc(var(--px) * 8px);
  top: calc(var(--px) * var(--eyes, 12) * 1px);
  width: calc(var(--px) * 1px);
  height: calc(var(--px) * 2px);
  background: #7cc6ff;
  opacity: 0;
  animation: buddy-tear 1.5s cubic-bezier(0.55, 0, 1, 0.45) infinite;
}

.buddy:is([data-mode="cry"], [data-mode="sitcry"]) .buddy__body::before {
  box-shadow: calc(var(--px) * 9px) calc(var(--px) * 1px) 0 #7cc6ff;
  animation-duration: 0.8s;
}

.buddy--ask[data-mode="sitcry"] { --eyes: 17; }

@keyframes buddy-tear {
  0% { translate: 0 0; opacity: 0; }
  12% { opacity: 1; }
  100% { translate: 0 calc(var(--px) * 9px); opacity: 0; }
}

/* Cured: pixel sparkles twinkle around him. */
.buddy[data-mode="happy"] .buddy__body::before,
.buddy[data-mode="happy"] .buddy__body::after {
  content: "";
  position: absolute;
  width: calc(var(--px) * 1px);
  height: calc(var(--px) * 1px);
  background: #ffd166;
  opacity: 0;
  animation: buddy-twinkle 1.7s ease-in-out infinite;
}

.buddy[data-mode="happy"] .buddy__body::before {
  left: calc(var(--px) * 1px);
  top: calc(var(--px) * 3px);
  box-shadow: calc(var(--px) * 23px) calc(var(--px) * 5px) 0 #ff9eb5;
}

.buddy[data-mode="happy"] .buddy__body::after {
  left: calc(var(--px) * 24px);
  top: calc(var(--px) * 1px);
  box-shadow: calc(var(--px) * -22px) calc(var(--px) * 12px) 0 #ffd166;
  animation-delay: 0.85s;
}

@keyframes buddy-twinkle {
  0%, 100% { opacity: 0; }
  50% { opacity: 1; }
}

/* A cough cloud drifting away from his mouth. */
.buddy-puff {
  position: absolute;
  left: calc(var(--px) * 14px);
  top: calc(var(--px) * 10px);
  width: calc(var(--px) * 7px);
  height: calc(var(--px) * 6px);
  background: no-repeat center / 100% 100%;
  image-rendering: pixelated;
  animation: buddy-puff 900ms cubic-bezier(0.16, 1, 0.3, 1) forwards;
}

.buddy--card .buddy-puff { --drift: 1; }

.buddy--ask .buddy-puff {
  --drift: -1;
  left: calc(var(--px) * 5px);
}

@keyframes buddy-puff {
  from { opacity: 0; transform: translate(0, 0); }
  15% { opacity: 1; }
  to { opacity: 0; transform: translate(calc(var(--drift, 1) * var(--px) * 7px), calc(var(--px) * -5px)); }
}

/* The scarf flying off once he is cured. */
.buddy-scarf {
  position: absolute;
  inset: 0;
  background: no-repeat center / 100% 100%;
  image-rendering: pixelated;
  transform-origin: 40% 47%;
}

.buddy-scarf--sit { transform-origin: 40% 63%; }

@media (prefers-reduced-motion: reduce) {
  .buddy__body,
  .buddy.is-on .buddy__body,
  .buddy-say,
  .buddy-say.is-on { transition: none; }

  .buddy.is-on .buddy__sprite,
  .buddy .buddy__body::before,
  .buddy .buddy__body::after,
  .buddy-puff { animation: none; }

  .buddy .buddy__body::before,
  .buddy .buddy__body::after { opacity: 1; }
}
