:root {
  --pink: #ff5d8f;
  --purple: #7a4ec7;
  --cream: #fff6fb;
  --panel-font: clamp(15px, 4.2vw, 22px);
  --label-font: clamp(9px, 2.4vw, 12px);
  font-family: 'Fredoka', 'Trebuchet MS', 'Verdana', system-ui, sans-serif;
}

* { box-sizing: border-box; }

html, body {
  margin: 0;
  height: 100%;
  overflow: hidden;
  overscroll-behavior: none;
  background: #bfe9ff;
  -webkit-tap-highlight-color: transparent;
  -webkit-text-size-adjust: 100%;
}

#stage { position: fixed; inset: 0; }
#scene { display: block; width: 100%; height: 100%; touch-action: none; }

/* --- HUD ------------------------------------------------------------- */
#hud {
  --hud-button: clamp(44px, 12vw, 56px);
  --hud-rush: clamp(42px, 11.5vw, 54px);        /* altura do ⚡ */
  --hud-rush-largura: clamp(100px, 27vw, 132px); /* e a largura dele */
  --hud-gap: clamp(5px, 1.6vw, 10px);
  position: absolute;
  top: calc(10px + env(safe-area-inset-top));
  left: calc(10px + env(safe-area-inset-left));
  right: calc(10px + env(safe-area-inset-right));
  display: flex;
  /* Cada painel fica com a altura do próprio conteúdo. Sem isto o flex
     estica todos até a altura do mais alto — e o grupo de controles, com
     três linhas (pause/som, ⚡ e velocímetro), esticava a fileira inteira. */
  align-items: flex-start;
  gap: var(--hud-gap);
  pointer-events: none;
  transition: opacity .3s;
}
#hud.dim { opacity: .25; }

/* Cada modo mostra só os painéis que fazem sentido nele. */
#hud[data-mode='baby'] .panel.lives,
#hud[data-mode='baby'] .panel.level,
#hud[data-mode='baby'] .panel.keys,
#hud[data-mode='adventure'] .panel.goal,
#hud[data-mode='adventure'] .panel.level,
#hud[data-mode='tutorial'] .panel.goal,
#hud[data-mode='tutorial'] .panel.level,
#hud[data-mode='levels'] .panel.goal,
#hud[data-mode='levels'] .panel.hearts { display: none; }

/* Pontos e Distância, empilhados: um item só na fileira do HUD, mas com
   Distância sempre na linha logo abaixo de Pontos — não depende de quantos
   outros painéis o modo mostra, nem de a fileira quebrar linha ou não. */
.hud-stack {
  display: flex;
  flex-direction: column;
  gap: var(--hud-gap);
}

.panel {
  background: rgba(255, 255, 255, .82);
  border: 3px solid #fff;
  border-radius: 16px;
  padding: 4px clamp(6px, 2vw, 14px);
  min-width: clamp(58px, 17vw, 96px);
  display: flex;
  flex-direction: column;
  align-items: center;
  color: var(--purple);
  font-size: var(--panel-font);
  font-weight: 700;
  line-height: 1.15;
  white-space: nowrap;
  box-shadow: 0 5px 0 rgba(122, 78, 199, .18);
}
.panel .label {
  font-size: var(--label-font);
  letter-spacing: .06em;
  text-transform: uppercase;
  opacity: .65;
  font-weight: 600;
}
.panel.pop { animation: pop .28s ease-out; }
@keyframes pop {
  0% { transform: scale(1); }
  45% { transform: scale(1.18) rotate(-2deg); }
  100% { transform: scale(1); }
}

/* Botão de som: é o único item do HUD que aceita toque. */
.panel.mute {
  pointer-events: auto;
  cursor: pointer;
  min-width: 0;
  width: var(--hud-button);
  /* Quadrados, e não achatados: além de virarem alvos maiores, é a altura
     deles que empurra o ⚡ da linha de baixo para debaixo dos painéis. Sem
     isto o ⚡ (que agora é largo) subia e cruzava com "Distância". */
  height: var(--hud-button);
  padding: 0;
  justify-content: center;
  font-size: clamp(18px, 5vw, 24px);
  margin-left: auto;
  touch-action: manipulation;
}
.panel.mute:active { transform: translateY(3px); }
.panel.mute[hidden] { display: none; }
#pause { margin-left: auto; }
#pause:not([hidden]) + #mute { margin-left: 0; }

/* Clarão vermelho quando bate em alguma coisa. */
#flash {
  position: absolute;
  inset: 0;
  pointer-events: none;
  opacity: 0;
  background: radial-gradient(circle at 50% 60%, rgba(255, 60, 110, 0) 35%, rgba(255, 40, 90, .55) 100%);
}
#flash.hit { animation: flash .38s ease-out; }

/* O clarão da Bomba Arco-Íris. O mesmo elemento do clarão da batida, com
   outro fundo e outro tempo: aquele é o "ai!", este é o "uau!". Clareia do
   meio para fora, na ordem do arco-íris, e sai devagar — a onda ainda está
   varrendo a pista quando ele acaba. */
#flash.arcoiris {
  background:
    radial-gradient(circle at 50% 62%, rgba(255, 255, 255, .85) 0%, rgba(255, 255, 255, 0) 26%),
    conic-gradient(from 0deg at 50% 62%,
      rgba(255, 123, 157, .5), rgba(255, 178, 107, .5), rgba(255, 227, 107, .5),
      rgba(140, 233, 154, .5), rgba(116, 192, 252, .5), rgba(192, 156, 255, .5),
      rgba(255, 123, 157, .5));
  animation: flash-arcoiris .85s ease-out;
}
@keyframes flash-arcoiris {
  0%   { opacity: 0; transform: scale(.7); }
  18%  { opacity: 1; }
  100% { opacity: 0; transform: scale(1.35); }
}
@keyframes flash {
  0% { opacity: 0; }
  18% { opacity: 1; }
  100% { opacity: 0; }
}

#stage.shake { animation: shake .4s; }
@keyframes shake {
  0%, 100% { transform: translate(0, 0) rotate(0); }
  15% { transform: translate(-12px, 6px) rotate(-.6deg); }
  35% { transform: translate(11px, -5px) rotate(.5deg); }
  60% { transform: translate(-7px, 3px) rotate(-.3deg); }
  80% { transform: translate(4px, -2px) rotate(.2deg); }
}

/* Tela estreita: o HUD mostra só o essencial de cada modo — o resto
   (recorde, pontos) aparece nas telas de fim e nas estatísticas. */
@media (max-width: 620px) {
  #hud { gap: 4px; }
  .panel { min-width: clamp(52px, 15vw, 96px); padding: 4px 6px; }
  .panel.best { display: none; }
  #hud[data-mode='levels'] .panel.score,
  #hud[data-mode='levels'] .panel.distance { display: none; }
}

/* --- Power-ups ligados ------------------------------------------------ */
#powers {
  position: absolute;
  left: 50%;
  transform: translateX(-50%);
  /* Abaixo de Pontos-e-Distância empilhados (`.hud-stack`), que agora são o
     item mais alto do lado esquerdo do HUD — sem isto os cartões de
     power-up nasciam por cima da Distância. */
  top: calc(130px + env(safe-area-inset-top));
  display: flex;
  gap: 10px;
  pointer-events: none;
}
.power {
  background: rgba(255, 255, 255, .85);
  border: 3px solid #fff;
  border-radius: 18px;
  padding: 5px 9px 6px;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 4px;
  box-shadow: 0 4px 0 rgba(122, 78, 199, .18);
  /* Só toca ao nascer — a cada quadro que o power-up segue ativo,
     `Ui.setPowers` reaproveita este mesmo elemento, então a animação não
     dispara de novo (ver o comentário de `powerBars` em ui.js). Sem isso o
     cartão inteiro parecia tremer o tempo todo em que o poder durava. */
  animation: pop .28s ease-out;
}
.power-face { font-size: clamp(24px, 6.5vw, 30px); line-height: 1; }
.power-bar {
  width: clamp(42px, 12vw, 56px);
  height: 9px;
  border-radius: 999px;
  background: rgba(122, 78, 199, .18);
  overflow: hidden;
}
.power-bar i {
  display: block;
  height: 100%;
  border-radius: 999px;
  background: linear-gradient(90deg, #ffd166, var(--pink));
}

/* Avisinho no meio da tela quando pega um power-up */
#toast {
  /* Acima do cartão. O `#toast` vem antes do `#overlay` no HTML e nenhum dos
     dois declarava camada, então o modal pintava por cima — o aviso de
     "segure para abrir o cantinho dos adultos", que nasce justamente com um
     modal aberto, aparecia atrás dele. */
  z-index: 18;
  position: absolute;
  left: 50%;
  /* Em pé, 38% de uma tela alta caía bem no meio do corredor da pista —
     onde a criança olha para ver o que vem — e tampava a visão. `#lesson-box`
     já resolvia o mesmo problema ficando perto do HUD em vez de a uma
     fração da altura; o toast segue o mesmo endereço. */
  top: clamp(150px, 38vw, 200px);
  transform: translate(-50%, -50%) scale(.8);
  padding: 10px 22px;
  border-radius: 999px;
  background: rgba(255, 255, 255, .92);
  border: 4px solid #fff;
  color: var(--pink);
  font-size: clamp(18px, 5.5vw, 26px);
  font-weight: 700;
  white-space: nowrap;
  box-shadow: 0 8px 0 rgba(122, 78, 199, .2);
  opacity: 0;
  pointer-events: none;
  transition: opacity .2s, transform .2s;
}
/* Com a faixa da lição na tela, o aviso desce: os dois no meio se cobriam,
   e no modo Aprender os avisos de power-up aparecem o tempo todo. Quem some
   é a caixa inteira (#lesson-box), que é irmã do toast — o <p> de dentro
   não é, e o seletor deixava de valer. */
#lesson-box:not([hidden]) ~ #toast { top: clamp(270px, 62vw, 320px); }

#toast.show {
  opacity: 1;
  transform: translate(-50%, -50%) scale(1);
}

/* --- Controles de toque ---------------------------------------------- */
#touch-controls {
  position: absolute;
  left: 0; right: 0;
  bottom: calc(16px + env(safe-area-inset-bottom));
  display: flex;
  justify-content: center;
  gap: clamp(14px, 6vw, 28px);
  padding: 0 12px;
}
#touch-controls button {
  width: clamp(58px, 17vw, 78px);
  height: clamp(58px, 17vw, 78px);
  border: none;
  border-radius: 50%;
  font-size: clamp(24px, 7vw, 32px);
  background: rgba(255, 255, 255, .75);
  box-shadow: 0 6px 0 rgba(122, 78, 199, .25);
  cursor: pointer;
  touch-action: manipulation;
}
#touch-controls button:active { transform: translateY(4px); box-shadow: 0 2px 0 rgba(122, 78, 199, .25); }

/* Teclado e mouse não precisam dos botões na tela. */
@media (hover: hover) and (pointer: fine) {
  #touch-controls { display: none; }
}

/* --- Overlay ---------------------------------------------------------- */
#overlay {
  position: absolute;
  inset: 0;
  display: grid;
  /* O cartão fica em cima para o unicórnio girando aparecer embaixo dele. */
  align-content: start;
  justify-items: center;
  padding: calc(10px + env(safe-area-inset-top)) 12px calc(12px + env(safe-area-inset-bottom));
  /* Sem desfoque: o personagem girando atrás do cartão precisa aparecer. */
  background: rgba(122, 78, 199, .18);
  transition: opacity .25s;
  overflow: auto;
}
#overlay.hidden { opacity: 0; pointer-events: none; }

