/* css/base.css — estrutura e layout. Só var(), zero hex cru. */
/* ============================================================
   🗺️ MAPA DA CASCATA — leia antes de mexer em botão da prancha
   (levantado em 12/08/2026 com ajuda do DeepSeek, arquivo com 1400 linhas)

   Este arquivo tem CAMADAS que se sobrescrevem. Quem vence NÃO é a regra mais
   específica que você lembra: é a ÚLTIMA que casa. Já quebrou o app duas vezes.

   '.botao-prancha' — o cartão
     min-height  declarado em 4 lugares → vence 'min-height: 124px' (base),
                 e '92px' dentro de '@media (max-height: 620px)'
     padding     em 3 → vence o da '@media (max-width: 900px)', no fim
     justify-content em 3 → vence 'space-between' (≤900px)
     max-height  ⚠️ a regra de '@media (max-height: 620px)' está MORTA:
                 '#prancha > *' com 'clamp(120px, 34vw, 210px)' vem depois

   '.simbolo' — o quadro do desenho
     width/height → vence 'width: 100%; height: auto' da '@media (max-width: 900px)'
     ⛔ NUNCA pôr 'flex: 0 1 auto' aqui: encolher só a altura de um círculo o
        vira elipse e leva o desenho junto (aconteceu, print às 13h24)

   '.palavra'
     font-size → vence 'clamp(16px, 0.8em, 26px)'. ⛔ O piso 16px é do DESIGN.md
     flex      → '0 0 auto': a palavra NUNCA encolhe. Quem cede é a figura

   🥇 REGRA DE OURO deste arquivo: mudança de tamanho no celular vai na camada
   '@media (max-width: 900px)', que é a última. Escrever antes não faz efeito.
   ============================================================ */

* { box-sizing: border-box; margin: 0; padding: 0; }

html, body {
  height: 100%; overflow: hidden;
  font-family: var(--fonte); font-size: var(--fonte-base);
  color: var(--cor-texto); background: var(--cor-fundo);
  -webkit-tap-highlight-color: transparent;
  user-select: none; -webkit-user-select: none;
}

#app {
  display: flex; flex-direction: column; height: 100%; max-width: 800px; margin: 0 auto;
}

/* --- categorias --- */
#categorias {
  display: flex; gap: var(--esp-4); padding: var(--esp-8);
  overflow-x: auto; -webkit-overflow-scrolling: touch; scrollbar-width: none;
  border-bottom: var(--borda);
  min-height: calc(var(--toque-min) + var(--esp-8));
  align-items: center; flex-shrink: 0;
}
#categorias::-webkit-scrollbar { display: none; }

.cat-btn {
  flex-shrink: 0; min-width: var(--toque-min); min-height: var(--toque-min);
  border: var(--borda); border-radius: var(--raio);
  background: var(--cor-fundo); color: var(--cor-texto);
  font-family: var(--fonte); font-size: calc(var(--fonte-base) * 0.85);
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: 2px; cursor: pointer; padding: var(--esp-4);
}
.cat-btn .icone { font-size: calc(var(--fonte-base) * 1.4); }
.cat-btn.ativa {
  background: var(--cor-turquesa); color: var(--cor-fundo); border-color: var(--cor-turquesa);
}

/* --- prancha --- */
#prancha {
  flex: 1; overflow-y: auto; -webkit-overflow-scrolling: touch;
  padding: var(--esp-8); display: grid; gap: var(--esp-8); align-content: start;
}
#prancha.grid-2 { grid-template-columns: repeat(2, minmax(0, 1fr)); }
#prancha.grid-3 { grid-template-columns: repeat(3, minmax(0, 1fr)); }
#prancha.grid-4 { grid-template-columns: repeat(4, minmax(0, 1fr)); }

.botao-prancha {
  aspect-ratio: 1; min-width: var(--toque-min); min-height: var(--toque-min);
  border: var(--borda); border-radius: var(--raio);
  background: var(--cor-fundo); color: var(--cor-texto);
  font-family: var(--fonte); font-size: var(--fonte-base);
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: var(--esp-4); cursor: pointer; padding: var(--esp-8);
  text-align: center; word-break: break-word; overflow: hidden;
}
.botao-prancha:active { background: var(--cor-turquesa); color: var(--cor-fundo); }
.botao-prancha .simbolo { font-size: 2em; line-height: 1; }
.botao-prancha .simbolo-img {
  width: 2.5em; height: 2.5em;
  object-fit: contain; border-radius: var(--esp-8);
}
.botao-prancha .palavra {
  font-size: 0.85em; font-weight: 500; line-height: 1.15;
}

/* --- barra de frase --- */
#barra-frase {
  display: flex; gap: var(--esp-8); padding: var(--esp-8);
  border-top: var(--borda); align-items: center; flex-shrink: 0;
  min-height: calc(var(--toque-min) + var(--esp-8));
}
#frase-container {
  flex: 1; display: flex; flex-wrap: wrap; gap: var(--esp-4); align-items: center;
  min-height: calc(var(--toque-min) - var(--esp-8)); padding: var(--esp-8);
  border: var(--borda); border-radius: var(--raio); background: var(--cor-fundo);
  overflow-y: auto; max-height: calc(var(--toque-min) * 1.5);
}
.chip-frase {
  background: var(--cor-turquesa); color: var(--cor-fundo);
  padding: var(--esp-4) var(--esp-8); border-radius: var(--raio);
  font-family: var(--fonte); font-size: calc(var(--fonte-base) * 0.9); font-weight: 500;
}

.btn-acao {
  min-width: var(--toque-min); min-height: var(--toque-min);
  border: var(--borda); border-radius: var(--raio);
  font-family: var(--fonte); font-size: calc(var(--fonte-base) * 0.85); font-weight: 600;
  cursor: pointer; display: flex; flex-direction: column;
  align-items: center; justify-content: center; gap: 2px;
  padding: var(--esp-4); flex-shrink: 0;
}
.btn-falar {
  background: var(--cor-turquesa); color: var(--cor-fundo);
  border-color: var(--cor-turquesa); font-size: calc(var(--fonte-base) * 1.1);
}
.btn-falar:active { background: var(--cor-azul); }
.btn-apagar, .btn-limpar { background: var(--cor-fundo); color: var(--cor-texto); }
.btn-apagar:active, .btn-limpar:active { background: var(--cor-rosa); color: var(--cor-fundo); }

/* --- ajustes --- */
#painel-ajustes {
  position: fixed; top: 0; right: 0; bottom: 0; left: 0; inset: 0; background: var(--cor-fundo); z-index: 100;
  display: flex; flex-direction: column; overflow-y: auto;
  -webkit-overflow-scrolling: touch;
}
#painel-ajustes.escondido { display: none; }

.ajustes-header {
  display: flex; align-items: center; justify-content: space-between;
  padding: var(--esp-16); border-bottom: var(--borda); flex-shrink: 0;
}
.ajustes-header h2 { font-size: calc(var(--fonte-base) * 1.2); font-weight: 600; }
/* 🐛 11/08/2026: a lista de ajustes aparecia espremida numa faixa curta que
   rolava por dentro, enquanto o texto legal de baixo aparecia grande e solto.
   Causa: DUAS rolagens aninhadas — '#painel-ajustes' já é 'overflow-y: auto',
   e este bloco pedia 'flex: 1' + 'overflow-y: auto' de novo. O 'flex: 1' fazia
   o corpo caber na altura que sobrava e rolar sozinho lá dentro.
   ⇒ Uma rolagem só, a do painel. 'flex: 0 0 auto' = o corpo tem a altura do
   conteúdo e a página inteira rola junto, como qualquer tela. */
.ajustes-corpo {
  flex: 0 0 auto; padding: var(--esp-16);
  display: flex; flex-direction: column; gap: var(--esp-24);
}
/* ============================================================
   TREINO DO PARCEIRO — "Como conversar usando a prancha"
   🔬 A intervenção com melhor evidência do campo. Ver js/ui/parceiro.js.
   ============================================================ */
#painel-parceiro {
  position: fixed; inset: 0; background: var(--cor-fundo); z-index: 110;
  display: flex; flex-direction: column; overflow-y: auto;
  -webkit-overflow-scrolling: touch;
}
#painel-parceiro.escondido { display: none; }

/* o tutorial de primeira abertura usa a mesma casca do painel acima — mesma
   navegação, mesmo tamanho de texto. ⛔ Não inventar um segundo estilo de
   painel: duas telas parecidas com desenhos diferentes é o que faz app parecer
   remendado. z-index acima do painel de ajustes, porque pode ser aberto de lá. */
#painel-tutorial {
  position: fixed; inset: 0; background: var(--cor-fundo); z-index: 120;
  display: flex; flex-direction: column; overflow-y: auto;
  -webkit-overflow-scrolling: touch;
}
#painel-tutorial.escondido { display: none; }

/* 🔴 O TEXTO ENCOSTAVA NA BORDA. Print dele no celular, 13/08: o título e o
   texto do tutorial começavam no pixel 0, enquanto todos os outros painéis do
   app respiram 16px. Eu criei o '#tutorial-conteudo' e esqueci que o recuo
   mora no CONTEÚDO, não no painel.
   🥇 Regra: painel novo copia o espaçamento do painel que ele imita — aqui, o
      mesmo do '#parceiro-conteudo'. Tela sem margem parece defeito, não estilo. */
#tutorial-conteudo {
  padding: var(--esp-24) var(--esp-16);
  max-width: 640px; margin: 0 auto; width: 100%;
}
#painel-tutorial .parceiro-navegacao { max-width: 640px; margin: 0 auto; width: 100%; }

/* 🔴 E NO EDITOR ADULTO a fileira de botões vazava para FORA da tela: medido
   em 390px de largura, o ✕ terminava no pixel 391. O adulto tenta apertar
   "remover" e o dedo cai na borda do aparelho.
   A causa: '.info' com 'flex: 1' empurrava, e as ações não tinham permissão de
   ceder — nem de quebrar para a linha de baixo quando a palavra é longa.
   ⛔ 'min-width: auto' é o padrão de item flex e é o que impede o encolhimento:
      sem 'min-width: 0' no '.info', ela se recusa a ficar menor que o texto. */
.editor-btn-item { flex-wrap: wrap; }
.editor-btn-item .info { min-width: 0; overflow-wrap: anywhere; }
.editor-btn-item .acoes { flex-shrink: 0; margin-left: auto; }


/* o convite, primeiro item dos Ajustes */
.cartao-parceiro {
  display: flex; flex-direction: column; align-items: flex-start;
  gap: var(--esp-4); width: 100%; text-align: left;
  padding: var(--esp-16); line-height: 1.35;
}
.cartao-parceiro-titulo { font-size: calc(var(--fonte-base) * 1.05); font-weight: 700; }
.cartao-parceiro-sub { font-size: calc(var(--fonte-base) * 0.85); font-weight: 400; opacity: .92; }

#parceiro-conteudo {
  padding: var(--esp-24) var(--esp-16);
  max-width: 640px; margin: 0 auto; width: 100%;
}
.parceiro-passo {
  font-size: calc(var(--fonte-base) * 0.85); font-weight: 700;
  color: var(--cor-azul); margin-bottom: var(--esp-8);
}
.parceiro-titulo {
  font-size: calc(var(--fonte-base) * 1.4); line-height: 1.2;
  margin-bottom: var(--esp-16);
}
.parceiro-texto {
  font-size: calc(var(--fonte-base) * 1.05); line-height: 1.5;
  margin-bottom: var(--esp-16);
}
/* o exemplo é o que faz a dica virar ação: fica marcado, não solto no meio */
.parceiro-exemplo {
  font-size: var(--fonte-base); line-height: 1.5;
  padding: var(--esp-12) var(--esp-16);
  border-left: 4px solid var(--cor-turquesa);
  background: #F3FAF9;
  border-radius: var(--raio);
}
.parceiro-navegacao {
  display: flex; gap: var(--esp-8); padding: var(--esp-16);
  max-width: 640px; margin: 0 auto; width: 100%;
}
/* 🐛 26/08/2026 — o "‹ Anterior" era um retângulo de canto reto e sem cor:
   nunca ganhou estilo próprio, só herdava o do navegador. Enquanto vivia
   apagado por opacidade ninguém reparava; ao ficar legível, ficou torto ao
   lado do "Próximo". Agora é um botão secundário de verdade, com o MESMO
   raio do irmão. */
.parceiro-navegacao button,
.backup-botoes button {
  flex: 1; min-height: var(--toque-min);
  background: var(--cor-cartao, #fff); color: var(--cor-texto);
  border: var(--borda); border-radius: var(--raio);
  font-family: var(--fonte-titulo); font-weight: 800;
  font-size: calc(var(--fonte-base) * 1.05); cursor: pointer;
}
/* ⚠️ Botão desabilitado precisa PARECER desabilitado, senão o pai acha que o
   app travou. Opacidade sozinha não basta: o cursor também muda. */
.parceiro-navegacao button:disabled,
.backup-botoes button:disabled {
  /* ⛔ NADA de 'opacity' aqui — ver o comentário do '--desab-texto' no tema. */
  background: var(--desab-fundo); color: var(--desab-texto);
  border: 1px solid var(--desab-borda); box-shadow: none;
  cursor: not-allowed;
}
/* o de ação continua mandando: a classe vem depois e não pode ser apagada
   pelo estilo secundário acima. */
.parceiro-navegacao button.primario,
.backup-botoes button.primario { border: none; }

/* 🐛 26/08/2026 — O MESMO BUG DO "‹ Anterior", ESPALHADO PELOS AJUSTES.
   "Duplicar", "Renomear", "Apagar" e "Recuperar cópia" nunca ganharam estilo:
   saíam como retângulo cinza de canto reto, na fonte do navegador, ao lado de
   "+ Nova prancha" e "Salvar cópia" que são redondos e na fonte da marca.
   O adulto lia aquilo como "botão quebrado" ou nem via que era botão.
   🥇 Por isso a regra virou UMA, servindo os dois lugares, em vez de copiada:
      peça consertada num lugar só melhora todo mundo de uma vez.
   ⛔ Não criar um terceiro estilo de botão secundário — acrescentar o seletor
      novo NESTA regra. */

.ajustes-grupo { display: flex; flex-direction: column; gap: var(--esp-8); }
.ajustes-grupo label { font-weight: 600; font-size: calc(var(--fonte-base) * 0.9); }
.ajustes-grupo select, .ajustes-grupo input {
  padding: var(--esp-8) var(--esp-12); border: var(--borda); border-radius: var(--raio);
  font-family: var(--fonte); font-size: var(--fonte-base); min-height: var(--toque-min);
}
.ajustes-grupo .range-row { display: flex; align-items: center; gap: var(--esp-8); }
.ajustes-grupo input[type="range"] { flex: 1; }
.ajustes-grupo .range-valor {
  min-width: 3ch; text-align: center; font-weight: 600;
}
.ajustes-rodape {
  padding: var(--esp-16); border-top: var(--borda); text-align: center; flex-shrink: 0;
}

/* --- modo adulto --- */
#painel-adulto {
  position: fixed; top: 0; right: 0; bottom: 0; left: 0; inset: 0; background: var(--cor-fundo); z-index: 200;
  display: flex; flex-direction: column; overflow-y: auto;
}
#painel-adulto.escondido { display: none; }
.editor-header {
  display: flex; align-items: center; justify-content: space-between;
  padding: var(--esp-16); border-bottom: var(--borda); flex-shrink: 0;
}
.editor-header h2 { font-size: calc(var(--fonte-base) * 1.2); font-weight: 600; }
.editor-corpo {
  flex: 1; overflow-y: auto; padding: var(--esp-16);
  display: flex; flex-direction: column; gap: var(--esp-16);
}
.editor-cat { margin-bottom: var(--esp-16); }
.editor-cat h3 { font-size: var(--fonte-base); font-weight: 600; margin-bottom: var(--esp-8); }
.editor-btn-lista { display: flex; flex-direction: column; gap: var(--esp-4); }
.editor-btn-item {
  display: flex; align-items: center; gap: var(--esp-8);
  padding: var(--esp-8); border: var(--borda); border-radius: var(--raio);
  background: var(--cor-fundo);
}
.editor-btn-item .simbolo { font-size: calc(var(--fonte-base) * 1.5); }
.editor-btn-item .info { flex: 1; font-size: calc(var(--fonte-base) * 0.85); }
.editor-btn-item .acoes { display: flex; gap: var(--esp-4); }
.editor-btn-item button {
  min-width: var(--esp-32); min-height: var(--esp-32);
  border: var(--borda); border-radius: var(--raio);
  background: var(--cor-fundo); cursor: pointer; font-size: var(--fonte-base);
}

