/**
 * Ponoki Companion Stage — shared mascot rig for game intro/end screens.
 * See docs/specs/2026-07-19-ponoki-companion-screens.md.
 *
 * The host page sets --pk-hue (the game's feeling hue) on the .pk-stage
 * element (or an ancestor); everything here derives from it. All motion is
 * CSS transforms only; prefers-reduced-motion degrades to a static mascot
 * with the chosen expression.
 */

.pk-stage {
  --pk-hue: 185; /* fallback: global teal accent hue */
  /* Apricot palette (matches index.html companion defaults) */
  --pk-accent: hsl(248, 38%, 72%);
  --pk-band: hsl(250, 44%, 81%);
  --pk-eye: hsl(24, 34%, 19%);
  --pk-body: hsl(28, 66%, 80%);
  --pk-cheek: hsl(8, 66%, 72%);
  width: 100px;
  height: 100px;
  position: relative;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  flex: 0 0 auto;
}

/* ── Mount-point box reservation ──
   A mount point (#pk-intro-stage, #pk-mic-stage, #pk-calib-stage,
   #pk-end-stage, and whatever a future game names its own) is an empty <div>
   until companion-stage.js injects the rig and adds .pk-stage — and .pk-stage
   is what carries width/height. Without the rules below the div is 0px tall at
   first paint, so the mascot drops into space nothing reserved and shoves
   everything under it down (measured: 66px on pop-spiral, 0.038 CLS).

   Matched by id pattern rather than by an explicit list, so game twelve gets
   the reservation without anyone remembering a step. This file is the single
   source of truth for the mascot box; games size only the margins around it,
   otherwise a local width traded the shift for a resize at mount. */
[id^="pk-"][id$="-stage"] { width: 88px; height: 88px; }
#pk-end-stage { width: 80px; height: 80px; }

/* Mood halo in the game's feeling hue */
.pk-stage::before {
  content: '';
  position: absolute;
  inset: -14%;
  border-radius: 50%;
  background: radial-gradient(circle, hsla(var(--pk-hue), 85%, 62%, 0.42) 0%, hsla(var(--pk-hue), 85%, 62%, 0) 66%);
  animation: pkHalo 3600ms ease-in-out infinite;
}
@keyframes pkHalo {
  0%, 100% { transform: scale(0.94); opacity: 0.75; }
  50% { transform: scale(1.06); opacity: 1; }
}

.pk-stage .pk-inner {
  width: 100%;
  height: 100%;
  transform-origin: 50% 92%;
  animation: pkBreathe 3400ms ease-in-out infinite;
}
.pk-stage svg { width: 100%; height: 100%; overflow: visible; display: block; }
@keyframes pkBreathe {
  0%, 100% { transform: translateY(0) scale(1); }
  50% { transform: translateY(-2px) scale(1.015); }
}

/* ── Face expressions (exactly one exp-* class on .pk-stage) ── */
.pk-stage .pk-eyes-open, .pk-stage .pk-eyes-happy, .pk-stage .pk-eyes-wink, .pk-stage .pk-eyes-wide,
.pk-stage .pk-m-smile, .pk-stage .pk-m-big, .pk-stage .pk-m-o, .pk-stage .pk-m-content {
  opacity: 0;
  transition: opacity 180ms ease;
}
.pk-stage.exp-default .pk-eyes-open { opacity: 1; }
.pk-stage.exp-default .pk-m-smile { opacity: 1; }
.pk-stage.exp-happy .pk-eyes-happy { opacity: 1; }
.pk-stage.exp-happy .pk-m-big { opacity: 1; }
.pk-stage.exp-wink .pk-eyes-wink { opacity: 1; }
.pk-stage.exp-wink .pk-m-smile { opacity: 1; }
.pk-stage.exp-surprise .pk-eyes-wide { opacity: 1; }
.pk-stage.exp-surprise .pk-m-o { opacity: 1; }
.pk-stage.exp-content .pk-eyes-happy { opacity: 1; }
.pk-stage.exp-content .pk-m-content { opacity: 1; }

/* Blink only while the round open eyes are showing */
.pk-stage .pk-eyes-open { transform-box: fill-box; transform-origin: center; }
.pk-stage.exp-default .pk-eyes-open { animation: pkBlink 4600ms infinite; }
@keyframes pkBlink {
  0%, 42%, 48%, 90%, 96%, 100% { transform: scaleY(1); }
  45%, 93% { transform: scaleY(0.12); }
}

/* ── Independent parts ── */
.pk-stage .pk-hat { transform-box: fill-box; transform-origin: center bottom; }
.pk-stage .pk-hand-l { transform-box: fill-box; transform-origin: right center; }
.pk-stage .pk-hand-r { transform-box: fill-box; transform-origin: left center; }
.pk-stage .pk-foot-l, .pk-stage .pk-foot-r { transform-box: fill-box; transform-origin: top center; }

