Acessibilidade
Em andamentoO que reprova o CI
| Guarda | Onde roda | O que verifica |
|---|---|---|
| Contraste de texto e de controle | npm run audit:check | Mede cada par de cor declarado no contrato. Reprova abaixo de 4,5:1 em texto e 3:1 em limite de controle. Eram 4 pares reprovando em setembro; hoje são 0. |
| Cor fora do contrato | npm run lint | `slate-600`, `red-500` e hexadecimal em componente são erro, não aviso. Paleta bruta saiu de 177 ocorrências para 0, e hexadecimal de 50 para 0. |
| Regras de marcação | npm run lint | `eslint-plugin-jsx-a11y` no conjunto recomendado, promovido a erro na E12. Rótulo sem campo, `div` clicável, ordem de cabeçalho, nome acessível — tudo reprova o push. |
| axe em navegador de verdade | npm run test | Toda ficha passa pelo axe em Chromium, a cada `npm run test`. Não é simulação de DOM: é a página montada, com a cor composta que o navegador realmente pinta. Desde a E140, com a regra do SC 2.5.3 (`label-content-name-mismatch`: o nome acessível contém o texto visível), que o axe traz desligada e que pega o controle que o comando de voz não alcança. |
| Foco nas cores forçadas | npm run audit:check | Contorno de foco zerado, na classe ou no CSS, reprova — nas peças e nas fichas. O anel de foco é sombra, e o alto contraste do Windows apaga sombra: sem contorno, o foco sumia ali — 159 de 165 paradas de Tab medidas em setembro de 2026. Com `outline-hidden` e o contorno transparente do `anel-de-foco`, são 0. Eram 126 ocorrências; hoje são 0. |
| Conteúdo visível sem JavaScript | npm run test | As catorze peças que animam a entrada são renderizadas como o servidor as renderiza, e nenhuma pode esconder conteúdo com opacidade zero. A entrada parte do visível: só é armada no cliente, para o que está abaixo da dobra. Com o JavaScript desligado, eram 153 trechos de texto invisíveis em 13 prévias; hoje são 0. |
| Leitura e reflow | npm run test + npm run audit:check | As peças que cortavam texto ou rolavam de lado rodam a 320px com o espaçamento do SC 1.4.12 forçado (entrelinha 1,5, letras 0,12em, palavras 0,16em): a página não pode rolar de lado, e texto não pode ser cortado — só o resumo de cartão, com o texto inteiro no destino. E fonte abaixo de 12px, a mínima do perfil Standard, reprova no audit: eram 31; hoje são 0. |
| Movimento | código + CSS | `MotionConfig reducedMotion="user"` no template e um bloco `prefers-reduced-motion` no `globals.css`. Conteúdo que se move sozinho pode ser pausado. |
Alvo de toque e densidade
Todo controle interativo tem pelo menos 44×44px — o token --spacing-alvo-toque, que gera min-h-alvo-toque, size-alvo-toque e as outras classes. É mais do que o mínimo da WCAG 2.5.8 (24px) de propósito: é o tamanho de um dedo.
A exceção documentada é o Button variant="link", que é texto dentro de uma frase e segue a altura da linha. Quando o desenho não comporta 44px — um link numa barra de 40px —, a área de toque cresce por pseudo-elemento, e o desenho não muda.
O sistema tem uma densidade só, a confortável. Não há modo compacto: um controle menor para caber mais numa tela é um controle que alguém erra.
O que ainda não está verificado
A passada com leitor de tela
O axe cobre uma fatia e não ouve. Nenhuma peça sobe para Pronto antes disso — é por isso que as 81 estão em Em andamento, e não por modéstia. O ambiente já está montado: os cenários isolados de /validacao, com a folha de registro em docs/a11y-screen-reader-checklist.md.
Conferência de `prefers-reduced-motion` no navegador
O código respeita a preferência e o CSS também. Falta ligar a opção no DevTools e percorrer as peças que animam, uma a uma.
Mais de uma largura na guarda visual
O Chromatic fotografa numa largura só. Enquanto for assim, quebra de layout em telas estreitas não é pega por ninguém.