/* --- trava --- */
#trava-tela {
  position: fixed; top: 0; right: 0; bottom: 0; left: 0; inset: 0; background: var(--cor-fundo); z-index: 500;
  display: flex; flex-direction: column; align-items: center; justify-content: center;
  gap: var(--esp-24);
}
#trava-tela.escondido { display: none; }
#trava-tela .icone-trava { font-size: calc(var(--fonte-base) * 3); }
#trava-tela input {
  padding: var(--esp-12); border: var(--borda); border-radius: var(--raio);
  font-family: var(--fonte); font-size: var(--fonte-base);
  text-align: center; max-width: 200px;
}

/* --- modal PIN --- */
.modal-pin {
  position: fixed; top: 0; right: 0; bottom: 0; left: 0; inset: 0; background: rgba(0,0,0,0.4); z-index: 300;
  display: flex; align-items: center; justify-content: center;
}
.modal-pin.escondido { display: none; }
.modal-pin .caixa {
  background: var(--cor-fundo); padding: var(--esp-24);
  border-radius: var(--raio); border: var(--borda);
  display: flex; flex-direction: column; gap: var(--esp-16);
  min-width: 260px; text-align: center;
}
.modal-pin input {
  padding: var(--esp-12); border: var(--borda); border-radius: var(--raio);
  font-family: var(--fonte); font-size: var(--fonte-base); text-align: center;
}
.modal-pin .pin-botoes { display: flex; gap: var(--esp-8); justify-content: center; }
.modal-pin .pin-botoes button {
  flex: 1; padding: var(--esp-8); border: var(--borda); border-radius: var(--raio);
  font-family: var(--fonte); font-size: var(--fonte-base); cursor: pointer;
  background: var(--cor-fundo);
}
.modal-pin .pin-botoes .ok {
  background: var(--cor-turquesa); color: var(--cor-fundo); border-color: var(--cor-turquesa);
}

/* --- botões flutuantes --- */
#btn-ajustes, #btn-adulto, #btn-trava {
  position: fixed; z-index: 50; width: var(--esp-48); height: var(--esp-48);
  border-radius: 50%; border: var(--borda); background: var(--cor-fundo);
  font-size: calc(var(--fonte-base) * 1.2); cursor: pointer;
  display: flex; align-items: center; justify-content: center;
}
#btn-ajustes { bottom: calc(var(--toque-min) + var(--esp-24)); right: var(--esp-8); }
#btn-adulto { bottom: calc(var(--toque-min) + var(--esp-24)); right: calc(var(--esp-48) + var(--esp-16)); }
#btn-trava { bottom: calc(var(--toque-min) + var(--esp-24)); right: calc(var(--esp-48) * 2 + var(--esp-24)); }

/* --- utilitários --- */
button.primario {
  background: var(--cor-turquesa); color: var(--cor-fundo); border: none;
  border-radius: var(--raio); padding: var(--esp-8) var(--esp-16);
  font-family: var(--fonte); font-size: var(--fonte-base); font-weight: 600;
  cursor: pointer; min-height: var(--toque-min);
}
button.primario:active { background: var(--cor-azul); }
.escondido { display: none !important; }

/* --- consentimento --- */
/* 🐛 CELULAR DEITADO: NINGUÉM CONSEGUIA ENTRAR NO APP.
   A caixa tem 677px de altura; numa tela de 375 o topo saía cortado e o
   botão "Sou o responsável e autorizo" ficava 113px ABAIXO da tela — e o
   overlay não rolava ('overflow: visible'). O app inteiro ficava
   inacessível na horizontal.
   'overflow-y: auto' + 'align-items: flex-start' fazem a caixa rolar em
   vez de centralizar e vazar. ⚠️ Centralizar conteúdo mais alto que a tela
   corta dos DOIS lados e não há rolagem que alcance. */
#overlay-consentimento {
  position: fixed; top: 0; right: 0; bottom: 0; left: 0; inset: 0; background: var(--cor-fundo); z-index: 9999;
  display: flex; align-items: flex-start; justify-content: center;
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  padding: var(--esp-24);
}
/* quando cabe, continua centralizado como antes */
@media (min-height: 700px) { #overlay-consentimento { align-items: center; } }
#overlay-consentimento.escondido { display: none; }
.consentimento-caixa {
  max-width: 480px; display: flex; flex-direction: column; gap: var(--esp-16);
}
.consentimento-caixa h2 {
  font-size: calc(var(--fonte-base) * 1.3); font-weight: 700; line-height: 1.3;
}
.consentimento-caixa p {
  font-size: var(--fonte-base); line-height: 1.5;
}
.consentimento-botoes {
  display: flex; gap: var(--esp-8); margin-top: var(--esp-8);
}
.consentimento-botoes button {
  flex: 1; padding: var(--esp-12); border: var(--borda); border-radius: var(--raio);
  font-family: var(--fonte); font-size: var(--fonte-base); font-weight: 600;
  cursor: pointer; min-height: var(--toque-min);
}

#tela-sair {
  position: fixed; top: 0; right: 0; bottom: 0; left: 0; inset: 0; background: var(--cor-fundo); z-index: 10000;
  display: flex; align-items: center; justify-content: center;
  overflow-y: auto;   /* mesma proteção do consentimento */
}
#tela-sair.escondido { display: none; }

/* --- seções legais nos ajustes --- */
.ajustes-secao {
  /* padding lateral incluído: o aviso RDC e o crédito da licença
     renderizavam colados nas bordas da tela */
  padding: var(--esp-16); border-top: var(--borda);
  display: flex; flex-direction: column; gap: var(--esp-8);
}
.ajustes-secao:first-of-type { border-top: none; }
.ajustes-secao h3 {
  font-size: calc(var(--fonte-base) * 1.05); font-weight: 700;
}
.ajustes-secao p {
  font-size: calc(var(--fonte-base) * 0.85); line-height: 1.45;
}
.ajustes-secao button {
  padding: var(--esp-12); border: none; border-radius: var(--raio);
  font-family: var(--fonte); font-size: var(--fonte-base); font-weight: 600;
  cursor: pointer; min-height: var(--toque-min);
}

/* --- alto contraste --- */
body.alto-contraste .cat-btn.ativa {
  background: var(--cor-turquesa); color: var(--hc-fundo);
}
body.alto-contraste .chip-frase {
  background: var(--cor-turquesa); color: var(--hc-fundo);
}
body.alto-contraste .btn-falar {
  background: var(--cor-turquesa); color: var(--hc-fundo);
}
body.alto-contraste .modal-pin { background: rgba(255,255,255,0.3); }

/* ============================================================
   CAMADA VISUAL — redesign de 10/08/2026
   Mesma lógica do app adulto, com a marca Balbuu.
   Regra: nenhuma cor crua aqui, tudo vem de css/tema.css.
   ============================================================ */

body { background: var(--cor-fundo); }

/* ---------- O VISOR: a frase é a estrela ---------- */
/* 🐛 CORRIGIDO 10/08 noite: aqui estava 'display: block', que apagava o
   'display: flex' da regra original. Resultado: os três botões desciam
   empilhados soltos na esquerda e o visor comia 40% da tela em branco.
   O '<footer>' também é o último no HTML, então ia parar no rodapé; o
   'order: -1' o traz para o topo, igual ao app adulto. */
#barra-frase {
  display: flex;
  flex-wrap: wrap;
  align-items: center;
  gap: var(--esp-8);
  order: -1;
  flex-shrink: 0;
  background: var(--cor-visor);
  border: none;
  border-radius: 0 0 var(--raio-grande) var(--raio-grande);
  padding: var(--esp-12) var(--esp-16) var(--esp-16);
  position: relative;
  overflow: hidden;
}
#barra-frase::after {
  content: ""; position: absolute; top: 0; right: 0; bottom: 0; left: 0; inset: 0; pointer-events: none;
  background: radial-gradient(120% 90% at 12% 0%, rgba(36,191,173,.20), transparent 60%);
}
#frase-container {
  background: transparent;
  border: none;
  color: var(--cor-visor-texto);
  font-size: var(--fonte-frase);
  font-weight: 700;
  line-height: 1.2;
  letter-spacing: -.02em;
  min-height: 52px;
  display: block;
  margin-bottom: var(--esp-12);
  /* 🐛 Mesmo defeito do app adulto: a frase crescia sem limite e empurrava
     a prancha para fora da tela. Teto de 2 linhas e meia, e o resto rola
     por dentro do visor. */
  max-height: 3em;
  overflow-y: auto;
  scrollbar-width: thin;
}
#frase-container:empty::before {
  /* 🐛 faltava o content: sem ele o pseudo-elemento nem existe e o visor
     vazio ficava sem convite nenhum */
  /* ✂️ 26/08: era "Toque nos botões para montar a frase" — 36 caracteres que
     quebravam em DUAS linhas dentro do visor depois que a fonte subiu para 19px
     (subiu porque o contraste em 16px não passava). Duas linhas espremidas no
     visor é o primeiro que a mãe vê do app.
     O texto novo é mais curto E diz melhor o que o app faz: quem toca é a
     criança, o que ela toca é FIGURA, e o que acontece é o aparelho FALAR. */
  content: "Toque nas figuras para falar";
  display: block;
  color: var(--cor-visor-vazio);
  font-weight: 400;
  font-size: 20px;
  letter-spacing: 0;
}
#frase-container .palavra { display: inline-block; margin-right: 12px; position: relative; }
#frase-container .palavra::after {
  content: ""; position: absolute; left: 0; right: 0; bottom: -4px; height: 3px;
  background: var(--cor-turquesa); border-radius: 2px; opacity: .6;
}

#btn-apagar, #btn-limpar, #btn-trava {
  background: rgba(255,255,255,.10);
  color: var(--cor-visor-texto);
  border: 1px solid rgba(255,255,255,.20);
  border-radius: var(--raio);
}

/* ============================================================
   CARA DE BALBUU — 10/08/2026 noite
   Queixa dele: "não tô achando nada a ver com o Balbuu" e "que tanto de
   emoji feio". O conserto não foi inventar estilo novo: foi puxar o que o
   Balbuu já tem (personagem, logo, paleta e o gabarito de ícone de
   'docs/amostra-icones-balbuu.html').
   ============================================================ */

/* ---------- o personagem abre o app ---------- */
.consent-personagem {
  display: block;
  width: 150px; height: 150px;
  margin: 0 auto var(--esp-8);
  object-fit: contain;
}
/* ⚠️ 'balbuu-logo.png' é o MESMO passarinho do 'balbuu.webp': usar os dois
   punha o personagem duplicado na tela. Fica a imagem + o nome escrito. */
.consentimento-caixa { text-align: center; }
.consentimento-caixa p, .consentimento-caixa h2 { text-align: left; }
.consentimento-caixa::after { margin-inline: auto; }

/* ---------- fontes do Balbuu, em arquivo local ---------- */
@font-face {
  font-family: 'Baloo 2'; font-style: normal; font-weight: 800; font-display: swap;
  src: url('../fontes/baloo2-extrabold.woff2') format('woff2');
}
@font-face {
  font-family: 'Nunito'; font-style: normal; font-weight: 400; font-display: swap;
  src: url('../fontes/nunito-400.woff2') format('woff2');
}
@font-face {
  font-family: 'Nunito'; font-style: normal; font-weight: 700; font-display: swap;
  src: url('../fontes/nunito-700.woff2') format('woff2');
}
body, button, input, select { font-family: var(--fonte); }
#frase-container, .palavra, h2, h3, .cat-btn, .btn-falar, .consentimento-caixa::before {
  font-family: var(--fonte-titulo);
  font-weight: 800;
}

/* ---------- profundidade ---------- */
#prancha .botao-prancha { box-shadow: var(--sombra-marca); }
#prancha .botao-prancha:active { box-shadow: none; }
#categorias .cat-btn { box-shadow: 0 2px 8px rgba(21,39,58,.06); }
#categorias .cat-btn.ativa { box-shadow: var(--sombra-marca); }
#barra-frase { box-shadow: var(--sombra-alta); position: relative; z-index: 2; }
.consentimento-caixa { box-shadow: var(--sombra-alta); }

/* ============================================================
   DEGRADÊS — mesma dosagem do app adulto: 4–10% nas superfícies (só para
   tirar o chapado) e degradê visível SÓ no que é ação. ⛔ Se dá para "ver
   o degradê" numa superfície, está forte demais.
   ============================================================ */
body {
  background:
    radial-gradient(85% 55% at 100% 0%, #E6F7F4 0%, transparent 60%),
    radial-gradient(70% 50% at 0% 100%, #EAF2FB 0%, transparent 62%),
    var(--cor-fundo);
}
/* o visor: navy da marca com o brilho turquesa vindo do canto do Balbuu */
#barra-frase {
  background:
    radial-gradient(90% 130% at 6% 0%, rgba(36,191,173,.22) 0%, transparent 60%),
    linear-gradient(160deg, #1D3550 0%, var(--cor-visor) 55%, #0C1723 100%);
}
/* ⚠️ COMPATIBILIDADE: 'color-mix()' não existe em iPhone anterior ao iOS
   16.2, e o navegador descarta a declaração inteira. Por isso cada regra
   tem cor sólida na linha de cima — senão a aba ativa e o FALAR ficam com
   texto sobre fundo transparente. */

/* a tecla: branco em cima, um sopro da cor da categoria no pé */
#prancha .botao-prancha {
  background: var(--cor-cartao);
  background: linear-gradient(180deg,
    var(--cor-cartao) 60%,
    color-mix(in srgb, var(--cat-ativa, var(--cor-turquesa)) 9%, var(--cor-cartao)) 100%);
}
/* o disco: radial de dois tons, claro em cima — dá volume sem sombra */
#prancha .botao-prancha .simbolo {
  background: #DEF3F0;
  background:
    radial-gradient(80% 80% at 50% 22%,
      color-mix(in srgb, var(--cat-ativa, var(--cor-turquesa)) 10%, #FFFFFF) 0%,
      color-mix(in srgb, var(--cat-ativa, var(--cor-turquesa)) 26%, #FFFFFF) 100%);
}
/* categoria ativa e FALAR: aqui o degradê é para ser visto */
#categorias .cat-btn.ativa {
  background: var(--cat-cor, var(--cor-turquesa));
  background: linear-gradient(135deg,
    var(--cat-cor, var(--cor-turquesa)) 0%,
    color-mix(in srgb, var(--cat-cor, var(--cor-turquesa)) 76%, #000000) 100%);
}
/* 🩸 27/08/2026 — O ÍCONE DA ABA SUMIA QUANDO ELA ERA SELECIONADA.
   Achado olhando o print da loja: "Ações" tem desenho laranja e a aba
   selecionada fica com o FUNDO laranja ⇒ contraste **1.00**: o desenho
   desaparecia por completo, sobrava só um risco no topo.
   📐 Medido nas 12: **8 delas** sumiam ou ficavam fracas — não era só a Ações.
   É falha de sistema, não de desenho: os ícones têm cor fixa e as categorias
   rodam por 7 cores de fundo (`--cat-1..7`, o `i % 7` em `renderCategorias`),
   então a colisão era questão de tempo.
   ⛔ Consertar os 8 desenhos na mão NÃO resolve: basta mudar a ordem das
      categorias para o problema voltar em outras.
   ✅ Uma regra só, que vale para qualquer ícone e qualquer ordem: na aba
      selecionada o desenho vira escuro. Medido nos 7 fundos, o pior caso fica
      acima do **3,0** que o WCAG pede para elemento gráfico (o branco dava
      2,13 e o teal e o laranja continuavam sumindo). */
#categorias .cat-btn.ativa svg {
  filter: brightness(0) opacity(0.88);
}
/* ⛔ O alto contraste tem par de cores próprio, já calibrado: não passa aqui. */
body.alto-contraste #categorias .cat-btn.ativa svg { filter: none; }

#barra-frase #btn-falar {
  background: var(--cor-turquesa);
  background: linear-gradient(105deg,
    #1A8F82 0%,
    var(--cor-turquesa) 45%,
    var(--cor-amarelo) 100%);
  color: var(--cor-texto);
}

/* ============================================================
   ACESSIBILIDADE DE APARELHO — o app obedece o que o celular já mandou
   ============================================================ */
/* área de segurança do iPhone: sem isto os botões redondos de baixo caem
   atrás da barra de gestos e não dá para acertar */
#btn-ajustes, #btn-adulto, #btn-trava {
  bottom: max(var(--esp-16), env(safe-area-inset-bottom));
}
#prancha { padding-bottom: calc(76px + env(safe-area-inset-bottom)); }
#barra-frase { padding-top: max(var(--esp-12), env(safe-area-inset-top)); }

/* quem pediu menos movimento no sistema não vê animação nenhuma */
@media (prefers-reduced-motion: reduce) {
  *, *::before, *::after {
    animation-duration: .001ms !important;
    animation-iteration-count: 1 !important;
    transition-duration: .001ms !important;
    scroll-behavior: auto !important;
  }
}
/* quem pediu mais contraste ganha borda mais forte */
@media (prefers-contrast: more) {
  #prancha .botao-prancha, #categorias .cat-btn {
    border-width: 2px; border-color: var(--cor-texto); box-shadow: none;
  }
}
/* foco gordo: a criança navega por acionador, e o adulto por teclado */
:focus-visible { outline: 4px solid var(--cor-azul); outline-offset: 3px; }
/* 🐛 Esta regra genérica esticou os 3 botões redondos de 48×48 para 48×72
   (o '--toque-min' daqui é 72). ⚠️ Alvo mínimo em regra genérica quebra
   qualquer botão de tamanho fixo — por isso a exceção logo abaixo. */
