/* Çiço, the hero (BRIEF-RUNG-4.md §1, step 4): his materials, his states and his moves. Moved
   here unchanged from F4's f4.css with his code, now prototypes/shell/hero.js, since Kasa Başı
   puts him at the till too (design/kasa/kasa-basi-brief.md, B2). The shell links it, so any game
   that draws him has it.

   Every colour is a token by role (ui/tokens.css), and every motion answers something: a tap (the
   jump, the bonk), the lava (the flood), the top (the cheer) or a printed receipt (the tick and the
   cross, Kasa Başı's sign). Waiting has no animation at all: the hero never moves on its own. Every class is the hero's own, .hero and .hero-*, so nothing
   here reaches a game or the shell. */

/* ---- the hero's materials ------------------------------------------------ */

.hero {
  display: block;
  overflow: visible;
}

.hero path,
.hero ellipse,
.hero circle,
.hero rect,
.hero polygon {
  stroke: var(--hero-line);
  stroke-width: 3.5;
  stroke-linejoin: round;
  stroke-linecap: round;
}

/* Stroke weights: the silhouette heaviest, details lighter, shading none at all. */
.hero .detail { stroke-width: 3; }
.hero .thin { stroke-width: 2; }
.hero .flat { stroke: none; }

.hero .hide { fill: var(--hero-hide); }
.hero .hide-shade { fill: var(--hero-hide-shade); }
.hero .claw { fill: var(--hero-line); stroke-width: 1.5; }
.hero .strap { fill: var(--hero-strap); }
.hero .buckle { fill: var(--hero-buckle); }
.hero .pack { fill: var(--hero-pack); }
.hero .pack-shade { fill: var(--hero-pack-shade); }
.hero .pack-trim { fill: var(--hero-pack-trim); }
.hero .pack-trim-shade { fill: var(--hero-pack-trim-shade); }
.hero .nozzle { fill: var(--hero-line); stroke-width: 2; }
.hero .rivet { fill: var(--hero-buckle); stroke: none; }
.hero .tooth { fill: var(--hero-tooth); stroke-width: 2; }
.hero .tongue { fill: var(--hero-tongue); }
.hero .mouth-inside { fill: var(--hero-mouth); }
.hero .nostril { fill: var(--hero-line); stroke: none; }
.hero .frame { fill: var(--hero-frame); }
.hero .frame-shade { fill: var(--hero-frame-shade); }
.hero .lens { fill: var(--hero-lens); }
.hero .iris { fill: var(--hero-iris); stroke: none; }
.hero .pupil { fill: var(--hero-line); stroke: none; }
.hero .gleam { fill: var(--hero-shine); stroke: none; }
.hero .glare { fill: var(--hero-shine); fill-opacity: .45; stroke: none; }
.hero .rock { fill: var(--hero-rock); }
.hero .rock-shade { fill: var(--hero-rock-shade); }
.hero .flame { fill: var(--hero-flame); stroke-width: 3; }
.hero .flame-core { fill: var(--hero-flame-core); stroke-width: 2; }
.hero .impact { fill: var(--hero-impact); stroke-width: 2; }
.hero .smoke { fill: var(--hero-smoke); stroke-width: 2; }
.hero .trophy-frame { fill: var(--surface-paper); stroke-width: 3; }
/* The market outfit (hero.js): a cap and a polo in the market's colour, a pale collar and badge. */
.hero .cap { fill: var(--hero-cap); }
.hero .cap-shade { fill: var(--hero-cap-shade); }
.hero .shirt { fill: var(--hero-shirt); }
.hero .shirt-shade { fill: var(--hero-shirt-shade); }
.hero .collar,
.hero .badge { fill: var(--hero-collar); }
/* Without the goggle glass behind it, the eye needs its own rim to read on the hide. */
.hero[data-outfit="market"] .iris { stroke: var(--hero-line); stroke-width: 2.5; }
/* The sign: a card on a stick, and its mark drawn thick enough to read across the counter. */
.hero .stick { fill: var(--hero-stick); }
.hero .placard { fill: var(--hero-placard); }
.hero .placard-shade { fill: var(--hero-placard-shade); }
.hero .mark { fill: none; stroke-width: 10; }
.hero .mark-tick { stroke: var(--hero-sign-yes); }
.hero .mark-cross { stroke: var(--hero-sign-no); }
/* A cut-out is held without the paper it was cut from (hero.js, setTrophy). */
.hero .trophy-cut-out .trophy-frame { display: none; }

/* Strokes with no fill: the knee, and the eyes a state draws as lines. */
.hero .line { fill: none; stroke-width: 3; }
.hero .shine { fill: none; stroke: var(--hero-shine); stroke-width: 2; stroke-opacity: .55; }

/* ---- what each state shows ------------------------------------------------ */

.hero .eye { display: none; }
.hero .eye-open { display: inline; }

/* The sign is not drawn at all until a tick or a cross holds it up, so it never widens the rig. */
.hero-sign,
.hero .mark { display: none; }
.hero[data-state="tick"] .hero-sign,
.hero[data-state="cross"] .hero-sign,
.hero[data-state="tick"] .mark-tick,
.hero[data-state="cross"] .mark-cross { display: inline; }

