Tema
Parte 7: Design System e Linguagem Visual
Projeto Caminho. Versão 0.1, 2026-07-19. Status: aprovada (2026-07-19), incluindo as decisões DS1-DS6. Etapa DS-A (fundação) implementada em 2026-07-19. Motivação: garantir uma UI prática de desenvolver, intuitiva, moderna e profissional, eliminando por construção os riscos de UI não uniforme, retrabalho e resultado amador. Substitui e detalha a linha única sobre estilo da Parte 4 (seção 3).
1. Diagnóstico: auditoria do estado atual (2026-07-19)
O CSS do protótipo é um placeholder assumido, e a auditoria mostra exatamente o padrão que produz resultado amador:
| Categoria | Achado | Alvo de um sistema |
|---|---|---|
| Cor | 59 valores hex no arquivo, dos quais só 9 estão em variáveis: 50 cores cravadas na mão | ~12 tokens semânticos, zero hex solto |
| Espaçamento | 190 ocorrências de px em 34 valores distintos (16, 14, 12, 10, 8, 6, 4, 18, 20, 15, 13, 3, 22, 9, 26, 28...) | escala de 8 a 10 degraus |
| Tipografia | fonte do sistema, tamanhos ad hoc | 1 família definida + escala de 6 a 7 degraus |
| Ícones | emojis (🪔 ⭐ 🐑) | conjunto vetorial coerente |
| Documentação | nenhuma | guia vivo dentro do app |
Falhas de acessibilidade já presentes (contraste calculado sobre as cores em uso, critério WCAG 2.1 AA):
| Uso | Contraste | Situação |
|---|---|---|
Dourado #b98a2f sobre card branco (títulos de unidade e seção, 13px) | 3,12:1 | Reprova para texto pequeno (exige 4,5:1) |
Cinza #9a8f75 sobre fundo areia (nota de rodapé 12px, dicas 14px) | 2,97:1 | Reprova |
Cinza #6b6455 sobre areia | 5,44:1 | Passa |
| Tinta sobre areia (corpo) | 13,23:1 | Passa |
| Verde sobre branco / branco sobre verde | 6,37:1 | Passa |
Áreas de toque abaixo do mínimo (44px na Apple, 48dp no Material): o botão de sair da lição (~32px), o botão "Praticar" (~33px) e, mais grave, os tokens de palavra do "Monte o versículo" (~36px), que são a interação central do produto e serão tocados por dedos de criança.
Nada disso é "descuido no CSS": é o resultado inevitável de escrever estilo sem sistema. E é exatamente o que se acumula em bugs e retrabalho na fase final de um projeto.
2. Os quatro medos e os mecanismos que os previnem
| Medo (experiência anterior) | Mecanismo que elimina |
|---|---|
| UI não uniforme | Tokens como única fonte de valores + Tailwind, onde usar um valor fora da escala exige sintaxe explícita de exceção (e o lint barra) |
| Dificuldade de implementação | Componentes prontos e acessíveis (shadcn/Radix) para a parte chata (diálogo, foco, teclado); utilitários evitam nomear classe e caçar CSS morto |
| Ajustes e bugs pós-construção | Acessibilidade e estados definidos no componente, não improvisados na tela; contraste verificado no CI; guia vivo para revisar tudo numa página |
| Resultado amador | Tipografia e escala profissionais desde o início; movimento com intenção; identidade autoral do ilustrador aplicada sobre uma base sólida |
3. Decisão de ferramental (DS1)
Tailwind CSS v4 + shadcn/ui (sobre Radix) + Motion (ex-Framer Motion).
- Tailwind v4 é o motor de restrição: o
@themeem CSS é a camada de tokens, e as classes utilitárias só oferecem os valores da escala. É a resposta direta aos 34 espaçamentos distintos. Em 2026 é o padrão de fato para React novo. - shadcn/ui não é uma biblioteca que se instala e prende: você copia o código do componente para o repositório e passa a ser dono dele. Isso dá a acessibilidade e o comportamento do Radix (foco, teclado, ARIA, que é onde nascem os bugs tardios) sem herdar um visual de dashboard que brigaria com a cara de jogo. Restilizamos com nossos tokens.
- Motion para as animações de jogo (celebração, transição do caminho, a ovelha reagindo), com
prefers-reduced-motionrespeitado.
Alternativa considerada e descartada: CSS Modules com arquivo de tokens. Não impede ninguém de digitar padding: 13px; ou seja, não resolve o problema que estamos atacando. Bibliotecas completas (MUI, Chakra) foram descartadas por peso e por um visual corporativo difícil de transformar em jogo infantojuvenil.
Isso reconcilia o plano com o código: a Parte 4 já previa Tailwind; o protótipo usou CSS puro por velocidade, e agora convergimos.
4. Arquitetura de tokens (três camadas)
O mesmo princípio do economy-config (as regras do jogo num lugar só, calibráveis) aplicado ao visual: arquitetura estável, valores trocáveis. Quando a identidade do ilustrador chegar, é troca de valores, não reescrita.
Camada 1 — Primitivos (a paleta bruta)
--verde-50 ... --verde-900, --dourado-50 ... --dourado-900, --areia-*, --tinta-*
↓ nunca usados direto na interface
Camada 2 — Semânticos (o papel de cada cor)
--cor-superficie, --cor-superficie-elevada, --cor-texto, --cor-texto-suave,
--cor-primaria, --cor-primaria-contraste, --cor-acento (dourado),
--cor-sucesso, --cor-erro, --cor-borda, --cor-foco
↓ é o que o componente consome
Camada 3 — Componente (quando necessário)
--botao-altura-min, --no-caminho-tamanho, --lamparina-corRegra de ouro: componente nunca conhece cor primitiva. Trocar a marca = mexer só na camada 1 e no mapeamento para a 2.
Escalas
- Espaçamento (base 4px):
0 · 1(4) · 2(8) · 3(12) · 4(16) · 6(24) · 8(32) · 12(48) · 16(64). Os 34 valores atuais colapsam para 9. - Tipografia: escala de 7 degraus (12 · 14 · 16 · 18 · 22 · 28 · 36), com altura de linha e peso definidos por degrau. Corpo mínimo de 16px (nunca menos, público jovem lendo em celular).
- Raio:
sm(8) · md(12) · lg(16) · xl(20) · full. - Elevação: 3 níveis (repouso, card, flutuante). Nada de sombra ad hoc.
- Movimento:
rapido(120ms) · padrao(200ms) · lento(320ms)+ molas para celebração.
5. Tipografia (DS2)
Lexend como família de texto, auto-hospedada em woff2.
Duas razões, uma de produto e uma de conformidade:
- A Lexend foi projetada para melhorar a fluência de leitura de quem está aprendendo a ler, com formas abertas e espaçamento generoso. Para um produto cujo propósito é fazer criança e adolescente lerem a Palavra, é uma escolha com intenção, não estética.
- Auto-hospedar (em vez de puxar do Google Fonts) mantém o app 100% offline, sem nenhuma requisição a terceiros, coerente com a Parte 5 (zero SDK externo, minimização de dados de menores).
Uma família display mais brincalhona para os momentos grandes (XP, celebração, títulos de unidade) fica a definir junto com o ilustrador, para casar com a identidade.
6. Inventário de componentes
Primitivos (via shadcn/Radix, restilizados): Botão, Card, Diálogo/Sheet, Barra de progresso, Seletor, Alternador, Aba, Aviso (toast), Rótulo. São ~9 peças onde mora a acessibilidade difícil.
Componentes de jogo (nossos, sobre os mesmos tokens):
| Componente | Estados |
|---|---|
NoCaminho (nó de lição) | bloqueado · disponível · concluído · perfeito · desafio |
OpcaoResposta | repouso · pressionado · correto · incorreto · desabilitado |
TokenPalavra (montar versículo) | disponível · escolhido · desabilitado |
PainelFeedback | acerto · erro (com explicação) |
BarraTopo (lamparina, XP, talentos, versículos) | com e sem animação de incremento |
CartaoVersiculo | semeado · criando raiz · firmado |
Ovelha | 5 estágios × 5 expressões (feliz, pensativa, comemorando, dormindo, acolhendo) |
CartaoMemoria (Aprisco) | bloqueado · conquistado |
Insignia | bloqueada · conquistada · recém-conquistada |
Cada um documentado com variantes, estados, tokens usados e comportamento de acessibilidade.
7. Acessibilidade como regra do sistema (DS4)
Piso: WCAG 2.1 AA. Não é burocracia: nosso público inclui crianças com dislexia, baixa visão e déficit de atenção.
Regras que o sistema impõe:
- Contraste mínimo 4,5:1 para texto normal e 3:1 para texto grande, verificado automaticamente no CI sobre os pares de tokens (o script já existe em protótipo). Os dois pares reprovados da seção 1 são corrigidos na fundação.
- Área de toque mínima de 48px em qualquer elemento interativo (56px nas ações primárias). Corrige os três casos apontados, incluindo os tokens de palavra.
- Foco visível sempre (anel de foco com token próprio), navegação completa por teclado.
prefers-reduced-motiondesliga celebrações e transições grandes.- Texto nunca abaixo de 16px no corpo; nenhuma informação transmitida só por cor (acerto e erro levam ícone e texto, não só verde e vermelho).
- Rótulos e leitura por leitor de tela definidos em cada componente do inventário.
8. Movimento com intenção
Animação é o que separa "site com quiz" de "jogo". Princípios:
- Feedback imediato (menos de 120ms) para toque; a celebração pode ser mais lenta (320ms).
- Celebrar aprendizado, não presença: a animação grande é a do versículo firmado e a do fim de unidade, não a de abrir o app.
- Nunca bloquear: toda animação é pulável tocando na tela.
- A ovelha reage (comemora, consola, dorme), sempre com leveza e nunca com culpa (contrato de anti-padrões da Parte 3).
9. Briefing do ilustrador (O1), agora concreto
O design system define onde a arte entra; o briefing fica assim:
| Entrega | Especificação |
|---|---|
| Ovelha | 5 estágios de evolução × 5 expressões, SVG, vetor limpo |
| Paleta da marca | primitivos em 9 tons por matiz, com contraste validado nos pares de uso |
| Família display | sugestão que combine com a Lexend |
| Itens do Aprisco | ~20 itens de memória, mesma grade e traço |
| Insígnias | ~15, em versão conquistada e bloqueada |
| Ícone do app | SVG + PNG 512/192 e apple-touch-icon 180 (pendência atual da PWA) |
| Formato | SVG otimizado, cores por token (não cravadas), grade e espessura de traço consistentes |
Ou seja: o ilustrador entrega identidade, não interface. A interface é o sistema.
10. Governança: como a uniformidade se mantém
Sem isso, todo design system vira decoração em seis meses.
- Proibição de valor cru: lint barra hex e px arbitrários nos componentes (Tailwind já força pela escala; a regra fecha o resto).
- Contraste no CI: teste automático sobre os pares de tokens; quebra o build se alguém introduzir uma combinação ilegível.
- Guia vivo em
#/estilo(DS6): uma rota dentro do próprio app mostrando todos os tokens, componentes e estados. Mais barato que Storybook, funciona offline e serve de checklist visual em cada revisão. Fica fora da navegação do jogo de propósito: é ferramenta de design, não conteúdo para o jovem. - Regra de revisão: tela nova só entra se usar componentes do inventário; componente novo entra no guia junto.
11. Plano de migração (sem parar o produto)
| Etapa | Escopo | Efeito visual |
|---|---|---|
| DS-A | Fundação: Tailwind v4, @theme com os tokens, Lexend auto-hospedada, reset | Concluída (2026-07-19): tokens em 3 camadas, contraste corrigido e travado por teste no CI, alvos de toque em 48px |
| DS-B | Primitivos: Botão, Card, Progresso, Diálogo, Toast | Concluída (2026-07-19): Botão (4 variantes), Cartão, Selo, BarraProgresso (com role/aria) e Diálogo sobre Radix. Toast fica para quando houver uso real |
| DS-C | Migrar as 5 telas existentes para os componentes de jogo do inventário | Concluída (2026-07-19): 8 componentes de jogo criados, 5 telas migradas, components.css (330 linhas) eliminado |
| DS-D | Guia vivo /estilo, contraste no CI, regras de lint | Concluída (2026-07-19): guia vivo em #/estilo com 13 seções; governança como teste (proíbe cor crua e valor arbitrário fora de 6 exceções registradas), provada com violação injetada |
| DS-E | Reskin com a identidade do ilustrador | Grande: o produto ganha alma |
DS-A a DS-D não dependem do ilustrador e podem começar já. DS-E é troca de valores de token e substituição de assets, sem reescrever componente.
12. Decisões da Parte 7
| # | Decisão | Recomendação |
|---|---|---|
| DS1 | Ferramental | Tailwind v4 + shadcn/ui (Radix) + Motion |
| DS2 | Tipografia | Lexend auto-hospedada; display a definir com o ilustrador |
| DS3 | Tema | Claro na Fase 2, com tokens já preparados para temas; escuro avaliado na Fase 4 |
| DS4 | Acessibilidade | WCAG 2.1 AA como piso, toque mínimo 48px, contraste verificado no CI |
| DS5 | Dono do sistema | Claude codifica e mantém; ilustrador entrega identidade; designer de produto reavaliado na Fase 3/4 |
| DS6 | Guia vivo | Rota /estilo no app, em vez de Storybook |