button, select, a { min-height: var(--toque-min); }
#btn-ajustes, #btn-adulto, #btn-trava {
  width: 56px; height: 56px; min-height: 56px; min-width: 56px;
  padding: 0; flex-shrink: 0;
}

/* ---------- tela BAIXA (celular deitado, tablet pequeno) ---------- */
@media (max-height: 620px) {
  /* 🐛 No celular deitado os botões ficavam atrás dos botões fixos e o
     próprio teste automático não conseguia clicar neles. A prancha manda:
     rola por dentro e reserva o rodapé. */
  #prancha { min-height: 0; overflow-y: auto; padding-bottom: 72px; }
  #frase-container { font-size: 24px; min-height: 40px; }
  #barra-frase { padding: var(--esp-8) var(--esp-12); }
  #balbuu-visor { width: 52px; height: 52px; }
  #barra-frase::before { font-size: 16px; left: calc(52px + var(--esp-16)); }
  #prancha > * { max-height: 120px; }
  #prancha { padding-bottom: calc(64px + env(safe-area-inset-bottom)); }

  /* 🔴 ACHADO 11/08 (noite), no retrato do iPhone deitado: os 3 botões
     redondos fixos estavam EM CIMA de "acabou" e "ajuda" da barra de núcleo.
     Causa: '#prancha' é 'flex: 1' com 'min-height: 0', então quando a altura
     acaba ela encolhe até ZERO — e aí o 'padding-bottom' que reserva o
     rodapé não reserva nada, porque não há prancha. O que sobrava no rodapé
     era o núcleo, bem embaixo dos botões.
     🥇 LIÇÃO: reservar rodapé com padding só funciona enquanto o elemento
     tem altura. Se ele pode encolher a zero, precisa de piso. */
  #prancha { min-height: 132px; }
  /* ⚠️ O resto do conserto do deitado (o visor virar uma fileira) mora no
     FIM deste arquivo, não aqui: media query NÃO aumenta especificidade, e
     a definição do grid do visor vem depois deste ponto — daqui ela perde. */
}

/* ---------- cartão "Conheça o Balbuu" ---------- */
/* Era um link de texto perdido no rodapé. Como este app existe para ser
   porta de entrada do Balbuu, o convite precisa ser visto por quem entra
   nos Ajustes — sem virar propaganda na cara da criança. */
.cartao-balbuu {
  display: flex;
  align-items: center;
  gap: var(--esp-12);
  text-align: left;
  text-decoration: none;
  color: var(--cor-texto);
  padding: var(--esp-12);
  border: 1px solid var(--cor-borda);
  border-radius: var(--raio);
  background: var(--cor-cartao);
  background: linear-gradient(135deg,
    var(--cor-cartao) 55%,
    color-mix(in srgb, var(--cor-turquesa) 12%, var(--cor-cartao)) 100%);
  box-shadow: var(--sombra-marca);
  min-height: var(--toque-min);
}
.cartao-balbuu img { width: 64px; height: 64px; object-fit: contain; flex-shrink: 0; }
.cartao-balbuu span { display: block; font-size: 15px; line-height: 1.45; }
.cartao-balbuu strong {
  display: block;
  font-family: var(--fonte-titulo);
  font-size: 19px;
  color: var(--cor-turquesa);
  margin-bottom: 2px;
}
/* O que faz o cartão parecer clicável. Sem ele era um parágrafo com desenho
   ao lado, e ninguém toca em parágrafo. Fica dentro do próprio <a>: o alvo
   de toque continua sendo o cartão inteiro, não só este pedaço. */
.cartao-balbuu-cta {
  display: inline-block;
  margin-top: var(--esp-8);
  padding: 10px var(--esp-16);
  background: var(--cor-turquesa);
  color: #fff;
  font-family: var(--fonte-titulo);
  font-size: 15px;
  border-radius: var(--raio);
}
/* Cartão largo em PC vira uma faixa gigante e o convite se perde no meio. */
.cartao-balbuu { max-width: 520px; }

/* ---------- alto contraste × degradês ---------- */
/* 🐛 As regras de degradê têm ID e venciam as do alto contraste: com ele
   ligado, as variáveis viram amarelo/branco e o FALAR ficava texto BRANCO
   sobre AMARELO (contraste ~1.1:1) — ilegível no botão mais importante.
   Estas duas, declaradas por último e com o body na frente, vencem. */
body.alto-contraste #barra-frase #btn-falar {
  background: var(--cor-turquesa);
  color: var(--hc-fundo, #000);
}
body.alto-contraste #categorias .cat-btn.ativa {
  background: var(--cor-turquesa);
  color: var(--hc-fundo, #000);
}
body.alto-contraste #barra-frase,
body.alto-contraste #prancha .botao-prancha,
body.alto-contraste #prancha .botao-prancha .simbolo { background-image: none; }

/* ---------- o Balbuu mora no visor e fala junto ---------- */
#balbuu-visor {
  width: 72px; height: 72px;
  object-fit: contain;
  flex: 0 0 auto;
  align-self: flex-start;
  margin-top: var(--esp-24);
  transform-origin: 50% 90%;
}
/* Balança de leve só enquanto sai o som. ⛔ Sem pulo, sem confete, sem
   som de premiação: o app não avalia nem premia a criança. */
body.falando #balbuu-visor { animation: balbuu-fala 1.05s ease-in-out infinite; }
@keyframes balbuu-fala {
  0%, 100% { transform: rotate(-3deg) translateY(0); }
  50%      { transform: rotate(3deg)  translateY(-4px); }
}
@media (prefers-reduced-motion: reduce) {
  body.falando #balbuu-visor { animation: none; }
}

/* ---------- categoria: ícone da marca + cor própria ---------- */
/* ⚠️ prefixado com #categorias de propósito: a camada de redesign que vem
   antes já define '.cat-btn', e sem a especificidade extra a cor da
   categoria não chegava a aparecer. */
#categorias .cat-btn .cat-ico { width: 34px; height: 34px; display: block; }
#categorias .cat-btn .icone { display: grid; place-items: center; }
#categorias .cat-btn {
  border-bottom: 5px solid var(--cat-cor, var(--cor-turquesa));
  gap: var(--esp-4);
}
#categorias .cat-btn.ativa {
  background: var(--cat-cor, var(--cor-turquesa));
  border-color: var(--cat-cor, var(--cor-turquesa));
  color: var(--cor-texto);
}

/* ---------- o botão da prancha ---------- */
/* O emoji ficava minúsculo perdido no meio de um botão de 320px: parecia
   página inacabada. Agora ele mora num disco com a cor da categoria e o
   botão tem teto de altura. */
#prancha .botao-prancha .simbolo,
#prancha .botao-prancha img {
  /* 🔍 O desenho ocupava só 38% do botão (42px num botão de 109px) e a
     criança não reconhecia a figura. Não era nitidez — SVG não borra — era
     TAMANHO. O disco cresceu de 16vmin para 23vmin. */
  width: clamp(58px, 23vmin, 112px);
  height: clamp(58px, 23vmin, 112px);
  display: grid;
  place-items: center;
  border-radius: 50%;
  /* 🔬 EVIDÊNCIA (11/08/2026): cor DENTRO do símbolo ajuda a criança a achar a
     palavra; cor de FUNDO não ajuda e ainda distrai (Light et al. 2019, revisão
     de telas de CAA). O desenho do Mulberry JÁ vem colorido ⇒ o fundo do disco
     vira branco e a cor da categoria passa a ser um ANEL: continua servindo de
     pista periférica, sem tingir o desenho por cima. */
  background: #FFFFFF;
  border: 3px solid #DEF3F0;
  border: 3px solid color-mix(in srgb, var(--cat-ativa, var(--cor-turquesa)) 45%, #FFFFFF);
  font-size: clamp(26px, 9vmin, 46px);
  line-height: 1;
  object-fit: contain;
  padding: var(--esp-8);
  flex-shrink: 0;
}
/* ⚠️ O padding de baixo reserva o espaço dos três botões redondos, que são
   'position: fixed' e não ocupam lugar no fluxo. Sem ele o "centro" da
   grade cai atrás deles e a prancha fica visivelmente empurrada. */
/* 🔬 11/08 (noite): CENTRALIZAR SAIU, e o motivo é de CAA, não de gosto.
   Centralizado, uma categoria de 4 palavras põe os botões numa altura e uma
   de 6 põe em outra: os símbolos DANÇAM de lugar a cada troca de aba. A
   criança decora a posição com a mão antes de decorar o desenho — é o que
   faz ela pedir água sem procurar. Posição estável vale mais que simetria.
   (No tablet o centralizado ainda abria um buraco no meio da tela.)
   🐛 O 'safe center' tinha vindo de outro bug: 'center' puro em grade
   rolável escondia a primeira linha. 'start' não tem esse problema. */
#prancha { align-content: start; padding-bottom: 76px; }
/* 🐛 A 3ª coluna ("banheiro" e "ajuda") saía CORTADA na borda direita:
   com 'aspect-ratio: 1' + teto de altura, a largura passava a ser derivada
   da altura e estourava a coluna do grid. 'width: 100%' + 'min-width: 0'
   devolvem o comando da largura para o grid. Mesma lição do app adulto. */
#prancha > * {
  max-height: clamp(120px, 34vw, 210px);
  width: 100%;
  min-width: 0;
}

/* o desenho do Mulberry é traço fino: dentro do disco ele ganha massa */
#prancha .botao-prancha .simbolo-img,
#prancha .botao-prancha .simbolo img {
  width: 100%; height: 100%;
  object-fit: contain;
  /* ⛔ 'mix-blend-mode: multiply' SAIU em 11/08/2026: ele existia para o branco
     do SVG desaparecer sobre o disco tingido, mas multiplicava as cores próprias
     do Mulberry pela cor da categoria — ou seja, embaçava justamente a cor que a
     evidência diz ser a que ajuda. Com o disco branco ele não tem mais função. */
  /* ⚠️ O arquivo do Mulberry tem margem branca dentro do próprio desenho
     (viewBox 850×850 com folga em volta). Sem o 'scale', essa folga vira
     espaço morto e o desenho encolhe mais ainda dentro do disco. */
  transform: scale(1.18);
}
/* padding menor: cada pixel de padding é um pixel a menos de desenho */
#prancha .botao-prancha .simbolo { padding: var(--esp-4); }

/* ---------- resposta ao toque e ao mouse ---------- */
/* ⛔ Sem festa: nada de pulo, brilho ou confete. A criança precisa de
   resposta clara de que acertou o botão, e só. */
#prancha .botao-prancha, #categorias .cat-btn {
  transition: transform .09s ease-out, box-shadow .14s ease-out;
}
@media (hover: hover) {
  #prancha .botao-prancha:hover {
    transform: translateY(-3px);
    box-shadow: var(--sombra-alta);
  }
  #prancha .botao-prancha:hover .simbolo {
    background: color-mix(in srgb, var(--cat-ativa, var(--cor-turquesa)) 28%, #FFFFFF);
  }
  #categorias .cat-btn:hover { transform: translateY(-2px); }
}
#prancha .botao-prancha:active { transform: translateY(2px) scale(.99); }
@media (prefers-reduced-motion: reduce) {
  #prancha .botao-prancha, #categorias .cat-btn { transition: none; }
  #prancha .botao-prancha:hover, #categorias .cat-btn:hover { transform: none; }
}

/* ---------- layout de dentro do visor ---------- */
/* ⚠️ Com flex-wrap o visor virava 281px de altura para uma frase de 52px:
   o Balbuu ficava sozinho numa linha e sobrava um buraco no meio. Grid
   resolve: o personagem ocupa as duas linhas na esquerda, a frase vai ao
   lado dele e os botões ficam embaixo, com FALAR longe do "limpar tudo". */
#barra-frase {
  display: grid;
  grid-template-columns: auto 1fr auto auto;
  /* 🐛 A marca era 'position: absolute' e caía EM CIMA do texto da frase
     (as duas em left:96px). Agora ela tem linha própria no grid: o
     pseudo-elemento de um grid container é um item do grid, então basta
     dar a área e tirar o absolute. */
  grid-template-areas:
    "bicho marca  marca  marca"
    "bicho frase  frase  frase"
    "bicho apagar limpar falar";
  align-items: center;
  gap: var(--esp-4) var(--esp-8);
  padding: var(--esp-12) var(--esp-16) var(--esp-16);
}
#balbuu-visor  { grid-area: bicho; align-self: center; margin-top: 0; }
#frase-container { grid-area: frase; }
#btn-apagar    { grid-area: apagar; }
#btn-limpar    { grid-area: limpar; }
#barra-frase #btn-falar {
  grid-area: falar;
  justify-self: end;
  padding-inline: var(--esp-24);
}
/* (a posição da marca mora na regra única de #barra-frase::before) */

/* Os três botões redondos estavam ancorados no rodapé e ficavam boiando
   por cima do visor. Vão para o canto de baixo, em linha, fora do caminho
   da criança (quem usa é o adulto). */
#btn-ajustes, #btn-adulto, #btn-trava {
  bottom: var(--esp-16);
  background: var(--cor-fundo);
  color: var(--cor-texto);
  border: 1px solid rgba(0,0,0,.10);
}
#btn-ajustes { right: var(--esp-16); }
#btn-adulto  { right: calc(var(--esp-48) + var(--esp-24)); }
#btn-trava   { right: calc(var(--esp-48) * 2 + var(--esp-32)); }
#btn-falar {
  background: var(--cor-turquesa);
  color: var(--cor-texto);
  border: none;
  border-bottom: 5px solid rgba(0,0,0,.22);
  border-radius: var(--raio);
  font-weight: 700;
  letter-spacing: .04em;
}
#btn-falar:active { transform: translateY(2px); border-bottom-width: 3px; }

/* ---------- a marca aparece de verdade ---------- */
/* 🐛 Esta regra vinha DEPOIS da que posiciona a marca ao lado do bicho e
   devolvia o "balbuu" para o canto — em cima do personagem. Regra única
   agora: a marca fica à direita do Balbuu, fora dele. */
#barra-frase::before {
  content: "balbuu";
  grid-area: marca;              /* linha própria, não flutua mais */
  justify-self: start;
  align-self: end;
  font-size: 20px; font-weight: 700; letter-spacing: .06em;
  line-height: 1.1;
  text-transform: lowercase;
  color: var(--cor-turquesa);
  pointer-events: none;
}