.card {
  background: var(--cream);
  border: 6px solid #fff;
  border-radius: clamp(20px, 5vw, 32px);
  padding: clamp(18px, 5vw, 28px) clamp(18px, 6vw, 34px) clamp(16px, 4vw, 24px);
  text-align: center;
  width: min(460px, 92vw);
  box-shadow: 0 12px 0 rgba(122, 78, 199, .25);
  position: relative;
  /* O cartão nunca toma a tela inteira: o miolo rola por dentro e o
     cenário (com o personagem girando) continua aparecendo embaixo. */
  display: flex;
  flex-direction: column;
  align-items: center;
  /* `dvh`, e não `vh`.
     Em celular, `vh` é medido com a barra de endereço **escondida**: com ela
     à vista, 92vh é maior que a tela — o cartão "acha" que cabe, não rola, e
     os últimos botões ficam embaixo da barra sem nenhum sinal de que estão
     lá. O `dvh` é a tela que existe agora, e encolhe junto com a barra.
     (Tentei antes `100%` do #overlay; não funciona: com `align-content:
     start` a linha do grid tem altura automática, e porcentagem não tem
     contra o que resolver.)
     A linha em `vh` fica como reserva para navegador sem `dvh`.
     A de `--vh1` vale por cima das duas: em alguns aparelhos o `dvh` não
     acompanha a barra de endereço sozinho, e os botões saem cortados do
     mesmo jeito. `--vh1` é 1% da altura de verdade, medida no JS a cada
     redimensionamento (ver Game.resize) — não depende do navegador ter
     entendido `dvh` direito. */
  max-height: 92vh;
  max-height: 92dvh;
  max-height: calc(var(--vh1, 1vh) * 92);
}
/* Grade maior que o cartão: as pontas desbotam, para ficar claro que dá
   para rolar e que a fileira cortada não é um defeito. */
.card.rola #overlay-extra {
  -webkit-mask-image: linear-gradient(to bottom, transparent 0, #000 12px, #000 calc(100% - 18px), transparent 100%);
  mask-image: linear-gradient(to bottom, transparent 0, #000 12px, #000 calc(100% - 18px), transparent 100%);
}

#overlay-text, #overlay-extra {
  overflow-y: auto;
  flex-shrink: 1;
  min-height: 0;
  width: 100%;
}
/* Quem aperta o cinto é a grade, não a fileira de botões.
   O flex reparte a falta de espaço proporcional ao tamanho de cada um, e a
   grade é enorme: com o elenco inteiro ela ficava com 90% do aperto e
   passava os outros 10% para os botões — que, com 122px de conteúdo e 61px
   de sobra, apareciam cortados no meio do "Pronto" (numa tela de 540x960).
   Botão pela metade não é botão: parece defeito, e some justamente o único
   caminho para a frente. Com o fator alto a grade abre mão de todo o espaço
   dela antes de a fileira ceder um pixel — e a grade rola, que é o que ela
   já sabe fazer e anuncia com as pontas desbotadas. A fileira ainda encolhe
   (e rola) depois disso, para o caso de a tela ser baixa demais até para
   ela. */
#overlay-extra { flex-shrink: 100; }
.card h1 {
  margin: 0 0 6px;
  font-size: clamp(30px, 9vw, 46px);
  color: var(--pink);
  text-shadow: 2px 3px 0 #fff, 4px 6px 0 rgba(122, 78, 199, .2);
}
.card p {
  color: var(--purple);
  font-size: clamp(14px, 4vw, 18px);
  line-height: 1.45;
  margin: 8px 0 14px;
}
.card .hint { font-size: clamp(11px, 3.2vw, 14px); opacity: .7; margin: 12px 0 0; }
.card.no-hint .hint { display: none; }
.card.no-arrows .hint-arrows { display: none; }
.hint-touch { display: none; }
@media (hover: none) and (pointer: coarse) {
  .hint-keyboard { display: none; }
  .hint-touch { display: inline; }
}

.brand {
  margin: 0;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  font-size: clamp(13px, 3.6vw, 16px);
  font-weight: 700;
  color: var(--pink);
  opacity: .85;
  letter-spacing: .02em;
}

/* --- Botões dos cantos do cartão --------------------------------------- */
/* Voltar (esquerda) e o cantinho dos adultos (direita). Sempre no mesmo
   lugar, para o voltar não competir com o botão grande da tela. */
.corner-button {
  position: absolute;
  top: clamp(6px, 1.6vw, 10px);
  width: clamp(40px, 11vw, 48px);
  height: clamp(40px, 11vw, 48px);
  border-radius: 50%;
  border: 3px solid #f3dcef;
  background: #fff;
  font-size: clamp(17px, 4.6vw, 21px);
  line-height: 1;
  cursor: pointer;
  touch-action: manipulation;
  box-shadow: 0 3px 0 rgba(122, 78, 199, .18);
}
.corner-button[hidden] { display: none; }
.corner-button:active { transform: translateY(2px); box-shadow: none; }
.corner-button.back { left: clamp(6px, 1.6vw, 10px); }
.corner-button.grown { right: clamp(6px, 1.6vw, 10px); opacity: .55; }

/* O 👑 só abre segurando o dedo: o anel enche enquanto o adulto segura. */
.corner-button.grown::after {
  content: '';
  position: absolute;
  inset: -4px;
  border-radius: 50%;
  border: 3px solid var(--pink);
  opacity: 0;
  transform: scale(.4);
  pointer-events: none;
}
.corner-button.grown.holding::after { animation: segurando 1.1s linear forwards; }
@keyframes segurando {
  from { opacity: .25; transform: scale(.4); }
  to   { opacity: 1;   transform: scale(1); }
}

/* Os controles ficam num grupo próprio, encostado à direita: pause e som na
   primeira linha, e o ⚡ na segunda, ocupando as duas colunas — assim ele
   fica centralizado embaixo da dupla sem depender de nenhuma conta, mesmo
   que os botões mudem de tamanho (o HUD aperta os controles quando a tela é
   estreita, e a grade acompanha sozinha). */
#hud-buttons {
  margin-left: auto;
  /* Pode encolher junto com o resto do HUD numa tela estreita, como os
     botões faziam quando estavam soltos na fileira. */
  min-width: 0;
  display: grid;
  /* Duas colunas do tamanho de um botão, que podem encolher. Com `1fr 1fr`
     o ⚡ da segunda linha (que ocupa as duas) definia a largura do grupo e
     espremia a dupla de cima. */
  grid-template-columns: repeat(2, minmax(0, var(--hud-button)));
  gap: var(--hud-gap);
  align-content: start;
  pointer-events: none;
}
#hud-buttons .panel.mute {
  margin-left: 0;
  width: 100%;
  max-width: var(--hud-button);
  justify-self: center;
}
/* O ⚡ é o único botão que muda a corrida enquanto ela acontece, e o único
   que a criança precisa achar sem tirar o olho da pista. Então ele é o
   maior do canto: ocupa as duas colunas inteiras, é mais alto que os outros,
   tem a palavra escrita do lado e fica pulsando enquanto está disponível.
   (Antes desenhava do tamanho de um botão só e se perdia entre o pause e o
   som — três ícones iguais em fila.) */
#hud-buttons #rush {
  grid-column: 1 / -1;
  /* Largura própria, e não a do grupo: numa tela estreita os painéis do HUD
     espremem o grupo inteiro para uns 57 px, e o ⚡ ficaria menor do que
     antes. Ancorado à direita, ele cresce para a esquerda — para dentro do
     céu, que ali embaixo dos painéis está vazio. */
  width: var(--hud-rush-largura);
  max-width: none;
  justify-self: end;
  height: var(--hud-rush);
  flex-direction: row;
  gap: clamp(2px, 1vw, 5px);
  /* A borda é um arco inteiro: sem este respiro dos lados, o ⚡ e a palavra
     ficam por fora do arredondado e aparecem cortados. */
  padding: 0 clamp(8px, 2.6vw, 12px);
  border-radius: 999px;
  border-color: #ffd166;
  background: linear-gradient(180deg, #fffdf5, #fff1cf);
  box-shadow: 0 5px 0 rgba(191, 138, 20, .3);
  animation: rush-chama 1.7s ease-in-out infinite;
}
#hud-buttons #rush .fi {
  width: clamp(20px, 5.8vw, 26px);
  height: clamp(20px, 5.8vw, 26px);
  flex: none;
  vertical-align: 0;
}
.rush-label {
  font-size: clamp(9px, 2.5vw, 12px);
  font-weight: 800;
  letter-spacing: .04em;
  color: #b07a12;
  line-height: 1;
}
/* Disponível e desligado: um anel dourado que abre e some, chamando o dedo. */
@keyframes rush-chama {
  0%, 100% { box-shadow: 0 5px 0 rgba(191, 138, 20, .3), 0 0 0 0 rgba(255, 176, 46, .5); }
  55%      { box-shadow: 0 5px 0 rgba(191, 138, 20, .3), 0 0 0 9px rgba(255, 176, 46, 0); }
}
#hud-buttons #rush:active {
  transform: translateY(4px);
  box-shadow: 0 1px 0 rgba(191, 138, 20, .3);
  animation: none;
}

/* Velocímetro: fica na terceira linha do canto, embaixo do ⚡, com a mesma
   largura dos botões somados. A barra é o que se lê de relance; o número é
   para quem quiser conferir. */
#hud-buttons #speed {
  grid-column: 1 / -1;
  /* Mesma largura do ⚡: os dois são o mesmo canto, e um velocímetro estreito
     embaixo de um botão largo parece defeito. */
  width: var(--hud-rush-largura);
  justify-self: end;
  min-width: 0;
  padding: 3px 6px 5px;
  gap: 1px;
}
#speed[hidden] { display: none; }
#speed .label { font-size: clamp(7px, 1.9vw, 9px); }
#speed-value { font-size: clamp(13px, 3.6vw, 17px); line-height: 1; }
.gauge-bar {
  width: 100%;
  height: 5px;
  margin-top: 2px;
  border-radius: 999px;
  background: rgba(122, 78, 199, .18);
  overflow: hidden;
}
.gauge-bar i {
  display: block;
  height: 100%;
  width: 0;
  border-radius: 999px;
  background: linear-gradient(90deg, #8ce99a, #ffd166);
  transition: width .12s linear;
}
/* Perto do teto a barra fica quente, para dar a sensação de limite. */
#speed.cheio .gauge-bar i { background: linear-gradient(90deg, #ffd166, #ff5d5d); }

/* Ligado ele fica aceso, para dar para ver de relance se está disparando. */
/* A aula do ⚡ está pedindo: o botão ganha um anel rosa em volta do dourado,
   diferente do pulso de "disponível" que ele já tem — quem pede é a lição,
   não o jogo. */
#hud-buttons #rush.pedindo {
  border-color: var(--pink);
  animation: rush-pedido .8s ease-in-out infinite;
}
@keyframes rush-pedido {
  0%, 100% { box-shadow: 0 5px 0 rgba(191, 138, 20, .3), 0 0 0 0 rgba(255, 93, 143, .7); }
  70%      { box-shadow: 0 5px 0 rgba(191, 138, 20, .3), 0 0 0 14px rgba(255, 93, 143, 0); }
}

/* Ligado: dourado cheio, a palavra em branco e o pulso mais rápido e mais
   forte — dá para ver que está ligado pelo canto do olho, correndo. */
#hud-buttons #rush.ligado {
  background: linear-gradient(180deg, #ffd875, #ffab1f);
  border-color: #fff3c4;
  animation: rush-ligado .55s ease-in-out infinite;
}
#hud-buttons #rush.ligado .rush-label {
  color: #fff;
  text-shadow: 0 1px 0 rgba(150, 100, 10, .45);
}
@keyframes rush-ligado {
  0%, 100% { box-shadow: 0 5px 0 rgba(150, 100, 10, .4), 0 0 0 0 rgba(255, 209, 102, .85); }
  70%      { box-shadow: 0 5px 0 rgba(150, 100, 10, .4), 0 0 0 11px rgba(255, 209, 102, 0); }
}

.wallet {
  margin-left: 6px;
  padding: 2px 9px;
  border-radius: 999px;
  background: #fff6dd;
  border: 2px solid #ffe1a8;
  color: #b07a12;
  font-size: clamp(11px, 3vw, 13px);
  font-weight: 700;
  white-space: nowrap;
}
.wallet[hidden] { display: none; }