.hero-flames,
.hero-fx .fx,
.hero-rock,
.hero-trophy { opacity: 0; }

.hero[data-state="bonk"] .eye-open,
.hero[data-state="flood"] .eye-open,
.hero[data-state="cheer"] .eye-open,
.hero[data-state="tick"] .eye-open { display: none; }

.hero[data-state="bonk"] .eye-dizzy,
.hero[data-state="flood"] .eye-x,
.hero[data-state="cheer"] .eye-happy,
.hero[data-state="tick"] .eye-happy { display: inline; }

.hero .x-eye { stroke-width: 4; }

/* ---- where each part turns ------------------------------------------------- */

/* Pivots in the drawing's own units: the feet for the whole body, the nozzles for the fire, the
   hinge for the jaw, the shoulder for the arm. */
.hero-rig,
.hero-rock,
.hero-flames,
.hero-jaw,
.hero-arm-near,
.hero-trophy,
.hero-sign,
.hero-fx .fx {
  transform-box: view-box;
}
.hero-rig,
.hero-rock { transform-origin: 150px 196px; }
.hero-flames { transform-origin: 107px 102px; }
.hero-jaw { transform-origin: 214px 94px; }
.hero-arm-near { transform-origin: 198px 118px; }
.hero-trophy { transform-origin: 235px 143px; }

/* Shown mirrored (hero.js, mirrored), he turns what he holds back the right way round, each about
   its own centre: the sign's mark on its card, and a drawing in his hands. The cross is the same
   either way; the tick and a drawing are not. */
.hero[data-mirrored="true"] .mark,
.hero[data-mirrored="true"] .trophy-picture {
  transform: scaleX(-1);
  transform-box: view-box;
}
.hero[data-mirrored="true"] .mark { transform-origin: 246px -22px; }
.hero[data-mirrored="true"] .trophy-picture { transform-origin: 235px 143px; }
/* The sign turns up from the far hand that holds its stick. */
.hero-sign { transform-origin: 209px 118px; }
.hero-fx .impact { transform-origin: 254px 33px; }
/* Each puff grows from its own centre. */
.hero-fx .smoke { transform-box: fill-box; transform-origin: center; }

/* ---- the moves --------------------------------------------------------------
   The rig's own animation is the one the game waits for (hero.js), so each state gives the rig
   one, and every part's motion fits inside it. */

/* A right pick: crouch, fire, up, land. The game moves him to the next junction meanwhile. */
.hero[data-state="jump"] .hero-rig { animation: hero-jump .62s ease-out both; }
.hero[data-state="jump"] .hero-flames { animation: hero-fire .62s linear both; }

/* A wrong pick: the same jump into a dead end, a knock, a dizzy slide back. */
.hero[data-state="bonk"] .hero-rig { animation: hero-bonk .95s ease-out both; }
.hero[data-state="bonk"] .hero-flames { animation: hero-fire-short .95s linear both; }
.hero[data-state="bonk"] .hero-fx .impact { animation: hero-impact .95s ease-out both; }

/* The lava caught up: he bobs up on a rock with X eyes in a cloud of smoke, so a child sees what
   happened, and is himself again when the climb restarts. The puffs finish inside the bob. */
.hero[data-state="flood"] .hero-rig,
.hero[data-state="flood"] .hero-rock { animation: hero-bob 1.5s ease-out both; }
.hero[data-state="flood"] .hero-rock { opacity: 1; }
.hero[data-state="flood"] .hero-fx .smoke { animation: hero-smoke 1.2s ease-out both; }
.hero[data-state="flood"] .hero-fx .smoke-2 { animation-delay: .08s; }
.hero[data-state="flood"] .hero-fx .smoke-3 { animation-delay: .16s; }
.hero[data-state="flood"] .hero-fx .smoke-4 { animation-delay: .22s; }
.hero[data-state="flood"] .hero-fx .smoke-5 { animation-delay: .25s; }

/* Out at the top: a hop on the jetpack, and the drawing held up in his tiny hands. It holds. */
.hero[data-state="cheer"] .hero-rig { animation: hero-cheer 1.1s ease-out both; }
.hero[data-state="cheer"] .hero-flames { animation: hero-fire-short 1.1s linear both; }
.hero[data-state="cheer"] .hero-jaw { animation: hero-jaw-open 1.1s ease-out both; }
.hero[data-state="cheer"] .hero-arm-near { animation: hero-arm-up 1.1s ease-out both; }
.hero[data-state="cheer"] .hero-trophy { animation: hero-trophy 1.1s ease-out both; }

/* A receipt that matches: the cheer's hop, happy eyes and an open jaw, and the tick held up. It
   holds until the game moves on. */
.hero[data-state="tick"] .hero-rig { animation: hero-cheer 1.1s ease-out both; }
.hero[data-state="tick"] .hero-jaw { animation: hero-jaw-open 1.1s ease-out both; }
.hero[data-state="tick"] .hero-sign { animation: hero-sign-up 1.1s ease-out both; }