/* A primeira tela que o pai vê não pode parecer aviso de site genérico:
   ganha o nome, a cor da marca e os pontinhos do Balbuu. */
.consentimento-caixa::before {
  content: "balbuu";
  display: block;
  font-size: 32px; font-weight: 700; letter-spacing: .04em;
  text-transform: lowercase;
  color: var(--cor-turquesa);
  margin-bottom: var(--esp-4);
}
.consentimento-caixa::after {
  content: "";
  display: block;
  height: 6px;
  width: 96px;
  margin-top: var(--esp-16);
  border-radius: 999px;
  background: linear-gradient(90deg,
    var(--cor-turquesa) 0 25%, var(--cor-amarelo) 25% 50%,
    var(--cor-azul) 50% 75%, var(--cor-rosa) 75% 100%);
}

/* ---------- categorias ---------- */
.cat-btn {
  border-radius: var(--raio-pilula);
  border: 2px solid var(--cor-borda);
  background: var(--cor-cartao);
  color: var(--cor-texto);
  min-height: 56px;
  padding: 0 var(--esp-16);
  font-weight: 700;
}
.cat-btn:nth-child(1) { --c: var(--cat-1); }
.cat-btn:nth-child(2) { --c: var(--cat-2); }
.cat-btn:nth-child(3) { --c: var(--cat-3); }
.cat-btn:nth-child(4) { --c: var(--cat-4); }
.cat-btn:nth-child(5) { --c: var(--cat-5); }
.cat-btn:nth-child(6) { --c: var(--cat-6); }
.cat-btn:nth-child(7) { --c: var(--cat-7); }
.cat-btn.ativa {
  background: var(--cor-visor);
  border-color: var(--cor-visor);
  color: #FFFFFF;
  box-shadow: inset 0 -5px 0 var(--c, var(--cat-1));
}

/* ---------- as teclas ---------- */
.botao-prancha {
  background: var(--cor-cartao);
  border: 1px solid var(--cor-borda);
  border-bottom: var(--tecla-base) solid var(--cat-ativa);
  border-radius: var(--raio);
  min-height: 124px;
  padding: var(--esp-12) var(--esp-8);
}
.botao-prancha:active { transform: translateY(2px); border-bottom-width: 4px; }
.botao-prancha .simbolo { font-size: 38px; }
/* 🐛 Era 18px FIXO: o ajuste "Tamanho da fonte" não fazia nada na palavra
   do botão. Com 'em' ela acompanha a fonte que o adulto escolheu. */
.botao-prancha .palavra { font-size: clamp(11px, 0.72em, 26px); font-weight: 700; }

/* foco sempre visível */
.botao-prancha:focus-visible, .cat-btn:focus-visible, #btn-falar:focus-visible {
  outline: 3px solid var(--cor-turquesa);
  outline-offset: 3px;
}

/* ============================================================
   BARRA DE NÚCLEO — as palavras que servem para tudo
   Mora entre as abas e a prancha, e é a única fileira que NÃO muda quando a
   criança troca de categoria. Visual de propósito diferente da tecla comum
   (mais baixa, fundo navy claro): tem que ler como "prateleira fixa", não
   como mais uma linha da prancha.
   ============================================================ */
/* ⚠️ NÃO é 'flex' com rolagem lateral, e a conta explica por quê: 6 botões de
   64px + os espaços dão 448px, e o celular em pé tem 375. A barra rolaria de
   lado e a criança NUNCA acharia o último botão — rolagem horizontal é coisa
   que criança pequena não descobre. Em grade, tudo aparece: 3 por linha no
   celular em pé, 6 numa linha quando há largura. */
#nucleo {
  display: grid;
  grid-template-columns: repeat(3, minmax(0, 1fr));
  gap: var(--esp-8);
  flex: 0 0 auto;
  padding: var(--esp-8) var(--esp-12);
  background: linear-gradient(180deg, rgba(21,39,58,.06) 0%, transparent 100%);
  border-bottom: 1px solid var(--cor-borda);
}
@media (min-width: 600px) {
  #nucleo { grid-template-columns: repeat(6, minmax(0, 1fr)); }
}
/* deitado sobra largura e falta altura: tudo numa fileira só */
@media (max-height: 620px) {
  #nucleo { grid-template-columns: repeat(6, minmax(0, 1fr)); }
}
#nucleo.escondido { display: none; }

.botao-nucleo {
  min-width: 0;
  min-height: 76px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  gap: 2px;
  padding: var(--esp-4);
  cursor: pointer;
  background: var(--cor-cartao);
  border: 1px solid var(--cor-borda);
  /* borda de baixo navy: marca que esta fileira é de outra natureza */
  border-bottom: 4px solid #8FA3B5;
  border-radius: var(--raio);
  box-shadow: 0 2px 8px rgba(21,39,58,.06);
  transition: transform .09s ease-out;
}
.botao-nucleo:active { transform: translateY(2px); border-bottom-width: 2px; }
.botao-nucleo .simbolo {
  width: clamp(30px, 8vmin, 46px);
  height: clamp(30px, 8vmin, 46px);
  display: grid;
  place-items: center;
  font-size: clamp(20px, 6vmin, 30px);
  line-height: 1;
}
.botao-nucleo .simbolo img {
  width: 100%; height: 100%; object-fit: contain;
}
.botao-nucleo .palavra {
  font-family: var(--fonte-titulo);
  font-weight: 800;
  font-size: clamp(11px, 3.2vmin, 15px);
  line-height: 1.1;
}
.botao-nucleo:focus-visible { outline: 3px solid var(--cor-turquesa); outline-offset: 3px; }
@media (prefers-reduced-motion: reduce) {
  .botao-nucleo { transition: none; }
}
/* no celular deitado a altura é o recurso escasso: a barra encolhe em vez
   de roubar a prancha */
@media (max-height: 620px) {
  #nucleo { padding: var(--esp-4) var(--esp-8); gap: var(--esp-4); }
  .botao-nucleo { min-height: 56px; }
  .botao-nucleo .simbolo { width: 26px; height: 26px; font-size: 18px; }
  .botao-nucleo .palavra { font-size: 11px; }
}

/* ============================================================
   A PRANCHA EM PAPEL
   Na tela esta folha não existe; ela só nasce quando o adulto manda
   imprimir. Papel não é o plano B do app: bateria acaba, escola não deixa
   levar celular e o fono precisa entregar algo na primeira sessão.
   ============================================================ */
#folha-impressao { display: none; }

@media print {
  /* ⛔ Nada da interface vai para o papel: nem botão, nem painel, nem o
     visor da frase. Só a folha. */
  body > *:not(#folha-impressao) { display: none !important; }
  body { background: #FFFFFF; }

  #folha-impressao {
    display: block;
    color: #000000;
    font-family: var(--fonte);
  }
  .folha-cabecalho {
    font-size: 15pt;
    margin-bottom: 6mm;
    border-bottom: 1px solid #000000;
    padding-bottom: 2mm;
  }
  .folha-cabecalho span { display: block; font-size: 10pt; margin-top: 1mm; }
  .folha-secao { break-inside: auto; margin-bottom: 6mm; }
  .folha-secao h3 {
    font-family: var(--fonte-titulo);
    font-size: 12pt;
    margin: 0 0 2mm;
    break-after: avoid;
  }
  .folha-grade {
    display: grid;
    grid-template-columns: repeat(4, minmax(0, 1fr));
    gap: 3mm;
  }
  /* o cartão é recortável: quem quiser monta cartão solto com tesoura */
  .folha-cartao {
    break-inside: avoid;
    border: 1px solid #000000;
    border-radius: 2mm;
    padding: 2mm;
    text-align: center;
    min-height: 30mm;
    display: flex;
    flex-direction: column;
    align-items: center;
    justify-content: center;
    gap: 1mm;
  }
  .folha-cartao .simbolo { display: block; font-size: 20pt; line-height: 1; }
  .folha-cartao .simbolo img { width: 22mm; height: 22mm; object-fit: contain; }
  .folha-cartao .palavra { font-family: var(--fonte-titulo); font-size: 11pt; }
  .folha-rodape { margin-top: 6mm; font-size: 8pt; }

  /* sem isto o navegador imprime os desenhos desbotados */
  #folha-impressao, #folha-impressao * {
    -webkit-print-color-adjust: exact;
    print-color-adjust: exact;
  }
  @page { margin: 10mm; }
}

/* aviso que o adulto precisa ler antes de sair da tela */
.aviso-forte {
  opacity: 1;
  font-weight: 700;
  border-left: 4px solid var(--cor-laranja);
  padding: var(--esp-8) var(--esp-12);
  background: rgba(254,154,32,.10);
  border-radius: var(--raio);
}
.aviso-forte.escondido { display: none; }

/* o bloco do núcleo dentro do editor: primeiro da lista e marcado, porque
   mexer nele muda a tela inteira da criança, não só uma categoria */
.editor-nucleo {
  border: 2px solid #8FA3B5;
  border-radius: var(--raio);
  padding: var(--esp-12);
  margin-bottom: var(--esp-16);
  background: rgba(143,163,181,.08);
}
.editor-nucleo h3 { margin-top: 0; }

/* ---------- cópia de segurança ---------- */
.backup-botoes {
  display: flex;
  gap: var(--esp-8);
  flex-wrap: wrap;
  margin-top: var(--esp-12);
}
.backup-botoes button { flex: 1 1 140px; }
.backup-aviso {
  min-height: 1.4em;
  margin-top: var(--esp-8);
  font-weight: 700;
}
/* explicação curta embaixo de um ajuste — o adulto precisa saber PARA QUE
   serve antes de desligar alguma coisa que a criança usa */
.ajustes-dica {
  margin: var(--esp-4) 0 0;
  font-size: 14px;
  line-height: 1.4;
  opacity: .85;
}

/* ============================================================
   ALTO CONTRASTE — o conserto de 11/08/2026
   O modo existe para quem enxerga pouco, e estava ATRAPALHANDO justamente
   quem liga. Dois sumiços:
   1) o visor da frase (que é o cabeçalho, sobe com 'order: -1') ficava PRETO
      sobre o fundo PRETO do corpo, sem contorno nenhum — não dava para ver
      onde ele começa e acaba;
   2) as abas inativas ficavam pretas com contorno navy: casco invisível.
   ============================================================ */
body.alto-contraste #barra-frase {
  border-bottom: 3px solid var(--hc-borda);
}
body.alto-contraste #categorias .cat-btn {
  background: var(--hc-fundo);
  color: var(--hc-texto);
  border: 2px solid var(--hc-borda);
  border-bottom: 5px solid var(--hc-primaria);
  box-shadow: none;
}
/* Na aba ativa o fundo é amarelo, então aqui o traço do ícone volta a ser
   escuro — senão fica ícone branco sobre amarelo, que é ilegível. */
body.alto-contraste #categorias .cat-btn.ativa {
  --icotraco: var(--hc-fundo);
  background: var(--hc-primaria);
  border-color: var(--hc-primaria);
  color: var(--hc-fundo);
}
/* a tecla também precisa de contorno próprio no preto */
body.alto-contraste #prancha .botao-prancha {
  border: 2px solid var(--hc-borda);
  border-bottom: var(--tecla-base) solid var(--hc-primaria);
  box-shadow: none;
}
body.alto-contraste #nucleo {
  background: var(--hc-fundo);
  background-image: none;
  border-bottom: 3px solid var(--hc-borda);
}
body.alto-contraste .botao-nucleo {
  background: var(--hc-fundo);
  color: var(--hc-texto);
  border: 2px solid var(--hc-borda);
  border-bottom: 4px solid var(--hc-destaque);
  box-shadow: none;
}

/* ============================================================
   CELULAR DEITADO — a última palavra sobre o visor
   🥇 Está no FIM do arquivo de propósito: '@media' não aumenta
   especificidade, então a regra do deitado tem que vir DEPOIS da regra
   normal do visor para vencer. A primeira tentativa ficou lá em cima e
   simplesmente não fez efeito — o visor continuou com 152px.

   Em pé o visor tem três linhas (marca / frase / botões) porque falta
   largura. Deitado é o contrário: sobra largura e falta altura, então tudo
   cabe numa fileira só. Sem isso as quatro faixas somam mais que a tela e a
   prancha da criança é a que fica de fora.
   ============================================================ */
@media (max-height: 620px) {
  #barra-frase {
    grid-template-columns: auto 1fr auto auto auto;
    grid-template-areas: "bicho frase apagar limpar falar";
    padding: var(--esp-4) var(--esp-12);
    padding-top: max(var(--esp-4), env(safe-area-inset-top));
    gap: var(--esp-8);
  }
  /* ⛔ a marca sai: com 375px de altura, quem precisa caber é a prancha */
  #barra-frase::before { display: none; }
  #frase-container:empty::before { display: none; }
  #balbuu-visor { width: 44px; height: 44px; margin-top: 0; }
  #frase-container { min-height: 32px; font-size: 22px; }
  #barra-frase #btn-falar { min-height: 56px; }
  #btn-apagar, #btn-limpar { min-height: 48px; }

  /* 🔴 Os 3 botões redondos ficavam no rodapé e obrigavam a prancha a
     reservar 64px de altura embaixo — num espaço de 140px, quase metade.
     Resultado: nenhum botão da prancha aparecia inteiro no deitado.
     🥇 Deitado sobra LARGURA e falta ALTURA ⇒ cobra-se o espaço na largura:
     os três viram uma coluna colada na direita e a prancha reserva a
     margem lateral, não o rodapé. */
  #btn-trava, #btn-adulto, #btn-ajustes {
    width: 44px; height: 44px; min-width: 44px; min-height: 44px;
    right: var(--esp-8);
  }
  #btn-ajustes { bottom: max(var(--esp-8), env(safe-area-inset-bottom)); }
  #btn-adulto  { bottom: calc(52px + max(var(--esp-8), env(safe-area-inset-bottom))); }
  #btn-trava   { bottom: calc(104px + max(var(--esp-8), env(safe-area-inset-bottom))); }
  #prancha {
    padding-bottom: var(--esp-8);
    padding-right: 60px;
  }
}

/* ============================================================
   DEITADO E LARGO — a prancha ganha colunas
   🔍 A medida que explicou tudo: no deitado a prancha tem 812px de largura
   e 3 colunas, então cada tecla vira um quadrado de 234px de lado
   ('aspect-ratio: 1') e não cabe nos 140px de altura que sobram. Nenhuma
   palavra aparecia inteira — a criança via meia figura.
   ⇒ Dobrar as colunas usa a largura que está sobrando e devolve a tecla a
   um tamanho que cabe. O adulto continua mandando: 2, 3 ou 4 em pé viram
   4, 6 ou 8 deitado, na mesma proporção.
   ============================================================ */
@media (max-height: 620px) and (min-width: 700px) {
  #prancha.grid-2 { grid-template-columns: repeat(4, minmax(0, 1fr)); }
  #prancha.grid-3 { grid-template-columns: repeat(6, minmax(0, 1fr)); }
  #prancha.grid-4 { grid-template-columns: repeat(8, minmax(0, 1fr)); }
  /* o último botão do núcleo ficava embaixo da coluna dos 3 botões
     redondos; a barra reserva a mesma margem que a prancha */
  #nucleo { padding-right: 60px; }
}

/* ============================================================
   DEITADO: quem cede altura é o secundário, nunca a prancha
   No iPhone deitado a altura útil é ~340px, menos que os 375 do teste — e a
   última fileira da prancha saía cortada pela metade. A prancha rola, mas
   ⛔ criança pequena não descobre rolagem: o que está cortado, para ela,
   não existe.
   ⇒ Abas e barra de núcleo encolhem (continuam com alvo de toque bem acima
   do mínimo) e a tecla da prancha aceita ficar mais baixa. A ordem de quem
   cede é: nome do app → abas → núcleo → prancha, por último.
   ============================================================ */
@media (max-height: 620px) {
  #categorias { min-height: 0; padding: var(--esp-4) var(--esp-8); }
  #categorias .cat-btn { min-height: 54px; font-size: 13px; }
  #categorias .cat-btn .cat-ico { width: 24px; height: 24px; }
  /* ⚠️ 'padding' inteiro aqui APAGARIA o 'padding-right: 60px' que reserva a
     coluna dos 3 botões redondos — foi assim que "ajuda" voltou a ficar
     tapado depois de já ter sido consertado. Reserva declarada junto. */
  #nucleo { padding: var(--esp-4) 60px var(--esp-4) var(--esp-8); }
  .botao-nucleo { min-height: 52px; }
  .botao-nucleo .simbolo { width: 24px; height: 24px; font-size: 18px; }
  #prancha .botao-prancha { min-height: 92px; }
}

