# F3.I3.T2 — SNIFF_A11Y_STRICT no CI + alvos/foco/teclado

| Campo | Valor |
|---|---|
| **Fase** | F3 — Layout & UX |
| **Issue** | F3.I3 — Gate de acessibilidade (plano 11) |
| **kd task** | `task_00evvp8w` (`closed`) |
| **Âncora** | `wiki/implementation/03-layout-ux.md` |
| **Status da revisão** | 🔧 com correções |

## O que foi implementado

- `SNIFF_A11Y_STRICT=1` sem `allow_failure`; alvos ≥24 px e ≥44 px em `pointer: coarse`; foco visível; teclado/skip links.
- Reconciliação com a correção do bug de paginação (`src/layout/Portal/pagination/tailwind.blade.php`).

## Arquivos para revisar

- `tools/sniff-gate.sh`
- `Makefile` (`a11y`, `a11y-baseline`, `a11y-diff`)
- `src/layout/Assets/css/*` (alvos/foco)
- `src/layout/Portal/pagination/tailwind.blade.php`
- `src/tests-e2e/tests/02-teclado-e-foco.spec.ts`
- `src/tests-e2e/tests/06-alvos-minimos.spec.ts`
- `wiki/specs/04-acessibilidade-ux.md`

## Pontos de revisão

### PHP 8.4
- [ ] `declare(strict_types=1)`; tipos nativos (union/enum/`readonly`); sem `mixed` desnecessário.
- [ ] Dependências **injetadas** (nenhum `new`/`app()`/`resolve()` no corpo); sem traits/abstract/generics.
- [ ] `match` em vez de cadeias de `if`; `?->`/`??`; sem código morto; PHPStan `max` limpo.

### Laravel 12
- [ ] Nativo primeiro (Eloquent casts/scopes, `FormRequest`, `Gate`, scheduler, events) — sem reimplementar.
- [ ] Sem closure em rota; resources/rotas nomeadas; `config()` só lê, `env()` só em `config/`.
- [ ] Migração **idempotente**; `down()` → `backup_*` (nunca `DROP`); sem `orderBy` cru quando `latest/oldest` serve.

### HTML semântico + a11y (eMAG/WCAG 2.2 AA)
- [ ] Um `<main>`, headings em nível correto, landmarks; só ARIA quando necessário.
- [ ] Alvos ≥ 24 px (≥ 44 px em ponteiro grosso); foco visível; rótulos em todos os campos; contraste (axe).
- [ ] Funciona **sem JS**; `sniffCSS` sem `fail`/`warn` fora do ledger.

### CSS moderno
- [ ] `oklch`, `clamp`, `rem`/`fr`/`dvh`/`%`; `@layer` (a11y por último); `@property`; subgrid com fallback.
- [ ] Sem `!important`, sem `style="…"` inline, sem hex/rgb (exceto justificado); sem CDN.

### Decisões do projeto (ADRs)
- [ ] Respeita a ADR do escopo (ver cabeçalho) e não escapa das demais (001, 002, 004, 013, 015…).
- [ ] Determinismo: relógio/id injetados, ordem explícita, dados idempotentes (ADR-001).

### i18n (ADR-012)
- [ ] Nenhuma string visível fixa; 4 locales com paridade de chaves; `route()`/`localized_url()` (nunca path literal).

### Observabilidade/segurança/testes
- [ ] Span + `log_event('{module}.{action}')` com atributos `scalar|null`, **sem PII** (ADR-024).
- [ ] Teste que falha sem a mudança (vermelho→verde) + evidência no `kd`; `make quality` 2×.

### Específicos desta task

- [ ] Ledger de exceções explícito; `fail` sempre bloqueia.
- [ ] Paginação do projeto (não a default) com alvos ≥ 2.75rem.

## Comandos úteis

```bash
make quality            # lint + PHPStan max + gates + testes
make e2e                # Playwright + axe (se a task toca UI)
make check-boundaries   # fronteiras core/services/layout/modules
```

---

> Revisar contra `AGENTS.md`, `wiki/adr/` e o plano citado. Registrar achados no `kd` (`kd write --anchor`) e, se houver correção, teste de regressão.

## Notas da revisão

| Data | Revisor | Resultado | Observações |
|---|---|---|---|
| 2026-10-18 | agente | 🔧 | **A** (médio) `wiki/specs/04-acessibilidade-ux.md` **stale**: §5 listava 6 de 14 histórias e omitia `cms-desktop`; §6 (ledger) citava `noticias-legacy-content.blade.php` (removido na F4/ADR-028); §1/§7 usavam alvos `make` removidos (`make test`/`make e2e`/`make a11y`) → corrigido (`fact_00xx4dum`); **B** (alto) e2e **não idempotente**: `08-cms-noticias` cria notícias com `Date.now()` e não limpa (**79** linhas `e2e-%` no banco dev) → task `task_00wmwv84`; **C** (alto) a regra “alvo ≥ 2.75rem na paginação” (ponto específico da ficha) **não tinha gate determinístico** (o `06` só vê paginação se o banco tiver >1 página) → **corrigido** com `tests/Feature/PortalPaginationTest.php` (4 testes; provado vermelho ao remover `min-h-11 min-w-11`) — `fact_008pgd0f`; **D** (baixo) comentário do `playwright.config.ts` dizia “três projetos” (são 4) → corrigido (`fact_00yj82cf`); **E** (médio) `KEY_PAGES` do `06` omite `/dados-abertos` (tem paginação) → task `task_00hzia04`; **F** (obs) `a11y-diff` usa `ls -t` (`risk_00ub9we8`); **G** (obs) `sniff-gate.sh` mede só a home (`risk_00kwwdvz`). O gate `E2eDocsTest` passou a cobrir a spec 04. Evidência: 7 testes/52 asserções OK; PHPStan `max` limpo. |

> Resultado: `✅ revisado` · `🔧 com correções` · `⏭️ delegado` (com justificativa).