/* A receipt that does not: no hop, a slow sway from side to side, and the cross held up. It is a
   shrug, not a scolding, and it holds until the child has put the line right. */
.hero[data-state="cross"] .hero-rig { animation: hero-shake 1.1s ease-in-out both; }
.hero[data-state="cross"] .hero-sign { animation: hero-sign-up 1.1s ease-out both; }

@keyframes hero-jump {
  0% { transform: translateY(0) scale(1, 1); }
  18% { transform: translateY(5px) scale(1.07, .9); }
  48% { transform: translateY(-52px) scale(.94, 1.07); }
  78% { transform: translateY(-44px) scale(1, 1); }
  92% { transform: translateY(2px) scale(1.05, .95); }
  100% { transform: translateY(0) scale(1, 1); }
}

/* The fire flickers by growing and shrinking from the nozzles, along its own slant. */
@keyframes hero-fire {
  0%, 14% { opacity: 0; transform: scale(.3); }
  22% { opacity: 1; transform: scale(1.1); }
  34% { transform: scale(.85); }
  46% { transform: scale(1.15); }
  58% { transform: scale(.9); }
  70% { opacity: 1; transform: scale(1); }
  84%, 100% { opacity: 0; transform: scale(.3); }
}

@keyframes hero-fire-short {
  0%, 8% { opacity: 0; transform: scale(.3); }
  14% { opacity: 1; transform: scale(1.1); }
  24% { transform: scale(.85); }
  32% { opacity: 1; transform: scale(1.1); }
  42%, 100% { opacity: 0; transform: scale(.3); }
}

@keyframes hero-bonk {
  0% { transform: translateY(0) rotate(0); }
  14% { transform: translateY(5px) scale(1.07, .9); }
  38% { transform: translateY(-36px) scale(.95, 1.06); }
  44% { transform: translateY(-32px) scale(1.08, .9) rotate(-3deg); }
  62% { transform: translateY(-12px) rotate(4deg); }
  80% { transform: translateY(0) rotate(-2deg); }
  100% { transform: translateY(0) rotate(0); }
}

@keyframes hero-impact {
  0%, 40% { opacity: 0; transform: scale(.4); }
  47% { opacity: 1; transform: scale(1.25); }
  70% { opacity: 1; transform: scale(1); }
  86%, 100% { opacity: 0; transform: scale(1); }
}

@keyframes hero-bob {
  0% { transform: translateY(26px); }
  26% { transform: translateY(-9px); }
  46% { transform: translateY(2px); }
  63% { transform: translateY(-5px); }
  81% { transform: translateY(1px); }
  100% { transform: translateY(0); }
}

@keyframes hero-smoke {
  0% { opacity: 0; transform: translateY(6px) scale(.4); }
  18% { opacity: .95; transform: translateY(0) scale(1); }
  70% { opacity: .9; }
  100% { opacity: 0; transform: translateY(-46px) scale(1.9); }
}

@keyframes hero-cheer {
  0% { transform: translateY(0) scale(1, 1); }
  14% { transform: translateY(5px) scale(1.06, .92); }
  40% { transform: translateY(-30px) scale(.96, 1.05); }
  68% { transform: translateY(0) scale(1.04, .96); }
  82% { transform: translateY(-4px) scale(1, 1); }
  100% { transform: translateY(0) scale(1, 1); }
}

@keyframes hero-jaw-open {
  0%, 30% { transform: rotate(0); }
  50%, 100% { transform: rotate(14deg); }
}

@keyframes hero-arm-up {
  0%, 30% { transform: rotate(0); }
  50%, 100% { transform: rotate(-16deg); }
}

@keyframes hero-sign-up {
  0%, 18% { opacity: 0; transform: translateY(44px) rotate(-14deg) scale(.6); }
  44% { opacity: 1; transform: translateY(-6px) rotate(3deg) scale(1.05); }
  60%, 100% { opacity: 1; transform: translateY(0) rotate(0) scale(1); }
}

@keyframes hero-shake {
  0%, 30% { transform: rotate(0); }
  42% { transform: rotate(-2.5deg); }
  58% { transform: rotate(2.5deg); }
  72% { transform: rotate(-1.5deg); }
  86%, 100% { transform: rotate(0); }
}

@keyframes hero-trophy {
  0%, 36% { opacity: 0; transform: scale(.5); }
  52% { opacity: 1; transform: scale(1.08); }
  64%, 100% { opacity: 1; transform: scale(1); }
}

/* Reduced motion keeps every pose and drops the travel: each move lands at once on its end, and
   hero.js holds the bonk and the flood long enough to read. What says what happened stays up,
   still: the bonk's star, and the flood's smoke. */
@media (prefers-reduced-motion: reduce) {
  .hero-rig,
  .hero-rig *,
  .hero-rock {
    animation-duration: .01ms !important;
    animation-delay: 0s !important;
  }

  .hero[data-state="bonk"] .hero-fx .impact,
  .hero[data-state="flood"] .hero-fx .smoke {
    animation: none !important;
    opacity: .95;
  }
}