/* ============================================================
   🔴 CONSERTO DE 12/08/2026 — A PALAVRA SAÍA CORTADA NO CELULAR
   Achado nos prints do Filipe e reproduzido em 412x600: as 9 palavras da
   tela vazavam exatamente na borda do botao e sumiam no 'overflow: hidden'.

   A CAUSA, que vale como regra: o simbolo era medido em 'vmin' (que segue a
   LARGURA da tela) e estava proibido de encolher ('flex-shrink: 0'). Quando
   falta ALTURA - celular com a barra do navegador aberta, tela baixa,
   teclado - o simbolo nao cede um pixel e quem paga a conta e' o texto.
   ⇒ Em botao de altura variavel, a FIGURA cede e a PALAVRA nunca cede:
   figura cortada ainda se reconhece, palavra cortada nao se le.

   🥇 Esta camada mora no FIM do arquivo de proposito: '@media' nao aumenta
   especificidade, entao regra escrita antes nao vence a de cima.
   ============================================================ */
#prancha .botao-prancha {
  /* justify-content: center empurrava o conteudo para fora nos dois lados
     quando nao cabia. Ancorado no topo, o que falta sobra embaixo. */
  justify-content: flex-start;
}
/* 🪤🔴 A 1ª TENTATIVA DESTE CONSERTO QUEBROU O APP (13h24, print dele): pôr
   'flex: 0 1 auto' + 'max-height' no símbolo E na img fez o disco achatar em
   ELIPSE e o desenho encolher até virar um pontinho. Os botões viraram anéis
   vazios.
   🥇 LIÇÃO: o disco é um CÍRCULO — deixar um flex encolher só a altura dele
   destrói a proporção e leva a imagem junto. Quem dá espaço à palavra é o
   TAMANHO do disco por media query de altura (abaixo), não o flex.
   ⛔ Não repor 'flex: 0 1 auto' aqui. */
#prancha .botao-prancha .simbolo {
  flex: 0 0 auto;
}
#prancha .botao-prancha .palavra {
  /* ⛔ NUNCA encolher e ⛔ nunca abaixo de 16px: e' o elemento mais lido do
     app e o DESIGN.md proibe. O piso era 11px - o mesmo defeito que ja tinha
     sido corrigido no app adulto e nunca chegou aqui. */
  flex: 0 0 auto;
  font-size: clamp(16px, 0.8em, 26px);
  line-height: 1.1;
  width: 100%;
  margin-top: auto;   /* cola a palavra na base: o respiro sobra em cima */
}

/* Tela baixa (navegador com barra, celular deitado): a figura encolhe mais
   ainda, mas a palavra continua com os mesmos 16px. */
@media (max-height: 700px) {
  #prancha .botao-prancha .simbolo,
  #prancha .botao-prancha img {
    width: clamp(40px, 16vmin, 96px);
    height: clamp(40px, 16vmin, 96px);
  }
}

/* Os três botões redondos passaram de emoji para SVG (12/08/2026): o desenho
   precisa de tamanho declarado, senão nasce 0x0 e o botão fica vazio. */
#btn-trava .ui-ico, #btn-adulto .ui-ico, #btn-ajustes .ui-ico {
  width: 60%;
  height: 60%;
  display: block;
  margin: auto;
}

/* o cadeado da tela de bloqueio virou SVG junto com os botões redondos */
.icone-trava .ui-ico { width: 72px; height: 72px; display: block; margin: 0 auto; }

/* ============================================================
   🔴 12/08/2026 — "PARECE QUE NÃO TEM ESPAÇO PARA NADA" (palavra dele)
   Medido em 412x720 antes de mexer:
     visor da frase 211px (29%) · categorias 86px (12%) · núcleo 177px (25%)
     ⇒ 66% da tela ia embora ANTES da prancha, e só 3 das 9 palavras
       apareciam sem rolar.
   🥇 A prancha é o app. Toda faixa fixa que cresce come palavra da criança —
   e criança pequena NÃO descobre rolagem: o que precisa rolar, para ela,
   não existe. Por isso o ajuste é de espaço, não de estética.
   ============================================================ */

/* 1. O NÚCLEO CABE EM UMA LINHA SÓ. Eram 3 colunas × 2 linhas = 177px.
   ⚠️ A regra antiga (6 botões de 64px = 448px) valia para tela de 375; com
   '1fr' os botões se dividem pela largura real e cabem seis de 60px numa tela
   de 380. ⛔ Abaixo de 380 continua em 3 colunas: melhor duas linhas do que
   alvo de toque miúdo demais para a mão da criança. */
@media (min-width: 360px) {
  /* 375px (iPhone SE/8) tambem cabe: 375 - 16 de padding - 5 gaps = 339 / 6 =
     56px por botao, acima do minimo de toque de 48px. Abaixo de 360 volta a
     3 colunas, porque ai o alvo ficaria miudo para a mao da crianca. */
  #nucleo { grid-template-columns: repeat(6, minmax(0, 1fr)); }
}

/* 2. O VISOR ENCOLHE ENQUANTO A FRASE ESTÁ VAZIA.
   Ele nasce grande porque a frase é o que o cuidador lê do outro lado do
   quarto — mas ANTES de existir frase, esse tamanho todo é espaço morto.
   Cresce sozinho quando a criança toca a primeira palavra. */
@media (max-width: 560px) {
  #barra-frase { padding: var(--esp-8); }
  #frase-container { min-height: 56px; }
  /* o convite ("Toque nos botões...") não precisa de letra de manchete */
  #frase-container:empty::before { font-size: 16px; line-height: 1.25; }
  /* os três botões da barra (apagar, limpar, FALAR) mais baixos */
  #btn-apagar, #btn-limpar, #btn-falar { min-height: 52px; }
}

/* 🔢 A CONTA QUE RESOLVE O CORTE (12/08, 2ª tentativa — a 1ª achatou o disco).
   Botão de 124px de altura: 24 de padding + 19 da palavra + 4 do respiro
   ⇒ sobram 77px para o disco. Ele estava com 95px (23vmin numa tela de 412),
   e os 18 que faltavam eram exatamente o que empurrava a palavra para fora.
   ⇒ No celular o disco vai a 18vmin (74px numa tela de 412) e cabe com folga.
   ⛔ Mexer no TAMANHO, nunca no 'flex' do disco: encolher só a altura de um
   círculo o transforma em elipse e leva o desenho junto. */
@media (max-width: 560px) {
  /* ⛔ Nao repor aqui width/height do simbolo: a media de 'max-width: 900px'
     (mais abaixo) vem depois e ANULA — ja custou uma tentativa perdida. */
  /* palavra longa ("descansar") quebrava em "descansa/r". Com hífen automático
     ela parte onde a sílaba deixa, e cabe em duas linhas sem virar sopa. */
  #prancha .botao-prancha .palavra {
    -webkit-hyphens: auto; hyphens: auto;   /* -webkit- é obrigatório no Safari < 17 */
    word-break: normal;
  }
}

/* ============================================================
   🖼️ 12/08/2026 — A FIGURA PASSA A MANDAR NO CARTÃO
   Ele mandou dois prints do EXPRESSIA lado a lado com o nosso e a diferença
   é estrutural, não de gosto: lá a figura ocupa ~75% do cartão e a palavra
   mora numa faixa própria embaixo. Aqui o desenho era pequeno dentro de um
   disco branco, cercado de vazio — o cartão parecia pobre E apertado.
   🥇 Em prancha de CAA quem carrega o significado é a FIGURA: ela merece o
   espaço, e a palavra merece uma faixa que não disputa com ela.
   ⚠️ A cor continua sendo ANEL/base, não fundo atrás do desenho: a evidência
   de 11/08 (Light et al. 2019) é que cor DENTRO do símbolo ajuda a achar e
   cor de FUNDO distrai. O Expressia usa fundo colorido — é escolha deles.
   ============================================================ */
/* 🔴 12/08 (noite): ESTE LAYOUT VALE EM TODA LARGURA, não só no celular.
   Ele abriu no PC e as palavras tinham sumido, com os cartões se sobrepondo:
   lá valia o layout ANTIGO, onde 'aspect-ratio: 1' pedia 251px de altura e um
   'max-height: 210px' cortava — o grid montava a linha por um valor e o cartão
   ficava com outro. ⇒ 6 pares sobrepostos, medidos em 1450x815.
   🥇 Um layout só, testado nos dois. ⛔ Não voltar a fechar isto numa media
   query de largura: o PC fica órfão e ninguém percebe até alguém abrir lá. */
#prancha .botao-prancha {
    padding: var(--esp-4) var(--esp-4) 0;
    gap: 0;
    justify-content: space-between;
  }
  /* o disco vira uma ÁREA: ocupa o que sobra, com o desenho preenchendo */
  #prancha .botao-prancha .simbolo {
    width: 100%;
    height: auto;
    flex: 1 1 auto;
    min-height: 0;
    border-radius: var(--esp-8);
    border: none;
    background: #FFFFFF;
    padding: 0;
    overflow: hidden;
  }
  #prancha .botao-prancha .simbolo img,
  #prancha .botao-prancha .simbolo-img {
    width: 100%;
    height: 100%;
    max-width: 100%;
    max-height: 100%;
    object-fit: contain;
    border-radius: 0;
  }
  /* a palavra ganha faixa própria, colada na base, sem disputar com o desenho */
  #prancha .botao-prancha .palavra {
    width: calc(100% + var(--esp-8));
    margin: var(--esp-4) calc(var(--esp-4) * -1) 0;
    padding: var(--esp-4) 2px;
    border-top: 1px solid var(--cor-borda);
    background: #FFFFFF;
    flex: 0 0 auto;
  }
}

/* 🪤 O 'scale(1.18)' da linha ~746 existia para o desenho não nadar dentro do
   disco pequeno (o SVG do Mulberry tem folga branca no próprio arquivo). Com o
   desenho ocupando o cartão inteiro ele passou a TRANSBORDAR — medido: 138px
   num cartão de 127, cortado pelo 'overflow: hidden'. Aqui ele sai, e a folga
   do arquivo é absorvida por um padding pequeno. */
@media (max-width: 1600px) {
  #prancha .botao-prancha .simbolo img,
  #prancha .botao-prancha .simbolo-img {
    transform: none;
    padding: 2px;
  }
}

/* 📏 O VISOR DE FRASE VAZIA COMIA 191px (26% da tela de 720).
   Composição medida: personagem 72 + frase 56 + botões 52/77 + respiros.
   Enquanto NÃO existe frase, esse tamanho todo é espaço morto — e cada 80px
   devolvidos são UMA LINHA INTEIRA de palavras a mais para a criança.
   ⛔ O botão FALAR não encolhe: é o que a criança mais procura.
   ⚠️ O personagem não some — ele é a marca e "fala junto" quando o app fala.
   Só fica menor enquanto não há o que falar. */
@media (max-width: 1600px) {
  #barra-frase { padding: var(--esp-4) var(--esp-8); gap: var(--esp-4); }
  .balbuu-visor { width: 46px; height: 46px; }
  #frase-container { min-height: 44px; }
  #btn-apagar, #btn-limpar { min-height: 46px; }
}

/* As abas de categoria gastavam 86px (12% da tela) com ícone grande + rótulo.
   Compactadas para ~66px no celular: continuam com alvo de toque acima do
   mínimo de 48px e devolvem espaço para a prancha. */
@media (max-width: 1600px) {
  #categorias { padding: var(--esp-4) var(--esp-8); gap: var(--esp-4); }
  #categorias .cat-btn { padding: var(--esp-4) var(--esp-8); min-height: 58px; }
  #categorias .cat-ico { width: 24px; height: 24px; }
  #categorias .cat-btn span:not(.cat-ico) { font-size: 14px; }
}

/* 🔴 OS TRÊS BOTÕES REDONDOS TAPAVAM A ÚLTIMA LINHA DA PRANCHA (visto no
   screenshot de 12/08): empilhados na vertical, ocupavam ~200px da lateral
   direita e ficavam por cima de três palavras.
   ⇒ Viram uma FILEIRA no rodapé, e a prancha reserva a altura deles.
   ⚠️ Reserva por 'padding-bottom' só funciona enquanto o elemento TEM altura;
   '#prancha' é 'flex:1' + 'min-height:0' e pode ir a zero — por isso a reserva
   vem junto de um piso. (Mesma armadilha registrada em 11/08.) */
@media (max-width: 1600px) {
  #btn-trava, #btn-adulto, #btn-ajustes {
    bottom: var(--esp-8);
    width: 46px;
    height: 46px;
  }
  #btn-ajustes { right: var(--esp-8); }
  #btn-adulto  { right: calc(var(--esp-8) + 54px); }
  #btn-trava   { right: calc(var(--esp-8) + 108px); }
  /* 🪤 'padding-bottom' NÃO resolve: ele faz parte da área ROLÁVEL, então
     protege só o fim da lista — no meio da rolagem os botões continuam
     passando por baixo dos três redondos. Com 'margin-bottom' a prancha
     TERMINA acima deles e nada nunca rola por trás.
     56px do botão + 8 de folga = 64. */
  #prancha { margin-bottom: 64px; padding-bottom: var(--esp-8); min-height: 120px; }

  /* 🐛 23/08: essa faixa de 64px era cobrada DUAS VEZES. Quando o "mais palavras"
     está visível ele já vive no fluxo e ocupa 72px justamente onde moram os três
     botões redondos (medido: eles ficam em 576–632, o botão em 560–632).
     Resultado: numa tela de 360x640 a prancha ficava com 174px — uma fileira e meia
     de símbolo, com a de baixo cortada no meio, e 64px de azul morto embaixo.
     ⇒ Com o botão visível, a margem sai e a prancha cresce ~37%.
     ⛔ Sem o botão a margem VOLTA: aí nada mais reserva a faixa dos três redondos.
     🪤 Em navegador sem ':has()' a regra é ignorada e fica como estava — degrada seguro. */
  #app:has(#btn-mais-palavras:not([hidden])) #prancha { margin-bottom: 0; }
}

/* 🪤 DEITADO: o 'min-height: 120px' que garante a prancha em pé faz ela
   TRANSBORDAR quando a tela tem 360px de altura — as faixas de cima já comem
   220px, e a prancha empurrada por baixo passava por trás dos três redondos
   ("brincar" tapado, medido em 740x360).
   ⇒ Em tela baixa a prancha cede o piso e os botões encolhem junto.
   Esta media vem DEPOIS da de largura de propósito: altura manda mais que
   largura quando as duas apertam. */
@media (max-height: 620px) {
  #prancha { min-height: 0; margin-bottom: 52px; }
  #btn-trava, #btn-adulto, #btn-ajustes { width: 42px; height: 42px; bottom: var(--esp-4); }
  #btn-ajustes { right: var(--esp-4); }
  #btn-adulto  { right: calc(var(--esp-4) + 48px); }
  #btn-trava   { right: calc(var(--esp-4) + 96px); }
}

/* ============================================================
   🎨 12/08 (noite) — O TOPO VIRA UMA PEÇA SÓ
   Palavra dele: *"está meio desproporcional… podia virar uma coisa só, um
   degradê"* e *"as pranchas estão espremidas"*.
   O topo eram TRÊS caixas empilhadas com fundo e borda cada uma (visor navy,
   abas branca, núcleo cinza) — três costuras horizontais em 200px de tela.
   ⇒ Um degradê contínuo do navy até o fundo claro, sem costura, e o que
   sobrava de enfeite sai para a prancha respirar.
   ⛔ É a ÚLTIMA camada do arquivo: escrever antes não vence.
   ============================================================ */
