# A11y Verification Report — Site da AmigUX

> Registro versionado do projeto. Padrão: [A11Y.md](https://github.com/fecarrico/A11Y.md/blob/main/docs/pt-BR/A11Y.md) v2.0.1
> Legenda: `[x]` verificado com evidência · `[!]` reprovado · `[~]` parcial · `[ ]` não verificado (motivo ao lado)

## 📌 Contexto da Validação
- **Funcionalidade/Épico:** site institucional completo — home única com hero, institucional, encontros, Circuito do Design, mentoria, parceiros e rodapé
- **Data do Teste:** 15/09/2026
- **Cobre a interface em:** `dist/` gerado por `node src/build.mjs` em 15/09/2026
- **Perfil de Conformidade:** ⚖️ Standard (AA) — adotado por suposição declarada (ver `A11Y-DECISIONS.md`)
- **Status de Conformidade:** ⚠️ **CONDICIONAL** — passa tudo que é verificável sem pessoa; faltam os checkpoints humanos
- **Independência da Verificação:** **self-reported** ⚠️ — o mesmo agente gerou e verificou. Pelo §2 do A11Y.md (*Independent Verification*), relatório self-reported tem teto em CONDICIONAL e **não pode** ser fechado como ✅ PASS. Falta um verificador que não escreveu este código.

## 1. Verificação Técnica (Automated & Semantics)
- [x] **Axe-Core:** **0 violações**, 45 regras passando. axe-core 4.10.2 via Playwright/Chromium 1234, tags `wcag2a, wcag2aa, wcag21a, wcag21aa, wcag22aa, best-practice`, com `label-content-name-mismatch` (SC 2.5.3) **ligada explicitamente** — ela vem desligada por padrão. Script: `src/auditar.py`.
  - *Corrigido nesta rodada:* `color-contrast` serious em 22 badges de UF (`.uf` estava em `#177B72` sobre `#E3F3F1` = 4.46:1, reprovando por 0,04). Agora `#146B63` = 5.54:1.
- [~] **Contraste indeterminado pelo axe:** 6 nós — os títulos dos encontros, cujo sublinhado é `background-image: linear-gradient()`. O axe desiste quando há gradiente. Medido à mão: o texto é `#343434` sobre `#F5F2EC` = **11.14:1**. O gradiente é uma faixa de 2px na base, não fundo do texto. Não é defeito.
- [x] **Semântica HTML:** nenhuma `div` clicável. Os filtros são `<button type="button">`; os links são `<a href>`. Confirmado pelo axe e por leitura do template.
- [x] **Hierarquia de Títulos:** 59 títulos, **1 `<h1>`, 0 saltos de nível** — medido no DOM renderizado.
- [x] **Landmarks:** 1 `main`, 1 `nav` (com `aria-label`), 1 `header`, 1 `footer`, **0 `<section>` sem nome acessível**.
  - *Corrigido nesta rodada:* a `<section>` do hero não tinha nome; ganhou `aria-labelledby` apontando para o `<h1>`.
- [x] **Conteúdo sem JavaScript:** com JS desligado, **26 de 26 eventos presentes e visíveis**. O anti-padrão *Conteúdo Refém do JavaScript* não se aplica: o build pré-renderiza tudo e o script da página só filtra.

## 2. Tab Order e Focus Management
- [x] **Indicador de Foco:** `outline: 3px solid rgb(1,118,166)` medido no elemento focado — acima do piso de 2px da Regra da Casa. `#0176A6` sobre o papel = 4.94:1, bem acima dos 3:1 exigidos. Nunca suprimido no CSS.
- [x] **Navegação Lógica (parcial, automatizada):** percurso de `Tab` até os filtros do Circuito reproduzido por script; ordem acompanha a ordem visual. `Enter` no chip "Mercado" filtrou para 8 eventos, `aria-pressed` migrou para o botão certo, e **o foco permaneceu no botão acionado**.
- [x] **Skip link:** `Pular para o conteúdo` é o primeiro elemento focável e aponta para `#conteudo`.
- [x] **Modais:** N/A — a interface não tem modal, overlay nem diálogo.

## 3. Comportamento e Retorno de Tarefas
- [ ] **Screen Reader Test:** **não verificado** — exige pessoa com leitor de tela. Nenhum agente pode alegar este teste (A11Y.md §5). *Quem deve executar:* Felipe ou alguém da comunidade, com **NVDA + Firefox** e **VoiceOver + Safari** no mínimo.
- [~] **Controle por Voz (SC 2.5.3):** conferido por leitura — todo controle tem o rótulo visível dentro do nome acessível; o ícone do WhatsApp é `aria-hidden` ao lado do texto "Entrar no grupo do WhatsApp", e nenhum `aria-label` substitui texto visível. A regra `label-content-name-mismatch` do axe rodou ligada e não acusou. **Falta** a passada com Voice Control / Voice Access de verdade.
- [x] **Estados interativos inventariados:** um só componente com estado — o filtro do Circuito. Estados: *todos* (inicial) e cada um dos 5 circuitos. Verificação: **navegado por teclado** (script), com `aria-pressed`, contagem e visibilidade conferidos a cada troca.
- [x] **Mudança de Status (`aria-live`):** a contagem de resultados é `role="status"` e foi observada mudando para "8 eventos no circuito mercado" após o filtro. Itens filtrados saem com o atributo `hidden` — somem da árvore de acessibilidade e da ordem de foco ao mesmo tempo.
- [x] **Formulários:** N/A — o site não tem formulário. Inscrição e agendamento acontecem no Luma, no WhatsApp e na plataforma do mentor.

## 4. Percepção Visual e Compreensão
- [x] **Contraste de Texto & UI:** toda a paleta recalibrada e medida com `tools/contrast-check.py` contra `#F5F2EC` (o fundo mais escuro em que texto colorido aparece), não contra o papel — as seis cores da marca ficam entre **4.51:1 e 4.57:1**, os cinzas em 4.53 e 6.15, a tinta em 11.14.
  - *Achado que motivou a recalibragem:* as cores vivas da marca **não servem para texto**. Sobre o papel: vermelho 3.48:1, coral 2.61, âmbar 1.94, verde 2.00, azul 2.12, teal 2.54 — cinco das seis reprovam até no piso de 3:1 de componente de UI. Elas ficaram restritas a preenchimento de forma grande, e existe uma escala "ui" (≥3:1) para os marcadores de seção.
- [x] **Redundância (SC 1.4.1):** nenhuma informação depende só de cor. Cada crachá de seção tem rótulo em texto; cada tag do Circuito é texto; o circuito de cada evento aparece escrito na tag, não só na cor.
- [x] **Scale / Zoom:** texto a **200%** num viewport de 1280 → `scrollWidth` 1280, **0 elementos com conteúdo cortado**. **Reflow a 320 CSS px** → `scrollWidth` 320, sem rolagem bidimensional. Também verificado a 390px e 1440px.
- [x] **Alvos (SC 2.5.8):** todos os controles ≥ 24px, com botões e itens de menu em 44–48px. Dois links ficam abaixo (`lu.ma/AmigUX` 101×23 e `A11Y.md` 57×21) — ambos **inline dentro de um bloco de texto**, o que é exceção explícita do próprio SC 2.5.8.
- [x] **Largura de linha:** `--medida: 72ch` no contêiner de texto, abaixo do teto de 80ch da Regra da Casa. Nenhum texto justificado; tudo alinhado ao início.

## 5. Mídia Temporal e Movimento
- [x] **Classificação:** sem vídeo e sem áudio. As imagens do Célio são **ilustração estática** — o primeiro quadro dos stickers animados, extraído de propósito para não haver movimento automático na página.
- [x] **Autoplay e Conteúdo em Movimento:** nada toca, pisca ou se move sozinho. Sem carrossel, sem parallax, sem animação de entrada.
- [x] **Movimento Reduzido:** com `prefers-reduced-motion: reduce`, **0 elementos mantêm transição acima de 20ms** — medido no DOM renderizado.
- [x] **Texto sobre Mídia:** N/A — nenhum texto sobre imagem ou vídeo.
- [ ] **Alternativas textuais das imagens do Célio:** **pendente de confirmação humana.** O A11Y.md §2 (*Image Evidence*) diz que declarar imagem decorativa é decisão de pessoa, nunca padrão silencioso do agente. Os rascunhos propostos:
  - Hero → `alt="Célio, o mascote da AmigUX: um cogumelo sorridente cujo chapéu tem as seis cores da marca como bolinhas."` (informativa: apresenta o mascote pela primeira vez)
  - Estado vazio da mentoria → `alt=""` (o título e o parágrafo ao lado já dizem o mesmo)
  - Convite final → `alt=""` (idem)
  - *Confirmar com o Felipe.*

## 6. Carga Cognitiva e Fluxo
- [x] **Fluxo de etapas:** N/A — página única, sem fluxo de várias etapas, sem autenticação, sem limite de tempo. Não há o que lembrar nem o que redigitar.
- [x] **Espaçamento de texto (SC 1.4.12):** com entrelinha 1,5×, letras 0,12em, palavras 0,16em e parágrafo 2em aplicados à força, **0 elementos com corte ou sobreposição**; a largura da página não mudou.
- [x] **Necessidades conflitantes:** nenhuma decisão desta rodada atendeu uma necessidade às custas de outra.

## 7. Conteúdo de terceiro
- [~] **Embed do Luma:** o axe registra `frame-tested` — não consegue auditar dentro do `<iframe>`, e o conteúdo é da plataforma, fora do nosso controle. Mitigação aplicada: o iframe tem `title`, vive dentro de uma `<section>` com cabeçalho e descrição nossos, e é **precedido pelo link direto para `lu.ma/AmigUX`** mais um aviso em texto. Se o embed não carregar, a informação continua alcançável.
  - **A conferir com o Felipe:** o Luma é a porta de inscrição dos encontros. Vale uma passada de leitor de tela dentro do embed — se ele for barreira, a lista de eventos em HTML nosso vira a rota principal e o embed, complemento.

---

## 8. Fase 1 fechada e fase 2 em container — 18/09/2026

**O que foi verificado por máquina nesta rodada.**

- **Nove páginas do dist/** (`/`, `/comunidade/`, `/celio/`, `/encontros/`, `/circuito/`, `/membros/`, `/mentoria/`, `/acessibilidade/`, `/censo/`): axe-core 4.10 com as tags WCAG 2.x A/AA, nos dois esquemas de cor — **zero violações**. Telas em desktop (1440) e celular (390) em `prova/telas/`.
- **Hero da home:** as seis regras ditadas pelo Felipe (fotos por lado, nada atrás das bolhas nem do mascote, bolha central acima do chapéu, bolinhas mínimas e fora do slogan, nada cortado) medidas em 36 carregamentos, seis larguras de 1100 a 1920 — **zero violações**. No celular, quatro larguras (320 a 430): zero sobreposição entre portas, corpo do Célio, slogan e botão de pausa.
- **Movimento:** botão "Pausar movimento" para o Célio, as portas, as fotos e as bolinhas de uma vez; stickers do Célio parados por padrão com botão para animar; `prefers-reduced-motion` respeitado em tudo.
- **Área do membro (`/conta/`)**, rodada num container com MariaDB 11 e PHP 8.2, com os 45 perfis do censo importados: entrar, confere e-mail, link inválido, perfil (com e sem erro), skills, privacidade e diretório logado — axe-core **zero violações**. Fluxo completo automatizado: link de uso único recusado na segunda abertura; pedido repetido em menos de dois minutos não gera e-mail; validação com `aria-invalid`, `role="alert"` e `aria-describedby`; apagar exige a palavra APAGAR; sair derruba a sessão e a página protegida redireciona com o caminho de volta.
- **Páginas públicas geradas do banco** (`/membros/`, `/mentoria/`): axe-core zero violações, com e sem gente.

**O que a máquina não cobre, e continua humano:** leitor de tela nos formulários da conta (a tabela de skills com 165 rádios é o ponto a testar), a teia como SVG `role="img"` com `desc` longa, e a leitura do calendário do Circuito por teclado.

## Pendências que bloqueiam o PASS

| # | O quê | Quem |
|---|---|---|
| 1 | Teste com leitor de tela (NVDA + Firefox, VoiceOver + Safari) | pessoa |
| 2 | Passada com controle por voz | pessoa |
| 3 | Confirmar os `alt` do Célio | Felipe |
| 4 | Verificação independente — outro agente ou sessão nova auditando este código | cross-agent / fresh-context |
| 5 | Acessibilidade do embed do Luma com leitor de tela | pessoa |
| 6 | Confirmar os `alt` das fotos da comunidade (marcados RASCUNHO) e o consentimento das pessoas fotografadas | Felipe |
| 7 | Leitor de tela na área do membro: tabela de skills, teia, formulário de privacidade | pessoa |
| 8 | Calendário do Circuito por teclado, com e sem JavaScript | pessoa |
| 9 | Envio real por SMTP da KingHost (testado só em modo arquivo) | Felipe, no ar |

**Enquanto restar qualquer `[ ]` ou verificação self-reported, o status é CONDICIONAL.**