/* ── Reactions (exactly one react-* class, or none for idle breathe) ── */
.pk-stage.react-hop .pk-inner { animation: pkHop 1700ms ease-in-out infinite; }
@keyframes pkHop {
  0%, 42% { transform: translateY(0) scale(1); }
  52% { transform: translateY(0) scale(1.05, 0.92); }
  70% { transform: translateY(-16px) scale(0.96, 1.06); }
  84% { transform: translateY(0) scale(1.06, 0.92); }
  92%, 100% { transform: translateY(0) scale(1); }
}

.pk-stage.react-sway .pk-inner { animation: pkSway 3600ms ease-in-out infinite; }
@keyframes pkSway {
  0%, 100% { transform: rotate(-4deg) translateY(0); }
  50% { transform: rotate(4deg) translateY(-3px); }
}

.pk-stage.react-wiggle .pk-inner { animation: pkWiggle 1100ms ease-in-out infinite; }
@keyframes pkWiggle {
  0%, 100% { transform: rotate(0); }
  20% { transform: rotate(-9deg); }
  40% { transform: rotate(7deg); }
  60% { transform: rotate(-5deg); }
  80% { transform: rotate(3deg); }
}

.pk-stage.react-wave .pk-hand-r { animation: pkWave 900ms ease-in-out infinite; }
@keyframes pkWave {
  0%, 100% { transform: rotate(-10deg); }
  25%, 75% { transform: rotate(-42deg); }
  50% { transform: rotate(-16deg); }
}

.pk-stage.react-cheer .pk-hand-l { animation: pkCheerL 1050ms ease-in-out infinite; }
.pk-stage.react-cheer .pk-hand-r { animation: pkCheerR 1050ms ease-in-out infinite; }
.pk-stage.react-cheer .pk-inner { animation: pkCheerBounce 1050ms ease-in-out infinite; }
@keyframes pkCheerL {
  0%, 100% { transform: translate(-3px, -15px) rotate(-34deg); }
  50% { transform: translate(-5px, -21px) rotate(-50deg); }
}
@keyframes pkCheerR {
  0%, 100% { transform: translate(3px, -15px) rotate(34deg); }
  50% { transform: translate(5px, -21px) rotate(50deg); }
}
@keyframes pkCheerBounce {
  0%, 100% { transform: translateY(0); }
  50% { transform: translateY(-6px); }
}

/* A real clap: hands now paint in front of the torso (see the SVG order in
   companion-stage.js), so they slide inward and down to meet just below the
   mouth, then part again. */
.pk-stage.react-clap .pk-hand-l { animation: pkClapL 460ms ease-in-out infinite; }
.pk-stage.react-clap .pk-hand-r { animation: pkClapR 460ms ease-in-out infinite; }
@keyframes pkClapL { 0%, 100% { transform: translate(0, 0) rotate(0); } 50% { transform: translate(40px, 24px) rotate(30deg); } }
@keyframes pkClapR { 0%, 100% { transform: translate(0, 0) rotate(0); } 50% { transform: translate(-40px, 24px) rotate(-30deg); } }

@media (prefers-reduced-motion: reduce) {
  .pk-stage::before,
  .pk-stage .pk-inner,
  .pk-stage .pk-eyes-open,
  .pk-stage .pk-hat,
  .pk-stage .pk-hand-l, .pk-stage .pk-hand-r,
  .pk-stage .pk-foot-l, .pk-stage .pk-foot-r { animation: none !important; }
}

/* ── Short-viewport compaction ──
   Intro/outro screens must reach their buttons without scrolling on small
   phones. Games already handle notches via env(safe-area-inset-*) paddings;
   this only shrinks the decorative layer (mascot, say-line, motifs) when
   vertical space is tight. Loaded after each game's own stylesheet, so these
   equal-specificity rules win. */
@media (max-height: 860px) {
  .pk-greet .pk-stage, [id^="pk-"][id$="-stage"] { width: 66px; height: 66px; }
  #pk-end-stage { width: 60px; height: 60px; }
  .pk-greet { gap: 0.5rem; }
  .pk-say { font-size: 0.92rem; max-width: 28ch; }
  .calib-mic-ring { width: 76px; height: 76px; }
  .calib-mic-ico { font-size: 22px; margin-bottom: 26px; }
  .intro-motif { height: 34px; }
}
@media (max-height: 700px) {
  .pk-greet .pk-stage, [id^="pk-"][id$="-stage"] { width: 54px; height: 54px; }
  #pk-end-stage { width: 48px; height: 48px; }
  .intro-motif { display: none; }
}

/* End-overlay cards join the compaction: tighter padding keeps stats and
   actions on screen without scrolling on notched phones. */
@media (max-height: 860px) {
  .overlay-card { padding: var(--space-6) var(--space-5); }
  .sprint-overlay-card { padding: var(--space-6) var(--space-5); }
  .overlay-score-display { margin-bottom: var(--space-4); }
  .overlay-msg { margin-bottom: var(--space-4); }
}