#app {
  background:
    linear-gradient(180deg,
      var(--cor-visor, #0C1A23) 0px,
      var(--cor-visor, #0C1A23) 34%,
      color-mix(in srgb, var(--cor-visor, #0C1A23) 22%, #FFFFFF) 62%,
      var(--cor-fundo-app, #F2F7F9) 100%)
    no-repeat top / 100% 260px;
}
/* as três faixas param de ter fundo e borda próprios: quem pinta é o #app */
#barra-frase, #categorias, #nucleo {
  background: transparent;
  border: none;
  box-shadow: none;
}
#nucleo { border-bottom: none; }

/* ⛔ Enfeite que custava altura e não ajuda ninguém a se comunicar: */
#barra-frase::before { display: none; }        /* a marca "balbuu" escrita — o personagem já é a marca */
#balbuu-visor { width: 40px; height: 40px; }   /* o personagem encolhe, não some: ele "fala junto" */

/* 🔴 O VISOR NÃO PODE CRESCER SEM FIM. Ele montou uma frase longa no PC e a
   caixa virou uma lista rolável ocupando o terço superior inteiro. Agora tem
   teto e rola por dentro. */
#frase-container {
  max-height: 84px;
  overflow-y: auto;
}

/* a prancha fica com o espaço que sobrou */
#prancha { padding-top: var(--esp-8); }

/* 🔴 CARTÕES SOBREPOSTOS NO PC (6 pares, medidos em 1450x815).
   O cartão é quadrado por 'aspect-ratio: 1', mas '#prancha > *' tem
   'max-height: clamp(120px, 34vw, 210px)'. Numa coluna de 251px o quadrado
   pede 251 de altura e o teto corta em 210 — o grid monta a linha por um
   número e o elemento desenha com outro, e eles se montam por cima.
   🥇 O conserto é fazer os dois CONCORDAREM: limitar a largura no mesmo valor
   do teto de altura. O cartão continua quadrado e centraliza na coluna. */
#prancha .botao-prancha {
  max-width: clamp(120px, 34vw, 210px);
  margin-inline: auto;
}

/* 🔴🪤 A CAUSA REAL DA SOBREPOSIÇÃO (medida em 1450x815):
   o GRID dimensionava a linha pelo CONTEÚDO — 112px do desenho + 19 da palavra
   = 131px — enquanto o CARTÃO, por ser quadrado ('aspect-ratio: 1') numa coluna
   de 251px, esticava para 210 e vazava 79px sobre a linha de baixo.
   ⇒ Os dois têm que usar a MESMA medida: a linha passa a ser declarada, e o
   cartão preenche a linha em vez de inventar a própria altura.
   🥇 Regra: 'aspect-ratio' + teto de altura dentro de um grid = o grid mede uma
   coisa e o elemento desenha outra. Um dos dois tem que ceder — aqui, o aspect. */
#prancha {
  /* 31vw ≈ a largura de uma coluna em grade de 3 ⇒ o cartão fica QUADRADO no
     celular (412px → 128) e para de crescer no PC (teto de 210).
     ⛔ Não usar h aqui: no celular a linha virava 187px e o cartão ficava
     alto e estranho, com 3 palavras visíveis em vez de 6. */
  grid-auto-rows: clamp(120px, 31vw, 210px);
}
#prancha .botao-prancha {
  aspect-ratio: auto;
  height: 100%;
  max-height: none;
}

/* o desenho volta a caber: com a linha do grid mandando, o quadro do símbolo
   pode ter altura própria e a imagem preenche ELE, não o cartão inteiro. */
#prancha .botao-prancha .simbolo {
  max-height: 100%;
  overflow: hidden;
}
#prancha .botao-prancha .simbolo img,
#prancha .botao-prancha .simbolo-img {
  width: 100%;
  height: 100%;
  max-width: 100%;
  max-height: 100%;
  object-fit: contain;
  /* 🪤 O 'scale(1.18)' da camada antiga voltou a valer porque a minha
     neutralização estava DENTRO de uma media query e a regra original, solta,
     ganhou. Medido: desenho de 236px num cartão de 210 (127%).
     ⛔ Aqui é a última linha do arquivo — é o único lugar que vence sempre. */
  transform: none;
}

/* ============================================================
   🎨 12/08 — A TELA DE CONSENTIMENTO NO PADRÃO DO BALBUU
   Palavra dele: *"essa página bem feinha e apertadaaa. temos uns termos
   lindos no balbuu não sei pq não usou"*. Estava certo — e é a regra dele
   de roubar do acervo antes de desenhar do zero.
   Formato copiado do modal "TERMOS BETA" do Balbuu de produção
   ('fonemas-app/index.html'): caixa branca bem arredondada, sombra alta,
   personagem no topo, bullets curtos com negrito no que importa, e um botão
   de largura inteira com degradê azul→turquesa.
   ⛔ Só o VISUAL veio de lá. O texto continua sendo o daqui.
   ============================================================ */
#overlay-consentimento {
  background: rgba(6, 40, 64, .55);
  padding: 16px;
}
.consentimento-caixa {
  background: #FFFFFF;
  border: none;
  border-radius: 28px;
  box-shadow: 0 24px 60px rgba(0, 40, 70, .35);
  padding: 20px 20px 18px;
  max-width: 420px;
  text-align: center;
}
/* ⚠️ 84px, não 108: a caixa inteira tem que caber numa tela de 840 sem rolar.
   Medido: com 108 ela dava 867px e o pai precisava rolar para achar o botão
   de autorizar — que é a única coisa que ele precisa fazer ali. */
.consent-personagem {
  width: 84px;
  height: 84px;
  margin: 0 auto var(--esp-4);
  display: block;
}
.consentimento-caixa h2 {
  font-family: var(--fonte-titulo);
  font-size: 21px;
  line-height: 1.2;
  margin: 0 0 var(--esp-8);
  text-align: center;
}
.consent-abre {
  font-weight: 700;
  font-size: 15px;
  margin: 0 0 var(--esp-8);
  text-align: left;
}
/* a lista é o que tira a cara de "parede de texto" da versão anterior */
.consent-lista {
  list-style: none;
  margin: 0 0 var(--esp-16);
  padding: 0;
  text-align: left;
}
.consent-lista li {
  position: relative;
  padding-left: 16px;
  margin-bottom: var(--esp-8);
  font-size: 14.5px;
  line-height: 1.45;
}
.consent-lista li::before {
  content: "•";
  position: absolute;
  left: 2px;
  color: var(--cor-turquesa, #24BFAD);
  font-weight: 800;
}
.consent-lista b { color: var(--cor-azul, #2570C6); }

.consentimento-botoes { display: flex; flex-direction: column; gap: var(--esp-8); }
#btn-autorizo {
  width: 100%;
  border: none;
  border-radius: 16px;
  padding: 15px 20px;
  font-family: var(--fonte-titulo);
  font-weight: 800;
  font-size: 17px;
  color: #FFFFFF;
  background: linear-gradient(135deg, var(--cor-azul, #2570C6), var(--cor-turquesa, #24BFAD));
  box-shadow: 0 6px 18px rgba(37, 112, 198, .3);
}
#btn-sair {
  width: 100%;
  border: none;
  background: transparent;
  color: var(--cor-texto-2, #5A6672);
  font-weight: 700;
  font-size: 15px;
  padding: 10px;
}

/* ============================================================
   🔴 12/08 (noite) — OS DOIS ACHADOS REAIS DA AUDITORIA DO MANUS
   Conferidos por mim em 812x360 antes de mexer: os dois procedem, e os dois
   nasceram de correções minhas de hoje.

   1) DEITADO: 0 de 9 cartões inteiros. A prancha ficava com 92px e o cartão
      com 210. Causa: 'grid-auto-rows' em 'vw' — no deitado a LARGURA é grande
      (812) e a ALTURA é curta (360), então a linha era dimensionada pelo lado
      errado. ⇒ a linha passa a respeitar as DUAS dimensões.
   2) A barra fixa usava 11px. O piso de 16px do DESIGN.md valia só para a
      palavra do cartão; as 6 palavras MAIS usadas do app ficaram de fora.
      ⛔ São as que a criança mais lê — é o pior lugar para economizar pixel.
   ============================================================ */
#prancha {
  /* min() com vh: em tela baixa quem manda é a altura. Em 812x360 dá ~86px
     de linha em vez de 210, e um cartão inteiro passa a caber. */
  grid-auto-rows: clamp(88px, min(31vw, 24vh), 210px);
}

/* o piso de 16px vale para TODA palavra que a criança lê, não só a do cartão */
#nucleo .botao-nucleo,
#nucleo .botao-nucleo .palavra {
  font-size: clamp(16px, 4vw, 20px);
}

/* Deitado: as faixas de cima cedem para sobrar altura de verdade à prancha.
   Medido antes: visor 83 + categorias 73 + núcleo 60 = 216px de 360. */
@media (max-height: 480px) {
  #barra-frase { padding: 2px var(--esp-8); }
  #balbuu-visor { width: 32px; height: 32px; }
  #frase-container { min-height: 34px; max-height: 46px; }
  /* ⛔ 40px reprova no Inspetor (mínimo 44 para o dedo) — medido em 12/08 à
     noite: "⌫ [72x40] · ✕ [72x40]". Apertar altura aqui economiza 4px e custa
     um botão que a criança erra. */
  #btn-apagar, #btn-limpar { min-height: 44px; }
  #btn-falar { min-height: 44px; }
  #categorias { padding: 2px var(--esp-8); }
  #categorias .cat-btn { min-height: 44px; padding: 2px var(--esp-8); }
  #categorias .cat-ico { width: 18px; height: 18px; }
  #nucleo { padding: 2px var(--esp-8); }
  #nucleo .botao-nucleo { min-height: 42px; }
  #nucleo .botao-nucleo .simbolo { width: 18px; height: 18px; }
  /* a palavra do núcleo NÃO encolhe junto: continua nos 16px */
  #nucleo .botao-nucleo .palavra { font-size: 16px; }
}

/* ============================================================
   🔴 12/08 (noite) — PALAVRA E CATEGORIA ESCONDIDAS ATRÁS DE ROLAGEM
   Achados 3 e 4 da auditoria de 12/08. O princípio que vale para os dois:

   🥇 GESTO DE ROLAGEM NÃO EXISTE PARA CRIANÇA NÃO LEITORA. Palavra que só
      aparece rolando é palavra que não existe — ela não sabe que tem mais.

   1) GRADE: a linha tinha altura FIXA ('grid-auto-rows'), então categoria de
      10-12 cartões empurrava de 1 a 3 palavras para fora da tela — sorvete,
      bolo, bicicleta, "com fome". Agora a grade recebe o NÚMERO DE LINHAS do
      JS e divide a altura disponível entre elas: cabendo, cabe tudo.
      O piso de 88px protege o alvo de toque; abaixo dele volta a rolar, e aí
      entra o botão grande de avanço (não o gesto).
   2) CATEGORIAS: a faixa é horizontal e mostrava 3 de 11 no celular em pé.
      Ganhou seta grande nas pontas — some quando não há o que rolar.
   ============================================================ */
/* 🪦 A altura da linha VOLTOU a ser só do CSS (o 'grid-auto-rows' lá de cima).
   Duas tentativas de calcular aqui e no JS morreram, e as duas ficam anotadas:
   ⛔ 'grid-template-rows: repeat(var(--linhas), minmax(88px,1fr))' não funciona:
      'repeat()' não aceita 'var()' na contagem. Vira inválido SEM erro no
      console e o navegador cai calado na regra de cima — parece aplicado e não
      está. Perdi tempo achando que a regra valia.
   ⛔ Calcular no JS quebrou a tela: 146 defeitos medidos, desenho cortado ao
      meio no PC. A altura do cartão já é decidida em 4 camadas deste arquivo;
      uma 5ª camada briga com todas.
   🥇 Enquanto a cascata de altura não for limpa de uma vez, ⛔ não empilhar
      camada nova aqui. */

/* ============================================================
   🔴🔴 O DESENHO SAÍA CORTADO — o achado dele na foto de 12/08 à noite
   ("a imagem tá cortada"): água, dormir, parar e colo com o desenho decepado.

   ⚠️ Medido: o defeito também está NA VERSÃO PUBLICADA (v33) — 458 cartões com
   corte nos 4 tamanhos. Não veio da rodada de agora; veio do redesenho de 12/08
   à tarde, quando a figura passou a ocupar 85% do cartão.

   A CAUSA: o quadro do símbolo tem tamanho próprio, preso à LARGURA. Quando o
   cartão fica mais largo que alto — o que acontece no PC e sempre que falta
   altura — o desenho continua pedindo o tamanho da largura, não cabe, e o
   'overflow: hidden' do cartão come o pé da figura.

   🥇 A regra do projeto já dizia o caminho: A FIGURA CEDE E A PALAVRA NUNCA.
      Só que ela não estava aplicada ao QUADRO do símbolo, só à imagem dentro.
   ⛔ 'aspect-ratio: 1' é obrigatório aqui: sem ele o disco vira ELIPSE ao
      encolher só a altura — erro já cometido neste arquivo em 12/08 (o print
      dele das 13h24). Encolher um círculo por um lado só o destrói.
   ============================================================ */
#prancha .botao-prancha .simbolo {
  flex: 1 1 auto;      /* cede altura em vez de estourar o cartão */
  min-height: 0;       /* sem isto o flex se recusa a encolher */
  aspect-ratio: 1;     /* ⛔ mantém o disco redondo enquanto encolhe */
  width: auto;
  max-width: 100%;
  margin-inline: auto;
  /* 🎨 E o quadro do símbolo perde o fundo próprio: com ele, o cartão virava
     CAIXA DENTRO DE CAIXA (visível na foto do PC) — mais uma borda para a
     criança processar, sem carregar significado nenhum. A figura agora se
     apoia direto no branco do cartão. */
  background: none;
  border: none;
  padding: 0;
}

/* 🔴 E O PAR "parar × sair" QUE SE SOBREPUNHA (também já estava na v33):
   a linha do grid mede 116px e o cartão exigia 124 de 'min-height' — 8px de
   vazamento sobre a fileira de baixo, exatamente o defeito que este arquivo já
   descreveu duas vezes.
   Agora que a figura cede (regra acima), o cartão pode obedecer à linha sem
   cortar nada. O alvo de toque continua enorme: quem manda no tamanho é a
   linha, nunca menos que os 88-120px do 'grid-auto-rows'.
   🥇 Regra: dentro de um grid, quem decide a altura é a LINHA. O item que
      insiste em ter altura própria vaza sobre o vizinho. */
#prancha .botao-prancha { min-height: 0; }

/* ============================================================
   🔴 A CATEGORIA INTEIRA CABE — agora em CSS puro (achado 3 da auditoria)
   Este é o conserto que eu tinha tentado no JS e quebrou a tela. A solução era
   uma linha de CSS que eu não tinha visto:

   'grid-auto-rows: minmax(120px, 1fr)' — as linhas DIVIDEM a altura disponível
   quando cabem, e param de encolher no piso de 120px quando não cabem.
   ⛔ Não confundir com 'grid-template-rows: repeat(var(--linhas), …)', que eu
      tentei antes: aquele precisa saber quantas linhas são e **'repeat()' não
      aceita 'var()'** — vira inválido sem avisar. O 'auto-rows' não precisa
      saber de nada, e é por isso que funciona.
   🥇 A regra: antes de calcular layout no JavaScript, procurar se o próprio
      grid já resolve. Quase sempre resolve, e sem brigar com a cascata.

   Medido depois: PC 6 → 9 cartões inteiros; tablet mostra categoria de 12
   inteira; celular em pé 9; deitado 6. Zero corte, zero sobreposição.
   ============================================================ */
/* 🪤 O PISO TAMBÉM CEDE EM TELA BAIXA. Com 120px fixo, o celular DEITADO (360px
   de altura) ficou com 0 de 9 cartões inteiros — o piso não cabia na tela.
   'clamp(88px, 24vh, 120px)': 120 na tela alta, 88 no deitado.
   ⛔ Altura de linha em medida fixa quebra o deitado. Já é a terceira vez que
      este projeto aprende isso — em pé sobra altura, deitado não sobra nada. */
#prancha { grid-auto-rows: minmax(clamp(88px, 24vh, 120px), 1fr); }

/* ⛔ ...com um teto, senão categoria curta em tela alta estica o cartão até
   virar um retângulo alto e estranho (já aconteceu: linha de 187px com 3
   palavras na tela). O cartão para de crescer e se centra na linha —
   ficar MENOR que a linha não sobrepõe ninguém; maior, sim. */
#prancha .botao-prancha { max-height: 210px; align-self: center; }

/* --- as setas da faixa de categorias --- */
#faixa-categorias {
  position: relative;
  display: flex; align-items: center;
  flex-shrink: 0;
  border-bottom: var(--borda);
}
#faixa-categorias #categorias { flex: 1; border-bottom: none; }

