* { box-sizing: border-box; }
:root { --blue: #2d6cdf; --card: min(21vh, 15vw); }
html, body { margin: 0; height: 100%; }
body { font-family: 'Baloo Bhaijaan 2', system-ui, sans-serif; overflow: hidden; background: #7cc8ff; user-select: none; -webkit-user-select: none; -webkit-touch-callout: none; }
button { font: inherit; color: inherit; cursor: pointer; -webkit-tap-highlight-color: transparent; }

.stage { position: fixed; inset: 0; overflow: hidden; touch-action: none; background: linear-gradient(#7cc8ff, #c4ecff 62%, #9be15d 62%, #6cc644); }
.stage.splash, .stage.home { background: url(img/bg-home.webp) center / cover, #7cc8ff; }
.stage.game { background: url(img/bg-game.webp) center / cover, #7cc8ff; }

/* ---- Mishmosh: a cutout rig. Parts sit in rig pixels (700 x 940); --s scales the whole kitten. ---- */
.mishmosh { position: absolute; z-index: 3; left: 0; bottom: 3vh; width: calc(700px * var(--s)); height: calc(940px * var(--s)); }
.mm-rig { position: absolute; left: 0; top: 0; width: 700px; height: 940px; transform-origin: 0 0; scale: var(--s); }
.mm-body { position: absolute; inset: 0; transform-origin: 350px 935px; }
.mm-rig img, .mm-tail, .mm-head, .mm-mouth { position: absolute; display: block; }

/* Joints: transform-origin is where each part attaches. Arms and legs hide their cut ends behind the torso. */
.mm-tail     { left: -80px; top: 380px; width: 336px; height: 429px; transform-origin: 321px 325px; }
.mm-tail-img { left: 0; top: 0; scale: -1 1; }
.mm-leg-l    { left: 141px; top: 647px; transform-origin: 140px 28px; }
.mm-leg-r    { left: 344px; top: 647px; transform-origin: 75px 28px; }
.mm-arm-l    { left: 46px;  top: 480px; transform-origin: 165px 40px; }
.mm-arm-r    { left: 454px; top: 480px; transform-origin: 35px 40px; }
.mm-torso    { left: 151px; top: 405px; transform-origin: 199px 381px; }
/* head.webp is art/head-noeyes.png scaled to 534px wide: the parts-sheet head had closed eyes painted on too high. */
.mm-head     { left: 83px;  top: 0; width: 534px; height: 449px; transform-origin: 267px 430px; }
.mm-head-img { left: 0; top: 0; }
/* Eyes sit low and big, next to the nose, like the original drawing. Closed/happy eyes are one arc: ∪ to blink, ∩ when happy. */
.mm-eye-l    { left: 132px; top: 208px; width: 124px; }
.mm-eye-r    { left: 332px; top: 208px; width: 124px; }
.mm-eye-closed-l, .mm-eye-closed-r { top: 248px; width: 124px; visibility: hidden; scale: 1 -1; }
.mm-eye-closed-l { left: 132px; }
.mm-eye-closed-r { left: 332px; }
.mishmosh[data-eyes=happy] :is(.mm-eye-closed-l, .mm-eye-closed-r) { scale: 1; top: 240px; }
.mm-mouth    { left: 294px; top: 322px; } /* on the nose: every mouth image includes the nose */
.mm-mouth img   { visibility: hidden; }
.mm-mouth-smile { left: -73px; top: -9px;  width: 149px; }
.mm-mouth-oh    { left: -29px; top: -14px; width: 54px; }
.mm-mouth-ah    { left: -71px; top: -13px; width: 143px; }
.mm-mouth-laugh { left: -76px; top: -14px; width: 159px; }
.mishmosh[data-mouth=smile] .mm-mouth-smile, .mishmosh[data-mouth=oh] .mm-mouth-oh,
.mishmosh[data-mouth=ah] .mm-mouth-ah, .mishmosh[data-mouth=laugh] .mm-mouth-laugh { visibility: visible; }
.mishmosh:is([data-eyes=closed], [data-eyes=happy]) :is(.mm-eye-l, .mm-eye-r) { visibility: hidden; }
.mishmosh:is([data-eyes=closed], [data-eyes=happy]) :is(.mm-eye-closed-l, .mm-eye-closed-r) { visibility: visible; }
.mishmosh[data-facing=left] .mm-body { transform: scaleX(-1); }
.mm-arm-r, .mm-leg-r { --dir: -1; } /* mirror the right side's rotations */

/* Idle: breathing, a slow head sway, a lazy tail. */
.idle .mm-torso { animation: mm-breathe 3.2s ease-in-out infinite; }
.idle .mm-head  { animation: mm-head-idle 3.2s ease-in-out infinite; }
.idle :is(.mm-arm-l, .mm-arm-r) { animation: mm-arm-idle 3.2s ease-in-out infinite; }
.idle .mm-tail  { animation: mm-tail 2.4s ease-in-out infinite; }
@keyframes mm-breathe   { 50% { scale: 1.02 1.03; } }
@keyframes mm-head-idle { 0%, 100% { rotate: -2deg; } 50% { rotate: 2deg; translate: 0 -10px; } }
@keyframes mm-arm-idle  { 50% { rotate: calc(6deg * var(--dir, 1)); translate: 0 -8px; } }
@keyframes mm-tail      { 0%, 100% { rotate: -6deg; } 50% { rotate: 8deg; } }

/* Walk: a bouncy strut. One stride = .6s; the body bobs twice per stride. */
.walk .mm-body { animation: mm-bob .3s ease-in-out infinite alternate, mm-waddle .6s ease-in-out infinite; }
.walk :is(.mm-leg-l, .mm-leg-r) { animation: mm-step .6s ease-in-out infinite; }
.walk :is(.mm-arm-l, .mm-arm-r) { animation: mm-swing .6s ease-in-out infinite; }
.walk :is(.mm-leg-r, .mm-arm-r) { animation-delay: -.3s; }
.walk .mm-head { animation: mm-nod .6s ease-in-out infinite; }
.walk .mm-tail { animation: mm-tail .6s ease-in-out infinite; }
@keyframes mm-bob    { to { translate: 0 -22px; } }
@keyframes mm-waddle { 0%, 100% { rotate: -3deg; } 50% { rotate: 3deg; } }
/* High steps, small swing: the legs face the camera, so a big swing crosses the feet. */
@keyframes mm-step   { 0%, 100% { rotate: 8deg; translate: 0 0; } 25% { rotate: 0deg; translate: 0 -36px; } 50% { rotate: -8deg; translate: 0 0; } }
@keyframes mm-swing  { 0%, 100% { rotate: -20deg; } 50% { rotate: 20deg; } }
@keyframes mm-nod    { 0%, 100% { rotate: 4deg; } 50% { rotate: -4deg; } }

/* Dance 1: hip wiggle with waving arms. */
.dance1 .mm-body { animation: mm-wiggle .8s ease-in-out infinite; }
.dance1 .mm-head { animation: mm-nod .4s ease-in-out infinite; }
.dance1 :is(.mm-arm-l, .mm-arm-r) { animation: mm-wave .4s ease-in-out infinite alternate; }
.dance1 :is(.mm-leg-l, .mm-leg-r) { animation: mm-tap .8s ease-in-out infinite; }
.dance1 .mm-leg-r { animation-delay: -.4s; }
.dance1 .mm-tail { animation: mm-tail .4s ease-in-out infinite; }
@keyframes mm-wiggle { 0%, 100% { rotate: -8deg; translate: -14px 0; } 50% { rotate: 8deg; translate: 14px 0; } }
@keyframes mm-wave   { from { rotate: calc(40deg * var(--dir, 1)); } to { rotate: calc(80deg * var(--dir, 1)); } }
@keyframes mm-tap    { 0%, 50%, 100% { translate: 0 0; } 25% { translate: 0 -26px; rotate: calc(-10deg * var(--dir, 1)); } }

/* Dance 2: hopping with squash and stretch, arms pumping. */
.dance2 .mm-body { animation: mm-hop .7s ease-in-out infinite; }
.dance2 .mm-head { animation: mm-nod .35s ease-in-out infinite; }
.dance2 :is(.mm-arm-l, .mm-arm-r) { animation: mm-pump .35s ease-in-out infinite alternate; }
.dance2 :is(.mm-leg-l, .mm-leg-r) { animation: mm-kick .7s ease-in-out infinite; }
.dance2 .mm-tail { animation: mm-tail .35s ease-in-out infinite; }
@keyframes mm-hop  { 0%, 100% { translate: 0 0; scale: 1.06 .94; } 15% { scale: 1; } 45% { translate: 0 -90px; scale: .96 1.05; } 75% { translate: 0 0; scale: 1.08 .92; } }
@keyframes mm-pump { from { rotate: calc(10deg * var(--dir, 1)); } to { rotate: calc(85deg * var(--dir, 1)); } }
@keyframes mm-kick { 0%, 100% { rotate: 0deg; } 45% { rotate: calc(18deg * var(--dir, 1)); } }

/* Cheer: two big jumps with both arms up. */
.cheer .mm-body { animation: mm-hop .8s ease-in-out 2; }
.cheer :is(.mm-arm-l, .mm-arm-r) { animation: mm-arms-up .8s ease-out forwards; }
.cheer .mm-tail { animation: mm-tail .3s ease-in-out infinite; }
@keyframes mm-arms-up { 30%, 100% { rotate: calc(85deg * var(--dir, 1)); } }

/* Hop: one quick happy jump (a right answer). Nope: a gentle head shake (a wrong one). */
.hop .mm-body { animation: mm-hop .6s ease-in-out; }
.hop :is(.mm-arm-l, .mm-arm-r) { animation: mm-arms-up .6s ease-out; }
.nope .mm-head { animation: mm-nope .6s ease-in-out; }
@keyframes mm-nope { 20% { rotate: -9deg; } 40% { rotate: 9deg; } 60% { rotate: -6deg; } 80% { rotate: 4deg; } }

/* Talking: a small nod while the line plays. */
.talking .mm-head { animation: mm-nod .5s ease-in-out infinite; }

/* ---- Splash ---- */
.logo { position: absolute; inset: 5vh 0 auto; margin: 0; text-align: center; font-size: 20vmin; line-height: 1.1; color: #ff8a1f;
  -webkit-text-stroke: 1.4vmin #fff; paint-order: stroke fill; text-shadow: 0 1.4vmin 0 #0002; animation: float 3s ease-in-out infinite; }
.loading { position: absolute; left: 30vw; right: 30vw; bottom: 8vh; height: 3.5vmin; border-radius: 9vmin; background: #fff; overflow: hidden; box-shadow: 0 .6vmin 0 #0002; }
.loading i { display: block; width: 0; height: 100%; background: linear-gradient(#ffb74d, #fb8c00); transition: width .2s; }
.play { position: absolute; left: 58vw; top: 52vh; width: 26vmin; height: 26vmin; border-radius: 50%; border: 1.4vmin solid #fff;
  background: radial-gradient(circle at 35% 30%, #8be36a, #3fae2a); box-shadow: 0 1.4vmin 0 #2b7a1d, 0 2vmin 3vmin #0003; animation: pulse 1.2s ease-in-out infinite; }
.play::after { content: ''; position: absolute; inset: 0; margin: auto; width: 0; height: 0; border-left: 8vmin solid #fff; border-block: 5vmin solid transparent; translate: 1.3vmin 0; }
@keyframes float { 50% { translate: 0 -1.5vmin; } }
@keyframes pulse { 50% { scale: 1.08; } }

/* ---- Home: one floating bubble per topic ---- */
.topics { position: absolute; inset: 8vh 3vw 6vh 26vw; display: flex; flex-wrap: wrap; align-content: center; justify-content: center; gap: 4vmin 6vmin; }
.bubble { width: 26vmin; height: 26vmin; padding: 0; border-radius: 50%; border: 1.4vmin solid var(--ring); background: #fff;
  box-shadow: 0 1.4vmin 0 #0002, inset 0 -1.2vmin 0 #0001; display: grid; place-items: center; animation: float 3s ease-in-out calc(var(--i) * -.6s) infinite; }
.bubble:active { scale: .92; }
.bubble img { width: 14.5vmin; height: 14.5vmin; object-fit: contain; } /* small enough that even its corners stay inside the circle */
.bubble .glyph { font-size: 9vmin; }
.bubble .shape { width: 66%; height: 66%; }
.wheel { width: 66%; aspect-ratio: 1; border-radius: 50%; background: conic-gradient(#e53935, #fb8c00, #fdd835, #43a047, #1e88e5, #8e24aa, #e53935); }

/* ---- Game chrome: title ribbon, replay and home buttons ---- */
.banner { position: absolute; top: 2vh; left: 50%; translate: -50%; z-index: 2; padding: .2vmin 9vmin 1.4vmin; white-space: nowrap; font-size: 6.5vmin; font-weight: 800;
  color: #fff; background: linear-gradient(#cf62f5, #9c2bd8); clip-path: polygon(0 0, 100% 0, 95% 50%, 100% 100%, 0 100%, 5% 50%); }
.btn { position: absolute; top: 2.5vh; z-index: 2; width: 13vmin; height: 13vmin; padding: 0; border: .8vmin solid #fff; border-radius: 4vmin;
  background: linear-gradient(#ff8a50, #f4511e); box-shadow: 0 1vmin 0 #b23c12; display: grid; place-items: center; }
.btn svg { width: 62%; fill: #fff; }
.btn:active { translate: 0 .6vmin; box-shadow: 0 .4vmin 0 #b23c12; }
.speaker { left: 2.5vw; }
.close { right: 2.5vw; }

/* ---- Board and cards ---- */
.board { position: absolute; inset: 17vh 2vw 5vh 24vw; z-index: 1; display: grid; place-content: center; grid-template-columns: repeat(var(--cols, 3), auto); gap: 4vmin; }
.board.explore, .board.match { --cols: 4; }
.board.match { row-gap: 14vh; }
.card { position: relative; width: var(--card); height: var(--card); padding: 0; border: .9vmin solid #fff; border-radius: 3.5vmin; background: #fff;
  box-shadow: 0 0 0 .5vmin var(--blue), 0 1.3vmin 0 .5vmin #0003; display: grid; place-items: center; touch-action: none; }
.card:active { scale: .96; }
.card img { width: calc(var(--card) * .8); height: calc(var(--card) * .8); object-fit: contain; pointer-events: none; -webkit-user-drag: none; }
.swatch { display: block; width: 76%; aspect-ratio: 1; border-radius: 24%; box-shadow: inset 0 -1.2vmin 0 #0002; }
.shape { width: 78%; height: 78%; overflow: visible; }
.glyph { font-size: calc(var(--card) * .62); line-height: 1; font-weight: 800; }
.shadow { display: contents; }
.shadow img { filter: brightness(0) opacity(.5); }
.dots { display: flex; flex-wrap: wrap; justify-content: center; align-content: center; gap: .8vmin; width: 84%; }
.dots i { width: 22%; aspect-ratio: 1; border-radius: 50%; background: #fb8c00; box-shadow: inset 0 -.5vmin 0 #0003; }

/* Explore cards: the thing on top, its example below; a star once she has heard it. */
.card.teach { --card: min(28vh, 17vw); height: calc(var(--card) * 1.2); display: flex; flex-direction: column; align-items: center; justify-content: center; gap: 5%; }
.teach :is(.swatch, .shape) { width: 52%; height: auto; }
.teach img { width: 58%; height: auto; max-height: 42%; }
.teach > :only-child { width: 86%; max-height: 86%; }
.teach .glyph { font-size: calc(var(--card) * .5); }
.teach .count { display: flex; flex-wrap: wrap; justify-content: center; gap: 0 .5vmin; width: 90%; }
.teach .count img { width: 17%; max-height: none; }
.card.seen::after { content: '★'; position: absolute; top: -3vmin; right: -2vmin; font-size: 7vmin; line-height: 1; color: #ffc107; -webkit-text-stroke: .5vmin #fff; paint-order: stroke fill; }

.card.hint { animation: glow 1s ease-in-out infinite; }
@keyframes glow { 50% { scale: 1.06; box-shadow: 0 0 0 .5vmin var(--blue), 0 0 5vmin 2vmin #ffeb3b; } }
.card.picked { box-shadow: 0 0 0 1vmin #ffb300, 0 1.3vmin 0 .5vmin #0003; }
.card.done { box-shadow: 0 0 0 .9vmin #43a047, 0 1.3vmin 0 .5vmin #0003; }

/* Match: the connecting lines (dotted while dragging, green once matched) */
.lines { position: absolute; inset: 0; width: 100%; height: 100%; overflow: visible; pointer-events: none; }
.lines line { stroke-width: 1.6vmin; stroke-linecap: round; }
.lines .drag { stroke: #ffb300; stroke-dasharray: .1vmin 3vmin; }
.lines .ok { stroke: #43a047; }

/* Memory: cards flip in 3D; the back is blue with a star */
.card.mem { background: none; border: 0; box-shadow: none; perspective: 90vmin; }
.mem .inner { position: relative; width: 100%; height: 100%; transform-style: preserve-3d; transition: rotate .45s; rotate: y 180deg; }
.mem.up .inner { rotate: y 0deg; }
.mem :is(.front, .back) { position: absolute; inset: 0; display: grid; place-items: center; border: .9vmin solid #fff; border-radius: 3.5vmin;
  backface-visibility: hidden; -webkit-backface-visibility: hidden; box-shadow: 0 0 0 .5vmin var(--blue), 0 1.3vmin 0 .5vmin #0003; }
.mem .front { background: #fff; }
.mem .back { rotate: y 180deg; background: radial-gradient(#ffffff2e 18%, transparent 20%) 0 0 / 25% 25%, linear-gradient(#2f7de1, #1c56b0); }
.mem .back::after { content: '★'; font-size: 9vmin; color: #fff; opacity: .85; }
.mem.done .front { box-shadow: 0 0 0 .9vmin #43a047, 0 1.3vmin 0 .5vmin #0003; }

.confetti { position: absolute; top: 0; z-index: 5; width: 1.6vmin; height: 1vmin; border-radius: 2px; pointer-events: none; }

@media (orientation: portrait) {
  :root { --card: min(20vw, 13vh); }
  .board, .topics { inset: 14vh 3vw 30vh; }
  .card.teach { --card: min(28vw, 15vh); }
}