/* Modo teste ligado: o selo fica sempre à vista, porque esquecer que ele
   está ligado é achar que o progresso sumiu. */
.test-badge {
  margin-left: 6px;
  padding: 2px 9px;
  border-radius: 999px;
  background: #e6f7e6;
  border: 2px solid #a8dba8;
  color: #2f7a3a;
  font-size: clamp(11px, 3vw, 13px);
  font-weight: 700;
  white-space: nowrap;
}
.test-badge[hidden] { display: none; }

/* Os ícones entram no lugar de um emoji, então precisam se comportar como
   uma letra: acompanhar o tamanho e a linha do texto em volta. */
.fi {
  display: inline-block;
  width: 1.15em;
  height: 1.15em;
  vertical-align: -0.22em;
  object-fit: contain;
  user-select: none;
}
/* Na vitrine dos modos o ícone é a informação, não um enfeite do texto. */
.mode-strip .fi { width: 1.5em; height: 1.5em; vertical-align: -0.4em; }

.brand-mark {
  width: clamp(20px, 5.5vw, 26px);
  height: auto;
  border-radius: 6px;
  vertical-align: -4px;
}

#overlay-text[hidden], #overlay-extra[hidden], #overlay-buttons[hidden] { display: none; }

/* --- Escolha do personagem -------------------------------------------- */
/* --- Hub: a tela de onde tudo sai ------------------------------------- */
/* O botão de jogar vem antes das figuras, e as figuras são o único jeito de
   trocar alguma coisa — cada uma abre a grade daquilo. */
.card.home .brand { order: 0; }
.card.home h1, .card.home #overlay-text { order: 1; }
.card.home #overlay-buttons { order: 2; }
.card.home #overlay-extra { order: 3; }
.card.home .hint { order: 4; }

.picks {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: clamp(6px, 2vw, 12px);
}
.pick {
  border: 3px solid #f3dcef;
  background: #fff;
  border-radius: 20px;
  padding: 6px 4px 8px;
  font: inherit;
  color: var(--purple);
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 3px;
  min-height: clamp(84px, 24vw, 118px);
  cursor: pointer;
  touch-action: manipulation;
  transition: transform .15s, border-color .15s;
}
.pick:active { transform: scale(.95); }
.pick-face {
  width: 100%;
  height: clamp(52px, 15vw, 76px);
  object-fit: contain;
  display: block;
}
.pick-emoji {
  position: relative;
  font-size: clamp(38px, 11vw, 54px);
  line-height: clamp(52px, 15vw, 76px);
}
/* A velocidade do Desafio vira um selo na quina da figura do modo. */
.pick-badge {
  position: absolute;
  right: -10px;
  bottom: 4px;
  font-size: .45em;
  background: #fff;
  border: 2px solid #f3dcef;
  border-radius: 50%;
  padding: 2px 3px;
  line-height: 1;
}
.pick-name {
  font-size: clamp(12px, 3.2vw, 15px);
  font-weight: 600;
  white-space: nowrap;
}

/* A história e os poderes são as duas coisas que valem um botão de
   verdade, mesmo sem ser o de jogar: uma é o porquê do jogo, a outra é o
   que segurar a atenção de quem já tem tudo. Preenchidos e coloridos, e
   não desbotados como a fileira miúda logo abaixo. */