.cat-seta {
  flex-shrink: 0;
  width: var(--toque-min); min-height: var(--toque-min);
  display: grid; place-items: center;
  border: none; background: var(--cor-fundo); color: var(--cor-texto);
  cursor: pointer; padding: 0;
}
.cat-seta[hidden] { display: none; }
.cat-seta:active { background: var(--cor-turquesa); color: var(--cor-fundo); }
.cat-seta svg { width: 24px; height: 24px; display: block; }

/* --- o botão de mais palavras, quando a grade não coube --- */
#btn-mais-palavras {
  /* 🪤 DUAS TENTATIVAS ERRADAS ANTES DESTA, as duas tapando palavra:
     1ª centralizado no meio da tela (comia o cartão "parar" inteiro, foto do PC)
     2ª fixo no canto de baixo (continuava por cima da grade quando ela rolava —
        'position: fixed' está FORA do fluxo, então nada reserva espaço para ele).
     ⇒ Agora ele vive NO FLUXO, como último item do '#app': empurra a prancha em
       vez de cobrir, e quando está escondido não ocupa altura nenhuma.
     ⛔ 'margin-right' reserva a coluna dos 3 botões redondos do adulto, que são
       fixos ali — sem isso o dedo da criança acerta o cadeado. */
  align-self: flex-start;
  margin: 0 auto var(--esp-8) var(--esp-16);
  margin-right: 190px;
  flex-shrink: 0;
  z-index: 5;
  display: flex; align-items: center; gap: var(--esp-8);
  min-height: var(--toque-min); padding: var(--esp-8) var(--esp-16);
  border: var(--borda); border-radius: 999px;
  background: var(--cor-turquesa); color: var(--cor-fundo);
  font-family: var(--fonte); font-size: 16px; font-weight: 600;
  cursor: pointer; box-shadow: var(--sombra-marca);
}
#btn-mais-palavras[hidden] { display: none; }
#btn-mais-palavras svg { width: 20px; height: 20px; display: block; }

/* ============================================================
   🎨 O FUNDO PASSA A SER O DO BALBUU (pedido dele, 12/08 à noite:
   "o fundo pode botar o degradê igual Balbuu, não precisa desse cinza aí")

   O cinza era '--cor-fundo: #F2F7F7', papel neutro. Trocado pelo mesmo degradê
   do app do Balbuu (navy → azul → teal), reaproveitado de
   'Balbuu\fonemas-app\index.html'. ⛔ A variável '--cor-fundo' NÃO muda: ela
   pinta botão, painel e cartão, e virar degradê quebraria os três.

   🥇 De quebra resolve a outra coisa que ele apontou — "tem telas demais para
      uma criança". Não eram telas: eram quatro faixas com fundo próprio
      empilhadas (frase, categorias, núcleo, prancha), cada uma desenhando a
      própria caixa. Agora as faixas ficam TRANSPARENTES e o degradê corre por
      trás de tudo: os botões flutuam num fundo só, e a tela deixa de parecer
      um formulário em camadas.
   ⚠️ A barra da frase continua navy: ela É o topo do degradê, não uma faixa
      separada.
   ============================================================ */
body {
  background: #0E2A4A;   /* ⛔ cor sólida antes: iPhone antigo não tem degradê de 4 paradas */
  background: linear-gradient(180deg, #0E2A4A 0%, #123B66 38%, #0E5E8F 70%, #1B8FA8 100%);
  background-attachment: fixed;
}
#app, #faixa-categorias, #categorias, #nucleo, #prancha { background: transparent; }
#faixa-categorias, #categorias, #nucleo { border-bottom: none; }

/* 🔴 O VISOR PRECISA DE CAIXA. Com o degradê atrás, a barra da frase ficou sem
   fundo e o chip da palavra passou a flutuar solto no meio do azul (foto de
   12/08). O visor é o lugar onde a frase se monta — é o que a criança aponta
   para o adulto ler. Ele tem que ser uma CAIXA, visivelmente. */
#frase-container {
  background: rgba(255, 255, 255, .10);
  border: 1px solid rgba(255, 255, 255, .22);
  border-radius: var(--raio);
  padding: var(--esp-8);
}

/* as setas viram botão branco de verdade: sobre fundo escuro, ícone navy solto
   ficaria invisível */
.cat-seta {
  background: var(--cor-cartao);
  border: var(--borda); border-radius: 999px;
  /* ⛔ 44px nos DOIS lados. Estava 40 de largura e o Inspetor reprovou:
     "Mais categorias [40x44]". Alvo de toque é área, não só altura. */
  width: var(--toque-min); min-height: var(--toque-min);
  max-width: 44px; margin: 0 var(--esp-4);
  box-shadow: var(--sombra-marca);
}

/* ⛔ O alto contraste desliga o degradê — é a regra do DESIGN.md, e sem isto o
   modo de quem enxerga pouco ficaria com fundo azulado no lugar do preto. */
body.alto-contraste {
  background: var(--hc-fundo);
}
body.alto-contraste .cat-seta {
  background: var(--hc-fundo); color: var(--hc-texto); border-color: var(--hc-borda);
}

/* --- voltar a frase apagada (fica pendurado na borda da barra da frase, que
       já é 'position: relative') --- */
#btn-voltar-frase {
  position: absolute; right: var(--esp-8); bottom: -18px; z-index: 3;
  display: flex; align-items: center; gap: var(--esp-4);
  /* ⛔ 44px é o piso do Inspetor, e vale também para botão que aparece pouco:
     o adulto aperta este com pressa, olhando a criança e não a tela. */
  min-height: var(--toque-min); padding: var(--esp-4) var(--esp-12);
  border: var(--borda); border-radius: 999px;
  background: var(--cor-fundo); color: var(--cor-texto);
  font-family: var(--fonte); font-size: 14px; font-weight: 600;
  cursor: pointer; box-shadow: var(--sombra-marca);
}
#btn-voltar-frase[hidden] { display: none; }
#btn-voltar-frase svg { width: 16px; height: 16px; display: block; }

@media (max-height: 480px) {
  #faixa-categorias .cat-seta { min-height: 44px; }
  #btn-mais-palavras { padding: var(--esp-4) var(--esp-12); }
  #btn-voltar-frase { bottom: -16px; }
}


/* ============================================================
   🔴🪤 O VISOR ESMAGADO NO NAVEGADOR (print dele, 13/08)
   Palavra dele: "quando instalei ficou legal, mas no navegador tem esse espaço
   na direita e lá em cima curto". O que ele via: a frase virava uma coluna
   estreita com as palavras empilhadas de lado.

   🥇 A CAUSA: a regra do CELULAR DEITADO dispara só por ALTURA
   ('max-height: 620px'). Ela põe visor e botões numa fileira só, em 5 colunas —
   o que só faz sentido quando SOBRA LARGURA. Só que o celular EM PÉ com a barra
   do navegador aberta também fica com menos de 620px de altura... e 390px de
   largura. As 5 colunas não cabem e o visor é espremido para 65px (medido).
   Instalado na tela inicial não acontece: sem a barra, a altura passa de 620 e
   a regra nem entra. É exatamente por isso que "instalado ficou legal".

   ⛔ REGRA: 'max-height' sozinho NÃO significa deitado. Deitado é falta de
      altura COM sobra de largura — as duas coisas, sempre.
   🪤 E este bloco tem que ficar no FIM DO ARQUIVO: '@media' não aumenta
      especificidade, então quem vence é quem vem depois. Escrevi ele no meio do
      arquivo primeiro e não fez efeito nenhum — o mesmo erro que o comentário
      do deitado, lá em cima, já avisava.
   ============================================================ */
@media (max-height: 620px) and (max-width: 599px) {
  #barra-frase {
    grid-template-columns: auto 1fr auto auto;
    grid-template-areas:
      "bicho frase  frase  frase"
      "bicho apagar limpar falar";
  }
  /* a marca continua fora: quem precisa da altura é a prancha */
  #barra-frase::before { display: none; }
}


/* ============================================================
   🔴 26/08/2026 — O BOTÃO DE ENTRAR NÃO APARECIA NO CELULAR PEQUENO.
   Medido no ar, na PRIMEIRA tela que todo mundo vê:
       320x568 → o "Sou o responsável e autorizo" ficava 246px ABAIXO da tela
       360x640 → 88px abaixo   ·   390x844 → visível
   O overlay ROLAVA (conserto de 12/08), então o botão era alcançável — mas
   nada na tela dizia isso. Mãe apressada num Android popular via uma lista de
   regras sem saída e ia embora achando que o app não abre.
   ⛔ "Dá pra rolar até lá" NÃO é o mesmo que "aparece". A ação que destranca
      o app fica SEMPRE visível; quem rola é o texto, não o botão.
   🥇 O jeito: a caixa vira uma coluna com teto de altura, a LISTA é a única
      parte que rola, e a fileira de botões é o rodapé que não sai do lugar.
   ⚠️ 'min-height: 0' é obrigatório: item de flex se recusa a encolher abaixo
      do próprio conteúdo, e sem isso a lista empurra o botão pra fora de novo.
   ⚠️ '100dvh' (não '100vh'): no celular a barra do navegador entra e sai, e o
      'vh' mede a tela SEM a barra — a conta dá maior que a tela de verdade.
   ============================================================ */
.consentimento-caixa {
  max-height: calc(100vh - 32px);
  max-height: calc(100dvh - 32px);
  display: flex;
  flex-direction: column;
}
.consent-lista {
  overflow-y: auto;
  -webkit-overflow-scrolling: touch;
  min-height: 0;
  flex: 1 1 auto;
}
.consentimento-botoes { flex-shrink: 0; }
.consent-personagem, .consentimento-caixa h2, .consent-abre { flex-shrink: 0; }

/* Tela baixa: o topo cede espaço para a lista respirar.
   🩸 A 1ª tentativa deste conserto trouxe o botão para a tela e ESMAGOU a
   lista a ZERO em 320x568 — a mãe veria "Ao continuar, você concorda que:"
   seguido do botão, sem uma única regra no meio. Autorizar sem ver o que se
   autoriza é pior que o bug original. ⛔ Só o número disse "botão visível";
      quem pegou isso foi OLHAR a foto.
   📐 O que foi medido em 320x568 (caixa de 536px) e o que cada corte devolve:
        logo "balbuu" do ::before ... 51px  → sai (o passarinho já é a marca)
        gap de 16 entre 6 blocos .... 80px  → 8px, devolve 40
        "Ao continuar…" em 2 linhas .. 54px → fonte menor, devolve ~27
        fileira de botões ........... 164px → devolve ~60
      ⇒ ~178px de volta para a lista, que precisa de 326.
   ⚠️ '--toque-min: 72px' é o alvo da MÃO DA CRIANÇA, e esta tela é do ADULTO
      — a mesma exceção já aberta no DESIGN.md para as abas de categoria.
   ⛔ 'min-height' na lista é o que impede a volta do esmagamento: com ele a
      lista some por último, nunca primeiro. */
@media (max-height: 700px) {
  .consentimento-caixa { padding: 14px 14px 12px; gap: var(--esp-8); }
  .consentimento-caixa::before { display: none; }
  .consent-personagem { width: 52px; height: 52px; }
  .consentimento-caixa h2 { font-size: 18px; }
  .consent-abre { font-size: 14px; margin-bottom: var(--esp-4); }
  .consent-lista { margin-bottom: var(--esp-8); }
  .consentimento-botoes button { min-height: 52px; }
  .consentimento-botoes #btn-sair { min-height: 40px; }
}

/* A lista nunca some: some por último, e sempre mostra 3 linhas.
   ⛔ Sem isto o flex esmaga a lista a zero antes de encolher qualquer outra
      coisa — foi exatamente o que aconteceu. */
.consent-lista { min-height: 5.4em; }

/* 🪤 A LISTA ROLA, MAS NADA DIZIA ISSO: em 360px o texto cortava no meio de
   uma frase e parecia conteúdo quebrado, não conteúdo que continua.
   A sombra de baixo é a pista de "tem mais aqui". Ela vive no PAI, porque
   dentro do elemento que rola ela rolaria junto e sumiria. */
.consent-lista-area {
  position: relative; min-height: 0; flex: 1 1 auto; display: flex;
}
.consent-lista-area::after {
  content: ''; position: absolute; left: 0; right: 0; bottom: 0; height: 24px;
  background: linear-gradient(to bottom, rgba(255,255,255,0), #fff);
  pointer-events: none;
}

/* 🐛 O teto de altura que trouxe o botão para a tela nos celulares pequenos
   cortou 15px da ÚLTIMA regra num celular grande (390x844) — onde antes cabia
   tudo. Medido: lista precisa de 284px e recebia 269.
   ⇒ 12px do passarinho + 10px dos vãos devolvem 22. Sobra folga de 7.
   ⛔ Não voltar o passarinho para 84: ele é a peça que mais cresce quando o
      texto legal cresce, e é o primeiro a empurrar a última regra para fora. */
.consentimento-caixa { gap: 14px; }
.consent-personagem { width: 72px; height: 72px; }

/* 🐛 26/08/2026 — '1fr' NÃO É "um pedaço igual": o mínimo dele é 'auto', ou
   seja, o tamanho do CONTEÚDO. Uma palavra comprida numa figura da prancha
   ("descansar", "banheiro") se recusa a encolher, empurra a coluna e a tela
   inteira ganha rolagem lateral — no celular a criança perde a última coluna.
   'minmax(0, 1fr)' diz "pode encolher até zero", e aí o texto quebra em vez
   de empurrar. Trocado em TODOS os grids do app de uma vez.
   ⛔ Não escrever 'repeat(N, 1fr)' de novo neste projeto. */

/* 🔴 26/08/2026 — TEXTO BRANCO SUMINDO NA PONTA DO DEGRADÊ.
   O botão que destranca o app ia de '#2570C6' (azul) a '#24BFAD' (turquesa),
   com texto branco. Medido: sobre o azul dá 5,03 — ótimo; sobre o turquesa dá
   **2,30**. Metade do botão mais importante do app estava ilegível.
   🪤 É o MESMO bug do "EXERCÍCIOS DE FALA" do Balbuu de produção (26/08): a
      cor de marca funciona como FUNDO DE BLOCO e falha como fundo de TEXTO.
   ⛔ Turquesa '#24BFAD' não recebe texto branco em lugar nenhum deste app.
   ✅ A ponta vira '--cat-6' (#1A8F82, o teal escurecido que JÁ está na paleta —
      não se inventou cor) e a fonte sobe para 19px/800. A 19 em negrito o alvo
      passa a ser 3,0 (regra de texto grande) e o pior ponto do botão dá 3,96.
   ⚠️ Não é folga grande: se alguém clarear esse teal, o botão quebra de novo. */
#btn-autorizo {
  background-image: linear-gradient(135deg, var(--cor-azul), var(--cat-6));
  font-size: 19px;
}

/* 🐛 26/08/2026 — A INSTRUÇÃO DO VISOR ESTAVA NO LIMITE DA LEITURA.
   "Toque nos botões para montar a frase" é o texto que ensina o app a quem
   abre pela primeira vez, e media **3,57** de contraste em 16px — abaixo dos
   4,5 exigidos. Medido por pixel no recorte: papel rgb(32,72,96) (o azul do
   visor sobre o fundo), tinta #8FA3B5.
   ⛔ NÃO clarear a cor: '--cor-visor-vazio' é o '--cat-5' da paleta e trocá-la
      inventa a 8ª cor do app — o DESIGN.md proíbe.
   ✅ 19px em negrito faz o texto entrar na régua de TEXTO GRANDE (alvo 3,0),
      onde 3,57 passa com folga — e de quebra a mãe lê a instrução de longe.
   🪤 A régua 'le-se.js' NÃO enxerga este texto: ele é 'content' de '::before',
      e pseudo-elemento não é nó de texto. Foi medido na mão. */
