/* Tela de jogo. --k = pixels de tela por pixel de arte (definido pelo JS, inteiro quando possível). */
.game { position: fixed; inset: 0; background: #12345a; display: grid; place-items: center; overflow: hidden; touch-action: manipulation; }
.stage { position: relative; width: calc(var(--stage-w, 384) * 1px * var(--k)); height: calc(var(--stage-h, 216) * 1px * var(--k)); user-select: none; -webkit-user-select: none; overflow: hidden; }
/* abaixo da cena (tela mais alta que 16:9): a própria cena, desfocada e escura, como chão do teclado */
.stage::before { content: ''; position: absolute; inset: 0; background: var(--scene-url, none) center bottom / cover, #12345a; filter: blur(10px) brightness(0.55) saturate(0.85); transform: scale(1.05); }
.stage canvas { position: absolute; left: 0; top: 0; width: 100%; height: calc(216px * var(--k)); image-rendering: pixelated; image-rendering: crisp-edges; }
/* teclado ampliado para o espaço livre: centralizado, do tamanho do conteúdo */
.stage .keyboard.grown { left: 50%; right: auto; width: max-content; transform: translateX(-50%) scale(var(--kbs, 1)); transform-origin: bottom center; }
.stage .keyboard { margin-bottom: var(--kb-lift, 0px); }

/* Campo que recebe o teclado: fora da área visível, mas focável */
.key-input { position: absolute; left: -9999px; top: 0; width: 1px; height: 1px; opacity: 0; }

/* Alvo: fileira de teclas (specs/04, seção 8.1) */
.targets { position: absolute; left: 0; right: 0; top: calc(30px * var(--k)); display: flex; justify-content: center; gap: calc(4px * var(--k)); }
.tile { --s: calc(44px * var(--k)); width: var(--s); height: var(--s); border-radius: calc(5px * var(--k)); background: var(--surface);
  border: calc(0.6px * var(--k)) solid var(--linha); box-shadow: 0 calc(2px * var(--k)) 0 var(--linha);
  display: grid; place-items: center; font: 800 calc(30px * var(--k))/1 var(--font); color: var(--tinta);
  position: relative; transition: transform 120ms; }
.tile.current { transform: translateY(calc(-1px * var(--k))) scale(1.04); }

.tile.correct { background: #e7f6dd; border-color: var(--correct); box-shadow: 0 calc(2px * var(--k)) 0 var(--folha-escura); }
.tile.correct::after { content: '✓'; position: absolute; right: calc(-4px * var(--k)); top: calc(-4px * var(--k));
  width: calc(12px * var(--k)); height: calc(12px * var(--k)); border-radius: 50%; background: var(--correct); color: #fff;
  font: 800 calc(9px * var(--k))/calc(12px * var(--k)) var(--font); text-align: center; }
.tile.retry { animation: retry 400ms steps(1, end) 2; }   /* 2 piscadas a 2,5 por segundo (limite: 3) */
@keyframes retry { 0% { background: var(--retry); color: #fff; border-color: var(--retry); } 50% { background: var(--surface); color: var(--tinta); } }

/* Teclado da tela (specs/04, seção 8.2) */
.keyboard { position: absolute; left: calc(48px * var(--k)); right: calc(48px * var(--k)); bottom: calc(4px * var(--k));
  background: rgba(246, 243, 236, 0.9); border-radius: calc(6px * var(--k)); padding: calc(4px * var(--k));
  display: flex; flex-direction: column; gap: calc(2px * var(--k)); align-items: center; }
.kb-row { display: flex; gap: calc(2px * var(--k)); }
.kb-row:nth-child(2) { margin-left: calc(6px * var(--k)); }
.kb-row:nth-child(3) { margin-left: calc(14px * var(--k)); }
.key { width: calc(21px * var(--k)); height: calc(15px * var(--k)); border-radius: calc(3px * var(--k)); border: 1px solid var(--linha);
  background: var(--surface); box-shadow: 0 calc(1.2px * var(--k)) 0 var(--linha); font: 700 calc(8px * var(--k))/1 var(--font);
  color: var(--tinta); display: grid; place-items: center; cursor: pointer; padding: 0; }
.key.space { width: calc(120px * var(--k)); }
.key.pressed { transform: translateY(calc(1px * var(--k))); box-shadow: none; }
.keyboard.with-support .key:not(.support):not(.hint) { opacity: 0.55; }
.key.support { background: #EEE9FF; border-color: #A38EFF; box-shadow: 0 calc(1.2px * var(--k)) 0 #A38EFF; }
.key.hint { outline: calc(1.4px * var(--k)) solid var(--target); outline-offset: calc(1px * var(--k)); background: #fff6cf; animation: hint 1s ease-in-out infinite; }
@keyframes hint { 50% { outline-color: var(--sol-escuro); } }

/* Botão discreto da profissional: segurar 1 s */
.control { position: absolute; right: calc(3px * var(--k)); bottom: calc(3px * var(--k)); width: calc(12px * var(--k)); height: calc(12px * var(--k));
  border-radius: 50%; border: 0; background: rgba(255, 255, 255, 0.25); cursor: pointer; }
.control.holding { background: rgba(255, 255, 255, 0.7); }

/* Camadas por cima da cena */
.overlay { position: absolute; inset: 0; display: grid; place-items: center; background: rgba(18, 52, 90, 0.35); z-index: 6; } /* acima das camadas dos jogos (trem, ninja) */
.ctrl-panel { background: var(--papel); border-radius: var(--radius); padding: calc(6px * var(--k)); display: grid; gap: calc(3px * var(--k));
  min-width: calc(110px * var(--k)); font-size: calc(6px * var(--k)); }
.ctrl-panel .btn { font-size: calc(6px * var(--k)); min-height: calc(16px * var(--k)); }
.play { width: calc(56px * var(--k)); height: calc(56px * var(--k)); border-radius: 50%; border: 0; background: var(--teal); color: #fff;
  font-size: calc(26px * var(--k)); box-shadow: 0 calc(3px * var(--k)) 0 var(--teal-escuro); cursor: pointer; }
.reward { display: grid; justify-items: center; gap: calc(6px * var(--k)); }
.reward img { width: calc(96px * var(--k)); height: calc(96px * var(--k)); image-rendering: pixelated; background: rgba(255,255,255,.85);
  border-radius: 50%; padding: calc(8px * var(--k)); }
.reward .row { gap: calc(8px * var(--k)); }
.round-btn { width: calc(34px * var(--k)); height: calc(34px * var(--k)); border-radius: 50%; border: 0; cursor: pointer;
  font-size: calc(14px * var(--k)); color: #fff; background: var(--teal); box-shadow: 0 calc(2px * var(--k)) 0 var(--teal-escuro); }
.round-btn.stop { background: var(--tinta-suave); box-shadow: 0 calc(2px * var(--k)) 0 var(--tinta); }

@media (prefers-reduced-motion: reduce) {
  .tile, .key { transition: none; }
  .key.hint { animation: none; }
}

/* Livro ilustrado: prólogos e epílogos (specs/12-narrativa.md, seção 4) */
.story { position: absolute; inset: 0; background: #0d2440; overflow: hidden; }
/* em tela alta, a história (16:9) fica no meio da tela; em volta, a cena desfocada */
.stage > .story { top: calc((var(--stage-h, 216) - 216) / 2 * 1px * var(--k)); bottom: auto; height: calc(216px * var(--k)); z-index: 6; }
/* durante a história, as peças do jogo (trem, teclado) não aparecem por cima nem em volta do livro */
.stage:has(> .story) .keyboard, .stage:has(> .story) .tower-game, .stage:has(> .story) .flight-game { visibility: hidden; }
.story-canvas { position: absolute; inset: 0; width: 100%; height: 100%; image-rendering: pixelated; opacity: 0; transition: opacity var(--fade, 800ms) ease; }
.story.shown .story-canvas, .story.shown .story-message { opacity: 1; }
.story-message { position: absolute; left: 0; right: 0; top: calc(28px * var(--k)); display: flex; flex-direction: column; align-items: center;
  gap: calc(3px * var(--k)); opacity: 0; transition: opacity var(--fade, 800ms) ease; }
.story-message .msg-line { display: flex; justify-content: center; gap: calc(2px * var(--k)); }
.story-message .gap { width: calc(var(--ms, 30) * 0.7px * var(--k)); }
.tile.small { --s: calc(var(--ms, 30) * 1px * var(--k)); font-size: calc(var(--ms, 30) * 0.68px * var(--k)); }
/* Botão ▶ em pixel, no canto da caixa de diálogo */
.story-next { position: absolute; right: calc(20px * var(--k)); bottom: calc(15px * var(--k)); z-index: 3; width: calc(24px * var(--k)); height: calc(22px * var(--k));
  border: 0; background: var(--teal); color: #fff; font: 700 calc(11px * var(--k))/1 var(--font-pixel); cursor: pointer;
  clip-path: polygon(0 calc(2px * var(--k)), calc(2px * var(--k)) calc(2px * var(--k)), calc(2px * var(--k)) 0, calc(100% - 2px * var(--k)) 0,
    calc(100% - 2px * var(--k)) calc(2px * var(--k)), 100% calc(2px * var(--k)), 100% calc(100% - 2px * var(--k)), calc(100% - 2px * var(--k)) calc(100% - 2px * var(--k)),
    calc(100% - 2px * var(--k)) 100%, calc(2px * var(--k)) 100%, calc(2px * var(--k)) calc(100% - 2px * var(--k)), 0 calc(100% - 2px * var(--k)));
  box-shadow: inset 0 calc(-2px * var(--k)) 0 var(--teal-escuro); }
.story-next:active { transform: translateY(calc(1px * var(--k))); box-shadow: none; }
@media (prefers-reduced-motion: reduce) { .story-canvas, .story-message { transition: none; } }
/* Recado posicionado sobre um objeto do quadro (ex.: o papel do Polvim) */
.story-message.at { right: auto; left: calc(var(--mx) * 1px * var(--k)); top: calc(var(--my) * 1px * var(--k));
  transform: translate(-50%, -50%); gap: calc(2px * var(--k)); width: max-content; }
.story-message.at .tile { --s: calc(var(--ms) * 1px * var(--k)); font-size: calc(var(--ms) * 0.7px * var(--k));
  box-shadow: 0 calc(1px * var(--k)) 0 var(--linha); }

/* Pérolas da rodada: apagadas → acesas com um pulinho */
.pearls { position: absolute; left: 0; right: 0; top: calc(8px * var(--k)); display: flex; justify-content: center; gap: calc(4px * var(--k)); pointer-events: none; }
.pearl { width: calc(12px * var(--k)); image-rendering: pixelated; filter: grayscale(1) brightness(0.55); opacity: 0.55; transition: filter 300ms, opacity 300ms; }
.pearl.lit { filter: none; opacity: 1; animation: pearl-pop 420ms ease; }
@keyframes pearl-pop { 40% { transform: scale(1.5); } }
@media (prefers-reduced-motion: reduce) { .pearl.lit { animation: none; } }

/* Recompensa: a carta gira e aparece; contagem do álbum; botões grandes com ícone e palavra */
.reward-screen { display: grid; justify-items: center; align-content: center; gap: calc(5px * var(--k)); width: 100%; height: 100%;
  background: radial-gradient(circle at 50% 40%, rgba(255, 246, 200, 0.45), rgba(18, 52, 90, 0.88) 62%); }
.reward-title { font: 900 calc(16px * var(--k)) var(--font-ui, var(--font)); color: #fff; text-shadow: 0 calc(1.5px * var(--k)) 0 rgba(18, 52, 90, 0.55);
  animation: reward-title 500ms cubic-bezier(0.2, 1.4, 0.4, 1) both; }
.reward-card { perspective: 600px; animation: reward-flip 900ms cubic-bezier(0.2, 1.1, 0.3, 1) both 150ms; }
.reward-screen .sticker-card { width: calc(84px * var(--k)); }
.reward-count { display: grid; justify-items: center; gap: calc(2px * var(--k)); font: 800 calc(7px * var(--k)) var(--font-ui, var(--font)); color: #fff;
  text-shadow: 0 1px 0 rgba(18, 52, 90, 0.6); }
.reward-bar { width: calc(80px * var(--k)); height: calc(4px * var(--k)); border-radius: 99px; background: rgba(255, 255, 255, 0.35); overflow: hidden; }
.reward-bar span { display: block; height: 100%; background: #fff; border-radius: inherit; }
.reward-actions { display: flex; gap: calc(8px * var(--k)); margin-top: calc(2px * var(--k)); }
.reward-btn { display: flex; align-items: center; gap: calc(4px * var(--k)); border: 0; cursor: pointer; border-radius: 99px;
  padding: calc(5px * var(--k)) calc(10px * var(--k)); font: 900 calc(8px * var(--k)) var(--font-ui, var(--font)); }
.reward-btn .i { width: calc(10px * var(--k)); height: calc(10px * var(--k)); }
.reward-btn.again { background: var(--teal); color: #fff; box-shadow: 0 calc(2.5px * var(--k)) 0 var(--teal-escuro); }
.reward-btn.back { background: #fff; color: var(--tinta); box-shadow: 0 calc(2.5px * var(--k)) 0 #cfc7b7; }
.reward-btn:active { transform: translateY(calc(2px * var(--k))); box-shadow: none; }
@keyframes reward-flip { from { transform: scale(0.2) rotateY(540deg); opacity: 0; } 60% { opacity: 1; } }
@keyframes reward-title { from { transform: scale(0.4); opacity: 0; } }
@media (prefers-reduced-motion: reduce) { .reward-card, .reward-title { animation: none; } }

/* ───── História estilo jogo: caixa de diálogo em pixel, legenda letra por letra ───── */
/* No alto: nos quadros, a parte de cima é água; os personagens ficam embaixo */
.dlg { --px: calc(1px * var(--k)); position: absolute; left: calc(12px * var(--k)); right: calc(44px * var(--k)); top: calc(8px * var(--k)); z-index: 2;
  min-height: calc(34px * var(--k)); padding: calc(7px * var(--k)) calc(14px * var(--k)) calc(7px * var(--k)) calc(11px * var(--k));
  background: rgba(13, 36, 64, 0.94); color: #fff; cursor: pointer;
  /* borda dupla em pixel (branca por dentro, escura por fora) e cantos chanfrados */
  box-shadow: inset 0 0 0 var(--px) #0d2440, inset 0 0 0 calc(2 * var(--px)) #f6f3ec, inset 0 0 0 calc(3 * var(--px)) #0d2440;
  clip-path: polygon(0 calc(2 * var(--px)), calc(2 * var(--px)) calc(2 * var(--px)), calc(2 * var(--px)) 0, calc(100% - 2 * var(--px)) 0,
    calc(100% - 2 * var(--px)) calc(2 * var(--px)), 100% calc(2 * var(--px)), 100% calc(100% - 2 * var(--px)), calc(100% - 2 * var(--px)) calc(100% - 2 * var(--px)),
    calc(100% - 2 * var(--px)) 100%, calc(2 * var(--px)) 100%, calc(2 * var(--px)) calc(100% - 2 * var(--px)), 0 calc(100% - 2 * var(--px)));
  opacity: 0; transition: opacity 300ms ease; }
.dlg.left { right: calc(120px * var(--k)); }
.dlg.bottom { top: auto; bottom: calc(8px * var(--k)); }
.dlg { transform: translateY(calc(-8px * var(--k))); transition: opacity 300ms ease, transform 300ms cubic-bezier(0.2, 1.2, 0.4, 1); }
.story.shown .dlg.up { opacity: 1; transform: none; } /* a caixa sobe quando a narradora começa */
.dlg-text { margin: 0; font: 400 calc(10px * var(--k))/1.4 var(--font-pixel); letter-spacing: 0.02em; min-height: calc(28px * var(--k));
  padding-right: calc(6px * var(--k));
  text-shadow: var(--px) var(--px) 0 #0d2440; }
.dlg-name { display: inline-block; margin-bottom: calc(2px * var(--k)); padding: 0 calc(5px * var(--k)); font: 700 calc(8px * var(--k))/1.5 var(--font-pixel);
  color: #fff; background: var(--polvim); box-shadow: 0 var(--px) 0 var(--polvim-escuro, #b5442f); }
.dlg-name[hidden] { display: none; }
.dlg.polvim .dlg-text { color: #ffe1db; }
.dlg-more { position: absolute; right: calc(7px * var(--k)); bottom: calc(5px * var(--k)); width: 0; height: 0;
  border: calc(3px * var(--k)) solid transparent; border-top: calc(4px * var(--k)) solid #fff; border-bottom: 0; animation: dlg-blink 900ms steps(1) infinite; }
@keyframes dlg-blink { 50% { opacity: 0; } }
/* Páginas da história: quadradinhos acesos no canto */
.story-pages { position: absolute; top: calc(8px * var(--k)); right: calc(10px * var(--k)); display: flex; gap: calc(3px * var(--k)); z-index: 2; }
.story-pages .pg { width: calc(5px * var(--k)); height: calc(5px * var(--k)); background: rgba(255, 255, 255, 0.35); box-shadow: 0 0 0 calc(1px * var(--k)) #0d2440; }
.story-pages .pg.on { background: #fff; }
/* Cartão de título na abertura */
.story-title { position: absolute; inset: 0; z-index: 4; display: grid; place-content: center; justify-items: center; gap: calc(4px * var(--k));
  background: radial-gradient(circle at 50% 45%, #1e5ea6, #0d2440 70%); color: #fff; text-align: center; transition: opacity 700ms ease; }
.story-title strong { font: 700 calc(24px * var(--k))/1.1 var(--font-pixel); text-shadow: calc(2px * var(--k)) calc(2px * var(--k)) 0 #0d2440, 0 0 calc(12px * var(--k)) rgba(63, 227, 242, 0.45);
  animation: title-in 700ms cubic-bezier(0.2, 1.3, 0.4, 1) both; }
.story-title span { font: 400 calc(10px * var(--k)) var(--font-pixel); color: #c4e8ff; animation: title-in 700ms ease both 250ms; }
.story-title.gone { opacity: 0; pointer-events: none; }
@keyframes title-in { from { transform: translateY(calc(6px * var(--k))); opacity: 0; } }
@media (prefers-reduced-motion: reduce) { .dlg-more, .story-title strong, .story-title span { animation: none; } }

/* Balão de gibi (fala do Polvim): branco, contorno escuro, rabinho apontando para ele, entra com um pulinho */
.balloon { --bx: 0; --by: 0; position: absolute; z-index: 3; left: calc(var(--bx) * 1px * var(--k)); top: calc(var(--by) * 1px * var(--k));
  transform: translate(calc(6px * var(--k)), calc(-100% - 12px * var(--k))); transform-origin: 0 100%;
  background: #fff; color: var(--tinta); border: calc(1.5px * var(--k)) solid #0d2440; border-radius: calc(10px * var(--k));
  padding: calc(4px * var(--k)) calc(9px * var(--k)); box-shadow: calc(2px * var(--k)) calc(2px * var(--k)) 0 rgba(13, 36, 64, 0.35);
  animation: balloon-pop 380ms cubic-bezier(0.2, 1.6, 0.4, 1) both; white-space: nowrap; }
.balloon.left { transform: translate(calc(-100% - 6px * var(--k)), calc(-100% - 12px * var(--k))); transform-origin: 100% 100%; }
.balloon-text { font: 700 calc(14px * var(--k))/1.1 var(--font-pixel); letter-spacing: 0.02em; }
/* rabinho: contorno escuro + miolo branco */
.balloon::before, .balloon::after { content: ''; position: absolute; width: 0; height: 0; border-style: solid; }
.balloon::before { left: calc(4px * var(--k)); bottom: calc(-11px * var(--k)); border-width: calc(11px * var(--k)) calc(9px * var(--k)) 0 0;
  border-color: #0d2440 transparent transparent transparent; }
.balloon::after { left: calc(5.5px * var(--k)); bottom: calc(-7.5px * var(--k)); border-width: calc(8px * var(--k)) calc(6.5px * var(--k)) 0 0;
  border-color: #fff transparent transparent transparent; }
.balloon.left::before { left: auto; right: calc(4px * var(--k)); border-width: calc(11px * var(--k)) 0 0 calc(9px * var(--k)); border-color: #0d2440 transparent transparent transparent; }
.balloon.left::after { left: auto; right: calc(5.5px * var(--k)); border-width: calc(8px * var(--k)) 0 0 calc(6.5px * var(--k)); border-color: #fff transparent transparent transparent; }
.balloon.out { animation: balloon-out 220ms ease forwards; }
@keyframes balloon-pop { from { scale: 0.2; opacity: 0; } 60% { opacity: 1; } }
@keyframes balloon-out { to { scale: 0.6; opacity: 0; } }
@media (prefers-reduced-motion: reduce) { .balloon, .balloon.out { animation: none; } .dlg { transition: opacity 300ms ease; transform: none; } }

/* Fase passada: a concha abriu (régua do jogo, specs/15) */
.reward-pass { display: flex; align-items: center; gap: calc(4px * var(--k)); padding: calc(2px * var(--k)) calc(8px * var(--k)) calc(2px * var(--k)) calc(3px * var(--k));
  border-radius: 99px; background: #fff; color: var(--teal-escuro); font: 900 calc(8px * var(--k)) var(--font-ui, var(--font));
  box-shadow: 0 calc(2px * var(--k)) 0 rgba(13, 36, 64, 0.35); animation: reward-title 500ms cubic-bezier(0.2, 1.3, 0.4, 1) both; }
.reward-pass img { width: calc(18px * var(--k)); image-rendering: pixelated; }

/* Teclas especiais: no teclado da tela e nos quadrados (ESPAÇO, ENTER, APAGAR) */
.key.special { width: calc(30px * var(--k)); font-size: calc(9px * var(--k)); }
.tile.special { width: auto; min-width: var(--s); padding: 0 calc(6px * var(--k)); font-size: calc(12px * var(--k)); background: #f0ecff; }
.tile.k-space { min-width: calc(70px * var(--k)); color: #8a84a0; font-size: calc(10px * var(--k)); }
.tile.k-enter { color: var(--tinta); }
.tile.k-back { font-size: calc(18px * var(--k)); }
/* Fase "Ops!": a letra errada já escrita (riscada), que some ao apagar */
.tile.wrong-pre { background: #ffe1db; border-color: #e4572e; color: #b5442f; position: relative; }
.tile.wrong-pre::after { content: ''; position: absolute; left: 12%; right: 12%; top: 50%; height: calc(2.5px * var(--k)); background: #e4572e; transform: rotate(-20deg); }
.tile.wrong-pre.erased { transition: transform 300ms ease, opacity 300ms ease; transform: scale(0.3) translateY(calc(-10px * var(--k))); opacity: 0; }

/* ───── Fase bônus: Pulo das Bolhas ───── */
.jump-game { position: absolute; inset: 0; pointer-events: none; }
.jump-game > * { position: absolute; left: calc(var(--x) * 1px * var(--k)); top: calc(var(--y) * 1px * var(--k)); }
.jump-shell { width: calc(30px * var(--k)); transform: translate(-50%, -30%); image-rendering: pixelated; }
.jump-shell.goal { filter: drop-shadow(0 0 calc(4px * var(--k)) rgba(255, 246, 180, 0.9)); }
.jump-bubble { width: calc(26px * var(--k)); height: calc(26px * var(--k)); border-radius: 50%; display: grid; place-items: center;
  border: calc(1.5px * var(--k)) solid rgba(255, 255, 255, 0.9);
  background: radial-gradient(circle at 32% 30%, rgba(255, 255, 255, 0.9) 0 12%, rgba(196, 232, 255, 0.45) 40%, rgba(116, 198, 242, 0.25) 70%);
  animation: jump-float 2.4s ease-in-out var(--d, 0s) infinite; transition: transform 250ms ease, opacity 250ms ease; }
.jump-bubble span { font: 800 calc(14px * var(--k))/1 var(--font); color: var(--tinta); }
.jump-bubble.target { width: calc(32px * var(--k)); height: calc(32px * var(--k)); margin: calc(-3px * var(--k)) 0 0 calc(-3px * var(--k)); background-color: #fff6cf;
  box-shadow: 0 0 0 calc(2px * var(--k)) var(--target, #ffd23f), 0 0 calc(10px * var(--k)) rgba(255, 210, 63, 0.8); }
.jump-bubble.target span { font-size: calc(18px * var(--k)); }
.jump-bubble.reached { background-color: #e7f6dd; }
.jump-bubble.popped { animation: jump-pop 300ms ease forwards; }
.jump-bubble.wobble { animation: jump-wobble 400ms ease; }
.jump-polvim { width: calc(44px * var(--k)); transition: left 520ms cubic-bezier(0.3, 0, 0.7, 1), top 520ms cubic-bezier(0.3, 0, 0.7, 1); z-index: 2; }
.jump-polvim img { width: 100%; image-rendering: pixelated; display: block; }
.jump-polvim.jumping img { animation: jump-hop 520ms ease-out; }
@keyframes jump-float { 50% { transform: translateY(calc(-3px * var(--k))); } }
@keyframes jump-pop { to { transform: scale(1.6); opacity: 0; } }
@keyframes jump-wobble { 25% { transform: translateX(calc(-3px * var(--k))); } 75% { transform: translateX(calc(3px * var(--k))); } }
@keyframes jump-hop { 0% { transform: translateY(0) scaleY(0.85); } 45% { transform: translateY(calc(-26px * var(--k))) scaleY(1.08); } 100% { transform: translateY(0); } }
@media (prefers-reduced-motion: reduce) { .jump-bubble, .jump-polvim.jumping img { animation: none; } .jump-polvim { transition: none; } }
.reward-screen.with-pass { gap: calc(3px * var(--k)); }
.reward-screen.with-pass .sticker-card { width: calc(66px * var(--k)); }
.reward-screen.with-pass .reward-title { font-size: calc(13px * var(--k)); }

/* Fase "Ops!" em dois passos */
.tile.wrong-pre { animation: ops-shake 600ms ease 300ms 2; }
.tile.wrong-pre::before { content: '✗'; position: absolute; right: calc(-5px * var(--k)); top: calc(-5px * var(--k)); width: calc(13px * var(--k)); height: calc(13px * var(--k));
  border-radius: 50%; background: #e4572e; color: #fff; font: 800 calc(9px * var(--k))/calc(13px * var(--k)) var(--font); text-align: center; }
.tile.k-back.pending { position: relative; outline: calc(1.5px * var(--k)) solid #ffd23f; outline-offset: calc(1px * var(--k)); }
.tile.k-back.pending::after { content: '◀'; position: absolute; left: calc(-11px * var(--k)); top: 50%; transform: translateY(-50%);
  color: #ffd23f; font-size: calc(10px * var(--k)); text-shadow: 0 calc(1px * var(--k)) 0 rgba(13, 36, 64, 0.5); animation: ops-point 900ms ease-in-out infinite; }
.tile.later { display: none; }
.tile.k-back.used { opacity: 0.6; }
.tile.k-back.gone { display: none; }
@keyframes ops-shake { 20% { transform: translateX(calc(-2px * var(--k))) rotate(-3deg); } 40% { transform: translateX(calc(2px * var(--k))) rotate(3deg); } 60% { transform: translateX(calc(-1px * var(--k))); } }
@keyframes ops-point { 50% { transform: translate(calc(-2px * var(--k)), -50%); } }
@media (prefers-reduced-motion: reduce) { .tile.wrong-pre, .tile.k-back.pending::after { animation: none; } }
/* Várias teclas na tentativa: a VEZ fica bem marcada (mesmo amarelo da tecla acesa no teclado) + setinha embaixo */
.targets:has(.tile + .tile) .tile.current:not(.correct) { outline: calc(2px * var(--k)) solid var(--target, #ffd23f); outline-offset: calc(1.5px * var(--k)); }
.targets:has(.tile + .tile) .tile.current:not(.correct):not(.k-back)::after { content: '▲'; position: absolute; left: 50%; bottom: calc(-12px * var(--k)); transform: translateX(-50%);
  color: var(--target, #ffd23f); font-size: calc(8px * var(--k)); text-shadow: 0 calc(1px * var(--k)) 0 rgba(13, 36, 64, 0.4); animation: turn-point 900ms ease-in-out infinite; }
@keyframes turn-point { 50% { transform: translate(-50%, calc(-2px * var(--k))); } }
@media (prefers-reduced-motion: reduce) { .targets .tile.current::after { animation: none; } }
.targets .tile { position: relative; }
/* A peça que a narradora está dizendo agora (leitura sincronizada com a fala) */
.targets .tile.reading:not(.correct) { background: #fff6cc; border-color: #f2c94c; transform: translateY(calc(-3px * var(--k))); }
@media (prefers-reduced-motion: reduce) { .targets .tile.reading:not(.correct) { transform: none; } }
/* Sequências longas: até 11 peças cabem nos 384 px do palco (specs/15, 05/10/2026) */
.targets.long { gap: calc(3px * var(--k)); }
.targets.long .tile { --s: calc(36px * var(--k)); font-size: calc(25px * var(--k)); }
.targets.long .tile.k-space { min-width: calc(44px * var(--k)); font-size: calc(9px * var(--k)); }
/* Jogos em que o meio da tela é do cenário (Ponte das Frases): as peças ficam menores e no alto, em qualquer tentativa */
.stage.tiles-compact .targets { top: calc(25px * var(--k)); } /* abaixo das pérolas (8 + 12 px, e a pérola cresce ao acender) */
.stage.tiles-compact .targets .tile { --s: calc(24px * var(--k)); font-size: calc(18px * var(--k)); border-radius: calc(4px * var(--k)); }
.stage.tiles-compact .targets .tile.k-space { min-width: calc(24px * var(--k)); width: auto; padding: 0 calc(2px * var(--k)); font-size: calc(6.5px * var(--k)); }
.stage.tiles-compact .targets .tile.current:not(.correct)::after { bottom: calc(-9px * var(--k)); }
/* Frases com ponto (Mundo 7): agrupadas por palavra, quebrando em até duas linhas, sem cortar palavra */
.targets.phrase { top: calc(25px * var(--k)); flex-wrap: wrap; column-gap: calc(5px * var(--k)); row-gap: calc(4px * var(--k)); padding: 0 calc(10px * var(--k)); }
.targets.phrase .word { display: flex; gap: calc(2px * var(--k)); }
.targets.phrase .tile { --s: calc(23px * var(--k)); font-size: calc(17px * var(--k)); border-radius: calc(4px * var(--k)); }
.targets.phrase .tile.k-space { min-width: calc(23px * var(--k)); width: auto; padding: 0 calc(2px * var(--k)); font-size: calc(6.5px * var(--k)); }
.targets.phrase .tile.k-period { font-size: calc(22px * var(--k)); line-height: 0.6; }
.targets.phrase .tile.current:not(.correct)::after { bottom: calc(-9px * var(--k)); }
.targets.xlong { gap: calc(3px * var(--k)); }
.targets.xlong .tile { --s: calc(28px * var(--k)); font-size: calc(20px * var(--k)); border-radius: calc(4px * var(--k)); }
.targets.xlong .tile.k-space { min-width: calc(34px * var(--k)); padding: 0 calc(3px * var(--k)); font-size: calc(8px * var(--k)); }
.targets.xlong .tile.correct::after, .targets.long .tile.correct::after { width: calc(10px * var(--k)); height: calc(10px * var(--k)); font-size: calc(7px * var(--k)); line-height: calc(10px * var(--k)); }

/* Conquista do mundo (como nos videogames): medalha girando, estrelas novas acendendo, palavra do recado */
.achievement { display: grid; justify-items: center; align-content: center; gap: calc(3px * var(--k)); width: 100%; height: 100%;
  background: radial-gradient(circle at 50% 42%, rgba(255, 214, 90, 0.45), rgba(13, 36, 64, 0.94) 62%); position: relative; z-index: 5; }
.ach-banner { font: 700 calc(22px * var(--k))/1 var(--font-pixel); text-transform: uppercase; letter-spacing: 0.06em; color: var(--sol);
  text-shadow: calc(1.5px * var(--k)) calc(1.5px * var(--k)) 0 #7a4c05, calc(-1px * var(--k)) calc(-1px * var(--k)) 0 #7a4c05, 0 0 calc(10px * var(--k)) rgba(255, 210, 63, 0.6);
  animation: reward-title 500ms cubic-bezier(0.2, 1.4, 0.4, 1) both; }
.ach-sub { font: 800 calc(8.5px * var(--k)) var(--font-ui, var(--font)); color: #fff; text-shadow: 0 calc(1px * var(--k)) 0 rgba(18, 52, 90, 0.6); }
.ach-medal { animation: ach-in 1000ms cubic-bezier(0.2, 1.2, 0.4, 1) both 150ms; }
.ach-medal .medal { font-size: calc(6.2px * var(--k)); }
.ach-medal .medal-star.fresh { animation: star-pop 500ms cubic-bezier(0.2, 1.8, 0.4, 1) both 1150ms; }
.ach-medal .medal-star.fresh:nth-child(2) { animation-delay: 1450ms; } .ach-medal .medal-star.fresh:nth-child(3) { animation-delay: 1750ms; }
.ach-stars { list-style: none; margin: 0; padding: 0; display: grid; gap: calc(1px * var(--k)); justify-items: center;
  font: 800 calc(8px * var(--k)) var(--font-ui, var(--font)); color: #fff; }
.ach-stars .medal-star { font-size: 1.2em; margin-right: calc(2px * var(--k)); }
.ach-word { display: grid; justify-items: center; gap: calc(3px * var(--k)); max-width: calc(340px * var(--k)); font: 800 calc(7.5px * var(--k)) var(--font-ui, var(--font)); color: #fff; }
/* as teclas por palavra, quebrando entre palavras; o lado (--kc) vem do tamanho da frase */
.ach-keys { --kc: 16; display: flex; flex-wrap: wrap; justify-content: center; column-gap: calc(6px * var(--k)); row-gap: calc(3px * var(--k)); }
.ach-key-word { display: flex; gap: calc(2px * var(--k)); }
.ach-keys .keycap { width: calc(var(--kc) * 1px * var(--k)); height: calc(var(--kc) * 1px * var(--k)); display: grid; place-items: center; border-radius: calc(3px * var(--k));
  background: #fff; color: var(--tinta); font: 800 calc(var(--kc) * 0.69px * var(--k)) var(--font); box-shadow: 0 calc(1.5px * var(--k)) 0 #cfc7b7; }
@keyframes ach-in { from { transform: scale(0.2) rotateY(540deg); opacity: 0; } }
@keyframes star-pop { from { transform: scale(0); color: #fff; } 60% { transform: scale(1.5); } }
@media (prefers-reduced-motion: reduce) { .ach-medal, .ach-medal .medal-star.fresh, .ach-banner { animation: none; } }
.reward-btn .px-badge { font-size: 1em; }

/* ---------- Teclado Mágico (Mundo 0, Praia da Chegada) ---------- */
.magic-game { position: absolute; inset: 0; pointer-events: none; }
.magic-key { position: absolute; left: 50%; top: calc(26px * var(--k)); transform: translateX(-50%); min-width: calc(64px * var(--k)); height: calc(64px * var(--k));
  padding: 0 calc(10px * var(--k)); border-radius: calc(8px * var(--k)); background: var(--surface); border: calc(0.8px * var(--k)) solid var(--linha);
  box-shadow: 0 calc(4px * var(--k)) 0 var(--linha); display: grid; place-items: center; font: 800 calc(46px * var(--k))/1 var(--font); color: var(--tinta); }
.magic-key:empty { display: none; }
.magic-key.wide { font-size: calc(16px * var(--k)); min-width: calc(110px * var(--k)); color: var(--tinta-suave); background: #f0ecff; }
.magic-key.idle { color: #c9c2b4; }
.magic-key.target { outline: calc(2px * var(--k)) solid var(--target, #ffd23f); outline-offset: calc(2px * var(--k)); }
.magic-key.pop { animation: magic-pop 380ms cubic-bezier(0.2, 1.6, 0.4, 1); }
.magic-key.shake { animation: retry 400ms steps(1, end) 2; }
@keyframes magic-pop { from { transform: translateX(-50%) scale(0.4); } }
/* Concha (moldura do Mundo 0) com a figura da letra, à direita da tecla */
.magic-shell { position: absolute; left: calc(238px * var(--k)); top: calc(18px * var(--k)); width: calc(70px * var(--k)); height: calc(70px * var(--k));
  display: grid; place-items: center; }
.magic-shell .shell-art { position: absolute; inset: 0; width: 100%; height: 100%; image-rendering: pixelated; }
.magic-shell.no-art { border-radius: 50% 50% 46% 46%; background: radial-gradient(circle at 50% 60%, #fff3e6 0 45%, #ffc9b8 46% 70%, #f39a86 71%); }
.magic-figure { position: relative; width: calc(40px * var(--k)); height: calc(40px * var(--k)); image-rendering: pixelated; }
.magic-shell.pop { animation: magic-rise 520ms cubic-bezier(0.2, 1.4, 0.4, 1); }
@keyframes magic-rise { from { transform: translateY(calc(16px * var(--k))) scale(0.5); opacity: 0; } }
/* Onda (ESPAÇO): desenhada em pixel dentro da cena, atrás do Polvim (wave.js) */
/* Barquinho (ENTER): sai do píer à direita e vai embora pelo mar */
.magic-boat { position: absolute; left: calc(292px * var(--k)); top: calc(78px * var(--k)); width: calc(40px * var(--k)); height: calc(40px * var(--k)); opacity: 0; }
.magic-boat img { width: 100%; height: 100%; image-rendering: pixelated; }
.magic-boat.no-art { clip-path: polygon(50% 0, 50% 70%, 95% 70%, 80% 95%, 20% 95%, 5% 70%, 45% 70%, 45% 10%, 10% 62%, 45% 62%); background: linear-gradient(#fff 0 68%, #a0623a 69%); }
.magic-boat.go { animation: magic-boat 1400ms ease-in; }
/* sai do píer (à direita) rumo ao horizonte, ficando pequeno */
@keyframes magic-boat { from { opacity: 1; } 15% { opacity: 1; transform: translateY(calc(-2px * var(--k))); } to { opacity: 0.85; transform: translateX(calc(-150px * var(--k))) translateY(calc(-12px * var(--k))) scale(0.5); } }
@media (prefers-reduced-motion: reduce) { .magic-key.pop, .magic-shell.pop, .magic-key.shake { animation: none; } .magic-boat.go { animation-duration: 1ms; } }
.reward-polvim { width: calc(64px * var(--k)); image-rendering: pixelated; animation: bob 2.4s ease-in-out infinite; }

/* ---------- Mundo 2: teclado-vila (07/10/2026, v3: casas grandes) ----------
   Decisão do Guilherme: cada tecla é uma CASA — telhado colorido em cima e a fachada branca é a tecla, com a letra
   grande e escura (a mesma da peça de cima), para comparar com o teclado de verdade. As ruas (fileiras) ficam
   espaçadas, e o Polvim Ninja pousa no telhado, ATRÁS da rua de cima: nunca cobre uma letra. */
.keyboard.skin-vila { z-index: 1; left: calc(26px * var(--k)); right: calc(26px * var(--k)); bottom: calc(3px * var(--k)); gap: calc(15px * var(--k));
  padding: calc(9px * var(--k)) calc(4px * var(--k)) calc(3px * var(--k)); background: none; }
/* a rua: faixa clara e suave atrás das casas (contraste com o cenário, sem esconder a vila) */
.keyboard.skin-vila::before { content: ''; position: absolute; inset: 0; z-index: -1; border-radius: calc(8px * var(--k));
  background: linear-gradient(rgba(255, 248, 235, 0.55), rgba(255, 248, 235, 0.82)); box-shadow: 0 0 calc(10px * var(--k)) rgba(60, 30, 10, 0.25); }
.keyboard.skin-vila .kb-row { position: relative; z-index: 2; gap: calc(4px * var(--k)); }
.keyboard.skin-vila .key { --roof: #d9573f; --roof-dark: #a53a28; position: relative; width: calc(23px * var(--k)); height: calc(18px * var(--k));
  border: calc(0.7px * var(--k)) solid #bdb19a; border-top: 0; border-radius: 0 0 calc(3px * var(--k)) calc(3px * var(--k));
  background: #fff; color: #1e1b26; box-shadow: 0 calc(1.8px * var(--k)) 0 #a99d86; font: 800 calc(12px * var(--k))/1 var(--font); padding: 0; }
/* o telhado: largo (passa um pouco da casa), com as telhas e a chaminé */
.keyboard.skin-vila .key::before { content: ''; position: absolute; left: calc(-2px * var(--k)); right: calc(-2px * var(--k)); top: calc(-7.5px * var(--k)); height: calc(8px * var(--k));
  background: repeating-linear-gradient(90deg, transparent 0 calc(3px * var(--k)), rgba(0, 0, 0, 0.12) calc(3px * var(--k)) calc(3.6px * var(--k))),
    linear-gradient(var(--roof) 0 72%, var(--roof-dark) 72%);
  clip-path: polygon(50% 0, 100% 100%, 0 100%); }
.keyboard.skin-vila .key::after { content: ''; position: absolute; right: 18%; top: calc(-7px * var(--k)); width: calc(2.4px * var(--k)); height: calc(4px * var(--k));
  background: #8f6a4a; z-index: -1; }
.keyboard.skin-vila .kb-row .key:nth-child(4n+2) { --roof: #3f8fd0; --roof-dark: #2a6699; }
.keyboard.skin-vila .kb-row .key:nth-child(4n+3) { --roof: #4ea548; --roof-dark: #357632; }
.keyboard.skin-vila .kb-row .key:nth-child(4n) { --roof: #e8a92a; --roof-dark: #b57d14; }
.keyboard.skin-vila .key.special { font-size: calc(10px * var(--k)); color: #5e5a68; }
/* barra de espaço: a calçada da praça (sem telhado), onde o ninja começa */
.keyboard.skin-vila .key.space { width: calc(130px * var(--k)); height: calc(9px * var(--k)); border-top: calc(0.7px * var(--k)) solid #bdb19a; border-radius: calc(3px * var(--k)); }
.keyboard.skin-vila .key.space::before, .keyboard.skin-vila .key.space::after { display: none; }
/* dica: a fachada acende (amarelo) com o contorno pulsando, como nos outros mundos */
.keyboard.skin-vila .key.hint { outline: calc(1.4px * var(--k)) solid var(--target); outline-offset: calc(1px * var(--k)); background: #fff3b8; animation: hint 1s ease-in-out infinite; }
.keyboard.skin-vila .key.pressed { transform: translateY(calc(1px * var(--k))); box-shadow: none; }
.keyboard.skin-vila.with-support .key:not(.support):not(.hint) { opacity: 1; }
/* o ninja mora DENTRO da vila: na frente da rua (faixa), atrás das casas */
/* o ninja pousa no topo do telhado e cabe INTEIRO no vão entre as ruas: na frente, sem alcançar a letra de cima */
.keyboard.skin-vila > .ninja { z-index: 3; }
.keyboard.skin-vila > .ninja.frames { width: calc(21px * var(--k)); }
/* as ruas espaçadas ocupam mais altura: as peças de cima ficam um pouco menores e mais no alto */
.stage.skin-vila .targets { top: calc(28px * var(--k)); }
.stage.skin-vila .targets .tile { --s: calc(36px * var(--k)); font-size: calc(25px * var(--k)); }
.stage.skin-vila .targets.long .tile { --s: calc(31px * var(--k)); font-size: calc(21px * var(--k)); }
.stage.skin-vila .targets.xlong .tile { --s: calc(26px * var(--k)); font-size: calc(18px * var(--k)); }
.stage.skin-vila .targets .tile.special { min-width: calc(50px * var(--k)); font-size: calc(10px * var(--k)); }
.stage.skin-vila .targets .tile.k-back { font-size: calc(16px * var(--k)); }
/* Polvim Ninja: em pé no telhado da tecla; pula em arco */
.ninja { position: absolute; left: var(--nx, 50%); top: var(--ny, 60%); width: calc(24px * var(--k)); transform: translate(-50%, -96%); z-index: 4; pointer-events: none;
  transition: left 480ms cubic-bezier(0.3, 0, 0.7, 1), top 480ms cubic-bezier(0.3, 0, 0.7, 1); }
.ninja img { width: 100%; display: block; image-rendering: pixelated; }
.ninja.jumping.css img { animation: ninja-arc 480ms ease-out; }   /* sem a folha de pulo: arco do CSS */
.ninja.jumping.drawn img { animation: ninja-arc-soft 480ms ease-out; } /* com a folha: o desenho faz o agachar/esticar */
@keyframes ninja-arc-soft { 50% { transform: translateY(calc(-16px * var(--k))); } }
/* respiração: um quadro só, animado de leve (regra do 05 §3i) */
.ninja:not(.jumping) img { animation: ninja-breathe 2.6s ease-in-out infinite; transform-origin: 50% 100%; }
@keyframes ninja-breathe { 50% { transform: scaleY(1.035); } }
.ninja.bounce img { animation: ninja-bounce 300ms ease-out; }
@keyframes ninja-arc { 0% { transform: translateY(0) scaleY(0.85); } 45% { transform: translateY(calc(-22px * var(--k))) scaleY(1.06); } 100% { transform: translateY(0); } }
@keyframes ninja-bounce { 50% { transform: translateY(calc(-6px * var(--k))); } }
@media (prefers-reduced-motion: reduce) { .ninja { transition: none; } .ninja.jumping img, .ninja.bounce img { animation: none; } }

/* Balões do Polvim Ninja (bônus do Mundo 2) */
.balloon-game { position: absolute; inset: 0; pointer-events: none; }
.balloon-game > * { position: absolute; left: calc(var(--x) * 1px * var(--k)); top: calc(var(--y) * 1px * var(--k)); }
.party-balloon { width: calc(26px * var(--k)); height: calc(30px * var(--k)); margin-left: calc(-13px * var(--k)); margin-top: calc(-15px * var(--k));
  display: grid; place-items: center; animation: jump-float 2.4s ease-in-out var(--d, 0s) infinite; transition: transform 250ms ease, opacity 250ms ease; }
.balloon-art { position: absolute; inset: 0; width: 100%; height: 100%; image-rendering: pixelated; }
.party-balloon.no-art .balloon-art { display: none; }
.party-balloon.no-art { border-radius: 50% 50% 46% 46%; background: radial-gradient(circle at 35% 30%, #fff8 0 12%, transparent 13%), var(--bal, #e4572e); }
.party-balloon.amarelo { --bal: #f4c430; } .party-balloon.azul { --bal: #3e8ed0; }
.party-balloon .rope { position: absolute; left: 50%; top: 100%; width: calc(1px * var(--k)); height: calc(34px * var(--k) - 15px * var(--k)); background: #6b5a45; }
.balloon-letter { position: relative; font: 800 calc(14px * var(--k))/1 var(--font); color: #fff; text-shadow: 0 calc(1px * var(--k)) 0 rgba(0, 0, 0, 0.35); }
.party-balloon.target { transform: scale(1.18); }
.party-balloon.target .balloon-letter { color: var(--tinta); text-shadow: none; background: #fff6cf; border-radius: calc(4px * var(--k)); padding: calc(2px * var(--k)) calc(4px * var(--k)); }
.party-balloon.popped { animation: jump-pop 300ms ease forwards; }
.party-balloon.wobble { animation: jump-wobble 400ms ease; }
.balloon-ninja { width: calc(30px * var(--k)); margin-left: calc(-15px * var(--k)); margin-top: calc(-8px * var(--k)); z-index: 3;
  transition: left 560ms cubic-bezier(0.4, 0, 0.6, 1), top 560ms cubic-bezier(0.4, 0, 0.6, 1); }
.balloon-ninja img { width: 100%; display: block; image-rendering: pixelated; }
.balloon-ninja.swinging.css img { animation: ninja-swing 560ms ease-in-out; transform-origin: 50% 0; }
.balloon-ninja:not(.swinging):not(.landed) img { animation: ninja-sway 2.4s ease-in-out infinite; transform-origin: 50% 0; } /* pendurado, balança de leve */
@keyframes ninja-sway { 25% { transform: rotate(-4deg); } 75% { transform: rotate(4deg); } }
.balloon-ninja.landed { margin-top: calc(-30px * var(--k)); }
@keyframes ninja-swing { 0% { transform: rotate(0); } 40% { transform: translateY(calc(8px * var(--k))) rotate(-14deg); } 100% { transform: rotate(0); } }
@media (prefers-reduced-motion: reduce) { .party-balloon, .balloon-ninja.swinging img { animation: none; } .balloon-ninja { transition: none; } }
.ninja { width: calc(26px * var(--k)); }
/* Quadros de animação (96 px com espaço para o pulo): o personagem ocupa ~2/3 da caixa */
.ninja.frames { width: calc(30px * var(--k)); transform: translate(-50%, -100%); }
.balloon-ninja.frames { width: calc(36px * var(--k)); margin-left: calc(-18px * var(--k)); margin-top: calc(-4px * var(--k)); }

/* ---------- Mundo 3: Trem das Palavras (specs/17) ----------
   Trilho na beira da plataforma (os trilhos do cenário ficam atrás do teclado); locomotiva à esquerda com o Polvim na
   cabine; vagões com a letra engatam atrás, à direita. Sem a arte do trem (05 §3j passo 3): peças desenhadas em CSS.
   Com a arte, as peças vêm recortadas rente ao desenho (art-source/tools/trem-extras.py): a caixa segue o desenho. */
.train-game { position: absolute; left: 0; right: 0; top: 0; height: calc(216px * var(--k)); pointer-events: none; z-index: 1; }
.track { position: absolute; left: 0; right: 0; top: calc(126px * var(--k)); height: calc(4px * var(--k));
  background: repeating-linear-gradient(90deg, #6b4a2f 0 calc(3px * var(--k)), transparent calc(3px * var(--k)) calc(9px * var(--k))) 0 calc(1.5px * var(--k)) / 100% calc(2.5px * var(--k)) no-repeat,
    linear-gradient(#8d8d95 0 calc(1.2px * var(--k)), transparent calc(1.2px * var(--k))); }
.train { position: absolute; left: calc(70px * var(--k)); top: calc(96px * var(--k)); height: calc(30px * var(--k)); display: flex; align-items: flex-end; gap: calc(2px * var(--k)); }
.track.art { top: calc(124px * var(--k)); height: calc(7px * var(--k)); background: url(../assets/sprites/trem/trilho.png) 0 0 / auto 100% repeat-x; image-rendering: pixelated; }
.train-game:has(.track.art) .train { left: calc(12px * var(--k)); top: auto; bottom: calc(87px * var(--k)); height: auto; gap: calc(1px * var(--k)); }
.train.arriving { animation: train-arrive 900ms cubic-bezier(0.2, 0.7, 0.3, 1) both; }
.train.departing { animation: train-depart 1300ms cubic-bezier(0.5, 0, 0.8, 0.4) forwards; }
/* chega pela direita e parte para a esquerda (a locomotiva vai na frente, à esquerda) */
@keyframes train-arrive { from { transform: translateX(calc(330px * var(--k))); } }
@keyframes train-depart { to { transform: translateX(calc(-460px * var(--k))); } }
.loco { position: relative; width: calc(40px * var(--k)); height: calc(30px * var(--k)); }
.loco-art { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: contain; image-rendering: pixelated; }
.loco-css { position: absolute; inset: 0; border-radius: calc(10px * var(--k)) calc(4px * var(--k)) calc(3px * var(--k)) calc(3px * var(--k));
  background: linear-gradient(#e4572e 0 70%, #2a2733 70%); }
.loco-css::before { content: ''; position: absolute; left: calc(6px * var(--k)); top: calc(-8px * var(--k)); width: calc(6px * var(--k)); height: calc(9px * var(--k)); background: #2a2733; border-radius: calc(1px * var(--k)); }
.loco.art { width: calc(48px * var(--k)); height: auto; }
.loco.art .loco-art { position: static; display: block; height: auto; }
.loco.art .train-driver { right: calc(-2px * var(--k)); bottom: calc(15px * var(--k)); width: calc(26px * var(--k)); }
.train-driver { position: absolute; right: calc(1px * var(--k)); bottom: calc(14px * var(--k)); width: calc(22px * var(--k)); image-rendering: pixelated; z-index: 1; }
.wagons { display: flex; align-items: flex-end; gap: calc(2px * var(--k)); }
.wagon { position: relative; width: calc(24px * var(--k)); height: calc(20px * var(--k)); display: grid; place-items: center; animation: wagon-couple 260ms ease-out; }
.wagon:not(.art) { border-radius: calc(2px * var(--k)); background: var(--wagon, #f2c94c); box-shadow: inset 0 calc(-4px * var(--k)) 0 rgba(0, 0, 0, 0.18); }
.wagon.azul { --wagon: #4f9fd6; } .wagon.verde { --wagon: #5daa53; }
.wagon:not(.art)::after { content: ''; position: absolute; left: 15%; right: 15%; bottom: calc(-3px * var(--k)); height: calc(5px * var(--k));
  background: radial-gradient(circle, #2a2733 0 45%, transparent 50%) 0 0 / 50% 100% repeat-x; }
.wagon-art { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: contain; image-rendering: pixelated; }
.wagon-letter { position: relative; display: grid; place-items: center; min-width: calc(15px * var(--k)); height: calc(13px * var(--k)); margin-top: calc(-3px * var(--k));
  border-radius: calc(2px * var(--k)); background: #fff; color: #1e1b26; font: 800 calc(11px * var(--k))/1 var(--font); box-shadow: 0 calc(1px * var(--k)) 0 rgba(0, 0, 0, 0.25); }
.wagon.art { width: calc(40px * var(--k)); height: auto; display: block; }
.wagon.art .wagon-art { position: static; display: block; height: auto; }
.wagon.art .wagon-letter { position: absolute; left: 50%; top: 42%; transform: translate(-50%, -50%); margin: 0; min-width: calc(17px * var(--k)); height: calc(15px * var(--k));
  font-size: calc(13px * var(--k)); }
.wagon.gap { width: calc(10px * var(--k)); }
.wagon.art.gap { width: calc(6px * var(--k)); }
.wagon.gap .wagon-art { display: none; }
.wagon.gap .wagon-letter { display: none; }
.wagon-cargo { position: absolute; bottom: 100%; left: 50%; width: calc(22px * var(--k)); transform: translateX(-50%); image-rendering: pixelated; animation: cargo-hop 400ms ease-out; }
@keyframes wagon-couple { from { transform: translateX(calc(14px * var(--k))); opacity: 0; } }
@keyframes cargo-hop { from { transform: translate(-50%, calc(-30px * var(--k))) scale(1.4); } }
/* placa da plataforma com a figura da palavra: em pé na plataforma, à direita, ABAIXO da fileira de peças
   (frase longa, como "O I OI", ocupa a largura toda lá em cima) */
.train-sign { position: absolute; right: calc(14px * var(--k)); top: calc(80px * var(--k)); width: calc(46px * var(--k)); height: calc(42px * var(--k));
  display: grid; place-items: center; background: #fbf2df; border: calc(1.5px * var(--k)) solid #1f5f8b; border-radius: calc(4px * var(--k));
  box-shadow: 0 calc(2px * var(--k)) 0 #164566; }
.train-sign::before, .train-sign::after { content: ''; position: absolute; top: 100%; width: calc(2px * var(--k)); height: calc(6px * var(--k)); background: #6b5a45; }
.train-sign::before { left: 22%; } .train-sign::after { right: 22%; }
.train-picture { width: calc(34px * var(--k)); height: calc(34px * var(--k)); object-fit: contain; image-rendering: pixelated; transition: transform 400ms ease, opacity 400ms ease; }
.train-sign.boarding .train-picture { transform: translateY(calc(20px * var(--k))) scale(0.5); opacity: 0; }
@media (prefers-reduced-motion: reduce) { .train.arriving, .train.departing, .wagon, .wagon-cargo { animation: none; } .train.departing { opacity: 0; } }

/* Teclado da Estação: tecla de verdade (clara, letra grande) com uma plaquinha de estação azul no alto */
.keyboard.skin-estacao { background: rgba(250, 246, 236, 0.93); border-radius: calc(6px * var(--k)); box-shadow: 0 calc(2px * var(--k)) 0 rgba(31, 95, 139, 0.45); }
.keyboard.skin-estacao .key { background: #fff; color: #1e1b26; font-size: calc(9.5px * var(--k)); border-color: #c9bfae; border-top: calc(2.2px * var(--k)) solid #1f5f8b; }
.keyboard.skin-estacao .key.hint { background: #fff6cf; border-top-color: var(--target); }

/* Bônus do Mundo 3: Plataforma Viva */
.live-game { position: absolute; left: 0; right: 0; top: 0; height: calc(216px * var(--k)); pointer-events: none; z-index: 1; }
.live-spot { position: absolute; left: 50%; top: calc(78px * var(--k)); width: calc(52px * var(--k)); height: calc(52px * var(--k)); margin-left: calc(-26px * var(--k));
  display: grid; place-items: center; border-radius: 50%; background: radial-gradient(circle, rgba(255, 246, 180, 0.95), rgba(255, 246, 180, 0) 70%); }
.live-thing { width: calc(40px * var(--k)); height: calc(40px * var(--k)); object-fit: contain; image-rendering: pixelated; animation: jump-float 2.4s ease-in-out infinite; }
.live-spot.alive .live-thing { animation: live-hop 700ms cubic-bezier(0.2, 1.6, 0.4, 1); }
@keyframes live-hop { 30% { transform: translateY(calc(-14px * var(--k))) scale(1.2) rotate(-6deg); } 60% { transform: translateY(0) scale(0.95); } }
.live-polvim { position: absolute; left: calc(26px * var(--k)); top: calc(62px * var(--k)); width: calc(68px * var(--k)); image-rendering: pixelated; }
.live-shelf { position: absolute; left: calc(240px * var(--k)); right: calc(14px * var(--k)); top: calc(86px * var(--k)); display: flex; flex-wrap: wrap; align-content: flex-start; gap: calc(3px * var(--k)); }
.shelf-thing { width: calc(18px * var(--k)); height: calc(18px * var(--k)); object-fit: contain; image-rendering: pixelated; animation: wagon-couple 300ms ease-out; }
@media (prefers-reduced-motion: reduce) { .live-thing, .live-spot.alive .live-thing, .shelf-thing { animation: none; } }

/* ---------- Mundo 4: Casa Colorida (specs/18) ----------
   Objetos da fase em pé no chão do cômodo, "a lápis" (sem cor); o da vez brilha; escrito, ganha cor e pula.
   O cômodo (o fundo) perde o cinza a cada pérola: isso é feito no canvas (casa-colorida/index.js). */
.room-game { position: absolute; left: 0; right: 0; top: 0; height: calc(216px * var(--k)); pointer-events: none; z-index: 1; }
.room-thing { position: absolute; left: calc(var(--tx, 240) * 1px * var(--k)); top: calc(84px * var(--k)); width: calc(46px * var(--k)); height: calc(46px * var(--k));
  transform: translateX(-50%); display: grid; place-items: end center; }
.room-thing img { width: 100%; height: 100%; object-fit: contain; object-position: bottom; image-rendering: pixelated;
  filter: grayscale(1) brightness(1.18) contrast(0.85); opacity: 0.8; transition: filter 450ms ease, opacity 450ms ease; }
.room-thing.current img { opacity: 1; filter: grayscale(1) brightness(1.18) contrast(0.85) drop-shadow(0 0 calc(2px * var(--k)) #ffd23f) drop-shadow(0 0 calc(2px * var(--k)) #ffd23f); }
.room-thing.current { animation: thing-wait 1.8s ease-in-out infinite; }
.room-thing.painted img { filter: none; opacity: 1; }
.room-thing.hop { animation: thing-hop 650ms cubic-bezier(0.2, 1.6, 0.4, 1); }
@keyframes thing-wait { 50% { transform: translateX(-50%) translateY(calc(-2px * var(--k))); } }
@keyframes thing-hop { 35% { transform: translateX(-50%) translateY(calc(-12px * var(--k))) scale(1.15) rotate(-5deg); } 70% { transform: translateX(-50%) scale(0.95); } }
.room-painter { position: absolute; left: calc(22px * var(--k)); top: calc(76px * var(--k)); width: calc(58px * var(--k)); image-rendering: pixelated; }
@media (prefers-reduced-motion: reduce) { .room-thing.current, .room-thing.hop { animation: none; } .room-thing img { transition: none; } }

/* Bônus do Mundo 4: Sombras — a coisa aparece só como sombra; escrita, se revela colorida */
.shadow-game { position: absolute; left: 0; right: 0; top: 0; height: calc(216px * var(--k)); pointer-events: none; z-index: 1; }
.shadow-spot { position: absolute; left: 50%; top: calc(78px * var(--k)); width: calc(56px * var(--k)); height: calc(56px * var(--k)); margin-left: calc(-28px * var(--k));
  display: grid; place-items: center; border-radius: 50%; background: radial-gradient(circle, rgba(255, 255, 255, 0.75), rgba(255, 255, 255, 0) 70%); }
.shadow-thing { width: calc(46px * var(--k)); height: calc(46px * var(--k)); object-fit: contain; image-rendering: pixelated;
  filter: brightness(0) opacity(0.78); transition: filter 500ms ease; }
.shadow-spot.revealed .shadow-thing { filter: none; animation: live-hop 700ms cubic-bezier(0.2, 1.6, 0.4, 1); }
@media (prefers-reduced-motion: reduce) { .shadow-thing { transition: none; } .shadow-spot.revealed .shadow-thing { animation: none; } }

/* Teclado das Casas Coloridas: tecla de verdade (clara, letra grande) com uma pincelada de cor no alto */
.keyboard.skin-tinta { background: rgba(252, 248, 240, 0.93); border-radius: calc(6px * var(--k)); box-shadow: 0 calc(2px * var(--k)) 0 rgba(120, 90, 60, 0.35); }
.keyboard.skin-tinta .key { background: #fff; color: #1e1b26; font-size: calc(9.5px * var(--k)); border-color: #d6ccbb; border-top: calc(2.4px * var(--k)) solid var(--paint, #e5484d); }
.keyboard.skin-tinta .kb-row .key:nth-child(6n + 2) { --paint: #f2994a; }
.keyboard.skin-tinta .kb-row .key:nth-child(6n + 3) { --paint: #f2c94c; }
.keyboard.skin-tinta .kb-row .key:nth-child(6n + 4) { --paint: #4caf6a; }
.keyboard.skin-tinta .kb-row .key:nth-child(6n + 5) { --paint: #3d8bd9; }
.keyboard.skin-tinta .kb-row .key:nth-child(6n) { --paint: #9b5de5; }
.keyboard.skin-tinta .key.hint { background: #fff6cf; border-top-color: var(--target); }

/* ---------- Mundo 5: Pedidos (specs/19) ----------
   O morador chega pela direita até o balcão; o balão de pensamento mostra o que ele quer; a sacolinha voa do Polvim até
   ele; ele pula de alegria e vai embora. */
.order-game { position: absolute; left: 0; right: 0; top: 0; height: calc(216px * var(--k)); pointer-events: none; z-index: 1; }
.customer { position: absolute; left: calc(262px * var(--k)); top: calc(78px * var(--k)); width: calc(54px * var(--k)); height: calc(54px * var(--k));
  margin-left: calc(-27px * var(--k)); display: grid; place-items: end center; }
.customer-img { width: 100%; height: 100%; object-fit: contain; object-position: bottom; image-rendering: pixelated; }
.customer.arriving { animation: customer-in 650ms cubic-bezier(0.2, 0.8, 0.3, 1) both; }
.customer.happy .customer-img { animation: customer-hop 600ms cubic-bezier(0.2, 1.6, 0.4, 1); }
.customer.leaving { animation: customer-out 700ms ease-in forwards; }
@keyframes customer-in { from { transform: translateX(calc(150px * var(--k))); } }
@keyframes customer-out { to { transform: translateX(calc(170px * var(--k))); } }
@keyframes customer-hop { 40% { transform: translateY(calc(-14px * var(--k))) scale(1.1); } }
/* balão de pensamento (sem a arte do balão: desenhado em CSS) */
.wish { position: absolute; left: calc(186px * var(--k)); top: calc(80px * var(--k)); width: calc(44px * var(--k)); height: calc(38px * var(--k));
  display: grid; place-items: center; background: #fff; border: calc(1.4px * var(--k)) solid #2a2733; border-radius: 50%;
  box-shadow: 0 calc(2px * var(--k)) 0 rgba(18, 52, 90, 0.25); animation: wish-pop 300ms cubic-bezier(0.2, 1.6, 0.4, 1); }
.wish::before, .wish::after { content: ''; position: absolute; background: #fff; border: calc(1.2px * var(--k)) solid #2a2733; border-radius: 50%; }
.wish::before { width: calc(8px * var(--k)); height: calc(7px * var(--k)); right: calc(-2px * var(--k)); bottom: calc(-8px * var(--k)); }
.wish::after { width: calc(4px * var(--k)); height: calc(4px * var(--k)); right: calc(-7px * var(--k)); bottom: calc(-13px * var(--k)); }
.wish-img { width: calc(30px * var(--k)); height: calc(30px * var(--k)); object-fit: contain; image-rendering: pixelated; }
@keyframes wish-pop { from { transform: scale(0.3); opacity: 0; } }
/* com a arte do balão (passo 6): a nuvem de pixel por trás, sem o desenho de CSS */
.wish.art { background: none; border: 0; box-shadow: none; width: calc(56px * var(--k)); height: calc(46px * var(--k)); left: calc(180px * var(--k)); top: calc(72px * var(--k)); }
.wish.art::before, .wish.art::after { display: none; }
.wish-bg { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: contain; image-rendering: pixelated; transform: scaleX(-1); } /* as bolinhas apontam para o morador, à direita */
.wish.art .wish-img { position: relative; width: calc(28px * var(--k)); height: calc(28px * var(--k)); margin-top: calc(-6px * var(--k)); }
/* a sacolinha que o Polvim entrega */
.bag { position: absolute; left: calc(92px * var(--k)); top: calc(98px * var(--k)); width: calc(16px * var(--k)); height: calc(16px * var(--k)); }
.bag:not(:has(img)) { border-radius: calc(2px * var(--k)) calc(2px * var(--k)) calc(4px * var(--k)) calc(4px * var(--k)); background: #c99a5b; box-shadow: inset 0 calc(3px * var(--k)) 0 #b08045; }
.bag img { width: 100%; image-rendering: pixelated; }
.bag.flying { animation: bag-fly 600ms cubic-bezier(0.3, 0, 0.4, 1) forwards; }
@keyframes bag-fly { 50% { transform: translate(calc(80px * var(--k)), calc(-26px * var(--k))); } to { transform: translate(calc(158px * var(--k)), calc(-2px * var(--k))); opacity: 0.2; } }
.shop-polvim { position: absolute; left: calc(22px * var(--k)); top: calc(70px * var(--k)); width: calc(62px * var(--k)); image-rendering: pixelated; }
@media (prefers-reduced-motion: reduce) { .customer.arriving, .customer.leaving, .customer.happy .customer-img, .wish, .bag.flying { animation: none; } .customer.leaving { opacity: 0; } }

/* Bônus do Mundo 5: Correio da Ilha — pacote na esteira, escrito o nome, ele vai até a porta do correio */
.mail-game { position: absolute; left: 0; right: 0; top: 0; height: calc(216px * var(--k)); pointer-events: none; z-index: 1; }
.belt { position: absolute; left: calc(14px * var(--k)); right: calc(56px * var(--k)); top: calc(122px * var(--k)); height: calc(8px * var(--k));
  border-radius: calc(4px * var(--k)); background: repeating-linear-gradient(90deg, #6d6a75 0 calc(6px * var(--k)), #8e8a96 calc(6px * var(--k)) calc(12px * var(--k)));
  box-shadow: inset 0 calc(-2px * var(--k)) 0 rgba(0, 0, 0, 0.3); }
.belt.art { top: calc(118px * var(--k)); height: calc(14px * var(--k)); background: url(../assets/sprites/feira/esteira.png) 0 50% / auto 100% repeat-x; image-rendering: pixelated; box-shadow: none; }
.post-door { position: absolute; right: calc(8px * var(--k)); top: calc(78px * var(--k)); width: calc(44px * var(--k)); height: calc(52px * var(--k)); }
.post-door:not(.art) { border-radius: calc(16px * var(--k)) calc(16px * var(--k)) calc(2px * var(--k)) calc(2px * var(--k)); background: #3d7fc4; box-shadow: inset 0 0 0 calc(2px * var(--k)) #1f4f80; }
.post-door img { width: 100%; height: 100%; object-fit: contain; object-position: bottom; image-rendering: pixelated; }
.parcel { position: absolute; left: calc(110px * var(--k)); top: calc(86px * var(--k)); width: calc(40px * var(--k)); height: calc(36px * var(--k)); display: grid; place-items: center; }
.parcel:not(.art) { border-radius: calc(3px * var(--k)); background: #c99a5b; box-shadow: inset 0 0 0 calc(1.5px * var(--k)) #8a6232, inset 0 calc(-4px * var(--k)) 0 rgba(0, 0, 0, 0.15); }
.parcel-box { position: absolute; inset: 0; width: 100%; height: 100%; object-fit: contain; image-rendering: pixelated; }
.parcel-tag { position: relative; display: grid; place-items: center; width: calc(26px * var(--k)); height: calc(24px * var(--k)); background: #fffdf5; border-radius: calc(3px * var(--k));
  box-shadow: 0 0 0 calc(1px * var(--k)) #8a6232; }
.parcel-label { width: calc(20px * var(--k)); height: calc(20px * var(--k)); object-fit: contain; image-rendering: pixelated; }
.parcel.coming { animation: parcel-in 700ms cubic-bezier(0.2, 0.8, 0.3, 1) both; }
.parcel.sent { animation: parcel-out 1000ms cubic-bezier(0.5, 0, 0.7, 0.4) forwards; }
@keyframes parcel-in { from { transform: translateX(calc(-110px * var(--k))); } }
@keyframes parcel-out { 85% { transform: translateX(calc(212px * var(--k))); opacity: 1; } to { transform: translateX(calc(222px * var(--k))) scale(0.5); opacity: 0; } }
@media (prefers-reduced-motion: reduce) { .parcel.coming, .parcel.sent { animation: none; } .parcel.sent { opacity: 0; } }
/* Entrega da feira (realinhamento): a sacola vai na cesta de uma bicicleta até a casinha do morador (no lugar da esteira e do correio) */
.parcel.entrega { top: calc(68px * var(--k)); }
.parcel.entrega .bike { position: absolute; left: calc(-8px * var(--k)); bottom: calc(-24px * var(--k)); width: calc(56px * var(--k)); height: calc(40px * var(--k)); object-fit: contain; image-rendering: pixelated; }
.parcel.entrega.coming .bike, .parcel.entrega.sent .bike { animation: bike-pedal 320ms steps(2) infinite; }
@keyframes bike-pedal { 50% { transform: translateY(calc(-1px * var(--k))); } }
.post-door.house { top: calc(74px * var(--k)); width: calc(52px * var(--k)); height: calc(56px * var(--k)); }
@media (prefers-reduced-motion: reduce) { .parcel.entrega .bike { animation: none; } }

/* Teclado da Feira: tecla de verdade (clara, letra grande) com uma faixa de toldo listrado no alto */
.keyboard.skin-toldo { background: rgba(252, 248, 240, 0.93); border-radius: calc(6px * var(--k)); box-shadow: 0 calc(2px * var(--k)) 0 rgba(160, 60, 50, 0.35); }
.keyboard.skin-toldo .key { color: #1e1b26; font-size: calc(9.5px * var(--k)); border-color: #d6ccbb; border-top: 0;
  background: repeating-linear-gradient(90deg, #e2483d 0 calc(3px * var(--k)), #fff calc(3px * var(--k)) calc(6px * var(--k))) top / 100% calc(2.6px * var(--k)) no-repeat, #fff; }
.keyboard.skin-toldo .kb-row .key:nth-child(even) { background: repeating-linear-gradient(90deg, #2f86c9 0 calc(3px * var(--k)), #fff calc(3px * var(--k)) calc(6px * var(--k))) top / 100% calc(2.6px * var(--k)) no-repeat, #fff; }
.keyboard.skin-toldo .key.hint { background: repeating-linear-gradient(90deg, var(--target) 0 calc(3px * var(--k)), #fff calc(3px * var(--k)) calc(6px * var(--k))) top / 100% calc(2.6px * var(--k)) no-repeat, #fff6cf; }
/* Contar e digitar ("quantos barcos?"): a peça guarda o número até a criança acertar */
.tile.mystery { color: #9a92ad; border-style: dashed; }

/* ---------- Mundo 6: Subida do Farol (specs/20, o mundo vitrine) ----------
   Camadas: céu (pôr do sol → noite, por --night), estrelas, mar distante, a torre e as plataformas (sobem com a câmera,
   --cam), partículas. Sem a arte (prompts-de-arte/mundo-6.md): torre de faixas em CSS, plataformas de pedra em CSS. */
.tower-game { position: absolute; left: 0; right: 0; top: 0; height: calc(216px * var(--k)); overflow: hidden; pointer-events: none; z-index: 0; --night: 0; }
.tw-sky { position: absolute; inset: 0; background: linear-gradient(#ffb36b, #ff8a6b 40%, #c26aa0 75%, #6a5aa8); }
.tw-sky::after { content: ''; position: absolute; inset: 0; opacity: var(--night); transition: opacity 1.2s ease;
  background: linear-gradient(#0b1638, #1b2a5e 55%, #3a3f80); }
.tw-stars { position: absolute; inset: 0; opacity: var(--night); transition: opacity 1.2s ease;
  background-image: radial-gradient(1px 1px at 12% 18%, #fff 99%, transparent), radial-gradient(1px 1px at 28% 8%, #fff 99%, transparent),
    radial-gradient(1.5px 1.5px at 46% 22%, #fff7c2 99%, transparent), radial-gradient(1px 1px at 63% 12%, #fff 99%, transparent),
    radial-gradient(1px 1px at 78% 28%, #fff 99%, transparent), radial-gradient(1.5px 1.5px at 90% 10%, #fff 99%, transparent),
    radial-gradient(1px 1px at 8% 40%, #fff 99%, transparent), radial-gradient(1px 1px at 36% 36%, #fff 99%, transparent),
    radial-gradient(1px 1px at 70% 44%, #fff 99%, transparent), radial-gradient(1.5px 1.5px at 54% 4%, #fff 99%, transparent); }
.fx-normal .tw-stars, .fx-full .tw-stars { animation: twinkle 3.2s ease-in-out infinite; }
@keyframes twinkle { 50% { filter: brightness(1.5); } }
.tw-far { position: absolute; left: 0; right: 0; bottom: calc(-40px * var(--k)); width: 100%; height: calc(216px * var(--k)); object-fit: cover; image-rendering: pixelated;
  transform: translateY(calc(var(--py, 0) * 1px * var(--k))); transition: transform 600ms ease-out; filter: brightness(calc(1 - var(--night) * 0.55)) saturate(calc(1 - var(--night) * 0.3)); }
.tw-far-css { background: linear-gradient(transparent 55%, #4b7fb3 55%, #2f5c8c 80%, #3a6d4a 100%); }
.tw-world { position: absolute; left: 0; top: 0; width: calc(384px * var(--k)); height: 0; transform: translateY(calc(var(--cam, 128) * 1px * var(--k)));
  transition: transform 560ms cubic-bezier(0.3, 0.9, 0.4, 1); }
.tw-tower { position: absolute; left: calc(160px * var(--k)); width: calc(64px * var(--k)); top: calc(var(--h, 240) * -1px * var(--k)); height: calc((var(--h, 240) + 120) * 1px * var(--k));
  background: repeating-linear-gradient(#e2483d 0 calc(34px * var(--k)), #f6efe2 calc(34px * var(--k)) calc(68px * var(--k)));
  box-shadow: inset calc(-10px * var(--k)) 0 0 rgba(0, 0, 0, 0.18), inset calc(4px * var(--k)) 0 0 rgba(255, 255, 255, 0.25);
  filter: brightness(calc(1 - var(--night) * 0.35)); }
.tw-tower.art { left: calc(152px * var(--k)); width: calc(80px * var(--k)); background: url(../assets/cenarios/farol-torre.png) 50% 100% / 100% auto repeat-y; box-shadow: none; image-rendering: pixelated; }
.tw-floor { position: absolute; left: calc(var(--fx) * 1px * var(--k)); top: calc(var(--fy) * 1px * var(--k)); width: calc(42px * var(--k)); height: calc(8px * var(--k));
  transform: translateX(-50%); }
.tw-plat-css { position: absolute; inset: 0; border-radius: calc(2px * var(--k)); background: #a99a86; box-shadow: inset 0 calc(-3px * var(--k)) 0 #7d6f5d, 0 calc(2px * var(--k)) 0 rgba(0, 0, 0, 0.25); }
.tw-plat { position: absolute; left: 50%; top: calc(-6px * var(--k)); width: calc(48px * var(--k)); transform: translateX(-50%); image-rendering: pixelated; }
/* a placa com o número, em pé na plataforma (letra grande e clara, como as peças) */
.tw-sign { position: absolute; left: 50%; bottom: calc(100% + 1px * var(--k)); transform: translateX(-50%); min-width: calc(16px * var(--k)); height: calc(16px * var(--k));
  display: grid; place-items: center; padding: 0 calc(3px * var(--k)); border-radius: calc(3px * var(--k)); background: #fff8e6; color: #1e1b26;
  font: 800 calc(12px * var(--k))/1 var(--font); box-shadow: 0 0 0 calc(1.2px * var(--k)) #6b5a45, 0 calc(2px * var(--k)) 0 rgba(0, 0, 0, 0.3); }
.tw-sign.done { opacity: 0; transition: opacity 300ms ease; }
.tw-lamp { position: absolute; left: calc(192px * var(--k)); top: calc(var(--fy) * 1px * var(--k)); width: calc(10px * var(--k)); height: calc(10px * var(--k));
  transform: translate(-50%, -50%); border-radius: 50%; background: #5b5560; box-shadow: 0 0 0 calc(1.2px * var(--k)) #2a2733; }
.tw-lamp img { position: absolute; inset: calc(-4px * var(--k)); width: calc(18px * var(--k)); image-rendering: pixelated; }
.tw-lamp:has(img) { background: none; box-shadow: none; }
.tw-lamp.on { background: #ffe066; box-shadow: 0 0 0 calc(1.2px * var(--k)) #b8860b, 0 0 calc(10px * var(--k)) calc(3px * var(--k)) rgba(255, 220, 120, 0.75); }
.tw-lamp.on:has(img) { background: none; box-shadow: 0 0 calc(10px * var(--k)) calc(3px * var(--k)) rgba(255, 220, 120, 0.6); }
.tw-robot { position: absolute; left: calc(var(--rx) * 1px * var(--k)); top: calc(var(--ry) * 1px * var(--k)); width: calc(44px * var(--k)); height: calc(44px * var(--k));
  transform: translate(-50%, -96%); transition: left 560ms cubic-bezier(0.3, 0.9, 0.4, 1), top 560ms cubic-bezier(0.25, 1.35, 0.5, 1); z-index: 2; }
.tw-robot-img { width: 100%; height: 100%; object-fit: contain; object-position: bottom; image-rendering: pixelated; }
.tw-robot.jumping .tw-robot-img { animation: tw-stretch 560ms ease-out; }
@keyframes tw-stretch { 15% { transform: scale(1.15, 0.85); } 45% { transform: scale(0.88, 1.18); } 100% { transform: none; } }
/* o topo do farol: a sala da lâmpada e o feixe que varre o mar quando a luz religa */
.tw-top { position: absolute; left: calc(192px * var(--k)); top: calc(var(--fy, 0) * 1px * var(--k)); width: calc(80px * var(--k)); height: calc(194px * var(--k)); transform: translate(-50%, -82%); }
.tw-top img { display: block; width: 100%; filter: brightness(calc(1 - var(--night) * 0.3)); }
.tower-game.lit .tw-top img { filter: none; }
.tw-top img { width: 100%; image-rendering: pixelated; }
.tw-top-css { position: absolute; left: 25%; right: 25%; top: 10%; bottom: 0; border-radius: calc(14px * var(--k)) calc(14px * var(--k)) 0 0;
  background: linear-gradient(#8b2a2a 0 18%, #2a3a55 18% 52%, #e2483d 52% 70%, #f6efe2 70%); box-shadow: inset 0 0 0 calc(1.5px * var(--k)) #2a2733; }
.tw-beam { position: absolute; left: 50%; top: 32%; width: calc(380px * var(--k)); height: calc(60px * var(--k)); transform-origin: 0 50%; opacity: 0;
  background: linear-gradient(90deg, rgba(255, 236, 150, 0.9), rgba(255, 236, 150, 0)); clip-path: polygon(0 45%, 100% 0, 100% 100%, 0 55%); }
.tower-game.lit .tw-beam { opacity: 1; animation: tw-sweep 3.6s ease-in-out infinite alternate; }
.tower-game.fx-calm.lit .tw-beam { animation: none; transform: rotate(-12deg); }
@keyframes tw-sweep { from { transform: rotate(-35deg); } to { transform: rotate(35deg) scaleX(-1); } }
.fx-particles { position: absolute; inset: 0; width: 100%; height: 100%; image-rendering: pixelated; pointer-events: none; z-index: 3; }
.fx-shake { animation: fx-shake 260ms ease-out; }
@keyframes fx-shake { 25% { transform: translate(calc(1.5px * var(--k)), calc(-1px * var(--k))); } 50% { transform: translate(calc(-1.5px * var(--k)), calc(1px * var(--k))); } 75% { transform: translate(calc(1px * var(--k)), 0); } }
@media (prefers-reduced-motion: reduce) { .tw-world, .tw-robot, .tw-far, .tw-sky::after, .tw-stars { transition: none; } .tw-robot.jumping .tw-robot-img, .tw-stars { animation: none; } }

/* Teclado de madeira (Ponte das Frases): cada tecla uma tabuinha clara com a corda no alto; letra grande e escura */
.keyboard.skin-madeira { background: rgba(250, 240, 220, 0.94); border-radius: calc(6px * var(--k)); box-shadow: 0 calc(2px * var(--k)) 0 rgba(90, 52, 24, 0.35); }
.keyboard.skin-madeira .key { background: linear-gradient(#fdf4e2, #f3e0bd); color: #2a1608; font-size: calc(9.5px * var(--k)); border-color: #d9bf94;
  border-top: calc(2.4px * var(--k)) solid #a8743c; }
.keyboard.skin-madeira .key.support { background: linear-gradient(#f4efff, #e9e2ff); border-color: #a38eff; border-top-color: #a38eff; }
.keyboard.skin-madeira .key.hint { background: #fff3c4; border-top-color: var(--target); box-shadow: 0 0 calc(6px * var(--k)) rgba(255, 210, 63, 0.8); }
/* Teclado da noite (Farol): tecla clara com uma faixa luminosa amarela no alto; a dica acende como lâmpada */
.keyboard.skin-noite { background: rgba(240, 242, 252, 0.93); border-radius: calc(6px * var(--k)); box-shadow: 0 calc(2px * var(--k)) 0 rgba(30, 40, 90, 0.4); }
.keyboard.skin-noite .key { background: #fff; color: #1e1b26; font-size: calc(9.5px * var(--k)); border-color: #c8cbdc; border-top: calc(2.4px * var(--k)) solid #f2c94c; }
.keyboard.skin-noite .key.hint { background: #fff6cf; border-top-color: var(--target); box-shadow: 0 0 calc(6px * var(--k)) rgba(255, 210, 63, 0.8); }
/* Com a arte do Farol: o mar distante (com o próprio céu do pôr do sol) ocupa a tela inteira, sem a emenda com o céu
   do jogo; a noite é um véu azul por cima dele que vai fechando (--night); as estrelas ficam só no alto */
.tower-game.art .tw-far { top: 0; bottom: auto; height: calc(236px * var(--k)); object-fit: cover; object-position: 50% 100%; filter: none; }
.tw-dusk { position: absolute; inset: 0; background: linear-gradient(#0b1638, #16245a 60%, #1f2d66); mix-blend-mode: multiply; opacity: calc(var(--night) * 0.85); transition: opacity 1.2s ease; }
.tower-game.art .tw-stars { bottom: 45%; }
/* plataforma: só a pedra flutuante (a tabuleta de madeira da arte vira a placa do número) */
.tw-floor.art .tw-plat { top: calc(-21px * var(--k)); width: calc(46px * var(--k)); clip-path: inset(46% 0 0 0); }
.tw-floor.art .tw-sign { bottom: calc(100% + 13px * var(--k)); background: #d9893f; color: #2a1608; border-radius: calc(2px * var(--k));
  box-shadow: 0 0 0 calc(1.2px * var(--k)) #5a2f12, inset 0 calc(-2px * var(--k)) 0 #b8692a, 0 calc(2px * var(--k)) 0 rgba(0, 0, 0, 0.3); }
.tw-floor.art .tw-sign::after { content: ''; position: absolute; left: 50%; top: 100%; width: calc(3px * var(--k)); height: calc(9px * var(--k)); margin-left: calc(-1.5px * var(--k)); background: #7a4a22; }

/* Abertura do pacote estilo Yu-Gi-Oh! (Mundo 6 em diante, specs/20): enquanto a cerimônia acontece, o resto espera */
.reward-screen.packing > :not(.pack-ceremony) { visibility: hidden; }
.reward-screen { position: relative; }
.pack-ceremony { position: fixed; inset: 0; z-index: 30; border: 0; padding: 0; margin: 0; cursor: pointer; background: rgba(4, 8, 24, 0.86);
  display: grid; place-items: center; overflow: hidden; --u: min(1vh, 0.56vw); }
.pack-ceremony.gone { opacity: 0; transition: opacity 260ms ease; }
.pack-ceremony:focus-visible { outline: none; }
/* o holofote */
.cer-spot { position: absolute; inset: 0; background: radial-gradient(ellipse 30% 46% at 50% 52%, rgba(255, 246, 220, 0.24), rgba(255, 246, 220, 0) 70%),
  radial-gradient(ellipse 60% 60% at 50% 50%, rgba(40, 70, 140, 0.35), transparent 75%); animation: cer-breathe 3s ease-in-out infinite; }
@keyframes cer-breathe { 50% { opacity: 0.75; } }
/* o pacote: duas partes da mesma figura (tampa e corpo), para a tampa voar no rasgo */
.cer-pack { position: relative; width: calc(var(--u) * 34); aspect-ratio: 120 / 195; animation: cer-float 2.6s ease-in-out infinite, cer-enter 600ms cubic-bezier(0.2, 1.3, 0.4, 1) both;
  filter: drop-shadow(0 0 calc(var(--u) * 2) rgba(120, 220, 255, 0.55)); }
.cer-pack.gold { filter: drop-shadow(0 0 calc(var(--u) * 2.4) rgba(255, 210, 63, 0.9)); }
.cer-pack.gold .cer-pack-top, .cer-pack.gold .cer-pack-body { filter: sepia(0.9) saturate(2.6) hue-rotate(-14deg) brightness(1.12); }
@keyframes cer-enter { from { transform: translateY(calc(var(--u) * 60)) scale(0.6) rotate(-8deg); opacity: 0; } }
@keyframes cer-float { 50% { translate: 0 calc(var(--u) * -1.6); rotate: 1.5deg; } }
.cer-pack-top, .cer-pack-body { position: absolute; left: 0; right: 0; background: var(--pack) 0 0 / 100% auto no-repeat; image-rendering: pixelated; }
.cer-pack-top { top: 0; height: 17%; z-index: 2; }
.cer-pack-body { top: 17%; bottom: 0; background-position: 0 100%; }
/* o brilho holográfico passando (recortado pela figura do pacote) */
.cer-sheen { position: absolute; inset: 0; z-index: 3; pointer-events: none; mix-blend-mode: screen;
  background: linear-gradient(115deg, transparent 35%, rgba(255, 255, 255, 0.55) 48%, rgba(120, 230, 255, 0.35) 52%, transparent 65%) 0 0 / 300% 100%;
  -webkit-mask: var(--pack) 0 0 / 100% auto no-repeat; mask: var(--pack) 0 0 / 100% auto no-repeat; animation: cer-sheen 2.2s ease-in-out infinite; }
@keyframes cer-sheen { from { background-position: 120% 0; } to { background-position: -120% 0; } }
/* 2) o corte de luz atravessando o topo */
.cer-cut { position: absolute; left: 4%; top: 15%; height: calc(var(--u) * 0.9); width: 0; z-index: 4; border-radius: 99px;
  background: linear-gradient(90deg, #fff, #fff6c2, #fff); box-shadow: 0 0 calc(var(--u) * 2) #fff6c2, 0 0 calc(var(--u) * 5) rgba(255, 220, 120, 0.8); }
.stage-1 .cer-cut { width: 92%; transition: width 360ms cubic-bezier(0.6, 0, 0.4, 1); }
.stage-2 .cer-cut { width: 92%; opacity: 0; transition: opacity 200ms ease; }
.stage-2 .cer-pack-top, .stage-3 .cer-pack-top, .stage-4 .cer-pack-top { transform: translate(calc(var(--u) * 24), calc(var(--u) * -40)) rotate(38deg); opacity: 0;
  transition: transform 520ms cubic-bezier(0.3, 0.6, 0.4, 1), opacity 520ms ease 120ms; }
.stage-2 .cer-pack { animation: none; }
.stage-2 .cer-pack::after { content: ''; position: absolute; left: 10%; right: 10%; top: 10%; height: 30%; border-radius: 50%;
  background: radial-gradient(ellipse at 50% 0, rgba(255, 250, 220, 0.95), transparent 70%); animation: cer-burst 420ms ease-out both; }
@keyframes cer-burst { from { transform: scaleY(0.2); opacity: 0; } 40% { opacity: 1; } to { transform: scale(1.6, 2.4) translateY(-20%); opacity: 0; } }
.stage-3 .cer-pack, .stage-4 .cer-pack { transform: translateY(calc(var(--u) * 50)) scale(0.8); opacity: 0; transition: transform 500ms ease-in, opacity 400ms ease 100ms; animation: none; }
/* 3) a carta sobe virada, gira, o pilar de luz acende; 4) vira */
.cer-card { position: absolute; left: 50%; top: 50%; width: calc(var(--u) * 42); aspect-ratio: 5 / 7; perspective: calc(var(--u) * 120); z-index: 5;
  translate: -50% -50%; animation: cer-rise 800ms cubic-bezier(0.2, 1.1, 0.3, 1) both; }
@keyframes cer-rise { from { transform: translateY(calc(var(--u) * 26)) scale(0.5) rotate(-6deg); opacity: 0; } }
.cer-flip { position: relative; width: 100%; height: 100%; transform-style: preserve-3d; transition: transform 700ms cubic-bezier(0.3, 1.4, 0.5, 1); }
.stage-3 .cer-flip { animation: cer-spin 900ms ease-in-out; }
@keyframes cer-spin { 40% { transform: rotateY(-25deg) scale(1.04); } 70% { transform: rotateY(18deg); } }
.stage-4 .cer-flip { transform: rotateY(180deg); }
.cer-face { position: absolute; inset: 0; backface-visibility: hidden; display: grid; place-items: center; }
.cer-face.back img { width: 100%; height: 100%; image-rendering: pixelated; border-radius: calc(var(--u) * 1.4); box-shadow: 0 0 calc(var(--u) * 3) rgba(140, 200, 255, 0.6); }
.cer-face.front { transform: rotateY(180deg); }
.cer-face.front .sticker-card { width: 100%; }
.cer-pillar { position: absolute; left: 50%; top: -10%; bottom: -10%; width: calc(var(--u) * 26); translate: -50% 0; opacity: 0; z-index: 1; pointer-events: none;
  background: linear-gradient(90deg, transparent, var(--pc, rgba(255, 255, 255, 0.85)) 35%, #fff 50%, var(--pc, rgba(255, 255, 255, 0.85)) 65%, transparent);
  filter: blur(calc(var(--u) * 0.8)); }
.cer-pillar.r-comum { --pc: rgba(230, 240, 255, 0.7); } .cer-pillar.r-rara { --pc: rgba(110, 190, 255, 0.85); }
.cer-pillar.r-brilhante { --pc: rgba(255, 150, 230, 0.85); background: linear-gradient(90deg, transparent, #ff7ad9 25%, #ffd23f 40%, #fff 50%, #3fe3f2 60%, #a38eff 75%, transparent); }
.cer-pillar.r-lendaria { --pc: rgba(255, 205, 70, 0.95); width: calc(var(--u) * 40); }
.stage-3 .cer-pillar, .stage-4 .cer-pillar { opacity: 1; transition: opacity 500ms ease 250ms; animation: cer-pulse 1.4s ease-in-out infinite; }
@keyframes cer-pulse { 50% { filter: blur(calc(var(--u) * 0.8)) brightness(1.25); } }
.cer-rays { position: absolute; left: 50%; top: 50%; width: calc(var(--u) * 110); aspect-ratio: 1; translate: -50% -50%; opacity: 0; border-radius: 50%;
  background: repeating-conic-gradient(rgba(255, 220, 120, 0.32) 0 8deg, transparent 8deg 22deg); -webkit-mask: radial-gradient(circle, #000 25%, transparent 68%); mask: radial-gradient(circle, #000 25%, transparent 68%); }
.r-lendaria .cer-rays, .r-brilhante .cer-rays { opacity: 1; animation: cer-rays 9s linear infinite; }
@keyframes cer-rays { to { rotate: 360deg; } }
.cer-flash { position: absolute; inset: 0; background: #fff; opacity: 0; pointer-events: none; z-index: 6; }
.stage-4 .cer-flash { animation: cer-flash 520ms ease-out; }
.gold.stage-4 .cer-flash { background: #fff3c2; }
@keyframes cer-flash { 10% { opacity: 0.85; } to { opacity: 0; } }
.cer-hint { position: absolute; left: 50%; bottom: 8%; translate: -50% 0; color: #fff; font: 900 calc(var(--u) * 4) var(--font-ui); opacity: 0.85; animation: cer-hint 1.1s ease-in-out infinite; }
.stage-1 .cer-hint, .stage-2 .cer-hint, .stage-3 .cer-hint, .stage-4 .cer-hint { display: none; }
@keyframes cer-hint { 50% { translate: -50% calc(var(--u) * -1); opacity: 0.5; } }
.pack-ceremony.reduced *, .pack-ceremony.reduced { animation: none !important; transition: none !important; }

/* ---------- Mundo 6, bônus lendário: Voo da Baleia (specs/20, 4b) — desenhado no motor próprio (canvas.arcade) ---------- */
/* no final, o teclado sai devagar: o mar inteiro aparece para o salto da baleia */
.stage.fl-finale .keyboard { opacity: 0; transition: opacity 600ms ease; pointer-events: none; }
/* Motor próprio (engine/arcade.js): o canvas na resolução do pixel art, esticado para a cena, pixels nítidos */
canvas.arcade { position: absolute; left: 0; top: 0; width: calc(384px * var(--k)); height: calc(216px * var(--k)); image-rendering: pixelated; pointer-events: none; z-index: 0; }
/* a Ponte usa o palco inteiro (tela em pé: o mundo desce até o teclado, em vez de sobrar uma faixa vazia) */
canvas.arcade.bridge-game, canvas.arcade.dojo-game, canvas.arcade.duel-game, canvas.arcade.neon-game, canvas.arcade.tablet-game, canvas.arcade.school-game,
canvas.arcade.city-game, canvas.arcade.sea-game { height: calc(var(--stage-h) * 1px * var(--k)); }

/* Os números da rodada (faixas médio e grande, specs/22) */
.reward-stats { display: flex; gap: calc(6px * var(--k)); justify-content: center; font: 700 calc(7.5px * var(--k)) var(--font-ui, var(--font)); color: var(--tinta); }
.reward-stats .stat { background: rgba(255, 255, 255, 0.85); border-radius: calc(4px * var(--k)); padding: calc(1.5px * var(--k)) calc(5px * var(--k)); box-shadow: 0 calc(1px * var(--k)) 0 rgba(0, 0, 0, 0.12); }
.reward-stats .stat strong { font-weight: 900; }
.reward-stats .record { background: #ffd23f; color: #4a2208; font-weight: 900; animation: stat-pop 600ms cubic-bezier(0.2, 1.6, 0.4, 1) both 600ms; }
@keyframes stat-pop { from { transform: scale(0.3); opacity: 0; } }
@media (prefers-reduced-motion: reduce) { .reward-stats .record { animation: none; } }
/* "Pular" da história para os grandes (specs/22): discreto, no canto de cima */
.story-quick-skip { position: absolute; right: calc(8px * var(--k)); top: calc(8px * var(--k)); z-index: 8; border: 0; cursor: pointer;
  background: rgba(20, 24, 44, 0.55); color: #fff; font: 800 calc(7px * var(--k)) var(--font-ui, var(--font)); padding: calc(3px * var(--k)) calc(6px * var(--k));
  border-radius: calc(999px * var(--k)); }
.story-quick-skip:hover, .story-quick-skip:focus-visible { background: rgba(20, 24, 44, 0.8); }

/* Teclado do dojo (Mundo 8, specs/23): teclas laca escura com a faixa dourada; as teclas de acento em vermelho */
.keyboard.skin-dojo { background: rgba(14, 12, 34, 0.9); border-radius: calc(6px * var(--k)); box-shadow: 0 calc(2px * var(--k)) 0 rgba(0, 0, 0, 0.5), 0 0 0 calc(1px * var(--k)) rgba(212, 167, 74, 0.5); }
.keyboard.skin-dojo .key { background: linear-gradient(#2a2346, #1c1733); color: #f4ead2; font-size: calc(9.5px * var(--k)); border-color: #0c0a1c;
  border-top: calc(2.2px * var(--k)) solid #d4a74a; box-shadow: 0 calc(1.2px * var(--k)) 0 #07060f; }
.keyboard.skin-dojo .key.dead { background: linear-gradient(#7a1d2a, #571420); border-top-color: #ffd27a; font-size: calc(11px * var(--k)); }
/* o ´ sozinho é um risquinho: maior, para a criança achar a tecla */
.keyboard .key.dead[data-code=BracketLeft] .kb-t { font: 900 calc(26px * var(--k) * var(--fit, 1))/0.5 "Nunito", var(--font-ui, sans-serif); padding-top: calc(9px * var(--k)); }
.keyboard.skin-dojo .key.support { background: linear-gradient(#3b2a6e, #2a1f52); border-color: #a38eff; }
.keyboard.skin-dojo .key.hint { background: linear-gradient(#ffe7a0, #ffcf55); color: #1a1030; border-top-color: #fff; box-shadow: 0 0 calc(8px * var(--k)) rgba(255, 210, 90, 0.9); }
/* Dica em duas etapas (acento + letra): o número da etapa no canto; a 2ª etapa espera tracejada */
.keyboard .key[data-step] { position: relative; }
.keyboard .key[data-step]::after { content: attr(data-step); position: absolute; top: calc(-5px * var(--k)); right: calc(-4px * var(--k)); width: calc(9px * var(--k)); height: calc(9px * var(--k));
  border-radius: 50%; background: #ff4f7b; color: #fff; font: 900 calc(6.5px * var(--k))/calc(9px * var(--k)) var(--font-ui, sans-serif); text-align: center; box-shadow: 0 0 0 calc(1px * var(--k)) #fff; }
.keyboard .key.hint-next { outline: calc(1.4px * var(--k)) dashed #ffcf55; outline-offset: calc(1px * var(--k)); }
.keyboard .key.hint-shift { position: relative; }
.keyboard .key.hint-shift::before { content: '⇧ shift'; position: absolute; bottom: calc(-6px * var(--k)); left: 50%; transform: translateX(-50%); white-space: nowrap; z-index: 3;
  font: 800 calc(5.5px * var(--k))/1 var(--font-ui, sans-serif); color: #ffcf55; background: #1a1030; padding: calc(1px * var(--k)) calc(3px * var(--k)); border-radius: calc(999px * var(--k));
  box-shadow: 0 0 0 calc(0.8px * var(--k)) #ffcf55; }
.keyboard .key.armed { box-shadow: 0 0 0 calc(1.5px * var(--k)) #ff4f7b, 0 0 calc(8px * var(--k)) rgba(255, 79, 123, 0.8); }

/* Duelo sob a Lua: no golpe supremo, as peças e as pérolas saem de cena e o recado é escrito no céu, no lugar delas */
.stage.duel-sky .targets, .stage.duel-sky .pearls { opacity: 0; transition: opacity 400ms ease; }

/* Teclas com texto: o rótulo nunca sai da tecla (a tecla mede e encolhe a letra: --fit, onscreen-keyboard.js) */
.keyboard .key { white-space: nowrap; -webkit-tap-highlight-color: transparent; } /* tablet: sem o realce cinza do navegador no toque (o jogo tem o próprio) */
.keyboard .key .kb-t { font-size: calc(1em * var(--fit, 1)); }
.keyboard .key.word { font-weight: 700; letter-spacing: 0; }
/* Dois símbolos na mesma tecla, como na tecla de verdade (o de cima é com Shift) */
.keyboard .key.two, .keyboard.skin-dojo .key.two { display: flex; flex-direction: column; justify-content: center; align-items: center; gap: 0;
  font-size: calc(8px * var(--k)); line-height: 1; padding-top: calc(1px * var(--k)); }
.keyboard .key.two .kb-hi { font-size: calc(0.78em * var(--fit, 1)); opacity: 0.85; margin-bottom: calc(-0.5px * var(--k)); }
.keyboard .key.two .kb-lo { font-size: calc(0.95em * var(--fit, 1)); }
.keyboard .key.two.dead { font-size: calc(8.6px * var(--k)); line-height: 0.92; }
.keyboard .key.two.dead .kb-hi, .keyboard .key.two.dead .kb-lo { opacity: 1; font-size: calc(1em * var(--fit, 1)); }
/* Só desenho (tab, caps lock, shift, [ ] …): mais apagadas, não respondem ao toque */
.keyboard .key.inert { opacity: 0.5; cursor: default; }
.keyboard .key.inert.hint { opacity: 1; }
/* O teclado inteiro (MacBook, Mundo 8): as fileiras alinhadas nas duas pontas, cada tecla na largura de verdade */
.keyboard.full { left: calc(20px * var(--k)); right: calc(20px * var(--k)); align-items: stretch; }
.keyboard.full .kb-row { margin-left: 0; justify-content: center; }
.keyboard.full .key { width: calc((19px * var(--w, 1) + 2px * (var(--w, 1) - 1)) * var(--k)); }
.keyboard.full .key.space { width: calc(120px * var(--k)); }
.keyboard.full .key.word { font-size: calc(6px * var(--k)); }
/* Tablet só de toque: não há Shift — o circunflexo é tocar 2 vezes na tecla "~ ^" */
@media (pointer: coarse) and (not (any-pointer: fine)) { .keyboard .key.hint-shift::before { content: 'toque 2×'; } }

/* Pós-processamento em WebGL (Mundo 9): o canvas 2D desenha por baixo, invisível; o WebGL mostra o resultado no lugar */
canvas.post-src { opacity: 0; }
canvas.post { pointer-events: none; }

/* ---------- Distrito Neon (Mundo 9, specs/24) ---------- */
/* O MODELO: a palavra certa num painel holográfico; as peças que já estão certas na esteira vêm acesas */
.targets.neon-model { align-items: center; gap: calc(2px * var(--k)); flex-wrap: nowrap; padding: 0 calc(8px * var(--k)); }
.neon-model .model-label { font: 800 calc(7px * var(--k)) var(--font-ui, sans-serif); letter-spacing: 0.14em; text-transform: uppercase; color: #8ff3ff;
  text-shadow: 0 0 calc(4px * var(--k)) #28dcff; margin-right: calc(3px * var(--k)); }
.stage .targets.neon-model .tile { --s: calc(min(30px, 290px / var(--n, 4)) * var(--k)); font-size: calc(var(--s) * 0.7); border-radius: calc(var(--s) * 0.16); background: rgba(14, 10, 46, 0.82); color: #e8fbff;
  border: calc(1.2px * var(--k)) solid #28dcff; box-shadow: 0 0 calc(6px * var(--k)) rgba(40, 220, 255, 0.55), inset 0 0 calc(6px * var(--k)) rgba(40, 220, 255, 0.25); }
.stage .targets.neon-model .tile.special { font-size: calc(7px * var(--k)); color: #8ff3ff; }
.stage .targets.neon-model .tile.correct { background: rgba(10, 50, 40, 0.85); border-color: #3cffb4; color: #c8ffe9; box-shadow: 0 0 calc(6px * var(--k)) rgba(60, 255, 180, 0.6); }
.stage .targets.neon-model .tile.kept::after { display: none; }
.stage .targets.neon-model .tile.current { border-color: #ffd23f; box-shadow: 0 0 calc(9px * var(--k)) rgba(255, 210, 63, 0.9); animation: neon-pulse 1s ease-in-out infinite; }
/* a letra GRANDE do nome: marcada com ⇧ (precisa do Shift) */
.stage .targets.neon-model .tile.big { position: relative; }
.stage .targets.neon-model .tile.big::before { content: '⇧'; position: absolute; top: calc(-7px * var(--k)); left: 50%; transform: translateX(-50%); font: 900 calc(7px * var(--k))/1 var(--font-ui, sans-serif);
  color: #ffd23f; text-shadow: 0 0 calc(4px * var(--k)) #ffd23f; }
@keyframes neon-pulse { 50% { box-shadow: 0 0 calc(3px * var(--k)) rgba(255, 210, 63, 0.5); } }
/* quantas teclas faltam apagar (⌫ × 3): numa linha só dela, embaixo do modelo */
.stage .targets.neon-model .tile.gap { min-width: 0; width: calc(var(--s) * 0.5); padding: 0; border-color: transparent; background: none; box-shadow: none;
  color: #8ff3ff; font-size: calc(var(--s) * 0.55); align-items: end; padding-bottom: calc(var(--s) * 0.08); opacity: 0.85; }
.stage .targets.neon-model .tile.gap::after { display: none; }
.stage .targets.neon-model.xxlong .model-label { display: none; }
/* flutua logo abaixo do modelo, sem ocupar altura (a câmera mede o modelo; o selo fica por cima da cena) */
.erase-badge { position: absolute; left: 0; right: 0; top: calc(100% + 3px * var(--k)); display: flex; justify-content: center; z-index: 4; pointer-events: none; }
.erase-badge[hidden] { display: none; }
.erase-pill { padding: calc(2px * var(--k)) calc(8px * var(--k));
  border-radius: calc(999px * var(--k)); background: rgba(40, 6, 30, 0.88); color: #ffb3d9; font: 900 calc(9px * var(--k)) var(--font-ui, sans-serif);
  border: calc(1px * var(--k)) solid #ff3caa; box-shadow: 0 0 calc(8px * var(--k)) rgba(255, 60, 170, 0.7); animation: neon-pulse-pink 0.9s ease-in-out infinite; }
.erase-pill.retry { animation: retry 380ms ease; }
@keyframes neon-pulse-pink { 50% { box-shadow: 0 0 calc(3px * var(--k)) rgba(255, 60, 170, 0.4); } }
/* Caps Lock ligado (aviso, não erro) */
.caps-badge { position: absolute; right: calc(8px * var(--k)); top: calc(6px * var(--k)); z-index: 7; padding: calc(2px * var(--k)) calc(7px * var(--k));
  border-radius: calc(4px * var(--k)); background: #ffd23f; color: #3a2400; font: 900 calc(8px * var(--k)) var(--font-ui, sans-serif); box-shadow: 0 calc(1.5px * var(--k)) 0 #b58a00; }
/* o teclado do Distrito Neon: teclas de vidro escuro com borda de neon; o ⇧ em amarelo-elétrico */
.keyboard.skin-neon { background: rgba(10, 8, 30, 0.9); box-shadow: 0 0 0 calc(1px * var(--k)) rgba(40, 220, 255, 0.55), 0 0 calc(12px * var(--k)) rgba(255, 60, 170, 0.35); }
.keyboard.skin-neon .key { background: linear-gradient(#1c1640, #120d2c); color: #e8fbff; border-color: #070512; border-top: calc(1.6px * var(--k)) solid #28dcff;
  box-shadow: 0 calc(1.2px * var(--k)) 0 #05040d; font-size: calc(9.5px * var(--k)); }
.keyboard.skin-neon .key.dead { background: linear-gradient(#4a1040, #2e0a2a); border-top-color: #ff3caa; }
.keyboard.skin-neon .key.shift-key, .keyboard .key.shift-key { border-top-color: #ffd23f; color: #ffd23f; font-size: calc(11px * var(--k)); }
.keyboard .key.shift-key.armed { background: #ffd23f; color: #3a2400; box-shadow: 0 0 calc(8px * var(--k)) rgba(255, 210, 63, 0.9); }
.keyboard.skin-neon .key.hint { background: linear-gradient(#bff8ff, #4fe3ff); color: #071a2a; border-top-color: #fff; box-shadow: 0 0 calc(9px * var(--k)) rgba(40, 220, 255, 0.95); }
.keyboard.skin-neon .key.support { background: linear-gradient(#2a1f5e, #1b1440); border-color: #a38eff; }
.keyboard:not(.full) .key.shift-key { width: calc(30px * var(--k)); }
/* a barra de APRENDIZADO do Mega-Teclador (não é vida: ele aprende) */
.learn-meter { position: absolute; right: calc(8px * var(--k)); top: calc(8px * var(--k)); z-index: 5; display: grid; gap: calc(1.5px * var(--k)); justify-items: end; }
.learn-label { font: 900 calc(6px * var(--k)) var(--font-ui, sans-serif); letter-spacing: 0.14em; text-transform: uppercase; color: #8ff3ff; text-shadow: 0 0 calc(4px * var(--k)) #28dcff; }
.learn-bar { width: calc(70px * var(--k)); height: calc(6px * var(--k)); border-radius: calc(999px * var(--k)); background: rgba(10, 8, 30, 0.85);
  box-shadow: inset 0 0 0 calc(1px * var(--k)) #28dcff, 0 0 calc(6px * var(--k)) rgba(40, 220, 255, 0.5); overflow: hidden; }
.learn-fill { display: block; height: 100%; width: 0; background: linear-gradient(90deg, #ff3c6e, #ffd23f 50%, #28dcff); transition: width 300ms ease; }
.learn-meter.done .learn-fill { box-shadow: 0 0 calc(8px * var(--k)) #28dcff; }
/* o modelo do chefe fica no telão (desenhado): as peças do DOM seguem para o leitor de tela e os testes, invisíveis */
.stage .targets.neon-model.on-screen { opacity: 0; pointer-events: none; }
/* Mundo 9, prólogo: o recado bagunçado pelo vírus treme com glitch (canais de cor separados) */
.story-message .tile.glitch { color: #ff3caa; text-shadow: calc(-1px * var(--k)) 0 #28dcff, calc(1px * var(--k)) 0 #ff3caa; animation: glitch-key 0.6s steps(2) infinite; }
.story-message .tile.glitch:nth-child(3n) { animation-delay: -0.2s; } .story-message .tile.glitch:nth-child(3n + 1) { animation-delay: -0.4s; }
@keyframes glitch-key { 0% { transform: translate(0, 0); } 25% { transform: translate(calc(1px * var(--k)), calc(-1px * var(--k))); } 50% { transform: translate(calc(-1px * var(--k)), 0); } 75% { transform: translate(0, calc(1px * var(--k))) skewX(-6deg); } }
@media (prefers-reduced-motion: reduce) { .story-message .tile.glitch { animation: none; } }

/* A recompensa NUNCA sai da tela (Guilherme, 11/10/2026: os botões ficavam para fora em alguns aparelhos): coluna
   flexível em que título, números, contagem e botões ficam com o tamanho deles e a CARTA fica com o que sobra — a
   altura dela manda e a largura vem da proporção da carta. Sem medir nada em JavaScript. */
.reward-screen { display: flex; flex-direction: column; align-items: center; justify-content: center; overflow: hidden;
  padding: calc(4px * var(--k)) 0; box-sizing: border-box; }
.reward-screen > * { flex: 0 0 auto; }
.reward-screen > .reward-card { flex: 0 1 calc(84px * var(--k) * 1.5); min-height: calc(40px * var(--k)); display: flex; justify-content: center; }
.reward-screen.with-pass > .reward-card { flex-basis: calc(66px * var(--k) * 1.5); }
.reward-screen .reward-card > .sticker-card, .reward-screen.with-pass .reward-card > .sticker-card { width: auto; height: 100%; max-width: 90vw; }

/* ---------- Ilha do Tablet (Mundo 10, specs/25) ---------- */
canvas.arcade.tablet-game { image-rendering: auto; }
/* o teclado do TABLET: teclas claras e grandes, letras pequenas, ⇧ e ⌫ cinza, como o teclado de verdade */
.keyboard.tablet { left: calc(24px * var(--k)); right: calc(24px * var(--k)); background: rgba(210, 216, 228, 0.94); border-radius: calc(8px * var(--k));
  padding: calc(4px * var(--k)) calc(3px * var(--k)); gap: calc(3px * var(--k)); box-shadow: 0 calc(2px * var(--k)) calc(10px * var(--k)) rgba(20, 40, 80, 0.25); }
.keyboard.tablet .kb-row { margin-left: 0 !important; gap: calc(2.5px * var(--k)); }
.keyboard.tablet .kb-row:nth-child(2) { padding-left: calc(10px * var(--k)); }
.keyboard.tablet .key { width: calc(26px * var(--k)); height: calc(17px * var(--k)); border-radius: calc(4px * var(--k)); border: 0; background: #fff; color: #1b1f2a;
  box-shadow: 0 calc(1px * var(--k)) 0 rgba(60, 70, 90, 0.35); font: 500 calc(11px * var(--k))/1 -apple-system, "Helvetica Neue", Arial, sans-serif; position: relative; }
.keyboard.tablet .key.special, .keyboard.tablet .key.shift-key { width: calc(38px * var(--k)); background: #adb4c2; color: #1b1f2a; font-size: calc(12px * var(--k)); border-top: 0; }
.keyboard.tablet .key.space { width: calc(180px * var(--k)); }
.keyboard.tablet .key.shift-key.armed { background: #fff; color: #1b1f2a; }
.keyboard.tablet .key.hint { background: #fff3b0; outline: calc(1.6px * var(--k)) solid #3d8bff; }
.keyboard.tablet .key.pressed { background: #dfe4ee; transform: none; }
/* toque longo: "segura" na dica, e a lista de acentos que sobe em cima da letra */
.keyboard .key.hint-hold::before { content: 'segura'; position: absolute; top: calc(-9px * var(--k)); left: 50%; transform: translateX(-50%); white-space: nowrap;
  font: 800 calc(6px * var(--k))/1 var(--font-ui, sans-serif); color: #fff; background: #3d8bff; padding: calc(1.5px * var(--k)) calc(3px * var(--k)); border-radius: calc(999px * var(--k));
  animation: hold-pulse 0.9s ease-in-out infinite; }
@keyframes hold-pulse { 50% { transform: translateX(-50%) scale(1.15); } }
.keyboard .key.holding { background: #e8edf7; }
.kb-pop { position: absolute; bottom: calc(100% + 4px * var(--k)); left: 50%; transform: translateX(-50%); display: flex; gap: calc(2px * var(--k)); z-index: 20;
  padding: calc(3px * var(--k)); background: #fff; border-radius: calc(6px * var(--k)); box-shadow: 0 calc(3px * var(--k)) calc(10px * var(--k)) rgba(20, 30, 60, 0.35);
  animation: pop-up 160ms cubic-bezier(0.2, 1.4, 0.4, 1) both; }
.kb-opt { min-width: calc(24px * var(--k)); height: calc(26px * var(--k)); display: grid; place-items: center; border-radius: calc(4px * var(--k));
  font: 500 calc(15px * var(--k))/1 -apple-system, "Helvetica Neue", Arial, sans-serif; color: #1b1f2a; }
.kb-opt.hint { background: #fff3b0; outline: calc(1.4px * var(--k)) solid #3d8bff; }
.kb-opt.picked { background: #3d8bff; color: #fff; }
@keyframes pop-up { from { transform: translateX(-50%) translateY(calc(6px * var(--k))) scale(0.7); opacity: 0; } }
@media (prefers-reduced-motion: reduce) { .kb-pop, .keyboard .key.hint-hold::before { animation: none; } }
/* Ilha do Tablet: a frase longa cabe em até duas linhas de peças menores — o tablet (onde a frase aparece escrita, no
   app) fica com o espaço; com 3 linhas de peças grandes ele sumia lá embaixo (Guilherme, 12/10/2026) */
.stage.skin-tablet .targets.phrase { column-gap: calc(3px * var(--k)); row-gap: calc(2px * var(--k)); }
.stage.skin-tablet .targets.phrase .tile { --s: calc(15px * var(--k)); font-size: calc(11px * var(--k)); border-radius: calc(3px * var(--k)); }
.stage.skin-tablet .targets.phrase .tile.k-space { min-width: calc(15px * var(--k)); font-size: calc(4.5px * var(--k)); }
.stage.skin-tablet .targets.phrase .tile.k-period { font-size: calc(15px * var(--k)); }
.stage.skin-tablet .targets.phrase .word { gap: calc(1.5px * var(--k)); }
.stage.skin-tablet .targets .tile.correct::after { transform: scale(0.7); }

/* O recado como mensagem de app (Mundo 10): digitado nas linhas pautadas da tela desenhada, uma frase por linha,
   destinatário no campo "Para" e cursor piscando no fim (app-message.js). Pixels da cena × --k. */
.story-app { position: absolute; inset: 0; pointer-events: none; opacity: 0; transition: opacity var(--fade, 800ms) ease; }
.story.shown .story-app { opacity: 1; }
.app-msg { position: absolute; left: calc(var(--ax) * var(--uu)); top: calc(var(--ay) * var(--uu)); width: calc(var(--aw) * var(--uu));
  font: 700 calc(var(--af) * var(--uu)) / calc(var(--al) * var(--uu)) var(--font-ui); color: #183a63; text-align: left; overflow-wrap: break-word; }
.app-msg-to { position: absolute; left: calc(var(--ax) * var(--uu)); top: calc(var(--ay) * var(--uu)); transform: translateY(-50%);
  font: 700 calc(var(--af) * var(--uu)) / 1 var(--font-ui); color: #183a63; white-space: nowrap; }
.app-msg-to-label { color: #5b7fa6; font-weight: 600; }
.app-msg-caret { display: inline-block; width: calc(1.5 * var(--uu)); height: calc(var(--af) * 1.15 * var(--uu)); margin-left: calc(1 * var(--uu));
  vertical-align: -12%; background: #2f8fe8; animation: app-caret 1s steps(1) infinite; }
.app-msg.typing .app-msg-ch { opacity: 0; animation: app-type 1ms linear forwards; animation-delay: calc(700ms + var(--i) * 45ms); }
.app-msg.typing .app-msg-caret { opacity: 0; animation: app-type 1ms linear forwards, app-caret 1s steps(1) infinite;
  animation-delay: calc(700ms + var(--i) * 45ms), calc(700ms + var(--i) * 45ms); }
@keyframes app-type { to { opacity: 1; } }
@keyframes app-caret { 50% { visibility: hidden; } }
@media (prefers-reduced-motion: reduce) { .app-msg.typing .app-msg-ch, .app-msg.typing .app-msg-caret { animation: none; opacity: 1; } .app-msg-caret { animation: none; } }
.story-app { --uu: calc(1px * var(--k)); }

/* Mundo 11 (specs/30): os sinais nas peças — grandes, cada um com a cor do seu giz; o sinal ESCONDIDO é um espaço
   vazio que pulsa (a criança ouve a frase e decide) e, achado, salta */
.tile.k-mark { font-size: calc(22px * var(--k)); font-weight: 900; }
.tile.k-question { color: #c98a00; } .tile.k-exclamation { color: #d63a8a; } .tile.k-comma { color: var(--tinta); }
.tile.mark-slot { background: transparent; border: calc(2px * var(--k)) dashed #9db3c9; box-shadow: none; animation: mark-wait 1.4s ease-in-out infinite; }
.tile.mark-slot.current { border-color: #ffd23f; }
.tile.mark-found { animation: mark-found 0.45s cubic-bezier(0.3, 1.6, 0.5, 1); }
@keyframes mark-wait { 50% { transform: scale(0.92); opacity: 0.7; } }
@keyframes mark-found { 0% { transform: scale(0.4) rotate(-12deg); } 100% { transform: scale(1) rotate(0); } }
@media (prefers-reduced-motion: reduce) { .tile.mark-slot, .tile.mark-found { animation: none; } }

/* ---------- Escola da Ilha (Mundo 11, specs/30): a sala em 3D (luz suave, não pixelada) ---------- */
canvas.arcade.school-game { image-rendering: auto; }
/* a nota da rodada: o letreiro de giz cai no meio da sala */
.school-rank { position: absolute; left: 50%; top: 42%; translate: -50% -50%; z-index: 4; pointer-events: none; animation: school-rank 0.5s cubic-bezier(0.3, 1.6, 0.5, 1) both; }
.school-rank img { width: calc(88px * var(--k)); image-rendering: pixelated; filter: drop-shadow(0 calc(3px * var(--k)) calc(6px * var(--k)) rgba(0, 0, 0, 0.35)); }
@keyframes school-rank { 0% { scale: 2.4; opacity: 0; } 100% { scale: 1; opacity: 1; } }
@media (prefers-reduced-motion: reduce) { .school-rank { animation: none; } }
/* a entrada do chefe (o Apagador): a faixa com o close atravessa a tela */
.school-cutin { position: absolute; left: 0; right: 0; top: 34%; z-index: 5; pointer-events: none; display: flex; justify-content: center; animation: school-cutin 1.7s ease-in-out both; }
.school-cutin img { height: calc(96px * var(--k)); width: auto; max-width: 96%; image-rendering: pixelated; box-shadow: 0 calc(3px * var(--k)) calc(10px * var(--k)) rgba(0, 0, 0, 0.35); }
@keyframes school-cutin { 0% { translate: -100% 0; } 18%, 82% { translate: 0 0; } 100% { translate: 100% 0; } }
/* a carta escrita à mão no caderno (Mundo 11): tinta azul, levemente inclinada, a folha um pouco torta */
.app-msg.hand { rotate: var(--ar, 0deg); transform-origin: left top; font-family: var(--font-ui); font-style: italic; color: #1a2f78; letter-spacing: 0.02em; }
/* a escola: as peças da frase menores (a frase é longa e a sala precisa de espaço: o caderno e o quadro) */
.stage.school .targets.phrase { column-gap: calc(3px * var(--k)); row-gap: calc(2px * var(--k)); }
.stage.school .targets.phrase .tile { --s: calc(16px * var(--k)); font-size: calc(12px * var(--k)); border-radius: calc(3px * var(--k)); }
.stage.school .targets.phrase .tile.k-space { min-width: calc(16px * var(--k)); font-size: calc(4.5px * var(--k)); }
.stage.school .targets.phrase .tile.k-period, .stage.school .targets.phrase .tile.k-mark { font-size: calc(16px * var(--k)); }
/* o quadro é o modelo (Mundo 11): sem as peças de tecla em cima — a frase está no quadro-negro */
.stage.board-model .targets { display: none; }

/* ---------- Mundo 12: A Cidade (specs/31) — a rua em 3D, o celular de concha e o campo do modelo ---------- */
canvas.arcade.city-game, canvas.arcade.sea-game { image-rendering: auto; width: 100%; }
/* o MODELO: o campo de texto do celular, grande, colado em cima do teclado. O que escrever em cinza claro; o escrito escuro */
.phone-bar { position: absolute; z-index: 3; left: var(--pb-left, 3%); bottom: var(--pb-bottom, 40%); width: var(--pb-width, 70%);
  display: flex; align-items: center; gap: calc(4px * var(--k)); padding: calc(2.5px * var(--k)) calc(3.5px * var(--k)) calc(2.5px * var(--k)) calc(7px * var(--k));
  background: linear-gradient(180deg, rgba(255, 252, 255, 0.97), rgba(250, 238, 250, 0.95)); border-radius: calc(16px * var(--k));
  box-shadow: 0 calc(2px * var(--k)) calc(8px * var(--k)) rgba(60, 30, 90, 0.32), inset 0 0 0 calc(1.2px * var(--k)) rgba(196, 150, 230, 0.75);
  font: 800 calc(12.5px * var(--k))/1.15 var(--font); color: #1f2a44; pointer-events: none; }
.phone-bar.off { visibility: hidden; }
.phone-bar .pb-label { flex: none; font-size: calc(5.5px * var(--k)); font-weight: 900; color: #7a4fb0; text-transform: uppercase; letter-spacing: 0.04em;
  writing-mode: horizontal-tb; max-width: calc(46px * var(--k)); line-height: 1.1; }
.phone-bar .pb-field { flex: 1; min-width: 0; white-space: pre; overflow: hidden; display: flex; align-items: center; min-height: calc(17px * var(--k)); }
.phone-bar.long { font-size: calc(11px * var(--k)); }
.phone-bar.xlong { font-size: calc(9.5px * var(--k)); }
.phone-bar .pb-done { color: #1f2a44; }
.phone-bar .pb-rest { color: rgba(31, 42, 68, 0.3); }
.phone-bar .pb-next { color: rgba(31, 42, 68, 0.45); box-shadow: inset 0 calc(-2.2px * var(--k)) 0 #3d8bff; animation: pb-next 1s ease-in-out infinite; }
@keyframes pb-next { 50% { box-shadow: inset 0 calc(-2.2px * var(--k)) 0 rgba(61, 139, 255, 0.35); } }
.phone-bar .pb-caret { width: calc(1.6px * var(--k)); height: 1.1em; background: #3d8bff; border-radius: 1px; animation: pb-caret 1s steps(1, end) infinite; flex: none; }
@keyframes pb-caret { 50% { opacity: 0; } }
.phone-bar .pb-ear { display: none; margin-right: calc(4px * var(--k)); }
.phone-bar .pb-ear .px-icon { width: 1em; height: 1em; image-rendering: pixelated; display: block; }
.phone-bar.dictation .pb-ear { display: inline-grid; place-items: center; }
.phone-bar .pb-arrow { display: block; width: calc(9px * var(--k)); height: calc(9px * var(--k)); background-color: currentColor; margin-left: calc(1px * var(--k));
  -webkit-mask: url('../assets/sprites/cidade/enviar.svg') center / contain no-repeat; mask: url('../assets/sprites/cidade/enviar.svg') center / contain no-repeat; }
.phone-bar.dictation.empty .pb-field::after { content: 'escreva o que ouviu'; color: rgba(31, 42, 68, 0.28); font-size: 0.7em; margin-left: calc(4px * var(--k)); }
.phone-bar .pb-send { flex: none; display: grid; place-items: center; width: calc(20px * var(--k)); height: calc(20px * var(--k)); border-radius: 50%;
  background: #c9d6ee; color: #fff; font-size: calc(8px * var(--k)); transition: background 200ms; }
.phone-bar .pb-send small { font-size: calc(3.6px * var(--k)); font-weight: 900; margin-top: calc(-2px * var(--k)); }
.phone-bar.ready .pb-send { background: #3d8bff; animation: pb-send 0.9s ease-in-out infinite; }
@keyframes pb-send { 50% { box-shadow: 0 0 0 calc(5px * var(--k)) rgba(61, 139, 255, 0.28); scale: 1.08; } }
.phone-bar.ready .pb-next { box-shadow: none; }
.phone-bar.sent .pb-field { animation: pb-sent 0.45s ease-out; }
@keyframes pb-sent { 0% { translate: 0 0; opacity: 1; } 40% { translate: 0 calc(-14px * var(--k)); opacity: 0; } 41% { translate: 0 calc(8px * var(--k)); } 100% { translate: 0 0; opacity: 1; } }
.phone-bar .pb-field.shake { animation: pb-shake 0.36s ease-in-out; }
@keyframes pb-shake { 20%, 60% { translate: calc(-3px * var(--k)) 0; } 40%, 80% { translate: calc(3px * var(--k)) 0; } }
/* a escolha do presente (12.6): três botões grandes, por cima da rua (à esquerda do celular) */
.gift-choice { position: absolute; z-index: 4; left: var(--pb-left, 4%); width: var(--pb-width, 60%); bottom: var(--pb-bottom, 40%); top: var(--pb-top, 10%);
  display: flex; align-items: center; gap: calc(6px * var(--k)); justify-content: center; }
/* os três cartões têm SEMPRE o mesmo tamanho: a arte numa área igual e o nome numa faixa de duas linhas, centrado
   (um nome que quebra em duas linhas não desalinha os outros) */
.gift-option { flex: 1 1 0; min-width: 0; max-width: calc(78px * var(--k)); aspect-ratio: 0.86; display: grid; grid-template-rows: minmax(0, 1fr) 2.2em; justify-items: center; align-items: center;
  gap: calc(3px * var(--k)); padding: calc(6px * var(--k)) calc(4px * var(--k));
  border: calc(2px * var(--k)) solid rgba(255, 255, 255, 0.85); border-radius: calc(12px * var(--k)); background: rgba(255, 246, 252, 0.92); cursor: pointer;
  font: 900 calc(11px * var(--k))/1 var(--font); color: #4a2a7a; box-shadow: 0 calc(3px * var(--k)) calc(8px * var(--k)) rgba(60, 30, 90, 0.3); transition: transform 160ms, box-shadow 160ms; }
.gift-option img { width: 100%; height: 100%; max-width: calc(52px * var(--k)); max-height: calc(52px * var(--k)); min-height: 0; object-fit: contain; image-rendering: pixelated; }
.gift-option span { display: grid; place-items: center; height: 100%; text-align: center; line-height: 1.05; }
.gift-option.on, .gift-option:focus-visible { transform: translateY(calc(-4px * var(--k))) scale(1.08); border-color: #c36bff; box-shadow: 0 0 0 calc(3px * var(--k)) rgba(195, 107, 255, 0.45), 0 calc(6px * var(--k)) calc(12px * var(--k)) rgba(60, 30, 90, 0.35); }
.city-rank { position: absolute; left: 34%; top: 40%; translate: -50% -50%; z-index: 4; pointer-events: none; animation: school-rank 0.5s cubic-bezier(0.3, 1.6, 0.5, 1) both; }
.city-rank img { width: calc(80px * var(--k)); image-rendering: pixelated; filter: drop-shadow(0 calc(3px * var(--k)) calc(6px * var(--k)) rgba(0, 0, 0, 0.35)); }
@media (prefers-reduced-motion: reduce) { .city-rank, .phone-bar .pb-next, .phone-bar.ready .pb-send, .phone-bar .pb-caret { animation: none; } }

/* ---------- Mundo 12: O FINAL DA JORNADA (specs/31 seção 4) — o reencontro, a carta única, os créditos ---------- */
.finale { position: fixed; inset: 0; z-index: 50; background: #1a1430; overflow: hidden; font-family: var(--font); color: #fff; }
.stage.in-finale .keyboard, .stage.in-finale .pearls, .stage.in-finale .phone-bar, .stage.in-finale .control { visibility: hidden; }
.finale .fin-canvas { position: absolute; inset: 0; width: 100%; height: 100%; display: block; }
.finale .fin-canvas[hidden] { display: none; }
/* "Uma história escrita por {nome}": letra de mão que se escreve da esquerda para a direita */
.fin-title { position: absolute; left: 0; right: 0; top: 14%; display: grid; justify-items: center; gap: 0.6vh; text-align: center; pointer-events: none;
  text-shadow: 0 0.3vh 1.6vh rgba(120, 40, 90, 0.55); transform: rotate(-2deg); }
.fin-title span { font: italic 700 clamp(18px, 3.6vh, 40px)/1.1 var(--font); color: #fff7fb; }
.fin-title strong { font: italic 900 clamp(34px, 8vh, 96px)/1 var(--font); color: #fff; letter-spacing: 0.02em; }
.fin-title.writing span, .fin-title.writing strong { clip-path: inset(0 100% 0 0); animation: fin-write 2.6s cubic-bezier(0.5, 0, 0.3, 1) forwards; }
.fin-title.writing strong { animation-delay: 1.4s; animation-duration: 2.2s; }
@keyframes fin-write { to { clip-path: inset(0 0 0 0); } }
/* a cerimônia */
.fin-ceremony { position: absolute; inset: 0; display: grid; place-items: center; background: radial-gradient(ellipse at 50% 45%, rgba(255, 214, 236, 0.35), rgba(30, 14, 50, 0.82) 70%);
  opacity: 0; transition: opacity 1.2s ease; }
.fin-ceremony.in { opacity: 1; }
.fin-ceremony.glow { background: radial-gradient(ellipse at 50% 45%, rgba(255, 236, 246, 0.55), rgba(30, 14, 50, 0.82) 72%); }
.fin-card-stage { perspective: 1400px; display: grid; place-items: center; }
.fin-card.sticker-card.tica-card { width: min(72vw, 52vh); }
.fin-card.wrapped { opacity: 1; animation: fin-float 3s ease-in-out infinite; }
.fin-card.spinning { animation: fin-spin 1.7s cubic-bezier(0.22, 0.9, 0.3, 1.05) both; }
/* debaixo do lenço de cetim (cloth.js): parada (o pano está sobre ela) e invisível até o pano cobri-la */
.fin-card.under-cloth { opacity: 0; }
.fin-card.under-cloth.covered { opacity: 1; }
/* revelada: ela se ergue um pouco na direção de quem olha e volta, com o brilho atravessando */
.fin-card.revealed { animation: fin-reveal 1.6s cubic-bezier(0.2, 0.8, 0.25, 1) both; }
@keyframes fin-reveal { 0% { transform: translateY(0) scale(1); filter: brightness(1); } 35% { transform: translateY(-2.2vh) scale(1.07); filter: brightness(1.18); }
  100% { transform: translateY(0) scale(1); filter: brightness(1); } }
.fin-card.kept { animation: fin-keep 1s cubic-bezier(0.5, 0, 0.8, 0.2) forwards; }
@keyframes fin-float { 50% { translate: 0 -1.4vh; } }
@keyframes fin-spin { 0% { transform: rotateY(0deg) scale(0.96); } 60% { transform: rotateY(720deg) scale(1.08) translateY(-3vh); } 100% { transform: rotateY(1080deg) scale(1); } }
@keyframes fin-keep { to { transform: translate(38vw, 40vh) scale(0.12) rotate(12deg); opacity: 0; } }
.fin-cloth { position: absolute; inset: 0; width: 100%; height: 100%; pointer-events: none; z-index: 3; }
.fin-tica { position: absolute; left: 6%; bottom: 8%; height: min(26vh, 220px); image-rendering: pixelated; animation: fin-float 2.4s ease-in-out infinite; }
.fin-hint { position: absolute; bottom: 9%; left: 50%; translate: -50% 0; padding: 1vh 2.4vh; border-radius: 99px; background: rgba(255, 255, 255, 0.92); color: #7a3f8a;
  font: 900 clamp(16px, 3vh, 30px)/1 var(--font); animation: fin-pulse 1.4s ease-in-out infinite; }
@keyframes fin-pulse { 50% { scale: 1.06; } }
.fin-keep, .fin-end { font-size: clamp(16px, 3vh, 28px); padding: 1.4vh 3vh; }
.fin-keep { position: absolute; bottom: 5%; left: 50%; translate: -50% 0; animation: fin-pulse 1.6s ease-in-out infinite; }
/* os créditos */
.fin-credits { position: absolute; inset: 0; overflow: hidden; opacity: 0; animation: fin-in 1.5s ease forwards; }
.fin-credits.out { animation: fin-out 0.9s ease forwards; }
@keyframes fin-in { to { opacity: 1; } }
@keyframes fin-out { from { opacity: 1; } to { opacity: 0; } }
.fin-credits-bg { position: absolute; inset: -4%; background: var(--bg) 50% 88% / cover no-repeat; animation: fin-kenburns 60s ease-in-out forwards; }
.fin-credits-bg::after { content: ''; position: absolute; inset: 0; background: linear-gradient(180deg, rgba(40, 20, 70, 0.55), rgba(40, 20, 70, 0.15) 40%, rgba(40, 20, 70, 0.6)); }
@keyframes fin-kenburns { to { transform: scale(1.12) translateY(-2%); } }
.fin-roll { position: absolute; left: 50%; width: min(86vw, 720px); translate: -50% 0; top: 100%; display: grid; gap: 9vh; text-align: center; text-shadow: 0 0.3vh 1vh rgba(60, 20, 70, 0.8); }
.fin-credits.rolling .fin-roll { animation: fin-roll var(--roll, 48s) linear forwards; }
.fin-credits.calm .fin-roll { top: 6%; animation: none; max-height: 82%; overflow-y: auto; }
.fin-credits.calm .fin-thanks { top: 50%; }
@keyframes fin-roll { to { transform: translateY(calc(-100% - 100vh)); } }
.fin-roll h3 { margin: 0 0 2vh; font: 900 clamp(18px, 3.4vh, 34px)/1 var(--font); color: #ffe3f2; letter-spacing: 0.04em; }
.fin-hand { display: grid; gap: 1vh; transform: rotate(-2deg); }
.fin-hand span { font: italic 700 clamp(18px, 3.6vh, 38px)/1.1 var(--font); }
.fin-hand strong { font: italic 900 clamp(34px, 9vh, 100px)/1 var(--font); }
.fin-recado { display: flex; flex-wrap: wrap; justify-content: center; gap: 0.8vh; }
.fin-recado .keycap { font: 900 clamp(14px, 2.6vh, 26px)/1 var(--font); padding: 0.7vh 1.1vh; border-radius: 0.8vh; background: #fffdf6; color: #2a2340; text-shadow: none; box-shadow: 0 0.4vh 0 #c9b8d8; }
.fin-arrow { font-size: 4vh; margin: 1vh 0; }
.fin-letter { display: inline-grid; justify-self: center; gap: 0.6vh; padding: 2.4vh 3.6vh; border-radius: 1.6vh; background: rgba(255, 252, 244, 0.95); color: #1f3b6e; text-shadow: none;
  font: italic 800 clamp(16px, 3vh, 30px)/1.25 var(--font); transform: rotate(-1deg); }
.fin-letter p { margin: 0; }
.fin-stats { list-style: none; margin: 0; padding: 0; display: grid; gap: 1.4vh; font: 800 clamp(16px, 3vh, 30px)/1.2 var(--font); }
.fin-stats strong { font-size: 1.5em; color: #ffe08a; }
.fin-parade img { width: 100%; image-rendering: pixelated; animation: fin-parade 2s ease-in-out infinite alternate; }
@keyframes fin-parade { to { translate: 0 -0.8vh; } }
.fin-names { font: 700 clamp(14px, 2.4vh, 24px)/1.4 var(--font); margin: 1.6vh 0 0; }
.fin-thanks { position: absolute; left: 50%; top: 38%; translate: -50% -50%; width: min(86vw, 720px); text-align: center; text-shadow: 0 0.3vh 1.2vh rgba(60, 20, 70, 0.85); animation: fin-in 2.4s ease both; }
.fin-thanks p { font: 800 clamp(16px, 3vh, 30px)/1.3 var(--font); margin: 0 0 4vh; }
.fin-thanks .fin-big { font: italic 900 clamp(48px, 12vh, 140px)/1 var(--font); color: #fff; }
.fin-end { position: absolute; bottom: 7%; left: 50%; translate: -50% 0; z-index: 2; }
.finale-resume { position: fixed; inset: 0; display: grid; place-content: center; justify-items: center; gap: 3vh; background: radial-gradient(ellipse at 50% 40%, #ffd6ec, #4a2a7a); }
.finale-resume img { height: min(34vh, 280px); image-rendering: pixelated; }
@media (prefers-reduced-motion: reduce) {
  .fin-card.wrapped, .fin-tica, .fin-hint, .fin-keep, .fin-credits-bg, .fin-parade img { animation: none; }
  .fin-card.spinning, .fin-card.revealed { animation-duration: 0.01s; }
  .fin-title.writing span, .fin-title.writing strong { animation: none; clip-path: none; }
}
.finale-host { --k: 2.6; }

/* Mundo 12: a pintura é a protagonista — o teclado da tela fica compacto (teclas mais baixas, letra menor, sem crescer),
   para a cena ter pelo menos metade da altura mesmo numa janela larga e baixa */
.stage.city .keyboard { padding: calc(2.5px * var(--k)) calc(3px * var(--k)); gap: calc(1.5px * var(--k)); bottom: calc(2px * var(--k)); }
.stage.city .kb-row { gap: calc(1.5px * var(--k)); }
.stage.city .key { width: calc(18px * var(--k)); height: calc(11px * var(--k)); font-size: calc(6.5px * var(--k)); border-radius: calc(2.2px * var(--k)); }
.stage.city .key.space { width: calc(100px * var(--k)); }
.stage.city .keyboard.grown { transform: translateX(-50%) scale(var(--kbs, 1)); }
/* Cidade: as pérolas do progresso numa cápsula de vidro, no centro da área livre (nunca manchas cinzas soltas na pintura) */
.stage.city .pearls { left: var(--free-cx, 38%); right: auto; translate: -50% 0; top: calc(5px * var(--k)); gap: calc(3px * var(--k)); z-index: 3;
  padding: calc(2.5px * var(--k)) calc(6px * var(--k)); border-radius: 999px; background: rgba(30, 20, 60, 0.32);
  box-shadow: inset 0 0 0 calc(0.8px * var(--k)) rgba(255, 255, 255, 0.35), 0 calc(1px * var(--k)) calc(4px * var(--k)) rgba(20, 10, 40, 0.25);
  -webkit-backdrop-filter: blur(6px) saturate(1.2); backdrop-filter: blur(6px) saturate(1.2); }
.stage.city .pearl { width: calc(9px * var(--k)); filter: grayscale(0.85) brightness(1.15); opacity: 0.55; }
.stage.city .pearl.lit { filter: none; opacity: 1; }
/* o ABNT2 inteiro na Cidade: as larguras de verdade (o compacto da Cidade tem tecla 18 e espaço 1,5) */
.stage.city .keyboard.full .key { width: calc((18px * var(--w, 1) + 1.5px * (var(--w, 1) - 1)) * var(--k)); }
.stage.city .keyboard.full .key.space { width: calc(110px * var(--k)); }
/* o Enter do ABNT2: a tecla alta em L (a parte de cima, mais larga, e a de baixo desenhadas como uma tecla só) */
.keyboard.full .key[data-code="Enter-top"] { position: relative; z-index: 2; border-bottom-left-radius: 0; border-bottom-right-radius: 0; border-bottom-color: transparent; box-shadow: none; }
.keyboard.full .key[data-code="Enter-top"]::after { content: ''; position: absolute; right: -1px; width: calc(100% * 1.25 / 1.5 + 1px); top: calc(100% - 1px); height: calc(5px * var(--k));
  background: inherit; border: inherit; border-top: 0; border-bottom: 0; border-radius: 0; }
.keyboard.full .key[data-code="Enter-top"] ~ .key, .keyboard.full .kb-row .key[data-code="Enter"] { border-top-left-radius: 0; border-top-right-radius: 0; }
/* O teclado de verdade desde o 1º mundo: a tecla que a criança ainda não usa fica no lugar dela, apagada (acende quando
   o mundo a traz; na dica, acesa) */
.keyboard .key.off { opacity: 0.32; filter: saturate(0.3); box-shadow: none; }
.keyboard .key.off.hint { opacity: 1; filter: none; }
/* os telhados da Vila (Mundo 2): as casinhas no tamanho do teclado inteiro (a fileira tem 4 de espaço) */
.keyboard.full.skin-vila .key { width: calc((19px * var(--w, 1) + 4px * (var(--w, 1) - 1)) * var(--k)); }
.keyboard.full.skin-vila .key.space { width: calc(120px * var(--k)); }
/* Dois símbolos na tecla: um em cima do outro, juntinhos e sempre DENTRO da tecla (o teclado mede a altura também e
   encolhe os dois até caberem: --fit, onscreen-keyboard.js) */
.keyboard .key.two, .keyboard.skin-dojo .key.two, .keyboard .key.two.dead { overflow: hidden; padding: 0; line-height: 0.95; }
.keyboard .key.two .kb-hi, .keyboard .key.two .kb-lo { display: block; margin: 0; }
.keyboard .key.two.dead .kb-hi, .keyboard .key.two.dead .kb-lo { line-height: 0.7; }
/* rever o reencontro (depois do fim): o botão de sair, discreto, no canto */
.fin-skip { position: absolute; top: 2.5vh; right: 2.5vh; z-index: 20; border: 0; background: rgba(255, 255, 255, 0.85); border-radius: 50%; width: 6vh; height: 6vh;
  display: grid; place-items: center; cursor: pointer; box-shadow: 0 0.4vh 1.2vh rgba(40, 20, 60, 0.3); }
.fin-skip .px-badge { width: 70%; height: 70%; }

/* O BALÃO DE FALA do episódio do reencontro (specs/34 seção 2): papel creme chapado, contorno preto grosso de tinta (o
   mesmo dos personagens), sombra dura de desenho, o retrato de quem fala e a plaquinha do nome na cor de cada um.
   Anda com a câmera (--x, --y, --ponta: fala.js); o retrato pulsa no ritmo da voz (--vol). */
.fin-fala { --tinta: #1c1412; --papel: #fff4dc; --cor: #ff7a4d; --cor-clara: #ffd9c4; --nome: url("../assets/sprites/episodio/balao/nome-polvim.webp");
  position: absolute; left: 0; top: 0; z-index: 12; pointer-events: none; transform: translate(var(--x, -999px), var(--y, -999px));
  font-size: clamp(14px, 2.8vmin, 32px); }
.fin-fala[data-quem="tica"] { --cor: #86c440; --cor-clara: #e4f5cc; --nome: url("../assets/sprites/episodio/balao/nome-tica.webp"); }
.fin-fala-balao { position: relative; min-width: 11em; max-width: min(19em, 70vw); padding: 1.15em 1.5em 1.05em 4.5em; border-radius: 1.6em;
  background: var(--papel) url("../assets/sprites/episodio/balao/papel.webp") 0 0 / 9em 9em repeat; border: 0.26em solid var(--tinta);
  box-shadow: 0.32em 0.36em 0 rgba(28, 20, 18, 0.38); transform-origin: var(--ponta, 50%) 115%; }
/* o retrato: a moldura redonda saindo da ponta esquerda do balão; pulsa com a voz */
.fin-fala-retrato { position: absolute; left: -2.4em; top: 50%; translate: 0 -55%; width: 5.9em; height: 5.9em; border-radius: 50%; overflow: hidden;
  background: radial-gradient(circle at 50% 40%, var(--cor-clara) 0 55%, var(--cor) 56%); border: 0.26em solid var(--tinta);
  box-shadow: 0.24em 0.28em 0 rgba(28, 20, 18, 0.38); scale: calc(1 + var(--vol, 0) * 0.07); }
.fin-fala-retrato img { position: absolute; left: 50%; bottom: -4%; width: 108%; translate: -50% calc(var(--vol, 0) * -0.25em); }
/* a plaquinha do nome, inclinada em cima da borda */
.fin-fala-nome { position: absolute; top: -1.25em; left: 3.7em; height: 2.05em; padding: 0 1.25em; display: grid; place-items: center; rotate: -3deg;
  background: var(--nome) center / 100% 100% no-repeat; font: 700 1.1em/1 'Fredoka', var(--font-ui), sans-serif; color: #fff; letter-spacing: 0.03em;
  -webkit-text-stroke: 0.09em var(--tinta); paint-order: stroke fill; }
.fin-fala-texto { margin: 0.35em 0 0; font: 900 1.45em/1.18 'Nunito', var(--font-ui), sans-serif; color: var(--tinta); letter-spacing: 0.005em; }
.fin-fala-texto .w { display: inline-block; white-space: nowrap; }
.fin-fala-texto .l { opacity: 0; display: inline-block; white-space: pre; }
.fin-fala-texto .l.sp { display: inline; white-space: normal; }
.fin-fala-texto .l.on { opacity: 1; animation: fin-letra 0.16s ease-out both; }
.fin-fala-seta { position: absolute; right: 0.8em; bottom: 0.4em; width: 1.15em; opacity: 0; }
.fin-fala.fim .fin-fala-seta { opacity: 1; animation: fin-seta 0.7s ease-in-out infinite; }
/* a pontinha (o mesmo papel e a mesma tinta) */
.fin-fala-ponta { position: absolute; left: var(--ponta, 50%); bottom: -0.88em; width: 1.5em; height: 1.5em; translate: -50% 0; rotate: 45deg;
  background: var(--papel) url("../assets/sprites/episodio/balao/papel.webp") 0 0 / 9em 9em repeat;
  border-right: 0.26em solid var(--tinta); border-bottom: 0.26em solid var(--tinta); border-bottom-right-radius: 0.4em; }
/* a narradora: uma legenda embaixo, sem retrato e sem pontinha */
.fin-fala.narra .fin-fala-balao { padding: 0.7em 1.5em; max-width: min(26em, 86vw); border-radius: 1em; text-align: center; }
.fin-fala.narra .fin-fala-texto { margin: 0; font-size: 1.3em; font-style: italic; }
/* a entrada (um pulinho), a saída (encolhe) */
.fin-fala.in .fin-fala-balao { animation: fin-fala-in 0.42s cubic-bezier(0.3, 1.6, 0.5, 1) both; }
.fin-fala.in .fin-fala-retrato { animation: fin-retrato-in 0.5s 0.08s cubic-bezier(0.3, 1.7, 0.5, 1) both; }
.fin-fala.out .fin-fala-balao { animation: fin-fala-out 0.22s ease-in forwards; }
.fin-fala.calm.out .fin-fala-balao { animation: fin-out 0.22s ease forwards; }
@keyframes fin-fala-in { from { scale: 0.4; opacity: 0; } 60% { opacity: 1; } to { scale: 1; opacity: 1; } }
@keyframes fin-retrato-in { from { scale: 0.3; rotate: -14deg; } to { scale: 1; rotate: 0deg; } }
@keyframes fin-fala-out { to { scale: 0.5; opacity: 0; } }
@keyframes fin-letra { from { translate: 0 0.25em; scale: 0.6; } to { translate: 0 0; scale: 1; } }
@keyframes fin-seta { 0%, 100% { translate: 0 0; } 50% { translate: 0 0.28em; } }

/* A CARTELA DE ABERTURA do episódio ("Polvim em: O Reencontro"), como nos desenhos de TV: raios girando, o título com
   contorno de tinta e os dois entrando pelos lados. */
.ep-titulo { position: absolute; inset: 0; z-index: 14; overflow: hidden; display: grid; place-items: center; background: #ff9a52; }
.ep-titulo.sai { animation: fin-out 0.35s ease forwards; }
.ep-raios { position: absolute; left: 50%; top: 50%; width: 260vmax; height: 260vmax; translate: -50% -50%;
  background: repeating-conic-gradient(from 0deg, #ffb35c 0deg 9deg, #ff8a4f 9deg 18deg); animation: ep-gira 24s linear infinite; }
.ep-titulo::after { content: ''; position: absolute; inset: 0; background: radial-gradient(circle at 50% 50%, rgba(255, 244, 220, 0.25) 0 16%, rgba(255, 244, 220, 0) 42%, rgba(60, 20, 40, 0.4) 100%); }
.ep-nome { position: relative; z-index: 2; display: grid; justify-items: center; gap: 0.6vh; font-family: 'Fredoka', var(--font-ui), sans-serif;
  color: #ffe15a; -webkit-text-stroke: 0.11em #1c1412; paint-order: stroke fill; text-shadow: 0.07em 0.1em 0 #1c1412;
  animation: ep-pula 0.7s cubic-bezier(0.3, 1.7, 0.5, 1) both; }
.ep-nome span { font-size: clamp(24px, 6vh, 60px); font-weight: 700; color: #fff8e6; }
.ep-nome strong { font-size: clamp(40px, min(13vh, 10.5vw), 150px); font-weight: 700; line-height: 0.95; letter-spacing: 0.01em; rotate: -3deg; }
.ep-pol, .ep-tica { position: absolute; z-index: 1; bottom: 4vh; height: min(42vh, 27vw); }
.ep-pol { left: 4vw; animation: ep-entra-e 0.8s 0.35s cubic-bezier(0.3, 1.5, 0.5, 1) both, ep-bob 1.2s 1.2s ease-in-out infinite; }
.ep-tica { right: 4vw; animation: ep-entra-d 0.8s 0.5s cubic-bezier(0.3, 1.5, 0.5, 1) both, ep-bob 1.2s 1.4s ease-in-out infinite; }
@keyframes ep-gira { to { rotate: 360deg; } }
@keyframes ep-pula { from { scale: 0.2; opacity: 0; } to { scale: 1; opacity: 1; } }
@keyframes ep-entra-e { from { translate: -60vw 0; } to { translate: 0 0; } }
@keyframes ep-entra-d { from { translate: 60vw 0; } to { translate: 0 0; } }
@keyframes ep-bob { 0%, 100% { translate: 0 0; } 50% { translate: 0 -1.6vh; } }
/* a íris (o círculo que abre e fecha a cena): o raio vem do código (iris.js) */
.ep-iris { position: absolute; inset: 0; z-index: 13; pointer-events: none; background: #120c1c;
  -webkit-mask: radial-gradient(circle at var(--ix, 50%) var(--iy, 50%), transparent var(--r, 0px), #000 calc(var(--r, 0px) + 1px));
  mask: radial-gradient(circle at var(--ix, 50%) var(--iy, 50%), transparent var(--r, 0px), #000 calc(var(--r, 0px) + 1px)); }
/* o fundo vivo dos créditos: os dois sentados vendo o mar (a última cena do episódio, continuando) */
.fin-credits-bg.live { inset: 0; animation: none; }
.fin-credits.out-text > :not(.fin-credits-bg) { animation: fin-out 0.5s ease forwards; }
.fin-credits-bg.live .fin-live, .fin-credits-bg.live .fin-canvas { position: absolute; inset: 0; width: 100%; height: 100%; }
@media (prefers-reduced-motion: reduce) {
  .fin-fala .fin-fala-balao, .fin-fala .fin-fala-retrato, .fin-fala-texto .l.on, .fin-fala.fim .fin-fala-seta { animation: none; }
  .ep-raios, .ep-nome, .ep-pol, .ep-tica { animation: none; }
}