.destaques {
  display: flex;
  gap: clamp(6px, 2vw, 10px);
  width: 100%;
  margin-top: clamp(10px, 3vw, 16px);
}
.destaque {
  flex: 1;
  min-width: 0;
  border: none;
  border-radius: 16px;
  padding: clamp(9px, 2.6vw, 13px) 6px;
  font: inherit;
  font-size: clamp(13px, 3.6vw, 16px);
  font-weight: 700;
  display: flex;
  align-items: center;
  justify-content: center;
  gap: 6px;
  cursor: pointer;
  touch-action: manipulation;
}
.destaque-emoji { font-size: 1.25em; line-height: 1; }
.destaque.historia {
  color: #fff;
  background: linear-gradient(180deg, #c7a6f5, #9a6fe0);
  box-shadow: 0 5px 0 #7247b8;
}
.destaque.poderes {
  color: #6b4600;
  background: linear-gradient(180deg, #ffd875, #ffab1f);
  box-shadow: 0 5px 0 #c97a00;
}
.destaque:active { transform: translateY(3px); }
.destaque.historia:active { box-shadow: 0 2px 0 #7247b8; }
.destaque.poderes:active { box-shadow: 0 2px 0 #c97a00; }
/* A história ganha novidade quando o fim dela abre (todo mundo livre): o
   mesmo pulso do ⚡ pedindo toque, para não se perder no botão já colorido. */
.destaque.historia.nova { animation: destaque-nova .9s ease-in-out infinite; }
@keyframes destaque-nova {
  0%, 100% { box-shadow: 0 5px 0 #7247b8, 0 0 0 0 rgba(255, 209, 102, .8); }
  70%      { box-shadow: 0 5px 0 #7247b8, 0 0 0 10px rgba(255, 209, 102, 0); }
}

/* --- Perfis: mais de uma criança no mesmo aparelho ---------------------- */

/* O chip de quem está jogando agora, em cima das três escolhas no hub —
   um jeito rápido de dizer "sou outra pessoa" sem ter que abrir o
   cantinho dos adultos para isso. */
.perfil-chip {
  display: flex;
  align-items: center;
  gap: 6px;
  align-self: center;
  margin-bottom: clamp(8px, 2.4vw, 12px);
  padding: 4px 14px 4px 6px;
  border: 2px solid #f3dcef;
  border-radius: 999px;
  background: #fff;
  font: inherit;
  color: var(--purple);
  cursor: pointer;
  touch-action: manipulation;
}
.perfil-chip:active { transform: scale(.96); }
.perfil-chip-avatar {
  width: 26px;
  height: 26px;
  border-radius: 50%;
  background: #fff0f6;
  display: flex;
  align-items: center;
  justify-content: center;
  font-size: 15px;
  flex-shrink: 0;
}
.perfil-chip-nome {
  font-size: clamp(12px, 3.2vw, 14px);
  font-weight: 700;
  max-width: 30vw;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.perfil-chip-trocar { font-size: 11px; opacity: .55; }

/* A ficha de nome e avatar, na hora de criar um perfil. */
.perfil-form { display: flex; flex-direction: column; align-items: center; gap: 4px; width: 100%; }
.perfil-nome-input {
  width: 100%;
  max-width: 280px;
  border: 3px solid #f3dcef;
  border-radius: 999px;
  padding: 10px 18px;
  font: inherit;
  font-size: clamp(15px, 4.2vw, 18px);
  font-weight: 600;
  color: var(--purple);
  text-align: center;
  background: #fff;
}
.perfil-nome-input:focus { outline: none; border-color: var(--pink); }
.perfil-sub {
  margin: 14px 0 6px;
  font-size: clamp(12px, 3.2vw, 14px);
  font-weight: 600;
  color: var(--purple);
  opacity: .75;
}
.perfil-avatares {
  display: grid;
  grid-template-columns: repeat(5, 1fr);
  gap: 8px;
  width: 100%;
}
.avatar-opcao {
  border: 3px solid #f3dcef;
  background: #fff;
  border-radius: 16px;
  aspect-ratio: 1;
  font-size: clamp(20px, 5.6vw, 27px);
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  touch-action: manipulation;
}
.avatar-opcao:active { transform: scale(.92); }
.avatar-opcao.escolhido {
  border-color: var(--pink);
  background: #fff0f6;
  box-shadow: 0 0 0 3px rgba(255, 93, 143, .25);
}

/* A grade de perfis, no trocador — redondos, como retratos de verdade,
   nome embaixo de cada um. Três por linha cabe até no MAX_PROFILES (ver
   Game.showProfileSwitcher): duas linhas cheias e mais uma com o "+". */
.perfis-grade {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: clamp(10px, 3vw, 18px) clamp(6px, 2vw, 12px);
  width: 100%;
}
.perfil-tile-wrap {
  position: relative;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 6px;
}
.perfil-tile {
  width: clamp(64px, 18vw, 84px);
  height: clamp(64px, 18vw, 84px);
  border: 3px solid #f3dcef;
  background: #fff;
  border-radius: 50%;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  touch-action: manipulation;
}
.perfil-tile:active { transform: scale(.95); }
.perfil-tile.escolhido { border-color: var(--pink); background: #fff0f6; box-shadow: 0 0 0 3px rgba(255, 93, 143, .25); }
.perfil-tile-avatar { font-size: clamp(28px, 7.5vw, 38px); }
.perfil-tile-nome {
  font-size: clamp(11px, 3vw, 13px);
  font-weight: 600;
  color: var(--purple);
  text-align: center;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
  max-width: 100%;
}
.perfil-tile.novo { border-style: dashed; color: var(--purple); opacity: .7; }

/* O lápis de editar, encavalado no canto do círculo — perto o bastante do
   avatar para ficar óbvio o que ele edita, sem entrar dentro do botão do
   retrato (que já tem seu próprio toque: trocar de perfil). */
.perfil-tile-editar {
  position: absolute;
  top: -4px;
  right: 2px;
  width: 26px;
  height: 26px;
  border: 2px solid #f3dcef;
  border-radius: 50%;
  background: #fff;
  font-size: 12px;
  display: flex;
  align-items: center;
  justify-content: center;
  cursor: pointer;
  touch-action: manipulation;
}
.perfil-tile-editar:active { transform: scale(.9); }

/* Estatísticas e "sobre" ficam à mão, mas miúdos: são de adulto, e não
   podem disputar o olho com o botão de jogar. */
.extras {
  display: flex;
  justify-content: center;
  gap: 8px;
  flex-wrap: wrap;
  margin-top: clamp(10px, 3vw, 16px);
}
.mini-button {
  border: 2px solid #e9dcf7;
  background: #fff;
  border-radius: 999px;
  padding: 5px 13px;
  font: inherit;
  font-size: clamp(10.5px, 2.9vw, 12.5px);
  font-weight: 600;
  color: var(--purple);
  opacity: .75;
  cursor: pointer;
  touch-action: manipulation;
}
.mini-button:active { transform: scale(.94); }
/* O de aprender é o único da fileira que *faz* alguma coisa — os outros
   abrem informação. Por isso é tingido e não desbotado: numa tela estreita
   ele cai numa linha só para ele, e assim a quebra parece intenção, que é o
   que é. */
.mini-button.aprender {
  border-color: #ffc9de;
  background: #fff0f6;
  color: var(--pink);
  opacity: 1;
}

/* O de atualizar chama atenção, porque só existe quando há o que atualizar. */
.mini-button.nova {
  border-color: #ffd166;
  background: #fff6dd;
  color: #b07a12;
  opacity: 1;
}

/* A legenda das grades fica logo abaixo do título, acima do bloco que rola:
   é o texto que diz quem está escolhido e de quem é o ⚡ das pistas. */
.card.picker #overlay-text {
  margin: 2px 0 8px !important;
  opacity: .85;
}

/* --- As três brincadeiras ---------------------------------------------- */
.mode-list { display: flex; flex-direction: column; gap: clamp(6px, 2vw, 10px); }
.mode-card {
  border: 3px solid #f3dcef;
  background: #fff;
  border-radius: 20px;
  padding: clamp(8px, 2.4vw, 12px) 10px;
  font: inherit;
  color: var(--purple);
  display: flex;
  align-items: center;
  gap: clamp(8px, 2.6vw, 14px);
  text-align: left;
  cursor: pointer;
  touch-action: manipulation;
  transition: transform .15s, border-color .15s, background .15s;
}
.mode-card:active { transform: scale(.97); }
.mode-card.escolhido {
  border-color: var(--pink);
  background: #ffeef6;
  box-shadow: 0 4px 0 rgba(255, 93, 143, .3);
}
.mode-emoji { font-size: clamp(30px, 9vw, 42px); line-height: 1; }
.mode-body {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: 1px;
  flex: 1;
  min-width: 0;
}
.mode-name { font-size: clamp(17px, 4.8vw, 22px); font-weight: 700; color: var(--pink); }
.mode-hint { font-size: clamp(11px, 3vw, 13.5px); opacity: .75; }
/* A "vitrine": em vez de explicar o modo com palavras, mostra como é a
   pista dele. */
.mode-strip {
  display: flex;
  align-items: center;
  gap: 4px;
  font-size: clamp(13px, 3.6vw, 16px);
  letter-spacing: .1em;
  margin: 1px 0;
}
.map-dot {
  width: clamp(8px, 2.2vw, 11px);
  height: clamp(8px, 2.2vw, 11px);
  border-radius: 50%;
  border: 2px solid var(--pink);
  background: transparent;
}
.map-dot.done { background: #ffd166; border-color: #ffb703; }
.map-dot.locked { border-color: rgba(122, 78, 199, .25); }

/* A velocidade do Desafio abre dentro do próprio card, sem outra tela. */
.speeds {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: 6px;
  margin: -2px 4px 2px;
}
.speed {
  border: 3px solid #f3dcef;
  background: #fff;
  border-radius: 16px;
  padding: 6px 2px;
  font: inherit;
  font-size: clamp(11px, 3vw, 13px);
  font-weight: 600;
  color: var(--purple);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1px;
  cursor: pointer;
  touch-action: manipulation;
}
.speed b { font-size: clamp(20px, 6vw, 26px); line-height: 1.1; }
.speed:active { transform: scale(.94); }
.speed.escolhido { border-color: var(--pink); background: #ffeef6; }

.cast-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: clamp(6px, 2vw, 10px);
  margin: 4px 0;
}
.cast-card {
  position: relative;
  border: 3px solid #f3dcef;
  background: #fff;
  border-radius: 18px;
  padding: 6px 4px 8px;
  min-height: clamp(96px, 26vw, 140px);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  cursor: pointer;
  touch-action: manipulation;
  transition: transform .15s, border-color .15s, background .15s;
}
.cast-face {
  width: 100%;
  height: clamp(74px, 18vw, 108px);
  object-fit: contain;
  display: block;
}
.cast-name {
  font: inherit;
  font-size: clamp(11px, 3vw, 14px);
  font-weight: 600;
  color: var(--purple);
  white-space: nowrap;
}
.cast-card:active { transform: scale(.95); }
.cast-card.escolhido {
  border-color: var(--pink);
  background: #ffeef6;
  box-shadow: 0 4px 0 rgba(255, 93, 143, .3);
}

/* Trancado: o retrato continua à vista (é ele que dá vontade), mas
   desbotado, com o cadeado na quina e o preço no lugar do nome. */
.cast-card.trancado { background: #f7f2fb; border-color: #e6dcf3; }
.cast-card.trancado .cast-face { opacity: .45; filter: saturate(.35); }
.cast-lock {
  position: absolute;
  top: 4px;
  right: 6px;
  font-size: clamp(13px, 3.6vw, 17px);
}
/* O ⚡ da pista fica no canto oposto ao cadeado, para os dois conviverem. */
.cast-fast {
  position: absolute;
  top: 4px;
  left: 5px;
  font-size: clamp(12px, 3.4vw, 16px);
  background: #fff6dd;
  border: 2px solid #ffe1a8;
  border-radius: 999px;
  padding: 1px 4px;
  line-height: 1;
}

.cast-price {
  display: inline-block;
  background: #fff6dd;
  border: 2px solid #ffe1a8;
  border-radius: 999px;
  padding: 0 8px;
  color: #b07a12;
  font-weight: 700;
  white-space: nowrap;
}

/* O espaço de quem ainda não foi criado: fica na grade de propósito, para a
   criança ver que tem mais coisa vindo. */
.cast-card.vazio {
  background: #f7f2fb;
  border-style: dashed;
  border-color: #ded2f0;
  justify-content: center;
  gap: 2px;
}
.cast-soon {
  font-size: clamp(24px, 7vw, 34px);
  font-weight: 700;
  color: #c9b8e6;
  line-height: 1;
}
.cast-card.vazio .cast-name { color: #b3a3cf; font-weight: 600; }

/* --- A troca por chaves ------------------------------------------------- */
.shop { display: flex; flex-direction: column; align-items: center; }
.shop-face {
  width: clamp(120px, 34vw, 168px);
  height: auto;
  border-radius: 20px;
  background: #fff;
  border: 3px solid #f3dcef;
}
.shop-title {
  margin: 6px 0 2px !important;
  font-size: clamp(12px, 3.4vw, 15px) !important;
  font-weight: 600;
  opacity: .8;
}
.shop-story {
  margin: 0 !important;
  font-size: clamp(12.5px, 3.4vw, 15px) !important;
  line-height: 1.4 !important;
}
.shop-price {
  margin: 8px 0 0 !important;
  font-size: clamp(13px, 3.6vw, 16px) !important;
  background: #fff6dd;
  border: 2px solid #ffe1a8;
  border-radius: 999px;
  padding: 5px 14px;
  color: #b07a12;
}
.shop-price.falta { background: #fff0f3; border-color: #ffc9d6; color: #c2456b; }
/* A característica especial: é a informação que decide a escolha, então
   ganha o destaque mais forte da ficha. */
.shop-power {
  margin: 8px 0 0 !important;
  font-size: clamp(12.5px, 3.5vw, 15px) !important;
  background: #f0e6ff;
  border: 2px solid #d9c2ff;
  border-radius: 14px;
  padding: 6px 12px;
  color: #6b3fa8;
  line-height: 1.35 !important;
}
.shop-power b { color: #4f2b85; }

/* A linha das pistas rápidas: o complemento, com destaque mais leve. */
.shop-fast {
  margin: 8px 0 0 !important;
  font-size: clamp(12px, 3.3vw, 14.5px) !important;
  background: #fff6dd;
  border: 2px solid #ffe1a8;
  border-radius: 14px;
  padding: 5px 12px;
  color: #b07a12;
}
.shop-fast b { color: #8a5c08; }
/* Na ficha de quem já é seu não há preço: o lugar dele é a música da pista. */
.shop-note {
  margin: 8px 0 0 !important;
  font-size: clamp(12px, 3.3vw, 14px) !important;
  opacity: .75;
}
/* A linha embaixo da grade virou legenda do escolhido, sem toque. */
.pick-story.aberta { background: none; padding: 0; }

/* --- Grade de fases --------------------------------------------------- */
.levels-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: clamp(7px, 2.2vw, 12px);
  margin: 6px 0 4px;
}
.level-tile {
  position: relative;
  border: 3px solid #f3dcef;
  background: #fff;
  border-radius: 16px;
  padding: 10px 2px 8px;
  min-height: clamp(62px, 17vw, 84px);
  justify-content: center;
  font: inherit;
  color: var(--purple);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 1px;
  cursor: pointer;
  touch-action: manipulation;
  transition: transform .15s, border-color .15s, background .15s;
}
.level-number { font-size: clamp(18px, 5.4vw, 24px); font-weight: 700; line-height: 1.05; }
.level-keys { font-size: clamp(9px, 2.6vw, 11px); font-weight: 600; opacity: .75; white-space: nowrap; }
.level-done {
  position: absolute;
  top: -8px;
  right: -6px;
  font-size: clamp(13px, 3.6vw, 16px);
}
.level-tile.open { border-color: var(--pink); }
.level-tile.done { border-color: #ffd166; background: #fff8e6; }
/* A trancada continua do mesmo tamanho: criança mira mal, e um alvo menor
   colado num maior vira toque errado. Ela responde com a chacoalhada. */
.level-tile.locked { opacity: .6; background: #f6f1fb; border-color: #e6dcf3; }
.level-tile:active { transform: scale(.94); }

/* "Ainda não": o toque precisa responder alguma coisa. */
.nope { animation: chacoalha .4s; }
@keyframes chacoalha {
  0%, 100% { transform: translateX(0); }
  25% { transform: translateX(-5px) rotate(-3deg); }
  75% { transform: translateX(5px) rotate(3deg); }
}

/* --- Cartão "sobre" --------------------------------------------------- */
.about { display: flex; flex-direction: column; align-items: center; gap: 4px; }
.about-logo {
  width: clamp(54px, 15vw, 72px);
  height: auto;
  border-radius: 22%;
  box-shadow: 0 6px 0 rgba(122, 78, 199, .18);
  margin-bottom: 2px;
}
.about-text {
  margin: 0 !important;
  font-size: clamp(12.5px, 3.3vw, 14.5px) !important;
  line-height: 1.35 !important;
}
.about-links {
  display: flex;
  flex-direction: column;
  gap: 5px;
  width: 100%;
  margin: 4px 0 2px;
}
.about-link {
  display: block;
  padding: 7px 12px;
  border-radius: 999px;
  border: 3px solid #f3dcef;
  background: #fff;
  color: var(--purple);
  font-size: clamp(12px, 3.4vw, 15px);
  font-weight: 600;
  text-decoration: none;
  transition: transform .15s, border-color .15s, background .15s;
}
.about-link:hover { border-color: var(--pink); background: #ffeef6; }
.about-link:active { transform: scale(.97); }
.install-steps {
  margin: 6px 0;
  padding-left: 20px;
  text-align: left;
  color: var(--purple);
  font-size: clamp(12.5px, 3.4vw, 15px);
  line-height: 1.5;
}
.install-steps li { margin-bottom: 4px; }

/* A versão fica discreta, entre os links e os créditos: serve para saber o
   que está instalado quando algo não bate, não para chamar atenção. */
.about-version {
  margin: 6px 0 0 !important;
  font-size: clamp(11px, 3vw, 13px) !important;
  font-weight: 600;
  color: var(--purple);
  opacity: .55;
  letter-spacing: .03em;
}

.about-note {
  margin: 4px 0 0 !important;
  font-size: clamp(10px, 2.8vw, 12px) !important;
  opacity: .6;
}

/* --- Tela de estatísticas ------------------------------------------- */
#overlay-extra { width: 100%; }
#overlay-extra[hidden] { display: none; }

.stats-grid {
  display: grid;
  grid-template-columns: repeat(3, 1fr);
  gap: clamp(5px, 1.6vw, 9px);
  margin: 6px 0 4px;
}
.stat {
  background: #fff;
  border: 2px solid #f3dcef;
  border-radius: 16px;
  padding: 6px 4px 5px;
  display: flex;
  flex-direction: column;
  align-items: center;
  line-height: 1.1;
}
.stat-emoji { font-size: clamp(16px, 4.6vw, 20px); }
.stat-value {
  font-size: clamp(20px, 6vw, 27px);
  font-weight: 700;
  color: var(--pink);
}
.stat-label {
  font-size: clamp(9px, 2.6vw, 11px);
  font-weight: 600;
  color: var(--purple);
  opacity: .7;
  text-align: center;
}

.stats-title {
  margin: 8px 0 3px !important;
  font-size: clamp(10px, 2.8vw, 12px) !important;
  font-weight: 600;
  letter-spacing: .05em;
  text-transform: uppercase;
  opacity: .55;
}

.stats-rows { display: flex; flex-direction: column; gap: 5px; }
.stat-row {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: clamp(11px, 3vw, 13px);
  font-weight: 600;
  color: var(--purple);
}
.stat-row-name { width: clamp(74px, 22vw, 96px); text-align: left; white-space: nowrap; }
.stat-row-value { width: 26px; text-align: right; }
.stat-bar {
  flex: 1;
  height: 12px;
  border-radius: 999px;
  background: rgba(122, 78, 199, .12);
  overflow: hidden;
}
.stat-bar i {
  display: block;
  height: 100%;
  border-radius: 999px;
  background: linear-gradient(90deg, #ffb3d1, var(--pink));
  min-width: 4px;
}

#overlay-buttons {
  display: flex;
  flex-direction: column;
  gap: 10px;
  align-items: stretch;
  width: 100%;
  /* A fileira precisa poder rolar. O cantinho dos adultos chega a sete
     botões, e em tela baixa (aparelho pequeno, ou celular deitado) o último
     caía fora do cartão sem deixar rastro — medido, terminava 120px abaixo
     da borda da tela, e não havia como alcançá-lo.
     O `min-height: 0` é o que permite encolher dentro do cartão flex: sem
     ele o navegador respeita o tamanho do conteúdo e o `overflow` nunca
     entra em ação. */
  min-height: 0;
  overflow-y: auto;
  /* O `overflow` recorta na borda da caixa, e o bico 3D dos botões é
     desenhado **fora** dela (`box-shadow: 0 8px 0`, o degrau que faz o botão
     parecer apertável). Sem esta folga o bico some cortado reto, e o botão
     fica com cara de que a tela acabou no meio dele — foi o que aconteceu
     com o ⬅️ Voltar do cartão "Sobre". Oito pixels é o degrau do maior
     deles, e cobre também o instante do toque, quando ele desce 5px e o
     degrau encolhe para 3px. O botão grande escapava por sorte: a margem
     dele já dava a folga. */
  padding-bottom: 8px;

  /* E que **se veja** que rola. No celular a barra de rolagem é invisível
     até se arrastar, então o corte parecia um bug: a sombrinha só aparece
     do lado em que ainda há botão escondido.
     São quatro camadas: duas cor de cartão que tapam a sombra quando se
     chega ao fim (`local`, andam com o conteúdo) e duas sombras presas às
     bordas (`scroll`). */
  background:
    linear-gradient(var(--cream) 40%, rgba(255, 246, 251, 0)) top / 100% 20px no-repeat local,
    linear-gradient(rgba(255, 246, 251, 0), var(--cream) 60%) bottom / 100% 20px no-repeat local,
    radial-gradient(farthest-side at 50% 0, rgba(122, 78, 199, .22), transparent) top / 100% 9px no-repeat,
    radial-gradient(farthest-side at 50% 100%, rgba(122, 78, 199, .22), transparent) bottom / 100% 9px no-repeat;
}

.muted { opacity: .7; font-size: .88em; }

.big-button {
  border: none;
  border-radius: 999px;
  padding: clamp(10px, 3vw, 15px) clamp(18px, 5vw, 30px);
  font: inherit;
  font-size: clamp(17px, 5vw, 23px);
  font-weight: 700;
  color: #fff;
  background: linear-gradient(180deg, #ff8fb1, var(--pink));
  box-shadow: 0 6px 0 #d63e6d;
  cursor: pointer;
  touch-action: manipulation;
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
}
.big-button .button-label { display: block; }
.big-button small {
  font-size: clamp(10px, 2.9vw, 13px);
  font-weight: 500;
  opacity: .9;
}
.big-button:active { transform: translateY(4px); box-shadow: 0 2px 0 #d63e6d; }
.big-button.secondary {
  background: linear-gradient(180deg, #c7a6f5, #9a6fe0);
  box-shadow: 0 6px 0 #7247b8;
}
.big-button.secondary:active { box-shadow: 0 2px 0 #7247b8; }

/* O botão que faz a coisa acontecer (jogar, pronto) é o maior da tela e o
   único desse tamanho — não dá para confundir com os outros. */
.big-button.huge {
  font-size: clamp(24px, 8vw, 36px);
  padding: clamp(14px, 4vw, 20px) clamp(24px, 7vw, 40px);
  letter-spacing: .02em;
  box-shadow: 0 8px 0 #d63e6d;
  /* O alvo principal da tela respira: não encosta no que vem antes nem no
     que vem depois. */
  margin: clamp(12px, 3.6vw, 22px) 0;
}
.big-button.huge:active { transform: translateY(5px); box-shadow: 0 3px 0 #d63e6d; }

/* Tela baixa e larga (celular deitado, janela pequena): tudo encolhe e os
   botões ficam lado a lado, para o menu caber sem rolar. */
@media (orientation: landscape) and (max-height: 620px) {
  .card { padding: 10px 18px 12px; width: min(560px, 88vw); }
  .card h1 { font-size: 24px; margin-bottom: 2px; }
  .card p { font-size: 12.5px; line-height: 1.3; margin: 2px 0 4px; }
  .brand { font-size: 12px; }
  .pick { min-height: 74px; padding: 4px; border-width: 2px; }
  .pick-face, .pick-emoji { height: 44px; line-height: 44px; font-size: 32px; }
  .pick-name { font-size: 11px; }
  /* Deitado sobra largura e falta altura: os seis retratos vão para uma
     linha só, e o card do modo perde a legenda escrita (a vitrine de
     figuras continua, que é o que a criança lê). */
  .cast-grid { grid-template-columns: repeat(6, 1fr); gap: 6px; }
  .cast-card { min-height: 66px; padding: 4px 2px 5px; border-width: 2px; }
  .cast-face { height: 42px; }
  .cast-name { font-size: 10.5px; }
  .cast-lock { font-size: 12px; top: 2px; right: 3px; }
  .cast-price { padding: 0 6px; }
  .pick-story { margin-top: 5px !important; font-size: 11px !important; }
  .shop-face { width: 96px; }
  .shop-story { font-size: 11.5px !important; }
  .shop-price { margin-top: 5px !important; padding: 3px 10px; font-size: 12px !important; }
  .mode-list { gap: 5px; }
  .mode-card { padding: 4px 8px; border-width: 2px; gap: 8px; }
  .mode-emoji { font-size: 22px; }
  .mode-name { font-size: 14px; }
  .mode-hint { display: none; }
  .mode-strip { font-size: 12px; margin: 0; }
  .speeds { gap: 5px; margin: -1px 4px 1px; }
  .speed { padding: 3px 2px; font-size: 10.5px; border-width: 2px; }
  .speed b { font-size: 17px; }
  .levels-grid { grid-template-columns: repeat(5, 1fr); gap: 6px; }
  .level-tile { min-height: 50px; padding: 5px 2px; border-width: 2px; }
  .corner-button { width: 36px; height: 36px; font-size: 16px; border-width: 2px; }
  .big-button.huge { font-size: 20px; padding: 9px 22px; margin: 6px 0; }
  .extras { margin-top: 6px; gap: 6px; }
  .mini-button { padding: 3px 10px; font-size: 10px; }
  .card .hint { margin-top: 6px; font-size: 10.5px; }
  .stats-grid { grid-template-columns: repeat(6, 1fr); }
  .stat { padding: 5px 2px 4px; border-radius: 12px; }
  .stat-value { font-size: 18px; }
  .stats-title { margin: 6px 0 3px !important; }
  .stat-bar { height: 9px; }
  /* Em tela baixa os botões ficam lado a lado — e quebram para a linha de
     baixo quando são muitos. */
  #overlay-buttons { flex-direction: row; flex-wrap: wrap; justify-content: center; }
  .big-button { font-size: 16px; padding: 8px 18px; }
  /* Deitado, os botões vão para os cantos: setas no polegar esquerdo,
     pulo no direito. */
  #touch-controls {
    bottom: calc(8px + env(safe-area-inset-bottom));
    justify-content: flex-start;
    gap: 12px;
    padding: 0 calc(14px + env(safe-area-inset-left)) 0 calc(14px + env(safe-area-inset-right));
  }
  #touch-controls button { width: 52px; height: 52px; font-size: 22px; }
  #touch-controls [data-action='left'] { order: 1; }
  #touch-controls [data-action='right'] { order: 2; }
  #touch-controls [data-action='jump'] { order: 3; margin-left: auto; }

  /* Deitado a tela é baixa e a pista ocupa quase a altura inteira — o
     toast de pegar um power-up, que ficava à meia altura, caía bem em
     cima de onde os obstáculos aparecem, tapando a hora de decidir a
     faixa. Aqui ele sobe para a faixa de céu logo abaixo do HUD, baixo o
     bastante para não cobrir os painéis (que só existem lá em cima). */
  #toast { top: calc(122px + env(safe-area-inset-top)); font-size: 16px; padding: 7px 16px; }
  #lesson-box:not([hidden]) ~ #toast { top: calc(150px + env(safe-area-inset-top)); }

  /* Os cartões de power-up ligado tinham o mesmo problema, e centralizados
     eles ainda tapavam mais: a pista inteira, não só um instante. Deitado
     eles saem do meio e descem pela beira esquerda, embaixo de Pontos e
     Distância — ali é grama, não pista, e sobra altura de sobra para
     empilhar. */
  #powers {
    left: calc(10px + env(safe-area-inset-left));
    right: auto;
    transform: none;
    top: calc(112px + env(safe-area-inset-top));
    flex-direction: column;
    align-items: flex-start;
  }
}

/* Celular deitado de verdade (bem baixinho): o lembrete dos controles sai,
   porque os botões de toque já estão na tela. */
@media (orientation: landscape) and (max-height: 430px) {
  .card .hint { display: none; }
  .card { padding-bottom: 10px; }
  .card h1 { font-size: 20px; }
  .brand { font-size: 11px; }
  .stat-emoji { font-size: 14px; }
  .stat-value { font-size: 16px; }
  .stat-label { font-size: 8.5px; }
  .stats-title { margin: 4px 0 2px !important; font-size: 9.5px !important; }
  .stats-rows { gap: 3px; }
  .stat-row { font-size: 11px; gap: 6px; }
  .stat-row-name { width: 72px; }
  .stat-bar { height: 8px; }
}

/* Celular em pé: o cartão ocupa no máximo dois terços da tela, e as fichas
   ficam sempre numa linha só — assim dá para ver a pista e o personagem
   enquanto escolhe. */
@media (orientation: portrait) {
  .card {
    max-height: 88vh; max-height: 88dvh; max-height: calc(var(--vh1, 1vh) * 88);
    padding: 14px 14px 16px;
  }
  /* O cartão de escolha deixa o unicórnio girando aparecer embaixo, mas com
     21 slots o elenco passa a valer mais do que o espelho: o cartão cresce
     até quase a tela toda e a grade rola por dentro. */
  .card.picker { max-height: 86vh; max-height: 86dvh; max-height: calc(var(--vh1, 1vh) * 86); }
  /* A historinha é o que pode encolher, para as fichas e os botões caberem. */
  #overlay-text { font-size: clamp(12px, 3.3vw, 15px); line-height: 1.3; }
  .card h1 { font-size: clamp(24px, 7vw, 34px); }
  .card p { font-size: clamp(13px, 3.6vw, 16px); line-height: 1.35; }
  .levels-grid { gap: 7px; }
  /* O cartão do hub é curtinho de propósito: o unicórnio girando tem que
     aparecer embaixo dele. */
  .card.home { max-height: 72vh; max-height: 72dvh; max-height: calc(var(--vh1, 1vh) * 72); }
}

/* Celular em pé e baixinho (iPhone SE e parecidos): aqui ver os seis de uma
   vez vale mais do que ver o unicórnio embaixo do cartão — grade cortada é
   opção escondida, que é justamente o que a grade veio resolver. */
@media (orientation: portrait) and (max-height: 720px) {
  /* Numa tela dessas o cartão toma quase tudo: com nove retratos em três
     fileiras, ver o elenco inteiro (e os preços de quem está trancado) vale
     mais do que ver o unicórnio girando embaixo. */
  .card.picker { max-height: 88vh; max-height: 88dvh; max-height: calc(var(--vh1, 1vh) * 88); }
  /* Três colunas em vez de quatro: cabe na altura e o tile fica maior, que
     é o que importa para um dedo pequeno. */
  .levels-grid { grid-template-columns: repeat(3, 1fr); }
  .cast-grid { gap: 5px; }
  .cast-card { min-height: clamp(66px, 19vw, 88px); padding: 4px 3px 5px; }
  .cast-face { height: clamp(46px, 13vw, 66px); }
  .cast-name { font-size: clamp(10px, 2.9vw, 12px); }
  .pick-story { margin-top: 6px !important; font-size: clamp(11px, 3vw, 13px) !important; }
  .mode-card { padding: 6px 8px; }
  .mode-emoji { font-size: clamp(26px, 8vw, 34px); }
  .mode-name { font-size: clamp(15px, 4.4vw, 18px); }
  .mode-hint { font-size: clamp(10px, 2.8vw, 12px); }
  .speed { padding: 4px 2px; }
  .speed b { font-size: clamp(17px, 5vw, 22px); }
  .big-button.huge { font-size: clamp(21px, 6.6vw, 28px); padding: 11px 24px; margin: 9px 0; }
}

/* --- Vencer uma pista inteira ------------------------------------------ */
/* As 12 fases de uma pista, uma atrás da outra, ganham um cartão diferente
   do branco de sempre: borda de arco-íris (as mesmas cores da barra de
   carregamento) e um brilho dourado que respira — é o único troféu do
   jogo que não é por pontuação, e sim por terminar tudo (ver
   Game.trackComplete). */
.card.vitoria {
  border-color: transparent;
  background:
    linear-gradient(var(--cream), var(--cream)) padding-box,
    linear-gradient(120deg, #ff7b9d, #ffb26b, #ffe36b, #8ce99a, #74c0fc, #c09cff) border-box;
  animation: vitoria-brilho 1.8s ease-in-out infinite;
}
@keyframes vitoria-brilho {
  0%, 100% { box-shadow: 0 12px 0 rgba(122, 78, 199, .25), 0 0 0 0 rgba(255, 209, 102, .55); }
  50%      { box-shadow: 0 12px 0 rgba(122, 78, 199, .25), 0 0 30px 8px rgba(255, 209, 102, .5); }
}
@media (prefers-reduced-motion: reduce) {
  .card.vitoria { animation: none; box-shadow: 0 12px 0 rgba(122, 78, 199, .25), 0 0 20px 4px rgba(255, 209, 102, .5); }
}

/* A chuva das 10 chaves de presente: uma leva de chaves caindo por cima do
   cartão de vitória, cada uma com sua posição e seu atraso (ver
   Game.chuvaDeChaves) — decoração pura, por isso `pointer-events: none` e
   sem tocar em nada do layout (a `position: absolute` some do fluxo). */
.chaves-presente {
  position: absolute;
  inset: 0;
  overflow: hidden;
  border-radius: inherit;
  pointer-events: none;
}
.chave-caindo {
  position: absolute;
  top: -12%;
  font-size: clamp(20px, 6vw, 30px);
  opacity: 0;
  animation: chave-cai 1.6s cubic-bezier(.3, .6, .4, 1) forwards;
}
@keyframes chave-cai {
  /* `top`, e não `transform: translateY()`: a porcentagem de `top` é do
     cartão (o container tem `inset: 0`), a de `translateY()` seria da
     própria chavinha — o dobro de nada não anda coisa nenhuma. */
  0%   { top: -12%; transform: rotate(-18deg) scale(.6); opacity: 0; }
  12%  { opacity: 1; }
  75%  { opacity: 1; }
  100% { top: 112%; transform: rotate(28deg) scale(1); opacity: 0; }
}
@media (prefers-reduced-motion: reduce) {
  .chaves-presente { display: none; }
}

/* --- O livro da história ---------------------------------------------- */
/* O cartão vira página de livro: a figura sangra até as bordas de cima, o
   texto fica num quadro de papel embaixo dela e a página vira num botão
   grande. Nada de marca nem de dica de teclado — o livro é só o livro. */
.card.livro {
  padding: 0;
  overflow: hidden;
  background: #fffdf7;
  border-color: #fff;
  width: min(520px, 94vw);
}
.card.livro .brand,
.card.livro .hint { display: none; }
/* Um item de grade tem largura mínima automática igual ao seu conteúdo: sem
   este `min-width`, um botão comprido empurra o cartão para fora da tela do
   celular, e o livro sai pelo lado direito. */
.card.livro { min-width: 0; }
.card.livro .big-button {
  max-width: 100%;
  min-width: 0;
}
.card.livro .big-button .button-label {
  white-space: normal;
  overflow-wrap: break-word;
}
.card.livro #overlay-extra { overflow: visible; }
.card.livro #overlay-buttons {
  padding: 0 clamp(14px, 4vw, 22px) clamp(14px, 4vw, 20px);
  width: 100%;
}

.book { display: flex; flex-direction: column; width: 100%; }

/* A figura ocupa a largura inteira e mantém a proporção do desenho (320×200),
   para o enquadramento de cada página ser sempre o mesmo. */
.book-art {
  position: relative;
  width: 100%;
  aspect-ratio: 320 / 200;
  background: #bfe9ff;
  cursor: pointer;
  animation: pagina-vira .32s ease-out;
}
.book-art svg,
.book-img {
  display: block;
  width: 100%;
  height: 100%;
  /* As ilustrações são 16:10, igual à moldura — o `cover` só apara o meio
     pixel de arredondamento, nunca corta nada da cena. */
  object-fit: cover;
}
/* "Pular": para o adulto que já conhece a história. Fica no canto da figura,
   miúdo e discreto — não pode competir com o botão de virar a página, mas
   também não pode ficar escondido de quem procura por ele. */
.book-skip {
  position: absolute;
  top: clamp(6px, 2vw, 10px);
  right: clamp(6px, 2vw, 10px);
  border: 2px solid rgba(122, 78, 199, .22);
  background: rgba(255, 255, 255, .82);
  backdrop-filter: blur(3px);
  border-radius: 999px;
  padding: 4px 12px;
  font: inherit;
  font-size: clamp(11px, 3vw, 13px);
  font-weight: 600;
  color: var(--purple);
  cursor: pointer;
  touch-action: manipulation;
  z-index: 1;
}
.book-skip:active { transform: scale(.94); }

/* Uma sombra suave onde a figura encosta no texto: dá a dobra do papel. */
.book-art::after {
  content: '';
  position: absolute;
  left: 0; right: 0; bottom: 0;
  height: 14px;
  background: linear-gradient(to bottom, rgba(122, 78, 199, 0), rgba(122, 78, 199, .14));
  pointer-events: none;
}

.book-page {
  padding: clamp(12px, 3.6vw, 18px) clamp(16px, 5vw, 26px) clamp(6px, 2vw, 10px);
  animation: pagina-vira .32s ease-out;
}
.book-title {
  margin: 0 0 6px;
  font-size: clamp(20px, 6vw, 27px);
  color: var(--pink);
  text-shadow: 1px 2px 0 #fff, 2px 4px 0 rgba(122, 78, 199, .16);
}
.book-text {
  margin: 0 !important;
  color: var(--purple);
  font-size: clamp(14.5px, 4.1vw, 18px) !important;
  line-height: 1.5 !important;
}

/* A barra de virar página: seta, bolinhas, seta. */
.book-nav {
  display: flex;
  align-items: center;
  justify-content: center;
  gap: clamp(8px, 3vw, 14px);
  padding: clamp(6px, 2vw, 10px) 12px clamp(8px, 2.5vw, 12px);
}
.page-arrow {
  border: 2px solid #e9dcf7;
  background: #fff;
  border-radius: 999px;
  width: clamp(38px, 10vw, 46px);
  height: clamp(38px, 10vw, 46px);
  display: grid;
  place-items: center;
  padding: 0;
  cursor: pointer;
  touch-action: manipulation;
  box-shadow: 0 3px 0 rgba(122, 78, 199, .18);
}
.page-arrow:active { transform: translateY(3px); box-shadow: none; }
.page-arrow[disabled] { opacity: .3; box-shadow: none; cursor: default; }
.page-arrow .fi { width: clamp(18px, 5vw, 22px); vertical-align: 0; }

/* As bolinhas dizem de quantas páginas é o livro e onde estamos — e também
   levam direto para uma página. */
.page-dots { display: flex; align-items: center; gap: clamp(5px, 1.6vw, 8px); }
.page-dot {
  width: clamp(8px, 2.2vw, 10px);
  height: clamp(8px, 2.2vw, 10px);
  padding: 0;
  border-radius: 999px;
  border: 2px solid #d9c8f0;
  background: #fff;
  cursor: pointer;
  touch-action: manipulation;
}
.page-dot.lida { background: #d9c8f0; }
.page-dot.agora {
  background: var(--pink);
  border-color: var(--pink);
  transform: scale(1.45);
}

/* A virada de página: a figura e o texto entram deslizando de leve. */
@keyframes pagina-vira {
  from { opacity: 0; transform: translateX(14px); }
  to   { opacity: 1; transform: translateX(0); }
}

/* Celular deitado: a figura encolhe para o texto e o botão caberem. */
@media (orientation: landscape) and (max-height: 620px) {
  .card.livro { width: min(620px, 94vw); }
  .book { flex-direction: row; flex-wrap: wrap; align-items: center; }
  .book-art { width: 52%; }
  .book-page { width: 48%; padding: 8px 14px; }
  .book-title { font-size: 19px; }
  .book-text { font-size: 13px !important; line-height: 1.4 !important; }
  .book-nav { width: 100%; padding: 4px 12px 8px; }
}

/* --- Tela de carregamento --------------------------------------------- */
/* Montar o mundo leva alguns segundos num celular, e a espera é uma barra de
   progresso — só que quem a enche é a Uni, correndo da esquerda para a
   direita e deixando o arco-íris para trás. A figura dela é uma gravação do
   modelo 3D do jogo (assets/loading/uni.webp); o resto é CSS.

   As animações são todas de `transform` e `width`, e o `#loading` fica no
   index.html: assim a tela pinta no primeiro quadro e continua andando
   mesmo quando o JavaScript trava para montar o jogo. */
#loading {
  position: fixed;
  inset: 0;
  z-index: 20;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: clamp(14px, 4vw, 22px);
  background: linear-gradient(#bfe9ff, #ffe3f4);
  transition: opacity .45s ease-out;

  --barra-largura: min(300px, 76vw);
  --barra-altura: clamp(14px, 4vw, 18px);
  --uni-altura: clamp(64px, 18vw, 84px);
  /* A gravação é 300×260, então a largura sai da altura. */
  --uni-largura: calc(var(--uni-altura) * 300 / 260);
  --volta: 2.6s;                 /* uma travessia da barra, ponta a ponta */
}
#loading.pronto { opacity: 0; pointer-events: none; visibility: hidden; }

.load-brand {
  margin: 0;
  font-size: clamp(26px, 8vw, 40px);
  font-weight: 700;
  color: var(--pink);
  text-shadow: 2px 3px 0 #fff, 4px 6px 0 rgba(122, 78, 199, .2);
}
.load-text {
  margin: 0;
  font-size: clamp(13px, 3.8vw, 16px);
  font-weight: 600;
  color: var(--purple);
  opacity: .8;
}

/* A pista: o sulco da barra, o arco-íris já percorrido e a Uni em cima. */
.load-pista {
  position: relative;
  width: var(--barra-largura);
  height: var(--barra-altura);
  /* A Uni é posicionada em absoluto, então o flex não conta a altura dela e
     ela subia por cima do nome do jogo. Isto reserva o que ela ocupa acima
     da barra: da linha dos cascos (80% do quadro) até onde o desenho começa
     de fato (13%). */
  margin-top: calc(var(--uni-altura) * 0.68);
  border-radius: 999px;
  background: rgba(255, 255, 255, .7);
  box-shadow: inset 0 2px 0 rgba(122, 78, 199, .1);
}
/* O caminho já feito. O `background-size` é a barra inteira, e não o pedaço
   pintado: assim as cores ficam paradas no lugar e o arco-íris vai sendo
   revelado, em vez de espremido. */
.load-feito {
  position: absolute;
  left: 0;
  top: 0;
  bottom: 0;
  border-radius: 999px;
  background: linear-gradient(90deg, #ff7b9d, #ffb26b, #ffe36b, #8ce99a, #74c0fc, #c09cff);
  background-size: var(--barra-largura) 100%;
  animation: load-enche var(--volta) linear infinite;
}
/* Ela é sempre a ponta do que já foi feito: a barra vai até o meio dela. */
@keyframes load-enche {
  from { width: calc(var(--uni-largura) / 2); }
  to   { width: calc(100% - var(--uni-largura) / 2); }
}

.load-uni {
  position: absolute;
  left: 0;
  /* Na gravação os cascos ficam a 80% da altura do quadro; descontando os
     20% de sobra de baixo, ela pisa na beirada de cima da barra. */
  bottom: calc(var(--barra-altura) - var(--uni-altura) * 0.2);
  width: var(--uni-largura);
  height: var(--uni-altura);
  animation: load-corre var(--volta) linear infinite;
}
@keyframes load-corre {
  from { transform: translateX(0); }
  to   { transform: translateX(calc(var(--barra-largura) - var(--uni-largura))); }
}

/* As reticências que aparecem uma a uma: dá o tique-taque da espera sem
   precisar de mais nada na tela. */
.load-reticencias { animation: load-pontos 1.2s steps(1) infinite; }
@keyframes load-pontos {
  0%   { opacity: .25; }
  33%  { opacity: .55; }
  66%  { opacity: 1; }
  100% { opacity: .25; }
}

/* Quem pediu menos movimento ao aparelho vê a Uni parada no começo da barra:
   a tela continua dizendo "estou carregando", sem nada correndo. */
@media (prefers-reduced-motion: reduce) {
  #loading * { animation: none !important; }
  .load-feito { width: calc(var(--uni-largura) / 2); }
  /* O ⚡ do HUD para de pulsar, mas continua dourado quando ligado. */
  #hud-buttons #rush { animation: none; }
}

/* --- O portal que se abre ao destrancar ------------------------------- */
/* Trocar chaves por um unicórnio ou uma pista é a maior conquista do jogo —
   custa dezenas de corridas. Antes era um toast e pronto. Agora é o portal
   do livro da história (assets/story/4.webp) abrindo de verdade: o cadeado
   dourado cede, as portas giram e lá dentro está quem estava trancado.
   Tudo em CSS, sobre o retrato que a grade já usa. */
#reveal {
  position: absolute;
  inset: 0;
  z-index: 15;
  display: grid;
  place-content: center;
  gap: clamp(10px, 3vw, 18px);
  justify-items: center;
  padding: 16px;
  background: rgba(58, 34, 104, .55);
  backdrop-filter: blur(2px);
  cursor: pointer;
  animation: reveal-entra .3s ease-out;
}
#reveal[hidden] { display: none; }
#reveal.saindo { animation: reveal-sai .35s ease-in forwards; }

@keyframes reveal-entra { from { opacity: 0; } to { opacity: 1; } }
@keyframes reveal-sai { to { opacity: 0; } }

.portal {
  position: relative;
  width: min(280px, 68vw);
  aspect-ratio: 3 / 3.6;
  perspective: 700px;
  animation: portal-chega .5s cubic-bezier(.2, 1.5, .4, 1);
}
@keyframes portal-chega {
  from { transform: scale(.55); opacity: 0; }
  to   { transform: scale(1); opacity: 1; }
}

/* O arco de pedra roxa, com a mesma silhueta do desenho do livro. */
.portal-arco {
  position: absolute;
  inset: 0;
  background: linear-gradient(160deg, #8b5fd6, #5b3c96 60%, #4a2f80);
  border-radius: 50% 50% 16px 16px / 40% 40% 16px 16px;
  box-shadow: 0 10px 0 rgba(52, 32, 96, .55), inset 0 -5px 0 rgba(255, 255, 255, .14);
}
/* O vão: o escuro de dentro, onde o retrato espera. */
.portal-vao {
  position: absolute;
  inset: 9% 11% 7%;
  background: #2c1c50;
  border-radius: 50% 50% 10px 10px / 42% 42% 10px 10px;
  overflow: hidden;
  transform-style: preserve-3d;
}
/* O retrato começa como a silhueta preta do desenho e ganha cor quando as
   portas abrem — é a mesma imagem que a grade usa, sem nada extra.
   O unicórnio é uma figura recortada: flutua dentro do escuro. A pista é um
   lugar: preenche o vão inteiro, e o portal vira uma janela para lá — que é
   exatamente como ela aparece no livro da história. */
.portal-retrato {
  position: absolute;
  inset: 8%;
  width: 84%;
  height: 84%;
  object-fit: contain;
  filter: brightness(0) saturate(0) opacity(.5);
  transform: scale(.86);
  animation: portal-revela .9s ease-out 1.55s forwards;
}
.portal-retrato.lugar {
  inset: 0;
  width: 100%;
  height: 100%;
  object-fit: cover;
}

@keyframes portal-revela {
  from { filter: brightness(0) saturate(0) opacity(.5); transform: scale(.86); }
  60%  { filter: brightness(1.5) saturate(1); }
  to   { filter: none; transform: scale(1); }
}
/* O clarão que sai de dentro no instante em que abre. */
.portal-luz {
  position: absolute;
  inset: 0;
  background: radial-gradient(circle at 50% 58%, #fff6d0, rgba(255, 209, 102, 0) 68%);
  opacity: 0;
  animation: portal-luz 1.1s ease-out 1.35s;
}
@keyframes portal-luz {
  0%   { opacity: 0; }
  25%  { opacity: 1; }
  100% { opacity: 0; }
}

/* As duas folhas da porta, que giram para fora. */
.portal-porta {
  position: absolute;
  top: 0; bottom: 0;
  width: 50.5%;
  background: linear-gradient(180deg, #40286f, #2c1c50);
  animation: portal-abre .8s cubic-bezier(.5, 0, .3, 1) 1.35s forwards;
}
.portal-porta.esq { left: 0; transform-origin: left center; }
.portal-porta.dir { right: 0; transform-origin: right center; animation-name: portal-abre-dir; }
@keyframes portal-abre     { to { transform: rotateY(-105deg); } }
@keyframes portal-abre-dir { to { transform: rotateY(105deg); } }

/* O ornamento no alto do arco: o emoji de quem está sendo destrancado. */
.portal-selo {
  position: absolute;
  top: -6%;
  left: 50%;
  transform: translateX(-50%);
  width: clamp(46px, 13vw, 60px);
  height: clamp(46px, 13vw, 60px);
  display: grid;
  place-items: center;
  border-radius: 999px;
  background: linear-gradient(#ffe9a8, #ffc94f);
  box-shadow: 0 4px 0 rgba(150, 110, 20, .45);
  animation: portal-selo 1s ease-out 1.7s both;
}
.portal-selo .fi { width: 72%; }
@keyframes portal-selo {
  0%   { transform: translateX(-50%) scale(1); }
  35%  { transform: translateX(-50%) scale(1.35); }
  100% { transform: translateX(-50%) scale(1); }
}

/* O cadeado: chacoalha, o arco abre, ele cai. */
.portal-cadeado {
  position: absolute;
  left: 50%;
  top: 46%;
  width: clamp(64px, 19vw, 88px);
  margin-left: calc(clamp(64px, 19vw, 88px) / -2);
  animation: portal-cadeado-cai 1s ease-in .45s forwards;
}
@keyframes portal-cadeado-cai {
  0%   { transform: translate(0, 0) rotate(0); opacity: 1; }
  12%  { transform: translate(-6px, 0) rotate(-8deg); }
  24%  { transform: translate(6px, 0) rotate(8deg); }
  36%  { transform: translate(-5px, 0) rotate(-6deg); }
  48%  { transform: translate(0, -9px) rotate(0); opacity: 1; }
  100% { transform: translate(16px, 210px) rotate(58deg); opacity: 0; }
}
/* O arco do cadeado se solta antes de o corpo cair. */
.cadeado-haste {
  transform-origin: 76% 78%;
  animation: cadeado-abre .3s cubic-bezier(.3, 1.6, .5, 1) .8s forwards;
}
@keyframes cadeado-abre { to { transform: rotate(-38deg) translateY(-3px); } }

/* Faíscas saindo do portal no momento em que abre. */
.portal-faisca {
  position: absolute;
  left: 50%;
  top: 50%;
  width: clamp(14px, 4vw, 20px);
  opacity: 0;
  animation: portal-faisca 1.1s ease-out forwards;
}
@keyframes portal-faisca {
  0%   { opacity: 0; transform: translate(-50%, -50%) scale(.3); }
  20%  { opacity: 1; }
  100% { opacity: 0; transform: translate(var(--fx), var(--fy)) scale(1.1); }
}

.portal-nome {
  margin: 0;
  text-align: center;
  font-size: clamp(24px, 7vw, 34px);
  font-weight: 700;
  color: #fff;
  text-shadow: 2px 3px 0 rgba(60, 38, 110, .5);
  animation: portal-nome .6s ease-out 2.05s both;
}
.portal-nome small {
  display: block;
  font-size: clamp(12px, 3.4vw, 15px);
  font-weight: 500;
  opacity: .85;
  margin-top: 2px;
}
@keyframes portal-nome {
  from { opacity: 0; transform: translateY(10px); }
  to   { opacity: 1; transform: translateY(0); }
}

/* Quem pediu menos movimento vê o fim da história direto: portal aberto,
   retrato revelado, sem nada girando nem caindo. */
@media (prefers-reduced-motion: reduce) {
  #reveal, #reveal * { animation: none !important; }
  .portal-porta { transform: rotateY(-105deg); }
  .portal-porta.dir { transform: rotateY(105deg); }
  .portal-retrato { filter: none; transform: scale(1); }
  .portal-cadeado, .portal-faisca, .portal-luz { display: none; }
}

/* --- A faixa da lição (modo Aprender) --------------------------------- */
/* Fica no alto, abaixo do HUD, e só troca quando a aula troca. É o único
   texto que permanece durante a corrida: por isso é grande, curto e sai do
   caminho do que está acontecendo na pista. */
/* A caixa da lição: a frase e, embaixo, as bolinhas do progresso. Fica
   abaixo do canto de controles do HUD (pause/som, ⚡ e velocímetro) — mais
   acima, encostava no botão RÁPIDO. */
#lesson-box[hidden] { display: none; }
#lesson-box {
  position: absolute;
  left: 50%;
  top: clamp(178px, 45vw, 224px);
  transform: translateX(-50%);
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: clamp(6px, 1.8vw, 10px);
  pointer-events: none;
}

#lesson {
  margin: 0;
  max-width: min(460px, 90vw);
  padding: clamp(7px, 2.2vw, 11px) clamp(14px, 4vw, 22px);
  border-radius: 999px;
  border: 3px solid #fff;
  background: rgba(255, 255, 255, .88);
  box-shadow: 0 5px 0 rgba(122, 78, 199, .18);
  color: var(--purple);
  font-size: clamp(13px, 3.9vw, 18px);
  font-weight: 700;
  line-height: 1.25;
  text-align: center;
  pointer-events: none;
}
#lesson[hidden] { display: none; }
#lesson .fi { vertical-align: -0.18em; }
/* Aula nova entra com um pulinho, para o olho perceber que mudou. */
#lesson.nova { animation: licao-entra .45s cubic-bezier(.2, 1.5, .4, 1); }
@keyframes licao-entra {
  from { transform: scale(.8); opacity: 0; }
  to   { transform: scale(1); opacity: 1; }
}
@media (prefers-reduced-motion: reduce) {
  #lesson.nova { animation: none; }
}

/* --- Setas, ✅ e progresso da lição ----------------------------------- */
/* O progresso: uma bolinha por aula, logo abaixo da faixa. É a mesma
   linguagem das páginas do livro da história — quem já entendeu uma entende
   a outra. */
#lesson-dots {
  display: flex;
  gap: clamp(4px, 1.4vw, 7px);
  pointer-events: none;
}
#lesson-dots[hidden] { display: none; }
#lesson-dots i {
  width: clamp(6px, 1.8vw, 9px);
  height: clamp(6px, 1.8vw, 9px);
  border-radius: 999px;
  background: rgba(255, 255, 255, .75);
  box-shadow: 0 1px 0 rgba(122, 78, 199, .2);
}
#lesson-dots i.feita { background: #ffd166; }
#lesson-dots i.agora { background: var(--pink); transform: scale(1.5); }

/* A seta do movimento pedido. Fica acima dos botões de toque, grande e
   pulando: é o único jeito de dizer "faça isto" para quem não lê. */
#lesson-hint {
  position: absolute;
  left: 0;
  right: 0;
  bottom: calc(90px + env(safe-area-inset-bottom));
  display: flex;
  justify-content: center;
  /* Mesmo espaçamento e mesma largura de casa dos #touch-controls: é isso
     que faz cada seta cair em cima do seu botão, em vez de todas no meio
     (onde ficavam em cima do próprio unicórnio). */
  gap: clamp(14px, 6vw, 28px);
  padding: 0 12px;
  pointer-events: none;
}
#lesson-hint[hidden] { display: none; }
#lesson-hint > span {
  /* Exatamente a largura de um botão de toque. */
  width: clamp(58px, 17vw, 78px);
  display: flex;
  justify-content: center;
}
#lesson-hint .fi {
  width: clamp(38px, 11vw, 54px);
  height: clamp(38px, 11vw, 54px);
  filter: drop-shadow(0 4px 0 rgba(122, 78, 199, .3));
  animation: seta-pede 1s ease-in-out infinite;
}
#lesson-hint .fi:nth-child(2) { animation-delay: .12s; }
/* Duas setas na mesma casa (o pulo duplo): encolhem para caber na largura de
   um botão, e a segunda pula depois — que é a ordem dos dois toques. */
#lesson-hint > span.duplo .fi { width: clamp(26px, 8vw, 38px); height: clamp(26px, 8vw, 38px); }
#lesson-hint > span.duplo { gap: 2px; }
@keyframes seta-pede {
  0%, 100% { transform: translateY(0) scale(1); }
  50%      { transform: translateY(-10px) scale(1.12); }
}

/* No celular o próprio botão acende junto: assim a criança não precisa
   traduzir a seta da tela para o botão embaixo do polegar. */
#touch-controls button.pedindo {
  border-color: var(--pink);
  background: #fff0f6;
  animation: botao-pede 1s ease-in-out infinite;
}
@keyframes botao-pede {
  0%, 100% { box-shadow: 0 4px 0 rgba(122, 78, 199, .25), 0 0 0 0 rgba(255, 93, 143, .5); }
  60%      { box-shadow: 0 4px 0 rgba(122, 78, 199, .25), 0 0 0 12px rgba(255, 93, 143, 0); }
}

/* O ✅ de "isso mesmo": grande, no meio, e sai rápido — é confirmação, não
   comemoração. */
#lesson-ok {
  position: absolute;
  left: 50%;
  top: 44%;
  transform: translate(-50%, -50%);
  pointer-events: none;
}
#lesson-ok[hidden] { display: none; }
#lesson-ok .fi {
  width: clamp(70px, 22vw, 110px);
  height: clamp(70px, 22vw, 110px);
  filter: drop-shadow(0 6px 0 rgba(122, 78, 199, .25));
}
/* `forwards` é o que impede a segunda piscada: sem ele, o ícone volta ao
   estado normal (opaco, tamanho cheio) no instante em que a animação acaba e
   fica assim até o `hidden` chegar — meio segundo depois do certinho já ter
   sumido, ele reaparecia. */
#lesson-ok.bate .fi { animation: acertou .85s cubic-bezier(.2, 1.6, .4, 1) forwards; }
@keyframes acertou {
  0%   { transform: scale(.2) rotate(-18deg); opacity: 0; }
  35%  { transform: scale(1.15) rotate(4deg); opacity: 1; }
  55%  { transform: scale(1) rotate(0); opacity: 1; }
  100% { transform: scale(1.1) rotate(0); opacity: 0; }
}

@media (prefers-reduced-motion: reduce) {
  #lesson-hint .fi, #touch-controls button.pedindo, #lesson-ok.bate .fi { animation: none; }
}


/* --- Confete de aula concluída --------------------------------------- */
/* Cada aula vencida solta um punhado de papelzinho colorido do meio da tela.
   São elementos de verdade, criados e jogados fora a cada vez (uns 18, por
   uns 1,3 s) — barato o bastante para acontecer 17 vezes numa lição. */
#confetti {
  position: absolute;
  left: 50%;
  top: 44%;
  width: 0;
  height: 0;
  pointer-events: none;
}
#confetti i {
  position: absolute;
  width: clamp(7px, 2vw, 10px);
  height: clamp(10px, 2.8vw, 14px);
  border-radius: 2px;
  opacity: 0;
  animation: confete 1.25s cubic-bezier(.15, .6, .35, 1) forwards;
}
@keyframes confete {
  0%   { opacity: 1; transform: translate(0, 0) rotate(0) scale(.6); }
  15%  { opacity: 1; }
  100% { opacity: 0; transform: translate(var(--x), var(--y)) rotate(var(--giro)) scale(1); }
}
@media (prefers-reduced-motion: reduce) {
  #confetti { display: none; }
}

/* O que se conquista em vez de comprar (o Eco): troféu dourado no lugar da
   etiqueta de preço, para não parecer que custa zero. */
.cast-price.conquista {
  background: #fff6dd;
  border-color: #ffd166;
  color: #b07a12;
}

/* O retrato de quem ainda é mistério (o Eco): silhueta em vez do desenho.
   Ele é invisível na história — a lista não pode entregar quem ele é antes
   de a criança chegar lá.

   O `filter` pinta o elemento inteiro, fundo incluído: sem tirar o branco do
   `.shop-face`, a silhueta virava um retângulo cinza em vez do contorno do
   unicórnio. */
/* O seletor precisa ser mais específico que `.cast-card.trancado
   .cast-face`, que já desbota todo trancado — aquele tem três classes e
   vencia este, e a sombra saía apenas pálida em vez de preta. */
.cast-card.trancado .cast-face.sombra,
.shop-face.sombra {
  filter: brightness(0) opacity(.55);
}
/* E sem o desbote do trancado por cima: a sombra já é a informação. */
.cast-card.trancado .cast-face.sombra { opacity: .8; }
.shop-face.sombra {
  background: none;
  border-color: transparent;
}

/* --- O unicórnio de perto, para girar (ver models/viewer3d.js) ----------- */

/* A etiquetinha no canto do retrato, na ficha. Discreta de propósito: a
   decisão da tela é o botão grande lá embaixo. */
.shop-retrato {
  position: relative;
  display: inline-block;
  line-height: 0;
}
.ver3d {
  position: absolute;
  right: -8px;
  bottom: -6px;
  display: inline-flex;
  align-items: center;
  gap: 3px;
  padding: 4px 10px 4px 7px;
  border: 2px solid #f3dcef;
  border-radius: 999px;
  background: #fff;
  color: #a163c9;
  font: 600 .78rem/1 inherit;
  font-family: inherit;
  cursor: pointer;
  box-shadow: 0 2px 6px rgba(150, 90, 170, .18);
}
.ver3d .fi { width: 15px; height: 15px; }
.ver3d:hover { background: #fdf4ff; }
.ver3d:active { transform: translateY(1px); }

.viewer-vaga {
  display: flex;
  justify-content: center;
}
.viewer3d {
  width: 100%;
  max-width: 420px;
  border-radius: 22px;
  background: linear-gradient(#fff9fd, #f6ecff);
  border: 3px solid #f3dcef;
  overflow: hidden;
  /* O dedo aqui gira o bicho; sem isto o navegador entenderia o arrasto
     como rolagem do cartão e o unicórnio não sairia do lugar. */
  touch-action: none;
  cursor: grab;
}
.viewer3d.girando { cursor: grabbing; }
.viewer3d-tela {
  display: block;
  width: 100%;
  height: auto;
}
.viewer-dica {
  margin: 10px 0 0 !important;
  text-align: center;
  font-size: .82rem;
  color: #a98bc4;
}


/* --- Ouvir a ficha, para quem ainda não lê ------------------------------- */

.ouvir {
  float: right;
  margin: 0 0 4px 8px;
  width: 38px;
  height: 38px;
  display: inline-flex;
  align-items: center;
  justify-content: center;
  border: 2px solid #f3dcef;
  border-radius: 50%;
  background: #fff;
  cursor: pointer;
  box-shadow: 0 2px 6px rgba(150, 90, 170, .16);
}
.ouvir .fi { width: 20px; height: 20px; }
.ouvir:hover { background: #fdf4ff; }
.ouvir:active { transform: translateY(1px); }


/* --- A lista de ajustes do cantinho dos adultos -------------------------- */
/*
   Linha compacta, e não botão-pílula: são seis ajustes, e com um botão
   grande para cada um a fileira passava da tela do celular. Além de caber,
   linha é o que esta tela é — aqui não se joga, se configura.
*/
.ajustes {
  display: flex;
  flex-direction: column;
  gap: 6px;
  width: 100%;
}
.ajuste {
  display: grid;
  /* `minmax(0, …)` no nome: com o `1fr` puro a coluna não encolhe abaixo do
     próprio texto e espreme o valor até sumir. */
  grid-template-columns: 26px minmax(0, 1fr) auto;
  align-items: center;
  gap: 10px;
  padding: 11px 14px;
  border: 2px solid #f3dcef;
  border-radius: 14px;
  background: #fff;
  font: inherit;
  color: var(--purple);
  text-align: left;
  cursor: pointer;
}
.ajuste:active { transform: translateY(1px); }
.ajuste.aviso { border-color: #ffb3c8; background: #fff4f7; }
.ajuste-icone { font-size: 1.05rem; line-height: 1; }
.ajuste-icone .fi { width: 20px; height: 20px; }
.ajuste-nome {
  font-weight: 600;
  font-size: .95rem;
  min-width: 0;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.ajuste-valor {
  font-size: .82rem;
  color: #a98bc4;
  /* Em `ch`, e não em `%`.
     Porcentagem aqui resolve contra a própria coluna, que é `auto` e depende
     do conteúdo: a conta fica circular e o navegador colapsava o valor para
     uns 20px — no celular dava para ver duas letras e reticências, ou seja,
     depois de mudar um ajuste não dava para conferir o que ficou. */
  max-width: 13ch;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}

/* --- Escolher a voz, no cantinho dos adultos ----------------------------- */

.voz-lista {
  display: flex;
  flex-direction: column;
  gap: 6px;
}
.voz-item {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 10px;
  padding: 11px 14px;
  border: 2px solid #f3dcef;
  border-radius: 14px;
  background: #fff;
  font: inherit;
  font-size: .92rem;
  color: #7a4ec7;
  text-align: left;
  cursor: pointer;
}
.voz-item.escolhida {
  border-color: var(--pink);
  background: #fff4fa;
  font-weight: 600;
}
.voz-item:active { transform: translateY(1px); }
.voz-nome { overflow: hidden; text-overflow: ellipsis; white-space: nowrap; }
.voz-marca .fi { width: 16px; height: 16px; }


/* --- A contagem antes de largar (3, 2, 1, Vai!) -------------------------- */

#contagem {
  position: absolute;
  left: 50%;
  top: 42%;
  translate: -50% -50%;
  z-index: 17;              /* acima do HUD, abaixo do toast e do cartão */
  pointer-events: none;
  font-size: clamp(64px, 22vw, 130px);
  font-weight: 700;
  color: var(--pink);
  /* O mesmo contorno do letreiro do jogo: legível em qualquer pista, da
     grama clara do Campo ao roxo escuro da Noite. */
  text-shadow:
    3px 4px 0 #fff, -3px 4px 0 #fff, 3px -2px 0 #fff, -3px -2px 0 #fff,
    5px 8px 0 rgba(122, 78, 199, .3);
}
#contagem.pop { animation: contagem-pop .5s ease-out; }

@keyframes contagem-pop {
  0% { opacity: 0; scale: 1.6; }
  22% { opacity: 1; scale: 1; }
  75% { opacity: 1; scale: 1; }
  100% { opacity: 0; scale: .82; }
}

@media (prefers-reduced-motion: reduce) {
  #contagem.pop { animation: none; }
}