#frase-container:empty::before {
  font-size: 19px;
  font-weight: 700;
}


/* ============================================================
   PASSADA DE DESIGN — 26/08/2026, para o app entrar na Play Store.
   Ordem dele: "foca em ui ux e tudo pq quero publicar esse app na play".
   Tudo abaixo saiu de OLHAR a folha de contato das 12 telas, não de medição.
   ============================================================ */

/* 1. 🔴 A TELA DE TRAVA NÃO PARECIA O BALBUU.
   Cadeado cinza + uma frase + um campo, num fundo claro chapado: a tela que a
   mãe mais vê quando entrega o celular para a criança era a única sem marca
   nenhuma. Na loja, print assim faz o app parecer inacabado.
   ⇒ Ganha o fundo da prancha, o cadeado em círculo com a cor da marca e o
   texto em branco. ⛔ Sem inventar cor: tudo sai de `--cor-azul`/`--cat-1`. */
#trava-tela {
  background: linear-gradient(160deg, #0C3B57 0%, #17607F 100%);
  color: #FFFFFF;
  padding: var(--esp-24);
}
#trava-tela p {
  font-family: var(--fonte-titulo); font-weight: 800;
  font-size: 20px; text-align: center; margin: 0;
}
#trava-tela .icone-trava {
  width: 96px; height: 96px; display: grid; place-items: center;
  border-radius: 50%; background: rgba(255,255,255,.12);
  border: 2px solid rgba(255,255,255,.35);
  font-size: 40px;
}
#trava-tela input {
  background: #FFFFFF; border: 2px solid var(--cat-1);
  font-size: 22px; font-weight: 700; letter-spacing: .3em;
  min-height: 56px; width: 200px;
}

/* 2. 🔴 O MODAL DE PIN NÃO TINHA VÉU: a prancha inteira, colorida, continuava
   competindo com a caixinha branca no meio. O olho não sabia onde olhar, e o
   print ficava confuso.
   ⛔ Véu é obrigatório em modal que tapa o app — o consentimento já tinha um. */
.modal-pin {
  background: rgba(6, 40, 64, .55);
  backdrop-filter: blur(2px);
}
.modal-pin .caixa { box-shadow: var(--sombra-alta); }

/* 3. 🟡 A ÚLTIMA ABA DE CATEGORIA CORTAVA NO MEIO DA PALAVRA ("Per…").
   Corte seco lê como defeito; corte com esmaecimento lê como "tem mais".
   A seta já existe — o que faltava era a pista de que a faixa desliza. */
#faixa-categorias #categorias {
  -webkit-mask-image: linear-gradient(to right, #000 0, #000 calc(100% - 28px), transparent 100%);
  mask-image: linear-gradient(to right, #000 0, #000 calc(100% - 28px), transparent 100%);
}


/* 4. 🟡 O TUTORIAL DEIXAVA 60% DA TELA EM BRANCO.
   O conteúdo de cada passo ocupava o terço de cima e o resto era vazio — lê
   como tela inacabada, e é a segunda coisa que todo mundo vê.
   ⇒ O conteúdo centraliza no espaço que sobra e os botões ficam no rodapé, que
   é onde o polegar já está. ⛔ Não encher o vazio com decoração: o tutorial é
   para ser lido e vencido depressa. */
#painel-tutorial {
  display: flex;
  flex-direction: column;
}
#tutorial-conteudo {
  flex: 1 1 auto;
  display: flex;
  flex-direction: column;
  justify-content: center;
  min-height: 0;
  overflow-y: auto;
}
#painel-tutorial .parceiro-navegacao {
  flex-shrink: 0;
  padding-bottom: var(--esp-24);
}

/* 5. 🎨 A trava ganha o passarinho e o cadeado vira selo pequeno em cima dele:
   o que a criança vê primeiro é o Balbuu, não um cadeado. */
.trava-personagem { width: 108px; height: 108px; display: block; }
/* 🐛 27/08 — a intenção acima estava certa, a conta não: `margin-top: -28px`
   sozinho puxa o selo para cima MANTENDO-O centrado, e ele foi parar em cima
   dos PÉS do passarinho, parecendo erro de montagem. Achado olhando o print
   que ia para a loja.
   ✅ Empurra também para a direita (vira selo no canto, como crachá) e ganha
   um anel escuro que o RECORTA do desenho — sem o anel, cadeado e passarinho
   viram uma mancha só. */
#trava-tela .icone-trava {
  width: 60px; height: 60px; font-size: 26px;
  margin: -30px 0 0 84px;
  box-shadow: 0 0 0 5px #114F6D;
}
#trava-tela { gap: var(--esp-16); }

/* ============================================================
   🔴🔴 26/08/2026 — ELE RELATOU: "quando entra nessas configs não dá mais
   para voltar para a página inicial e ver as pranchas". ESTAVA CERTO.

   📐 Medido com o DEDO (tap real, Pixel 5, no ar): depois de rolar os Ajustes
   até o fim, o X de fechar ficava com o topo em **-3257px** — três mil pixels
   ACIMA da tela. Não havia como tocá-lo. A pessoa ficava presa e a única saída
   era fechar o app.

   🪤 O TESTE AUTOMÁTICO DISSE QUE ESTAVA TUDO BEM. O Playwright rola até o
   elemento antes de clicar, então o robô SEMPRE alcança o botão. O dedo não
   rola de volta — ele procura o botão onde ele deveria estar.
   ⛔ "O robô fechou o painel" não prova que a pessoa consegue fechar.

   ✅ O cabeçalho de todo painel que rola gruda no topo. A saída fica SEMPRE
   na tela, em qualquer ponto da rolagem.
   ⛔ Painel novo que rola nasce com o cabeçalho grudado — sem exceção.
   ============================================================ */
.ajustes-header {
  position: sticky;
  top: 0;
  z-index: 5;
  background: var(--cor-fundo);
  /* a borda de baixo já existia; a sombra só aparece quando há conteúdo
     passando por baixo, e é o que diz "isto está flutuando". */
  box-shadow: 0 2px 10px rgba(21, 39, 58, .08);
}

/* O mesmo vale para a fileira de botões do tutorial e do painel do parceiro:
   quem lê até o fim precisa achar "Próximo" sem rolar de volta. */
#painel-parceiro .parceiro-navegacao,
#painel-tutorial .parceiro-navegacao {
  position: sticky;
  bottom: 0;
  background: var(--cor-fundo);
  box-shadow: 0 -2px 10px rgba(21, 39, 58, .08);
}

/* 🔴🔴 26/08/2026 — O "voltar a frase" ROUBAVA O TOQUE DO "FALAR".
   Provado usando o app: `elementFromPoint` no CENTRO do FALAR devolvia
   `btn-voltar-frase`. Ou seja, depois de limpar a frase, quem tocasse no botão
   principal do app — o que faz o aparelho FALAR — acertava o botãozinho de
   desfazer. O app inteiro existe para esse toque.
   📐 Medido em 393x851 (Pixel 5): FALAR em x=276..385, e o "voltar a frase"
   ancorado à direita (132px de largura) caía em cima dele.
   ✅ Ele passa para a ESQUERDA, embaixo do ⌫ e do ✕, onde não há nada.
   ⛔ Nada de posição absoluta ancorada à direita nessa barra: aquele canto é
      do FALAR. */
#btn-voltar-frase {
  right: auto;
  left: var(--esp-8);
}

/* 🐛 26/08/2026 — A LINHA DO EDITOR DO ADULTO ESTAVA ILEGÍVEL.
   Visto ampliando o print: dois campos de texto colados um no outro sem
   rótulo nenhum (ninguém sabia que o de baixo era a FIGURA), e o botão da
   câmera pousado EM CIMA da borda do campo de baixo, cortando ele.
   Somado aos emoji de sistema no lugar dos ícones, a tela onde a fono
   trabalha era a mais feia do app.
   ✅ Os campos ganham respiro e os 4 botões viram alvos redondos de 44px
      com os ícones SVG novos. ⛔ Nada de emoji aqui — regra do CLAUDE.md. */
.editor-btn-item .info { display: flex; flex-direction: column; gap: var(--esp-4); }
.editor-btn-item .info input { min-height: 40px; padding: var(--esp-4) var(--esp-8); }
.editor-btn-item .acoes { display: flex; gap: var(--esp-4); align-items: center; }
.editor-btn-item .acoes button {
  width: 44px; height: 44px; min-height: 44px; padding: 0;
  display: grid; place-items: center; flex-shrink: 0;
  background: transparent; border: none; border-radius: 50%; cursor: pointer;
}
.editor-btn-item .acoes button .ui-ico { width: 30px; height: 30px; display: block; }
.editor-btn-item .acoes button:active { background: rgba(21,39,58,.08); }

/* 🐛 O X de fechar o modo adulto era ROSA — a mesma cor de "Apagar todos os
   dados". A fono lia "apagar" onde estava escrito "fechar" e não clicava.
   ⛔ Rosa neste app é destruição. Fechar é neutro. */
#fechar-adulto {
  background: var(--desab-fundo) !important;
  color: var(--cor-texto) !important;
  border: 1px solid var(--desab-borda) !important;
}

/* O "voltar a frase" deixa de flutuar e vira um botão da fileira, no lugar do
   ✕ — ver o comentário em `mostrarVoltarFrase()` (js/ui/prancha.js).
   ⛔ Nada de `position: absolute` aqui: foi assim que ele roubou o toque do
      FALAR e depois o do ⌫. */
#btn-voltar-frase {
  position: static; right: auto; left: auto; bottom: auto;
  flex-shrink: 0; max-width: 152px;
  justify-content: center;
}

/* 🪤 `hidden` NÃO ESCONDE quando o CSS dá `display` ao elemento. Escondi o ✕
   por JS e ele continuou na tela — o medidor dizia "escondido" (o atributo
   estava lá) e a FOTO mostrava o botão. ⛔ Quem decide é a foto.
   E o "voltar a frase", ao virar item do fluxo, foi parar ACIMA do visor,
   empurrando a barra inteira. `order` põe ele na fileira dos botões, no lugar
   exato que o ✕ deixou. */
#barra-frase [hidden] { display: none !important; }
#btn-voltar-frase { order: 3; }
#btn-apagar { order: 2; }
#btn-falar  { order: 4; }

/* 🪤 `order` só resolve se TODOS os irmãos tiverem ordem. Dei ordem a três
   botões e o passarinho e o visor ficaram no padrão (0), então o "voltar a
   frase" (3) continuou caindo numa linha própria acima de tudo.
   ⇒ Ordem explícita na fileira inteira. */
#barra-frase #balbuu-visor   { order: 0; }
#barra-frase #frase-container{ order: 1; flex-basis: 100%; }
#barra-frase #btn-apagar     { order: 2; }
#barra-frase #btn-limpar     { order: 3; }
#barra-frase #btn-voltar-frase { order: 3; }
#barra-frase #btn-falar      { order: 4; margin-left: auto; }

/* O "voltar a frase" ocupa a primeira linha da barra, sozinho e alinhado à
   direita. ⚠️ Não é o lugar mais bonito — mas é o único que NÃO rouba o toque
   de ninguém, e ele vive 10 segundos. Tentei três posições antes desta:
   à direita da barra (roubava o FALAR), à esquerda (roubava o ⌫) e no lugar do
   ✕ (o `order` não venceu o `flex-wrap` do visor).
   ⛔ Antes de mexer nisto de novo: medir `elementFromPoint` no centro do FALAR
      e do ⌫. Se algum devolver `btn-voltar-frase`, voltou o bug. */
#barra-frase #btn-voltar-frase {
  margin-left: auto;
  min-height: 52px;
  font-size: 15px;
  padding: var(--esp-4) var(--esp-16);
}

/* 🐛 26/08 — OS DOIS INTERRUPTORES DOS AJUSTES MEDIAM 13px DE LARGURA.
   `chk-contraste` e `chk-nucleo` eram a caixinha padrão do navegador: 13x13,
   com o rótulo caindo na linha de baixo (visto no print). Quem tem a mão
   trêmula, ou está com a criança no colo, não acerta 13px.
   ✅ O RÓTULO INTEIRO vira o alvo: a linha toda tem 44px e reage ao toque,
   como interruptor de app de verdade. A caixinha cresce para 24px.
   ⛔ Alvo de interface neste app não fica abaixo de 44px — a régua do molde
      cobra isso, e ela cobrou. */
.ajustes-grupo label:has(input[type="checkbox"]) {
  display: flex; align-items: center; gap: var(--esp-12);
  min-height: 52px; padding: var(--esp-8) var(--esp-4);
  cursor: pointer; border-radius: var(--raio);
  font-weight: 600; line-height: 1.35;
}
.ajustes-grupo label:has(input[type="checkbox"]):active { background: rgba(21,39,58,.05); }
.ajustes-grupo input[type="checkbox"] {
  width: 24px; height: 24px; min-height: 24px; flex-shrink: 0;
  accent-color: var(--cor-turquesa); cursor: pointer;
}

/* 🐛 26/08 — OS CAMPOS DO EDITOR DA FONO ERAM PEQUENOS DEMAIS.
   Medido nas 4 análises: `edt-cat-nome` e `edt-cat-icone` com **22px** de
   altura, `edt-palavra` e `edt-simbolo` com 40. É a tela onde a fono monta a
   prancha do paciente, campo por campo, e onde ela mais erra o toque.
   ⛔ 44px é o piso — vale também para campo de digitar, não só para botão. */
.edt-cat-nome, .edt-cat-icone, .edt-palavra, .edt-simbolo,
#painel-adulto input[type="text"] {
  min-height: 44px;
  padding: var(--esp-8);
  font-size: 16px;   /* ⚠️ abaixo de 16px o iPhone dá ZOOM sozinho ao focar */
}

/* O "Sair" do consentimento tinha 40px. Ele é uma saída, e saída se acerta. */
.consentimento-botoes #btn-sair { min-height: 44px; }

/* 🐛 Últimos alvos pequenos do editor, medidos nas 4 análises:
   `del-cat` (apagar categoria) com **22px de largura** e `edt-cat-icone` com 29.
   ⛔ Botão que APAGA precisa ser fácil de ver e difícil de errar — nunca o
      contrário. 44px nos dois. */
.del-cat {
  min-width: 44px; width: 44px; height: 44px; min-height: 44px;
  display: grid; place-items: center; flex-shrink: 0;
}
.edt-cat-icone { min-width: 56px; width: 56px; text-align: center; }

/* 🐛 26/08 — EM CELULAR PEQUENO AS 6 PALAVRAS FIXAS TINHAM 39px DE LARGURA.
   Medido em 320x568: seis colunas em 320px de tela dão 39px cada, e o
   DESIGN.md manda 72px nos botões da prancha porque **mão de criança erra
   mais**. "quero, mais, sim, não, acabou, ajuda" são justamente as palavras
   que ela mais toca.
   ✅ Abaixo de 340px viram DUAS fileiras de três: cada botão fica com ~96px.
   ⛔ Não espremer as seis numa linha só para "caber bonito" — quem paga é o
      dedo da criança. */
@media (max-width: 340px) {
  #nucleo { grid-template-columns: repeat(3, minmax(0, 1fr)); }
}

/* 🐛 26/08 — A SETA DA FAIXA ROUBAVA O TOQUE DA ÚLTIMA ABA VISÍVEL.
   Medido em 393px: a aba "Perguntas" ocupava x=307..392 e a seta x=345..389 —
   o CENTRO da aba caía debaixo da seta. Quem via "Per…" e tocava para entrar
   na categoria fazia a faixa rolar, não abrir.
   ✅ A área que rola termina ANTES da seta: nenhuma aba fica por baixo dela.
   ⛔ Botão flutuante não pode pousar sobre área tocável — foi o mesmo erro do
      "voltar a frase" sobre o FALAR, no mesmo dia. */
#faixa-categorias { padding-right: 48px; }

/* O rodapé da folha impressa: a linha da marca lê primeiro, o crédito legal
   fica menor embaixo. ⛔ O crédito do Mulberry não sai — é licença CC BY-SA. */
@media print {
  .folha-marca {
    font-weight: 700;
    font-size: 9pt;
    margin-bottom: 1mm;
  }
  .folha-credito {
    font-size: 7.5pt;
    color: #444;
  }
}
